1// Aseprite
2// Copyright (C) 2018-2021 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#ifndef APP_UI_COLOR_BAR_H_INCLUDED
9#define APP_UI_COLOR_BAR_H_INCLUDED
10#pragma once
11
12#include "app/color.h"
13#include "app/context_observer.h"
14#include "app/doc_observer.h"
15#include "app/docs_observer.h"
16#include "app/tilemap_mode.h"
17#include "app/tileset_mode.h"
18#include "app/ui/button_set.h"
19#include "app/ui/color_button.h"
20#include "app/ui/input_chain_element.h"
21#include "app/ui/palette_view.h"
22#include "app/ui/tile_button.h"
23#include "doc/object_id.h"
24#include "doc/palette_gradient_type.h"
25#include "doc/pixel_format.h"
26#include "doc/sort_palette.h"
27#include "doc/tileset.h"
28#include "obs/connection.h"
29#include "obs/signal.h"
30#include "ui/box.h"
31#include "ui/button.h"
32#include "ui/splitter.h"
33#include "ui/view.h"
34
35namespace ui {
36 class TooltipManager;
37}
38
39namespace app {
40 class ColorButton;
41 class ColorSpectrum;
42 class ColorTintShadeTone;
43 class ColorWheel;
44 class CommandExecutionEvent;
45 class PaletteIndexChangeEvent;
46 class PalettePopup;
47 class PalettesLoader;
48
49 class ColorBar : public ui::Box
50 , public PaletteViewDelegate
51 , public ContextObserver
52 , public DocObserver
53 , public InputChainElement {
54 static ColorBar* m_instance;
55 public:
56 enum class ColorSelector {
57 NONE,
58 SPECTRUM,
59 RGB_WHEEL,
60 RYB_WHEEL,
61 TINT_SHADE_TONE,
62 NORMAL_MAP_WHEEL,
63 };
64
65 static ColorBar* instance() { return m_instance; }
66
67 ColorBar(int align, ui::TooltipManager* tooltipManager);
68 ~ColorBar();
69
70 void setPixelFormat(PixelFormat pixelFormat);
71
72 app::Color getFgColor() const;
73 app::Color getBgColor() const;
74 void setFgColor(const app::Color& color);
75 void setBgColor(const app::Color& color);
76
77 doc::tile_index getFgTile() const;
78 doc::tile_index getBgTile() const;
79 void setFgTile(doc::tile_t tile);
80 void setBgTile(doc::tile_t tile);
81
82 PaletteView* getPaletteView() { return &m_paletteView; }
83 PaletteView* getTilesView() { return &m_tilesView; }
84
85 ColorSelector getColorSelector() const;
86 void setColorSelector(ColorSelector selector);
87
88 // Used by the Palette Editor command to change the status of button
89 // when the visibility of the dialog changes.
90 bool inEditMode() const;
91 void setEditMode(bool state);
92
93 TilemapMode tilemapMode() const;
94 void setTilemapMode(TilemapMode mode);
95
96 TilesetMode tilesetMode() const;
97 void setTilesetMode(const TilesetMode mode);
98
99 ColorButton* fgColorButton() { return &m_fgColor; }
100 ColorButton* bgColorButton() { return &m_bgColor; }
101
102 // ContextObserver impl
103 void onActiveSiteChange(const Site& site) override;
104
105 // DocObserver impl
106 void onGeneralUpdate(DocEvent& ev) override;
107 void onTilesetChanged(DocEvent& ev) override;
108
109 // InputChainElement impl
110 void onNewInputPriority(InputChainElement* element,
111 const ui::Message* msg) override;
112 bool onCanCut(Context* ctx) override;
113 bool onCanCopy(Context* ctx) override;
114 bool onCanPaste(Context* ctx) override;
115 bool onCanClear(Context* ctx) override;
116 bool onCut(Context* ctx) override;
117 bool onCopy(Context* ctx) override;
118 bool onPaste(Context* ctx) override;
119 bool onClear(Context* ctx) override;
120 void onCancel(Context* ctx) override;
121
122 obs::signal<void()> ChangeSelection;
123
124 protected:
125 void onSizeHint(ui::SizeHintEvent& ev) override;
126 void onAppPaletteChange();
127 void onFocusPaletteView(ui::Message* msg);
128 void onFocusTilesView(ui::Message* msg);
129 void onBeforeExecuteCommand(CommandExecutionEvent& ev);
130 void onAfterExecuteCommand(CommandExecutionEvent& ev);
131 void onSwitchPalEditMode();
132 void onPaletteButtonClick();
133 void onTilesButtonClick();
134 void onTilesButtonRightClick();
135 void onTilesetModeButtonClick();
136 void onTilesetOptionsClick();
137 void onRemapPalButtonClick();
138 void onRemapTilesButtonClick();
139 void onPaletteIndexChange(PaletteIndexChangeEvent& ev);
140 void onFgColorChangeFromPreferences();
141 void onBgColorChangeFromPreferences();
142 void onFgTileChangeFromPreferences();
143 void onBgTileChangeFromPreferences();
144 void onFgColorButtonBeforeChange(app::Color& color);
145 void onFgColorButtonChange(const app::Color& color);
146 void onBgColorButtonChange(const app::Color& color);
147 void onColorButtonChange(const app::Color& color);
148 void onFgTileButtonChange(doc::tile_t tile);
149 void onBgTileButtonChange(doc::tile_t tile);
150 void onPickSpectrum(const app::Color& color, ui::MouseButton button);
151 void onReverseColors();
152 void onSortBy(doc::SortPaletteBy channel);
153 void onGradient(GradientType gradientType);
154 void onFixWarningClick(ColorButton* colorButton, ui::Button* warningIcon);
155 void onTimerTick();
156 void setAscending(bool ascending);
157
158 // PaletteViewDelegate impl
159 bool onIsPaletteViewActive(PaletteView* paletteView) const override;
160 void onPaletteViewIndexChange(int index, ui::MouseButton button) override;
161 void onPaletteViewModification(const doc::Palette* newPalette, PaletteViewModification mod) override;
162 void onPaletteViewChangeSize(PaletteView* paletteView, int boxsize) override;
163 void onPaletteViewPasteColors(const Palette* fromPal, const doc::PalettePicks& from, const doc::PalettePicks& to) override;
164 app::Color onPaletteViewGetForegroundIndex() override;
165 app::Color onPaletteViewGetBackgroundIndex() override;
166 doc::tile_index onPaletteViewGetForegroundTile() override;
167 doc::tile_index onPaletteViewGetBackgroundTile() override;
168 void onTilesViewClearTiles(const doc::PalettePicks& picks) override;
169 void onTilesViewResize(const int newSize) override;
170 void onTilesViewDragAndDrop(doc::Tileset* tileset,
171 doc::PalettePicks& picks,
172 int& currentEntry,
173 const int beforeIndex,
174 const bool isCopy) override;
175 void onTilesViewIndexChange(int index, ui::MouseButton button) override;
176
177 private:
178 void showRemapPal();
179 void showRemapTiles();
180 void hideRemapPal();
181 void hideRemapTiles();
182 void setPalette(const doc::Palette* newPalette, const std::string& actionText);
183 void setTransparentIndex(int index);
184 void updateWarningIcon(const app::Color& color, ui::Button* warningIcon);
185 int setPaletteEntry(const app::Color& color);
186 void updateCurrentSpritePalette(const char* operationName);
187 void setupTooltips(ui::TooltipManager* tooltipManager);
188 void registerCommands();
189 void showPaletteSortOptions();
190 void showPalettePresets();
191 void showPaletteOptions();
192 bool canEditTiles() const;
193 void updateFromTilemapMode();
194 static void fixColorIndex(ColorButton& color);
195
196 class ScrollableView : public ui::View {
197 public:
198 ScrollableView();
199 protected:
200 void onInitTheme(ui::InitThemeEvent& ev) override;
201 };
202
203 class WarningIcon;
204
205 ui::HBox m_palHBox;
206 ui::HBox m_tilesHBox;
207 ButtonSet m_editPal;
208 ButtonSet m_buttons;
209 ButtonSet m_tilesButton;
210 ButtonSet m_tilesetModeButtons;
211 std::unique_ptr<PalettePopup> m_palettePopup;
212 ui::Splitter m_splitter;
213 ui::VBox m_palettePlaceholder;
214 ui::VBox m_selectorPlaceholder;
215 ui::Splitter m_splitterPalTil;
216 ScrollableView m_scrollablePalView;
217 ScrollableView m_scrollableTilesView;
218 PaletteView m_paletteView;
219 PaletteView m_tilesView;
220 ui::Button m_remapPalButton;
221 ui::Button m_remapTilesButton;
222 ui::VBox m_colorHelpers;
223 ui::HBox m_tilesHelpers;
224 ColorSelector m_selector;
225 ColorTintShadeTone* m_tintShadeTone;
226 ColorSpectrum* m_spectrum;
227 ColorWheel* m_wheel;
228 ColorButton m_fgColor;
229 ColorButton m_bgColor;
230 WarningIcon* m_fgWarningIcon;
231 WarningIcon* m_bgWarningIcon;
232 TileButton m_fgTile;
233 TileButton m_bgTile;
234
235 // True when the user clicks the PaletteView so we're changing the
236 // color from the palette view.
237 bool m_fromPalView;
238
239 // If m_syncingWithPref is true it means that the eyedropper was
240 // used to change the color.
241 bool m_fromPref;
242
243 bool m_fromFgButton;
244 bool m_fromBgButton;
245
246 std::unique_ptr<doc::Palette> m_oldPalette;
247 std::unique_ptr<doc::Tileset> m_oldTileset;
248 Doc* m_lastDocument;
249 doc::ObjectId m_lastTilesetId;
250 bool m_ascending;
251 obs::scoped_connection m_beforeCmdConn;
252 obs::scoped_connection m_afterCmdConn;
253 obs::scoped_connection m_fgConn;
254 obs::scoped_connection m_bgConn;
255 obs::scoped_connection m_fgTileConn;
256 obs::scoped_connection m_bgTileConn;
257 obs::scoped_connection m_sepConn;
258 obs::scoped_connection m_appPalChangeConn;
259 ui::MouseButton m_lastButton;
260
261 // True if the editing mode is on.
262 bool m_editMode;
263
264 // True if we should be putting/setting tiles.
265 TilemapMode m_tilemapMode;
266 TilesetMode m_tilesetMode;
267
268 // Timer to redraw editors after a palette change.
269 ui::Timer m_redrawTimer;
270 bool m_redrawAll;
271
272 // True if a palette change must be implant in the UndoHistory
273 // (e.g. when two or more changes in the palette are made in a
274 // very short time).
275 bool m_implantChange;
276
277 // True if the App::PaletteChange signal is generated by this same
278 // ColorBar.
279 bool m_selfPalChange;
280
281 double m_splitterPalTilPos;
282 };
283
284 class DisableColorBarEditMode {
285 public:
286 DisableColorBarEditMode()
287 : m_colorBar(ColorBar::instance())
288 , m_oldMode(m_colorBar->inEditMode()) {
289 if (m_oldMode)
290 m_colorBar->setEditMode(false);
291 }
292 ~DisableColorBarEditMode() {
293 if (m_oldMode)
294 m_colorBar->setEditMode(true);
295 }
296 private:
297 ColorBar* m_colorBar;
298 bool m_oldMode;
299 };
300
301} // namespace app
302
303#endif
304