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