mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-30 04:20:23 +00:00
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:
parent
8cc854aef6
commit
ed90055bf7
12
data/gui.xml
12
data/gui.xml
@ -71,7 +71,6 @@
|
||||
<key command="MakeUniqueEditor" shortcut="Ctrl+1" />
|
||||
<key command="SplitEditorVertically" shortcut="Ctrl+2" />
|
||||
<key command="SplitEditorHorizontally" shortcut="Ctrl+3" />
|
||||
<key command="CloseEditor" shortcut="Ctrl+4" />
|
||||
<key command="Preview" shortcut="F8" />
|
||||
<key command="ShowGrid" shortcut="Shift+G" />
|
||||
<key command="SnapToGrid" shortcut="Shift+S" />
|
||||
@ -355,14 +354,9 @@
|
||||
<item command="SaveMask" text="&Save to MSK file" />
|
||||
</menu>
|
||||
<menu text="&View">
|
||||
<menu text="Sprite &Editor">
|
||||
<item command="MakeUniqueEditor" text="Make &Unique" />
|
||||
<separator />
|
||||
<item command="SplitEditorVertically" text="Split &Vertically" />
|
||||
<item command="SplitEditorHorizontally" text="Split &Horizontally" />
|
||||
<separator />
|
||||
<item command="CloseEditor" text="&Close" />
|
||||
</menu>
|
||||
<item command="MakeUniqueEditor" text="Make &Unique" />
|
||||
<item command="SplitEditorVertically" text="Split &Vertically" />
|
||||
<item command="SplitEditorHorizontally" text="Split &Horizontally" />
|
||||
<separator />
|
||||
<item command="ShowGrid" text="Show &Grid" />
|
||||
<item command="SnapToGrid" text="&Snap to Grid" />
|
||||
|
@ -61,6 +61,7 @@
|
||||
<color id="filelist_selected_row_text" value="#ffffff" />
|
||||
<color id="filelist_selected_row_face" value="#2c4c91" />
|
||||
<color id="filelist_disabled_row_text" value="#ffc8c8" />
|
||||
<color id="workspace" value="#7d929e" />
|
||||
</colors>
|
||||
|
||||
<cursors>
|
||||
|
@ -9,7 +9,7 @@
|
||||
horizontal="true" expansive="true"
|
||||
by="pixel" position="52">
|
||||
<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>
|
||||
<box noborders="true" vertical="true" id="toolbar" />
|
||||
</box>
|
||||
|
@ -255,7 +255,6 @@ add_library(aseprite-library
|
||||
commands/cmd_save_file.cpp
|
||||
commands/cmd_save_mask.cpp
|
||||
commands/cmd_scroll.cpp
|
||||
commands/cmd_select_file.cpp
|
||||
commands/cmd_sprite_editor.cpp
|
||||
commands/cmd_sprite_properties.cpp
|
||||
commands/cmd_sprite_size.cpp
|
||||
@ -377,6 +376,7 @@ add_library(aseprite-library
|
||||
widgets/color_button.cpp
|
||||
widgets/color_selector.cpp
|
||||
widgets/color_sliders.cpp
|
||||
widgets/document_view.cpp
|
||||
widgets/drop_down_button.cpp
|
||||
widgets/editor/cursor.cpp
|
||||
widgets/editor/drawing_state.cpp
|
||||
@ -399,11 +399,13 @@ add_library(aseprite-library
|
||||
widgets/main_menu_bar.cpp
|
||||
widgets/main_window.cpp
|
||||
widgets/menuitem2.cpp
|
||||
widgets/mini_editor.cpp
|
||||
widgets/palette_view.cpp
|
||||
widgets/popup_window_pin.cpp
|
||||
widgets/status_bar.cpp
|
||||
widgets/tabs.cpp
|
||||
widgets/toolbar.cpp)
|
||||
widgets/toolbar.cpp
|
||||
widgets/workspace.cpp)
|
||||
|
||||
######################################################################
|
||||
# ASEPRITE application
|
||||
|
39
src/app.cpp
39
src/app.cpp
@ -40,7 +40,6 @@
|
||||
#include "ini_file.h"
|
||||
#include "log.h"
|
||||
#include "modules.h"
|
||||
#include "modules/editors.h"
|
||||
#include "modules/gfx.h"
|
||||
#include "modules/gui.h"
|
||||
#include "modules/palettes.h"
|
||||
@ -158,7 +157,10 @@ int App::run()
|
||||
|
||||
// Create the main window and show it.
|
||||
m_mainWindow.reset(new MainWindow);
|
||||
m_mainWindow->createFirstEditor();
|
||||
|
||||
// Create the list of tabs
|
||||
app_rebuild_documents_tabs();
|
||||
|
||||
m_mainWindow->openWindow();
|
||||
|
||||
// Redraw the whole screen.
|
||||
@ -190,9 +192,6 @@ int App::run()
|
||||
context->setActiveDocument(document);
|
||||
|
||||
if (isGui()) {
|
||||
// Show it
|
||||
set_document_in_more_reliable_editor(context->getFirstDocument());
|
||||
|
||||
// Recent file
|
||||
getRecentFiles()->addRecentFile(it->c_str());
|
||||
}
|
||||
@ -217,6 +216,11 @@ int App::run()
|
||||
// Uninstall support to 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.
|
||||
m_mainWindow.reset(NULL);
|
||||
}
|
||||
@ -295,32 +299,9 @@ void app_refresh_screen(const Document* document)
|
||||
ui::Manager::getDefault()->invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Regenerates the label for each tab in the @em tabsbar.
|
||||
*/
|
||||
void app_rebuild_documents_tabs()
|
||||
{
|
||||
UIContext* context = UIContext::instance();
|
||||
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));
|
||||
App::instance()->getMainWindow()->getTabsBar()->updateTabsText();
|
||||
}
|
||||
|
||||
PixelFormat app_get_current_pixel_format()
|
||||
|
@ -86,7 +86,6 @@ private:
|
||||
void app_refresh_screen(const Document* document);
|
||||
|
||||
void app_rebuild_documents_tabs();
|
||||
void app_update_document_tab(const Document* document);
|
||||
|
||||
PixelFormat app_get_current_pixel_format();
|
||||
|
||||
|
@ -213,9 +213,8 @@ void CanvasSizeCommand::onExecute(Context* context)
|
||||
undoTransaction.commit();
|
||||
|
||||
documentWriter->generateMaskBoundaries();
|
||||
update_screen_for_document(documentWriter);
|
||||
}
|
||||
|
||||
update_screen_for_document(document);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
@ -146,7 +146,7 @@ void CelPropertiesCommand::onExecute(Context* context)
|
||||
// Change cel opacity.
|
||||
cel_writer->setOpacity(new_opacity);
|
||||
|
||||
update_screen_for_document(document);
|
||||
update_screen_for_document(document_writer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,11 +27,15 @@
|
||||
#include "raster/sprite.h"
|
||||
#include "ui/gui.h"
|
||||
#include "ui_context.h"
|
||||
#include "widgets/document_view.h"
|
||||
#include "widgets/main_window.h"
|
||||
#include "widgets/status_bar.h"
|
||||
#include "widgets/workspace.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
using namespace ui;
|
||||
using namespace widgets;
|
||||
|
||||
static bool close_active_document(Context* context);
|
||||
|
||||
@ -61,7 +65,23 @@ protected:
|
||||
|
||||
void onExecute(Context* context)
|
||||
{
|
||||
close_active_document(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);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Close the active view.
|
||||
workspace->closeView(workspace->getActiveView());
|
||||
}
|
||||
|
||||
private:
|
||||
@ -92,14 +112,14 @@ protected:
|
||||
|
||||
void onExecute(Context* context)
|
||||
{
|
||||
if (!context->getActiveDocument())
|
||||
set_document_in_more_reliable_editor(context->getFirstDocument());
|
||||
|
||||
while (true) {
|
||||
if (context->getActiveDocument() != NULL) {
|
||||
if (!close_active_document(context))
|
||||
break;
|
||||
}
|
||||
else if (context->getFirstDocument() != NULL) {
|
||||
context->setActiveDocument(context->getFirstDocument());
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
@ -115,6 +135,7 @@ protected:
|
||||
*/
|
||||
static bool close_active_document(Context* context)
|
||||
{
|
||||
Document* nextDocument = NULL;
|
||||
bool save_it;
|
||||
bool try_again = true;
|
||||
|
||||
@ -124,6 +145,7 @@ static bool close_active_document(Context* context)
|
||||
{
|
||||
// The sprite is locked as reader temporaly
|
||||
ActiveDocumentReader document(context);
|
||||
nextDocument = context->getNextDocument(document);
|
||||
|
||||
// see if the sprite has changes
|
||||
while (document->isModified()) {
|
||||
@ -167,6 +189,10 @@ static bool close_active_document(Context* context)
|
||||
base::get_file_name(document->getFilename()).c_str());
|
||||
document.deleteDocument();
|
||||
}
|
||||
|
||||
// Select next document in the context
|
||||
context->setActiveDocument(nextDocument);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -498,13 +498,11 @@ void ConfigureTools::onSnapToGridClick()
|
||||
void ConfigureTools::onViewGridClick()
|
||||
{
|
||||
m_docSettings->setGridVisible(m_viewGrid->isSelected());
|
||||
refresh_all_editors();
|
||||
}
|
||||
|
||||
void ConfigureTools::onPixelGridClick()
|
||||
{
|
||||
m_docSettings->setPixelGridVisible(m_pixelGrid->isSelected());
|
||||
refresh_all_editors();
|
||||
}
|
||||
|
||||
void ConfigureTools::onSetGridClick()
|
||||
@ -517,9 +515,6 @@ void ConfigureTools::onSetGridClick()
|
||||
const Mask* mask(document->getMask());
|
||||
|
||||
m_docSettings->setGridBounds(mask->getBounds());
|
||||
|
||||
if (m_docSettings->getGridVisible())
|
||||
refresh_all_editors();
|
||||
}
|
||||
else {
|
||||
Command* grid_settings_cmd =
|
||||
@ -536,7 +531,6 @@ void ConfigureTools::onSetGridClick()
|
||||
void ConfigureTools::onOnionSkinClick()
|
||||
{
|
||||
m_docSettings->setUseOnionskin(m_onionSkin->isSelected());
|
||||
refresh_all_editors();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
@ -97,7 +97,6 @@ void DuplicateSpriteCommand::onExecute(Context* context)
|
||||
docCopy->setFilename(dst_name->getText());
|
||||
|
||||
context->addDocument(docCopy);
|
||||
set_document_in_more_reliable_editor(docCopy);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,15 +18,15 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "commands/command.h"
|
||||
#include "app.h"
|
||||
#include "commands/command.h"
|
||||
#include "document_wrappers.h"
|
||||
#include "modules/gui.h"
|
||||
#include "modules/editors.h"
|
||||
#include "raster/layer.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "widgets/editor/editor.h"
|
||||
#include "widgets/status_bar.h"
|
||||
#include "document_wrappers.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// goto_previous_layer
|
||||
|
@ -63,8 +63,6 @@ protected:
|
||||
IDocumentSettings* docSettings = context->getSettings()->getDocumentSettings(context->getActiveDocument());
|
||||
|
||||
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);
|
||||
|
||||
docSettings->setGridBounds(bounds);
|
||||
|
||||
if (docSettings->getGridVisible())
|
||||
refresh_all_editors(); // TODO this should be done by "setGridBounds" impl
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "widgets/editor/editor_decorator.h"
|
||||
#include "widgets/editor/select_box_state.h"
|
||||
#include "widgets/editor/standby_state.h"
|
||||
#include "widgets/workspace.h"
|
||||
|
||||
#include <allegro/color.h>
|
||||
|
||||
@ -129,7 +130,7 @@ protected:
|
||||
MenuItem* item = new MenuItem("Use Current Sprite");
|
||||
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);
|
||||
|
||||
menu->addChild(item);
|
||||
|
@ -97,7 +97,7 @@ void LayerPropertiesCommand::onExecute(Context* context)
|
||||
|
||||
const_cast<Layer*>(layer)->setName(entry_name->getText());
|
||||
|
||||
update_screen_for_document(document);
|
||||
update_screen_for_document(documentWriter);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,9 +94,8 @@ void LoadMaskCommand::onExecute(Context* context)
|
||||
|
||||
undo.commit();
|
||||
documentWriter->generateMaskBoundaries();
|
||||
update_screen_for_document(documentWriter);
|
||||
}
|
||||
|
||||
update_screen_for_document(document);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "ui_context.h"
|
||||
#include "util/clipboard.h"
|
||||
#include "widgets/color_bar.h"
|
||||
#include "widgets/workspace.h"
|
||||
|
||||
#include <allegro/config.h>
|
||||
#include <allegro/unicode.h>
|
||||
@ -187,11 +188,7 @@ void NewFileCommand::onExecute(Context* context)
|
||||
}
|
||||
|
||||
// Show the sprite to the user
|
||||
context->addDocument(document);
|
||||
|
||||
// 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());
|
||||
context->addDocument(document.release());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -148,8 +148,6 @@ void OpenFileCommand::onExecute(Context* context)
|
||||
|
||||
App::instance()->getRecentFiles()->addRecentFile(fop->filename.c_str());
|
||||
context->addDocument(document);
|
||||
|
||||
set_document_in_more_reliable_editor(document);
|
||||
}
|
||||
else if (!fop_is_stop(fop))
|
||||
unrecent = true;
|
||||
|
@ -166,9 +166,6 @@ void OptionsCommand::onExecute(Context* context)
|
||||
|
||||
// Save configuration
|
||||
flush_config_file();
|
||||
|
||||
// Refresh all editors
|
||||
refresh_all_editors();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -413,8 +413,9 @@ bool PaletteEntryEditor::onProcessMessage(Message* msg)
|
||||
|
||||
// Redraw all editors
|
||||
try {
|
||||
const ActiveDocumentReader document(UIContext::instance());
|
||||
update_editors_with_document(document);
|
||||
ActiveDocumentWriter document(UIContext::instance());
|
||||
if (document != NULL)
|
||||
document->notifyGeneralUpdate();
|
||||
}
|
||||
catch (...) {
|
||||
// Do nothing
|
||||
@ -423,7 +424,8 @@ bool PaletteEntryEditor::onProcessMessage(Message* msg)
|
||||
// Redraw just the current editor
|
||||
else {
|
||||
m_redrawAll = true;
|
||||
current_editor->updateEditor();
|
||||
if (current_editor != NULL)
|
||||
current_editor->updateEditor();
|
||||
}
|
||||
}
|
||||
return Window::onProcessMessage(msg);
|
||||
|
@ -115,7 +115,8 @@ void PlayAnimationCommand::onExecute(Context* context)
|
||||
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;
|
||||
|
||||
|
@ -142,6 +142,8 @@ static void save_as_dialog(const DocumentReader& document, const char* dlg_title
|
||||
|
||||
// Save the document
|
||||
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);
|
||||
|
||||
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
|
||||
// save-as dialog to the user to select for first time the file-name
|
||||
@ -192,8 +195,6 @@ void SaveFileCommand::onExecute(Context* context)
|
||||
else {
|
||||
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);
|
||||
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->setFilename(old_filename.c_str());
|
||||
update_screen_for_document(documentWriter);
|
||||
}
|
||||
|
||||
update_screen_for_document(document);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
@ -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;
|
||||
}
|
@ -18,34 +18,11 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "app.h"
|
||||
#include "commands/command.h"
|
||||
#include "modules/editors.h"
|
||||
#include "ui/base.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);
|
||||
}
|
||||
#include "widgets/main_window.h"
|
||||
#include "widgets/workspace.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// make_unique_editor
|
||||
@ -69,7 +46,9 @@ MakeUniqueEditorCommand::MakeUniqueEditorCommand()
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
split_editor(current_editor, JI_VERTICAL);
|
||||
widgets::Workspace* workspace = App::instance()->getMainWindow()->getWorkspace();
|
||||
if (workspace->getActiveView() != NULL)
|
||||
workspace->splitView(workspace->getActiveView(), JI_VERTICAL);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// CommandFactory
|
||||
|
||||
Command* CommandFactory::createCloseEditorCommand()
|
||||
{
|
||||
return new CloseEditorCommand;
|
||||
}
|
||||
|
||||
Command* CommandFactory::createMakeUniqueEditorCommand()
|
||||
{
|
||||
return new MakeUniqueEditorCommand;
|
||||
|
@ -240,7 +240,8 @@ void SpriteSizeCommand::onExecute(Context* context)
|
||||
job.startJob();
|
||||
}
|
||||
|
||||
update_screen_for_document(document);
|
||||
DocumentWriter docWriter(document);
|
||||
update_screen_for_document(docWriter);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,9 @@ void UndoCommand::onExecute(Context* context)
|
||||
if (spritePosition != sprite->getCurrentPosition()) {
|
||||
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);
|
||||
|
||||
ui::dirty_display_flag = true;
|
||||
|
@ -28,7 +28,6 @@ FOR_EACH_COMMAND(ChangePen)
|
||||
FOR_EACH_COMMAND(ChangePixelFormat)
|
||||
FOR_EACH_COMMAND(Clear)
|
||||
FOR_EACH_COMMAND(CloseAllFiles)
|
||||
FOR_EACH_COMMAND(CloseEditor)
|
||||
FOR_EACH_COMMAND(CloseFile)
|
||||
FOR_EACH_COMMAND(ColorCurve)
|
||||
FOR_EACH_COMMAND(ConfigureTools)
|
||||
@ -96,7 +95,6 @@ FOR_EACH_COMMAND(SaveFileAs)
|
||||
FOR_EACH_COMMAND(SaveFileCopyAs)
|
||||
FOR_EACH_COMMAND(SaveMask)
|
||||
FOR_EACH_COMMAND(Scroll)
|
||||
FOR_EACH_COMMAND(SelectFile)
|
||||
FOR_EACH_COMMAND(ShowGrid)
|
||||
FOR_EACH_COMMAND(SnapToGrid)
|
||||
FOR_EACH_COMMAND(SplitEditorHorizontally)
|
||||
|
@ -34,6 +34,9 @@ Context::Context(ISettings* settings)
|
||||
|
||||
Context::~Context()
|
||||
{
|
||||
// The context must be empty at this point.
|
||||
ASSERT(m_documents.empty());
|
||||
|
||||
delete m_settings;
|
||||
}
|
||||
|
||||
@ -54,13 +57,23 @@ Document* Context::getNextDocument(Document* document) const
|
||||
{
|
||||
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()) {
|
||||
++it;
|
||||
if (it != m_documents.end())
|
||||
if (it != end) {
|
||||
if (it != begin) {
|
||||
--it;
|
||||
return *it;
|
||||
}
|
||||
else {
|
||||
++it;
|
||||
if (it != end)
|
||||
return *it;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -103,6 +116,9 @@ Document* Context::getActiveDocument() const
|
||||
|
||||
void Context::setActiveDocument(Document* document)
|
||||
{
|
||||
if (document == m_activeDocument)
|
||||
return;
|
||||
|
||||
m_observers.notifyActiveDocumentBeforeChange(this);
|
||||
|
||||
m_activeDocument = document;
|
||||
|
@ -198,8 +198,6 @@ void switch_between_animation_and_sprite_editor()
|
||||
|
||||
// Destroy thumbnails
|
||||
destroy_thumbnails();
|
||||
|
||||
update_screen_for_document(document);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
@ -200,7 +200,7 @@ static void mask_preview(const DocumentReader& document)
|
||||
{
|
||||
DocumentWriter documentWriter(document);
|
||||
documentWriter->generateMaskBoundaries(mask);
|
||||
update_screen_for_document(documentWriter);
|
||||
}
|
||||
update_screen_for_document(document);
|
||||
}
|
||||
}
|
||||
|
@ -61,12 +61,6 @@ Document::Document(Sprite* sprite)
|
||||
// Boundary stuff
|
||||
m_bound.nseg = 0;
|
||||
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()
|
||||
@ -138,6 +132,18 @@ void Document::addSprite(Sprite* sprite)
|
||||
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
|
||||
{
|
||||
return m_filename.c_str();
|
||||
@ -172,19 +178,6 @@ void Document::setFormatOptions(const SharedPtr<FormatOptions>& 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
|
||||
|
||||
@ -473,7 +466,6 @@ Document* Document::duplicate(DuplicateType type) const
|
||||
|
||||
documentCopy->setMask(getMask());
|
||||
documentCopy->m_maskVisible = m_maskVisible;
|
||||
documentCopy->m_preferred = m_preferred;
|
||||
documentCopy->generateMaskBoundaries();
|
||||
|
||||
return documentCopy.release();
|
||||
|
@ -40,13 +40,7 @@ class Mutex;
|
||||
class Sprite;
|
||||
struct _BoundSeg;
|
||||
|
||||
struct PreferredEditorSettings
|
||||
{
|
||||
int scroll_x;
|
||||
int scroll_y;
|
||||
int zoom;
|
||||
bool virgin;
|
||||
};
|
||||
namespace gfx { class Region; }
|
||||
|
||||
enum DuplicateType
|
||||
{
|
||||
@ -85,6 +79,12 @@ public:
|
||||
|
||||
void addSprite(Sprite* sprite);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Notifications
|
||||
|
||||
void notifyGeneralUpdate();
|
||||
void notifySpritePixelsModified(Sprite* sprite, const gfx::Region& region);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// File related properties
|
||||
|
||||
@ -100,12 +100,6 @@ public:
|
||||
|
||||
void setFormatOptions(const SharedPtr<FormatOptions>& format_options);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Preferred editor settings
|
||||
|
||||
PreferredEditorSettings getPreferredEditorSettings() const;
|
||||
void setPreferredEditorSettings(const PreferredEditorSettings& settings);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Boundaries
|
||||
|
||||
@ -208,9 +202,6 @@ private:
|
||||
// Data to save the file in the same format that it was loaded
|
||||
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.)
|
||||
Cel* m_extraCel;
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#ifndef DOCUMENT_EVENT_H_INCLUDED
|
||||
#define DOCUMENT_EVENT_H_INCLUDED
|
||||
|
||||
#include "gfx/region.h"
|
||||
#include "raster/frame_number.h"
|
||||
|
||||
class Cel;
|
||||
@ -36,14 +37,16 @@ public:
|
||||
Cel* cel = NULL,
|
||||
Image* image = NULL,
|
||||
int imageIndex = -1,
|
||||
FrameNumber frame = FrameNumber())
|
||||
FrameNumber frame = FrameNumber(),
|
||||
const gfx::Region& region = gfx::Region())
|
||||
: m_document(document)
|
||||
, m_sprite(sprite)
|
||||
, m_layer(layer)
|
||||
, m_cel(cel)
|
||||
, m_image(image)
|
||||
, m_imageIndex(imageIndex)
|
||||
, m_frame(frame) {
|
||||
, m_frame(frame)
|
||||
, m_region(region) {
|
||||
}
|
||||
|
||||
Document* document() const { return m_document; }
|
||||
@ -53,6 +56,7 @@ public:
|
||||
Image* image() const { return m_image; }
|
||||
int imageIndex() const { return m_imageIndex; }
|
||||
FrameNumber frame() const { return m_frame; }
|
||||
const gfx::Region& region() const { return m_region; }
|
||||
|
||||
private:
|
||||
Document* m_document;
|
||||
@ -62,6 +66,7 @@ private:
|
||||
Image* m_image;
|
||||
int m_imageIndex;
|
||||
FrameNumber m_frame;
|
||||
gfx::Region m_region;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -29,6 +29,10 @@ class DocumentObserver {
|
||||
public:
|
||||
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 onAddLayer(DocumentEvent& ev) { }
|
||||
virtual void onAddFrame(DocumentEvent& ev) { }
|
||||
@ -51,6 +55,7 @@ public:
|
||||
|
||||
virtual void onImageReplaced(DocumentEvent& ev) { }
|
||||
virtual void onImagePixelsModified(DocumentEvent& ev) { }
|
||||
virtual void onSpritePixelsModified(DocumentEvent& ev) { }
|
||||
|
||||
// Called to destroy the observer. (Here you could call "delete this".)
|
||||
virtual void dispose() { }
|
||||
|
@ -40,6 +40,9 @@ public:
|
||||
const_iterator begin() const { return m_documents.begin(); }
|
||||
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(); }
|
||||
bool empty() const { return m_documents.empty(); }
|
||||
|
||||
|
@ -20,692 +20,4 @@
|
||||
|
||||
#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;
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -19,37 +19,7 @@
|
||||
#ifndef MODULES_EDITORS_H_INCLUDED
|
||||
#define MODULES_EDITORS_H_INCLUDED
|
||||
|
||||
class Document;
|
||||
class Editor;
|
||||
class Sprite;
|
||||
|
||||
namespace ui { class Widget; }
|
||||
|
||||
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
|
||||
|
@ -268,7 +268,7 @@ void set_screen_scaling(int scaling)
|
||||
screen_scaling = scaling;
|
||||
}
|
||||
|
||||
void update_screen_for_document(const Document* document)
|
||||
void update_screen_for_document(Document* document)
|
||||
{
|
||||
// Without document.
|
||||
if (!document) {
|
||||
@ -280,21 +280,10 @@ void update_screen_for_document(const Document* document)
|
||||
}
|
||||
// With a document.
|
||||
else {
|
||||
const Sprite* sprite = document->getSprite();
|
||||
|
||||
// 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);
|
||||
}
|
||||
document->notifyGeneralUpdate();
|
||||
|
||||
// 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();
|
||||
|
||||
// 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)
|
||||
return;
|
||||
#endif
|
||||
|
@ -47,7 +47,7 @@ void exit_module_gui();
|
||||
int get_screen_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_feedback();
|
||||
|
@ -42,7 +42,7 @@ public:
|
||||
Observers() { }
|
||||
|
||||
~Observers() {
|
||||
disposeAllObservers();
|
||||
ASSERT(m_observers.empty());
|
||||
}
|
||||
|
||||
// Adds the observer in the collection. The observer is owned by the
|
||||
@ -60,15 +60,6 @@ public:
|
||||
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)()) {
|
||||
for (iterator
|
||||
it = this->begin(),
|
||||
|
@ -26,8 +26,11 @@
|
||||
#include "tools/point_shape.h"
|
||||
#include "tools/tool.h"
|
||||
#include "tools/tool_box.h"
|
||||
#include "ui/manager.h"
|
||||
#include "ui_context.h"
|
||||
#include "widgets/color_bar.h"
|
||||
#include "widgets/main_window.h"
|
||||
#include "widgets/workspace.h"
|
||||
|
||||
#include <allegro/color.h>
|
||||
#include <string>
|
||||
@ -113,6 +116,11 @@ public:
|
||||
virtual void setOnionskinOpacityStep(int step) OVERRIDE;
|
||||
|
||||
private:
|
||||
void redrawDocumentViews() {
|
||||
// TODO Redraw only document's views
|
||||
ui::Manager::getDefault()->invalidate();
|
||||
}
|
||||
|
||||
TiledMode m_tiledMode;
|
||||
bool m_use_onionskin;
|
||||
int m_prev_frames_onionskin;
|
||||
@ -237,16 +245,19 @@ void UIDocumentSettingsImpl::setSnapToGrid(bool state)
|
||||
void UIDocumentSettingsImpl::setGridVisible(bool state)
|
||||
{
|
||||
m_gridVisible = state;
|
||||
redrawDocumentViews();
|
||||
}
|
||||
|
||||
void UIDocumentSettingsImpl::setGridBounds(const Rect& rect)
|
||||
{
|
||||
m_gridBounds = rect;
|
||||
redrawDocumentViews();
|
||||
}
|
||||
|
||||
void UIDocumentSettingsImpl::setGridColor(const app::Color& color)
|
||||
{
|
||||
m_gridColor = color;
|
||||
redrawDocumentViews();
|
||||
}
|
||||
|
||||
void UIDocumentSettingsImpl::snapToGrid(gfx::Point& point, SnapBehavior snapBehavior) const
|
||||
@ -279,11 +290,13 @@ app::Color UIDocumentSettingsImpl::getPixelGridColor()
|
||||
void UIDocumentSettingsImpl::setPixelGridVisible(bool state)
|
||||
{
|
||||
m_pixelGridVisible = state;
|
||||
redrawDocumentViews();
|
||||
}
|
||||
|
||||
void UIDocumentSettingsImpl::setPixelGridColor(const app::Color& color)
|
||||
{
|
||||
m_pixelGridColor = color;
|
||||
redrawDocumentViews();
|
||||
}
|
||||
|
||||
bool UIDocumentSettingsImpl::getUseOnionskin()
|
||||
|
@ -324,6 +324,7 @@ SkinTheme::SkinTheme()
|
||||
color_mapping["filelist_selected_row_text"] = ThemeColor::FileListSelectedRowText;
|
||||
color_mapping["filelist_selected_row_face"] = ThemeColor::FileListSelectedRowFace;
|
||||
color_mapping["filelist_disabled_row_text"] = ThemeColor::FileListDisabledRowText;
|
||||
color_mapping["workspace"] = ThemeColor::Workspace;
|
||||
|
||||
reload_skin();
|
||||
}
|
||||
|
@ -95,6 +95,7 @@ namespace ThemeColor {
|
||||
FileListSelectedRowText,
|
||||
FileListSelectedRowFace,
|
||||
FileListDisabledRowText,
|
||||
Workspace,
|
||||
MaxColors
|
||||
};
|
||||
}
|
||||
|
@ -21,7 +21,6 @@
|
||||
|
||||
#include "filters/tiled_mode.h"
|
||||
#include "gfx/point.h"
|
||||
#include "gfx/rect.h"
|
||||
#include "tools/trace_policy.h"
|
||||
|
||||
class Context;
|
||||
@ -34,6 +33,8 @@ class Mask;
|
||||
class Pen;
|
||||
class Sprite;
|
||||
|
||||
namespace gfx { class Region; }
|
||||
|
||||
namespace tools {
|
||||
|
||||
class Controller;
|
||||
@ -166,8 +167,12 @@ public:
|
||||
// Converts a coordinate in the screen to the sprite.
|
||||
virtual gfx::Point screenToSprite(const gfx::Point& screenPoint) = 0;
|
||||
|
||||
// Redraws in the screen the specified are of sprite.
|
||||
virtual void updateArea(const gfx::Rect& dirty_area) = 0;
|
||||
// This region is modified by the ToolLoopManager so then you know
|
||||
// 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;
|
||||
|
||||
|
@ -21,7 +21,9 @@
|
||||
#include "tools/tool_loop_manager.h"
|
||||
|
||||
#include "context.h"
|
||||
#include "gfx/region.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "settings/document_settings.h"
|
||||
#include "tools/controller.h"
|
||||
#include "tools/ink.h"
|
||||
@ -141,7 +143,7 @@ void ToolLoopManager::movement(const Pointer& pointer)
|
||||
|
||||
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;
|
||||
if (!last_step)
|
||||
@ -179,21 +181,17 @@ void ToolLoopManager::doLoopStep(bool last_step)
|
||||
else
|
||||
m_toolLoop->getIntertwine()->fillPoints(m_toolLoop, points_to_interwine);
|
||||
|
||||
// Calculat the area to be updated in the screen/editor/sprite
|
||||
Rect dirty_area;
|
||||
// Calculate the area to be updated in all document observers.
|
||||
Region& dirty_area = m_toolLoop->getDirtyArea();
|
||||
calculateDirtyArea(m_toolLoop, points_to_interwine, dirty_area);
|
||||
|
||||
Rect new_dirty_area;
|
||||
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;
|
||||
}
|
||||
else {
|
||||
new_dirty_area = dirty_area;
|
||||
}
|
||||
|
||||
if (!new_dirty_area.isEmpty())
|
||||
m_toolLoop->updateArea(new_dirty_area);
|
||||
if (!dirty_area.isEmpty())
|
||||
m_toolLoop->updateDirtyArea();
|
||||
}
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
||||
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) {
|
||||
Point minpt, maxpt;
|
||||
calculateMinMax(points, minpt, maxpt);
|
||||
@ -221,10 +221,54 @@ void ToolLoopManager::calculateDirtyArea(ToolLoop* loop, const Points& points, R
|
||||
Rect r1, r2;
|
||||
loop->getPointShape()->getModifiedArea(loop, minpt.x, minpt.y, r1);
|
||||
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
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
dirty_area = Rect();
|
||||
}
|
||||
|
||||
void ToolLoopManager::calculateMinMax(const Points& points, Point& minpt, Point& maxpt)
|
||||
|
@ -22,7 +22,8 @@
|
||||
#include <vector>
|
||||
|
||||
#include "gfx/point.h"
|
||||
#include "gfx/rect.h"
|
||||
|
||||
namespace gfx { class Region; }
|
||||
|
||||
namespace tools {
|
||||
|
||||
@ -99,7 +100,7 @@ private:
|
||||
|
||||
static void calculateDirtyArea(ToolLoop* loop,
|
||||
const Points& points,
|
||||
gfx::Rect& dirty_area);
|
||||
gfx::Region& dirty_area);
|
||||
|
||||
static void calculateMinMax(const Points& points,
|
||||
gfx::Point& minpt,
|
||||
|
@ -13,15 +13,14 @@
|
||||
|
||||
struct BITMAP;
|
||||
|
||||
#define JI_SCREEN_W ui::ji_screen_w
|
||||
#define JI_SCREEN_H ui::ji_screen_h
|
||||
|
||||
namespace she { class Display; }
|
||||
|
||||
namespace ui {
|
||||
|
||||
/***********************************************************************/
|
||||
/* screen related */
|
||||
|
||||
#define JI_SCREEN_W ji_screen_w
|
||||
#define JI_SCREEN_H ji_screen_h
|
||||
// Screen related
|
||||
|
||||
extern struct BITMAP* ji_screen;
|
||||
extern int ji_screen_w;
|
||||
@ -33,13 +32,11 @@ namespace ui {
|
||||
|
||||
void SetDisplay(she::Display* display);
|
||||
|
||||
/***********************************************************************/
|
||||
/* timer related */
|
||||
// Timer related
|
||||
|
||||
extern int volatile ji_clock; /* in milliseconds */
|
||||
|
||||
/***********************************************************************/
|
||||
/* mouse related */
|
||||
// Mouse related
|
||||
|
||||
// Updates the position of the mouse cursor overlay depending on the
|
||||
// current mouse position.
|
||||
|
@ -28,35 +28,94 @@
|
||||
#include "ui_context.h"
|
||||
#include "undo/undo_history.h"
|
||||
#include "widgets/color_bar.h"
|
||||
#include "widgets/document_view.h"
|
||||
#include "widgets/editor/editor.h"
|
||||
#include "widgets/main_window.h"
|
||||
#include "widgets/mini_editor.h"
|
||||
#include "widgets/tabs.h"
|
||||
#include "widgets/workspace.h"
|
||||
|
||||
#include <allegro/file.h>
|
||||
#include <allegro/system.h>
|
||||
|
||||
UIContext* UIContext::m_instance = NULL;
|
||||
|
||||
using namespace widgets;
|
||||
|
||||
UIContext::UIContext()
|
||||
: Context(new UISettingsImpl)
|
||||
{
|
||||
ASSERT(m_instance == NULL);
|
||||
m_instance = this;
|
||||
m_activeView = NULL;
|
||||
}
|
||||
|
||||
UIContext::~UIContext()
|
||||
{
|
||||
// No views at this point.
|
||||
ASSERT(m_allViews.empty());
|
||||
ASSERT(m_activeView == NULL);
|
||||
|
||||
ASSERT(m_instance == this);
|
||||
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)
|
||||
{
|
||||
// base method
|
||||
Context::onAddDocument(document);
|
||||
|
||||
// add the tab for this sprite
|
||||
App::instance()->getMainWindow()->getTabsBar()
|
||||
->addTab(get_filename(document->getFilename()), document);
|
||||
// Add a new view for this document
|
||||
DocumentView* view = new DocumentView(document, DocumentView::Normal);
|
||||
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
|
||||
app_rebuild_documents_tabs();
|
||||
@ -64,25 +123,48 @@ void UIContext::onAddDocument(Document* document)
|
||||
|
||||
void UIContext::onRemoveDocument(Document* document)
|
||||
{
|
||||
// base method
|
||||
Context::onRemoveDocument(document);
|
||||
|
||||
// Remove this document from tabs
|
||||
App::instance()->getMainWindow()->getTabsBar()->removeTab(document);
|
||||
// Remove all views of this 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
|
||||
app_rebuild_documents_tabs();
|
||||
|
||||
// Select other documents in the editors where are this sprite
|
||||
editors_hide_document(document);
|
||||
}
|
||||
|
||||
void UIContext::onSetActiveDocument(Document* document)
|
||||
{
|
||||
Context::onSetActiveDocument(document);
|
||||
|
||||
// Select the document in the tabs.
|
||||
App::instance()->getMainWindow()->getTabsBar()->selectTab(document);
|
||||
if (!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.
|
||||
ColorBar::instance()->setPixelFormat(app_get_current_pixel_format());
|
||||
|
@ -21,6 +21,11 @@
|
||||
|
||||
#include "context.h"
|
||||
|
||||
class Editor;
|
||||
namespace widgets { class DocumentView; }
|
||||
|
||||
typedef std::vector<widgets::DocumentView*> DocumentViews;
|
||||
|
||||
class UIContext : public Context
|
||||
{
|
||||
public:
|
||||
@ -31,14 +36,29 @@ public:
|
||||
|
||||
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:
|
||||
virtual void onAddDocument(Document* document);
|
||||
virtual void onRemoveDocument(Document* document);
|
||||
virtual void onSetActiveDocument(Document* document);
|
||||
|
||||
private:
|
||||
static UIContext* m_instance;
|
||||
DocumentViews m_allViews;
|
||||
widgets::DocumentView* m_activeView;
|
||||
|
||||
static UIContext* m_instance;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -167,6 +167,8 @@ void util::clipboard::copy_image(Image* image, Palette* pal, const gfx::Point& p
|
||||
void util::clipboard::paste()
|
||||
{
|
||||
Editor* editor = current_editor;
|
||||
if (editor == NULL)
|
||||
return;
|
||||
|
||||
#ifdef ALLEGRO_WINDOWS
|
||||
// Get the image from the clipboard.
|
||||
|
170
src/widgets/document_view.cpp
Normal file
170
src/widgets/document_view.cpp
Normal 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());
|
||||
}
|
73
src/widgets/document_view.h
Normal file
73
src/widgets/document_view.h
Normal 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
|
@ -152,20 +152,20 @@ static void on_palette_change_update_cursor_color()
|
||||
|
||||
static void on_pen_size_before_change()
|
||||
{
|
||||
ASSERT(current_editor != NULL);
|
||||
|
||||
pen_size_thick = current_editor->getCursorThick();
|
||||
if (pen_size_thick)
|
||||
current_editor->hideDrawingCursor();
|
||||
if (current_editor != NULL) {
|
||||
pen_size_thick = current_editor->getCursorThick();
|
||||
if (pen_size_thick)
|
||||
current_editor->hideDrawingCursor();
|
||||
}
|
||||
}
|
||||
|
||||
static void on_pen_size_after_change()
|
||||
{
|
||||
ASSERT(current_editor != NULL);
|
||||
|
||||
// Show drawing cursor
|
||||
if (current_editor->getSprite() && pen_size_thick > 0)
|
||||
current_editor->showDrawingCursor();
|
||||
if (current_editor != NULL) {
|
||||
// Show drawing cursor
|
||||
if (current_editor->getSprite() && pen_size_thick > 0)
|
||||
current_editor->showDrawingCursor();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
uint32_t new_mask_color;
|
||||
Pen* pen = editor_get_current_pen();
|
||||
int half = pen->get_size()/2;
|
||||
|
||||
// Create the extra cel to show the pen preview
|
||||
m_document->prepareExtraCel(x-pen->get_size()/2,
|
||||
y-pen->get_size()/2,
|
||||
m_document->prepareExtraCel(x-half,
|
||||
y-half,
|
||||
pen->get_size(), pen->get_size(),
|
||||
tool_settings->getOpacity());
|
||||
|
||||
@ -304,14 +305,15 @@ void Editor::editor_draw_cursor(int x, int y, bool refresh)
|
||||
Image* extraImage = m_document->getExtraCelImage();
|
||||
if (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) {
|
||||
editors_draw_sprite(m_sprite,
|
||||
x-pen->get_size()/2,
|
||||
y-pen->get_size()/2,
|
||||
x+pen->get_size()/2,
|
||||
y+pen->get_size()/2);
|
||||
m_document->notifySpritePixelsModified
|
||||
(m_sprite,
|
||||
gfx::Region(gfx::Rect(x-half,
|
||||
y-half,
|
||||
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()) {
|
||||
Pen* pen = editor_get_current_pen();
|
||||
editors_draw_sprite(m_sprite,
|
||||
std::min(new_x, old_x)-pen->get_size()/2,
|
||||
std::min(new_y, old_y)-pen->get_size()/2,
|
||||
std::max(new_x, old_x)+pen->get_size()/2,
|
||||
std::max(new_y, old_y)+pen->get_size()/2);
|
||||
int half = pen->get_size()/2;
|
||||
gfx::Rect rc1(old_x-half, old_y-half, pen->get_size(), pen->get_size());
|
||||
gfx::Rect rc2(new_x-half, new_y-half, pen->get_size(), pen->get_size());
|
||||
m_document->notifySpritePixelsModified
|
||||
(m_sprite, gfx::Region(rc1.createUnion(rc2)));
|
||||
}
|
||||
|
||||
/* save area and draw the cursor */
|
||||
@ -423,11 +425,12 @@ void Editor::editor_clean_cursor(bool refresh)
|
||||
0); // Opacity = 0
|
||||
|
||||
if (refresh) {
|
||||
editors_draw_sprite(m_sprite,
|
||||
x-pen->get_size()/2,
|
||||
y-pen->get_size()/2,
|
||||
x+pen->get_size()/2,
|
||||
y+pen->get_size()/2);
|
||||
m_document->notifySpritePixelsModified
|
||||
(m_sprite,
|
||||
gfx::Region(gfx::Rect(x-pen->get_size()/2,
|
||||
y-pen->get_size()/2,
|
||||
pen->get_size(),
|
||||
pen->get_size())));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include "commands/params.h"
|
||||
#include "document_wrappers.h"
|
||||
#include "ini_file.h"
|
||||
#include "modules/editors.h"
|
||||
#include "modules/gfx.h"
|
||||
#include "modules/gui.h"
|
||||
#include "modules/palettes.h"
|
||||
@ -123,20 +122,20 @@ private:
|
||||
Editor* m_editor;
|
||||
};
|
||||
|
||||
Editor::Editor()
|
||||
Editor::Editor(Document* document)
|
||||
: Widget(editor_type())
|
||||
, m_state(new StandbyState())
|
||||
, m_decorator(NULL)
|
||||
, m_document(document)
|
||||
, m_sprite(m_document->getSprite())
|
||||
, m_zoom(0)
|
||||
, m_mask_timer(100, this)
|
||||
, m_customizationDelegate(NULL)
|
||||
, m_docView(NULL)
|
||||
{
|
||||
// Add the first state into the history.
|
||||
m_statesHistory.push(m_state);
|
||||
|
||||
m_document = NULL;
|
||||
m_sprite = NULL;
|
||||
m_zoom = 0;
|
||||
|
||||
m_cursor_thick = 0;
|
||||
m_cursor_screen_x = 0;
|
||||
m_cursor_screen_y = 0;
|
||||
@ -163,7 +162,6 @@ Editor::~Editor()
|
||||
setCustomizationDelegate(NULL);
|
||||
|
||||
m_mask_timer.stop();
|
||||
remove_editor(this);
|
||||
|
||||
// Remove this editor as observer of CurrentToolChange signal.
|
||||
App::instance()->CurrentToolChange.disconnect(m_currentToolChangeSlot);
|
||||
@ -238,61 +236,13 @@ void Editor::backToPreviousState()
|
||||
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
|
||||
View* view = View::getView(this);
|
||||
Rect vp = view->getViewportBounds();
|
||||
|
||||
// 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);
|
||||
Rect vp = view->getViewportBounds();
|
||||
|
||||
preferred.virgin = false;
|
||||
preferred.scroll_x = -vp.w/2 + (m_sprite->getWidth()/2);
|
||||
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);
|
||||
setEditorScroll(m_offset_x - vp.w/2 + (m_sprite->getWidth()/2),
|
||||
m_offset_y - vp.h/2 + (m_sprite->getHeight()/2), false);
|
||||
}
|
||||
|
||||
// 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));
|
||||
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) {
|
||||
// Move screen with blits
|
||||
scrollRegion(region,
|
||||
@ -344,7 +283,7 @@ void Editor::updateEditor()
|
||||
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);
|
||||
Rect vp = view->getViewportBounds();
|
||||
@ -356,12 +295,12 @@ void Editor::drawSprite(int x1, int y1, int x2, int y2)
|
||||
|
||||
// Output information
|
||||
|
||||
source_x = x1 << m_zoom;
|
||||
source_y = y1 << m_zoom;
|
||||
source_x = rc.x << m_zoom;
|
||||
source_y = rc.y << m_zoom;
|
||||
dest_x = vp.x - scroll.x + m_offset_x + source_x;
|
||||
dest_y = vp.y - scroll.y + m_offset_y + source_y;
|
||||
width = (x2 - x1 + 1) << m_zoom;
|
||||
height = (y2 - y1 + 1) << m_zoom;
|
||||
width = rc.w << m_zoom;
|
||||
height = rc.h << m_zoom;
|
||||
|
||||
// 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;
|
||||
getDrawableRegion(region, kCutTopWindows);
|
||||
@ -499,12 +438,17 @@ void Editor::drawSpriteSafe(int x1, int y1, int x2, int y2)
|
||||
int cx1, cy1, cx2, cy2;
|
||||
get_clip_rect(ji_screen, &cx1, &cy1, &cx2, &cy2);
|
||||
|
||||
for (Region::const_iterator it=region.begin(), end=region.end();
|
||||
it != end; ++it) {
|
||||
for (Region::const_iterator
|
||||
it=region.begin(), end=region.end(); it != end; ++it) {
|
||||
const Rect& rc = *it;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -922,7 +866,7 @@ bool Editor::onProcessMessage(Message* msg)
|
||||
x1-1, y1-1, x2+1, y2+2, theme->getColor(ThemeColor::EditorFace));
|
||||
|
||||
// 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
|
||||
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:
|
||||
if (msg->timer.timer == &m_mask_timer) {
|
||||
if (m_sprite) {
|
||||
if (isVisible() && m_sprite) {
|
||||
drawMaskSafe();
|
||||
|
||||
// Set offset to make selection-movement effect
|
||||
@ -965,6 +909,9 @@ bool Editor::onProcessMessage(Message* msg)
|
||||
else
|
||||
m_offset_count = 0;
|
||||
}
|
||||
else if (m_mask_timer.isRunning()) {
|
||||
m_mask_timer.stop();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "base/compiler_specific.h"
|
||||
#include "base/signal.h"
|
||||
#include "document.h"
|
||||
#include "gfx/rect.h"
|
||||
#include "ui/base.h"
|
||||
#include "ui/timer.h"
|
||||
#include "ui/widget.h"
|
||||
@ -38,20 +39,20 @@ class EditorCustomizationDelegate;
|
||||
class PixelsMovement;
|
||||
class Sprite;
|
||||
|
||||
namespace ui {
|
||||
class View;
|
||||
}
|
||||
|
||||
namespace tools {
|
||||
class Tool;
|
||||
}
|
||||
namespace gfx { class Region; }
|
||||
namespace tools { class Tool; }
|
||||
namespace ui { class View; }
|
||||
namespace widgets { class DocumentView; }
|
||||
|
||||
class Editor : public ui::Widget
|
||||
{
|
||||
public:
|
||||
Editor();
|
||||
Editor(Document* document);
|
||||
~Editor();
|
||||
|
||||
widgets::DocumentView* getDocumentView() { return m_docView; }
|
||||
void setDocumentView(widgets::DocumentView* docView) { m_docView = docView; }
|
||||
|
||||
// Returns the current state.
|
||||
EditorStatePtr getState() { return m_state; }
|
||||
|
||||
@ -67,7 +68,6 @@ public:
|
||||
void setDecorator(EditorDecorator* decorator) { m_decorator = decorator; }
|
||||
|
||||
Document* getDocument() { return m_document; }
|
||||
void setDocument(Document* document);
|
||||
|
||||
Sprite* getSprite() { return m_sprite; }
|
||||
|
||||
@ -80,19 +80,14 @@ public:
|
||||
void setOffsetX(int x) { m_offset_x = x; }
|
||||
void setOffsetY(int y) { m_offset_y = y; }
|
||||
|
||||
void setDefaultScroll();
|
||||
void setEditorScroll(int x, int y, int use_refresh_region);
|
||||
|
||||
// Updates the Editor's view.
|
||||
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.
|
||||
// For each rectangle calls Editor::drawSprite.
|
||||
void drawSpriteSafe(int x1, int y1, int x2, int y2);
|
||||
void drawSpriteClipped(const gfx::Region& updateRegion);
|
||||
|
||||
void drawMask();
|
||||
void drawMaskSafe();
|
||||
@ -158,12 +153,6 @@ protected:
|
||||
void onCurrentToolChange();
|
||||
void onFgColorChange();
|
||||
|
||||
// Returns true if this editor should change the preferred document
|
||||
// settings.
|
||||
virtual bool changePreferredSettings() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
void setStateInternal(const EditorStatePtr& newState);
|
||||
void editor_update_quicktool();
|
||||
@ -180,6 +169,11 @@ private:
|
||||
int sprite_x, int sprite_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).
|
||||
EditorStatesHistory m_statesHistory;
|
||||
|
||||
@ -225,6 +219,10 @@ private:
|
||||
|
||||
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();
|
||||
|
@ -32,9 +32,6 @@ public:
|
||||
|
||||
// Called when the scroll or zoom of the editor changes.
|
||||
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
|
||||
|
@ -46,8 +46,3 @@ void EditorObservers::notifyScrollChanged(Editor* editor)
|
||||
{
|
||||
m_observers.notifyObservers(&EditorObserver::scrollChanged, editor);
|
||||
}
|
||||
|
||||
void EditorObservers::notifyDocumentChanged(Editor* editor)
|
||||
{
|
||||
m_observers.notifyObservers(&EditorObserver::documentChanged, editor);
|
||||
}
|
||||
|
@ -34,7 +34,6 @@ public:
|
||||
|
||||
void notifyStateChanged(Editor* editor);
|
||||
void notifyScrollChanged(Editor* editor);
|
||||
void notifyDocumentChanged(Editor* editor);
|
||||
|
||||
private:
|
||||
Observers<EditorObserver> m_observers;
|
||||
|
@ -22,7 +22,6 @@
|
||||
|
||||
#include "app.h"
|
||||
#include "app/color.h"
|
||||
#include "modules/editors.h"
|
||||
#include "modules/gui.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/sprite.h"
|
||||
|
@ -27,7 +27,6 @@
|
||||
#include "commands/command.h"
|
||||
#include "commands/commands.h"
|
||||
#include "gfx/rect.h"
|
||||
#include "modules/editors.h"
|
||||
#include "modules/gui.h"
|
||||
#include "raster/algorithm/flip_image.h"
|
||||
#include "raster/mask.h"
|
||||
@ -258,18 +257,8 @@ bool MovingPixelsState::onMouseMove(Editor* editor, Message* msg)
|
||||
transfHandles->invalidateHandles(editor, m_pixelsMovement->getTransformation());
|
||||
|
||||
// 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();
|
||||
return true;
|
||||
}
|
||||
@ -413,10 +402,9 @@ void MovingPixelsState::onChangeTransparentColor(const app::Color& color)
|
||||
|
||||
void MovingPixelsState::setTransparentColor(const app::Color& color)
|
||||
{
|
||||
ASSERT(current_editor != NULL);
|
||||
ASSERT(m_pixelsMovement != NULL);
|
||||
|
||||
Sprite* sprite = current_editor->getSprite();
|
||||
Sprite* sprite = m_currentEditor->getSprite();
|
||||
ASSERT(sprite != NULL);
|
||||
|
||||
PixelFormat format = sprite->getPixelFormat();
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include "app.h"
|
||||
#include "document.h"
|
||||
#include "gfx/region.h"
|
||||
#include "la/vector2d.h"
|
||||
#include "modules/gui.h"
|
||||
#include "raster/algorithm/flip_image.h"
|
||||
@ -97,9 +98,8 @@ void PixelsMovement::flipImage(raster::algorithm::FlipType flipType)
|
||||
|
||||
documentWriter->setMask(m_currentMask);
|
||||
documentWriter->generateMaskBoundaries(m_currentMask);
|
||||
update_screen_for_document(documentWriter);
|
||||
}
|
||||
|
||||
update_screen_for_document(m_documentReader);
|
||||
}
|
||||
|
||||
void PixelsMovement::cutMask()
|
||||
@ -119,9 +119,8 @@ void PixelsMovement::copyMask()
|
||||
{
|
||||
DocumentWriter documentWriter(m_documentReader);
|
||||
documentWriter->generateMaskBoundaries(&emptyMask);
|
||||
update_screen_for_document(documentWriter);
|
||||
}
|
||||
|
||||
update_screen_for_document(m_documentReader);
|
||||
}
|
||||
|
||||
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->generateMaskBoundaries(&emptyMask);
|
||||
update_screen_for_document(documentWriter);
|
||||
}
|
||||
|
||||
update_screen_for_document(m_documentReader);
|
||||
}
|
||||
|
||||
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->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;
|
||||
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(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)
|
||||
@ -500,9 +503,8 @@ void PixelsMovement::dropImageTemporarily()
|
||||
}
|
||||
|
||||
documentWriter->generateMaskBoundaries(m_currentMask);
|
||||
update_screen_for_document(documentWriter);
|
||||
}
|
||||
|
||||
update_screen_for_document(m_documentReader);
|
||||
}
|
||||
|
||||
void PixelsMovement::dropImage()
|
||||
@ -567,9 +569,8 @@ void PixelsMovement::setMaskColor(uint32_t mask_color)
|
||||
|
||||
extraImage->mask_color = mask_color;
|
||||
redrawExtraImage(documentWriter);
|
||||
update_screen_for_document(documentWriter);
|
||||
}
|
||||
|
||||
update_screen_for_document(m_documentReader);
|
||||
}
|
||||
|
||||
|
||||
|
@ -61,9 +61,8 @@ public:
|
||||
void maskImage(const Image* image, int x, int y);
|
||||
|
||||
// Moves the image to the new position (relative to the start
|
||||
// position given in the ctor). Returns the rectangle that should be
|
||||
// redrawn.
|
||||
gfx::Rect moveImage(int x, int y, MoveModifier moveModifier);
|
||||
// position given in the ctor).
|
||||
void moveImage(int x, int y, MoveModifier moveModifier);
|
||||
|
||||
// Returns a copy of the current image being dragged with the
|
||||
// current transformation.
|
||||
|
@ -22,7 +22,6 @@
|
||||
|
||||
#include "app.h"
|
||||
#include "gfx/rect.h"
|
||||
#include "modules/editors.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "ui/message.h"
|
||||
#include "ui/system.h"
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include "commands/params.h"
|
||||
#include "gfx/rect.h"
|
||||
#include "ini_file.h"
|
||||
#include "modules/editors.h"
|
||||
#include "raster/layer.h"
|
||||
#include "raster/mask.h"
|
||||
#include "raster/sprite.h"
|
||||
@ -142,13 +141,10 @@ bool StandbyState::onMouseDown(Editor* editor, Message* msg)
|
||||
tools::Tool* current_tool = editor->getCurrentEditorTool();
|
||||
tools::Ink* clickedInk = current_tool->getInk(msg->mouse.right ? 1: 0);
|
||||
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();
|
||||
context->setActiveDocument(document);
|
||||
|
||||
// When an editor is clicked the current view is changed.
|
||||
context->setActiveView(editor->getDocumentView());
|
||||
|
||||
// Start scroll loop
|
||||
if (checkForScroll(editor, msg))
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include "app/color.h"
|
||||
#include "app/color_utils.h"
|
||||
#include "context.h"
|
||||
#include "modules/editors.h"
|
||||
#include "raster/cel.h"
|
||||
#include "raster/layer.h"
|
||||
#include "raster/mask.h"
|
||||
@ -75,6 +74,7 @@ class ToolLoopImpl : public tools::ToolLoop
|
||||
int m_secondary_color;
|
||||
UndoTransaction m_undoTransaction;
|
||||
ExpandCelCanvas m_expandCelCanvas;
|
||||
gfx::Region m_dirtyArea;
|
||||
|
||||
public:
|
||||
ToolLoopImpl(Editor* editor,
|
||||
@ -225,16 +225,14 @@ public:
|
||||
return spritePoint;
|
||||
}
|
||||
|
||||
void updateArea(const gfx::Rect& dirty_area) OVERRIDE
|
||||
gfx::Region& getDirtyArea() OVERRIDE
|
||||
{
|
||||
int x1 = dirty_area.x-m_offset.x;
|
||||
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;
|
||||
return m_dirtyArea;
|
||||
}
|
||||
|
||||
acquire_bitmap(ji_screen);
|
||||
editors_draw_sprite_tiled(m_sprite, x1, y1, x2, y2);
|
||||
release_bitmap(ji_screen);
|
||||
void updateDirtyArea() OVERRIDE
|
||||
{
|
||||
m_document->notifySpritePixelsModified(m_sprite, m_dirtyArea);
|
||||
}
|
||||
|
||||
void updateStatusBar(const char* text) OVERRIDE
|
||||
|
@ -30,21 +30,18 @@
|
||||
#include "ui/view.h"
|
||||
#include "ui_context.h"
|
||||
#include "widgets/color_bar.h"
|
||||
#include "widgets/document_view.h"
|
||||
#include "widgets/editor/editor.h"
|
||||
#include "widgets/editor/editor_view.h"
|
||||
#include "widgets/main_menu_bar.h"
|
||||
#include "widgets/mini_editor.h"
|
||||
#include "widgets/status_bar.h"
|
||||
#include "widgets/tabs.h"
|
||||
#include "widgets/toolbar.h"
|
||||
#include "widgets/workspace.h"
|
||||
|
||||
using namespace ui;
|
||||
|
||||
class AppTabsDelegate : public TabsDelegate
|
||||
{
|
||||
public:
|
||||
void clickTab(Tabs* tabs, void* data, int button);
|
||||
void mouseOverTab(Tabs* tabs, void* data);
|
||||
};
|
||||
using namespace widgets;
|
||||
|
||||
MainWindow::MainWindow()
|
||||
: Window(true, NULL)
|
||||
@ -59,21 +56,20 @@ MainWindow::MainWindow()
|
||||
Widget* mainBox = app::load_widget<Widget>("main_window.xml", "main_box");
|
||||
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_colorbar = findChild("colorbar");
|
||||
Widget* box_toolbar = findChild("toolbar");
|
||||
Widget* box_statusbar = findChild("statusbar");
|
||||
Widget* box_tabsbar = findChild("tabsbar");
|
||||
Widget* box_workspace = findChild("workspace");
|
||||
|
||||
m_menuBar = new MainMenuBar();
|
||||
m_statusBar = new StatusBar();
|
||||
m_colorBar = new ColorBar(box_colorbar->getAlign());
|
||||
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");
|
||||
|
||||
// configure all widgets to expansives
|
||||
@ -82,45 +78,40 @@ MainWindow::MainWindow()
|
||||
m_colorBar->setExpansive(true);
|
||||
m_toolBar->setExpansive(true);
|
||||
m_tabsBar->setExpansive(true);
|
||||
m_workspace->setExpansive(true);
|
||||
|
||||
// Setup the menus
|
||||
m_menuBar->setMenu(AppMenus::instance()->getRootMenu());
|
||||
|
||||
/* start text of status bar */
|
||||
// Start text of status bar
|
||||
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_colorbar) box_colorbar->addChild(m_colorBar);
|
||||
if (box_toolbar) box_toolbar->addChild(m_toolBar);
|
||||
if (box_statusbar) box_statusbar->addChild(m_statusBar);
|
||||
if (box_tabsbar) box_tabsbar->addChild(m_tabsBar);
|
||||
if (box_workspace) box_workspace->addChild(m_workspace);
|
||||
|
||||
// Prepare the window
|
||||
remapWindow();
|
||||
|
||||
// Initialize editors.
|
||||
init_module_editors();
|
||||
|
||||
// Create the list of tabs
|
||||
app_rebuild_documents_tabs();
|
||||
AppMenus::instance()->rebuildRecentList();
|
||||
}
|
||||
|
||||
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
|
||||
// module should destroy it).
|
||||
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()
|
||||
@ -131,22 +122,6 @@ void MainWindow::reloadMenus()
|
||||
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)
|
||||
{
|
||||
// Check if we already are in the given mode.
|
||||
@ -180,47 +155,43 @@ void MainWindow::onSaveLayout(SaveLayoutEvent& ev)
|
||||
m_colorBarSplitter->setPosition(m_lastSplitterPos);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// AppTabsDelegate
|
||||
|
||||
void AppTabsDelegate::clickTab(Tabs* tabs, void* data, int button)
|
||||
void MainWindow::clickTab(Tabs* tabs, TabView* tabView, int button)
|
||||
{
|
||||
Document* document = reinterpret_cast<Document*>(data);
|
||||
if (!tabView)
|
||||
return;
|
||||
|
||||
// put as current sprite
|
||||
set_document_in_more_reliable_editor(document);
|
||||
DocumentView* docView = static_cast<DocumentView*>(tabView);
|
||||
Document* document = docView->getDocument();
|
||||
|
||||
if (document) {
|
||||
Context* context = UIContext::instance();
|
||||
context->updateFlags();
|
||||
UIContext* context = UIContext::instance();
|
||||
context->setActiveView(docView);
|
||||
context->updateFlags();
|
||||
|
||||
// right-button: popup-menu
|
||||
if (button & 2) {
|
||||
Menu* popup_menu = AppMenus::instance()->getDocumentTabPopupMenu();
|
||||
if (popup_menu != NULL) {
|
||||
popup_menu->showPopup(jmouse_x(0), jmouse_y(0));
|
||||
}
|
||||
// Right-button: popup-menu
|
||||
if (button & 2) {
|
||||
Menu* popup_menu = AppMenus::instance()->getDocumentTabPopupMenu();
|
||||
if (popup_menu != NULL) {
|
||||
popup_menu->showPopup(jmouse_x(0), jmouse_y(0));
|
||||
}
|
||||
// middle-button: close the sprite
|
||||
else if (button & 4) {
|
||||
Command* close_file_cmd =
|
||||
CommandsModule::instance()->getCommandByName(CommandId::CloseFile);
|
||||
}
|
||||
// Middle-button: close the sprite
|
||||
else if (button & 4) {
|
||||
Command* close_file_cmd =
|
||||
CommandsModule::instance()->getCommandByName(CommandId::CloseFile);
|
||||
|
||||
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
|
||||
Document* document = (Document*)data;
|
||||
|
||||
if (data) {
|
||||
StatusBar::instance()->setStatusText(250, "%s",
|
||||
static_cast<const char*>(document->getFilename()));
|
||||
// Note: tabView can be NULL
|
||||
if (tabView) {
|
||||
DocumentView* docView = static_cast<DocumentView*>(tabView);
|
||||
Document* document = docView->getDocument();
|
||||
m_statusBar->setStatusText(250, "%s", static_cast<const char*>(document->getFilename()));
|
||||
}
|
||||
else {
|
||||
StatusBar::instance()->clearText();
|
||||
m_statusBar->clearText();
|
||||
}
|
||||
}
|
||||
|
@ -20,18 +20,21 @@
|
||||
#define MAIN_WINDOW_H_INCLUDED
|
||||
|
||||
#include "ui/window.h"
|
||||
#include "widgets/tabs.h"
|
||||
|
||||
class AppTabsDelegate;
|
||||
class ColorBar;
|
||||
class MainMenuBar;
|
||||
class StatusBar;
|
||||
class Tabs;
|
||||
|
||||
namespace ui {
|
||||
class Splitter;
|
||||
namespace ui { class Splitter; }
|
||||
namespace widgets
|
||||
{
|
||||
class MiniEditorWindow;
|
||||
class Workspace;
|
||||
}
|
||||
|
||||
class MainWindow : public ui::Window
|
||||
, public TabsDelegate
|
||||
{
|
||||
public:
|
||||
MainWindow();
|
||||
@ -39,18 +42,22 @@ public:
|
||||
|
||||
MainMenuBar* getMenuBar() { return m_menuBar; }
|
||||
Tabs* getTabsBar() { return m_tabsBar; }
|
||||
widgets::Workspace* getWorkspace() { return m_workspace; }
|
||||
widgets::MiniEditorWindow* getMiniEditor() { return m_miniEditor; }
|
||||
|
||||
void reloadMenus();
|
||||
void createFirstEditor();
|
||||
|
||||
bool isAdvancedMode() const { return m_advancedMode; }
|
||||
void setAdvancedMode(bool advanced);
|
||||
|
||||
// TabsDelegate implementation.
|
||||
void clickTab(Tabs* tabs, TabView* tabView, int button);
|
||||
void mouseOverTab(Tabs* tabs, TabView* tabView);
|
||||
|
||||
protected:
|
||||
void onSaveLayout(ui::SaveLayoutEvent& ev) OVERRIDE;
|
||||
|
||||
private:
|
||||
AppTabsDelegate* m_tabsDelegate;
|
||||
MainMenuBar* m_menuBar; // the menu bar widget
|
||||
StatusBar* m_statusBar; // the status bar widget
|
||||
ColorBar* m_colorBar; // the color bar widget
|
||||
@ -59,6 +66,8 @@ private:
|
||||
Tabs* m_tabsBar; // The tabs bar widget
|
||||
double m_lastSplitterPos;
|
||||
bool m_advancedMode;
|
||||
widgets::Workspace* m_workspace; // The workspace (document's views)
|
||||
widgets::MiniEditorWindow* m_miniEditor;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
144
src/widgets/mini_editor.cpp
Normal file
144
src/widgets/mini_editor.cpp
Normal 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
50
src/widgets/mini_editor.h
Normal 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
|
@ -779,8 +779,8 @@ bool StatusBar::onProcessMessage(Message* msg)
|
||||
sprite->setCurrentLayer(layer);
|
||||
|
||||
// Flash the current layer
|
||||
ASSERT(current_editor != NULL); // Cannot be null when we have a current sprite
|
||||
current_editor->flashCurrentLayer();
|
||||
if (current_editor != NULL)
|
||||
current_editor->flashCurrentLayer();
|
||||
|
||||
// Redraw the status-bar
|
||||
invalidate();
|
||||
|
@ -122,10 +122,10 @@ Tabs::~Tabs()
|
||||
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->width = calcTabWidth(tab);
|
||||
Tab* tab = new Tab(tabView);
|
||||
calcTabWidth(tab);
|
||||
|
||||
m_list_of_tabs.push_back(tab);
|
||||
|
||||
@ -133,70 +133,66 @@ void Tabs::addTab(const char* text, void* data)
|
||||
setScrollX(m_scrollX);
|
||||
|
||||
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_selected == tab) m_selected = NULL;
|
||||
if (m_hot == tab) m_hot = NULL;
|
||||
if (m_selected == tab) m_selected = NULL;
|
||||
|
||||
TabsListIterator it =
|
||||
std::find(m_list_of_tabs.begin(), m_list_of_tabs.end(), tab);
|
||||
TabsListIterator it =
|
||||
std::find(m_list_of_tabs.begin(), m_list_of_tabs.end(), tab);
|
||||
|
||||
ASSERT(it != m_list_of_tabs.end() && "Removing a tab that is not part of the Tabs widget");
|
||||
ASSERT(it != m_list_of_tabs.end() && "Removing a tab that is not part of the Tabs widget");
|
||||
|
||||
it = m_list_of_tabs.erase(it);
|
||||
it = m_list_of_tabs.erase(it);
|
||||
|
||||
// Width of the removed tab
|
||||
if (m_removedTab) {
|
||||
delete m_removedTab;
|
||||
m_removedTab = NULL;
|
||||
}
|
||||
m_removedTab = tab;
|
||||
|
||||
// Next tab in the list
|
||||
if (it != m_list_of_tabs.end())
|
||||
m_nextTabOfTheRemovedOne = *it;
|
||||
else
|
||||
m_nextTabOfTheRemovedOne = NULL;
|
||||
|
||||
// Update scroll (in the same position if we can)
|
||||
setScrollX(m_scrollX);
|
||||
|
||||
startAni(ANI_REMOVING_TAB);
|
||||
// Width of the removed tab
|
||||
if (m_removedTab) {
|
||||
delete m_removedTab;
|
||||
m_removedTab = NULL;
|
||||
}
|
||||
m_removedTab = tab;
|
||||
|
||||
// Next tab in the list
|
||||
if (it != m_list_of_tabs.end())
|
||||
m_nextTabOfTheRemovedOne = *it;
|
||||
else
|
||||
m_nextTabOfTheRemovedOne = NULL;
|
||||
|
||||
// Update scroll (in the same position if we can)
|
||||
setScrollX(m_scrollX);
|
||||
|
||||
startAni(ANI_REMOVING_TAB);
|
||||
}
|
||||
|
||||
void Tabs::setTabText(const char* text, void* data)
|
||||
void Tabs::updateTabsText()
|
||||
{
|
||||
Tab* tab = getTabByData(data);
|
||||
if (tab) {
|
||||
TabsListIterator it, end = m_list_of_tabs.end();
|
||||
|
||||
for (it = m_list_of_tabs.begin(); it != end; ++it) {
|
||||
Tab* tab = *it;
|
||||
|
||||
// Change text of the tab
|
||||
tab->text = text;
|
||||
tab->width = calcTabWidth(tab);
|
||||
|
||||
// Make it visible (if it's the selected)
|
||||
if (m_selected == tab)
|
||||
makeTabVisible(tab);
|
||||
|
||||
invalidate();
|
||||
calcTabWidth(tab);
|
||||
}
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void Tabs::selectTab(void* data)
|
||||
void Tabs::selectTab(TabView* tabView)
|
||||
{
|
||||
Tab *tab = getTabByData(data);
|
||||
Tab *tab = getTabByView(tabView);
|
||||
if (tab != NULL)
|
||||
selectTabInternal(tab);
|
||||
}
|
||||
|
||||
void Tabs::selectNextTab()
|
||||
{
|
||||
TabsListIterator currentTabIt = getTabIteratorByData(m_selected->data);
|
||||
TabsListIterator currentTabIt = getTabIteratorByView(m_selected->view);
|
||||
TabsListIterator it = currentTabIt;
|
||||
if (it != m_list_of_tabs.end()) {
|
||||
// If we are at the end of the list, cycle to the first tab.
|
||||
@ -209,14 +205,14 @@ void Tabs::selectNextTab()
|
||||
if (it != currentTabIt) {
|
||||
selectTabInternal(*it);
|
||||
if (m_delegate)
|
||||
m_delegate->clickTab(this, m_selected->data, 1);
|
||||
m_delegate->clickTab(this, m_selected->view, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Tabs::selectPreviousTab()
|
||||
{
|
||||
TabsListIterator currentTabIt = getTabIteratorByData(m_selected->data);
|
||||
TabsListIterator currentTabIt = getTabIteratorByView(m_selected->view);
|
||||
TabsListIterator it = currentTabIt;
|
||||
if (it != m_list_of_tabs.end()) {
|
||||
// If we are at the beginning of the list, cycle to the last tab.
|
||||
@ -229,15 +225,15 @@ void Tabs::selectPreviousTab()
|
||||
if (it != currentTabIt) {
|
||||
selectTabInternal(*it);
|
||||
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)
|
||||
return m_selected->data;
|
||||
return m_selected->view;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
@ -359,7 +355,7 @@ bool Tabs::onProcessMessage(Message* msg)
|
||||
|
||||
if (m_selected && m_delegate)
|
||||
m_delegate->clickTab(this,
|
||||
m_selected->data,
|
||||
m_selected->view,
|
||||
msg->mouse.flags);
|
||||
}
|
||||
return true;
|
||||
@ -457,7 +453,7 @@ void Tabs::onSetText()
|
||||
|
||||
for (it = m_list_of_tabs.begin(); it != end; ++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
|
||||
}
|
||||
|
||||
Tabs::TabsListIterator Tabs::getTabIteratorByData(void* data)
|
||||
Tabs::TabsListIterator Tabs::getTabIteratorByView(TabView* tabView)
|
||||
{
|
||||
TabsListIterator it, end = m_list_of_tabs.end();
|
||||
|
||||
for (it = m_list_of_tabs.begin(); it != end; ++it) {
|
||||
if ((*it)->data == data)
|
||||
if ((*it)->view == tabView)
|
||||
break;
|
||||
}
|
||||
|
||||
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())
|
||||
return *it;
|
||||
else
|
||||
@ -656,7 +652,7 @@ void Tabs::calculateHot()
|
||||
m_hot = hot;
|
||||
|
||||
if (m_delegate)
|
||||
m_delegate->mouseOverTab(this, m_hot ? m_hot->data: NULL);
|
||||
m_delegate->mouseOverTab(this, m_hot ? m_hot->view: NULL);
|
||||
|
||||
invalidate();
|
||||
}
|
||||
@ -665,15 +661,18 @@ void Tabs::calculateHot()
|
||||
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();
|
||||
#ifdef CLOSE_BUTTON_IN_EACH_TAB
|
||||
SkinTheme* theme = static_cast<SkinTheme*>(this->theme);
|
||||
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
|
||||
return (border + text_length(getFont(), tab->text.c_str()) + border);
|
||||
tab->width = (border + text_length(getFont(), tab->text.c_str()) + border);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,17 @@
|
||||
|
||||
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.
|
||||
class TabsDelegate
|
||||
{
|
||||
@ -37,29 +48,22 @@ public:
|
||||
// button & 1 => left click
|
||||
// button & 2 => right 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
|
||||
// mouse just leave all tabs)
|
||||
virtual void mouseOverTab(Tabs* tabs, void* data) = 0;
|
||||
virtual void mouseOverTab(Tabs* tabs, TabView* tabView) = 0;
|
||||
};
|
||||
|
||||
// Tabs control.
|
||||
//
|
||||
// Used to show opened files/sprites.
|
||||
// Tabs control. Used to show opened documents.
|
||||
class Tabs : public ui::Widget
|
||||
{
|
||||
struct Tab
|
||||
{
|
||||
std::string text; // Label in the tab
|
||||
void* data; // Opaque pointer to user data
|
||||
int width; // Width of the tab
|
||||
struct Tab {
|
||||
TabView* view;
|
||||
std::string text;
|
||||
int width;
|
||||
|
||||
Tab(const char* text, void* data)
|
||||
{
|
||||
this->text = text;
|
||||
this->data = data;
|
||||
this->width = 0;
|
||||
Tab(TabView* view) : view(view), width(0) {
|
||||
}
|
||||
};
|
||||
|
||||
@ -76,15 +80,14 @@ public:
|
||||
Tabs(TabsDelegate* delegate);
|
||||
~Tabs();
|
||||
|
||||
void addTab(const char* text, void* data);
|
||||
void removeTab(void* data);
|
||||
void addTab(TabView* tabView);
|
||||
void removeTab(TabView* tabView);
|
||||
void updateTabsText();
|
||||
|
||||
void setTabText(const char* text, void* data);
|
||||
|
||||
void selectTab(void* data);
|
||||
void selectTab(TabView* tabView);
|
||||
void selectNextTab();
|
||||
void selectPreviousTab();
|
||||
void* getSelectedTab();
|
||||
TabView* getSelectedTab();
|
||||
|
||||
void startScrolling();
|
||||
void stopScrolling();
|
||||
@ -101,17 +104,17 @@ private:
|
||||
|
||||
void selectTabInternal(Tab* tab);
|
||||
void drawTab(BITMAP* bmp, ui::JRect box, Tab* tab, int y_delta, bool selected);
|
||||
TabsListIterator getTabIteratorByData(void* data);
|
||||
Tab* getTabByData(void* data);
|
||||
TabsListIterator getTabIteratorByView(TabView* tabView);
|
||||
Tab* getTabByView(TabView* tabView);
|
||||
int getMaxScrollX();
|
||||
void makeTabVisible(Tab* tab);
|
||||
void setScrollX(int scroll_x);
|
||||
void calculateHot();
|
||||
int calcTabWidth(Tab* tab);
|
||||
void calcTabWidth(Tab* tab);
|
||||
|
||||
TabsList m_list_of_tabs;
|
||||
Tab *m_hot;
|
||||
Tab *m_selected;
|
||||
Tab* m_hot;
|
||||
Tab* m_selected;
|
||||
int m_scrollX;
|
||||
|
||||
// Variables for animation purposes
|
||||
|
@ -34,6 +34,8 @@
|
||||
#include "tools/tool_box.h"
|
||||
#include "ui/gui.h"
|
||||
#include "ui_context.h"
|
||||
#include "widgets/main_window.h"
|
||||
#include "widgets/mini_editor.h"
|
||||
#include "widgets/status_bar.h"
|
||||
|
||||
#include <allegro.h>
|
||||
@ -190,7 +192,7 @@ bool ToolBar::onProcessMessage(Message* msg)
|
||||
toolrc = getToolGroupBounds(MiniEditorVisibilityIndex);
|
||||
toolrc.offset(-msg->draw.rect.x1, -msg->draw.rect.y1);
|
||||
isHot = (m_hot_index == MiniEditorVisibilityIndex ||
|
||||
is_mini_editor_enabled());
|
||||
App::instance()->getMainWindow()->getMiniEditor()->isMiniEditorEnabled());
|
||||
theme->draw_bounds_nw(doublebuffer,
|
||||
toolrc,
|
||||
isHot ? PART_TOOLBUTTON_HOT_NW:
|
||||
@ -248,7 +250,10 @@ bool ToolBar::onProcessMessage(Message* msg)
|
||||
toolrc = getToolGroupBounds(MiniEditorVisibilityIndex);
|
||||
if (msg->mouse.y >= toolrc.y && msg->mouse.y < toolrc.y+toolrc.h) {
|
||||
// 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;
|
||||
}
|
||||
@ -501,7 +506,7 @@ void ToolBar::openTipWindow(int group_index, Tool* tool)
|
||||
tooltip = "Configure Tool";
|
||||
}
|
||||
else if (group_index == MiniEditorVisibilityIndex) {
|
||||
if (is_mini_editor_enabled())
|
||||
if (App::instance()->getMainWindow()->getMiniEditor()->isMiniEditorEnabled())
|
||||
tooltip = "Disable Mini-Editor";
|
||||
else
|
||||
tooltip = "Enable Mini-Editor";
|
||||
|
96
src/widgets/workspace.cpp
Normal file
96
src/widgets/workspace.cpp
Normal 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
53
src/widgets/workspace.h
Normal 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
|
36
src/widgets/workspace_view.h
Normal file
36
src/widgets/workspace_view.h
Normal 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
|
Loading…
x
Reference in New Issue
Block a user