From cc6c1234f51088447ddf30a1f51a5d1a33d9677f Mon Sep 17 00:00:00 2001 From: Nat Quayle Nelson Date: Sun, 31 Aug 2025 15:08:16 -0500 Subject: [PATCH] tooltips on node links --- src/dialogxml/dialogs/dialog.cpp | 10 ++++++++++ src/dialogxml/dialogs/dialog.hpp | 4 ++++ src/dialogxml/widgets/control.hpp | 5 +++++ src/scenedit/scen.keydlgs.cpp | 12 ++++++++++-- 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/dialogxml/dialogs/dialog.cpp b/src/dialogxml/dialogs/dialog.cpp index bf75e705..5393f9a7 100644 --- a/src/dialogxml/dialogs/dialog.cpp +++ b/src/dialogxml/dialogs/dialog.cpp @@ -808,13 +808,23 @@ void cDialog::handle_one_event(const sf::Event& currentEvent, cFramerateLimiter& redraw_everything(); bool inField = false; + bool onTooltip = false; for(auto& ctrl : controls) { + if(!ctrl.second->tooltip_text.empty() && ctrl.second->getBounds().contains(x, y)){ + if(tooltip_control.empty()){ + LOG("Warning! Tooltip activated but nowhere to show it!"); + }else{ + getControl(tooltip_control).setText(ctrl.second->tooltip_text); + onTooltip = true; + } + } if(ctrl.second->getType() == CTRL_FIELD && ctrl.second->getBounds().contains(x, y)) { set_cursor(text_curs); inField = true; break; } } + if(!onTooltip && !tooltip_control.empty()) getControl(tooltip_control).setText(""); if(!inField) set_cursor(sword_curs); }break; default: // To silence warning of unhandled enum values diff --git a/src/dialogxml/dialogs/dialog.hpp b/src/dialogxml/dialogs/dialog.hpp index beb17a27..a2a0288e 100644 --- a/src/dialogxml/dialogs/dialog.hpp +++ b/src/dialogxml/dialogs/dialog.hpp @@ -107,6 +107,8 @@ public: /// Create a new dialog with no items. /// @param p Optionally, a parent dialog. explicit cDialog(cDialog* p = nullptr); + /// Designate a control as the place to display tooltip text + void setTooltipControl(std::string key) { this->tooltip_control = key; } /// Creates a new dialog, loading its definition from a file. /// @param path The name of the file to load. It must be in the game's dialogs directory. /// @param p Optionally, a parent dialog. @@ -298,6 +300,8 @@ private: std::string fname; std::string defaultButton; std::string escapeButton; + /// TODO make this specifiable in dialogxml + std::string tooltip_control; sf::Clock animTimer, paintTimer; friend class cControl; friend class cContainer; diff --git a/src/dialogxml/widgets/control.hpp b/src/dialogxml/widgets/control.hpp index 8502447b..15941e8f 100644 --- a/src/dialogxml/widgets/control.hpp +++ b/src/dialogxml/widgets/control.hpp @@ -385,6 +385,9 @@ public: /// If the control automatically determines its rect based on certain criteria, override this. /// It will automatically be called during parsing. virtual void recalcRect() {} + + // Set text that will be displayed when the mouse hovers this + void setTooltipText(std::string text) { this->tooltip_text = text; } protected: /// Create a new control attached to a dialog. /// @param t The type of the control. @@ -508,6 +511,8 @@ private: std::string anchor; bool is_link = false; static std::mt19937 ui_rand; + // TODO make this specifiable in dialogXML + std::string tooltip_text; }; #endif diff --git a/src/scenedit/scen.keydlgs.cpp b/src/scenedit/scen.keydlgs.cpp index a075c8f6..2d727e4c 100644 --- a/src/scenedit/scen.keydlgs.cpp +++ b/src/scenedit/scen.keydlgs.cpp @@ -829,6 +829,8 @@ static void push_spec_enc_in_stack(cDialog& me, node_stack_t& edit_stack, node_i put_spec_enc_in_dlog(me, edit_stack); } +extern cUniverse temp_universe(); + static void put_spec_enc_in_dlog(cDialog& me, node_stack_t& edit_stack) { cSpecial& spec = edit_stack.back().node; @@ -845,12 +847,15 @@ static void put_spec_enc_in_dlog(cDialog& me, node_stack_t& edit_stack) { std::vector locals = local_node_graph(scenario, edit_stack, cur_town); which = locals[edit_stack.back().which]; } + cUniverse univ = temp_universe(); int i = 0; for(node_id_t from_id : which.from_nodes){ if(me.hasControl(fmt::format("calledby{}", i))){ me[fmt::format("calledby{}", i)].setText(label(from_id)); + me[fmt::format("calledby{}", i)].recalcRect(); me[fmt::format("calledby{}", i)].show(); - // TODO setTooltipText + // TODO null check get_spec_ref + me[fmt::format("calledby{}", i)].setTooltipText(get_spec_ref(scenario, edit_stack, from_id.which, from_id.town_num_or_out_x, from_id.out_y)->editor_hint(univ)); me[fmt::format("calledby{}", i)].attachClickHandler([from_id, &edit_stack](cDialog& me, std::string, eKeyMod) -> bool { push_spec_enc_in_stack(me, edit_stack, from_id); return true; @@ -868,8 +873,10 @@ static void put_spec_enc_in_dlog(cDialog& me, node_stack_t& edit_stack) { for(node_id_t to_id : which.to_nodes){ if(me.hasControl(fmt::format("calls{}", i))){ me[fmt::format("calls{}", i)].setText(label(to_id)); + me[fmt::format("calls{}", i)].recalcRect(); me[fmt::format("calls{}", i)].show(); - // TODO setTooltipText + // TODO null check get_spec_ref + me[fmt::format("calls{}", i)].setTooltipText(get_spec_ref(scenario, edit_stack, to_id.which, to_id.town_num_or_out_x, to_id.out_y)->editor_hint(univ)); me[fmt::format("calls{}", i)].attachClickHandler([to_id, &edit_stack](cDialog& me, std::string, eKeyMod) -> bool { push_spec_enc_in_stack(me, edit_stack, to_id); return true; @@ -1743,6 +1750,7 @@ bool edit_spec_enc(short which_node,short mode,cDialog* parent,bool is_new) { } cDialog special(*ResMgr::dialogs.get("edit-special-node"),parent); + special.setTooltipControl("tooltip"); special.attachClickHandlers(std::bind(commit_spec_enc, _1, _2, std::ref(edit_stack)), {"okay", "back"}); special.attachClickHandlers(std::bind(edit_spec_enc_type, _1, _2, std::ref(edit_stack)), { "general", "oneshot", "affectpc", "ifthen", "town", "out", "rect", "all"