The Battle for Wesnoth  1.19.13+dev
status_label_helper.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2010 - 2025
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #pragma once
16 
17 #include "gettext.hpp"
22 
23 #include <functional>
24 
25 namespace gui2
26 {
27 namespace implementation
28 {
29 template<typename T>
31 {
32  // Menu Buttons
33  if constexpr(std::is_same_v<menu_button, T>) {
34  return w.get_value_string();
35  }
36 
37  // Selectable widgets (like toggle buttons)
38  if constexpr(std::is_base_of_v<selectable_item, T>) {
39  return w.get_value_bool() ? _("yes") : _("no");
40  }
41 
42  // Sliders
43  if constexpr(std::is_same_v<slider, T>) {
44  return w.get_value_label();
45  }
46 
47  return w.get_label();
48 }
49 
50 /**
51  * Searches for the status target, starting with the source widget's parent.
52  * and walking backwards up the parent tree until the target is found.
53  *
54  * @todo this is a more powerful version of find_widget. Investigate whether
55  * we want this behavior exposed more broadly.
56  */
57 inline auto& find_target(std::string_view target_id, widget& source)
58 {
59  widget* parent = source.parent();
60  widget* target = nullptr;
61 
62  while(parent) {
63  target = parent->find(target_id, false);
64  parent = parent->parent();
65 
66  if(target) {
67  break;
68  }
69  }
70 
71  VALIDATE(target, missing_widget(std::string(target_id)));
72  return dynamic_cast<styled_widget&>(*target);
73 }
74 
75 /** Returns the dereferenced target pointer if valid, else the default target. */
76 inline auto& validate_target(styled_widget* target, widget& source)
77 {
78  if(target) {
79  return *target;
80  }
81 
82  return find_target(source.id() + "_label", source);
83 }
84 
85 } // namespace implementation
86 
87 /**
88  * Binds a given target widget to reflect another widget's label.
89  *
90  * The initial status label value will be set here and updated whenever the source
91  * widget is modified (specifically, when a NOTIFY_MODIFIED event is fired).
92  *
93  * @param source The widget whose value will be represented in the target.
94  * @param value_getter Functor to process the value of the source widget.
95  * The expected signature is [](const W&) -> [t_]string.
96  * @param target_ptr Pointer to the status widget. If no target is specified,
97  * the default with ID [sourceID + "_label"] will be used.
98  */
99 template<typename W, typename F>
100 void bind_status_label(W& source, const F& value_getter, styled_widget* target_ptr = nullptr)
101 {
102  // Get fallback if necessary.
103  styled_widget& target = implementation::validate_target(target_ptr, source);
104 
106  [&, value_getter](auto&&...) { target.set_label(value_getter(source)); });
107 
108  // Set initial value.
109  source.fire(event::NOTIFY_MODIFIED, source, nullptr);
110 }
111 
112 /**
113  * Binds a status label using the default value getter and default target ID.
114  */
115 template<typename W>
117 {
118  bind_status_label(source, implementation::get_status_label<W>, nullptr);
119 }
120 
121 /**
122  * Binds a status label using the default value getter and the given ID.
123  */
124 template<typename W>
125 void bind_default_status_label(W& source, std::string_view target_id)
126 {
127  auto& target = implementation::find_target(target_id, source);
128  bind_status_label(source, implementation::get_status_label<W>, &target);
129 }
130 
131 } // namespace gui2
virtual void set_label(const t_string &text)
Base class for all widgets.
Definition: widget.hpp:55
virtual widget * find(const std::string_view id, const bool must_be_active)
Returns a widget with the wanted id.
Definition: widget.cpp:560
const std::string & id() const
Definition: widget.cpp:110
widget * parent()
Definition: widget.cpp:170
int w
static std::string _(const char *str)
Definition: gettext.hpp:97
@ NOTIFY_MODIFIED
Definition: handler.hpp:175
void connect_signal_notify_modified(dispatcher &dispatcher, const signal_notification &signal)
Connects a signal handler for getting a notification upon modification.
Definition: dispatcher.cpp:189
t_string get_status_label(const T &w)
auto & find_target(std::string_view target_id, widget &source)
Searches for the status target, starting with the source widget's parent.
auto & validate_target(styled_widget *target, widget &source)
Returns the dereferenced target pointer if valid, else the default target.
Generic file dialog.
void bind_default_status_label(W &source)
Binds a status label using the default value getter and default target ID.
t_string missing_widget(const std::string &id)
Returns a default error message if a mandatory widget is omitted.
Definition: helper.cpp:146
void bind_status_label(W &source, const F &value_getter, styled_widget *target_ptr=nullptr)
Binds a given target widget to reflect another widget's label.
Contains the implementation details for lexical_cast and shouldn't be used directly.
#define VALIDATE(cond, message)
The macro to use for the validation of WML.