The Battle for Wesnoth  1.15.0+dev
tooltips.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2018 by David White <dave@whitevine.net>
3  Part of the Battle for Wesnoth Project https://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 #include "tooltips.hpp"
16 
17 #include "floating_label.hpp"
18 #include "font/standard_colors.hpp"
19 #include "game_display.hpp"
20 #include "help/help.hpp"
21 #include "video.hpp"
22 
23 #include <SDL2/SDL_rect.h> // Travis doesn't like this, although it works on my machine -> '#include <SDL2/SDL_sound.h>
24 
25 namespace {
26 
27 static const int font_size = font::SIZE_NORMAL;
28 static const int text_width = 400;
29 
30 struct tooltip
31 {
32  tooltip(const SDL_Rect& r, const std::string& msg, const std::string& act = "", bool use_markup = false, const surface& fg = surface())
33  : rect(r), message(msg), action(act), markup(use_markup), foreground(fg)
34  {}
35  SDL_Rect rect;
36  std::string message;
37  std::string action;
38  bool markup;
39  surface foreground;
40 };
41 
42 std::map<int, tooltip> tips;
43 std::map<int, tooltip>::const_iterator current_tooltip = tips.end();
44 
45 int tooltip_handle = 0;
46 int tooltip_id = 0;
47 
48 surface current_background = nullptr;
49 
50 }
51 
52 static void clear_tooltip()
53 {
54  if(tooltip_handle != 0) {
55  font::remove_floating_label(tooltip_handle);
56  tooltip_handle = 0;
57  }
58 }
59 
60 static void show_tooltip(const tooltip& tip)
61 {
62  CVideo& video = CVideo::get_singleton();
63 
64  if(video.faked()) {
65  return;
66  }
67 
68  clear_tooltip();
69 
70  const color_t bgcolor {0,0,0,192};
71  SDL_Rect area = video.screen_area();
72 
73  unsigned int border = 10;
74 
75  font::floating_label flabel(tip.message, tip.foreground);
76  flabel.use_markup(tip.markup);
77  flabel.set_font_size(font_size);
79  flabel.set_clip_rect(area);
80  flabel.set_width(text_width);
82  flabel.set_bg_color(bgcolor);
83  flabel.set_border_size(border);
84 
85  tooltip_handle = font::add_floating_label(flabel);
86 
87  SDL_Rect rect = font::get_floating_label_rect(tooltip_handle);
88 
89  //see if there is enough room to fit it above the tip area
90  if(tip.rect.y > rect.h) {
91  rect.y = tip.rect.y - rect.h;
92  } else {
93  rect.y = tip.rect.y + tip.rect.h;
94  }
95 
96  rect.x = tip.rect.x;
97  if(rect.x < 0) {
98  rect.x = 0;
99  } else if(rect.x + rect.w > area.w) {
100  rect.x = area.w - rect.w;
101  }
102 
103  font::move_floating_label(tooltip_handle,rect.x,rect.y);
104 }
105 
106 namespace tooltips {
107 
108 manager::manager()
109 {
110  clear_tooltips();
111 }
112 
113 manager::~manager()
114 {
115  try {
116  clear_tooltips();
117  } catch (...) {}
118 }
119 
121 {
122  clear_tooltip();
123  tips.clear();
124  current_tooltip = tips.end();
125 }
126 
127 void clear_tooltips(const SDL_Rect& rect)
128 {
129  for(std::map<int,tooltip>::iterator i = tips.begin(); i != tips.end(); ) {
130  if(sdl::rects_overlap(i->second.rect,rect)) {
131  if (i==current_tooltip) {
132  clear_tooltip();
133  }
134  tips.erase(i++);
135  current_tooltip = tips.end();
136  } else {
137  ++i;
138  }
139  }
140 }
141 
142 
143 
144 bool update_tooltip(int id, const SDL_Rect& rect, const std::string& message,
145  const std::string& action, bool use_markup)
146 {
147  std::map<int, tooltip>::iterator it = tips.find(id);
148  if (it == tips.end() ) return false;
149  it->second.action = action;
150  it->second.markup = use_markup;
151  it->second.message = message;
152  it->second.rect = rect;
153  return true;
154 }
155 
156 bool update_tooltip(int id, const SDL_Rect& rect, const std::string& message,
157  const std::string& action, bool use_markup, const surface& foreground)
158 {
159  std::map<int, tooltip>::iterator it = tips.find(id);
160  if (it == tips.end() ) return false;
161  it->second.action = action;
162  it->second.foreground = foreground;
163  it->second.markup = use_markup;
164  it->second.message = message;
165  it->second.rect = rect;
166  return true;
167 }
168 
169 void remove_tooltip(int id)
170 {
171  tips.erase(id);
172  clear_tooltip();
173 }
174 
175 int add_tooltip(const SDL_Rect& rect, const std::string& message, const std::string& action, bool use_markup, const surface& foreground)
176 {
177  for(std::map<int, tooltip>::iterator it = tips.begin(); it != tips.end();) {
178  if(sdl::rects_overlap(it->second.rect,rect)) {
179  tips.erase(it++);
180  } else {
181  ++it;
182  }
183  }
184 
185  int id = tooltip_id++;
186 
187  tips.emplace(id, tooltip(rect, message, action, use_markup, foreground));
188 
189  current_tooltip = tips.end();
190  return id;
191 }
192 
193 void process(int mousex, int mousey)
194 {
195  for(std::map<int, tooltip>::const_iterator i = tips.begin(); i != tips.end(); ++i) {
196  if(mousex > i->second.rect.x && mousey > i->second.rect.y &&
197  mousex < i->second.rect.x + i->second.rect.w && mousey < i->second.rect.y + i->second.rect.h) {
198  if(current_tooltip != i) {
199  show_tooltip(i->second);
200  current_tooltip = i;
201  }
202 
203  return;
204  }
205  }
206 
207  clear_tooltip();
208  current_tooltip = tips.end();
209 }
210 
211 bool click(int mousex, int mousey)
212 {
213  for(std::map<int, tooltip>::const_iterator i = tips.begin(); i != tips.end(); ++i) {
214  if(!i->second.action.empty() && sdl::point_in_rect(mousex, mousey, i->second.rect)) {
215  help::show_help(i->second.action);
216  return true;
217  }
218  }
219  return false;
220 }
221 
222 }
void show_help(const std::string &show_topic, int xloc, int yloc)
Open the help browser, show topic with id show_topic.
Definition: help.cpp:116
void set_clip_rect(const SDL_Rect &r)
std::vector< game_tip > tips
Definition: settings.cpp:46
bool rects_overlap(const SDL_Rect &rect1, const SDL_Rect &rect2)
Tests whether two rectangles overlap.
Definition: rect.cpp:33
Definition: video.hpp:31
void remove_tooltip(int id)
Definition: tooltips.cpp:169
void remove_floating_label(int handle)
removes the floating label given by &#39;handle&#39; from the screen
static CVideo & get_singleton()
Definition: video.hpp:43
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:109
void set_font_size(int font_size)
-file util.hpp
const int SIZE_NORMAL
Definition: constants.cpp:19
void move_floating_label(int handle, double xmove, double ymove)
moves the floating label given by &#39;handle&#39; by (xmove,ymove)
void clear_tooltips(const SDL_Rect &rect)
Definition: tooltips.cpp:127
void process(int mousex, int mousey)
Definition: tooltips.cpp:193
void set_alignment(ALIGN align)
void set_bg_color(const color_t &bg_color)
static void show_tooltip(const tooltip &tip)
Definition: tooltips.cpp:60
static tooltip & tip()
Definition: tooltip.cpp:144
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:22
void set_color(const color_t &color)
bool update_tooltip(int id, const SDL_Rect &rect, const std::string &message, const std::string &action, bool use_markup, const surface &foreground)
Definition: tooltips.cpp:156
bool faked() const
Definition: video.hpp:60
bool click(int mousex, int mousey)
Definition: tooltips.cpp:211
tooltips.
std::size_t i
Definition: function.cpp:933
int add_floating_label(const floating_label &flabel)
add a label floating on the screen above everything else.
SDL_Rect get_floating_label_rect(int handle)
static void clear_tooltip()
Definition: tooltips.cpp:52
void set_border_size(int border)
SDL_Rect screen_area(bool as_pixels=true) const
Returns the current window renderer area, either in pixels or screen coordinates. ...
Definition: video.cpp:286
const int font_size
Definition: button.cpp:40
int add_tooltip(const SDL_Rect &rect, const std::string &message, const std::string &action, bool use_markup, const surface &foreground)
Definition: tooltips.cpp:175
std::string::const_iterator iterator
Definition: tokenizer.hpp:24