28 #define DBG_FT LOG_STREAM(debug, log_font)
29 #define LOG_FT LOG_STREAM(info, log_font)
34 static const int text_width = 400;
35 static 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();
54 DBG_FT <<
"created tooltip for " << origin <<
" at " <<
loc;
57 void 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;
86 bool wont_fit =
false;
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;
109 void 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;
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;
151 DBG_FT <<
"\tFinal: loc.x,y,w,h = " <<
loc.
x <<
"," <<
loc.
y <<
"," <<
loc.w <<
"," <<
loc.h <<
" origin = " << origin.
x <<
"," << origin.y;
156 std::map<int, tooltip>
tips;
157 int 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) {
203 if(!
tip.label_initialized) {
208 tip.label.update(std::chrono::steady_clock::now());
214 if(!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();
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) {
293 int add_tooltip(
const rect& origin,
const std::string& message,
const std::string& action)
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};
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
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="")
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.