The Battle for Wesnoth  1.13.10+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
location_palette.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2017 by David White <dave@whitevine.net>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #define GETTEXT_DOMAIN "wesnoth-editor"
16 
18 
19 #include "gettext.hpp"
20 #include "font/marked-up_text.hpp"
21 #include "font/standard_colors.hpp"
22 #include "tooltips.hpp"
23 
26 
27 #include "formula/string_utils.hpp"
29 {
30 public:
31  struct state_t {
33  : selected(false)
34  , mouseover(false)
35  {}
36  bool selected;
37  bool mouseover;
38  friend bool operator==(state_t r, state_t l)
39  {
40  return r.selected == l.selected && r.mouseover == l.mouseover;
41  }
42 
43  };
45  : gui::widget(video, true)
46  , parent_(parent)
47  {
48  }
49 
50  void draw_contents() override
51  {
52  if (state_.mouseover) {
53  sdl::fill_rectangle(location(), {200, 200, 200, 26});
54  }
55  if (state_.selected) {
56  sdl::draw_rectangle(location(), {255, 255, 255, 255});
57  }
58  font::draw_text(&video(), location(), 16, font::NORMAL_COLOR, desc_.empty() ? id_ : desc_, location().x + 2, location().y, 0);
59  }
60 
61  //TODO move to widget
62  bool hit(int x, int y) const
63  {
64  return sdl::point_in_rect(x, y, location());
65  }
66 
67  void mouse_up(SDL_MouseButtonEvent const &e)
68  {
69  if (!(hit(e.x, e.y)))
70  return;
71  if (e.button == SDL_BUTTON_LEFT) {
73  }
74  if (e.button == SDL_BUTTON_RIGHT) {
75  //TODO: add a context menu with the follwing options:
76  // 1) 'copy it to clipboard'
77  // 2) 'jump to item'
78  // 3) 'delete item'.
79  }
80  }
81 
82  void handle_event(const SDL_Event& e) override
83  {
85 
86  if (hidden() || !enabled() || mouse_locked())
87  return;
88 
89  state_t start_state = state_;
90 
91  switch (e.type) {
92  case SDL_MOUSEBUTTONUP:
93  mouse_up(e.button);
94  break;
95  case SDL_MOUSEMOTION:
96  state_.mouseover = hit(e.motion.x, e.motion.y);
97  break;
98  default:
99  return;
100  }
101 
102  if (!(start_state == state_))
103  set_dirty(true);
104  }
105 
106  void set_item_id(const std::string& id)
107  {
108  id_ = id;
109  bool is_number = std::find_if(id.begin(), id.end(), [](char c) { return !std::isdigit(c); }) == id.end();
110  if (is_number) {
111  desc_ = vgettext("Player $side_num", utils::string_map{ {"side_num", id} });
112  }
113  else {
114  desc_ = "";
115  }
116  }
118  {
120  }
121  void draw() override { gui::widget::draw(); }
122 private:
127 };
128 
130 {
131 public:
132  location_palette_button(CVideo& video, const SDL_Rect& location, const std::string& text, const std::function<void (void)>& callback)
133  : gui::button(video, text)
134  , callback_(callback)
135  {
136  this->set_location(location.x, location.y);
137  this->hide(false);
138  }
139 protected:
140  virtual void mouse_up(const SDL_MouseButtonEvent& e) override
141  {
143  if (callback_) {
144  if (this->pressed()) {
145  callback_();
146  }
147  }
148  }
149  std::function<void (void)> callback_;
150 
151 };
152 namespace editor {
154  editor_toolkit &toolkit)
155  : common_palette(gui.video())
156  , item_size_(20)
157  //TODO avoid magic number
158  , item_space_(20 + 3)
159  , palette_y_(0)
160  , palette_x_(0)
161  , items_start_(0)
162  , selected_item_()
163  , items_()
164  , toolkit_(toolkit)
165  , buttons_()
166  , button_add_()
167  , button_delete_()
168  , button_goto_()
169  , help_handle_(-1)
170  , disp_(gui)
171  {
172  for (int i = 1; i < 10; ++i) {
173  items_.push_back(std::to_string(i));
174  }
175  selected_item_ = items_[0];
176  }
177 
179 {
181  for (gui::widget& b : buttons_) {
182  h.push_back(&b);
183  }
184  if (button_add_) { h.push_back(button_add_.get()); }
185  if (button_delete_) { h.push_back(button_delete_.get()); }
186  if (button_goto_) { h.push_back(button_goto_.get()); }
187  return h;
188 }
189 
190 void location_palette::hide(bool hidden)
191 {
192  widget::hide(hidden);
193 
195 
196  std::shared_ptr<gui::button> palette_menu_button = disp_.find_menu_button("menu-editor-terrain");
197  palette_menu_button->set_overlay("");
198  palette_menu_button->enable(false);
199 
200  for(auto& w : handler_members()) {
201  static_cast<gui::widget&>(*w).hide(hidden);
202  }
203 }
204 
206 {
207  int decrement = 1;
208  if(items_start_ >= decrement) {
209  items_start_ -= decrement;
210  draw();
211  return true;
212  }
213  return false;
214 }
216 {
217  return (items_start_ != 0);
218 }
219 
221 {
222  return (items_start_ + num_visible_items() + 1 <= num_items());
223 }
224 
226 {
227  bool end_reached = (!(items_start_ + num_visible_items() + 1 <= num_items()));
228  bool scrolled = false;
229 
230  // move downwards
231  if(!end_reached) {
232  items_start_ += 1;
233  scrolled = true;
234  set_dirty(true);
235  }
236  draw();
237  return scrolled;
238 }
239 
240 void location_palette::adjust_size(const SDL_Rect& target)
241 {
242  palette_x_ = target.x;
243  palette_y_ = target.y;
244  const int button_height = 22;
245  const int button_y = 30;
246  int bottom = target.y + target.h;
247  if (!button_goto_) {
248  button_goto_.reset(new location_palette_button(video(), SDL_Rect{ target.x , bottom -= button_y, target.w - 10, button_height }, _("Go To"), [this]() {
249  //static_cast<mouse_action_starting_position&>(toolkit_.get_mouse_action()). ??
251  if (pos.valid()) {
253  }
254  }));
255  button_add_.reset(new location_palette_button(video(), SDL_Rect{ target.x , bottom -= button_y, target.w - 10, button_height }, _("Add"), [this]() {
256  std::string newid;
257  if (gui2::dialogs::edit_text::execute(_("New Location Identifer"), "", newid, video())) {
258  add_item(newid);
259  }
260  }));
261  button_delete_.reset(new location_palette_button(video(), SDL_Rect{ target.x , bottom -= button_y, target.w - 10, button_height }, _("Delete"), nullptr));
262  }
263  else {
264  button_goto_->set_location(SDL_Rect{ target.x , bottom -= button_y, target.w - 10, button_height });
265  button_add_->set_location(SDL_Rect{ target.x , bottom -= button_y, target.w - 10, button_height });
266  button_delete_->set_location(SDL_Rect{ target.x , bottom -= button_y, target.w - 10, button_height });
267  }
268 
269  const int space_for_items = bottom - target.y;
270  const int items_fitting = space_for_items / item_space_;
271  if (num_visible_items() != items_fitting) {
272  location_palette_item lpi(disp_.video(), *this);
273  //Why does this need a pointer to a non-const as second paraeter?
274  //TODO: we should write our own ptr_vector class, boost::ptr_vector has a lot of flaws.
275  buttons_.resize(items_fitting, &lpi);
276  }
277 
278  set_location(target);
279  set_dirty(true);
282 }
283 
285 {
286  if (selected_item_ != item_id) {
287  selected_item_ = item_id;
288  set_dirty();
289  }
292 }
293 
295 {
296  return items_.size();
297 }
299 {
300  return buttons_.size();
301 }
302 
304 {
305  return selected_item_ == id;
306 }
307 
309 {
311  int y = palette_y_;
312  const int x = palette_x_;
313  const int starting = items_start_;
314  int ending = std::min<int>(starting + num_visible_items(), num_items());
315  std::shared_ptr<gui::button> upscroll_button = disp_.find_action_button("upscroll-button-editor");
316  if (upscroll_button)
317  upscroll_button->enable(starting != 0);
318  std::shared_ptr<gui::button> downscroll_button = disp_.find_action_button("downscroll-button-editor");
319  if (downscroll_button)
320  downscroll_button->enable(ending != num_items());
321 
322  if (button_goto_) {
323  button_goto_->set_dirty(true);
324  }
325  if (button_add_) {
326  button_add_->set_dirty(true);
327  }
328  if (button_delete_) {
329  button_delete_->set_dirty(true);
330  }
331  for (int i = 0, size = num_visible_items(); i < size; i++) {
332 
333  location_palette_item & tile = buttons_[i];
334 
335  tile.hide(true);
336 
337  if (i >= ending) {
338  //We want to hide all following buttons so we cannot use break here.
339  continue;
340  }
341 
342  const std::string item_id = items_[starting + i];
343 
344  std::stringstream tooltip_text;
345 
346  SDL_Rect dstrect;
347  dstrect.x = x;
348  dstrect.y = y;
349  dstrect.w = location().w - 10;
350  dstrect.h = item_size_ + 2;
351 
352  tile.set_location(dstrect);
353  tile.set_tooltip_string(tooltip_text.str());
354  tile.set_item_id(item_id);
355  tile.set_selected(is_selected_item(item_id));
356  tile.set_dirty(true);
357  tile.hide(false);
358  tile.draw();
359 
360  // Adjust location
361  y += item_space_;
362  }
363 }
364 
365 std::vector<std::string> location_palette::action_pressed() const
366 {
367  std::vector<std::string> res;
368  if (button_delete_ && button_delete_->pressed()) {
369  res.push_back("editor-remove-location");
370  }
371  return res;
372 }
373 
375 {
376 }
377 
379 {
380  int pos;
381  const auto itor = std::find(items_.begin(), items_.end(), id);
382  if (itor == items_.end()) {
383  items_.push_back(id);
384  pos = items_.size() - 1;
385  }
386  else {
387  pos = itor - items_.begin();
388  }
389  selected_item_ = id;
390  items_start_ = std::max(pos - num_visible_items() + 1, items_start_);
391  items_start_ = std::min(pos, items_start_);
393 }
394 
395 } // end namespace editor
std::shared_ptr< gui::button > find_action_button(const std::string &id)
Retrieves a pointer to a theme UI button.
Definition: display.cpp:849
virtual bool scroll_down() override
Scroll the editor-palette down one step if possible.
location_palette(editor_display &gui, const config &, editor_toolkit &toolkit)
virtual void mouse_up(const SDL_MouseButtonEvent &event)
Definition: button.cpp:502
button(CVideo &video, const std::string &label, TYPE type=TYPE_PRESS, std::string button_image="", SPACE_CONSUMPTION spacing=DEFAULT_SPACE, const bool auto_join=true, std::string overlay_image="")
Definition: button.cpp:46
std::vector< char_t > string
virtual bool can_scroll_up() override
std::map< std::string, t_string > string_map
bool enabled() const
Definition: widget.cpp:210
std::vector< events::sdl_handler * > sdl_handler_vector
Definition: events.hpp:176
virtual bool can_scroll_down() override
location_palette_item(CVideo &video, editor::location_palette &parent)
Definition: video.hpp:29
boost::ptr_vector< location_palette_item > buttons_
CVideo & video() const
Definition: widget.hpp:84
General purpose widgets.
virtual bool is_selected_item(const std::string &id)
void set_mouseover_overlay(editor_display &gui)
#define h
virtual std::vector< std::string > action_pressed() const override
virtual void mouse_up(const SDL_MouseButtonEvent &e) override
editor::location_palette & parent_
std::unique_ptr< location_palette_button > button_goto_
#define b
virtual void draw() override
bool hidden() const
Definition: widget.cpp:196
void set_dirty(bool dirty=true)
Definition: widget.cpp:215
static UNUSEDNOWARN std::string _(const char *str)
Definition: gettext.hpp:89
bool valid() const
Definition: location.hpp:72
virtual void hide(bool value=true)
Definition: widget.cpp:160
void draw_rectangle(const SDL_Rect &rect, const color_t &color)
Draw a rectangle outline.
Definition: rect.cpp:60
std::string selected
location_palette_button(CVideo &video, const SDL_Rect &location, const std::string &text, const std::function< void(void)> &callback)
virtual std::string get_help_string()
Manage the empty-palette in the editor.
Definition: action.cpp:29
bool pressed()
Definition: button.cpp:583
static bool execute(const std::string &title, const std::string &label, std::string &text, CVideo &video)
Executes the dialog.
Definition: edit_text.hpp:52
int num_visible_items()
Return the maximum number of items shown at the same time.
void set_item_id(const std::string &id)
const color_t NORMAL_COLOR
bool point_in_rect(int x, int y, const SDL_Rect &rect)
Tests whether a point is inside a rectangle.
Definition: rect.cpp:21
void set_selected(bool selected)
Encapsulates the map of the game.
Definition: location.hpp:40
virtual bool scroll_up() override
Scroll the editor-palette up one step if possible.
size_t size(const utf8::string &str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:86
map_location special_location(const std::string &id) const
Definition: map.cpp:311
void add_item(const std::string &id)
void scroll_to_tile(const map_location &loc, SCROLL_TYPE scroll_type=ONSCREEN, bool check_fogged=true, bool force=true)
Scroll such that location loc is on-screen.
Definition: display.cpp:2155
virtual void draw_contents() override
#define i
virtual void draw()
Definition: widget.cpp:277
int w
std::unique_ptr< location_palette_button > button_add_
void set_tooltip_string(const std::string &str)
Definition: widget.cpp:312
std::string vgettext(const char *msgid, const utils::string_map &symbols)
int set_help_string(const std::string &str)
Definition: video.cpp:470
void adjust_size(const SDL_Rect &target) override
Update the size of this widget.
std::unique_ptr< location_palette_button > button_delete_
const gamemap & get_map() const
Definition: display.hpp:92
bool find(E event, F functor)
Tests whether an event handler is available.
SDL_Rect draw_text(surface &dst, const SDL_Rect &area, int size, const color_t &color, const std::string &txt, int x, int y, bool use_tooltips, int style)
Function to draw text on a surface.
void fill_rectangle(const SDL_Rect &rect, const color_t &color)
Draws a filled rectangle.
Definition: rect.cpp:68
std::function< void(void)> callback_
bool mouse_locked() const
Definition: widget.cpp:70
CVideo & video()
Gets the underlying screen object.
Definition: display.hpp:195
void draw_contents() override
bool hit(int x, int y) const
virtual void set_location(SDL_Rect const &rect)
Definition: widget.cpp:83
#define e
virtual void handle_event(SDL_Event const &)
Definition: widget.cpp:338
virtual void select_item(const std::string &item_id)
SDL_Rect const & location() const
Definition: widget.cpp:142
widget(widget const &o)
Definition: widget.cpp:33
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:93
void mouse_up(SDL_MouseButtonEvent const &e)
mock_char c
int num_items() override
Return the number of items in the palette.
void hide(bool hidden) override
void handle_event(const SDL_Event &e) override
const std::string & id() const
Definition: widget.cpp:230
std::shared_ptr< gui::button > find_menu_button(const std::string &id)
Definition: display.cpp:859
friend bool operator==(state_t r, state_t l)
std::vector< std::string > items_
void clear_help_string(int handle)
Definition: video.cpp:501
virtual sdl_handler_vector handler_members() override