| 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 |  | 
|---|
| 28 | namespace doc { | 
|---|
| 29 | class Palette; | 
|---|
| 30 | class Tileset; | 
|---|
| 31 | } | 
|---|
| 32 |  | 
|---|
| 33 | namespace 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 |  | 
|---|