HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
radio_button_widget.hpp
1// Copyright Take Vos 2020-2021.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "abstract_radio_button_widget.hpp"
8#include "../GUI/draw_context.hpp"
9#include "../observable.hpp"
10#include "../label.hpp"
11#include <memory>
12#include <string>
13#include <array>
14#include <optional>
15#include <future>
16
17namespace tt {
18
19template<typename T>
21public:
23 using value_type = typename super::value_type;
24
26
27 template<typename Value, typename Label>
31 value_type true_value,
32 Value &&value,
33 Label &&label) noexcept :
34 abstract_radio_button_widget<T>(window, parent, std::move(true_value), std::forward<Value>(value)),
35 label(std::forward<Label>(label))
36 {
37 }
38
39 template<typename Value>
43 value_type true_value,
44 Value &&value) noexcept :
45 radio_button_widget(window, parent, std::move(true_value), std::forward<Value>(value), observable<tt::label>{})
46 {
47 }
48
51 {
52 }
53
55
56 void init() noexcept override
57 {
58 label_callback = label.subscribe([this](auto...) {
59 this->_request_reconstrain = true;
60 });
61 }
62
63 [[nodiscard]] bool update_constraints(hires_utc_clock::time_point display_time_point, bool need_reconstrain) noexcept override
64 {
65 tt_axiom(gui_system_mutex.recurse_lock_count());
66
67 if (super::update_constraints(display_time_point, need_reconstrain)) {
68 _label_stencil = stencil::make_unique(alignment::top_left, *label, theme::global->labelStyle);
69
70 ttlet minimum_height = std::max(_label_stencil->preferred_extent().height(), theme::global->smallSize);
71 ttlet minimum_width = theme::global->smallSize + theme::global->margin + _label_stencil->preferred_extent().width();
72
73 super::_preferred_size = interval_vec2::make_minimum(minimum_width, minimum_height);
74 super::_preferred_base_line = relative_base_line{vertical_alignment::top, -theme::global->smallSize * 0.5f};
75 return true;
76 } else {
77 return false;
78 }
79 }
80
81 [[nodiscard]] void update_layout(hires_utc_clock::time_point display_time_point, bool need_layout) noexcept override
82 {
83 tt_axiom(gui_system_mutex.recurse_lock_count());
84
85 need_layout |= std::exchange(this->_request_relayout, false);
86 if (need_layout) {
87 _outline_rectangle = aarect{
88 0.0f, this->base_line() - theme::global->smallSize * 0.5f, theme::global->smallSize, theme::global->smallSize};
89
90 ttlet labelX = _outline_rectangle.p3().x() + theme::global->margin;
91 _label_rectangle = aarect{labelX, 0.0f, this->rectangle().width() - labelX, this->rectangle().height()};
92 _label_stencil->set_layout_parameters(_label_rectangle, this->base_line());
93
94 _pip_rectangle = shrink(_outline_rectangle, 1.5f);
95 }
96 super::update_layout(display_time_point, need_layout);
97 }
98
99 void draw(draw_context context, hires_utc_clock::time_point display_time_point) noexcept override
100 {
101 tt_axiom(gui_system_mutex.recurse_lock_count());
102
103 if (overlaps(context, this->window_clipping_rectangle())) {
104 draw_outline(context);
105 draw_pip(context);
106 draw_label(context);
107 }
108 super::draw(std::move(context), display_time_point);
109 }
110
111private:
112 aarect _outline_rectangle;
113 aarect _pip_rectangle;
114 aarect _label_rectangle;
115 std::unique_ptr<stencil> _label_stencil;
116
117 typename decltype(label)::callback_ptr_type label_callback;
118
119 void draw_outline(draw_context context) noexcept
120 {
121 tt_axiom(gui_system_mutex.recurse_lock_count());
122
123 context.corner_shapes = f32x4::broadcast(_outline_rectangle.height() * 0.5f);
124 context.draw_box_with_border_inside(_outline_rectangle);
125 }
126
127 void draw_pip(draw_context context) noexcept
128 {
129 tt_axiom(gui_system_mutex.recurse_lock_count());
130
131 // draw pip
132 if (this->value == this->true_value) {
133 if (*this->enabled && this->window.active) {
134 context.line_color = theme::global->accentColor;
135 }
136 std::swap(context.line_color, context.fill_color);
137 context.corner_shapes = f32x4::broadcast(_pip_rectangle.height() * 0.5f);
138 context.draw_box_with_border_inside(_pip_rectangle);
139 }
140 }
141
142 void draw_label(draw_context context) noexcept
143 {
144 tt_axiom(gui_system_mutex.recurse_lock_count());
145
146 if (*this->enabled) {
147 context.line_color = theme::global->labelStyle.color;
148 }
149
150 _label_stencil->draw(context, true);
151 }
152};
153
154} // namespace tt
Definition alignment.hpp:104
Draw context for drawing using the TTauri shaders.
Definition draw_context.hpp:33
Definition gui_window.hpp:39
std::atomic< bool > active
Definition gui_window.hpp:71
A localized text + icon label.
Definition label.hpp:76
Definition observable.hpp:20
int recurse_lock_count() const noexcept
This function should be used in tt_axiom() to check if the lock is held by current thread.
Definition unfair_recursive_mutex.hpp:60
An abstract radio button widget.
Definition abstract_radio_button_widget.hpp:15
Definition radio_button_widget.hpp:20
bool update_constraints(hires_utc_clock::time_point display_time_point, bool need_reconstrain) noexcept override
Update the constraints of the widget.
Definition radio_button_widget.hpp:63
void draw(draw_context context, hires_utc_clock::time_point display_time_point) noexcept override
Draw the widget.
Definition radio_button_widget.hpp:99
void update_layout(hires_utc_clock::time_point display_time_point, bool need_layout) noexcept override
Update the internal layout of the widget.
Definition radio_button_widget.hpp:81
void init() noexcept override
Should be called right after allocating and constructing a widget.
Definition radio_button_widget.hpp:56
virtual void update_layout(hires_utc_clock::time_point display_time_point, bool need_layout) noexcept
Update the internal layout of the widget.
observable< bool > enabled
The widget is enabled.
Definition widget.hpp:105
gui_window & window
Convenient reference to the Window.
Definition widget.hpp:100
virtual void draw(draw_context context, hires_utc_clock::time_point display_time_point) noexcept
Draw the widget.
Definition widget.hpp:460
float base_line() const noexcept
Get the base-line in local coordinates.
Definition widget.hpp:350
virtual bool update_constraints(hires_utc_clock::time_point display_time_point, bool need_reconstrain) noexcept
Update the constraints of the widget.
abstract_container_widget const & parent() const noexcept
Get a reference to the parent.
virtual aarect window_clipping_rectangle() const noexcept
Get the clipping-rectangle in window coordinates.
Definition widget.hpp:320
aarect rectangle() const noexcept
Get the rectangle in local coordinates.
Definition widget.hpp:340
T max(T... args)
T move(T... args)
T swap(T... args)