diff --git a/data/pref.xml b/data/pref.xml index 5510a4661..88e141fb3 100644 --- a/data/pref.xml +++ b/data/pref.xml @@ -1,6 +1,6 @@ - + @@ -275,6 +275,11 @@ diff --git a/src/app/ini_file.cpp b/src/app/ini_file.cpp index 6ce7f3d7b..8863fb6c4 100644 --- a/src/app/ini_file.cpp +++ b/src/app/ini_file.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2001-2015 David Capello +// Copyright (C) 2001-2016 David Capello // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -145,6 +145,28 @@ void set_config_bool(const char* section, const char* name, bool value) g_configs.back()->setBoolValue(section, name, value); } +Point get_config_point(const char* section, const char* name, const Point& point) +{ + Point point2(point); + const char* value = get_config_string(section, name, ""); + if (value) { + std::vector parts; + base::split_string(value, parts, " "); + if (parts.size() == 2) { + point2.x = strtol(parts[0].c_str(), NULL, 10); + point2.y = strtol(parts[1].c_str(), NULL, 10); + } + } + return point2; +} + +void set_config_point(const char* section, const char* name, const Point& point) +{ + char buf[128]; + sprintf(buf, "%d %d", point.x, point.y); + set_config_string(section, name, buf); +} + Rect get_config_rect(const char* section, const char* name, const Rect& rect) { Rect rect2(rect); diff --git a/src/app/ini_file.h b/src/app/ini_file.h index 1323752a6..eba8e2f5e 100644 --- a/src/app/ini_file.h +++ b/src/app/ini_file.h @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2001-2015 David Capello +// Copyright (C) 2001-2016 David Capello // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -9,8 +9,9 @@ #define APP_INI_FILE_H_INCLUDED #pragma once -#include "gfx/rect.h" #include "app/color.h" +#include "gfx/point.h" +#include "gfx/rect.h" namespace app { @@ -42,6 +43,9 @@ namespace app { bool get_config_bool(const char* section, const char* name, bool value); void set_config_bool(const char* section, const char* name, bool value); + gfx::Point get_config_point(const char* section, const char* name, const gfx::Point& point); + void set_config_point(const char* section, const char* name, const gfx::Point& point); + gfx::Rect get_config_rect(const char* section, const char* name, const gfx::Rect& rect); void set_config_rect(const char* section, const char* name, const gfx::Rect& rect); @@ -77,6 +81,10 @@ namespace app { return get_config_double(section, name, value); } + inline gfx::Point get_config_value(const char* section, const char* name, const gfx::Point& value) { + return get_config_point(section, name, value); + } + inline gfx::Rect get_config_value(const char* section, const char* name, const gfx::Rect& value) { return get_config_rect(section, name, value); } @@ -110,6 +118,10 @@ namespace app { set_config_double(section, name, value); } + inline void set_config_value(const char* section, const char* name, const gfx::Point& value) { + set_config_point(section, name, value); + } + inline void set_config_value(const char* section, const char* name, const gfx::Rect& value) { set_config_rect(section, name, value); } diff --git a/src/app/pref/preferences.h b/src/app/pref/preferences.h index 0fd2c8b9d..50e267ec0 100644 --- a/src/app/pref/preferences.h +++ b/src/app/pref/preferences.h @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2001-2015 David Capello +// Copyright (C) 2001-2016 David Capello // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -26,6 +26,7 @@ #include "filters/tiled_mode.h" #include "gfx/rect.h" #include "render/onionskin_position.h" +#include "render/zoom.h" #include "pref.xml.h" diff --git a/src/app/ui/document_view.cpp b/src/app/ui/document_view.cpp index 28fed28de..14a30410d 100644 --- a/src/app/ui/document_view.cpp +++ b/src/app/ui/document_view.cpp @@ -28,7 +28,6 @@ #include "app/ui/editor/editor_view.h" #include "app/ui/keyboard_shortcuts.h" #include "app/ui/main_window.h" -#include "app/ui/preview_editor.h" #include "app/ui/status_bar.h" #include "app/ui/workspace.h" #include "app/ui_context.h" @@ -54,7 +53,10 @@ class AppEditor : public Editor, public EditorObserver, public EditorCustomizationDelegate { public: - AppEditor(Document* document) : Editor(document) { + AppEditor(Document* document, + DocumentViewPreviewDelegate* previewDelegate) + : Editor(document) + , m_previewDelegate(previewDelegate) { addObserver(this); setCustomizationDelegate(this); } @@ -66,29 +68,25 @@ public: // EditorObserver implementation void dispose() override { - PreviewEditorWindow* preview = - App::instance()->getMainWindow()->getPreviewEditor(); - - if (preview->relatedEditor() == this) - updatePreviewEditor(nullptr); + m_previewDelegate->onDisposeOtherEditor(this); } void onScrollChanged(Editor* editor) override { - updatePreviewEditor(this); + m_previewDelegate->onScrollOtherEditor(this); if (isActive()) StatusBar::instance()->updateFromEditor(this); } void onAfterFrameChanged(Editor* editor) override { - updatePreviewEditor(this); + m_previewDelegate->onPreviewOtherEditor(this); if (isActive()) set_current_palette(editor->sprite()->palette(editor->frame()), true); } void onAfterLayerChanged(Editor* editor) override { - updatePreviewEditor(this); + m_previewDelegate->onPreviewOtherEditor(this); } // EditorCustomizationDelegate implementation @@ -144,44 +142,28 @@ protected: } private: - - void updatePreviewEditor(Editor* editor) { - App::instance()->getMainWindow()->getPreviewEditor()->updateUsingEditor(editor); - } - + DocumentViewPreviewDelegate* m_previewDelegate; }; -class PreviewEditor : public Editor, - public EditorObserver { +class PreviewEditor : public Editor { public: PreviewEditor(Document* document) : Editor(document, Editor::kShowOutside) // Don't show grid/mask in preview preview { - addObserver(this); - } - - ~PreviewEditor() { - removeObserver(this); - } - -private: - void onScrollChanged(Editor* editor) override { - if (hasCapture()) { - // TODO create a signal - App::instance()->getMainWindow()->getPreviewEditor()->uncheckCenterButton(); - } } }; -DocumentView::DocumentView(Document* document, Type type) +DocumentView::DocumentView(Document* document, Type type, + DocumentViewPreviewDelegate* previewDelegate) : Box(VERTICAL) , m_type(type) , m_document(document) , m_view(new EditorView(type == Normal ? EditorView::CurrentEditorMode: EditorView::AlwaysSelected)) + , m_previewDelegate(previewDelegate) , m_editor((type == Normal ? - (Editor*)new AppEditor(document): - (Editor*)new PreviewEditor(document))) + (Editor*)new AppEditor(document, previewDelegate): + (Editor*)new PreviewEditor(document))) { addChild(m_view); @@ -215,7 +197,7 @@ TabIcon DocumentView::getTabIcon() WorkspaceView* DocumentView::cloneWorkspaceView() { - return new DocumentView(m_document, Normal); + return new DocumentView(m_document, Normal, m_previewDelegate); } void DocumentView::onWorkspaceViewSelected() diff --git a/src/app/ui/document_view.h b/src/app/ui/document_view.h index e8c7e16b9..807ce9bdd 100644 --- a/src/app/ui/document_view.h +++ b/src/app/ui/document_view.h @@ -27,6 +27,14 @@ namespace app { class Document; class Editor; + class DocumentViewPreviewDelegate { + public: + virtual ~DocumentViewPreviewDelegate() { } + virtual void onScrollOtherEditor(Editor* editor) = 0; + virtual void onDisposeOtherEditor(Editor* editor) = 0; + virtual void onPreviewOtherEditor(Editor* editor) = 0; + }; + class DocumentView : public ui::Box , public TabView , public doc::DocumentObserver @@ -38,7 +46,8 @@ namespace app { Preview }; - DocumentView(Document* document, Type type); + DocumentView(Document* document, Type type, + DocumentViewPreviewDelegate* previewDelegate); ~DocumentView(); Document* getDocument() const { return m_document; } @@ -93,6 +102,7 @@ namespace app { Type m_type; Document* m_document; ui::View* m_view; + DocumentViewPreviewDelegate* m_previewDelegate; Editor* m_editor; }; diff --git a/src/app/ui/editor/editor.cpp b/src/app/ui/editor/editor.cpp index 456419b5a..17e51dc18 100644 --- a/src/app/ui/editor/editor.cpp +++ b/src/app/ui/editor/editor.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2001-2015 David Capello +// Copyright (C) 2001-2016 David Capello // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -355,6 +355,14 @@ Site Editor::getSite() const return site; } +void Editor::setZoom(const render::Zoom& zoom) +{ + if (m_zoom != zoom) { + m_zoom = zoom; + notifyZoomChanged(); + } +} + void Editor::setDefaultScroll() { View* view = View::getView(this); @@ -1481,7 +1489,7 @@ void Editor::setZoomAndCenterInMouse(const Zoom& zoom, padding.y - (screenPos.y-vp.y) + zoom.apply(spritePos.y+zoom.remove(1)/2) + int(zoom.apply(subpixelPos.y))); if ((m_zoom != zoom) || (screenPos != view->viewScroll())) { - m_zoom = zoom; + setZoom(zoom); updateEditor(); setEditorScroll(scrollPos); @@ -1576,6 +1584,11 @@ void Editor::notifyScrollChanged() m_observers.notifyScrollChanged(this); } +void Editor::notifyZoomChanged() +{ + m_observers.notifyZoomChanged(this); +} + void Editor::play(bool playOnce) { ASSERT(m_state); diff --git a/src/app/ui/editor/editor.h b/src/app/ui/editor/editor.h index 479483c52..e1d2f9713 100644 --- a/src/app/ui/editor/editor.h +++ b/src/app/ui/editor/editor.h @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2001-2015 David Capello +// Copyright (C) 2001-2016 David Capello // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -128,7 +128,7 @@ namespace app { const render::Zoom& zoom() const { return m_zoom; } const gfx::Point& padding() const { return m_padding; } - void setZoom(const render::Zoom& zoom) { m_zoom = zoom; } + void setZoom(const render::Zoom& zoom); void setDefaultScroll(); void setEditorScroll(const gfx::Point& scroll); void setEditorZoom(const render::Zoom& zoom); @@ -194,6 +194,7 @@ namespace app { // Used by EditorView to notify changes in the view's scroll // position. void notifyScrollChanged(); + void notifyZoomChanged(); // Animation control void play(bool playOnce); diff --git a/src/app/ui/editor/editor_observer.h b/src/app/ui/editor/editor_observer.h index ca335f13a..c1c6927a7 100644 --- a/src/app/ui/editor/editor_observer.h +++ b/src/app/ui/editor/editor_observer.h @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2001-2015 David Capello +// Copyright (C) 2001-2016 David Capello // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -25,6 +25,7 @@ namespace app { // Called when the scroll or zoom of the editor changes. virtual void onScrollChanged(Editor* editor) { } + virtual void onZoomChanged(Editor* editor) { } // Called when the current frame of the editor changes. virtual void onBeforeFrameChanged(Editor* editor) { } diff --git a/src/app/ui/editor/editor_observers.cpp b/src/app/ui/editor/editor_observers.cpp index c9c3e5cb6..5f10ff1fb 100644 --- a/src/app/ui/editor/editor_observers.cpp +++ b/src/app/ui/editor/editor_observers.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2001-2015 David Capello +// Copyright (C) 2001-2016 David Capello // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -45,6 +45,11 @@ void EditorObservers::notifyScrollChanged(Editor* editor) m_observers.notifyObservers(&EditorObserver::onScrollChanged, editor); } +void EditorObservers::notifyZoomChanged(Editor* editor) +{ + m_observers.notifyObservers(&EditorObserver::onZoomChanged, editor); +} + void EditorObservers::notifyBeforeFrameChanged(Editor* editor) { m_observers.notifyObservers(&EditorObserver::onBeforeFrameChanged, editor); diff --git a/src/app/ui/editor/editor_observers.h b/src/app/ui/editor/editor_observers.h index 672a52c3c..a2557ad85 100644 --- a/src/app/ui/editor/editor_observers.h +++ b/src/app/ui/editor/editor_observers.h @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2001-2015 David Capello +// Copyright (C) 2001-2016 David Capello // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -25,6 +25,7 @@ namespace app { void notifyDestroyEditor(Editor* editor); void notifyStateChanged(Editor* editor); void notifyScrollChanged(Editor* editor); + void notifyZoomChanged(Editor* editor); void notifyBeforeFrameChanged(Editor* editor); void notifyAfterFrameChanged(Editor* editor); void notifyBeforeLayerChanged(Editor* editor); diff --git a/src/app/ui/preview_editor.cpp b/src/app/ui/preview_editor.cpp index ee95b914c..77d71c247 100644 --- a/src/app/ui/preview_editor.cpp +++ b/src/app/ui/preview_editor.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2001-2015 David Capello +// Copyright (C) 2001-2016 David Capello // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -270,13 +270,26 @@ void PreviewEditorWindow::onWindowResize() updateUsingEditor(view->getEditor()); } +bool PreviewEditorWindow::hasDocument() const +{ + return (m_docView && m_docView->getDocument() != nullptr); +} + +DocumentPreferences& PreviewEditorWindow::docPref() +{ + Document* doc = (m_docView ? m_docView->getDocument(): nullptr); + return Preferences::instance().document(doc); +} + void PreviewEditorWindow::onCenterClicked() { - if (m_centerButton->isSelected()) { - DocumentView* view = UIContext::instance()->activeView(); - if (view) - updateUsingEditor(view->getEditor()); - } + if (!m_relatedEditor || !hasDocument()) + return; + + bool autoScroll = m_centerButton->isSelected(); + docPref().preview.autoScroll(autoScroll); + if (autoScroll) + updateUsingEditor(m_relatedEditor); } void PreviewEditorWindow::onPlayClicked() @@ -323,31 +336,38 @@ void PreviewEditorWindow::updateUsingEditor(Editor* editor) if (!isVisible()) openWindow(); - gfx::Rect visibleBounds = editor->getVisibleSpriteBounds(); - gfx::Point centerPoint = visibleBounds.center(); - bool center = (m_centerButton->isSelected()); + // Document preferences used to store the preferred zoom/scroll point + auto& docPref = Preferences::instance().document(document); + bool autoScroll = docPref.preview.autoScroll(); // Set the same location as in the given editor. if (!miniEditor || miniEditor->document() != document) { destroyDocView(); - m_docView = new DocumentView(document, DocumentView::Preview); + m_docView = new DocumentView(document, DocumentView::Preview, this); addChild(m_docView); miniEditor = m_docView->getEditor(); - miniEditor->setZoom(render::Zoom(1, 1)); + miniEditor->setZoom(render::Zoom::fromScale(docPref.preview.zoom())); miniEditor->setLayer(editor->layer()); miniEditor->setFrame(editor->frame()); miniEditor->setState(EditorStatePtr(new NavigateState)); miniEditor->setAnimationSpeedMultiplier(m_aniSpeed); miniEditor->addObserver(this); layout(); - center = true; + + if (!autoScroll) + miniEditor->setEditorScroll(docPref.preview.scroll()); } - if (center) + m_centerButton->setSelected(autoScroll); + if (autoScroll) { + gfx::Point centerPoint = editor->getVisibleSpriteBounds().center(); miniEditor->centerInSpritePoint(centerPoint); + saveScrollPref(); + } + if (!m_playButton->isPlaying()) { miniEditor->stop(); miniEditor->setLayer(editor->layer()); @@ -370,8 +390,10 @@ void PreviewEditorWindow::updateUsingEditor(Editor* editor) void PreviewEditorWindow::uncheckCenterButton() { - if (m_centerButton->isSelected()) + if (m_centerButton->isSelected()) { m_centerButton->setSelected(false); + onCenterClicked(); + } } void PreviewEditorWindow::onStateChanged(Editor* editor) @@ -386,6 +408,48 @@ void PreviewEditorWindow::onStateChanged(Editor* editor) } } +void PreviewEditorWindow::onScrollChanged(Editor* miniEditor) +{ + if (miniEditor->hasCapture()) { + saveScrollPref(); + uncheckCenterButton(); + } +} + +void PreviewEditorWindow::onZoomChanged(Editor* miniEditor) +{ + saveScrollPref(); +} + +void PreviewEditorWindow::saveScrollPref() +{ + ASSERT(m_docView); + if (!m_docView) + return; + + Editor* miniEditor = m_docView->getEditor(); + ASSERT(miniEditor); + + docPref().preview.scroll(View::getView(miniEditor)->viewScroll()); + docPref().preview.zoom(miniEditor->zoom().scale()); +} + +void PreviewEditorWindow::onScrollOtherEditor(Editor* editor) +{ + updateUsingEditor(editor); +} + +void PreviewEditorWindow::onDisposeOtherEditor(Editor* editor) +{ + if (m_relatedEditor == editor) + updateUsingEditor(nullptr); +} + +void PreviewEditorWindow::onPreviewOtherEditor(Editor* editor) +{ + updateUsingEditor(editor); +} + void PreviewEditorWindow::hideWindow() { destroyDocView(); diff --git a/src/app/ui/preview_editor.h b/src/app/ui/preview_editor.h index 57ff4f6a7..b45ff57ce 100644 --- a/src/app/ui/preview_editor.h +++ b/src/app/ui/preview_editor.h @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2001-2015 David Capello +// Copyright (C) 2001-2016 David Capello // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -12,6 +12,7 @@ #include "app/ui/document_view.h" #include "app/ui/editor/editor_observer.h" #include "doc/frame.h" +#include "app/pref/preferences.h" #include "ui/window.h" namespace app { @@ -19,7 +20,8 @@ namespace app { class MiniPlayButton; class PreviewEditorWindow : public ui::Window - , public EditorObserver { + , public EditorObserver + , public DocumentViewPreviewDelegate { public: PreviewEditorWindow(); ~PreviewEditorWindow(); @@ -28,12 +30,18 @@ namespace app { void setPreviewEnabled(bool state); void updateUsingEditor(Editor* editor); - void uncheckCenterButton(); Editor* relatedEditor() const { return m_relatedEditor; } // EditorObserver impl void onStateChanged(Editor* editor) override; + void onScrollChanged(Editor* editor) override; + void onZoomChanged(Editor* editor) override; + + // DocumentViewPreviewDelegate impl + void onScrollOtherEditor(Editor* editor) override; + void onDisposeOtherEditor(Editor* editor) override; + void onPreviewOtherEditor(Editor* editor) override; protected: bool onProcessMessage(ui::Message* msg) override; @@ -41,11 +49,15 @@ namespace app { void onWindowResize() override; private: + void uncheckCenterButton(); + bool hasDocument() const; + DocumentPreferences& docPref(); void onCenterClicked(); void onPlayClicked(); void onPopupSpeed(); void hideWindow(); void destroyDocView(); + void saveScrollPref(); bool m_isEnabled; DocumentView* m_docView; diff --git a/src/app/ui_context.cpp b/src/app/ui_context.cpp index 527bda3be..222d305c1 100644 --- a/src/app/ui_context.cpp +++ b/src/app/ui_context.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2001-2015 David Capello +// Copyright (C) 2001-2016 David Capello // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -194,7 +194,10 @@ void UIContext::onAddDocument(doc::Document* doc) return; // Add a new view for this document - DocumentView* view = new DocumentView(m_lastSelectedDoc, DocumentView::Normal); + DocumentView* view = new DocumentView( + m_lastSelectedDoc, + DocumentView::Normal, + App::instance()->getMainWindow()->getPreviewEditor()); // Add a tab with the new view for the document App::instance()->getMainWindow()->getWorkspace()->addView(view);