26 #include <SDL2/SDL_rect.h>
29 #define DBG_FT LOG_STREAM(debug, log_font)
30 #define LOG_FT LOG_STREAM(info, log_font)
35 static const int text_width = 400;
36 static const double height_fudge = 0.95;
40 tooltip(
const SDL_Rect& r,
const std::string&
msg,
const std::string& act =
"");
48 void update_label_pos();
55 DBG_FT <<
"created tooltip for " << origin <<
" at " <<
loc;
58 void tooltip::init_label()
60 const color_t bgcolor {0,0,0,192};
68 label.set_font_size(font_size);
70 label.set_clip_rect(huge);
71 label.set_width(text_width);
73 label.set_bg_color(bgcolor);
76 label.create_texture();
79 int new_text_width = text_width *
static_cast<float>(lsize.y)/
game_canvas.h;
90 bool wont_fit =
false;
95 DBG_FT <<
"lsize.x,y = " << lsize.x <<
"," << lsize.y <<
", new_text_width = " << new_text_width;
97 label.set_width(new_text_width);
98 label.clear_texture();
99 label.create_texture();
101 lsize =
label.get_draw_size();
102 DBG_FT <<
"new label lsize.x,y = " << lsize.x <<
"," << lsize.y;
106 new_text_width *= 1.3;
111 label.clear_texture();
112 label.create_texture();
117 void tooltip::update_label_pos()
122 loc = {0, 0, lsize.x, lsize.y};
124 DBG_FT <<
"\nupdate_label_pos() Start: loc = " <<
loc.
x <<
"," <<
loc.
y <<
" origin = " << origin.x <<
"," << origin.y;
126 if(origin.y >
loc.h) {
129 DBG_FT <<
"\tAbove: loc = " <<
loc.
x <<
"," <<
loc.
y <<
" origin = " << origin.x <<
"," << origin.y;
130 }
else if((origin.y + origin.h +
loc.h) <=
game_canvas.h*height_fudge) {
132 loc.
y = origin.y + origin.h;
133 DBG_FT <<
"\tBelow: loc = " <<
loc.
x <<
"," <<
loc.
y <<
" origin = " << origin.x <<
"," << origin.y;
134 }
else if(((origin.y + origin.h/2 -
loc.h/2) >= 0) &&
135 ((origin.y + origin.h/2 +
loc.h/2) <=
game_canvas.h*height_fudge)) {
137 loc.
y = origin.y + origin.h/2 -
loc.h/2;
138 DBG_FT <<
"\tCenter: loc = " <<
loc.
x <<
"," <<
loc.
y <<
" origin = " << origin.x <<
"," << origin.y;
142 DBG_FT <<
"\tScreen Center: loc = " <<
loc.
x <<
"," <<
loc.
y <<
" origin = " << origin.x <<
"," << origin.y;
146 DBG_FT <<
"\tToo big: loc = " <<
loc.
x <<
"," <<
loc.
y <<
" origin = " << origin.x <<
"," << origin.y;
149 DBG_FT <<
"\tBefore x adjust: loc.x,y,w,h = " <<
loc.
x <<
"," <<
loc.
y <<
"," <<
loc.w <<
"," <<
loc.h <<
" origin = " << origin.
x <<
"," << origin.y;
159 DBG_FT <<
"\tFinal: loc.x,y,w,h = " <<
loc.
x <<
"," <<
loc.
y <<
"," <<
loc.w <<
"," <<
loc.h <<
" origin = " << origin.
x <<
"," << origin.y;
164 std::map<int, tooltip>
tips;
165 int active_tooltip = 0;
169 surface current_background =
nullptr;
182 if(!active_tooltip) {
185 DBG_FT <<
"clearing active tooltip " << active_tooltip;
186 tips.at(active_tooltip).label.undraw();
196 current_manager =
this;
204 current_manager =
nullptr;
209 if(!active_tooltip) {
214 tips.at(active_tooltip).label.update(std::chrono::steady_clock::now());
220 if(!active_tooltip) {
224 if(!
tip.loc.overlaps(region)) {
234 if(!active_tooltip) {
237 return tips.at(active_tooltip).loc;
243 LOG_FT <<
"clearing all tooltips";
250 for(
auto i =
tips.begin();
i !=
tips.end(); ) {
251 if(
i->second.origin.overlaps(r)) {
252 DBG_FT <<
"clearing tip " <<
i->first <<
" at "
253 <<
i->second.origin <<
" overlapping " << r;
255 if (
i->first == active_tooltip) {
256 i->second.label.undraw();
270 if (it ==
tips.end() )
return false;
272 if(
tip.message == message &&
tip.origin == origin) {
275 if(
tip.message != message) {
276 LOG_FT <<
"updating tooltip " <<
id <<
" message";
277 tip.message = message;
281 if(
tip.origin != origin) {
282 DBG_FT <<
"updating tooltip " <<
id <<
" origin " << origin;
284 tip.update_label_pos();
292 DBG_FT <<
"removing tooltip " <<
id;
293 if(
id == active_tooltip) {
299 int add_tooltip(
const SDL_Rect& origin,
const std::string& message,
const std::string& action)
304 if(
tip.origin == origin &&
tip.message == message &&
tip.action == action) {
308 DBG_FT <<
"adding tooltip for " << origin;
313 int id = tooltip_id++;
314 tips.emplace(
id,
tooltip(origin, message, action));
321 if(!current_manager) {
322 throw game::error(
"trying to show tooltip with no tooltip manager");
329 if(active_tooltip ==
id) {
333 LOG_FT <<
"showing tip " <<
id <<
" for " <<
tip.origin;
336 tip.label.update(std::chrono::steady_clock::now());
342 point mouseloc{mousex, mousey};
344 if(
tip.origin.contains(mouseloc)) {
351 LOG_FT <<
"clearing tooltip because none hovered";
358 for(
auto& [
id,
tip] :
tips) { (void)
id;
359 if(!
tip.action.empty() &&
tip.origin.contains(mousex, mousey)) {
@ border
The border of the map.
std::string label
What to show in the filter's drop-down list.
std::string tooltip
Shown when hovering over an entry in the filter's drop-down list.
std::string id
Text to match against addon_info.tags()
Standard logging facilities (interface).
void raise_drawable(top_level_drawable *tld)
Raise a TLD to the top of the drawing stack.
const color_t NORMAL_COLOR
static std::unique_ptr< tooltip > tip
std::vector< game_tip > tips
void show_help(const std::string &show_topic)
Open the help browser, show topic with id show_topic.
rect game_canvas()
The game canvas area, in drawing coordinates.
std::string::const_iterator iterator
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
The basic class for representing 8-bit RGB or RGBA colour values.
Base class for all the errors encountered by the engine.
An abstract description of a rectangle with integer coordinates.