The Battle for Wesnoth  1.17.0-dev
editor_palettes.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2021
3  by David White <dave@whitevine.net>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #define GETTEXT_DOMAIN "wesnoth-editor"
17 
19 
20 #include "gettext.hpp"
21 #include "font/text_formatting.hpp"
22 #include "tooltips.hpp"
23 #include "overlay.hpp"
24 #include "filesystem.hpp"
25 #include "units/types.hpp"
26 
28 
29 namespace editor {
30 
31 template<class Item>
33 {
35  for (gui::widget& b : buttons_) {
36  h.push_back(&b);
37  }
38  return h;
39 }
40 
41 template<class Item>
43 {
44  auto pos = items.erase(items.begin() + i);
45 
46  std::vector<config> groups;
47  const std::vector<item_group>& item_groups = get_groups();
48 
49  for (std::size_t mci = 0; mci < item_groups.size(); ++mci) {
50  std::string groupname = item_groups[mci].name;
51  if (groupname.empty()) {
52  groupname = _("(Unknown Group)");
53  }
54  std::string img = item_groups[mci].icon + "_30";
55  if (mci == active_group_index()) {
56  std::string pressed_img = img + "-pressed.png";
57  if(!filesystem::get_binary_file_location("images", pressed_img).empty()) {
58  img = pressed_img;
59  } else {
60  img += ".png~CS(70,70,0)";
61  }
62  } else {
63  img += ".png";
64  }
65 
66  groups.emplace_back(
67  "label", groupname,
68  "icon", img
69  );
70  }
71 
72  items.insert(pos, groups.begin(), groups.end());
73 }
74 
75 template<class Item>
77 {
78  int decrement = item_width_;
79  if (items_start_ + num_visible_items() == num_items() && num_items() % item_width_ != 0) {
80  decrement = num_items() % item_width_;
81  }
82  if(items_start_ >= decrement) {
83  items_start_ -= decrement;
84  draw();
85  return true;
86  }
87  return false;
88 }
89 
90 template<class Item>
92 {
93  return (items_start_ != 0);
94 }
95 
96 template<class Item>
98 {
99  return (items_start_ + nitems_ + item_width_ <= num_items());
100 }
101 
102 template<class Item>
104 {
105  bool end_reached = (!(items_start_ + nitems_ + item_width_ <= num_items()));
106  bool scrolled = false;
107 
108  // move downwards
109  if(!end_reached) {
110  items_start_ += item_width_;
111  scrolled = true;
112  }
113  else if (items_start_ + nitems_ + (num_items() % item_width_) <= num_items()) {
114  items_start_ += num_items() % item_width_;
115  scrolled = true;
116  }
117  set_dirty(scrolled);
118  draw();
119  return scrolled;
120 }
121 
122 template<class Item>
123 void editor_palette<Item>::set_group(const std::string& id)
124 {
125  assert(!id.empty());
126 
127  bool found = false;
128  for (const item_group& group : groups_) {
129  if (group.id == id) {
130  found = true;
131  std::shared_ptr<gui::button> palette_menu_button = gui_.find_menu_button("menu-editor-terrain");
132  if (palette_menu_button) {
133  //palette_menu_button->set_label(group.name);
134  palette_menu_button->set_tooltip_string(group.name);
135  palette_menu_button->set_overlay(group.icon);
136  }
137  }
138  }
139  assert(found);
140 
141  active_group_ = id;
142 
143  if(active_group().empty()) {
144  ERR_ED << "No items found in group with the id: '" << id << "'." << std::endl;
145  }
146 }
147 
148 template<class Item>
150 {
151  assert(groups_.size() > index);
152  set_group(groups_[index].id);
153 }
154 
155 template<class Item>
157 {
158  assert(!active_group_.empty());
159 
160  for (std::size_t i = 0 ; i < groups_.size(); i++) {
161  if (groups_[i].id == active_group_)
162  return i;
163  }
164 
165  return static_cast<std::size_t>(-1);
166 }
167 
168 template<class Item>
169 void editor_palette<Item>::adjust_size(const SDL_Rect& target)
170 {
171  palette_x_ = target.x;
172  palette_y_ = target.y;
173  const int space_for_items = target.h;
174  const int items_fitting = (space_for_items / item_space_) * item_width_;
175  nitems_ = std::min(items_fitting, nmax_items_);
176  if (num_visible_items() != nitems_) {
177  buttons_.resize(nitems_, gui::tristate_button(gui_.video(), this));
178  }
179  set_location(target);
180  set_dirty(true);
181  gui_.video().clear_help_string(help_handle_);
182  help_handle_ = gui_.video().set_help_string(get_help_string());
183 }
184 
185 template<class Item>
186 void editor_palette<Item>::select_fg_item(const std::string& item_id)
187 {
188  if (selected_fg_item_ != item_id) {
189  selected_fg_item_ = item_id;
190  set_dirty();
191  }
192  gui_.video().clear_help_string(help_handle_);
193  help_handle_ = gui_.video().set_help_string(get_help_string());
194 }
195 
196 template<class Item>
197 void editor_palette<Item>::select_bg_item(const std::string& item_id)
198 {
199  if (selected_bg_item_ != item_id) {
200  selected_bg_item_ = item_id;
201  set_dirty();
202  }
203  gui_.video().clear_help_string(help_handle_);
204  help_handle_ = gui_.video().set_help_string(get_help_string());
205 }
206 
207 template<class Item>
209 {
210  std::swap(selected_fg_item_, selected_bg_item_);
211  select_fg_item(selected_fg_item_);
212  select_bg_item(selected_bg_item_);
213  set_dirty();
214 }
215 
216 template<class Item>
218 {
219  return group_map_[active_group_].size();
220 }
221 
222 template<class Item>
223 bool editor_palette<Item>::is_selected_fg_item(const std::string& id)
224 {
225  return selected_fg_item_ == id;
226 }
227 
228 template<class Item>
229 bool editor_palette<Item>::is_selected_bg_item(const std::string& id)
230 {
231  return selected_bg_item_ == id;
232 }
233 
234 template<class Item>
236 {
237  toolkit_.set_mouseover_overlay(gui_);
238 
239  std::shared_ptr<gui::button> palette_menu_button = gui_.find_menu_button("menu-editor-terrain");
240  if (palette_menu_button) {
241 
242  t_string& name = groups_[active_group_index()].name;
243  std::string& icon = groups_[active_group_index()].icon;
244 
245  palette_menu_button->set_tooltip_string(name);
246  palette_menu_button->set_overlay(icon);
247  }
248 
249  unsigned int y = palette_y_;
250  unsigned int x = palette_x_;
251  int starting = items_start_;
252  int ending = std::min<int>(starting + nitems_, num_items());
253 
254  std::shared_ptr<gui::button> upscroll_button = gui_.find_action_button("upscroll-button-editor");
255  if (upscroll_button)
256  upscroll_button->enable(starting != 0);
257  std::shared_ptr<gui::button> downscroll_button = gui_.find_action_button("downscroll-button-editor");
258  if (downscroll_button)
259  downscroll_button->enable(ending != num_items());
260 
261 
262  int counter = starting;
263  for (int i = 0, size = num_visible_items(); i < size ; ++i) {
264  //TODO check if the conditions still hold for the counter variable
265  //for (unsigned int counter = starting; counter < ending; counter++)
266 
267  gui::tristate_button& tile = buttons_[i];
268 
269  tile.hide(true);
270 
271  if (i >= ending) continue;
272 
273  const std::string item_id = active_group()[counter];
274  //typedef std::map<std::string, Item> item_map_wurscht;
275  typename item_map::iterator item = item_map_.find(item_id);
276 
277  surface item_image(nullptr);
278  std::stringstream tooltip_text;
279  draw_item((*item).second, item_image, tooltip_text);
280 
281  bool is_core = non_core_items_.find(get_id((*item).second)) == non_core_items_.end();
282  if (!is_core) {
283  tooltip_text << " "
285  << _("(non-core)") << "\n"
286  << _("Will not work in game without extra care.")
287  << "</span>";
288  }
289 
290  const int counter_from_zero = counter - starting;
291  SDL_Rect dstrect;
292  dstrect.x = x + (counter_from_zero % item_width_) * item_space_;
293  dstrect.y = y;
294  dstrect.w = item_size_ + 2;
295  dstrect.h = item_size_ + 2;
296 
297  tile.set_location(dstrect);
298  tile.set_tooltip_string(tooltip_text.str());
299  tile.set_item_image(item_image);
300  tile.set_item_id(item_id);
301 
302 // if (get_id((*item).second) == selected_bg_item_
303 // && get_id((*item).second) == selected_fg_item_) {
304 // tile.set_pressed(gui::tristate_button::BOTH);
305 // } else if (get_id((*item).second) == selected_bg_item_) {
306 // tile.set_pressed(gui::tristate_button::RIGHT);
307 // } else if (get_id((*item).second) == selected_fg_item_) {
308 // tile.set_pressed(gui::tristate_button::LEFT);
309 // } else {
310 // tile.set_pressed(gui::tristate_button::NONE);
311 // }
312 
313  if (is_selected_bg_item(get_id(item->second))
314  && is_selected_fg_item(get_id(item->second))) {
316  } else if (is_selected_bg_item(get_id(item->second))) {
318  } else if (is_selected_fg_item(get_id(item->second))) {
320  } else {
322  }
323 
324  tile.set_dirty(true);
325  tile.hide(false);
326  tile.draw();
327 
328  // Adjust location
329  if (counter_from_zero % item_width_ == item_width_ - 1)
330  y += item_space_;
331  ++counter;
332  }
333 }
334 
335 // Force compilation of the following template instantiations
337 template class editor_palette<const unit_type&>;
338 template class editor_palette<overlay>;
339 
340 } // end namespace editor
std::vector< events::sdl_handler * > sdl_handler_vector
Definition: events.hpp:190
virtual sdl_handler_vector handler_members() override
virtual void select_fg_item(const std::string &item_id) override
Select a foreground item.
Stores the info about the groups in a nice format.
virtual void select_bg_item(const std::string &item_id) override
std::size_t active_group_index()
void set_item_id(const std::string &id)
virtual bool scroll_down() override
Scroll the editor-palette down one step if possible.
void set_group(std::size_t index) override
virtual bool scroll_up() override
Scroll the editor-palette up one step if possible.
virtual bool is_selected_bg_item(const std::string &id)
#define h
std::string get_binary_file_location(const std::string &type, const std::string &filename)
Returns a complete path to the actual file of a given type or an empty string if the file isn&#39;t prese...
const std::vector< std::string > items
static std::string _(const char *str)
Definition: gettext.hpp:93
virtual bool can_scroll_up() override
void expand_palette_groups_menu(std::vector< config > &items, int i) override
Menu expanding for palette group list.
#define b
void set_pressed(PRESSED_STATE new_pressed_state)
virtual bool is_selected_fg_item(const std::string &id)
std::string span_color(const color_t &color)
Returns a Pango formatting string using the provided color_t object.
void set_dirty(bool dirty=true)
Definition: widget.cpp:207
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:87
int num_items() override
Return the number of items in the palette.
virtual void hide(bool value=true)
Definition: widget.cpp:152
virtual bool can_scroll_down() override
Manage the empty-palette in the editor.
Definition: action.cpp:30
void swap(config &lhs, config &rhs)
Implement non-member swap function for std::swap (calls config::swap).
Definition: config.cpp:1437
virtual void set_location(const SDL_Rect &rect)
Definition: widget.cpp:75
std::string id
Text to match against addon_info.tags()
Definition: manager.cpp:215
std::size_t i
Definition: function.cpp:941
Declarations for File-IO.
std::size_t index(const std::string &str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition: unicode.cpp:72
void set_tooltip_string(const std::string &str)
Definition: widget.cpp:304
void draw() override
virtual void draw_contents() override
void adjust_size(const SDL_Rect &target) override
Update the size of this widget.
#define ERR_ED
std::string::const_iterator iterator
Definition: tokenizer.hpp:25
HOTKEY_COMMAND get_id(const std::string &command)
returns get_hotkey_command(command).id
void set_item_image(const surface &image)
std::pair< std::string, unsigned > item
Definition: help_impl.hpp:410
const color_t BAD_COLOR