28#define DBG_FT LOG_STREAM(debug, log_font)
29#define LOG_FT LOG_STREAM(info, log_font)
34static const int text_width = 400;
35static const double height_fudge = 0.95;
39 tooltip(
const rect& r,
const std::string& msg,
const std::string& act =
"");
45 bool label_initialized =
false;
48 void update_label_pos();
51tooltip::tooltip(
const rect& r,
const std::string& msg,
const std::string& act)
52 : origin(r), message(msg), action(act),
label(msg)
54 DBG_FT <<
"created tooltip for " << origin <<
" at " <<
loc;
57void tooltip::init_label()
59 const color_t bgcolor {0,0,0,192};
63 label.set_font_size(font_size);
65 label.set_width(text_width);
66 label.set_height(1000000);
68 label.set_bg_color(bgcolor);
71 label.clear_texture();
72 label.create_texture();
75 int new_text_width = text_width *
static_cast<float>(lsize.y)/game_canvas.h;
76 while((lsize.y > game_canvas.h*height_fudge) && (lsize.x < game_canvas.w)) {
86 bool wont_fit =
false;
87 if(new_text_width>game_canvas.w) {
88 new_text_width=game_canvas.w;
91 DBG_FT <<
"lsize.x,y = " << lsize.x <<
"," << lsize.y <<
", new_text_width = " << new_text_width;
93 label.set_width(new_text_width);
94 label.clear_texture();
95 label.create_texture();
97 lsize =
label.get_draw_size();
98 DBG_FT <<
"new label lsize.x,y = " << lsize.x <<
"," << lsize.y;
102 new_text_width *= 1.3;
106 label_initialized =
true;
109void tooltip::update_label_pos()
114 loc = {0, 0, lsize.x, lsize.y};
116 DBG_FT <<
"\nupdate_label_pos() Start: loc = " <<
loc.
x <<
"," <<
loc.
y <<
" origin = " << origin.x <<
"," << origin.y;
118 if(origin.y >
loc.h) {
121 DBG_FT <<
"\tAbove: loc = " <<
loc.
x <<
"," <<
loc.
y <<
" origin = " << origin.x <<
"," << origin.y;
122 }
else if((origin.y + origin.h +
loc.h) <= game_canvas.h*height_fudge) {
124 loc.
y = origin.y + origin.h;
125 DBG_FT <<
"\tBelow: loc = " <<
loc.
x <<
"," <<
loc.
y <<
" origin = " << origin.x <<
"," << origin.y;
126 }
else if(((origin.y + origin.h/2 -
loc.h/2) >= 0) &&
127 ((origin.y + origin.h/2 +
loc.h/2) <= game_canvas.h*height_fudge)) {
129 loc.
y = origin.y + origin.h/2 -
loc.h/2;
130 DBG_FT <<
"\tCenter: loc = " <<
loc.
x <<
"," <<
loc.
y <<
" origin = " << origin.x <<
"," << origin.y;
131 }
else if(
loc.h <= game_canvas.h*0.95) {
133 loc.
y = game_canvas.h/2 -
loc.h/2;
134 DBG_FT <<
"\tScreen Center: loc = " <<
loc.
x <<
"," <<
loc.
y <<
" origin = " << origin.x <<
"," << origin.y;
138 DBG_FT <<
"\tToo big: loc = " <<
loc.
x <<
"," <<
loc.
y <<
" origin = " << origin.x <<
"," << origin.y;
141 DBG_FT <<
"\tBefore x adjust: loc.x,y,w,h = " <<
loc.
x <<
"," <<
loc.
y <<
"," <<
loc.w <<
"," <<
loc.h <<
" origin = " << origin.
x <<
"," << origin.y;
144 if(
loc.
x +
loc.w > game_canvas.w) {
151 DBG_FT <<
"\tFinal: loc.x,y,w,h = " <<
loc.
x <<
"," <<
loc.
y <<
"," <<
loc.w <<
"," <<
loc.h <<
" origin = " << origin.
x <<
"," << origin.y;
156std::map<int, tooltip> tips;
157int active_tooltip = 0;
172 if(!active_tooltip) {
175 DBG_FT <<
"clearing active tooltip " << active_tooltip;
176 tips.at(active_tooltip).label.undraw();
186 current_manager =
this;
194 current_manager =
nullptr;
199 if(!active_tooltip) {
202 tooltip& tip = tips.at(active_tooltip);
203 if(!tip.label_initialized) {
208 tip.label.update(std::chrono::steady_clock::now());
214 if(!active_tooltip) {
217 tooltip& tip = tips.at(active_tooltip);
218 if(!tip.loc.overlaps(region)) {
228 if(!active_tooltip) {
231 return tips.at(active_tooltip).loc;
237 LOG_FT <<
"clearing all tooltips";
244 for(
auto i = tips.begin();
i != tips.end(); ) {
245 if(
i->second.origin.overlaps(r)) {
246 DBG_FT <<
"clearing tip " <<
i->first <<
" at "
247 <<
i->second.origin <<
" overlapping " << r;
249 if (
i->first == active_tooltip) {
250 i->second.label.undraw();
263 std::map<int, tooltip>::iterator it = tips.find(
id);
264 if (it == tips.end() )
return false;
266 if(tip.message == message && tip.origin == origin) {
269 if(tip.message != message) {
270 LOG_FT <<
"updating tooltip " <<
id <<
" message";
271 tip.message = message;
275 if(tip.origin != origin) {
276 DBG_FT <<
"updating tooltip " <<
id <<
" origin " << origin;
278 tip.update_label_pos();
286 DBG_FT <<
"removing tooltip " <<
id;
287 if(
id == active_tooltip) {
293int add_tooltip(
const rect& origin,
const std::string& message,
const std::string& action)
297 for(
auto& [
id, tip] : tips) {
298 if(tip.origin == origin && tip.message == message && tip.action == action) {
302 DBG_FT <<
"adding tooltip for " << origin;
307 int id = tooltip_id++;
308 tips.try_emplace(
id, origin, message, action);
315 if(!current_manager) {
316 throw game::error(
"trying to show tooltip with no tooltip manager");
323 if(active_tooltip ==
id) {
327 LOG_FT <<
"showing tip " <<
id <<
" for " << tip.origin;
330 tip.label.update(std::chrono::steady_clock::now());
336 point mouseloc{mousex, mousey};
337 for(
auto& [
id, tip] : tips) {
338 if(tip.origin.contains(mouseloc)) {
345 LOG_FT <<
"clearing tooltip because none hovered";
352 for(
auto& [
id, tip] : tips) { (void)
id;
353 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
void show_help(const std::string &show_topic)
Open the help browser.
rect game_canvas()
The game canvas area, in drawing coordinates.
Contains the SDL_Rect helper code.
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.