1 | // Aseprite |
2 | // Copyright (C) 2019-2022 Igara Studio S.A. |
3 | // Copyright (C) 2016-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/ui/layer_frame_comboboxes.h" |
13 | |
14 | #include "app/i18n/strings.h" |
15 | #include "app/restore_visible_layers.h" |
16 | #include "app/site.h" |
17 | #include "doc/anidir.h" |
18 | #include "doc/layer.h" |
19 | #include "doc/selected_frames.h" |
20 | #include "doc/selected_layers.h" |
21 | #include "doc/slice.h" |
22 | #include "doc/sprite.h" |
23 | #include "doc/tag.h" |
24 | #include "ui/combobox.h" |
25 | |
26 | namespace app { |
27 | |
28 | const char* kWholeCanvas = "" ; |
29 | const char* kAllLayers = "" ; |
30 | const char* kAllFrames = "" ; |
31 | const char* kSelectedCanvas = "**selected-canvas**" ; |
32 | const char* kSelectedLayers = "**selected-layers**" ; |
33 | const char* kSelectedFrames = "**selected-frames**" ; |
34 | |
35 | SliceListItem::SliceListItem(doc::Slice* slice) |
36 | : ListItem("Slice: " + slice->name()) |
37 | , m_slice(slice) |
38 | { |
39 | setValue(m_slice->name()); |
40 | } |
41 | |
42 | LayerListItem::LayerListItem(doc::Layer* layer) |
43 | : ListItem(buildName(layer)) |
44 | , m_layer(layer) |
45 | { |
46 | setValue(layer->name()); |
47 | } |
48 | |
49 | // static |
50 | std::string LayerListItem::buildName(const doc::Layer* layer) |
51 | { |
52 | bool isGroup = layer->isGroup(); |
53 | std::string name; |
54 | while (layer != layer->sprite()->root()) { |
55 | if (!name.empty()) |
56 | name.insert(0, " > " ); |
57 | name.insert(0, layer->name()); |
58 | layer = layer->parent(); |
59 | } |
60 | const std::string namePrefix = |
61 | (isGroup ? Strings::layer_combo_group() : |
62 | Strings::layer_combo_layer()) + " " ; |
63 | name.insert(0, namePrefix); |
64 | return name; |
65 | } |
66 | |
67 | FrameListItem::FrameListItem(doc::Tag* tag) |
68 | : ListItem(Strings::frame_combo_tag() + " " + tag->name()) |
69 | , m_tag(tag) |
70 | { |
71 | setValue(m_tag->name()); |
72 | } |
73 | |
74 | void fill_area_combobox(const doc::Sprite* sprite, ui::ComboBox* area, const std::string& defArea) |
75 | { |
76 | int i = area->addItem("Canvas" ); |
77 | dynamic_cast<ui::ListItem*>(area->getItem(i))->setValue(kWholeCanvas); |
78 | |
79 | i = area->addItem("Selection" ); |
80 | dynamic_cast<ui::ListItem*>(area->getItem(i))->setValue(kSelectedCanvas); |
81 | if (defArea == kSelectedCanvas) |
82 | area->setSelectedItemIndex(i); |
83 | |
84 | for (auto slice : sprite->slices()) { |
85 | if (slice->name().empty()) |
86 | continue; |
87 | |
88 | i = area->addItem(new SliceListItem(slice)); |
89 | if (defArea == slice->name()) |
90 | area->setSelectedItemIndex(i); |
91 | } |
92 | } |
93 | |
94 | void fill_layers_combobox(const doc::Sprite* sprite, ui::ComboBox* layers, const std::string& defLayer, const int defLayerIndex) |
95 | { |
96 | int i = layers->addItem(Strings::layer_combo_visible_layers()); |
97 | dynamic_cast<ui::ListItem*>(layers->getItem(i))->setValue(kAllLayers); |
98 | |
99 | i = layers->addItem(Strings::layer_combo_selected_layers()); |
100 | dynamic_cast<ui::ListItem*>(layers->getItem(i))->setValue(kSelectedLayers); |
101 | if (defLayer == kSelectedLayers) |
102 | layers->setSelectedItemIndex(i); |
103 | |
104 | assert(layers->getItemCount() == kLayersComboboxExtraInitialItems); |
105 | static_assert(kLayersComboboxExtraInitialItems == 2, |
106 | "Update kLayersComboboxExtraInitialItems value to match the number of initial items in layers combobox" ); |
107 | |
108 | doc::LayerList layersList = sprite->allLayers(); |
109 | for (auto it=layersList.rbegin(), end=layersList.rend(); it!=end; ++it) { |
110 | doc::Layer* layer = *it; |
111 | i = layers->addItem(new LayerListItem(layer)); |
112 | if (defLayer == layer->name() && (defLayerIndex == -1 || |
113 | defLayerIndex == i-kLayersComboboxExtraInitialItems)) |
114 | layers->setSelectedItemIndex(i); |
115 | } |
116 | } |
117 | |
118 | void fill_frames_combobox(const doc::Sprite* sprite, ui::ComboBox* frames, const std::string& defFrame) |
119 | { |
120 | int i = frames->addItem(Strings::frame_combo_all_frames()); |
121 | dynamic_cast<ui::ListItem*>(frames->getItem(i))->setValue(kAllFrames); |
122 | |
123 | i = frames->addItem(Strings::frame_combo_selected_frames()); |
124 | dynamic_cast<ui::ListItem*>(frames->getItem(i))->setValue(kSelectedFrames); |
125 | if (defFrame == kSelectedFrames) |
126 | frames->setSelectedItemIndex(i); |
127 | |
128 | for (auto tag : sprite->tags()) { |
129 | // Don't allow to select empty frame tags |
130 | if (tag->name().empty()) |
131 | continue; |
132 | |
133 | i = frames->addItem(new FrameListItem(tag)); |
134 | if (defFrame == tag->name()) |
135 | frames->setSelectedItemIndex(i); |
136 | } |
137 | } |
138 | |
139 | void fill_anidir_combobox(ui::ComboBox* anidir, doc::AniDir defAnidir) |
140 | { |
141 | static_assert( |
142 | int(doc::AniDir::FORWARD) == 0 && |
143 | int(doc::AniDir::REVERSE) == 1 && |
144 | int(doc::AniDir::PING_PONG) == 2, "doc::AniDir has changed" ); |
145 | |
146 | anidir->addItem(Strings::anidir_combo_forward()); |
147 | anidir->addItem(Strings::anidir_combo_reverse()); |
148 | anidir->addItem(Strings::anidir_combo_ping_pong()); |
149 | anidir->setSelectedItemIndex(int(defAnidir)); |
150 | } |
151 | |
152 | void calculate_visible_layers(const Site& site, |
153 | const std::string& layersValue, |
154 | const int layersIndex, |
155 | RestoreVisibleLayers& layersVisibility) |
156 | { |
157 | if (layersValue == kSelectedLayers) { |
158 | if (!site.selectedLayers().empty()) { |
159 | layersVisibility.showSelectedLayers( |
160 | const_cast<Sprite*>(site.sprite()), |
161 | site.selectedLayers()); |
162 | } |
163 | else { |
164 | layersVisibility.showLayer(const_cast<Layer*>(site.layer())); |
165 | } |
166 | } |
167 | else if (layersValue != kAllLayers) { |
168 | int i = site.sprite()->allLayersCount(); |
169 | // TODO add a getLayerByName |
170 | for (doc::Layer* layer : site.sprite()->allLayers()) { |
171 | i--; |
172 | if (layer->name() == layersValue && (layersIndex == -1 || |
173 | layersIndex == i)) { |
174 | layersVisibility.showLayer(layer); |
175 | break; |
176 | } |
177 | } |
178 | } |
179 | } |
180 | |
181 | doc::Tag* calculate_selected_frames(const Site& site, |
182 | const std::string& framesValue, |
183 | doc::SelectedFrames& selFrames) |
184 | { |
185 | doc::Tag* tag = nullptr; |
186 | |
187 | if (framesValue == kSelectedFrames) { |
188 | if (!site.selectedFrames().empty()) { |
189 | selFrames = site.selectedFrames(); |
190 | } |
191 | else { |
192 | selFrames.insert(site.frame(), site.frame()); |
193 | } |
194 | } |
195 | else if (framesValue != kAllFrames) { |
196 | tag = site.sprite()->tags().getByName(framesValue); |
197 | if (tag) |
198 | selFrames.insert(tag->fromFrame(), |
199 | tag->toFrame()); |
200 | else |
201 | selFrames.insert(0, site.sprite()->lastFrame()); |
202 | } |
203 | else |
204 | selFrames.insert(0, site.sprite()->lastFrame()); |
205 | |
206 | return tag; |
207 | } |
208 | |
209 | } // namespace app |
210 | |