diff --git a/src/app/commands/cmd_configure_tools.cpp b/src/app/commands/cmd_configure_tools.cpp index 369e4030c..a4375bef1 100644 --- a/src/app/commands/cmd_configure_tools.cpp +++ b/src/app/commands/cmd_configure_tools.cpp @@ -36,6 +36,7 @@ #include "app/ui/status_bar.h" #include "app/ui_context.h" #include "base/bind.h" +#include "doc/context_observer.h" #include "gfx/size.h" #include "raster/mask.h" #include "ui/ui.h" @@ -55,13 +56,15 @@ static void on_exit_delete_this_widget() delete window; } -class ConfigureTools : public Command { +class ConfigureTools : public Command, + public doc::ContextObserver { public: ConfigureTools(); Command* clone() const override { return new ConfigureTools(*this); } protected: - void onExecute(Context* context); + void onExecute(Context* context) override; + void onSetActiveDocument(doc::Document* document) override; private: CheckBox* m_tiled; @@ -93,8 +96,8 @@ ConfigureTools::ConfigureTools() void ConfigureTools::onExecute(Context* context) { - m_settings = UIContext::instance()->settings(); - m_docSettings = m_settings->getDocumentSettings(NULL); + m_settings = context->settings(); + m_docSettings = NULL; Button* set_grid; bool first_time = false; @@ -105,10 +108,13 @@ void ConfigureTools::onExecute(Context* context) } // If the window is opened, close it else if (window->isVisible()) { + context->removeObserver(this); window->closeWindow(NULL); return; } + context->addObserver(this); + try { m_tiled = app::find_widget(window, "tiled"); m_tiledX = app::find_widget(window, "tiled_x"); @@ -124,15 +130,7 @@ void ConfigureTools::onExecute(Context* context) throw; } - if (m_docSettings->getTiledMode() != filters::TILED_NONE) { - m_tiled->setSelected(true); - if (m_docSettings->getTiledMode() & filters::TILED_X_AXIS) m_tiledX->setSelected(true); - if (m_docSettings->getTiledMode() & filters::TILED_Y_AXIS) m_tiledY->setSelected(true); - } - - if (m_docSettings->getSnapToGrid()) m_snapToGrid->setSelected(true); - if (m_docSettings->getGridVisible()) m_viewGrid->setSelected(true); - if (m_docSettings->getPixelGridVisible()) m_pixelGrid->setSelected(true); + onSetActiveDocument(context->activeDocument()); if (first_time) { // Slots @@ -227,6 +225,24 @@ void ConfigureTools::onSetGridClick() } } +void ConfigureTools::onSetActiveDocument(doc::Document* document) +{ + if (!document) + return; + + m_docSettings = m_settings->getDocumentSettings(document); + ASSERT(m_docSettings); + if (!m_docSettings) + return; + + m_tiled->setSelected(m_docSettings->getTiledMode() != filters::TILED_NONE); + m_tiledX->setSelected(m_docSettings->getTiledMode() & filters::TILED_X_AXIS ? true: false); + m_tiledY->setSelected(m_docSettings->getTiledMode() & filters::TILED_Y_AXIS ? true: false); + m_snapToGrid->setSelected(m_docSettings->getSnapToGrid()); + m_viewGrid->setSelected(m_docSettings->getGridVisible()); + m_pixelGrid->setSelected(m_docSettings->getPixelGridVisible()); +} + Command* CommandFactory::createConfigureToolsCommand() { return new ConfigureTools; diff --git a/src/app/commands/cmd_grid.cpp b/src/app/commands/cmd_grid.cpp index 1e862b759..3b77638a3 100644 --- a/src/app/commands/cmd_grid.cpp +++ b/src/app/commands/cmd_grid.cpp @@ -23,6 +23,7 @@ #include "app/app.h" #include "app/commands/command.h" #include "app/context.h" +#include "app/document.h" #include "app/find_widget.h" #include "app/load_widget.h" #include "app/modules/editors.h" diff --git a/src/app/commands/cmd_onionskin.cpp b/src/app/commands/cmd_onionskin.cpp index b2f71fd08..af17d5ecb 100644 --- a/src/app/commands/cmd_onionskin.cpp +++ b/src/app/commands/cmd_onionskin.cpp @@ -23,6 +23,7 @@ #include "app/app.h" #include "app/commands/command.h" #include "app/context.h" +#include "app/document.h" #include "app/settings/document_settings.h" #include "app/settings/settings.h" diff --git a/src/app/commands/cmd_options.cpp b/src/app/commands/cmd_options.cpp index d257fb00e..eb700c831 100644 --- a/src/app/commands/cmd_options.cpp +++ b/src/app/commands/cmd_options.cpp @@ -52,7 +52,7 @@ class OptionsWindow : public app::gen::Options { public: OptionsWindow(Context* context) : m_settings(context->settings()) - , m_docSettings(m_settings->getDocumentSettings(NULL)) + , m_docSettings(m_settings->getDocumentSettings(context->activeDocument())) , m_checked_bg_color1(new ColorButton(RenderEngine::getCheckedBgColor1(), IMAGE_RGB)) , m_checked_bg_color2(new ColorButton(RenderEngine::getCheckedBgColor2(), IMAGE_RGB)) , m_pixelGridColor(new ColorButton(m_docSettings->getPixelGridColor(), IMAGE_RGB)) diff --git a/src/app/commands/filters/cmd_convolution_matrix.cpp b/src/app/commands/filters/cmd_convolution_matrix.cpp index 3092ae9d4..0512f3d43 100644 --- a/src/app/commands/filters/cmd_convolution_matrix.cpp +++ b/src/app/commands/filters/cmd_convolution_matrix.cpp @@ -26,6 +26,7 @@ #include "app/commands/filters/filter_manager_impl.h" #include "app/commands/filters/filter_window.h" #include "app/context.h" +#include "app/document.h" #include "app/find_widget.h" #include "app/ini_file.h" #include "app/load_widget.h" diff --git a/src/app/commands/filters/cmd_despeckle.cpp b/src/app/commands/filters/cmd_despeckle.cpp index ecbdbc5b6..ed633ef49 100644 --- a/src/app/commands/filters/cmd_despeckle.cpp +++ b/src/app/commands/filters/cmd_despeckle.cpp @@ -24,6 +24,7 @@ #include "app/commands/filters/filter_manager_impl.h" #include "app/commands/filters/filter_window.h" #include "app/context.h" +#include "app/document.h" #include "app/find_widget.h" #include "app/ini_file.h" #include "app/load_widget.h" diff --git a/src/app/ini_file.cpp b/src/app/ini_file.cpp index 19c8a349e..3c8285d3e 100644 --- a/src/app/ini_file.cpp +++ b/src/app/ini_file.cpp @@ -54,13 +54,12 @@ ConfigModule::ConfigModule() } #endif - override_config_file(fn.c_str()); + set_config_file(fn.c_str()); g_configFilename = fn; } ConfigModule::~ConfigModule() { - //override_config_file(NULL); flush_config_file(); } diff --git a/src/app/settings/settings.h b/src/app/settings/settings.h index ae173d152..45a60b7f5 100644 --- a/src/app/settings/settings.h +++ b/src/app/settings/settings.h @@ -31,10 +31,13 @@ #include "gfx/rect.h" #include "raster/brush_type.h" +namespace doc { + class Document; +} + namespace app { class ColorSwatches; - class Document; class IColorSwatchesStore; class IDocumentSettings; class IBrushSettings; @@ -82,7 +85,7 @@ namespace app { // Returns the specific settings for the given document. If the // document is null, it should return an interface for // global/default settings. - virtual IDocumentSettings* getDocumentSettings(const Document* document) = 0; + virtual IDocumentSettings* getDocumentSettings(const doc::Document* document) = 0; // Specific configuration for the given tool. virtual IToolSettings* getToolSettings(tools::Tool* tool) = 0; diff --git a/src/app/settings/ui_settings_impl.cpp b/src/app/settings/ui_settings_impl.cpp index 9d410301e..e8a480c95 100644 --- a/src/app/settings/ui_settings_impl.cpp +++ b/src/app/settings/ui_settings_impl.cpp @@ -24,7 +24,9 @@ #include "app/app.h" #include "app/color_swatches.h" +#include "app/document.h" #include "app/ini_file.h" +#include "app/resource_finder.h" #include "app/settings/document_settings.h" #include "app/tools/controller.h" #include "app/tools/ink.h" @@ -32,7 +34,10 @@ #include "app/tools/tool.h" #include "app/tools/tool_box.h" #include "app/ui/color_bar.h" +#include "app/ui_context.h" #include "base/observable.h" +#include "doc/context.h" +#include "doc/documents_observer.h" #include "ui/manager.h" #include "ui/system.h" @@ -55,45 +60,88 @@ namespace { class UIDocumentSettingsImpl : public IDocumentSettings, public base::Observable { public: - UIDocumentSettingsImpl() - : m_tiledMode((TiledMode)get_config_int("Tools", "Tiled", (int)TILED_NONE)) - , m_use_onionskin(get_config_bool("Onionskin", "Enabled", false)) - , m_prev_frames_onionskin(get_config_int("Onionskin", "PrevFrames", 1)) - , m_next_frames_onionskin(get_config_int("Onionskin", "NextFrames", 1)) - , m_onionskin_opacity_base(get_config_int("Onionskin", "OpacityBase", DEFAULT_ONIONSKIN_OPACITY_BASE)) - , m_onionskin_opacity_step(get_config_int("Onionskin", "OpacityStep", DEFAULT_ONIONSKIN_OPACITY_STEP)) - , m_onionskinType((OnionskinType)get_config_int("Onionskin", "Type", (int)DEFAULT_ONIONSKIN_TYPE)) - , m_snapToGrid(get_config_bool("Grid", "SnapTo", false)) - , m_gridVisible(get_config_bool("Grid", "Visible", false)) - , m_gridBounds(get_config_rect("Grid", "Bounds", Rect(0, 0, 16, 16))) - , m_gridColor(get_config_color("Grid", "Color", app::Color::fromRgb(0, 0, 255))) - , m_pixelGridVisible(get_config_bool("PixelGrid", "Visible", false)) - , m_pixelGridColor(get_config_color("PixelGrid", "Color", app::Color::fromRgb(200, 200, 200))) + UIDocumentSettingsImpl(const doc::Document* doc) + : m_doc(doc) + , m_tiledMode(TILED_NONE) + , m_use_onionskin(false) + , m_prev_frames_onionskin(1) + , m_next_frames_onionskin(1) + , m_onionskin_opacity_base(DEFAULT_ONIONSKIN_OPACITY_BASE) + , m_onionskin_opacity_step(DEFAULT_ONIONSKIN_OPACITY_STEP) + , m_onionskinType(DEFAULT_ONIONSKIN_TYPE) + , m_snapToGrid(false) + , m_gridVisible(false) + , m_gridBounds(0, 0, 16, 16) + , m_gridColor(app::Color::fromRgb(0, 0, 255)) + , m_pixelGridVisible(false) + , m_pixelGridColor(app::Color::fromRgb(200, 200, 200)) , m_isLoop(false) , m_loopBegin(0) - , m_loopEnd(-1) + , m_loopEnd(1) , m_aniDir(AniDir_Normal) { - m_tiledMode = (TiledMode)MID(0, (int)m_tiledMode, (int)TILED_BOTH); - m_onionskinType = (OnionskinType)MID(0, (int)m_onionskinType, (int)Onionskin_Last); + bool specific_file = false; + if (m_doc && static_cast(m_doc)->isAssociatedToFile()) { + push_config_state(); + set_config_file(configFileName().c_str()); + specific_file = true; + + m_tiledMode = (TiledMode)get_config_int("Tools", "Tiled", (int)m_tiledMode); + m_use_onionskin = get_config_bool("Onionskin", "Enabled", m_use_onionskin); + m_prev_frames_onionskin = get_config_int("Onionskin", "PrevFrames", m_prev_frames_onionskin); + m_next_frames_onionskin = get_config_int("Onionskin", "NextFrames", m_next_frames_onionskin); + m_onionskin_opacity_base = get_config_int("Onionskin", "OpacityBase", m_onionskin_opacity_base); + m_onionskin_opacity_step = get_config_int("Onionskin", "OpacityStep", m_onionskin_opacity_step); + m_onionskinType = (OnionskinType)get_config_int("Onionskin", "Type", m_onionskinType); + m_snapToGrid = get_config_bool("Grid", "SnapTo", m_snapToGrid); + m_gridVisible = get_config_bool("Grid", "Visible", m_gridVisible); + m_gridBounds = get_config_rect("Grid", "Bounds", m_gridBounds); + m_pixelGridVisible = get_config_bool("PixelGrid", "Visible", m_pixelGridVisible); + + // Limit values + m_tiledMode = (TiledMode)MID(0, (int)m_tiledMode, (int)TILED_BOTH); + m_onionskinType = (OnionskinType)MID(0, (int)m_onionskinType, (int)Onionskin_Last); + } + + m_gridColor = get_config_color("Grid", "Color", m_gridColor); + m_pixelGridColor = get_config_color("PixelGrid", "Color", m_pixelGridColor); + + if (specific_file) + pop_config_state(); } ~UIDocumentSettingsImpl() { - set_config_int("Tools", "Tiled", m_tiledMode); - set_config_bool("Grid", "SnapTo", m_snapToGrid); - set_config_bool("Grid", "Visible", m_gridVisible); - set_config_rect("Grid", "Bounds", m_gridBounds); - set_config_color("Grid", "Color", m_gridColor); - set_config_bool("PixelGrid", "Visible", m_pixelGridVisible); - set_config_color("PixelGrid", "Color", m_pixelGridColor); + bool specific_file = false; + if (m_doc) { + // We don't save the document configuration if it isn't associated with a file. + if (!static_cast(m_doc)->isAssociatedToFile()) + return; - set_config_bool("Onionskin", "Enabled", m_use_onionskin); - set_config_int("Onionskin", "PrevFrames", m_prev_frames_onionskin); - set_config_int("Onionskin", "NextFrames", m_next_frames_onionskin); - set_config_int("Onionskin", "OpacityBase", m_onionskin_opacity_base); - set_config_int("Onionskin", "OpacityStep", m_onionskin_opacity_step); - set_config_int("Onionskin", "Type", m_onionskinType); + push_config_state(); + set_config_file(configFileName().c_str()); + specific_file = true; + + set_config_int("Tools", "Tiled", m_tiledMode); + set_config_bool("Grid", "SnapTo", m_snapToGrid); + set_config_bool("Grid", "Visible", m_gridVisible); + set_config_rect("Grid", "Bounds", m_gridBounds); + set_config_bool("PixelGrid", "Visible", m_pixelGridVisible); + + set_config_bool("Onionskin", "Enabled", m_use_onionskin); + set_config_int("Onionskin", "PrevFrames", m_prev_frames_onionskin); + set_config_int("Onionskin", "NextFrames", m_next_frames_onionskin); + set_config_int("Onionskin", "OpacityBase", m_onionskin_opacity_base); + set_config_int("Onionskin", "OpacityStep", m_onionskin_opacity_step); + set_config_int("Onionskin", "Type", m_onionskinType); + } + + saveSharedSettings(); + + if (specific_file) { + flush_config_file(); + pop_config_state(); + } } // Tiled mode @@ -154,11 +202,36 @@ public: virtual void removeObserver(DocumentSettingsObserver* observer) override; private: + void saveSharedSettings() { + set_config_color("Grid", "Color", m_gridColor); + set_config_color("PixelGrid", "Color", m_pixelGridColor); + } + + std::string configFileName() { + if (!m_doc) + return ""; + + if (m_cfgName.empty()) { + ResourceFinder rf; + std::string fn = m_doc->filename(); + for (size_t i=0; iinvalidate(); } + const doc::Document* m_doc; + std::string m_cfgName; TiledMode m_tiledMode; bool m_use_onionskin; int m_prev_frames_onionskin; @@ -176,7 +249,6 @@ private: raster::FrameNumber m_loopBegin; raster::FrameNumber m_loopEnd; AniDir m_aniDir; - }; class UISelectionSettingsImpl @@ -210,7 +282,6 @@ private: UISettingsImpl::UISettingsImpl() : m_currentTool(NULL) - , m_globalDocumentSettings(new UIDocumentSettingsImpl) , m_colorSwatches(NULL) , m_selectionSettings(new UISelectionSettingsImpl) , m_zoomWithScrollWheel(get_config_bool("Options", "ZoomWithMouseWheel", true)) @@ -233,17 +304,22 @@ UISettingsImpl::~UISettingsImpl() set_config_bool("Options", "GrabAlpha", m_grabAlpha); set_config_int("Options", "RightClickMode", static_cast(m_rightClickMode)); - // Delete all tool settings. - for (std::map::iterator - it = m_toolSettings.begin(), end = m_toolSettings.end(); it != end; ++it) { - delete it->second; - } + for (auto it : m_docSettings) + delete it.second; - // Delete all color swatches - for (std::vector::iterator - it = m_colorSwatchesStore.begin(), end = m_colorSwatchesStore.end(); - it != end; ++it) { - delete *it; + for (auto it : m_toolSettings) + delete it.second; + + for (auto it : m_colorSwatchesStore) + delete it; +} + +void UISettingsImpl::onRemoveDocument(doc::Document* doc) +{ + auto it = m_docSettings.find(doc->id()); + if (it != m_docSettings.end()) { + delete it->second; + m_docSettings.erase(it); } } @@ -369,9 +445,20 @@ void UISettingsImpl::setColorSwatches(app::ColorSwatches* colorSwatches) notifyObservers(&GlobalSettingsObserver::onSetColorSwatches, colorSwatches); } -IDocumentSettings* UISettingsImpl::getDocumentSettings(const Document* document) +IDocumentSettings* UISettingsImpl::getDocumentSettings(const doc::Document* document) { - return m_globalDocumentSettings; + doc::ObjectId id; + + if (!document) + id = doc::NullId; + else + id = document->id(); + + auto it = m_docSettings.find(id); + if (it != m_docSettings.end()) + return it->second; + + return m_docSettings[id] = new UIDocumentSettingsImpl(document); } IColorSwatchesStore* UISettingsImpl::getColorSwatchesStore() @@ -482,6 +569,8 @@ void UIDocumentSettingsImpl::setGridColor(const app::Color& color) { m_gridColor = color; notifyObservers(&DocumentSettingsObserver::onSetGridColor, color); + + saveSharedSettings(); } void UIDocumentSettingsImpl::snapToGrid(gfx::Point& point) const @@ -520,6 +609,8 @@ void UIDocumentSettingsImpl::setPixelGridColor(const app::Color& color) { m_pixelGridColor = color; redrawDocumentViews(); + + saveSharedSettings(); } bool UIDocumentSettingsImpl::getUseOnionskin() diff --git a/src/app/settings/ui_settings_impl.h b/src/app/settings/ui_settings_impl.h index 85a2d9c2c..5bb794bab 100644 --- a/src/app/settings/ui_settings_impl.h +++ b/src/app/settings/ui_settings_impl.h @@ -28,6 +28,8 @@ #include "app/settings/settings_observers.h" #include "base/observable.h" #include "base/unique_ptr.h" +#include "doc/documents_observer.h" +#include "doc/object_id.h" namespace app { @@ -35,11 +37,15 @@ namespace app { : public ISettings , public IExperimentalSettings , public IColorSwatchesStore + , public doc::DocumentsObserver , base::Observable { public: UISettingsImpl(); ~UISettingsImpl(); + // doc::DocumentsObserver + void onRemoveDocument(doc::Document* doc) override; + // Undo settings size_t undoSizeLimit() const override; bool undoGotoModified() const override; @@ -65,7 +71,7 @@ namespace app { void setCurrentTool(tools::Tool* tool) override; void setColorSwatches(app::ColorSwatches* colorSwatches) override; - IDocumentSettings* getDocumentSettings(const Document* document) override; + IDocumentSettings* getDocumentSettings(const doc::Document* document) override; IToolSettings* getToolSettings(tools::Tool* tool) override; IColorSwatchesStore* getColorSwatchesStore() override; @@ -87,7 +93,6 @@ namespace app { private: tools::Tool* m_currentTool; - base::UniquePtr m_globalDocumentSettings; std::map m_toolSettings; app::ColorSwatches* m_colorSwatches; std::vector m_colorSwatchesStore; @@ -96,6 +101,7 @@ namespace app { bool m_showSpriteEditorScrollbars; bool m_grabAlpha; RightClickMode m_rightClickMode; + std::map m_docSettings; }; } // namespace app diff --git a/src/app/ui_context.cpp b/src/app/ui_context.cpp index aab1d5f2d..9468042d8 100644 --- a/src/app/ui_context.cpp +++ b/src/app/ui_context.cpp @@ -48,6 +48,8 @@ UIContext::UIContext() : Context(new UISettingsImpl) , m_lastSelectedView(NULL) { + documents().addObserver(static_cast(settings())); + ASSERT(m_instance == NULL); m_instance = this; } @@ -57,6 +59,8 @@ UIContext::~UIContext() ASSERT(m_instance == this); m_instance = NULL; + documents().removeObserver(static_cast(settings())); + // The context must be empty at this point. (It's to check if the UI // is working correctly, i.e. closing all files when the user can // take any action about it.)