HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
button_widget.hpp
1// Copyright Take Vos 2019-2020.
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_button_widget.hpp"
8#include "../stencils/label_stencil.hpp"
9#include "../label.hpp"
10#include <memory>
11#include <string>
12#include <array>
13#include <optional>
14#include <future>
15
16namespace tt {
17
18template<typename T>
19class button_widget final : public abstract_button_widget<T> {
20public:
22 using value_type = T;
23
25
26 template<typename Value = observable<value_type>>
30 value_type true_value,
31 Value &&value = {}) noexcept :
32 super(window, parent, std::move(true_value), std::forward<Value>(value))
33 {
34 }
35
36 void init() noexcept override
37 {
38 _label_callback = label.subscribe([this](auto...) {
39 this->_request_reconstrain = true;
40 });
41
42 _callback = this->subscribe([this](auto...) {
43 this->clicked();
44 });
45 }
46
47 [[nodiscard]] bool update_constraints(hires_utc_clock::time_point display_time_point, bool need_reconstrain) noexcept override
48 {
49 tt_axiom(gui_system_mutex.recurse_lock_count());
50
51 if (super::update_constraints(display_time_point, need_reconstrain)) {
52 _label_stencil = stencil::make_unique(alignment::middle_center, *label, theme::global->labelStyle);
53 this->_preferred_size = interval_vec2::make_minimum(_label_stencil->preferred_extent() + theme::global->margin2Dx2);
54 return true;
55 } else {
56 return false;
57 }
58 }
59
60 [[nodiscard]] void update_layout(hires_utc_clock::time_point displayTimePoint, bool need_layout) noexcept override
61 {
62 tt_axiom(gui_system_mutex.recurse_lock_count());
63
64 need_layout |= std::exchange(this->_request_relayout, false);
65 if (need_layout) {
66 _label_stencil->set_layout_parameters(this->rectangle(), this->base_line());
67 }
68 super::update_layout(displayTimePoint, need_layout);
69 }
70
71 void draw(draw_context context, hires_utc_clock::time_point display_time_point) noexcept override
72 {
73 tt_axiom(gui_system_mutex.recurse_lock_count());
74
75 if (overlaps(context, this->window_clipping_rectangle())) {
76 context.corner_shapes = f32x4::broadcast(theme::global->roundingRadius);
77 if (*this->value) {
78 context.fill_color = theme::global->accentColor;
79 }
80
81 // Move the border of the button in the middle of a pixel.
82 context.draw_box_with_border_inside(this->rectangle());
83
84 if (*this->enabled) {
85 context.line_color = theme::global->foregroundColor;
86 }
87 context.transform = translate3{0.0f, 0.0f, 0.1f} * context.transform;
88 _label_stencil->draw(context, true);
89 }
90
91 super::draw(std::move(context), display_time_point);
92 }
93
94 void clicked() noexcept
95 {
96 ttlet lock = std::scoped_lock(gui_system_mutex);
97 if (compare_then_assign(this->value, !this->value)) {
98 this->window.request_redraw(this->window_clipping_rectangle());
99 }
100 }
101
102private:
103 typename decltype(label)::callback_ptr_type _label_callback;
104 super::callback_ptr_type _callback;
105
106 std::unique_ptr<label_stencil> _label_stencil;
107};
108
109} // namespace tt
Definition translate.hpp:14
Draw context for drawing using the TTauri shaders.
Definition draw_context.hpp:33
Definition gui_window.hpp:39
void request_redraw(aarect rectangle=aarect::infinity()) noexcept
Request a rectangle on the window to be redrawn.
Definition gui_window.hpp:115
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 button widget.
Definition abstract_button_widget.hpp:16
callback_ptr_type subscribe(Callback &&callback) noexcept
Subscribe a callback to call when the button is activated.
Definition abstract_button_widget.hpp:109
Definition button_widget.hpp:19
void init() noexcept override
Should be called right after allocating and constructing a widget.
Definition button_widget.hpp:36
void draw(draw_context context, hires_utc_clock::time_point display_time_point) noexcept override
Draw the widget.
Definition button_widget.hpp:71
bool update_constraints(hires_utc_clock::time_point display_time_point, bool need_reconstrain) noexcept override
Update the constraints of the widget.
Definition button_widget.hpp:47
void update_layout(hires_utc_clock::time_point displayTimePoint, bool need_layout) noexcept override
Update the internal layout of the widget.
Definition button_widget.hpp:60
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 move(T... args)