Replace modules/editors.cpp with widgets::Workspace class

Now we have one editor for each Document we want to edit. Before we were
creating one editor and switching the document on it, but now we have
several Editors (one for each opened Document). This simplifies the
Document implementation, because it doesn't need to know temporal
Editor information (like "preferred editor settings").

- Removed all code from modules/editors.cpp (legacy from C code).
- Removed PreferredEditorSettings class and
  Document::getPreferredEditorSettings().
- Added Workspace/WorkspaceView classes.
- Added DocumentView (a DocumentObserver).
- Added MiniEditorWindow class.
- Removed SelectFileCommand & CloseEditorCommand.
- Added TabView interface instead of using a raw void* in
  Tabs/TabsDelegate classes.
- Modified editors_draw_sprite() calls to Document::notifySpritePixelsModified
  notifications.
- The "current_editor" global variable wasn't removed because it's
  used in several places yet, but it will be removed in the near future.
  (Also this variable now can be NULL when we don't have an opened
  document.)
This commit is contained in:
David Capello 2013-01-20 18:40:37 -03:00
parent 8cc854aef6
commit ed90055bf7
76 changed files with 1240 additions and 1418 deletions

View File

@ -71,7 +71,6 @@
<key command="MakeUniqueEditor" shortcut="Ctrl+1" /> <key command="MakeUniqueEditor" shortcut="Ctrl+1" />
<key command="SplitEditorVertically" shortcut="Ctrl+2" /> <key command="SplitEditorVertically" shortcut="Ctrl+2" />
<key command="SplitEditorHorizontally" shortcut="Ctrl+3" /> <key command="SplitEditorHorizontally" shortcut="Ctrl+3" />
<key command="CloseEditor" shortcut="Ctrl+4" />
<key command="Preview" shortcut="F8" /> <key command="Preview" shortcut="F8" />
<key command="ShowGrid" shortcut="Shift+G" /> <key command="ShowGrid" shortcut="Shift+G" />
<key command="SnapToGrid" shortcut="Shift+S" /> <key command="SnapToGrid" shortcut="Shift+S" />
@ -355,15 +354,10 @@
<item command="SaveMask" text="&amp;Save to MSK file" /> <item command="SaveMask" text="&amp;Save to MSK file" />
</menu> </menu>
<menu text="&amp;View"> <menu text="&amp;View">
<menu text="Sprite &amp;Editor">
<item command="MakeUniqueEditor" text="Make &amp;Unique" /> <item command="MakeUniqueEditor" text="Make &amp;Unique" />
<separator />
<item command="SplitEditorVertically" text="Split &amp;Vertically" /> <item command="SplitEditorVertically" text="Split &amp;Vertically" />
<item command="SplitEditorHorizontally" text="Split &amp;Horizontally" /> <item command="SplitEditorHorizontally" text="Split &amp;Horizontally" />
<separator /> <separator />
<item command="CloseEditor" text="&amp;Close" />
</menu>
<separator />
<item command="ShowGrid" text="Show &amp;Grid" /> <item command="ShowGrid" text="Show &amp;Grid" />
<item command="SnapToGrid" text="&amp;Snap to Grid" /> <item command="SnapToGrid" text="&amp;Snap to Grid" />
<item command="GridSettings" text="Gri&amp;d Settings" /> <item command="GridSettings" text="Gri&amp;d Settings" />

View File

@ -61,6 +61,7 @@
<color id="filelist_selected_row_text" value="#ffffff" /> <color id="filelist_selected_row_text" value="#ffffff" />
<color id="filelist_selected_row_face" value="#2c4c91" /> <color id="filelist_selected_row_face" value="#2c4c91" />
<color id="filelist_disabled_row_text" value="#ffc8c8" /> <color id="filelist_disabled_row_text" value="#ffc8c8" />
<color id="workspace" value="#7d929e" />
</colors> </colors>
<cursors> <cursors>

View File

@ -9,7 +9,7 @@
horizontal="true" expansive="true" horizontal="true" expansive="true"
by="pixel" position="52"> by="pixel" position="52">
<box noborders="true" vertical="true" id="colorbar" /> <box noborders="true" vertical="true" id="colorbar" />
<box noborders="true" horizontal="true" id="editor" expansive="true" /> <box noborders="true" horizontal="true" id="workspace" expansive="true" />
</splitter> </splitter>
<box noborders="true" vertical="true" id="toolbar" /> <box noborders="true" vertical="true" id="toolbar" />
</box> </box>

View File

@ -255,7 +255,6 @@ add_library(aseprite-library
commands/cmd_save_file.cpp commands/cmd_save_file.cpp
commands/cmd_save_mask.cpp commands/cmd_save_mask.cpp
commands/cmd_scroll.cpp commands/cmd_scroll.cpp
commands/cmd_select_file.cpp
commands/cmd_sprite_editor.cpp commands/cmd_sprite_editor.cpp
commands/cmd_sprite_properties.cpp commands/cmd_sprite_properties.cpp
commands/cmd_sprite_size.cpp commands/cmd_sprite_size.cpp
@ -377,6 +376,7 @@ add_library(aseprite-library
widgets/color_button.cpp widgets/color_button.cpp
widgets/color_selector.cpp widgets/color_selector.cpp
widgets/color_sliders.cpp widgets/color_sliders.cpp
widgets/document_view.cpp
widgets/drop_down_button.cpp widgets/drop_down_button.cpp
widgets/editor/cursor.cpp widgets/editor/cursor.cpp
widgets/editor/drawing_state.cpp widgets/editor/drawing_state.cpp
@ -399,11 +399,13 @@ add_library(aseprite-library
widgets/main_menu_bar.cpp widgets/main_menu_bar.cpp
widgets/main_window.cpp widgets/main_window.cpp
widgets/menuitem2.cpp widgets/menuitem2.cpp
widgets/mini_editor.cpp
widgets/palette_view.cpp widgets/palette_view.cpp
widgets/popup_window_pin.cpp widgets/popup_window_pin.cpp
widgets/status_bar.cpp widgets/status_bar.cpp
widgets/tabs.cpp widgets/tabs.cpp
widgets/toolbar.cpp) widgets/toolbar.cpp
widgets/workspace.cpp)
###################################################################### ######################################################################
# ASEPRITE application # ASEPRITE application

View File

@ -40,7 +40,6 @@
#include "ini_file.h" #include "ini_file.h"
#include "log.h" #include "log.h"
#include "modules.h" #include "modules.h"
#include "modules/editors.h"
#include "modules/gfx.h" #include "modules/gfx.h"
#include "modules/gui.h" #include "modules/gui.h"
#include "modules/palettes.h" #include "modules/palettes.h"
@ -158,7 +157,10 @@ int App::run()
// Create the main window and show it. // Create the main window and show it.
m_mainWindow.reset(new MainWindow); m_mainWindow.reset(new MainWindow);
m_mainWindow->createFirstEditor();
// Create the list of tabs
app_rebuild_documents_tabs();
m_mainWindow->openWindow(); m_mainWindow->openWindow();
// Redraw the whole screen. // Redraw the whole screen.
@ -190,9 +192,6 @@ int App::run()
context->setActiveDocument(document); context->setActiveDocument(document);
if (isGui()) { if (isGui()) {
// Show it
set_document_in_more_reliable_editor(context->getFirstDocument());
// Recent file // Recent file
getRecentFiles()->addRecentFile(it->c_str()); getRecentFiles()->addRecentFile(it->c_str());
} }
@ -217,6 +216,11 @@ int App::run()
// Uninstall support to drop files // Uninstall support to drop files
uninstall_drop_files(); uninstall_drop_files();
// Destroy all documents in the UIContext.
const Documents& docs = m_modules->m_ui_context.getDocuments();
while (!docs.empty())
m_modules->m_ui_context.removeDocument(docs.back());
// Destroy the window. // Destroy the window.
m_mainWindow.reset(NULL); m_mainWindow.reset(NULL);
} }
@ -295,32 +299,9 @@ void app_refresh_screen(const Document* document)
ui::Manager::getDefault()->invalidate(); ui::Manager::getDefault()->invalidate();
} }
/**
* Regenerates the label for each tab in the @em tabsbar.
*/
void app_rebuild_documents_tabs() void app_rebuild_documents_tabs()
{ {
UIContext* context = UIContext::instance(); App::instance()->getMainWindow()->getTabsBar()->updateTabsText();
const Documents& docs = context->getDocuments();
// Insert all other sprites
for (Documents::const_iterator
it = docs.begin(), end = docs.end(); it != end; ++it) {
const Document* document = *it;
app_update_document_tab(document);
}
}
void app_update_document_tab(const Document* document)
{
std::string str = get_filename(document->getFilename());
// Add an asterisk if the document is modified.
if (document->isModified())
str += "*";
App::instance()->getMainWindow()->getTabsBar()
->setTabText(str.c_str(), const_cast<Document*>(document));
} }
PixelFormat app_get_current_pixel_format() PixelFormat app_get_current_pixel_format()

View File

@ -86,7 +86,6 @@ private:
void app_refresh_screen(const Document* document); void app_refresh_screen(const Document* document);
void app_rebuild_documents_tabs(); void app_rebuild_documents_tabs();
void app_update_document_tab(const Document* document);
PixelFormat app_get_current_pixel_format(); PixelFormat app_get_current_pixel_format();

View File

@ -213,9 +213,8 @@ void CanvasSizeCommand::onExecute(Context* context)
undoTransaction.commit(); undoTransaction.commit();
documentWriter->generateMaskBoundaries(); documentWriter->generateMaskBoundaries();
update_screen_for_document(documentWriter);
} }
update_screen_for_document(document);
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////

View File

@ -146,7 +146,7 @@ void CelPropertiesCommand::onExecute(Context* context)
// Change cel opacity. // Change cel opacity.
cel_writer->setOpacity(new_opacity); cel_writer->setOpacity(new_opacity);
update_screen_for_document(document); update_screen_for_document(document_writer);
} }
} }
} }

View File

@ -27,11 +27,15 @@
#include "raster/sprite.h" #include "raster/sprite.h"
#include "ui/gui.h" #include "ui/gui.h"
#include "ui_context.h" #include "ui_context.h"
#include "widgets/document_view.h"
#include "widgets/main_window.h"
#include "widgets/status_bar.h" #include "widgets/status_bar.h"
#include "widgets/workspace.h"
#include <memory> #include <memory>
using namespace ui; using namespace ui;
using namespace widgets;
static bool close_active_document(Context* context); static bool close_active_document(Context* context);
@ -61,7 +65,23 @@ protected:
void onExecute(Context* context) void onExecute(Context* context)
{ {
Workspace* workspace = App::instance()->getMainWindow()->getWorkspace();
if (workspace->getActiveView() == NULL)
return;
if (DocumentView* docView =
dynamic_cast<DocumentView*>(workspace->getActiveView())) {
Document* document = docView->getDocument();
if (static_cast<UIContext*>(context)->countViewsOf(document) == 1) {
// If we have only one view for this document, close the file.
close_active_document(context); close_active_document(context);
return;
}
}
// Close the active view.
workspace->closeView(workspace->getActiveView());
} }
private: private:
@ -92,14 +112,14 @@ protected:
void onExecute(Context* context) void onExecute(Context* context)
{ {
if (!context->getActiveDocument())
set_document_in_more_reliable_editor(context->getFirstDocument());
while (true) { while (true) {
if (context->getActiveDocument() != NULL) { if (context->getActiveDocument() != NULL) {
if (!close_active_document(context)) if (!close_active_document(context))
break; break;
} }
else if (context->getFirstDocument() != NULL) {
context->setActiveDocument(context->getFirstDocument());
}
else else
break; break;
} }
@ -115,6 +135,7 @@ protected:
*/ */
static bool close_active_document(Context* context) static bool close_active_document(Context* context)
{ {
Document* nextDocument = NULL;
bool save_it; bool save_it;
bool try_again = true; bool try_again = true;
@ -124,6 +145,7 @@ static bool close_active_document(Context* context)
{ {
// The sprite is locked as reader temporaly // The sprite is locked as reader temporaly
ActiveDocumentReader document(context); ActiveDocumentReader document(context);
nextDocument = context->getNextDocument(document);
// see if the sprite has changes // see if the sprite has changes
while (document->isModified()) { while (document->isModified()) {
@ -167,6 +189,10 @@ static bool close_active_document(Context* context)
base::get_file_name(document->getFilename()).c_str()); base::get_file_name(document->getFilename()).c_str());
document.deleteDocument(); document.deleteDocument();
} }
// Select next document in the context
context->setActiveDocument(nextDocument);
return true; return true;
} }

View File

@ -498,13 +498,11 @@ void ConfigureTools::onSnapToGridClick()
void ConfigureTools::onViewGridClick() void ConfigureTools::onViewGridClick()
{ {
m_docSettings->setGridVisible(m_viewGrid->isSelected()); m_docSettings->setGridVisible(m_viewGrid->isSelected());
refresh_all_editors();
} }
void ConfigureTools::onPixelGridClick() void ConfigureTools::onPixelGridClick()
{ {
m_docSettings->setPixelGridVisible(m_pixelGrid->isSelected()); m_docSettings->setPixelGridVisible(m_pixelGrid->isSelected());
refresh_all_editors();
} }
void ConfigureTools::onSetGridClick() void ConfigureTools::onSetGridClick()
@ -517,9 +515,6 @@ void ConfigureTools::onSetGridClick()
const Mask* mask(document->getMask()); const Mask* mask(document->getMask());
m_docSettings->setGridBounds(mask->getBounds()); m_docSettings->setGridBounds(mask->getBounds());
if (m_docSettings->getGridVisible())
refresh_all_editors();
} }
else { else {
Command* grid_settings_cmd = Command* grid_settings_cmd =
@ -536,7 +531,6 @@ void ConfigureTools::onSetGridClick()
void ConfigureTools::onOnionSkinClick() void ConfigureTools::onOnionSkinClick()
{ {
m_docSettings->setUseOnionskin(m_onionSkin->isSelected()); m_docSettings->setUseOnionskin(m_onionSkin->isSelected());
refresh_all_editors();
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////

View File

@ -97,7 +97,6 @@ void DuplicateSpriteCommand::onExecute(Context* context)
docCopy->setFilename(dst_name->getText()); docCopy->setFilename(dst_name->getText());
context->addDocument(docCopy); context->addDocument(docCopy);
set_document_in_more_reliable_editor(docCopy);
} }
} }

View File

@ -18,15 +18,15 @@
#include "config.h" #include "config.h"
#include "commands/command.h"
#include "app.h" #include "app.h"
#include "commands/command.h"
#include "document_wrappers.h"
#include "modules/gui.h" #include "modules/gui.h"
#include "modules/editors.h" #include "modules/editors.h"
#include "raster/layer.h" #include "raster/layer.h"
#include "raster/sprite.h" #include "raster/sprite.h"
#include "widgets/editor/editor.h" #include "widgets/editor/editor.h"
#include "widgets/status_bar.h" #include "widgets/status_bar.h"
#include "document_wrappers.h"
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// goto_previous_layer // goto_previous_layer

View File

@ -63,8 +63,6 @@ protected:
IDocumentSettings* docSettings = context->getSettings()->getDocumentSettings(context->getActiveDocument()); IDocumentSettings* docSettings = context->getSettings()->getDocumentSettings(context->getActiveDocument());
docSettings->setGridVisible(docSettings->getGridVisible() ? false: true); docSettings->setGridVisible(docSettings->getGridVisible() ? false: true);
refresh_all_editors(); // TODO this should be done by "setGridVisible" impl
} }
}; };
@ -159,9 +157,6 @@ void GridSettingsCommand::onExecute(Context* context)
bounds.h = MAX(bounds.h, 1); bounds.h = MAX(bounds.h, 1);
docSettings->setGridBounds(bounds); docSettings->setGridBounds(bounds);
if (docSettings->getGridVisible())
refresh_all_editors(); // TODO this should be done by "setGridBounds" impl
} }
} }

View File

@ -40,6 +40,7 @@
#include "widgets/editor/editor_decorator.h" #include "widgets/editor/editor_decorator.h"
#include "widgets/editor/select_box_state.h" #include "widgets/editor/select_box_state.h"
#include "widgets/editor/standby_state.h" #include "widgets/editor/standby_state.h"
#include "widgets/workspace.h"
#include <allegro/color.h> #include <allegro/color.h>
@ -129,7 +130,7 @@ protected:
MenuItem* item = new MenuItem("Use Current Sprite"); MenuItem* item = new MenuItem("Use Current Sprite");
item->Click.connect(&ImportSpriteSheetWindow::onUseCurrentSprite, this); item->Click.connect(&ImportSpriteSheetWindow::onUseCurrentSprite, this);
if (m_editor || current_editor->getDocument() == NULL) if (m_editor || !current_editor || current_editor->getDocument() == NULL)
item->setEnabled(false); item->setEnabled(false);
menu->addChild(item); menu->addChild(item);

View File

@ -97,7 +97,7 @@ void LayerPropertiesCommand::onExecute(Context* context)
const_cast<Layer*>(layer)->setName(entry_name->getText()); const_cast<Layer*>(layer)->setName(entry_name->getText());
update_screen_for_document(document); update_screen_for_document(documentWriter);
} }
} }

View File

@ -94,9 +94,8 @@ void LoadMaskCommand::onExecute(Context* context)
undo.commit(); undo.commit();
documentWriter->generateMaskBoundaries(); documentWriter->generateMaskBoundaries();
update_screen_for_document(documentWriter);
} }
update_screen_for_document(document);
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////

View File

@ -38,6 +38,7 @@
#include "ui_context.h" #include "ui_context.h"
#include "util/clipboard.h" #include "util/clipboard.h"
#include "widgets/color_bar.h" #include "widgets/color_bar.h"
#include "widgets/workspace.h"
#include <allegro/config.h> #include <allegro/config.h>
#include <allegro/unicode.h> #include <allegro/unicode.h>
@ -187,11 +188,7 @@ void NewFileCommand::onExecute(Context* context)
} }
// Show the sprite to the user // Show the sprite to the user
context->addDocument(document); context->addDocument(document.release());
// Release the document as it is already owned by the context.
// And put the document in a reliable editor.
set_document_in_more_reliable_editor(document.release());
} }
} }
} }

View File

@ -148,8 +148,6 @@ void OpenFileCommand::onExecute(Context* context)
App::instance()->getRecentFiles()->addRecentFile(fop->filename.c_str()); App::instance()->getRecentFiles()->addRecentFile(fop->filename.c_str());
context->addDocument(document); context->addDocument(document);
set_document_in_more_reliable_editor(document);
} }
else if (!fop_is_stop(fop)) else if (!fop_is_stop(fop))
unrecent = true; unrecent = true;

View File

@ -166,9 +166,6 @@ void OptionsCommand::onExecute(Context* context)
// Save configuration // Save configuration
flush_config_file(); flush_config_file();
// Refresh all editors
refresh_all_editors();
} }
} }

View File

@ -413,8 +413,9 @@ bool PaletteEntryEditor::onProcessMessage(Message* msg)
// Redraw all editors // Redraw all editors
try { try {
const ActiveDocumentReader document(UIContext::instance()); ActiveDocumentWriter document(UIContext::instance());
update_editors_with_document(document); if (document != NULL)
document->notifyGeneralUpdate();
} }
catch (...) { catch (...) {
// Do nothing // Do nothing
@ -423,6 +424,7 @@ bool PaletteEntryEditor::onProcessMessage(Message* msg)
// Redraw just the current editor // Redraw just the current editor
else { else {
m_redrawAll = true; m_redrawAll = true;
if (current_editor != NULL)
current_editor->updateEditor(); current_editor->updateEditor();
} }
} }

View File

@ -115,7 +115,8 @@ void PlayAnimationCommand::onExecute(Context* context)
oldpal = newpal; oldpal = newpal;
} }
current_editor->drawSpriteSafe(0, 0, sprite->getWidth(), sprite->getHeight()); current_editor->drawSpriteClipped
(gfx::Region(gfx::Rect(0, 0, sprite->getWidth(), sprite->getHeight())));
ui::dirty_display_flag = true; ui::dirty_display_flag = true;

View File

@ -142,6 +142,8 @@ static void save_as_dialog(const DocumentReader& document, const char* dlg_title
// Save the document // Save the document
save_document_in_background(documentWriter, mark_as_saved); save_document_in_background(documentWriter, mark_as_saved);
update_screen_for_document(documentWriter);
} }
} }
@ -185,6 +187,7 @@ void SaveFileCommand::onExecute(Context* context)
DocumentWriter documentWriter(document); DocumentWriter documentWriter(document);
save_document_in_background(documentWriter, true); save_document_in_background(documentWriter, true);
update_screen_for_document(documentWriter);
} }
// If the document isn't associated to a file, we must to show the // If the document isn't associated to a file, we must to show the
// save-as dialog to the user to select for first time the file-name // save-as dialog to the user to select for first time the file-name
@ -192,8 +195,6 @@ void SaveFileCommand::onExecute(Context* context)
else { else {
save_as_dialog(document, "Save File", true); save_as_dialog(document, "Save File", true);
} }
update_screen_for_document(document);
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
@ -226,7 +227,6 @@ void SaveFileAsCommand::onExecute(Context* context)
{ {
const ActiveDocumentReader document(context); const ActiveDocumentReader document(context);
save_as_dialog(document, "Save As", true); save_as_dialog(document, "Save As", true);
update_screen_for_document(document);
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
@ -267,9 +267,8 @@ void SaveFileCopyAsCommand::onExecute(Context* context)
{ {
DocumentWriter documentWriter(document); DocumentWriter documentWriter(document);
documentWriter->setFilename(old_filename.c_str()); documentWriter->setFilename(old_filename.c_str());
update_screen_for_document(documentWriter);
} }
update_screen_for_document(document);
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////

View File

@ -1,107 +0,0 @@
/* ASEPRITE
* Copyright (C) 2001-2012 David Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "app.h"
#include "commands/command.h"
#include "commands/params.h"
#include "document_wrappers.h"
#include "modules/editors.h"
#include "ui/gui.h"
#include "ui_context.h"
#include <allegro/debug.h>
#include <allegro/unicode.h>
//////////////////////////////////////////////////////////////////////
// select_file
class SelectFileCommand : public Command
{
public:
SelectFileCommand();
Command* clone() { return new SelectFileCommand(*this); }
protected:
void onLoadParams(Params* params);
bool onEnabled(Context* context);
bool onChecked(Context* context);
void onExecute(Context* context);
private:
DocumentId m_documentId;
};
SelectFileCommand::SelectFileCommand()
: Command("SelectFile",
"Select File",
CmdUIOnlyFlag)
{
m_documentId = WithoutDocumentId;
}
void SelectFileCommand::onLoadParams(Params* params)
{
if (params->has_param("document_id")) {
m_documentId = (DocumentId)ustrtol(params->get("document_id").c_str(), NULL, 10);
}
}
bool SelectFileCommand::onEnabled(Context* context)
{
// m_documentId != 0, the ID specifies a Document
if (m_documentId != WithoutDocumentId) {
Document* document = context->getDocuments().getById(m_documentId);
return document != NULL;
}
// m_documentId=0, means the select "Nothing" option
else
return true;
}
bool SelectFileCommand::onChecked(Context* context)
{
const ActiveDocumentReader document(context);
if (m_documentId != WithoutDocumentId)
return document == context->getDocuments().getById(m_documentId);
else
return document == NULL;
}
void SelectFileCommand::onExecute(Context* context)
{
if (m_documentId != WithoutDocumentId) {
Document* document = context->getDocuments().getById(m_documentId);
ASSERT(document != NULL);
set_document_in_more_reliable_editor(document);
}
else {
set_document_in_more_reliable_editor(NULL);
}
}
//////////////////////////////////////////////////////////////////////
// CommandFactory
Command* CommandFactory::createSelectFileCommand()
{
return new SelectFileCommand;
}

View File

@ -18,34 +18,11 @@
#include "config.h" #include "config.h"
#include "app.h"
#include "commands/command.h" #include "commands/command.h"
#include "modules/editors.h"
#include "ui/base.h" #include "ui/base.h"
#include "widgets/main_window.h"
////////////////////////////////////////////////////////////////////// #include "widgets/workspace.h"
// close_editor
class CloseEditorCommand : public Command
{
public:
CloseEditorCommand();
Command* clone() { return new CloseEditorCommand(*this); }
protected:
void onExecute(Context* context);
};
CloseEditorCommand::CloseEditorCommand()
: Command("CloseEditor",
"Close Editor",
CmdUIOnlyFlag)
{
}
void CloseEditorCommand::onExecute(Context* context)
{
close_editor(current_editor);
}
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// make_unique_editor // make_unique_editor
@ -69,7 +46,9 @@ MakeUniqueEditorCommand::MakeUniqueEditorCommand()
void MakeUniqueEditorCommand::onExecute(Context* context) void MakeUniqueEditorCommand::onExecute(Context* context)
{ {
make_unique_editor(current_editor); widgets::Workspace* workspace = App::instance()->getMainWindow()->getWorkspace();
if (workspace->getActiveView() != NULL)
workspace->makeUnique(workspace->getActiveView());
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
@ -94,7 +73,9 @@ SplitEditorHorizontallyCommand::SplitEditorHorizontallyCommand()
void SplitEditorHorizontallyCommand::onExecute(Context* context) void SplitEditorHorizontallyCommand::onExecute(Context* context)
{ {
split_editor(current_editor, JI_HORIZONTAL); widgets::Workspace* workspace = App::instance()->getMainWindow()->getWorkspace();
if (workspace->getActiveView() != NULL)
workspace->splitView(workspace->getActiveView(), JI_HORIZONTAL);
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
@ -119,17 +100,14 @@ SplitEditorVerticallyCommand::SplitEditorVerticallyCommand()
void SplitEditorVerticallyCommand::onExecute(Context* context) void SplitEditorVerticallyCommand::onExecute(Context* context)
{ {
split_editor(current_editor, JI_VERTICAL); widgets::Workspace* workspace = App::instance()->getMainWindow()->getWorkspace();
if (workspace->getActiveView() != NULL)
workspace->splitView(workspace->getActiveView(), JI_VERTICAL);
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// CommandFactory // CommandFactory
Command* CommandFactory::createCloseEditorCommand()
{
return new CloseEditorCommand;
}
Command* CommandFactory::createMakeUniqueEditorCommand() Command* CommandFactory::createMakeUniqueEditorCommand()
{ {
return new MakeUniqueEditorCommand; return new MakeUniqueEditorCommand;

View File

@ -240,7 +240,8 @@ void SpriteSizeCommand::onExecute(Context* context)
job.startJob(); job.startJob();
} }
update_screen_for_document(document); DocumentWriter docWriter(document);
update_screen_for_document(docWriter);
} }
} }

View File

@ -81,7 +81,9 @@ void UndoCommand::onExecute(Context* context)
if (spritePosition != sprite->getCurrentPosition()) { if (spritePosition != sprite->getCurrentPosition()) {
sprite->setCurrentPosition(spritePosition); sprite->setCurrentPosition(spritePosition);
current_editor->drawSpriteSafe(0, 0, sprite->getWidth(), sprite->getHeight()); current_editor->drawSpriteClipped
(gfx::Region(gfx::Rect(0, 0, sprite->getWidth(), sprite->getHeight())));
update_screen_for_document(document); update_screen_for_document(document);
ui::dirty_display_flag = true; ui::dirty_display_flag = true;

View File

@ -28,7 +28,6 @@ FOR_EACH_COMMAND(ChangePen)
FOR_EACH_COMMAND(ChangePixelFormat) FOR_EACH_COMMAND(ChangePixelFormat)
FOR_EACH_COMMAND(Clear) FOR_EACH_COMMAND(Clear)
FOR_EACH_COMMAND(CloseAllFiles) FOR_EACH_COMMAND(CloseAllFiles)
FOR_EACH_COMMAND(CloseEditor)
FOR_EACH_COMMAND(CloseFile) FOR_EACH_COMMAND(CloseFile)
FOR_EACH_COMMAND(ColorCurve) FOR_EACH_COMMAND(ColorCurve)
FOR_EACH_COMMAND(ConfigureTools) FOR_EACH_COMMAND(ConfigureTools)
@ -96,7 +95,6 @@ FOR_EACH_COMMAND(SaveFileAs)
FOR_EACH_COMMAND(SaveFileCopyAs) FOR_EACH_COMMAND(SaveFileCopyAs)
FOR_EACH_COMMAND(SaveMask) FOR_EACH_COMMAND(SaveMask)
FOR_EACH_COMMAND(Scroll) FOR_EACH_COMMAND(Scroll)
FOR_EACH_COMMAND(SelectFile)
FOR_EACH_COMMAND(ShowGrid) FOR_EACH_COMMAND(ShowGrid)
FOR_EACH_COMMAND(SnapToGrid) FOR_EACH_COMMAND(SnapToGrid)
FOR_EACH_COMMAND(SplitEditorHorizontally) FOR_EACH_COMMAND(SplitEditorHorizontally)

View File

@ -34,6 +34,9 @@ Context::Context(ISettings* settings)
Context::~Context() Context::~Context()
{ {
// The context must be empty at this point.
ASSERT(m_documents.empty());
delete m_settings; delete m_settings;
} }
@ -54,13 +57,23 @@ Document* Context::getNextDocument(Document* document) const
{ {
ASSERT(document != NULL); ASSERT(document != NULL);
Documents::const_iterator it = std::find(m_documents.begin(), m_documents.end(), document); Documents::const_iterator begin = m_documents.begin();
Documents::const_iterator end = m_documents.end();
Documents::const_iterator it = std::find(begin, end, document);
ASSERT(it != end);
if (it != m_documents.end()) { if (it != end) {
++it; if (it != begin) {
if (it != m_documents.end()) --it;
return *it; return *it;
} }
else {
++it;
if (it != end)
return *it;
}
}
return NULL; return NULL;
} }
@ -103,6 +116,9 @@ Document* Context::getActiveDocument() const
void Context::setActiveDocument(Document* document) void Context::setActiveDocument(Document* document)
{ {
if (document == m_activeDocument)
return;
m_observers.notifyActiveDocumentBeforeChange(this); m_observers.notifyActiveDocumentBeforeChange(this);
m_activeDocument = document; m_activeDocument = document;

View File

@ -198,8 +198,6 @@ void switch_between_animation_and_sprite_editor()
// Destroy thumbnails // Destroy thumbnails
destroy_thumbnails(); destroy_thumbnails();
update_screen_for_document(document);
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////

View File

@ -200,7 +200,7 @@ static void mask_preview(const DocumentReader& document)
{ {
DocumentWriter documentWriter(document); DocumentWriter documentWriter(document);
documentWriter->generateMaskBoundaries(mask); documentWriter->generateMaskBoundaries(mask);
} update_screen_for_document(documentWriter);
update_screen_for_document(document); }
} }
} }

View File

@ -61,12 +61,6 @@ Document::Document(Sprite* sprite)
// Boundary stuff // Boundary stuff
m_bound.nseg = 0; m_bound.nseg = 0;
m_bound.seg = NULL; m_bound.seg = NULL;
// Preferred edition options
m_preferred.scroll_x = 0;
m_preferred.scroll_y = 0;
m_preferred.zoom = 0;
m_preferred.virgin = true;
} }
Document::~Document() Document::~Document()
@ -138,6 +132,18 @@ void Document::addSprite(Sprite* sprite)
notifyObservers<DocumentEvent&>(&DocumentObserver::onAddSprite, ev); notifyObservers<DocumentEvent&>(&DocumentObserver::onAddSprite, ev);
} }
void Document::notifyGeneralUpdate()
{
DocumentEvent ev(this);
notifyObservers<DocumentEvent&>(&DocumentObserver::onGeneralUpdate, ev);
}
void Document::notifySpritePixelsModified(Sprite* sprite, const gfx::Region& region)
{
DocumentEvent ev(this, sprite, NULL, NULL, NULL, -1, FrameNumber(), region);
notifyObservers<DocumentEvent&>(&DocumentObserver::onSpritePixelsModified, ev);
}
const char* Document::getFilename() const const char* Document::getFilename() const
{ {
return m_filename.c_str(); return m_filename.c_str();
@ -172,19 +178,6 @@ void Document::setFormatOptions(const SharedPtr<FormatOptions>& format_options)
m_format_options = format_options; m_format_options = format_options;
} }
//////////////////////////////////////////////////////////////////////
// Preferred editor settings
PreferredEditorSettings Document::getPreferredEditorSettings() const
{
return m_preferred;
}
void Document::setPreferredEditorSettings(const PreferredEditorSettings& settings)
{
m_preferred = settings;
}
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// Boundaries // Boundaries
@ -473,7 +466,6 @@ Document* Document::duplicate(DuplicateType type) const
documentCopy->setMask(getMask()); documentCopy->setMask(getMask());
documentCopy->m_maskVisible = m_maskVisible; documentCopy->m_maskVisible = m_maskVisible;
documentCopy->m_preferred = m_preferred;
documentCopy->generateMaskBoundaries(); documentCopy->generateMaskBoundaries();
return documentCopy.release(); return documentCopy.release();

View File

@ -40,13 +40,7 @@ class Mutex;
class Sprite; class Sprite;
struct _BoundSeg; struct _BoundSeg;
struct PreferredEditorSettings namespace gfx { class Region; }
{
int scroll_x;
int scroll_y;
int zoom;
bool virgin;
};
enum DuplicateType enum DuplicateType
{ {
@ -85,6 +79,12 @@ public:
void addSprite(Sprite* sprite); void addSprite(Sprite* sprite);
//////////////////////////////////////////////////////////////////////
// Notifications
void notifyGeneralUpdate();
void notifySpritePixelsModified(Sprite* sprite, const gfx::Region& region);
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// File related properties // File related properties
@ -100,12 +100,6 @@ public:
void setFormatOptions(const SharedPtr<FormatOptions>& format_options); void setFormatOptions(const SharedPtr<FormatOptions>& format_options);
//////////////////////////////////////////////////////////////////////
// Preferred editor settings
PreferredEditorSettings getPreferredEditorSettings() const;
void setPreferredEditorSettings(const PreferredEditorSettings& settings);
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// Boundaries // Boundaries
@ -208,9 +202,6 @@ private:
// Data to save the file in the same format that it was loaded // Data to save the file in the same format that it was loaded
SharedPtr<FormatOptions> m_format_options; SharedPtr<FormatOptions> m_format_options;
// Preferred options in the editor.
PreferredEditorSettings m_preferred;
// Extra cel used to draw extra stuff (e.g. editor's pen preview, pixels in movement, etc.) // Extra cel used to draw extra stuff (e.g. editor's pen preview, pixels in movement, etc.)
Cel* m_extraCel; Cel* m_extraCel;

View File

@ -19,6 +19,7 @@
#ifndef DOCUMENT_EVENT_H_INCLUDED #ifndef DOCUMENT_EVENT_H_INCLUDED
#define DOCUMENT_EVENT_H_INCLUDED #define DOCUMENT_EVENT_H_INCLUDED
#include "gfx/region.h"
#include "raster/frame_number.h" #include "raster/frame_number.h"
class Cel; class Cel;
@ -36,14 +37,16 @@ public:
Cel* cel = NULL, Cel* cel = NULL,
Image* image = NULL, Image* image = NULL,
int imageIndex = -1, int imageIndex = -1,
FrameNumber frame = FrameNumber()) FrameNumber frame = FrameNumber(),
const gfx::Region& region = gfx::Region())
: m_document(document) : m_document(document)
, m_sprite(sprite) , m_sprite(sprite)
, m_layer(layer) , m_layer(layer)
, m_cel(cel) , m_cel(cel)
, m_image(image) , m_image(image)
, m_imageIndex(imageIndex) , m_imageIndex(imageIndex)
, m_frame(frame) { , m_frame(frame)
, m_region(region) {
} }
Document* document() const { return m_document; } Document* document() const { return m_document; }
@ -53,6 +56,7 @@ public:
Image* image() const { return m_image; } Image* image() const { return m_image; }
int imageIndex() const { return m_imageIndex; } int imageIndex() const { return m_imageIndex; }
FrameNumber frame() const { return m_frame; } FrameNumber frame() const { return m_frame; }
const gfx::Region& region() const { return m_region; }
private: private:
Document* m_document; Document* m_document;
@ -62,6 +66,7 @@ private:
Image* m_image; Image* m_image;
int m_imageIndex; int m_imageIndex;
FrameNumber m_frame; FrameNumber m_frame;
gfx::Region m_region;
}; };
#endif #endif

View File

@ -29,6 +29,10 @@ class DocumentObserver {
public: public:
virtual ~DocumentObserver() { } virtual ~DocumentObserver() { }
// General update. If an observer receives this event, it's because
// anything in the document could be changed.
virtual void onGeneralUpdate(DocumentEvent& ev) { }
virtual void onAddSprite(DocumentEvent& ev) { } virtual void onAddSprite(DocumentEvent& ev) { }
virtual void onAddLayer(DocumentEvent& ev) { } virtual void onAddLayer(DocumentEvent& ev) { }
virtual void onAddFrame(DocumentEvent& ev) { } virtual void onAddFrame(DocumentEvent& ev) { }
@ -51,6 +55,7 @@ public:
virtual void onImageReplaced(DocumentEvent& ev) { } virtual void onImageReplaced(DocumentEvent& ev) { }
virtual void onImagePixelsModified(DocumentEvent& ev) { } virtual void onImagePixelsModified(DocumentEvent& ev) { }
virtual void onSpritePixelsModified(DocumentEvent& ev) { }
// Called to destroy the observer. (Here you could call "delete this".) // Called to destroy the observer. (Here you could call "delete this".)
virtual void dispose() { } virtual void dispose() { }

View File

@ -40,6 +40,9 @@ public:
const_iterator begin() const { return m_documents.begin(); } const_iterator begin() const { return m_documents.begin(); }
const_iterator end() const { return m_documents.end(); } const_iterator end() const { return m_documents.end(); }
Document* front() const { return m_documents.front(); }
Document* back() const { return m_documents.back(); }
int size() const { return m_documents.size(); } int size() const { return m_documents.size(); }
bool empty() const { return m_documents.empty(); } bool empty() const { return m_documents.empty(); }

View File

@ -20,692 +20,4 @@
#include "modules/editors.h" #include "modules/editors.h"
#include "app.h"
#include "document_wrappers.h"
#include "ini_file.h"
#include "modules/gui.h"
#include "modules/palettes.h"
#include "raster/image.h"
#include "raster/sprite.h"
#include "skin/skin_theme.h"
#include "ui/gui.h"
#include "ui_context.h"
#include "util/misc.h"
#include "widgets/editor/editor.h"
#include "widgets/editor/editor_customization_delegate.h"
#include "widgets/editor/editor_view.h"
#include "widgets/main_window.h"
#include "widgets/popup_window_pin.h"
#include "widgets/status_bar.h"
#include "widgets/toolbar.h"
#include <algorithm>
#include <vector>
using namespace ui;
#define FIXUP_TOP_WINDOW() \
App::instance()->getMainWindow()->remapWindow(); \
App::instance()->getMainWindow()->invalidate();
class EditorItem
{
public:
enum Type { Normal, Mini };
EditorItem(Editor* editor, Type type)
: m_editor(editor)
, m_type(type)
{ }
Editor* getEditor() const { return m_editor; }
Type getType() const { return m_type; }
private:
Editor* m_editor;
Type m_type;
};
typedef std::vector<EditorItem> EditorList;
Editor* current_editor = NULL; Editor* current_editor = NULL;
Widget* box_editors = NULL;
static EditorList editors;
static bool mini_editor_enabled = true; // True if the user wants to use the mini editor
static Editor* mini_editor = NULL;
static int is_document_in_some_editor(Document* document);
static Document* get_more_reliable_document();
static Widget* find_next_editor(Widget* widget);
static int count_parents(Widget* widget);
static void create_mini_editor_window();
static void hide_mini_editor_window();
static void update_mini_editor_window(Editor* editor);
class WrappedEditor : public Editor,
public EditorObserver,
public EditorCustomizationDelegate
{
public:
WrappedEditor() {
addObserver(this);
setCustomizationDelegate(this);
}
~WrappedEditor() {
removeObserver(this);
setCustomizationDelegate(NULL);
}
// EditorObserver implementation
void dispose() OVERRIDE {
// Do nothing
}
void scrollChanged(Editor* editor) OVERRIDE {
update_mini_editor_window(editor);
}
void documentChanged(Editor* editor) OVERRIDE {
if (editor == current_editor)
update_mini_editor_window(editor);
}
void stateChanged(Editor* editor) OVERRIDE {
// Do nothing
}
// EditorCustomizationDelegate implementation
tools::Tool* getQuickTool(tools::Tool* currentTool) OVERRIDE {
return get_selected_quicktool(currentTool);
}
bool isCopySelectionKeyPressed() OVERRIDE {
Accelerator* accel = get_accel_to_copy_selection();
if (accel)
return accel->checkFromAllegroKeyArray();
else
return false;
}
bool isSnapToGridKeyPressed() OVERRIDE {
Accelerator* accel = get_accel_to_snap_to_grid();
if (accel)
return accel->checkFromAllegroKeyArray();
else
return false;
}
bool isAngleSnapKeyPressed() OVERRIDE {
Accelerator* accel = get_accel_to_angle_snap();
if (accel)
return accel->checkFromAllegroKeyArray();
else
return false;
}
bool isMaintainAspectRatioKeyPressed() OVERRIDE {
Accelerator* accel = get_accel_to_maintain_aspect_ratio();
if (accel)
return accel->checkFromAllegroKeyArray();
else
return false;
}
bool isLockAxisKeyPressed() OVERRIDE {
Accelerator* accel = get_accel_to_lock_axis();
if (accel)
return accel->checkFromAllegroKeyArray();
else
return false;
}
};
class MiniEditor : public Editor
{
public:
MiniEditor() {
}
bool changePreferredSettings() OVERRIDE {
return false;
}
};
class MiniEditorWindow : public Window
{
public:
// Create mini-editor
MiniEditorWindow() : Window(false, "Mini-Editor") {
child_spacing = 0;
setAutoRemap(false);
setWantFocus(false);
}
protected:
void onClose(CloseEvent& ev) OVERRIDE {
Button* closeButton = dynamic_cast<Button*>(ev.getSource());
if (closeButton != NULL &&
closeButton->getId() == SkinTheme::kThemeCloseButtonId) {
// Here we don't use "enable_mini_editor" to change the state of
// "mini_editor_enabled" because we're coming from a close event
// of the window.
mini_editor_enabled = false;
// Redraw the tool bar because it shows the mini editor enabled state.
// TODO abstract this event
ToolBar::instance()->invalidate();
}
}
};
static MiniEditorWindow* mini_editor_window = NULL;
int init_module_editors()
{
mini_editor_enabled = get_config_bool("MiniEditor", "Enabled", true);
return 0;
}
void exit_module_editors()
{
set_config_bool("MiniEditor", "Enabled", mini_editor_enabled);
if (mini_editor_window) {
save_window_pos(mini_editor_window, "MiniEditor");
delete mini_editor_window;
mini_editor_window = NULL;
}
ASSERT(editors.empty());
}
Editor* create_new_editor()
{
Editor* editor = new WrappedEditor();
editors.push_back(EditorItem(editor, EditorItem::Normal));
return editor;
}
// Removes the specified editor from the "editors" list.
// It does not delete the editor.
void remove_editor(Editor* editor)
{
for (EditorList::iterator
it = editors.begin(),
end = editors.end(); it != end; ++it) {
if (it->getEditor() == editor) {
editors.erase(it);
return;
}
}
ASSERT(false && "Editor not found in the list");
}
void refresh_all_editors()
{
for (EditorList::iterator it = editors.begin(); it != editors.end(); ++it) {
it->getEditor()->invalidate();
}
}
void update_editors_with_document(const Document* document)
{
for (EditorList::iterator it = editors.begin(); it != editors.end(); ++it) {
Editor* editor = it->getEditor();
if (document == editor->getDocument())
editor->updateEditor();
}
}
void editors_draw_sprite(const Sprite* sprite, int x1, int y1, int x2, int y2)
{
for (EditorList::iterator it = editors.begin(); it != editors.end(); ++it) {
Editor* editor = it->getEditor();
if (sprite == editor->getSprite() && editor->isVisible())
editor->drawSpriteSafe(x1, y1, x2, y2);
}
}
// TODO improve this (with JRegion or something, and without recursivity).
void editors_draw_sprite_tiled(const Sprite* sprite, int x1, int y1, int x2, int y2)
{
int cx1, cy1, cx2, cy2; // Cel rectangle.
int lx1, ly1, lx2, ly2; // Limited rectangle to the cel rectangle.
#ifdef TILED_IN_LAYER
Image *image = GetImage2(sprite, &cx1, &cy1, NULL);
cx2 = cx1+image->w-1;
cy2 = cy1+image->h-1;
#else
cx1 = 0;
cy1 = 0;
cx2 = cx1+sprite->getWidth()-1;
cy2 = cy1+sprite->getHeight()-1;
#endif
lx1 = MAX(x1, cx1);
ly1 = MAX(y1, cy1);
lx2 = MIN(x2, cx2);
ly2 = MIN(y2, cy2);
// Draw the rectangles inside the editor.
editors_draw_sprite(sprite, lx1, ly1, lx2, ly2);
// Left.
if (x1 < cx1 && lx2 < cx2) {
editors_draw_sprite_tiled(sprite,
MAX(lx2+1, cx2+1+(x1-cx1)), y1,
cx2, y2);
}
// Top.
if (y1 < cy1 && ly2 < cy2) {
editors_draw_sprite_tiled(sprite,
x1, MAX(ly2+1, cy2+1+(y1-cx1)),
x2, cy2);
}
// Right.
if (x2 >= cx2+1 && lx1 > cx1) {
#ifdef TILED_IN_LAYER
editors_draw_sprite_tiled(sprite,
cx1, y1,
MIN(lx1-1, x2-image->w), y2);
#else
editors_draw_sprite_tiled(sprite,
cx1, y1,
MIN(lx1-1, x2-sprite->getWidth()), y2);
#endif
}
// Bottom.
if (y2 >= cy2+1 && ly1 > cy1) {
#if TILED_IN_LAYER
editors_draw_sprite_tiled(sprite,
x1, cy1,
x2, MIN(ly1-1, y2-image->h));
#else
editors_draw_sprite_tiled(sprite,
x1, cy1,
x2, MIN(ly1-1, y2-sprite->getHeight()));
#endif
}
}
void editors_hide_document(const Document* document)
{
UIContext* context = UIContext::instance();
Document* activeDocument = context->getActiveDocument();
Sprite* activeSprite = (activeDocument ? activeDocument->getSprite(): NULL);
bool refresh = (activeSprite == document->getSprite()) ? true: false;
for (EditorList::iterator it = editors.begin(); it != editors.end(); ++it) {
Editor* editor = it->getEditor();
if (document == editor->getDocument())
editor->setDocument(get_more_reliable_document());
}
if (refresh) {
Document* document = current_editor->getDocument();
context->setActiveDocument(document);
app_refresh_screen(document);
}
}
void set_current_editor(Editor* editor)
{
if (current_editor != editor) {
// Here we check if the specified editor in the parameter is the
// mini-editor, in this case, we cannot put the mini-editor as the
// current one.
for (EditorList::iterator it = editors.begin(); it != editors.end(); ++it) {
if (it->getEditor() == editor) {
if (it->getType() != EditorItem::Normal) {
// Avoid setting the mini-editor as the current one
return;
}
break;
}
}
if (current_editor)
View::getView(current_editor)->invalidate();
current_editor = editor;
View::getView(current_editor)->invalidate();
UIContext* context = UIContext::instance();
Document* document = current_editor->getDocument();
context->setActiveDocument(document);
app_refresh_screen(document);
app_rebuild_documents_tabs();
update_mini_editor_window(editor);
}
}
void set_document_in_current_editor(Document* document)
{
if (current_editor) {
UIContext* context = UIContext::instance();
context->setActiveDocument(document);
if (document != NULL)
context->sendDocumentToTop(document);
current_editor->setDocument(document);
View::getView(current_editor)->invalidate();
app_refresh_screen(document);
app_rebuild_documents_tabs();
}
}
void set_document_in_more_reliable_editor(Document* document)
{
// The current editor
Editor* best = current_editor;
// Search for any empty editor
if (best->getDocument()) {
for (EditorList::iterator it = editors.begin(); it != editors.end(); ++it) {
// Avoid using abnormal editors (mini, etc.)
if (it->getType() != EditorItem::Normal)
continue;
Editor* editor = it->getEditor();
if (!editor->getDocument()) {
best = editor;
break;
}
}
}
set_current_editor(best);
set_document_in_current_editor(document);
}
void split_editor(Editor* editor, int align)
{
if (count_parents(editor) > 10) {
Alert::show("Error<<You cannot split this editor more||&Close");
return;
}
View* view = View::getView(editor);
Widget* parent_box = view->getParent(); // Box or splitter.
// Create a new box to contain both editors, and a new view to put the new editor.
Widget* new_splitter = new Splitter(Splitter::ByPercentage, align);
View* new_view = new EditorView(EditorView::CurrentEditorMode);
Editor* new_editor = create_new_editor();
// Insert the "new_box" in the same location that the view.
parent_box->replaceChild(view, new_splitter);
// Append the new editor.
new_view->attachToView(new_editor);
// Set the sprite for the new editor.
new_editor->setDocument(editor->getDocument());
new_editor->setZoom(editor->getZoom());
// Expansive widgets.
new_splitter->setExpansive(true);
new_view->setExpansive(true);
// Append both views to the "new_splitter".
new_splitter->addChild(view);
new_splitter->addChild(new_view);
// Same position.
{
new_view->setViewScroll(view->getViewScroll());
jrect_copy(new_view->rc, view->rc);
jrect_copy(new_view->getViewport()->rc, view->getViewport()->rc);
jrect_copy(new_editor->rc, editor->rc);
new_editor->setOffsetX(editor->getOffsetX());
new_editor->setOffsetY(editor->getOffsetY());
}
// Fixup window.
FIXUP_TOP_WINDOW();
// Update both editors.
editor->updateEditor();
new_editor->updateEditor();
}
void close_editor(Editor* editor)
{
View* view = View::getView(editor);
Widget* parent_box = view->getParent(); // Box or panel
Widget* other_widget;
// You can't remove all (normal) editors.
int normalEditors = 0;
for (EditorList::iterator it = editors.begin(); it != editors.end(); ++it) {
if (it->getType() == EditorItem::Normal)
normalEditors++;
}
if (normalEditors == 1) // In this case we avoid to remove the last normal editor
return;
// Deselect the editor.
if (editor == current_editor)
current_editor = 0;
// Remove this editor.
parent_box->removeChild(view);
delete view;
// Fixup the parent.
other_widget = UI_FIRST_WIDGET(parent_box->getChildren());
parent_box->removeChild(other_widget);
parent_box->getParent()->replaceChild(parent_box, other_widget);
delete parent_box;
// Find next editor to select.
if (!current_editor) {
Widget* next_editor = find_next_editor(other_widget);
if (next_editor) {
ASSERT(next_editor->type == editor_type());
set_current_editor(static_cast<Editor*>(next_editor));
}
}
// Fixup window.
FIXUP_TOP_WINDOW();
// Update all editors.
for (EditorList::iterator it = editors.begin(); it != editors.end(); ++it) {
Editor* editor = it->getEditor();
editor->updateEditor();
}
}
void make_unique_editor(Editor* editor)
{
View* view = View::getView(editor);
// It's the unique editor.
if (editors.size() == 1)
return;
// Remove the editor-view of its parent.
view->getParent()->removeChild(view);
// Remove all children of main_editor_box.
while (!box_editors->getChildren().empty()) {
Widget* child = box_editors->getChildren().front();
box_editors->removeChild(child);
delete child; // widget
}
// Append the editor to main box.
box_editors->addChild(view);
// New current editor.
set_current_editor(editor);
// Fixup window.
FIXUP_TOP_WINDOW();
// Update new editor.
editor->updateEditor();
}
bool is_mini_editor_enabled()
{
return mini_editor_enabled;
}
void enable_mini_editor(bool state)
{
mini_editor_enabled = state;
update_mini_editor_window(current_editor);
}
static int is_document_in_some_editor(Document* document)
{
for (EditorList::iterator it = editors.begin(); it != editors.end(); ++it) {
Editor* editor = it->getEditor();
if (document == editor->getDocument())
return true;
}
return false;
}
// Returns the next sprite that should be show if we close the current one.
static Document* get_more_reliable_document()
{
UIContext* context = UIContext::instance();
const Documents& docs = context->getDocuments();
for (Documents::const_iterator
it = docs.begin(), end = docs.end(); it != end; ++it) {
Document* document = *it;
if (!(is_document_in_some_editor(document)))
return document;
}
return NULL;
}
static Widget* find_next_editor(Widget* widget)
{
Widget* editor = NULL;
if (widget->type == JI_VIEW) {
editor = UI_FIRST_WIDGET(static_cast<View*>(widget)->getViewport()->getChildren());
}
else {
UI_FOREACH_WIDGET(widget->getChildren(), it)
if ((editor = find_next_editor(*it)))
break;
}
return editor;
}
static int count_parents(Widget* widget)
{
int count = 0;
while ((widget = widget->getParent()))
count++;
return count;
}
static void create_mini_editor_window()
{
// Create mini-editor
mini_editor_window = new MiniEditorWindow();
// Create the new for the mini editor
View* newView = new EditorView(EditorView::AlwaysSelected);
newView->setExpansive(true);
// Create mini editor
mini_editor = new MiniEditor();
editors.push_back(EditorItem(mini_editor, EditorItem::Mini));
newView->attachToView(mini_editor);
mini_editor_window->addChild(newView);
// Default bounds
int width = JI_SCREEN_W/4;
int height = JI_SCREEN_H/4;
mini_editor_window->setBounds
(gfx::Rect(JI_SCREEN_W - width - jrect_w(ToolBar::instance()->rc),
JI_SCREEN_H - height - jrect_h(StatusBar::instance()->rc),
width, height));
load_window_pos(mini_editor_window, "MiniEditor");
}
static void hide_mini_editor_window()
{
if (mini_editor_window &&
mini_editor_window->isVisible()) {
mini_editor_window->closeWindow(NULL);
}
}
static void update_mini_editor_window(Editor* editor)
{
if (!mini_editor_enabled || !editor) {
hide_mini_editor_window();
return;
}
Document* document = editor->getDocument();
// Show the mini editor if it wasn't created yet and the user
// zoomed in, or if the mini-editor was created and the zoom of
// both editors is not the same.
if (document && document->getSprite() &&
((!mini_editor && editor->getZoom() > 0) ||
(mini_editor && mini_editor->getZoom() != editor->getZoom()))) {
// If the mini window does not exist, create it
if (!mini_editor_window)
create_mini_editor_window();
if (!mini_editor_window->isVisible())
mini_editor_window->openWindow();
gfx::Rect visibleBounds = editor->getVisibleSpriteBounds();
gfx::Point pt = visibleBounds.getCenter();
// Set the same location as in the given editor.
if (mini_editor->getDocument() != document) {
mini_editor->setDocument(document);
mini_editor->setZoom(0);
mini_editor->setState(EditorStatePtr(new EditorState));
}
mini_editor->centerInSpritePoint(pt.x, pt.y);
}
else {
hide_mini_editor_window();
}
}

View File

@ -19,37 +19,7 @@
#ifndef MODULES_EDITORS_H_INCLUDED #ifndef MODULES_EDITORS_H_INCLUDED
#define MODULES_EDITORS_H_INCLUDED #define MODULES_EDITORS_H_INCLUDED
class Document;
class Editor; class Editor;
class Sprite;
namespace ui { class Widget; }
extern Editor* current_editor; extern Editor* current_editor;
extern ui::Widget* box_editors;
int init_module_editors();
void exit_module_editors();
Editor* create_new_editor();
void remove_editor(Editor* editor);
void set_current_editor(Editor* editor);
void refresh_all_editors();
void update_editors_with_document(const Document* document);
void editors_draw_sprite(const Sprite* sprite, int x1, int y1, int x2, int y2);
void editors_draw_sprite_tiled(const Sprite* sprite, int x1, int y1, int x2, int y2);
void editors_hide_document(const Document* document);
void set_document_in_current_editor(Document* document);
void set_document_in_more_reliable_editor(Document* document);
void split_editor(Editor* editor, int align);
void close_editor(Editor* editor);
void make_unique_editor(Editor* editor);
bool is_mini_editor_enabled();
void enable_mini_editor(bool state);
#endif #endif

View File

@ -268,7 +268,7 @@ void set_screen_scaling(int scaling)
screen_scaling = scaling; screen_scaling = scaling;
} }
void update_screen_for_document(const Document* document) void update_screen_for_document(Document* document)
{ {
// Without document. // Without document.
if (!document) { if (!document) {
@ -280,21 +280,10 @@ void update_screen_for_document(const Document* document)
} }
// With a document. // With a document.
else { else {
const Sprite* sprite = document->getSprite(); document->notifyGeneralUpdate();
// Select the palette of the sprite.
if (set_current_palette(sprite->getPalette(sprite->getCurrentFrame()), false)) {
// If the palette changes, invalidate the whole screen, we've to
// redraw it.
Manager::getDefault()->invalidate();
}
else {
// If it's the same palette update only the editors with the sprite.
update_editors_with_document(document);
}
// Update the tabs (maybe the modified status has been changed). // Update the tabs (maybe the modified status has been changed).
app_update_document_tab(document); app_rebuild_documents_tabs();
} }
} }
@ -311,7 +300,7 @@ void gui_feedback()
ui::UpdateCursorOverlay(); ui::UpdateCursorOverlay();
// Avoid updating a non-dirty screen over and over again. // Avoid updating a non-dirty screen over and over again.
#if 0 // It doesn't work #if 0 // TODO It doesn't work yet
if (!dirty_display_flag) if (!dirty_display_flag)
return; return;
#endif #endif

View File

@ -47,7 +47,7 @@ void exit_module_gui();
int get_screen_scaling(); int get_screen_scaling();
void set_screen_scaling(int scaling); void set_screen_scaling(int scaling);
void update_screen_for_document(const Document* document); void update_screen_for_document(Document* document);
void gui_run(); void gui_run();
void gui_feedback(); void gui_feedback();

View File

@ -42,7 +42,7 @@ public:
Observers() { } Observers() { }
~Observers() { ~Observers() {
disposeAllObservers(); ASSERT(m_observers.empty());
} }
// Adds the observer in the collection. The observer is owned by the // Adds the observer in the collection. The observer is owned by the
@ -60,15 +60,6 @@ public:
m_observers.erase(it); m_observers.erase(it);
} }
// Disposes all observers. It's called automatically in the
// Observers dtor.
void disposeAllObservers() {
while (!empty())
(*begin())->dispose();
m_observers.clear();
}
void notifyObservers(void (observer_type::*method)()) { void notifyObservers(void (observer_type::*method)()) {
for (iterator for (iterator
it = this->begin(), it = this->begin(),

View File

@ -26,8 +26,11 @@
#include "tools/point_shape.h" #include "tools/point_shape.h"
#include "tools/tool.h" #include "tools/tool.h"
#include "tools/tool_box.h" #include "tools/tool_box.h"
#include "ui/manager.h"
#include "ui_context.h" #include "ui_context.h"
#include "widgets/color_bar.h" #include "widgets/color_bar.h"
#include "widgets/main_window.h"
#include "widgets/workspace.h"
#include <allegro/color.h> #include <allegro/color.h>
#include <string> #include <string>
@ -113,6 +116,11 @@ public:
virtual void setOnionskinOpacityStep(int step) OVERRIDE; virtual void setOnionskinOpacityStep(int step) OVERRIDE;
private: private:
void redrawDocumentViews() {
// TODO Redraw only document's views
ui::Manager::getDefault()->invalidate();
}
TiledMode m_tiledMode; TiledMode m_tiledMode;
bool m_use_onionskin; bool m_use_onionskin;
int m_prev_frames_onionskin; int m_prev_frames_onionskin;
@ -237,16 +245,19 @@ void UIDocumentSettingsImpl::setSnapToGrid(bool state)
void UIDocumentSettingsImpl::setGridVisible(bool state) void UIDocumentSettingsImpl::setGridVisible(bool state)
{ {
m_gridVisible = state; m_gridVisible = state;
redrawDocumentViews();
} }
void UIDocumentSettingsImpl::setGridBounds(const Rect& rect) void UIDocumentSettingsImpl::setGridBounds(const Rect& rect)
{ {
m_gridBounds = rect; m_gridBounds = rect;
redrawDocumentViews();
} }
void UIDocumentSettingsImpl::setGridColor(const app::Color& color) void UIDocumentSettingsImpl::setGridColor(const app::Color& color)
{ {
m_gridColor = color; m_gridColor = color;
redrawDocumentViews();
} }
void UIDocumentSettingsImpl::snapToGrid(gfx::Point& point, SnapBehavior snapBehavior) const void UIDocumentSettingsImpl::snapToGrid(gfx::Point& point, SnapBehavior snapBehavior) const
@ -279,11 +290,13 @@ app::Color UIDocumentSettingsImpl::getPixelGridColor()
void UIDocumentSettingsImpl::setPixelGridVisible(bool state) void UIDocumentSettingsImpl::setPixelGridVisible(bool state)
{ {
m_pixelGridVisible = state; m_pixelGridVisible = state;
redrawDocumentViews();
} }
void UIDocumentSettingsImpl::setPixelGridColor(const app::Color& color) void UIDocumentSettingsImpl::setPixelGridColor(const app::Color& color)
{ {
m_pixelGridColor = color; m_pixelGridColor = color;
redrawDocumentViews();
} }
bool UIDocumentSettingsImpl::getUseOnionskin() bool UIDocumentSettingsImpl::getUseOnionskin()

View File

@ -324,6 +324,7 @@ SkinTheme::SkinTheme()
color_mapping["filelist_selected_row_text"] = ThemeColor::FileListSelectedRowText; color_mapping["filelist_selected_row_text"] = ThemeColor::FileListSelectedRowText;
color_mapping["filelist_selected_row_face"] = ThemeColor::FileListSelectedRowFace; color_mapping["filelist_selected_row_face"] = ThemeColor::FileListSelectedRowFace;
color_mapping["filelist_disabled_row_text"] = ThemeColor::FileListDisabledRowText; color_mapping["filelist_disabled_row_text"] = ThemeColor::FileListDisabledRowText;
color_mapping["workspace"] = ThemeColor::Workspace;
reload_skin(); reload_skin();
} }

View File

@ -95,6 +95,7 @@ namespace ThemeColor {
FileListSelectedRowText, FileListSelectedRowText,
FileListSelectedRowFace, FileListSelectedRowFace,
FileListDisabledRowText, FileListDisabledRowText,
Workspace,
MaxColors MaxColors
}; };
} }

View File

@ -21,7 +21,6 @@
#include "filters/tiled_mode.h" #include "filters/tiled_mode.h"
#include "gfx/point.h" #include "gfx/point.h"
#include "gfx/rect.h"
#include "tools/trace_policy.h" #include "tools/trace_policy.h"
class Context; class Context;
@ -34,6 +33,8 @@ class Mask;
class Pen; class Pen;
class Sprite; class Sprite;
namespace gfx { class Region; }
namespace tools { namespace tools {
class Controller; class Controller;
@ -166,8 +167,12 @@ public:
// Converts a coordinate in the screen to the sprite. // Converts a coordinate in the screen to the sprite.
virtual gfx::Point screenToSprite(const gfx::Point& screenPoint) = 0; virtual gfx::Point screenToSprite(const gfx::Point& screenPoint) = 0;
// Redraws in the screen the specified are of sprite. // This region is modified by the ToolLoopManager so then you know
virtual void updateArea(const gfx::Rect& dirty_area) = 0; // what must be updated in updateDirtyArea().
virtual gfx::Region& getDirtyArea() = 0;
// Redraws the dirty area.
virtual void updateDirtyArea() = 0;
virtual void updateStatusBar(const char* text) = 0; virtual void updateStatusBar(const char* text) = 0;

View File

@ -21,7 +21,9 @@
#include "tools/tool_loop_manager.h" #include "tools/tool_loop_manager.h"
#include "context.h" #include "context.h"
#include "gfx/region.h"
#include "raster/image.h" #include "raster/image.h"
#include "raster/sprite.h"
#include "settings/document_settings.h" #include "settings/document_settings.h"
#include "tools/controller.h" #include "tools/controller.h"
#include "tools/ink.h" #include "tools/ink.h"
@ -141,7 +143,7 @@ void ToolLoopManager::movement(const Pointer& pointer)
void ToolLoopManager::doLoopStep(bool last_step) void ToolLoopManager::doLoopStep(bool last_step)
{ {
static Rect old_dirty_area; // TODO Not thread safe static Region old_dirty_area; // TODO Not thread safe
Points points_to_interwine; Points points_to_interwine;
if (!last_step) if (!last_step)
@ -179,21 +181,17 @@ void ToolLoopManager::doLoopStep(bool last_step)
else else
m_toolLoop->getIntertwine()->fillPoints(m_toolLoop, points_to_interwine); m_toolLoop->getIntertwine()->fillPoints(m_toolLoop, points_to_interwine);
// Calculat the area to be updated in the screen/editor/sprite // Calculate the area to be updated in all document observers.
Rect dirty_area; Region& dirty_area = m_toolLoop->getDirtyArea();
calculateDirtyArea(m_toolLoop, points_to_interwine, dirty_area); calculateDirtyArea(m_toolLoop, points_to_interwine, dirty_area);
Rect new_dirty_area;
if (m_toolLoop->getTracePolicy() == TracePolicyLast) { if (m_toolLoop->getTracePolicy() == TracePolicyLast) {
new_dirty_area = old_dirty_area.createUnion(dirty_area); dirty_area.createUnion(dirty_area, old_dirty_area);
old_dirty_area = dirty_area; old_dirty_area = dirty_area;
} }
else {
new_dirty_area = dirty_area;
}
if (!new_dirty_area.isEmpty()) if (!dirty_area.isEmpty())
m_toolLoop->updateArea(new_dirty_area); m_toolLoop->updateDirtyArea();
} }
// Applies the grid settings to the specified sprite point, if // Applies the grid settings to the specified sprite point, if
@ -211,8 +209,10 @@ void ToolLoopManager::snapToGrid(bool flexible, Point& point)
->snapToGrid(point, (flexible ? SnapInRightBottom: NormalSnap)); ->snapToGrid(point, (flexible ? SnapInRightBottom: NormalSnap));
} }
void ToolLoopManager::calculateDirtyArea(ToolLoop* loop, const Points& points, Rect& dirty_area) void ToolLoopManager::calculateDirtyArea(ToolLoop* loop, const Points& points, Region& dirty_area)
{ {
dirty_area.clear();
if (points.size() > 0) { if (points.size() > 0) {
Point minpt, maxpt; Point minpt, maxpt;
calculateMinMax(points, minpt, maxpt); calculateMinMax(points, minpt, maxpt);
@ -221,10 +221,54 @@ void ToolLoopManager::calculateDirtyArea(ToolLoop* loop, const Points& points, R
Rect r1, r2; Rect r1, r2;
loop->getPointShape()->getModifiedArea(loop, minpt.x, minpt.y, r1); loop->getPointShape()->getModifiedArea(loop, minpt.x, minpt.y, r1);
loop->getPointShape()->getModifiedArea(loop, maxpt.x, maxpt.y, r2); loop->getPointShape()->getModifiedArea(loop, maxpt.x, maxpt.y, r2);
dirty_area = r1.createUnion(r2);
dirty_area.createUnion(dirty_area, Region(r1.createUnion(r2)));
} }
// Apply offset mode
Point offset(loop->getOffset());
dirty_area.offset(-offset);
// Apply tiled mode
TiledMode tiledMode = loop->getDocumentSettings()->getTiledMode();
if (tiledMode != TILED_NONE) {
int w = loop->getSprite()->getWidth();
int h = loop->getSprite()->getHeight();
Region sprite_area(Rect(0, 0, w, h));
Region outside;
outside.createSubtraction(dirty_area, sprite_area);
switch (tiledMode) {
case TILED_X_AXIS:
outside.createIntersection(outside, Region(Rect(-w*10000, 0, w*20000, h)));
break;
case TILED_Y_AXIS:
outside.createIntersection(outside, Region(Rect(0, -h*10000, w, h*20000)));
break;
}
Rect outsideBounds = outside.getBounds();
if (outsideBounds.x < 0) outside.offset(w * (1+((-outsideBounds.x) / w)), 0);
if (outsideBounds.y < 0) outside.offset(0, h * (1+((-outsideBounds.y) / h)));
int x1 = outside.getBounds().x;
while (true) {
Region in_sprite;
in_sprite.createIntersection(outside, sprite_area);
outside.createSubtraction(outside, in_sprite);
dirty_area.createUnion(dirty_area, in_sprite);
outsideBounds = outside.getBounds();
if (outsideBounds.isEmpty())
break;
else if (outsideBounds.x+outsideBounds.w > w)
outside.offset(-w, 0);
else if (outsideBounds.y+outsideBounds.h > h)
outside.offset(x1-outsideBounds.x, -h);
else else
dirty_area = Rect(); break;
}
}
} }
void ToolLoopManager::calculateMinMax(const Points& points, Point& minpt, Point& maxpt) void ToolLoopManager::calculateMinMax(const Points& points, Point& minpt, Point& maxpt)

View File

@ -22,7 +22,8 @@
#include <vector> #include <vector>
#include "gfx/point.h" #include "gfx/point.h"
#include "gfx/rect.h"
namespace gfx { class Region; }
namespace tools { namespace tools {
@ -99,7 +100,7 @@ private:
static void calculateDirtyArea(ToolLoop* loop, static void calculateDirtyArea(ToolLoop* loop,
const Points& points, const Points& points,
gfx::Rect& dirty_area); gfx::Region& dirty_area);
static void calculateMinMax(const Points& points, static void calculateMinMax(const Points& points,
gfx::Point& minpt, gfx::Point& minpt,

View File

@ -13,15 +13,14 @@
struct BITMAP; struct BITMAP;
#define JI_SCREEN_W ui::ji_screen_w
#define JI_SCREEN_H ui::ji_screen_h
namespace she { class Display; } namespace she { class Display; }
namespace ui { namespace ui {
/***********************************************************************/ // Screen related
/* screen related */
#define JI_SCREEN_W ji_screen_w
#define JI_SCREEN_H ji_screen_h
extern struct BITMAP* ji_screen; extern struct BITMAP* ji_screen;
extern int ji_screen_w; extern int ji_screen_w;
@ -33,13 +32,11 @@ namespace ui {
void SetDisplay(she::Display* display); void SetDisplay(she::Display* display);
/***********************************************************************/ // Timer related
/* timer related */
extern int volatile ji_clock; /* in milliseconds */ extern int volatile ji_clock; /* in milliseconds */
/***********************************************************************/ // Mouse related
/* mouse related */
// Updates the position of the mouse cursor overlay depending on the // Updates the position of the mouse cursor overlay depending on the
// current mouse position. // current mouse position.

View File

@ -28,35 +28,94 @@
#include "ui_context.h" #include "ui_context.h"
#include "undo/undo_history.h" #include "undo/undo_history.h"
#include "widgets/color_bar.h" #include "widgets/color_bar.h"
#include "widgets/document_view.h"
#include "widgets/editor/editor.h"
#include "widgets/main_window.h" #include "widgets/main_window.h"
#include "widgets/mini_editor.h"
#include "widgets/tabs.h" #include "widgets/tabs.h"
#include "widgets/workspace.h"
#include <allegro/file.h> #include <allegro/file.h>
#include <allegro/system.h> #include <allegro/system.h>
UIContext* UIContext::m_instance = NULL; UIContext* UIContext::m_instance = NULL;
using namespace widgets;
UIContext::UIContext() UIContext::UIContext()
: Context(new UISettingsImpl) : Context(new UISettingsImpl)
{ {
ASSERT(m_instance == NULL); ASSERT(m_instance == NULL);
m_instance = this; m_instance = this;
m_activeView = NULL;
} }
UIContext::~UIContext() UIContext::~UIContext()
{ {
// No views at this point.
ASSERT(m_allViews.empty());
ASSERT(m_activeView == NULL);
ASSERT(m_instance == this); ASSERT(m_instance == this);
m_instance = NULL; m_instance = NULL;
} }
widgets::DocumentView* UIContext::getActiveView()
{
return m_activeView;
}
void UIContext::setActiveView(widgets::DocumentView* docView)
{
m_activeView = docView;
current_editor = (docView ? docView->getEditor(): NULL);
App::instance()->getMainWindow()->getTabsBar()->selectTab(docView);
App::instance()->getMainWindow()->getWorkspace()->setActiveView(docView);
if (current_editor)
current_editor->requestFocus();
setActiveDocument(docView ? docView->getDocument(): NULL);
App::instance()->getMainWindow()->getMiniEditor()->updateUsingEditor(current_editor);
}
size_t UIContext::countViewsOf(Document* document) const
{
size_t counter = 0;
for (DocumentViews::const_iterator
it=m_allViews.begin(), end=m_allViews.end(); it != end; ++it) {
DocumentView* view = *it;
if (view->getDocument() == document)
++counter;
}
return counter;
}
Editor* UIContext::getActiveEditor()
{
if (m_activeView)
return m_activeView->getEditor();
else
return NULL;
}
void UIContext::onAddDocument(Document* document) void UIContext::onAddDocument(Document* document)
{ {
// base method // base method
Context::onAddDocument(document); Context::onAddDocument(document);
// add the tab for this sprite // Add a new view for this document
App::instance()->getMainWindow()->getTabsBar() DocumentView* view = new DocumentView(document, DocumentView::Normal);
->addTab(get_filename(document->getFilename()), document); m_allViews.push_back(view);
// Add a tab with the new view for the document
App::instance()->getMainWindow()->getTabsBar()->addTab(view);
App::instance()->getMainWindow()->getWorkspace()->addView(view);
setActiveView(view);
view->getEditor()->setDefaultScroll();
// Rebuild the list of tabs // Rebuild the list of tabs
app_rebuild_documents_tabs(); app_rebuild_documents_tabs();
@ -64,25 +123,48 @@ void UIContext::onAddDocument(Document* document)
void UIContext::onRemoveDocument(Document* document) void UIContext::onRemoveDocument(Document* document)
{ {
// base method
Context::onRemoveDocument(document); Context::onRemoveDocument(document);
// Remove this document from tabs // Remove all views of this document
App::instance()->getMainWindow()->getTabsBar()->removeTab(document); for (DocumentViews::iterator it=m_allViews.begin(); it != m_allViews.end(); ) {
DocumentView* view = *it;
if (view->getDocument() == document) {
App::instance()->getMainWindow()->getTabsBar()->removeTab(view);
App::instance()->getMainWindow()->getWorkspace()->removeView(view);
// We cannot point as "active view" this view that we're destroying.
if (view == m_activeView)
m_activeView = NULL;
delete view;
it = m_allViews.erase(it);
}
else
++it;
}
// Rebuild the tabs // Rebuild the tabs
app_rebuild_documents_tabs(); app_rebuild_documents_tabs();
// Select other documents in the editors where are this sprite
editors_hide_document(document);
} }
void UIContext::onSetActiveDocument(Document* document) void UIContext::onSetActiveDocument(Document* document)
{ {
Context::onSetActiveDocument(document); Context::onSetActiveDocument(document);
// Select the document in the tabs. if (!document)
App::instance()->getMainWindow()->getTabsBar()->selectTab(document); setActiveView(NULL);
// Select the first view with the given document.
for (DocumentViews::iterator it=m_allViews.begin(), end=m_allViews.end();
it != end; ++it) {
DocumentView* view = *it;
if (view->getDocument() == document) {
setActiveView(view);
break;
}
}
// Change the image-type of color bar. // Change the image-type of color bar.
ColorBar::instance()->setPixelFormat(app_get_current_pixel_format()); ColorBar::instance()->setPixelFormat(app_get_current_pixel_format());

View File

@ -21,6 +21,11 @@
#include "context.h" #include "context.h"
class Editor;
namespace widgets { class DocumentView; }
typedef std::vector<widgets::DocumentView*> DocumentViews;
class UIContext : public Context class UIContext : public Context
{ {
public: public:
@ -31,14 +36,29 @@ public:
virtual bool isUiAvailable() const { return true; } virtual bool isUiAvailable() const { return true; }
widgets::DocumentView* getActiveView();
void setActiveView(widgets::DocumentView* documentView);
// Returns the number of views that the given document has.
size_t countViewsOf(Document* document) const;
// Returns the current editor. It can be null.
Editor* getActiveEditor();
// Returns the active editor for the given document, or creates a
// new one if it's necessary.
Editor* getEditorFor(Document* document);
protected: protected:
virtual void onAddDocument(Document* document); virtual void onAddDocument(Document* document);
virtual void onRemoveDocument(Document* document); virtual void onRemoveDocument(Document* document);
virtual void onSetActiveDocument(Document* document); virtual void onSetActiveDocument(Document* document);
private: private:
static UIContext* m_instance; DocumentViews m_allViews;
widgets::DocumentView* m_activeView;
static UIContext* m_instance;
}; };
#endif #endif

View File

@ -167,6 +167,8 @@ void util::clipboard::copy_image(Image* image, Palette* pal, const gfx::Point& p
void util::clipboard::paste() void util::clipboard::paste()
{ {
Editor* editor = current_editor; Editor* editor = current_editor;
if (editor == NULL)
return;
#ifdef ALLEGRO_WINDOWS #ifdef ALLEGRO_WINDOWS
// Get the image from the clipboard. // Get the image from the clipboard.

View File

@ -0,0 +1,170 @@
/* ASEPRITE
* Copyright (C) 2001-2012 David Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "widgets/document_view.h"
#include "app.h"
#include "base/path.h"
#include "document_event.h"
#include "modules/editors.h"
#include "modules/gui.h"
#include "ui/accelerator.h"
#include "ui/message.h"
#include "ui/view.h"
#include "widgets/editor/editor.h"
#include "widgets/editor/editor_customization_delegate.h"
#include "widgets/editor/editor_view.h"
#include "widgets/main_window.h"
#include "widgets/mini_editor.h"
#include "widgets/workspace.h"
using namespace ui;
using namespace widgets;
class AppEditor : public Editor,
public EditorObserver,
public EditorCustomizationDelegate
{
public:
AppEditor(Document* document) : Editor(document) {
addObserver(this);
setCustomizationDelegate(this);
}
~AppEditor() {
removeObserver(this);
setCustomizationDelegate(NULL);
}
// EditorObserver implementation
void dispose() OVERRIDE {
App::instance()->getMainWindow()->getMiniEditor()->updateUsingEditor(NULL);
}
void scrollChanged(Editor* editor) OVERRIDE {
App::instance()->getMainWindow()->getMiniEditor()->updateUsingEditor(this);
}
void stateChanged(Editor* editor) OVERRIDE {
// Do nothing
}
// EditorCustomizationDelegate implementation
tools::Tool* getQuickTool(tools::Tool* currentTool) OVERRIDE {
return get_selected_quicktool(currentTool);
}
bool isCopySelectionKeyPressed() OVERRIDE {
Accelerator* accel = get_accel_to_copy_selection();
if (accel)
return accel->checkFromAllegroKeyArray();
else
return false;
}
bool isSnapToGridKeyPressed() OVERRIDE {
Accelerator* accel = get_accel_to_snap_to_grid();
if (accel)
return accel->checkFromAllegroKeyArray();
else
return false;
}
bool isAngleSnapKeyPressed() OVERRIDE {
Accelerator* accel = get_accel_to_angle_snap();
if (accel)
return accel->checkFromAllegroKeyArray();
else
return false;
}
bool isMaintainAspectRatioKeyPressed() OVERRIDE {
Accelerator* accel = get_accel_to_maintain_aspect_ratio();
if (accel)
return accel->checkFromAllegroKeyArray();
else
return false;
}
bool isLockAxisKeyPressed() OVERRIDE {
Accelerator* accel = get_accel_to_lock_axis();
if (accel)
return accel->checkFromAllegroKeyArray();
else
return false;
}
};
DocumentView::DocumentView(Document* document, Type type)
: Box(JI_VERTICAL)
, m_document(document)
, m_view(new EditorView(type == Normal ? EditorView::CurrentEditorMode:
EditorView::AlwaysSelected))
, m_editor(type == Normal ? new AppEditor(document):
new Editor(document))
{
addChild(m_view);
m_view->attachToView(m_editor);
m_view->setExpansive(true);
m_view->hideScrollBars();
m_editor->setDocumentView(this);
m_document->addObserver(this);
}
DocumentView::~DocumentView()
{
m_document->removeObserver(this);
delete m_editor;
}
std::string DocumentView::getTabText()
{
std::string str = base::get_file_name(m_document->getFilename());
// Add an asterisk if the document is modified.
if (m_document->isModified())
str += "*";
return str;
}
bool DocumentView::onProcessMessage(Message* msg)
{
switch (msg->type) {
case JM_FOCUSENTER:
m_editor->requestFocus();
break;
}
return Box::onProcessMessage(msg);
}
void DocumentView::onGeneralUpdate(DocumentEvent& ev)
{
if (m_editor->isVisible())
m_editor->updateEditor();
}
void DocumentView::onSpritePixelsModified(DocumentEvent& ev)
{
if (m_editor->isVisible())
m_editor->drawSpriteClipped(ev.region());
}

View File

@ -0,0 +1,73 @@
/* ASEPRITE
* Copyright (C) 2001-2012 David Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef WIDGETS_DOCUMENT_VIEW_H_INCLUDED
#define WIDGETS_DOCUMENT_VIEW_H_INCLUDED
#include "base/compiler_specific.h"
#include "document_observer.h"
#include "ui/box.h"
#include "widgets/tabs.h"
#include "widgets/workspace_view.h"
class Document;
class Editor;
namespace ui { class View; }
namespace widgets {
class DocumentView : public ui::Box
, public TabView
, public DocumentObserver
, public WorkspaceView
{
public:
enum Type {
Normal,
Mini
};
DocumentView(Document* document, Type type);
~DocumentView();
Document* getDocument() const { return m_document; }
Editor* getEditor() { return m_editor; }
// TabView implementation
std::string getTabText() OVERRIDE;
// WorkspaceView implementation
ui::Widget* getContentWidget() OVERRIDE { return this; }
// DocumentObserver implementation
void onGeneralUpdate(DocumentEvent& ev);
void onSpritePixelsModified(DocumentEvent& ev);
protected:
bool onProcessMessage(ui::Message* msg) OVERRIDE;
private:
Document* m_document;
ui::View* m_view;
Editor* m_editor;
};
} // namespace widgets
#endif

View File

@ -152,21 +152,21 @@ static void on_palette_change_update_cursor_color()
static void on_pen_size_before_change() static void on_pen_size_before_change()
{ {
ASSERT(current_editor != NULL); if (current_editor != NULL) {
pen_size_thick = current_editor->getCursorThick(); pen_size_thick = current_editor->getCursorThick();
if (pen_size_thick) if (pen_size_thick)
current_editor->hideDrawingCursor(); current_editor->hideDrawingCursor();
} }
}
static void on_pen_size_after_change() static void on_pen_size_after_change()
{ {
ASSERT(current_editor != NULL); if (current_editor != NULL) {
// Show drawing cursor // Show drawing cursor
if (current_editor->getSprite() && pen_size_thick > 0) if (current_editor->getSprite() && pen_size_thick > 0)
current_editor->showDrawingCursor(); current_editor->showDrawingCursor();
} }
}
static Pen* editor_get_current_pen() static Pen* editor_get_current_pen()
{ {
@ -285,10 +285,11 @@ void Editor::editor_draw_cursor(int x, int y, bool refresh)
int pen_color = get_pen_color(m_sprite); int pen_color = get_pen_color(m_sprite);
uint32_t new_mask_color; uint32_t new_mask_color;
Pen* pen = editor_get_current_pen(); Pen* pen = editor_get_current_pen();
int half = pen->get_size()/2;
// Create the extra cel to show the pen preview // Create the extra cel to show the pen preview
m_document->prepareExtraCel(x-pen->get_size()/2, m_document->prepareExtraCel(x-half,
y-pen->get_size()/2, y-half,
pen->get_size(), pen->get_size(), pen->get_size(), pen->get_size(),
tool_settings->getOpacity()); tool_settings->getOpacity());
@ -304,14 +305,15 @@ void Editor::editor_draw_cursor(int x, int y, bool refresh)
Image* extraImage = m_document->getExtraCelImage(); Image* extraImage = m_document->getExtraCelImage();
if (extraImage->mask_color != new_mask_color) if (extraImage->mask_color != new_mask_color)
image_clear(extraImage, extraImage->mask_color = new_mask_color); image_clear(extraImage, extraImage->mask_color = new_mask_color);
image_putpen(extraImage, pen, pen->get_size()/2, pen->get_size()/2, pen_color, extraImage->mask_color); image_putpen(extraImage, pen, half, half, pen_color, extraImage->mask_color);
if (refresh) { if (refresh) {
editors_draw_sprite(m_sprite, m_document->notifySpritePixelsModified
x-pen->get_size()/2, (m_sprite,
y-pen->get_size()/2, gfx::Region(gfx::Rect(x-half,
x+pen->get_size()/2, y-half,
y+pen->get_size()/2); pen->get_size(),
pen->get_size())));
} }
} }
@ -361,11 +363,11 @@ void Editor::editor_move_cursor(int x, int y, bool refresh)
if (cursor_type & CURSOR_PENCIL && m_state->requirePenPreview()) { if (cursor_type & CURSOR_PENCIL && m_state->requirePenPreview()) {
Pen* pen = editor_get_current_pen(); Pen* pen = editor_get_current_pen();
editors_draw_sprite(m_sprite, int half = pen->get_size()/2;
std::min(new_x, old_x)-pen->get_size()/2, gfx::Rect rc1(old_x-half, old_y-half, pen->get_size(), pen->get_size());
std::min(new_y, old_y)-pen->get_size()/2, gfx::Rect rc2(new_x-half, new_y-half, pen->get_size(), pen->get_size());
std::max(new_x, old_x)+pen->get_size()/2, m_document->notifySpritePixelsModified
std::max(new_y, old_y)+pen->get_size()/2); (m_sprite, gfx::Region(rc1.createUnion(rc2)));
} }
/* save area and draw the cursor */ /* save area and draw the cursor */
@ -423,11 +425,12 @@ void Editor::editor_clean_cursor(bool refresh)
0); // Opacity = 0 0); // Opacity = 0
if (refresh) { if (refresh) {
editors_draw_sprite(m_sprite, m_document->notifySpritePixelsModified
x-pen->get_size()/2, (m_sprite,
gfx::Region(gfx::Rect(x-pen->get_size()/2,
y-pen->get_size()/2, y-pen->get_size()/2,
x+pen->get_size()/2, pen->get_size(),
y+pen->get_size()/2); pen->get_size())));
} }
} }

View File

@ -30,7 +30,6 @@
#include "commands/params.h" #include "commands/params.h"
#include "document_wrappers.h" #include "document_wrappers.h"
#include "ini_file.h" #include "ini_file.h"
#include "modules/editors.h"
#include "modules/gfx.h" #include "modules/gfx.h"
#include "modules/gui.h" #include "modules/gui.h"
#include "modules/palettes.h" #include "modules/palettes.h"
@ -123,20 +122,20 @@ private:
Editor* m_editor; Editor* m_editor;
}; };
Editor::Editor() Editor::Editor(Document* document)
: Widget(editor_type()) : Widget(editor_type())
, m_state(new StandbyState()) , m_state(new StandbyState())
, m_decorator(NULL) , m_decorator(NULL)
, m_document(document)
, m_sprite(m_document->getSprite())
, m_zoom(0)
, m_mask_timer(100, this) , m_mask_timer(100, this)
, m_customizationDelegate(NULL) , m_customizationDelegate(NULL)
, m_docView(NULL)
{ {
// Add the first state into the history. // Add the first state into the history.
m_statesHistory.push(m_state); m_statesHistory.push(m_state);
m_document = NULL;
m_sprite = NULL;
m_zoom = 0;
m_cursor_thick = 0; m_cursor_thick = 0;
m_cursor_screen_x = 0; m_cursor_screen_x = 0;
m_cursor_screen_y = 0; m_cursor_screen_y = 0;
@ -163,7 +162,6 @@ Editor::~Editor()
setCustomizationDelegate(NULL); setCustomizationDelegate(NULL);
m_mask_timer.stop(); m_mask_timer.stop();
remove_editor(this);
// Remove this editor as observer of CurrentToolChange signal. // Remove this editor as observer of CurrentToolChange signal.
App::instance()->CurrentToolChange.disconnect(m_currentToolChangeSlot); App::instance()->CurrentToolChange.disconnect(m_currentToolChangeSlot);
@ -238,61 +236,13 @@ void Editor::backToPreviousState()
setStateInternal(EditorStatePtr(NULL)); setStateInternal(EditorStatePtr(NULL));
} }
void Editor::setDocument(Document* document) void Editor::setDefaultScroll()
{ {
//if (this->hasMouse())
//jmanager_free_mouse(); // TODO Why is this here? Review this code
// Reset all states (back to standby).
EditorStatePtr firstState(new StandbyState);
m_statesHistory.clear();
m_statesHistory.push(firstState);
setState(firstState);
if (m_cursor_thick)
editor_clean_cursor();
// Change the sprite
m_document = document;
if (m_document) {
m_sprite = m_document->getSprite();
// Get the preferred doc's settings to edit it
PreferredEditorSettings preferred = m_document->getPreferredEditorSettings();
// Change the editor's configuration using the retrieved doc's settings
m_zoom = preferred.zoom;
updateEditor();
if (preferred.virgin) {
View* view = View::getView(this); View* view = View::getView(this);
Rect vp = view->getViewportBounds(); Rect vp = view->getViewportBounds();
preferred.virgin = false; setEditorScroll(m_offset_x - vp.w/2 + (m_sprite->getWidth()/2),
preferred.scroll_x = -vp.w/2 + (m_sprite->getWidth()/2); m_offset_y - vp.h/2 + (m_sprite->getHeight()/2), false);
preferred.scroll_y = -vp.h/2 + (m_sprite->getHeight()/2);
m_document->setPreferredEditorSettings(preferred);
}
setEditorScroll(m_offset_x + preferred.scroll_x,
m_offset_y + preferred.scroll_y,
false);
}
// In this case document is NULL
else {
m_sprite = NULL;
updateEditor();
setEditorScroll(0, 0, false); // No scroll
}
// Redraw the entire editor (because we have a new sprite to draw)
invalidate();
// Notify observers
m_observers.notifyDocumentChanged(this);
} }
// Sets the scroll position of the editor // Sets the scroll position of the editor
@ -314,17 +264,6 @@ void Editor::setEditorScroll(int x, int y, int use_refresh_region)
view->setViewScroll(Point(x, y)); view->setViewScroll(Point(x, y));
Point newScroll = view->getViewScroll(); Point newScroll = view->getViewScroll();
if (m_document && changePreferredSettings()) {
PreferredEditorSettings preferred;
preferred.virgin = false;
preferred.scroll_x = newScroll.x - m_offset_x;
preferred.scroll_y = newScroll.y - m_offset_y;
preferred.zoom = m_zoom;
m_document->setPreferredEditorSettings(preferred);
}
if (use_refresh_region) { if (use_refresh_region) {
// Move screen with blits // Move screen with blits
scrollRegion(region, scrollRegion(region,
@ -344,7 +283,7 @@ void Editor::updateEditor()
View::getView(this)->updateView(); View::getView(this)->updateView();
} }
void Editor::drawSprite(int x1, int y1, int x2, int y2) void Editor::drawSpriteUnclippedRect(const gfx::Rect& rc)
{ {
View* view = View::getView(this); View* view = View::getView(this);
Rect vp = view->getViewportBounds(); Rect vp = view->getViewportBounds();
@ -356,12 +295,12 @@ void Editor::drawSprite(int x1, int y1, int x2, int y2)
// Output information // Output information
source_x = x1 << m_zoom; source_x = rc.x << m_zoom;
source_y = y1 << m_zoom; source_y = rc.y << m_zoom;
dest_x = vp.x - scroll.x + m_offset_x + source_x; dest_x = vp.x - scroll.x + m_offset_x + source_x;
dest_y = vp.y - scroll.y + m_offset_y + source_y; dest_y = vp.y - scroll.y + m_offset_y + source_y;
width = (x2 - x1 + 1) << m_zoom; width = rc.w << m_zoom;
height = (y2 - y1 + 1) << m_zoom; height = rc.h << m_zoom;
// Clip from viewport // Clip from viewport
@ -491,7 +430,7 @@ void Editor::drawSprite(int x1, int y1, int x2, int y2)
} }
} }
void Editor::drawSpriteSafe(int x1, int y1, int x2, int y2) void Editor::drawSpriteClipped(const gfx::Region& updateRegion)
{ {
Region region; Region region;
getDrawableRegion(region, kCutTopWindows); getDrawableRegion(region, kCutTopWindows);
@ -499,12 +438,17 @@ void Editor::drawSpriteSafe(int x1, int y1, int x2, int y2)
int cx1, cy1, cx2, cy2; int cx1, cy1, cx2, cy2;
get_clip_rect(ji_screen, &cx1, &cy1, &cx2, &cy2); get_clip_rect(ji_screen, &cx1, &cy1, &cx2, &cy2);
for (Region::const_iterator it=region.begin(), end=region.end(); for (Region::const_iterator
it != end; ++it) { it=region.begin(), end=region.end(); it != end; ++it) {
const Rect& rc = *it; const Rect& rc = *it;
add_clip_rect(ji_screen, rc.x, rc.y, rc.x2()-1, rc.y2()-1); add_clip_rect(ji_screen, rc.x, rc.y, rc.x2()-1, rc.y2()-1);
drawSprite(x1, y1, x2, y2);
for (Region::const_iterator
it2=updateRegion.begin(), end2=updateRegion.end(); it2 != end2; ++it2) {
drawSpriteUnclippedRect(*it2);
}
set_clip_rect(ji_screen, cx1, cy1, cx2, cy2); set_clip_rect(ji_screen, cx1, cy1, cx2, cy2);
} }
} }
@ -922,7 +866,7 @@ bool Editor::onProcessMessage(Message* msg)
x1-1, y1-1, x2+1, y2+2, theme->getColor(ThemeColor::EditorFace)); x1-1, y1-1, x2+1, y2+2, theme->getColor(ThemeColor::EditorFace));
// Draw the sprite in the editor // Draw the sprite in the editor
drawSprite(0, 0, m_sprite->getWidth()-1, m_sprite->getHeight()-1); drawSpriteUnclippedRect(gfx::Rect(0, 0, m_sprite->getWidth(), m_sprite->getHeight()));
// Draw the sprite boundary // Draw the sprite boundary
rect(ji_screen, x1-1, y1-1, x2+1, y2+1, to_system(theme->getColor(ThemeColor::EditorSpriteBorder))); rect(ji_screen, x1-1, y1-1, x2+1, y2+1, to_system(theme->getColor(ThemeColor::EditorSpriteBorder)));
@ -956,7 +900,7 @@ bool Editor::onProcessMessage(Message* msg)
case JM_TIMER: case JM_TIMER:
if (msg->timer.timer == &m_mask_timer) { if (msg->timer.timer == &m_mask_timer) {
if (m_sprite) { if (isVisible() && m_sprite) {
drawMaskSafe(); drawMaskSafe();
// Set offset to make selection-movement effect // Set offset to make selection-movement effect
@ -965,6 +909,9 @@ bool Editor::onProcessMessage(Message* msg)
else else
m_offset_count = 0; m_offset_count = 0;
} }
else if (m_mask_timer.isRunning()) {
m_mask_timer.stop();
}
} }
break; break;

View File

@ -23,6 +23,7 @@
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/signal.h" #include "base/signal.h"
#include "document.h" #include "document.h"
#include "gfx/rect.h"
#include "ui/base.h" #include "ui/base.h"
#include "ui/timer.h" #include "ui/timer.h"
#include "ui/widget.h" #include "ui/widget.h"
@ -38,20 +39,20 @@ class EditorCustomizationDelegate;
class PixelsMovement; class PixelsMovement;
class Sprite; class Sprite;
namespace ui { namespace gfx { class Region; }
class View; namespace tools { class Tool; }
} namespace ui { class View; }
namespace widgets { class DocumentView; }
namespace tools {
class Tool;
}
class Editor : public ui::Widget class Editor : public ui::Widget
{ {
public: public:
Editor(); Editor(Document* document);
~Editor(); ~Editor();
widgets::DocumentView* getDocumentView() { return m_docView; }
void setDocumentView(widgets::DocumentView* docView) { m_docView = docView; }
// Returns the current state. // Returns the current state.
EditorStatePtr getState() { return m_state; } EditorStatePtr getState() { return m_state; }
@ -67,7 +68,6 @@ public:
void setDecorator(EditorDecorator* decorator) { m_decorator = decorator; } void setDecorator(EditorDecorator* decorator) { m_decorator = decorator; }
Document* getDocument() { return m_document; } Document* getDocument() { return m_document; }
void setDocument(Document* document);
Sprite* getSprite() { return m_sprite; } Sprite* getSprite() { return m_sprite; }
@ -80,19 +80,14 @@ public:
void setOffsetX(int x) { m_offset_x = x; } void setOffsetX(int x) { m_offset_x = x; }
void setOffsetY(int y) { m_offset_y = y; } void setOffsetY(int y) { m_offset_y = y; }
void setDefaultScroll();
void setEditorScroll(int x, int y, int use_refresh_region); void setEditorScroll(int x, int y, int use_refresh_region);
// Updates the Editor's view. // Updates the Editor's view.
void updateEditor(); void updateEditor();
// Draws the specified portion of sprite in the editor.
// Warning: You should setup the clip of the ji_screen before
// calling this routine.
void drawSprite(int x1, int y1, int x2, int y2);
// Draws the sprite taking care of the whole clipping region. // Draws the sprite taking care of the whole clipping region.
// For each rectangle calls Editor::drawSprite. void drawSpriteClipped(const gfx::Region& updateRegion);
void drawSpriteSafe(int x1, int y1, int x2, int y2);
void drawMask(); void drawMask();
void drawMaskSafe(); void drawMaskSafe();
@ -158,12 +153,6 @@ protected:
void onCurrentToolChange(); void onCurrentToolChange();
void onFgColorChange(); void onFgColorChange();
// Returns true if this editor should change the preferred document
// settings.
virtual bool changePreferredSettings() {
return true;
}
private: private:
void setStateInternal(const EditorStatePtr& newState); void setStateInternal(const EditorStatePtr& newState);
void editor_update_quicktool(); void editor_update_quicktool();
@ -180,6 +169,11 @@ private:
int sprite_x, int sprite_y, int color, int sprite_x, int sprite_y, int color,
void (*pixel)(BITMAP *bmp, int x, int y, int color)); void (*pixel)(BITMAP *bmp, int x, int y, int color));
// Draws the specified portion of sprite in the editor. Warning:
// You should setup the clip of the screen before calling this
// routine.
void drawSpriteUnclippedRect(const gfx::Rect& rc);
// Stack of states. The top element in the stack is the current state (m_state). // Stack of states. The top element in the stack is the current state (m_state).
EditorStatesHistory m_statesHistory; EditorStatesHistory m_statesHistory;
@ -225,6 +219,10 @@ private:
EditorCustomizationDelegate* m_customizationDelegate; EditorCustomizationDelegate* m_customizationDelegate;
// TODO This field shouldn't be here. It should be removed when
// editors.cpp are finally replaced with a fully funtional Workspace
// widget.
widgets::DocumentView* m_docView;
}; };
int editor_type(); int editor_type();

View File

@ -32,9 +32,6 @@ public:
// Called when the scroll or zoom of the editor changes. // Called when the scroll or zoom of the editor changes.
virtual void scrollChanged(Editor* editor) = 0; virtual void scrollChanged(Editor* editor) = 0;
// Called when the document shown in the editor changes.
virtual void documentChanged(Editor* editor) = 0;
}; };
#endif // WIDGETS_EDITOR_OBSERVER_H_INCLUDED #endif // WIDGETS_EDITOR_OBSERVER_H_INCLUDED

View File

@ -46,8 +46,3 @@ void EditorObservers::notifyScrollChanged(Editor* editor)
{ {
m_observers.notifyObservers(&EditorObserver::scrollChanged, editor); m_observers.notifyObservers(&EditorObserver::scrollChanged, editor);
} }
void EditorObservers::notifyDocumentChanged(Editor* editor)
{
m_observers.notifyObservers(&EditorObserver::documentChanged, editor);
}

View File

@ -34,7 +34,6 @@ public:
void notifyStateChanged(Editor* editor); void notifyStateChanged(Editor* editor);
void notifyScrollChanged(Editor* editor); void notifyScrollChanged(Editor* editor);
void notifyDocumentChanged(Editor* editor);
private: private:
Observers<EditorObserver> m_observers; Observers<EditorObserver> m_observers;

View File

@ -22,7 +22,6 @@
#include "app.h" #include "app.h"
#include "app/color.h" #include "app/color.h"
#include "modules/editors.h"
#include "modules/gui.h" #include "modules/gui.h"
#include "raster/image.h" #include "raster/image.h"
#include "raster/sprite.h" #include "raster/sprite.h"

View File

@ -27,7 +27,6 @@
#include "commands/command.h" #include "commands/command.h"
#include "commands/commands.h" #include "commands/commands.h"
#include "gfx/rect.h" #include "gfx/rect.h"
#include "modules/editors.h"
#include "modules/gui.h" #include "modules/gui.h"
#include "raster/algorithm/flip_image.h" #include "raster/algorithm/flip_image.h"
#include "raster/mask.h" #include "raster/mask.h"
@ -258,18 +257,8 @@ bool MovingPixelsState::onMouseMove(Editor* editor, Message* msg)
transfHandles->invalidateHandles(editor, m_pixelsMovement->getTransformation()); transfHandles->invalidateHandles(editor, m_pixelsMovement->getTransformation());
// Drag the image to that position // Drag the image to that position
gfx::Rect bounds = m_pixelsMovement->moveImage(x, y, moveModifier); m_pixelsMovement->moveImage(x, y, moveModifier);
// If "bounds" is empty is because the cel was not moved
if (!bounds.isEmpty()) {
// Redraw the extra cel in the new position
jmouse_hide();
editors_draw_sprite(editor->getSprite(),
bounds.x, bounds.y,
bounds.x+bounds.w-1,
bounds.y+bounds.h-1);
jmouse_show();
}
editor->updateStatusBar(); editor->updateStatusBar();
return true; return true;
} }
@ -413,10 +402,9 @@ void MovingPixelsState::onChangeTransparentColor(const app::Color& color)
void MovingPixelsState::setTransparentColor(const app::Color& color) void MovingPixelsState::setTransparentColor(const app::Color& color)
{ {
ASSERT(current_editor != NULL);
ASSERT(m_pixelsMovement != NULL); ASSERT(m_pixelsMovement != NULL);
Sprite* sprite = current_editor->getSprite(); Sprite* sprite = m_currentEditor->getSprite();
ASSERT(sprite != NULL); ASSERT(sprite != NULL);
PixelFormat format = sprite->getPixelFormat(); PixelFormat format = sprite->getPixelFormat();

View File

@ -22,6 +22,7 @@
#include "app.h" #include "app.h"
#include "document.h" #include "document.h"
#include "gfx/region.h"
#include "la/vector2d.h" #include "la/vector2d.h"
#include "modules/gui.h" #include "modules/gui.h"
#include "raster/algorithm/flip_image.h" #include "raster/algorithm/flip_image.h"
@ -97,9 +98,8 @@ void PixelsMovement::flipImage(raster::algorithm::FlipType flipType)
documentWriter->setMask(m_currentMask); documentWriter->setMask(m_currentMask);
documentWriter->generateMaskBoundaries(m_currentMask); documentWriter->generateMaskBoundaries(m_currentMask);
update_screen_for_document(documentWriter);
} }
update_screen_for_document(m_documentReader);
} }
void PixelsMovement::cutMask() void PixelsMovement::cutMask()
@ -119,9 +119,8 @@ void PixelsMovement::copyMask()
{ {
DocumentWriter documentWriter(m_documentReader); DocumentWriter documentWriter(m_documentReader);
documentWriter->generateMaskBoundaries(&emptyMask); documentWriter->generateMaskBoundaries(&emptyMask);
update_screen_for_document(documentWriter);
} }
update_screen_for_document(m_documentReader);
} }
void PixelsMovement::catchImage(int x, int y, HandleType handle) void PixelsMovement::catchImage(int x, int y, HandleType handle)
@ -151,9 +150,8 @@ void PixelsMovement::catchImageAgain(int x, int y, HandleType handle)
{ {
DocumentWriter documentWriter(m_documentReader); DocumentWriter documentWriter(m_documentReader);
documentWriter->generateMaskBoundaries(&emptyMask); documentWriter->generateMaskBoundaries(&emptyMask);
update_screen_for_document(documentWriter);
} }
update_screen_for_document(m_documentReader);
} }
void PixelsMovement::maskImage(const Image* image, int x, int y) void PixelsMovement::maskImage(const Image* image, int x, int y)
@ -168,10 +166,10 @@ void PixelsMovement::maskImage(const Image* image, int x, int y)
documentWriter->setMask(m_currentMask); documentWriter->setMask(m_currentMask);
documentWriter->generateMaskBoundaries(m_currentMask); documentWriter->generateMaskBoundaries(m_currentMask);
update_screen_for_document(m_documentReader); update_screen_for_document(documentWriter);
} }
gfx::Rect PixelsMovement::moveImage(int x, int y, MoveModifier moveModifier) void PixelsMovement::moveImage(int x, int y, MoveModifier moveModifier)
{ {
gfx::Transformation::Corners oldCorners; gfx::Transformation::Corners oldCorners;
m_currentData.transformBox(oldCorners); m_currentData.transformBox(oldCorners);
@ -404,7 +402,12 @@ gfx::Rect PixelsMovement::moveImage(int x, int y, MoveModifier moveModifier)
fullBounds = fullBounds.createUnion(gfx::Rect(oldCorners[i].x, oldCorners[i].y, 1, 1)); fullBounds = fullBounds.createUnion(gfx::Rect(oldCorners[i].x, oldCorners[i].y, 1, 1));
fullBounds = fullBounds.createUnion(gfx::Rect(newCorners[i].x, newCorners[i].y, 1, 1)); fullBounds = fullBounds.createUnion(gfx::Rect(newCorners[i].x, newCorners[i].y, 1, 1));
} }
return fullBounds;
// If "fullBounds" is empty is because the cel was not moved
if (!fullBounds.isEmpty()) {
// Notify the modified region.
documentWriter->notifySpritePixelsModified(m_sprite, gfx::Region(fullBounds));
}
} }
Image* PixelsMovement::getDraggedImageCopy(gfx::Point& origin) Image* PixelsMovement::getDraggedImageCopy(gfx::Point& origin)
@ -500,9 +503,8 @@ void PixelsMovement::dropImageTemporarily()
} }
documentWriter->generateMaskBoundaries(m_currentMask); documentWriter->generateMaskBoundaries(m_currentMask);
update_screen_for_document(documentWriter);
} }
update_screen_for_document(m_documentReader);
} }
void PixelsMovement::dropImage() void PixelsMovement::dropImage()
@ -567,9 +569,8 @@ void PixelsMovement::setMaskColor(uint32_t mask_color)
extraImage->mask_color = mask_color; extraImage->mask_color = mask_color;
redrawExtraImage(documentWriter); redrawExtraImage(documentWriter);
update_screen_for_document(documentWriter);
} }
update_screen_for_document(m_documentReader);
} }

View File

@ -61,9 +61,8 @@ public:
void maskImage(const Image* image, int x, int y); void maskImage(const Image* image, int x, int y);
// Moves the image to the new position (relative to the start // Moves the image to the new position (relative to the start
// position given in the ctor). Returns the rectangle that should be // position given in the ctor).
// redrawn. void moveImage(int x, int y, MoveModifier moveModifier);
gfx::Rect moveImage(int x, int y, MoveModifier moveModifier);
// Returns a copy of the current image being dragged with the // Returns a copy of the current image being dragged with the
// current transformation. // current transformation.

View File

@ -22,7 +22,6 @@
#include "app.h" #include "app.h"
#include "gfx/rect.h" #include "gfx/rect.h"
#include "modules/editors.h"
#include "raster/sprite.h" #include "raster/sprite.h"
#include "ui/message.h" #include "ui/message.h"
#include "ui/system.h" #include "ui/system.h"

View File

@ -25,7 +25,6 @@
#include "commands/params.h" #include "commands/params.h"
#include "gfx/rect.h" #include "gfx/rect.h"
#include "ini_file.h" #include "ini_file.h"
#include "modules/editors.h"
#include "raster/layer.h" #include "raster/layer.h"
#include "raster/mask.h" #include "raster/mask.h"
#include "raster/sprite.h" #include "raster/sprite.h"
@ -142,13 +141,10 @@ bool StandbyState::onMouseDown(Editor* editor, Message* msg)
tools::Tool* current_tool = editor->getCurrentEditorTool(); tools::Tool* current_tool = editor->getCurrentEditorTool();
tools::Ink* clickedInk = current_tool->getInk(msg->mouse.right ? 1: 0); tools::Ink* clickedInk = current_tool->getInk(msg->mouse.right ? 1: 0);
Sprite* sprite = editor->getSprite(); Sprite* sprite = editor->getSprite();
// Each time an editor is clicked the current editor and the active
// document are set.
set_current_editor(editor);
Document* document = editor->getDocument(); Document* document = editor->getDocument();
context->setActiveDocument(document);
// When an editor is clicked the current view is changed.
context->setActiveView(editor->getDocumentView());
// Start scroll loop // Start scroll loop
if (checkForScroll(editor, msg)) if (checkForScroll(editor, msg))

View File

@ -24,7 +24,6 @@
#include "app/color.h" #include "app/color.h"
#include "app/color_utils.h" #include "app/color_utils.h"
#include "context.h" #include "context.h"
#include "modules/editors.h"
#include "raster/cel.h" #include "raster/cel.h"
#include "raster/layer.h" #include "raster/layer.h"
#include "raster/mask.h" #include "raster/mask.h"
@ -75,6 +74,7 @@ class ToolLoopImpl : public tools::ToolLoop
int m_secondary_color; int m_secondary_color;
UndoTransaction m_undoTransaction; UndoTransaction m_undoTransaction;
ExpandCelCanvas m_expandCelCanvas; ExpandCelCanvas m_expandCelCanvas;
gfx::Region m_dirtyArea;
public: public:
ToolLoopImpl(Editor* editor, ToolLoopImpl(Editor* editor,
@ -225,16 +225,14 @@ public:
return spritePoint; return spritePoint;
} }
void updateArea(const gfx::Rect& dirty_area) OVERRIDE gfx::Region& getDirtyArea() OVERRIDE
{ {
int x1 = dirty_area.x-m_offset.x; return m_dirtyArea;
int y1 = dirty_area.y-m_offset.y; }
int x2 = dirty_area.x-m_offset.x+dirty_area.w-1;
int y2 = dirty_area.y-m_offset.y+dirty_area.h-1;
acquire_bitmap(ji_screen); void updateDirtyArea() OVERRIDE
editors_draw_sprite_tiled(m_sprite, x1, y1, x2, y2); {
release_bitmap(ji_screen); m_document->notifySpritePixelsModified(m_sprite, m_dirtyArea);
} }
void updateStatusBar(const char* text) OVERRIDE void updateStatusBar(const char* text) OVERRIDE

View File

@ -30,21 +30,18 @@
#include "ui/view.h" #include "ui/view.h"
#include "ui_context.h" #include "ui_context.h"
#include "widgets/color_bar.h" #include "widgets/color_bar.h"
#include "widgets/document_view.h"
#include "widgets/editor/editor.h" #include "widgets/editor/editor.h"
#include "widgets/editor/editor_view.h" #include "widgets/editor/editor_view.h"
#include "widgets/main_menu_bar.h" #include "widgets/main_menu_bar.h"
#include "widgets/mini_editor.h"
#include "widgets/status_bar.h" #include "widgets/status_bar.h"
#include "widgets/tabs.h" #include "widgets/tabs.h"
#include "widgets/toolbar.h" #include "widgets/toolbar.h"
#include "widgets/workspace.h"
using namespace ui; using namespace ui;
using namespace widgets;
class AppTabsDelegate : public TabsDelegate
{
public:
void clickTab(Tabs* tabs, void* data, int button);
void mouseOverTab(Tabs* tabs, void* data);
};
MainWindow::MainWindow() MainWindow::MainWindow()
: Window(true, NULL) : Window(true, NULL)
@ -59,21 +56,20 @@ MainWindow::MainWindow()
Widget* mainBox = app::load_widget<Widget>("main_window.xml", "main_box"); Widget* mainBox = app::load_widget<Widget>("main_window.xml", "main_box");
addChild(mainBox); addChild(mainBox);
box_editors = findChild("editor"); // WARNING / TODO this is a
// global variable defined in
// legacy "editors" modules
Widget* box_menubar = findChild("menubar"); Widget* box_menubar = findChild("menubar");
Widget* box_colorbar = findChild("colorbar"); Widget* box_colorbar = findChild("colorbar");
Widget* box_toolbar = findChild("toolbar"); Widget* box_toolbar = findChild("toolbar");
Widget* box_statusbar = findChild("statusbar"); Widget* box_statusbar = findChild("statusbar");
Widget* box_tabsbar = findChild("tabsbar"); Widget* box_tabsbar = findChild("tabsbar");
Widget* box_workspace = findChild("workspace");
m_menuBar = new MainMenuBar(); m_menuBar = new MainMenuBar();
m_statusBar = new StatusBar(); m_statusBar = new StatusBar();
m_colorBar = new ColorBar(box_colorbar->getAlign()); m_colorBar = new ColorBar(box_colorbar->getAlign());
m_toolBar = new ToolBar(); m_toolBar = new ToolBar();
m_tabsBar = new Tabs(m_tabsDelegate = new AppTabsDelegate()); m_tabsBar = new Tabs(this);
m_workspace = new Workspace();
m_miniEditor = new MiniEditorWindow();
m_colorBarSplitter = findChildT<Splitter>("colorbarsplitter"); m_colorBarSplitter = findChildT<Splitter>("colorbarsplitter");
// configure all widgets to expansives // configure all widgets to expansives
@ -82,45 +78,40 @@ MainWindow::MainWindow()
m_colorBar->setExpansive(true); m_colorBar->setExpansive(true);
m_toolBar->setExpansive(true); m_toolBar->setExpansive(true);
m_tabsBar->setExpansive(true); m_tabsBar->setExpansive(true);
m_workspace->setExpansive(true);
// Setup the menus // Setup the menus
m_menuBar->setMenu(AppMenus::instance()->getRootMenu()); m_menuBar->setMenu(AppMenus::instance()->getRootMenu());
/* start text of status bar */ // Start text of status bar
app_default_statusbar_message(); app_default_statusbar_message();
/* add the widgets in the boxes */ // Add the widgets in the boxes
if (box_menubar) box_menubar->addChild(m_menuBar); if (box_menubar) box_menubar->addChild(m_menuBar);
if (box_colorbar) box_colorbar->addChild(m_colorBar); if (box_colorbar) box_colorbar->addChild(m_colorBar);
if (box_toolbar) box_toolbar->addChild(m_toolBar); if (box_toolbar) box_toolbar->addChild(m_toolBar);
if (box_statusbar) box_statusbar->addChild(m_statusBar); if (box_statusbar) box_statusbar->addChild(m_statusBar);
if (box_tabsbar) box_tabsbar->addChild(m_tabsBar); if (box_tabsbar) box_tabsbar->addChild(m_tabsBar);
if (box_workspace) box_workspace->addChild(m_workspace);
// Prepare the window // Prepare the window
remapWindow(); remapWindow();
// Initialize editors.
init_module_editors();
// Create the list of tabs
app_rebuild_documents_tabs();
AppMenus::instance()->rebuildRecentList(); AppMenus::instance()->rebuildRecentList();
} }
MainWindow::~MainWindow() MainWindow::~MainWindow()
{ {
delete m_tabsDelegate; delete m_miniEditor;
// Destroy the workspace first so ~Editor can dettach slots from
// ColorBar. TODO this is a terrible hack for slot/signal stuff,
// connections should be handle in a better/safer way.
delete m_workspace;
// Remove the root-menu from the menu-bar (because the rootmenu // Remove the root-menu from the menu-bar (because the rootmenu
// module should destroy it). // module should destroy it).
m_menuBar->setMenu(NULL); m_menuBar->setMenu(NULL);
// Delete all editors first because they used signals from other
// widgets (e.g. color bar).
delete box_editors;
// Destroy mini-editor.
exit_module_editors();
} }
void MainWindow::reloadMenus() void MainWindow::reloadMenus()
@ -131,22 +122,6 @@ void MainWindow::reloadMenus()
invalidate(); invalidate();
} }
void MainWindow::createFirstEditor()
{
View* view = new EditorView(EditorView::CurrentEditorMode);
Editor* editor = create_new_editor();
// Prepare the first editor
view->attachToView(editor);
view->setExpansive(true);
if (box_editors)
box_editors->addChild(view);
// Set current editor
set_current_editor(editor); // TODO remove this line from here
}
void MainWindow::setAdvancedMode(bool advanced) void MainWindow::setAdvancedMode(bool advanced)
{ {
// Check if we already are in the given mode. // Check if we already are in the given mode.
@ -180,28 +155,26 @@ void MainWindow::onSaveLayout(SaveLayoutEvent& ev)
m_colorBarSplitter->setPosition(m_lastSplitterPos); m_colorBarSplitter->setPosition(m_lastSplitterPos);
} }
////////////////////////////////////////////////////////////////////// void MainWindow::clickTab(Tabs* tabs, TabView* tabView, int button)
// AppTabsDelegate
void AppTabsDelegate::clickTab(Tabs* tabs, void* data, int button)
{ {
Document* document = reinterpret_cast<Document*>(data); if (!tabView)
return;
// put as current sprite DocumentView* docView = static_cast<DocumentView*>(tabView);
set_document_in_more_reliable_editor(document); Document* document = docView->getDocument();
if (document) { UIContext* context = UIContext::instance();
Context* context = UIContext::instance(); context->setActiveView(docView);
context->updateFlags(); context->updateFlags();
// right-button: popup-menu // Right-button: popup-menu
if (button & 2) { if (button & 2) {
Menu* popup_menu = AppMenus::instance()->getDocumentTabPopupMenu(); Menu* popup_menu = AppMenus::instance()->getDocumentTabPopupMenu();
if (popup_menu != NULL) { if (popup_menu != NULL) {
popup_menu->showPopup(jmouse_x(0), jmouse_y(0)); popup_menu->showPopup(jmouse_x(0), jmouse_y(0));
} }
} }
// middle-button: close the sprite // Middle-button: close the sprite
else if (button & 4) { else if (button & 4) {
Command* close_file_cmd = Command* close_file_cmd =
CommandsModule::instance()->getCommandByName(CommandId::CloseFile); CommandsModule::instance()->getCommandByName(CommandId::CloseFile);
@ -209,18 +182,16 @@ void AppTabsDelegate::clickTab(Tabs* tabs, void* data, int button)
context->executeCommand(close_file_cmd, NULL); context->executeCommand(close_file_cmd, NULL);
} }
} }
}
void AppTabsDelegate::mouseOverTab(Tabs* tabs, void* data) void MainWindow::mouseOverTab(Tabs* tabs, TabView* tabView)
{ {
// Note: data can be NULL // Note: tabView can be NULL
Document* document = (Document*)data; if (tabView) {
DocumentView* docView = static_cast<DocumentView*>(tabView);
if (data) { Document* document = docView->getDocument();
StatusBar::instance()->setStatusText(250, "%s", m_statusBar->setStatusText(250, "%s", static_cast<const char*>(document->getFilename()));
static_cast<const char*>(document->getFilename()));
} }
else { else {
StatusBar::instance()->clearText(); m_statusBar->clearText();
} }
} }

View File

@ -20,18 +20,21 @@
#define MAIN_WINDOW_H_INCLUDED #define MAIN_WINDOW_H_INCLUDED
#include "ui/window.h" #include "ui/window.h"
#include "widgets/tabs.h"
class AppTabsDelegate;
class ColorBar; class ColorBar;
class MainMenuBar; class MainMenuBar;
class StatusBar; class StatusBar;
class Tabs; class Tabs;
namespace ui { class Splitter; }
namespace ui { namespace widgets
class Splitter; {
class MiniEditorWindow;
class Workspace;
} }
class MainWindow : public ui::Window class MainWindow : public ui::Window
, public TabsDelegate
{ {
public: public:
MainWindow(); MainWindow();
@ -39,18 +42,22 @@ public:
MainMenuBar* getMenuBar() { return m_menuBar; } MainMenuBar* getMenuBar() { return m_menuBar; }
Tabs* getTabsBar() { return m_tabsBar; } Tabs* getTabsBar() { return m_tabsBar; }
widgets::Workspace* getWorkspace() { return m_workspace; }
widgets::MiniEditorWindow* getMiniEditor() { return m_miniEditor; }
void reloadMenus(); void reloadMenus();
void createFirstEditor();
bool isAdvancedMode() const { return m_advancedMode; } bool isAdvancedMode() const { return m_advancedMode; }
void setAdvancedMode(bool advanced); void setAdvancedMode(bool advanced);
// TabsDelegate implementation.
void clickTab(Tabs* tabs, TabView* tabView, int button);
void mouseOverTab(Tabs* tabs, TabView* tabView);
protected: protected:
void onSaveLayout(ui::SaveLayoutEvent& ev) OVERRIDE; void onSaveLayout(ui::SaveLayoutEvent& ev) OVERRIDE;
private: private:
AppTabsDelegate* m_tabsDelegate;
MainMenuBar* m_menuBar; // the menu bar widget MainMenuBar* m_menuBar; // the menu bar widget
StatusBar* m_statusBar; // the status bar widget StatusBar* m_statusBar; // the status bar widget
ColorBar* m_colorBar; // the color bar widget ColorBar* m_colorBar; // the color bar widget
@ -59,6 +66,8 @@ private:
Tabs* m_tabsBar; // The tabs bar widget Tabs* m_tabsBar; // The tabs bar widget
double m_lastSplitterPos; double m_lastSplitterPos;
bool m_advancedMode; bool m_advancedMode;
widgets::Workspace* m_workspace; // The workspace (document's views)
widgets::MiniEditorWindow* m_miniEditor;
}; };
#endif #endif

144
src/widgets/mini_editor.cpp Normal file
View File

@ -0,0 +1,144 @@
/* ASEPRITE
* Copyright (C) 2001-2012 David Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "widgets/mini_editor.h"
#include "gfx/rect.h"
#include "ini_file.h"
#include "modules/editors.h"
#include "modules/gui.h"
#include "skin/skin_theme.h"
#include "ui/base.h"
#include "ui/button.h"
#include "ui/close_event.h"
#include "ui/rect.h"
#include "ui/system.h"
#include "widgets/editor/editor.h"
#include "widgets/status_bar.h"
#include "widgets/toolbar.h"
using namespace ui;
namespace widgets {
MiniEditorWindow::MiniEditorWindow()
: Window(false, "Mini-Editor")
, m_docView(NULL)
{
child_spacing = 0;
setAutoRemap(false);
setWantFocus(false);
// Default bounds
int width = JI_SCREEN_W/4;
int height = JI_SCREEN_H/4;
setBounds(gfx::Rect(JI_SCREEN_W - width - jrect_w(ToolBar::instance()->rc),
JI_SCREEN_H - height - jrect_h(StatusBar::instance()->rc),
width, height));
load_window_pos(this, "MiniEditor");
m_isEnabled = get_config_bool("MiniEditor", "Enabled", true);
}
MiniEditorWindow::~MiniEditorWindow()
{
set_config_bool("MiniEditor", "Enabled", m_isEnabled);
save_window_pos(this, "MiniEditor");
}
void MiniEditorWindow::setMiniEditorEnabled(bool state)
{
m_isEnabled = state;
updateUsingEditor(current_editor);
}
void MiniEditorWindow::onClose(ui::CloseEvent& ev)
{
Button* closeButton = dynamic_cast<Button*>(ev.getSource());
if (closeButton != NULL &&
closeButton->getId() == SkinTheme::kThemeCloseButtonId) {
// Here we don't use "setMiniEditorEnabled" to change the state of
// "m_isEnabled" because we're coming from a close event of the
// window.
m_isEnabled = false;
// Redraw the tool bar because it shows the mini editor enabled
// state. TODO abstract this event
ToolBar::instance()->invalidate();
delete m_docView;
m_docView = NULL;
}
}
void MiniEditorWindow::updateUsingEditor(Editor* editor)
{
if (!m_isEnabled || !editor) {
hideWindow();
return;
}
Document* document = editor->getDocument();
Editor* miniEditor = (m_docView ? m_docView->getEditor(): NULL);
// Show the mini editor if it wasn't created yet and the user
// zoomed in, or if the mini-editor was created and the zoom of
// both editors is not the same.
if (document &&
document->getSprite() &&
((!isVisible() && editor->getZoom() > 0) ||
(isVisible() && (!miniEditor || miniEditor->getZoom() != editor->getZoom())))) {
if (!isVisible())
openWindow();
gfx::Rect visibleBounds = editor->getVisibleSpriteBounds();
gfx::Point pt = visibleBounds.getCenter();
// Set the same location as in the given editor.
if (!miniEditor || miniEditor->getDocument() != document) {
delete m_docView;
m_docView = new DocumentView(document, DocumentView::Mini); // MiniEditorDocumentView(document, this);
addChild(m_docView);
miniEditor = m_docView->getEditor();
miniEditor->setZoom(0);
miniEditor->setState(EditorStatePtr(new EditorState));
layout();
}
miniEditor->centerInSpritePoint(pt.x, pt.y);
}
else {
hideWindow();
}
}
void MiniEditorWindow::hideWindow()
{
delete m_docView;
m_docView = NULL;
if (isVisible())
closeWindow(NULL);
}
} // namespace widgets

50
src/widgets/mini_editor.h Normal file
View File

@ -0,0 +1,50 @@
/* ASEPRITE
* Copyright (C) 2001-2012 David Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef WIDGETS_MINI_EDITOR_VIEW_H_INCLUDED
#define WIDGETS_MINI_EDITOR_VIEW_H_INCLUDED
#include "ui/window.h"
#include "widgets/document_view.h"
namespace widgets {
class MiniEditorWindow : public ui::Window
{
public:
MiniEditorWindow();
~MiniEditorWindow();
bool isMiniEditorEnabled() const { return m_isEnabled; }
void setMiniEditorEnabled(bool state);
void updateUsingEditor(Editor* editor);
protected:
void onClose(ui::CloseEvent& ev) OVERRIDE;
private:
void hideWindow();
bool m_isEnabled;
DocumentView* m_docView;
};
} // namespace widgets
#endif

View File

@ -779,7 +779,7 @@ bool StatusBar::onProcessMessage(Message* msg)
sprite->setCurrentLayer(layer); sprite->setCurrentLayer(layer);
// Flash the current layer // Flash the current layer
ASSERT(current_editor != NULL); // Cannot be null when we have a current sprite if (current_editor != NULL)
current_editor->flashCurrentLayer(); current_editor->flashCurrentLayer();
// Redraw the status-bar // Redraw the status-bar

View File

@ -122,10 +122,10 @@ Tabs::~Tabs()
delete m_button_right; // widget delete m_button_right; // widget
} }
void Tabs::addTab(const char* text, void* data) void Tabs::addTab(TabView* tabView)
{ {
Tab *tab = new Tab(text, data); Tab* tab = new Tab(tabView);
tab->width = calcTabWidth(tab); calcTabWidth(tab);
m_list_of_tabs.push_back(tab); m_list_of_tabs.push_back(tab);
@ -133,14 +133,14 @@ void Tabs::addTab(const char* text, void* data)
setScrollX(m_scrollX); setScrollX(m_scrollX);
startAni(ANI_ADDING_TAB); startAni(ANI_ADDING_TAB);
//invalidate();
} }
void Tabs::removeTab(void* data) void Tabs::removeTab(TabView* tabView)
{ {
Tab *tab = getTabByData(data); Tab* tab = getTabByView(tabView);
if (!tab)
return;
if (tab) {
if (m_hot == tab) m_hot = NULL; if (m_hot == tab) m_hot = NULL;
if (m_selected == tab) m_selected = NULL; if (m_selected == tab) m_selected = NULL;
@ -169,34 +169,30 @@ void Tabs::removeTab(void* data)
startAni(ANI_REMOVING_TAB); startAni(ANI_REMOVING_TAB);
} }
}
void Tabs::setTabText(const char* text, void* data) void Tabs::updateTabsText()
{ {
Tab* tab = getTabByData(data); TabsListIterator it, end = m_list_of_tabs.end();
if (tab) {
for (it = m_list_of_tabs.begin(); it != end; ++it) {
Tab* tab = *it;
// Change text of the tab // Change text of the tab
tab->text = text; calcTabWidth(tab);
tab->width = calcTabWidth(tab); }
// Make it visible (if it's the selected)
if (m_selected == tab)
makeTabVisible(tab);
invalidate(); invalidate();
} }
}
void Tabs::selectTab(void* data) void Tabs::selectTab(TabView* tabView)
{ {
Tab *tab = getTabByData(data); Tab *tab = getTabByView(tabView);
if (tab != NULL) if (tab != NULL)
selectTabInternal(tab); selectTabInternal(tab);
} }
void Tabs::selectNextTab() void Tabs::selectNextTab()
{ {
TabsListIterator currentTabIt = getTabIteratorByData(m_selected->data); TabsListIterator currentTabIt = getTabIteratorByView(m_selected->view);
TabsListIterator it = currentTabIt; TabsListIterator it = currentTabIt;
if (it != m_list_of_tabs.end()) { if (it != m_list_of_tabs.end()) {
// If we are at the end of the list, cycle to the first tab. // If we are at the end of the list, cycle to the first tab.
@ -209,14 +205,14 @@ void Tabs::selectNextTab()
if (it != currentTabIt) { if (it != currentTabIt) {
selectTabInternal(*it); selectTabInternal(*it);
if (m_delegate) if (m_delegate)
m_delegate->clickTab(this, m_selected->data, 1); m_delegate->clickTab(this, m_selected->view, 1);
} }
} }
} }
void Tabs::selectPreviousTab() void Tabs::selectPreviousTab()
{ {
TabsListIterator currentTabIt = getTabIteratorByData(m_selected->data); TabsListIterator currentTabIt = getTabIteratorByView(m_selected->view);
TabsListIterator it = currentTabIt; TabsListIterator it = currentTabIt;
if (it != m_list_of_tabs.end()) { if (it != m_list_of_tabs.end()) {
// If we are at the beginning of the list, cycle to the last tab. // If we are at the beginning of the list, cycle to the last tab.
@ -229,15 +225,15 @@ void Tabs::selectPreviousTab()
if (it != currentTabIt) { if (it != currentTabIt) {
selectTabInternal(*it); selectTabInternal(*it);
if (m_delegate) if (m_delegate)
m_delegate->clickTab(this, m_selected->data, 1); m_delegate->clickTab(this, m_selected->view, 1);
} }
} }
} }
void* Tabs::getSelectedTab() TabView* Tabs::getSelectedTab()
{ {
if (m_selected != NULL) if (m_selected != NULL)
return m_selected->data; return m_selected->view;
else else
return NULL; return NULL;
} }
@ -359,7 +355,7 @@ bool Tabs::onProcessMessage(Message* msg)
if (m_selected && m_delegate) if (m_selected && m_delegate)
m_delegate->clickTab(this, m_delegate->clickTab(this,
m_selected->data, m_selected->view,
msg->mouse.flags); msg->mouse.flags);
} }
return true; return true;
@ -457,7 +453,7 @@ void Tabs::onSetText()
for (it = m_list_of_tabs.begin(); it != end; ++it) { for (it = m_list_of_tabs.begin(); it != end; ++it) {
Tab* tab = *it; Tab* tab = *it;
tab->width = calcTabWidth(tab); calcTabWidth(tab);
} }
} }
@ -523,21 +519,21 @@ void Tabs::drawTab(BITMAP* bmp, JRect box, Tab* tab, int y_delta, bool selected)
#endif #endif
} }
Tabs::TabsListIterator Tabs::getTabIteratorByData(void* data) Tabs::TabsListIterator Tabs::getTabIteratorByView(TabView* tabView)
{ {
TabsListIterator it, end = m_list_of_tabs.end(); TabsListIterator it, end = m_list_of_tabs.end();
for (it = m_list_of_tabs.begin(); it != end; ++it) { for (it = m_list_of_tabs.begin(); it != end; ++it) {
if ((*it)->data == data) if ((*it)->view == tabView)
break; break;
} }
return it; return it;
} }
Tabs::Tab* Tabs::getTabByData(void* data) Tabs::Tab* Tabs::getTabByView(TabView* tabView)
{ {
TabsListIterator it = getTabIteratorByData(data); TabsListIterator it = getTabIteratorByView(tabView);
if (it != m_list_of_tabs.end()) if (it != m_list_of_tabs.end())
return *it; return *it;
else else
@ -656,7 +652,7 @@ void Tabs::calculateHot()
m_hot = hot; m_hot = hot;
if (m_delegate) if (m_delegate)
m_delegate->mouseOverTab(this, m_hot ? m_hot->data: NULL); m_delegate->mouseOverTab(this, m_hot ? m_hot->view: NULL);
invalidate(); invalidate();
} }
@ -665,15 +661,18 @@ void Tabs::calculateHot()
jrect_free(box); jrect_free(box);
} }
int Tabs::calcTabWidth(Tab* tab) void Tabs::calcTabWidth(Tab* tab)
{ {
// Cache current tab text
tab->text = tab->view->getTabText();
int border = 4*jguiscale(); int border = 4*jguiscale();
#ifdef CLOSE_BUTTON_IN_EACH_TAB #ifdef CLOSE_BUTTON_IN_EACH_TAB
SkinTheme* theme = static_cast<SkinTheme*>(this->theme); SkinTheme* theme = static_cast<SkinTheme*>(this->theme);
int close_icon_w = theme->get_part(PART_WINDOW_CLOSE_BUTTON_NORMAL)->w; int close_icon_w = theme->get_part(PART_WINDOW_CLOSE_BUTTON_NORMAL)->w;
return (border + text_length(getFont(), tab->text.c_str()) + border + close_icon_w + border); tab->width = (border + text_length(getFont(), tab->text.c_str()) + border + close_icon_w + border);
#else #else
return (border + text_length(getFont(), tab->text.c_str()) + border); tab->width = (border + text_length(getFont(), tab->text.c_str()) + border);
#endif #endif
} }

View File

@ -27,6 +27,17 @@
class Tabs; class Tabs;
// Required interface to be implemented by each new tab that is added
// in the Tabs widget.
class TabView
{
public:
virtual ~TabView() { }
// Returns the text to be shown in the tab.
virtual std::string getTabText() = 0;
};
// Interface used to control notifications from the Tabs widget. // Interface used to control notifications from the Tabs widget.
class TabsDelegate class TabsDelegate
{ {
@ -37,29 +48,22 @@ public:
// button & 1 => left click // button & 1 => left click
// button & 2 => right click // button & 2 => right click
// button & 4 => middle click // button & 4 => middle click
virtual void clickTab(Tabs* tabs, void* data, int button) = 0; virtual void clickTab(Tabs* tabs, TabView* tabView, int button) = 0;
// Called when the mouse is over a tab (the data can be null if the // Called when the mouse is over a tab (the data can be null if the
// mouse just leave all tabs) // mouse just leave all tabs)
virtual void mouseOverTab(Tabs* tabs, void* data) = 0; virtual void mouseOverTab(Tabs* tabs, TabView* tabView) = 0;
}; };
// Tabs control. // Tabs control. Used to show opened documents.
//
// Used to show opened files/sprites.
class Tabs : public ui::Widget class Tabs : public ui::Widget
{ {
struct Tab struct Tab {
{ TabView* view;
std::string text; // Label in the tab std::string text;
void* data; // Opaque pointer to user data int width;
int width; // Width of the tab
Tab(const char* text, void* data) Tab(TabView* view) : view(view), width(0) {
{
this->text = text;
this->data = data;
this->width = 0;
} }
}; };
@ -76,15 +80,14 @@ public:
Tabs(TabsDelegate* delegate); Tabs(TabsDelegate* delegate);
~Tabs(); ~Tabs();
void addTab(const char* text, void* data); void addTab(TabView* tabView);
void removeTab(void* data); void removeTab(TabView* tabView);
void updateTabsText();
void setTabText(const char* text, void* data); void selectTab(TabView* tabView);
void selectTab(void* data);
void selectNextTab(); void selectNextTab();
void selectPreviousTab(); void selectPreviousTab();
void* getSelectedTab(); TabView* getSelectedTab();
void startScrolling(); void startScrolling();
void stopScrolling(); void stopScrolling();
@ -101,13 +104,13 @@ private:
void selectTabInternal(Tab* tab); void selectTabInternal(Tab* tab);
void drawTab(BITMAP* bmp, ui::JRect box, Tab* tab, int y_delta, bool selected); void drawTab(BITMAP* bmp, ui::JRect box, Tab* tab, int y_delta, bool selected);
TabsListIterator getTabIteratorByData(void* data); TabsListIterator getTabIteratorByView(TabView* tabView);
Tab* getTabByData(void* data); Tab* getTabByView(TabView* tabView);
int getMaxScrollX(); int getMaxScrollX();
void makeTabVisible(Tab* tab); void makeTabVisible(Tab* tab);
void setScrollX(int scroll_x); void setScrollX(int scroll_x);
void calculateHot(); void calculateHot();
int calcTabWidth(Tab* tab); void calcTabWidth(Tab* tab);
TabsList m_list_of_tabs; TabsList m_list_of_tabs;
Tab* m_hot; Tab* m_hot;

View File

@ -34,6 +34,8 @@
#include "tools/tool_box.h" #include "tools/tool_box.h"
#include "ui/gui.h" #include "ui/gui.h"
#include "ui_context.h" #include "ui_context.h"
#include "widgets/main_window.h"
#include "widgets/mini_editor.h"
#include "widgets/status_bar.h" #include "widgets/status_bar.h"
#include <allegro.h> #include <allegro.h>
@ -190,7 +192,7 @@ bool ToolBar::onProcessMessage(Message* msg)
toolrc = getToolGroupBounds(MiniEditorVisibilityIndex); toolrc = getToolGroupBounds(MiniEditorVisibilityIndex);
toolrc.offset(-msg->draw.rect.x1, -msg->draw.rect.y1); toolrc.offset(-msg->draw.rect.x1, -msg->draw.rect.y1);
isHot = (m_hot_index == MiniEditorVisibilityIndex || isHot = (m_hot_index == MiniEditorVisibilityIndex ||
is_mini_editor_enabled()); App::instance()->getMainWindow()->getMiniEditor()->isMiniEditorEnabled());
theme->draw_bounds_nw(doublebuffer, theme->draw_bounds_nw(doublebuffer,
toolrc, toolrc,
isHot ? PART_TOOLBUTTON_HOT_NW: isHot ? PART_TOOLBUTTON_HOT_NW:
@ -248,7 +250,10 @@ bool ToolBar::onProcessMessage(Message* msg)
toolrc = getToolGroupBounds(MiniEditorVisibilityIndex); toolrc = getToolGroupBounds(MiniEditorVisibilityIndex);
if (msg->mouse.y >= toolrc.y && msg->mouse.y < toolrc.y+toolrc.h) { if (msg->mouse.y >= toolrc.y && msg->mouse.y < toolrc.y+toolrc.h) {
// Switch the state of the mini editor // Switch the state of the mini editor
enable_mini_editor(!is_mini_editor_enabled()); widgets::MiniEditorWindow* miniEditorWindow =
App::instance()->getMainWindow()->getMiniEditor();
bool state = miniEditorWindow->isMiniEditorEnabled();
miniEditorWindow->setMiniEditorEnabled(!state);
} }
break; break;
} }
@ -501,7 +506,7 @@ void ToolBar::openTipWindow(int group_index, Tool* tool)
tooltip = "Configure Tool"; tooltip = "Configure Tool";
} }
else if (group_index == MiniEditorVisibilityIndex) { else if (group_index == MiniEditorVisibilityIndex) {
if (is_mini_editor_enabled()) if (App::instance()->getMainWindow()->getMiniEditor()->isMiniEditorEnabled())
tooltip = "Disable Mini-Editor"; tooltip = "Disable Mini-Editor";
else else
tooltip = "Enable Mini-Editor"; tooltip = "Enable Mini-Editor";

96
src/widgets/workspace.cpp Normal file
View File

@ -0,0 +1,96 @@
/* ASEPRITE
* Copyright (C) 2001-2012 David Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "widgets/workspace.h"
#include "skin/skin_theme.h"
#include "widgets/workspace_view.h"
#include <algorithm>
using namespace ui;
using namespace widgets;
Workspace::Workspace()
: Box(JI_VERTICAL)
, m_activeView(NULL)
{
SkinTheme* theme = static_cast<SkinTheme*>(getTheme());
setBgColor(theme->getColor(ThemeColor::Workspace));
}
Workspace::~Workspace()
{
}
void Workspace::addView(WorkspaceView* view)
{
m_views.push_back(view);
addChild(view->getContentWidget());
setActiveView(view);
}
void Workspace::removeView(WorkspaceView* view)
{
WorkspaceViews::iterator it = std::find(m_views.begin(), m_views.end(), view);
ASSERT(it != m_views.end());
m_views.erase(it);
removeChild(view->getContentWidget());
setActiveView(NULL);
}
void Workspace::setActiveView(WorkspaceView* view)
{
m_activeView = view;
Widget* newContent = (view ? view->getContentWidget(): NULL);
WidgetsList children = getChildren();
UI_FOREACH_WIDGET(children, it) {
if ((*it) != newContent)
(*it)->setVisible(false);
}
if (newContent) {
newContent->setExpansive(true);
newContent->setVisible(true);
newContent->requestFocus();
}
layout();
}
void Workspace::splitView(WorkspaceView* view, int orientation)
{
// TODO
}
void Workspace::closeView(WorkspaceView* view)
{
// TODO
}
void Workspace::makeUnique(WorkspaceView* view)
{
// TODO
}

53
src/widgets/workspace.h Normal file
View File

@ -0,0 +1,53 @@
/* ASEPRITE
* Copyright (C) 2001-2012 David Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef WIDGETS_WORKSPACE_H_INCLUDED
#define WIDGETS_WORKSPACE_H_INCLUDED
#include "ui/box.h"
#include <vector>
namespace widgets {
class WorkspaceView;
typedef std::vector<WorkspaceView*> WorkspaceViews;
class Workspace : public ui::Box
{
public:
Workspace();
~Workspace();
void addView(WorkspaceView* view);
void removeView(WorkspaceView* view);
WorkspaceView* getActiveView() { return m_activeView; }
void setActiveView(WorkspaceView* view);
void splitView(WorkspaceView* view, int orientation);
void closeView(WorkspaceView* view);
void makeUnique(WorkspaceView* view);
private:
WorkspaceView* m_activeView;
WorkspaceViews m_views;
};
} // namespace widgets
#endif

View File

@ -0,0 +1,36 @@
/* ASEPRITE
* Copyright (C) 2001-2012 David Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef WIDGETS_WORKSPACE_VIEW_H_INCLUDED
#define WIDGETS_WORKSPACE_VIEW_H_INCLUDED
namespace ui { class Widget; }
namespace widgets {
class WorkspaceView
{
public:
virtual ~WorkspaceView() { }
virtual ui::Widget* getContentWidget() = 0;
};
} // namespace widgets
#endif