1// Aseprite
2// Copyright (C) 2020-2022 Igara Studio S.A.
3// Copyright (C) 2001-2017 David Capello
4//
5// This program is distributed under the terms of
6// the End-User License Agreement for Aseprite.
7
8#ifdef HAVE_CONFIG_H
9#include "config.h"
10#endif
11
12#include "app/ui/editor/editor_view.h"
13
14#include "app/app.h"
15#include "app/modules/editors.h"
16#include "app/modules/gui.h"
17#include "app/pref/preferences.h"
18#include "app/ui/editor/editor.h"
19#include "app/ui/skin/skin_theme.h"
20#include "os/surface.h"
21#include "ui/paint_event.h"
22#include "ui/resize_event.h"
23#include "ui/scroll_region_event.h"
24
25namespace app {
26
27using namespace app::skin;
28using namespace ui;
29
30// static
31EditorView::Method EditorView::g_scrollUpdateMethod = Method::KeepOrigin;
32
33// static
34void EditorView::SetScrollUpdateMethod(Method method)
35{
36 g_scrollUpdateMethod = method;
37}
38
39EditorView::EditorView(EditorView::Type type)
40 : View()
41 , m_type(type)
42{
43 m_scrollSettingsConn =
44 Preferences::instance().editor.showScrollbars.AfterChange.connect(
45 [this]{ setupScrollbars(); });
46
47 InitTheme.connect(
48 [this]{
49 auto theme = SkinTheme::get(this);
50 setBgColor(gfx::rgba(0, 0, 0)); // TODO Move this color to theme.xml
51 setStyle(theme->styles.editorView());
52 setupScrollbars();
53 });
54 initTheme();
55}
56
57void EditorView::onPaint(PaintEvent& ev)
58{
59 switch (m_type) {
60
61 // Only show the view selected if it is the current editor
62 case CurrentEditorMode:
63 if (editor()->isActive())
64 enableFlags(SELECTED);
65 else
66 disableFlags(SELECTED);
67 break;
68
69 // Always show selected
70 case AlwaysSelected:
71 enableFlags(SELECTED);
72 break;
73
74 }
75
76 View::onPaint(ev);
77}
78
79void EditorView::onResize(ResizeEvent& ev)
80{
81 Editor* editor = this->editor();
82 gfx::Point oldPos;
83 if (editor) {
84 switch (g_scrollUpdateMethod) {
85 case KeepOrigin:
86 oldPos = editor->editorToScreen(gfx::Point(0, 0));
87 break;
88 case KeepCenter:
89 oldPos = editor->screenToEditor(viewportBounds().center());
90 break;
91 }
92 }
93
94 View::onResize(ev);
95
96 if (editor) {
97 switch (g_scrollUpdateMethod) {
98 case KeepOrigin: {
99 // This keeps the same scroll position for the editor
100 gfx::Point newPos = editor->editorToScreen(gfx::Point(0, 0));
101 gfx::Point oldScroll = viewScroll();
102 editor->setEditorScroll(oldScroll + newPos - oldPos);
103 break;
104 }
105 case KeepCenter:
106 editor->centerInSpritePoint(oldPos);
107 break;
108 }
109 }
110}
111
112void EditorView::onSetViewScroll(const gfx::Point& pt)
113{
114 Editor* editor = this->editor();
115 if (editor) {
116 // Hide the brush preview to avoid leaving a cursor trail.
117 HideBrushPreview hide(editor->brushPreview());
118 View::onSetViewScroll(pt);
119 }
120}
121
122void EditorView::onScrollRegion(ui::ScrollRegionEvent& ev)
123{
124 gfx::Region& region = ev.region();
125 Editor* editor = this->editor();
126 ASSERT(editor);
127 if (editor) {
128 gfx::Region invalidRegion;
129 editor->getInvalidDecoratoredRegion(invalidRegion);
130 region.createSubtraction(region, invalidRegion);
131 }
132}
133
134void EditorView::onScrollChange()
135{
136 View::onScrollChange();
137
138 Editor* editor = this->editor();
139 ASSERT(editor != NULL);
140 if (editor)
141 editor->notifyScrollChanged();
142}
143
144void EditorView::setupScrollbars()
145{
146 if (m_type == AlwaysSelected ||
147 !Preferences::instance().editor.showScrollbars()) {
148 hideScrollBars();
149 }
150 else {
151 auto theme = SkinTheme::get(this);
152 int barsize = theme->dimensions.miniScrollbarSize();
153
154 horizontalBar()->setBarWidth(barsize);
155 verticalBar()->setBarWidth(barsize);
156
157 horizontalBar()->setStyle(theme->styles.miniScrollbar());
158 verticalBar()->setStyle(theme->styles.miniScrollbar());
159 horizontalBar()->setThumbStyle(theme->styles.miniScrollbarThumb());
160 verticalBar()->setThumbStyle(theme->styles.miniScrollbarThumb());
161
162 showScrollBars();
163 }
164}
165
166Editor* EditorView::editor()
167{
168 return static_cast<Editor*>(attachedWidget());
169}
170
171} // namespace app
172