1 // Aseprite
2 // Copyright (C) 2001-2018  David Capello
3 //
4 // This program is distributed under the terms of
5 // the End-User License Agreement for Aseprite.
6 
7 #ifndef APP_UI_COLOR_BAR_H_INCLUDED
8 #define APP_UI_COLOR_BAR_H_INCLUDED
9 #pragma once
10 
11 #include "app/color.h"
12 #include "app/context_observer.h"
13 #include "app/doc_observer.h"
14 #include "app/docs_observer.h"
15 #include "app/ui/button_set.h"
16 #include "app/ui/color_button.h"
17 #include "app/ui/input_chain_element.h"
18 #include "app/ui/palette_view.h"
19 #include "base/unique_ptr.h"
20 #include "doc/pixel_format.h"
21 #include "doc/sort_palette.h"
22 #include "obs/connection.h"
23 #include "obs/signal.h"
24 #include "ui/box.h"
25 #include "ui/button.h"
26 #include "ui/splitter.h"
27 #include "ui/tooltips.h"
28 #include "ui/view.h"
29 
30 namespace ui {
31   class TooltipManager;
32 }
33 
34 namespace app {
35   class ColorButton;
36   class ColorSpectrum;
37   class ColorTintShadeTone;
38   class ColorWheel;
39   class CommandExecutionEvent;
40   class PaletteIndexChangeEvent;
41   class PalettePopup;
42   class PalettesLoader;
43 
44   class ColorBar : public ui::Box
45                  , public PaletteViewDelegate
46                  , public ContextObserver
47                  , public DocObserver
48                  , public InputChainElement {
49     static ColorBar* m_instance;
50   public:
51     enum class ColorSelector {
52       NONE,
53       SPECTRUM,
54       RGB_WHEEL,
55       RYB_WHEEL,
56       TINT_SHADE_TONE,
57       NORMAL_MAP_WHEEL,
58     };
59 
instance()60     static ColorBar* instance() { return m_instance; }
61 
62     ColorBar(int align);
63     ~ColorBar();
64 
65     void setPixelFormat(PixelFormat pixelFormat);
66 
67     app::Color getFgColor() const;
68     app::Color getBgColor() const;
69     void setFgColor(const app::Color& color);
70     void setBgColor(const app::Color& color);
71 
72     PaletteView* getPaletteView();
73 
74     ColorSelector getColorSelector() const;
75     void setColorSelector(ColorSelector selector);
76 
77     // Used by the Palette Editor command to change the status of button
78     // when the visibility of the dialog changes.
79     bool inEditMode() const;
80     void setEditMode(bool state);
81 
fgColorButton()82     ColorButton* fgColorButton() { return &m_fgColor; }
bgColorButton()83     ColorButton* bgColorButton() { return &m_bgColor; }
84 
85     // ContextObserver impl
86     void onActiveSiteChange(const Site& site) override;
87 
88     // DocObserver impl
89     void onGeneralUpdate(DocEvent& ev) override;
90 
91     // InputChainElement impl
92     void onNewInputPriority(InputChainElement* element,
93                             const ui::Message* msg) override;
94     bool onCanCut(Context* ctx) override;
95     bool onCanCopy(Context* ctx) override;
96     bool onCanPaste(Context* ctx) override;
97     bool onCanClear(Context* ctx) override;
98     bool onCut(Context* ctx) override;
99     bool onCopy(Context* ctx) override;
100     bool onPaste(Context* ctx) override;
101     bool onClear(Context* ctx) override;
102     void onCancel(Context* ctx) override;
103 
104     obs::signal<void()> ChangeSelection;
105 
106   protected:
107     void onAppPaletteChange();
108     void onFocusPaletteView(ui::Message* msg);
109     void onBeforeExecuteCommand(CommandExecutionEvent& ev);
110     void onAfterExecuteCommand(CommandExecutionEvent& ev);
111     void onPaletteButtonClick();
112     void onRemapButtonClick();
113     void onPaletteIndexChange(PaletteIndexChangeEvent& ev);
114     void onFgColorChangeFromPreferences();
115     void onBgColorChangeFromPreferences();
116     void onFgColorButtonBeforeChange(app::Color& color);
117     void onFgColorButtonChange(const app::Color& color);
118     void onBgColorButtonChange(const app::Color& color);
119     void onColorButtonChange(const app::Color& color);
120     void onPickSpectrum(const app::Color& color, ui::MouseButtons buttons);
121     void onReverseColors();
122     void onSortBy(doc::SortPaletteBy channel);
123     void onGradient();
124     void onFixWarningClick(ColorButton* colorButton, ui::Button* warningIcon);
125     void onTimerTick();
126     void setAscending(bool ascending);
127 
128     // PaletteViewDelegate impl
129     void onPaletteViewIndexChange(int index, ui::MouseButtons buttons) override;
130     void onPaletteViewModification(const doc::Palette* newPalette, PaletteViewModification mod) override;
131     void onPaletteViewChangeSize(int boxsize) override;
132     void onPaletteViewPasteColors(const Palette* fromPal, const doc::PalettePicks& from, const doc::PalettePicks& to) override;
133     app::Color onPaletteViewGetForegroundIndex() override;
134     app::Color onPaletteViewGetBackgroundIndex() override;
135 
136   private:
137     void showRemap();
138     void hideRemap();
139     void setPalette(const doc::Palette* newPalette, const std::string& actionText);
140     void setTransparentIndex(int index);
141     void updateWarningIcon(const app::Color& color, ui::Button* warningIcon);
142     int setPaletteEntry(const app::Color& color);
143     void updateCurrentSpritePalette(const char* operationName);
144     void setupTooltips(ui::TooltipManager* tooltipManager);
145     void registerCommands();
146     void showPaletteSortOptions();
147     void showPalettePresets();
148     void showPaletteOptions();
149     static void fixColorIndex(ColorButton& color);
150 
151     class ScrollableView : public ui::View {
152     public:
153       ScrollableView();
154     protected:
155       void onInitTheme(ui::InitThemeEvent& ev) override;
156     };
157 
158     class WarningIcon;
159 
160     ui::TooltipManager m_tooltips;
161     ButtonSet m_buttons;
162     base::UniquePtr<PalettePopup> m_palettePopup;
163     ui::Splitter m_splitter;
164     ui::VBox m_palettePlaceholder;
165     ui::VBox m_selectorPlaceholder;
166     ScrollableView m_scrollableView;
167     PaletteView m_paletteView;
168     ui::Button m_remapButton;
169     ColorSelector m_selector;
170     ColorTintShadeTone* m_tintShadeTone;
171     ColorSpectrum* m_spectrum;
172     ColorWheel* m_wheel;
173     ColorButton m_fgColor;
174     ColorButton m_bgColor;
175     WarningIcon* m_fgWarningIcon;
176     WarningIcon* m_bgWarningIcon;
177 
178     // True when the user clicks the PaletteView so we're changing the
179     // color from the palette view.
180     bool m_fromPalView;
181 
182     // If m_syncingWithPref is true it means that the eyedropper was
183     // used to change the color.
184     bool m_fromPref;
185 
186     bool m_fromFgButton;
187     bool m_fromBgButton;
188 
189     base::UniquePtr<doc::Palette> m_oldPalette;
190     Doc* m_lastDocument;
191     bool m_ascending;
192     obs::scoped_connection m_beforeCmdConn;
193     obs::scoped_connection m_afterCmdConn;
194     obs::scoped_connection m_fgConn;
195     obs::scoped_connection m_bgConn;
196     obs::scoped_connection m_appPalChangeConn;
197     ui::MouseButtons m_lastButtons;
198 
199     // True if we the editing mode is on.
200     bool m_editMode;
201 
202     // Timer to redraw editors after a palette change.
203     ui::Timer m_redrawTimer;
204     bool m_redrawAll;
205 
206     // True if a palette change must be implant in the UndoHistory
207     // (e.g. when two or more changes in the palette are made in a
208     // very short time).
209     bool m_implantChange;
210 
211     // True if the App::PaletteChange signal is generated by this same
212     // ColorBar.
213     bool m_selfPalChange;
214   };
215 
216   class DisableColorBarEditMode {
217   public:
DisableColorBarEditMode()218     DisableColorBarEditMode()
219       : m_colorBar(ColorBar::instance())
220       , m_oldMode(m_colorBar->inEditMode()) {
221       if (m_oldMode)
222         m_colorBar->setEditMode(false);
223     }
~DisableColorBarEditMode()224     ~DisableColorBarEditMode() {
225       if (m_oldMode)
226         m_colorBar->setEditMode(true);
227     }
228   private:
229     ColorBar* m_colorBar;
230     bool m_oldMode;
231   };
232 
233 } // namespace app
234 
235 #endif
236