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_PALETTE_VIEW_H_INCLUDED
9#define APP_UI_PALETTE_VIEW_H_INCLUDED
10#pragma once
11
12#include "app/color.h"
13#include "app/context_observer.h"
14#include "app/ui/color_source.h"
15#include "app/ui/marching_ants.h"
16#include "app/ui/tile_source.h"
17#include "doc/palette_picks.h"
18#include "doc/tile.h"
19#include "obs/connection.h"
20#include "obs/signal.h"
21#include "ui/event.h"
22#include "ui/mouse_button.h"
23#include "ui/widget.h"
24
25#include <memory>
26#include <vector>
27
28namespace doc {
29 class Palette;
30 class Tileset;
31}
32
33namespace app {
34
35 enum class PaletteViewModification {
36 CLEAR,
37 DRAGANDDROP,
38 RESIZE,
39 };
40
41 class PaletteView;
42
43 class PaletteViewDelegate {
44 public:
45 virtual ~PaletteViewDelegate() { }
46 virtual bool onIsPaletteViewActive(PaletteView* paletteView) const { return false; }
47 virtual void onPaletteViewIndexChange(int index, ui::MouseButton button) { }
48 virtual void onPaletteViewModification(const doc::Palette* newPalette, PaletteViewModification mod) { }
49 virtual void onPaletteViewChangeSize(PaletteView* paletteView, int boxsize) { }
50 virtual void onPaletteViewPasteColors(
51 const doc::Palette* fromPal, const doc::PalettePicks& from, const doc::PalettePicks& to) { }
52 virtual app::Color onPaletteViewGetForegroundIndex() { return app::Color::fromMask(); }
53 virtual app::Color onPaletteViewGetBackgroundIndex() { return app::Color::fromMask(); }
54 virtual doc::tile_index onPaletteViewGetForegroundTile() { return -1; }
55 virtual doc::tile_index onPaletteViewGetBackgroundTile() { return -1; }
56 virtual void onTilesViewClearTiles(const doc::PalettePicks& tiles) { }
57 virtual void onTilesViewResize(const int newSize) { }
58 virtual void onTilesViewDragAndDrop(doc::Tileset* tileset,
59 doc::PalettePicks& picks,
60 int& currentEntry,
61 const int beforeIndex,
62 const bool isCopy) { }
63 virtual void onTilesViewIndexChange(int index, ui::MouseButton button) { }
64 };
65
66 class AbstractPaletteViewAdapter;
67 class PaletteViewAdapter;
68 class TilesetViewAdapter;
69
70 class PaletteView : public ui::Widget
71 , public MarchingAnts
72 , public IColorSource
73 , public ITileSource
74 , public ContextObserver {
75 friend class PaletteViewAdapter;
76 friend class TilesetViewAdapter;
77 public:
78 enum PaletteViewStyle {
79 SelectOneColor,
80 FgBgColors,
81 FgBgTiles,
82 };
83
84 PaletteView(bool editable, PaletteViewStyle style, PaletteViewDelegate* delegate, int boxsize);
85 ~PaletteView();
86
87 PaletteViewDelegate* delegate() { return m_delegate; }
88
89 bool isEditable() const { return m_editable; }
90 bool isPalette() const { return m_style != FgBgTiles; }
91 bool isTiles() const { return m_style == FgBgTiles; }
92
93 int getColumns() const { return m_columns; }
94 void setColumns(int columns);
95
96 void deselect();
97 void selectColor(int index);
98 void selectExactMatchColor(const app::Color& color);
99 void selectRange(int index1, int index2);
100
101 int getSelectedEntry() const;
102 bool getSelectedRange(int& index1, int& index2) const;
103 void getSelectedEntries(doc::PalettePicks& entries) const;
104 int getSelectedEntriesCount() const;
105 void setSelectedEntries(const doc::PalettePicks& entries);
106
107 doc::Tileset* tileset() const;
108
109 // IColorSource
110 app::Color getColorByPosition(const gfx::Point& pos) override;
111
112 // ITileSource
113 doc::tile_t getTileByPosition(const gfx::Point& pos) override;
114
115 // ContextObserver impl
116 void onActiveSiteChange(const Site& site) override;
117
118 int getBoxSize() const;
119 void setBoxSize(double boxsize);
120
121 void clearSelection();
122 void cutToClipboard();
123 void copyToClipboard();
124 void pasteFromClipboard();
125 void discardClipboardSelection();
126
127 obs::signal<void(ui::Message*)> FocusOrClick;
128
129 protected:
130 bool onProcessMessage(ui::Message* msg) override;
131 void onPaint(ui::PaintEvent& ev) override;
132 void onResize(ui::ResizeEvent& ev) override;
133 void onSizeHint(ui::SizeHintEvent& ev) override;
134 void onDrawMarchingAnts() override;
135
136 private:
137
138 enum class State {
139 WAITING,
140 SELECTING_COLOR,
141 DRAGGING_OUTLINE,
142 RESIZING_PALETTE,
143 };
144
145 struct Hit {
146 enum Part {
147 NONE,
148 COLOR,
149 OUTLINE,
150 RESIZE_HANDLE,
151 POSSIBLE_COLOR,
152 };
153 Part part;
154 int color;
155
156 Hit(Part part, int color = -1) : part(part), color(color) {
157 }
158
159 bool operator==(const Hit& hit) const {
160 return (
161 part == hit.part &&
162 color == hit.color);
163 }
164 bool operator!=(const Hit& hit) const {
165 return !operator==(hit);
166 }
167 };
168
169 void update_scroll(int color);
170 void onAppPaletteChange();
171 gfx::Rect getPaletteEntryBounds(int index) const;
172 Hit hitTest(const gfx::Point& pos);
173 void dropColors(int beforeIndex);
174 void getEntryBoundsAndClip(int i,
175 const doc::PalettePicks& entries,
176 const int outlineWidth,
177 gfx::Rect& box, gfx::Rect& clip) const;
178 bool pickedXY(const doc::PalettePicks& entries, int i, int dx, int dy) const;
179 void updateCopyFlag(ui::Message* msg);
180 void setCursor();
181 void setStatusBar();
182 doc::Palette* currentPalette() const;
183 int findExactIndex(const app::Color& color) const;
184 void setNewPalette(doc::Palette* oldPalette, doc::Palette* newPalette,
185 PaletteViewModification mod);
186 int boxSizePx() const;
187 void updateBorderAndChildSpacing();
188
189 State m_state;
190 bool m_editable;
191 PaletteViewStyle m_style;
192 PaletteViewDelegate* m_delegate;
193 std::unique_ptr<AbstractPaletteViewAdapter> m_adapter;
194 int m_columns;
195 double m_boxsize;
196 int m_currentEntry;
197 int m_rangeAnchor;
198 doc::PalettePicks m_selectedEntries;
199 bool m_isUpdatingColumns;
200 obs::scoped_connection m_palConn;
201 obs::scoped_connection m_csConn;
202 obs::scoped_connection m_sepConn;
203 Hit m_hot;
204 bool m_copy;
205 bool m_withSeparator;
206 };
207
208} // namespace app
209
210#endif
211