1// Aseprite
2// Copyright (C) 2020 Igara Studio S.A.
3// Copyright (C) 2001-2018 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/commands/filters/filter_window.h"
13
14#include "app/commands/filters/filter_manager_impl.h"
15#include "app/commands/filters/filter_worker.h"
16#include "app/i18n/strings.h"
17#include "app/ini_file.h"
18#include "app/modules/editors.h"
19#include "app/modules/gui.h"
20#include "app/pref/preferences.h"
21#include "app/ui/editor/editor.h"
22
23namespace app {
24
25using namespace filters;
26using namespace ui;
27
28FilterWindow::FilterWindow(const char* title, const char* cfgSection,
29 FilterManagerImpl* filterMgr,
30 WithChannels withChannels,
31 WithTiled withTiled,
32 TiledMode tiledMode)
33 : Window(WithTitleBar, title)
34 , m_cfgSection(cfgSection)
35 , m_filterMgr(filterMgr)
36 , m_hbox(HORIZONTAL)
37 , m_vbox(VERTICAL)
38 , m_container(VERTICAL)
39 , m_okButton(Strings::filters_ok())
40 , m_cancelButton(Strings::filters_cancel())
41 , m_preview(filterMgr)
42 , m_targetButton(filterMgr->pixelFormat(), (withChannels == WithChannelsSelector))
43 , m_showPreview(Strings::filters_preview())
44 , m_tiledCheck(withTiled == WithTiledCheckBox ?
45 new CheckBox(Strings::filters_tiled()) :
46 nullptr)
47{
48 m_okButton.processMnemonicFromText();
49 m_cancelButton.processMnemonicFromText();
50 m_showPreview.processMnemonicFromText();
51 if (m_tiledCheck)
52 m_tiledCheck->processMnemonicFromText();
53
54 CelsTarget celsTarget = Preferences::instance().filters.celsTarget();
55 filterMgr->setCelsTarget(celsTarget);
56
57 m_targetButton.setTarget(filterMgr->getTarget());
58 m_targetButton.setCelsTarget(celsTarget);
59 m_targetButton.TargetChange.connect(&FilterWindow::onTargetButtonChange, this);
60 m_okButton.Click.connect(&FilterWindow::onOk, this);
61 m_cancelButton.Click.connect(&FilterWindow::onCancel, this);
62 m_showPreview.Click.connect(&FilterWindow::onShowPreview, this);
63
64 m_container.setExpansive(true);
65
66 m_hbox.addChild(&m_container);
67 m_hbox.addChild(&m_vbox);
68
69 m_vbox.addChild(&m_okButton);
70 m_vbox.addChild(&m_cancelButton);
71 m_vbox.addChild(&m_targetButton);
72 m_vbox.addChild(&m_showPreview);
73
74 addChild(&m_preview);
75 addChild(&m_hbox);
76
77 if (m_tiledCheck) {
78 m_tiledCheck->setSelected(tiledMode != TiledMode::NONE);
79 m_tiledCheck->Click.connect([this]{ onTiledChange(); });
80
81 m_vbox.addChild(m_tiledCheck);
82 }
83
84 // Load "Preview" check status.
85 m_showPreview.setSelected(get_config_bool(m_cfgSection, "Preview", true));
86
87 // OK is magnetic (the default button)
88 m_okButton.setFocusMagnet(true);
89}
90
91FilterWindow::~FilterWindow()
92{
93 // Save window configuration
94 save_window_pos(this, m_cfgSection);
95
96 // Save "Preview" check status.
97 set_config_bool(m_cfgSection, "Preview", m_showPreview.isSelected());
98
99 // Save cels target button
100 Preferences::instance().filters.celsTarget(m_targetButton.celsTarget());
101}
102
103bool FilterWindow::doModal()
104{
105 bool result = false;
106
107 // Default position
108 remapWindow();
109 centerWindow();
110
111 // Load window configuration
112 load_window_pos(this, m_cfgSection);
113
114 // Start first preview
115 restartPreview();
116
117 // Open in foreground
118 openWindowInForeground();
119
120 // Did the user press OK?
121 if (closer() == &m_okButton) {
122 stopPreview();
123
124 // Apply the filter in background
125 start_filter_worker(m_filterMgr);
126 result = true;
127 }
128
129 // Always update editors
130 update_screen_for_document(m_filterMgr->document());
131
132 return result;
133}
134
135void FilterWindow::restartPreview()
136{
137 bool state = m_showPreview.isSelected();
138 m_preview.setEnablePreview(state);
139
140 if (state)
141 m_preview.restartPreview();
142 else
143 stopPreview();
144}
145
146void FilterWindow::setNewTarget(Target target)
147{
148 stopPreview();
149
150 m_filterMgr->setTarget(target);
151 m_targetButton.setTarget(target);
152}
153
154void FilterWindow::onOk(Event& ev)
155{
156 m_okButton.closeWindow();
157}
158
159void FilterWindow::onCancel(Event& ev)
160{
161 m_cancelButton.closeWindow();
162}
163
164void FilterWindow::onShowPreview(Event& ev)
165{
166 restartPreview();
167
168 // If the preview was disabled just redraw the current editor in its
169 // original state.
170 if (!m_showPreview.isSelected())
171 m_filterMgr->disablePreview();
172}
173
174// Called when the user changes the target-buttons.
175void FilterWindow::onTargetButtonChange()
176{
177 stopPreview();
178
179 // Change the targets in the filter manager and restart the filter preview.
180 m_filterMgr->setTarget(m_targetButton.target());
181 m_filterMgr->setCelsTarget(m_targetButton.celsTarget());
182 restartPreview();
183}
184
185void FilterWindow::onTiledChange()
186{
187 ASSERT(m_tiledCheck);
188 stopPreview();
189
190 // Call derived class implementation of setupTiledMode() so the
191 // filter is modified.
192 setupTiledMode(m_tiledCheck->isSelected() ?
193 TiledMode::BOTH:
194 TiledMode::NONE);
195
196 // Restart the preview.
197 restartPreview();
198}
199
200void FilterWindow::stopPreview()
201{
202 m_preview.stop();
203}
204
205} // namespace app
206