TachyonUI 0.1.0
High-performance UI for building tools.
Loading...
Searching...
No Matches
gui_default_handlers.h
Go to the documentation of this file.
1#pragma once
2
6
8
10#include <gui_core/style/gui_style_text.h> // TextID, IconID (used by value)
11
13
16
17#include <algorithm>
18#include <cmath>
19#include <vector>
20#include <memory>
21#include <stdint.h>
22#include <type_traits>
23
24namespace tachyon
25{
28
29 class ElementStorage;
30 class ITextSystem;
31 class StyleManager;
32
34 inline bool IsActivationKey(const ElementEvent& event)
35 {
36 if (event.type != EventType::KeyDown) return false;
37 return event.state.lastKey == tachyon::KeyCode::Return ||
38 event.state.lastKey == tachyon::KeyCode::Return2 ||
39 event.state.lastKey == tachyon::KeyCode::KeyPadEnter ||
40 event.state.lastKey == tachyon::KeyCode::Space;
41 }
42
43
46 bool TextEditorUsesKey(const InputState& state, bool readOnly);
47
51
52
62
69 int& sizeValue, int minSize, int maxSize,
70 std::function<void(int)> onChanged = nullptr,
71 std::function<int()> onAutoSize = nullptr,
72 bool invertMouseDelta = false, float pixelsPerUnit = 1.0f);
73
77 int& sizeValue, int minSize, int maxSize,
78 std::function<void(int)> onChanged = nullptr,
79 std::function<int()> onAutoSize = nullptr,
80 bool invertMouseDelta = false, float pixelsPerUnit = 1.0f);
81
84 {
86 float startValue = 0.0f;
87 bool editMode = false;
88 };
89
92 enum class SliderPress : uint8_t { Edit, Jump };
93
97 EventHandler MakeSliderHandler(GUIStateManager& guiStateManager, const ElementStorage& elementStorage,
98 float* value, int elementWidth,
99 std::function<void()> onChanged = nullptr,
100 float minVal = 0.0f, float maxVal = 1.0f,
102
105 {
107 };
108
112
114 EventHandler MakeLabelHandler(GUIStateManager& guiStateManager, const ElementStorage& elementStorage);
115
128
130 EventHandler MakeGroupLabelHandler(GUIStateManager& guiStateManager, const ElementStorage& elementStorage, LabelGroupVisualState groupVisual);
132
134 EventHandler MakeButtonHandler(GUIStateManager& guiStateManager, std::function<void()> onClick);
135
138 EventHandler MakeMouseWheelScrollHandler(ScrollManagement& scrollManagement, float wheelStep);
139
147
150 constexpr int32_t kScrollbarMinThumbLength = 20;
151
157 ElementStorage& elementStorage,
158 ID containerID, bool vertical,
159 int32_t trackLength = 0);
160
164 uint32_t payloadType,
165 std::function<uintptr_t()> getPayloadValue = nullptr,
166 std::function<std::any()> getPayload = nullptr,
167 DragVisualizer sourceVisualizer = {});
168
172 EventHandler MakeDropTargetHandler(uint32_t acceptedPayloadType,
173 std::function<void(uintptr_t payloadValue, ID sourceID)> onDrop,
174 std::function<bool(uintptr_t payloadValue)> canDrop = nullptr);
175
176
177
179 inline double LabelDragSpeedScale(const InputState& state)
180 {
181 double speed = 1.0;
182 if ((state.modifiers & KeyModifier::Control) != KeyModifier::None) speed = 0.1;
183 if ((state.modifiers & KeyModifier::Shift) != KeyModifier::None) speed = 10.0;
184 return speed;
185 }
186
190 template<typename T>
191 inline EventHandler ReportingChanges(GUIStateManager& guiStateManager, T* value, EventHandler inner)
192 {
193 return [&guiStateManager, value, inner = std::move(inner)](ElementEvent&& event) -> bool
194 {
195 const T before = *value;
196 const ID id = event.id;
197 const bool used = inner(std::move(event));
198 if (!(*value == before))
199 guiStateManager.Interaction().SetClicked(id);
200 return used;
201 };
202 }
203
206 template<typename T>
207 inline EventHandler MakeNumericalBoxHandler(GUIStateManager& guiStateManager, T& value, NumericFieldConfig<T> config = {})
208 {
209 struct LabelDragSnapshot { T startValue{}; };
210
211 return [&guiStateManager, &value, config](ElementEvent&& event)->bool
212 {
213 auto& store = guiStateManager.GetElementDataStore();
214 switch (event.type)
215 {
217 if (event.state.LeftPressed())
218 {
219 guiStateManager.Interaction().SetFocusID(event.id);
220 guiStateManager.TextEditorFocus().Set(event.id);
221 return true;
222 }
223 break;
224
226 case EventType::KeyUp:
228 if (guiStateManager.Interaction().GetFocusedID() == event.id && !event.state.consumed)
229 return event.type == EventType::TextInput ? !event.state.textInput.empty()
230 : TextEditorUsesKey(event.state, /*readOnly*/ false);
231 break;
232
234 {
235 auto& snapshot = store.GetOrCreate<LabelDragSnapshot>(event.id);
236 snapshot.startValue = value;
237 if constexpr (std::is_floating_point_v<T>)
238 if (!std::isfinite(snapshot.startValue)) { snapshot.startValue = T(0); value = T(0); }
239 return true;
240 }
241
243 {
244 auto* snapshot = store.Get<LabelDragSnapshot>(event.id);
245 if (!snapshot) return false;
246 T newVal = config.Calculate(static_cast<int32_t>(event.state.scroll.x), LabelDragSpeedScale(event.state), snapshot->startValue);
247 value = newVal;
248 return true;
249 }
250
252 return true;
253
255 if (auto* snapshot = store.Get<LabelDragSnapshot>(event.id))
256 value = snapshot->startValue;
257 return true;
258
259 default:
260 break;
261 }
262
263 return false;
264 };
265 }
266
267
268
270 template<typename T>
271 inline EventHandler MakeMultiDimDragHandler(GUIStateManager& guiStateManager, T& value,
273 {
274 using ComponentT = std::remove_reference_t<decltype(TypeDimensions<T>::GetComponent(value, 0))>;
275
276 // Value at drag start; in the element data store since handlers are rebuilt every frame.
277 struct Snapshot { T startValue{}; };
278
279 return [&guiStateManager, &value, config](ElementEvent&& event) -> bool
280 {
281 auto& store = guiStateManager.GetElementDataStore();
282 switch (event.type)
283 {
285 {
286 auto& snapshot = store.GetOrCreate<Snapshot>(event.id);
287 snapshot.startValue = value;
288 if constexpr (std::is_floating_point_v<ComponentT>)
289 for (int i = 0; i < TypeDimensions<T>::dimensions; i++)
290 {
291 ComponentT& comp = TypeDimensions<T>::GetComponent(value, i);
292 ComponentT& startComp = TypeDimensions<T>::GetComponent(snapshot.startValue, i);
293 if (!std::isfinite(startComp)) { startComp = ComponentT(0); comp = ComponentT(0); }
294 }
295 return true;
296 }
297
299 {
300 auto* snapshot = store.Get<Snapshot>(event.id);
301 if (!snapshot) return false;
302 double speed = LabelDragSpeedScale(event.state);
303 for (int i = 0; i < TypeDimensions<T>::dimensions; i++)
304 {
305 ComponentT& comp = TypeDimensions<T>::GetComponent(value, i);
306 ComponentT startComp = TypeDimensions<T>::GetComponent(snapshot->startValue, i);
307 comp = config.Calculate(static_cast<int32_t>(event.state.scroll.x), speed, startComp);
308 }
309 return true;
310 }
311
313 return true;
314
316 if (auto* snapshot = store.Get<Snapshot>(event.id))
317 value = snapshot->startValue;
318 return true;
319
320 default:
321 break;
322 }
323 return false;
324 };
325 }
326
327}
The frame's element tree.
Definition gui_element_storage.h:100
Owns the per-frame state objects and runs their BeginFrame / EndFrame in order.
Definition gui_state_manager.h:65
ElementDataStore & GetElementDataStore()
Definition gui_state_manager.h:108
InteractionState & Interaction()
Definition gui_state_manager.h:87
TextEditorFocusState & TextEditorFocus()
Definition gui_state_manager.h:96
Text and icon registration, measurement, rendering and editing.
Definition gui_text_system.h:178
void SetClicked(ID id)
Definition gui_interaction_state.h:85
ID GetFocusedID() const
Definition gui_interaction_state.h:63
void SetFocusID(ID id)
Definition gui_interaction_state.h:71
Scroll containers' offsets (pixels), kept across frames by ID behind handles.
Definition gui_scroll_management.h:33
Bakes serializable Styles into deduplicated runtime layout/visual styles; a StyleRef holds indices in...
Definition gui_style_manager.h:39
void Set(ID id)
Definition gui_state_atomic_values.h:42
constexpr int32_t kScrollbarMinThumbLength
Minimum thumb length in CSS pixels (scale with StyleManager::Px), so the thumb stays clickable over h...
Definition gui_default_handlers.h:150
EventHandler MakeDropTargetHandler(uint32_t acceptedPayloadType, std::function< void(uintptr_t payloadValue, ID sourceID)> onDrop, std::function< bool(uintptr_t payloadValue)> canDrop=nullptr)
Drop target handler for acceptedPayloadType; onDrop gets the payload value and the source ID.
bool TextEditorUsesKey(const InputState &state, bool readOnly)
Whether a focused text editor acts on this key (KeyDown/KeyUp), so its handler takes it; the rest rea...
EventHandler MakeButtonHandler(GUIStateManager &guiStateManager, std::function< void()> onClick)
Button handler: a left click, or an activation key while focused, calls onClick.
EventHandler MakeDragSourceHandler(GUIStateManager &guiStateManager, uint32_t payloadType, std::function< uintptr_t()> getPayloadValue=nullptr, std::function< std::any()> getPayload=nullptr, DragVisualizer sourceVisualizer={})
Drag source handler: a left press starts a drag of payloadType, with the value from getPayloadValue (...
EventHandler MakeGroupLabelHandler(GUIStateManager &guiStateManager, const ElementStorage &elementStorage, LabelGroupVisualState groupVisual)
Label group variants: the right edge resizes the shared label width.
EventHandler MakeGroupDraggableLabelHandler(GUIStateManager &guiStateManager, const ElementStorage &elementStorage, LabelGroupVisualState groupVisual)
EventHandler MakeDraggableLabelHandler(GUIStateManager &guiStateManager, const ElementStorage &elementStorage)
Turns mouse drags on a label into LabelDrag* events sent to the next sibling element.
bool IsActivationKey(const ElementEvent &event)
True for a KeyDown of Return, keypad Enter or Space.
Definition gui_default_handlers.h:34
EventHandler MakeHorizontalSizerHandler(GUIStateManager &guiStateManager, const ElementStorage &elementStorage, int &sizeValue, int minSize, int maxSize, std::function< void(int)> onChanged=nullptr, std::function< int()> onAutoSize=nullptr, bool invertMouseDelta=false, float pixelsPerUnit=1.0f)
Sizer handler that drags sizeValue within [minSize, maxSize], calling onChanged with each new size.
EventHandler MakeNumericalBoxHandler(GUIStateManager &guiStateManager, T &value, NumericFieldConfig< T > config={})
Numeric field handler: a left click focuses it for typing, and LabelDrag* events from its label drag ...
Definition gui_default_handlers.h:207
EventHandler MakeMouseWheelScrollHandler(ScrollManagement &scrollManagement, float wheelStep)
Wheel handler that scrolls the element's own scroll offset by wheelStep pixels per notch (StyleManage...
EventHandler MakeScrollbarHandler(GUIStateManager &guiStateManager, ElementStorage &elementStorage, ID containerID, bool vertical, int32_t trackLength=0)
Scrollbar track/thumb handler; writes the scroll offset of containerID (the scrollable parent).
SliderPress
What pressing a slider does: Edit - a click (no drag) opens its value for typing; Jump - the value mo...
Definition gui_default_handlers.h:92
EventHandler MakeSliderHandler(GUIStateManager &guiStateManager, const ElementStorage &elementStorage, float *value, int elementWidth, std::function< void()> onChanged=nullptr, float minVal=0.0f, float maxVal=1.0f, SliderPress press=SliderPress::Edit)
Slider handler for *value in [minVal, maxVal]; elementWidth (pixels, <= 0 is treated as 1) maps drag ...
EventHandler MakeLabelHandler(GUIStateManager &guiStateManager, const ElementStorage &elementStorage)
Label handler: a left click focuses the control bound to the label (else the label).
EventHandler MakeTextBoxHandler(GUIStateManager &guiStateManager)
Text box handler: a left click focuses it for editing; while focused it takes text input and the keys...
EventHandler ReportingChanges(GUIStateManager &guiStateManager, T *value, EventHandler inner)
Wraps a handler that writes *value: it runs during input, after the control's call returned,...
Definition gui_default_handlers.h:191
double LabelDragSpeedScale(const InputState &state)
Label-drag speed multiplier: 0.1 with Ctrl, 10 with Shift (which wins), else 1.
Definition gui_default_handlers.h:179
EventHandler MakeMultiDimDragHandler(GUIStateManager &guiStateManager, T &value, NumericFieldConfig< typename TypeDimensions< T >::ComponentType > config={})
Applies LabelDrag* events to all components (multi-dimensional Field groups).
Definition gui_default_handlers.h:271
EventHandler MakeVerticalSizerHandler(GUIStateManager &guiStateManager, const ElementStorage &elementStorage, int &sizeValue, int minSize, int maxSize, std::function< void(int)> onChanged=nullptr, std::function< int()> onAutoSize=nullptr, bool invertMouseDelta=false, float pixelsPerUnit=1.0f)
Y-axis counterpart of MakeHorizontalSizerHandler; invertMouseDelta grows the size when dragging up.
@ Jump
Definition gui_default_handlers.h:92
@ Edit
Definition gui_default_handlers.h:92
std::function< void(const DragVisualContext &context)> DragVisualizer
Draws the dragged item while a drag is in progress.
Definition gui_drag_drop_state.h:33
std::function< bool(ElementEvent &&input)> EventHandler
Element-level input handler used by the immediate-mode dispatcher; returns true when it consumed the ...
Definition gui_input_handler_func.h:35
@ Return2
Definition gui_input_enums.h:307
@ Return
Definition gui_input_enums.h:109
@ KeyPadEnter
Definition gui_input_enums.h:215
@ Space
Definition gui_input_enums.h:113
@ LabelDragBegin
label -> control: drag starting; state.scroll.x = 0
Definition gui_input_enums.h:89
@ KeyUp
Definition gui_input_enums.h:82
@ LabelDrag
label -> control: drag in progress; state.scroll.x = pixels moved since the start
Definition gui_input_enums.h:91
@ LabelDragEnd
label -> control: drag committed
Definition gui_input_enums.h:92
@ MouseDown
which button: state.buttons & ~state.prevButtons
Definition gui_input_enums.h:78
@ TextInput
Definition gui_input_enums.h:83
@ KeyDown
Definition gui_input_enums.h:81
@ LabelDragCancel
label -> control: drag cancelled (Escape)
Definition gui_input_enums.h:93
@ None
Definition gui_input_enums.h:27
@ Shift
Definition gui_input_enums.h:28
@ Control
Definition gui_input_enums.h:29
Definition gui_logging.h:24
Click-gesture tracker, owned per widget instance so instances (and tests) don't share it.
Definition gui_widget_state_types.h:75
Per-element state of a draggable label (element data store); internal.
Definition gui_default_handlers.h:105
PointerDrag drag
the press; a drag once it moves the drag distance
Definition gui_default_handlers.h:106
An input event delivered to an element's EventHandler.
Definition gui_input_handler_func.h:20
EventType type
Definition gui_input_handler_func.h:22
A 64-bit element ID whose bit layout depends on its IDMode.
Definition gui_id.h:23
static constexpr ID Invalid()
The "no element" ID (all bits zero); also the default for optional ID parameters.
Definition gui_id.h:66
Snapshot of input state for a single recorded OS event.
Definition gui_input_state.h:17
tachyon::KeyModifier modifiers
Definition gui_input_state.h:25
Shared by all labels in a group, so the edge highlight is synchronized.
Definition gui_default_handlers.h:117
const StyleManager * styleManager
for resolving label padding
Definition gui_default_handlers.h:125
ITextSystem * textSystem
for measuring label text widths
Definition gui_default_handlers.h:124
std::vector< TextID > * labelTextIDs
for double-click auto-size
Definition gui_default_handlers.h:123
bool * edgeHovered
a label's resize edge is hovered
Definition gui_default_handlers.h:121
int32_t * sharedWidth
the group's label width, CSS px
Definition gui_default_handlers.h:118
int32_t maxWidth
CSS px.
Definition gui_default_handlers.h:120
StyleRef labelStyleRef
Definition gui_default_handlers.h:126
int32_t minWidth
CSS px.
Definition gui_default_handlers.h:119
bool * edgeDragging
a label's resize edge is being dragged
Definition gui_default_handlers.h:122
Drag speed and range of a numeric Field, specialized per value type.
Definition gui_numeric_field_config.h:19
One press on an element that may become a drag.
Definition gui_pointer_drag.h:41
Per-element state of MakeScrollbarHandler (element data store); internal.
Definition gui_default_handlers.h:142
PointerDrag drag
a drag from the press on
Definition gui_default_handlers.h:143
int startScroll
scroll position before the press; put back by Escape
Definition gui_default_handlers.h:145
int thumbGrabOffset
cursor offset from the thumb's near edge at drag start, pixels
Definition gui_default_handlers.h:144
Per-element state of the sizer handlers (element data store); internal.
Definition gui_default_handlers.h:55
PointerDrag drag
a drag from the press on
Definition gui_default_handlers.h:56
ID previousTextFocusID
Definition gui_default_handlers.h:58
DoubleClickTracker clicks
a double-click auto-sizes
Definition gui_default_handlers.h:60
int startSize
put back by Escape
Definition gui_default_handlers.h:59
ID previousFocusID
focus to give back after the drag
Definition gui_default_handlers.h:57
Per-element state of MakeSliderHandler and the integer slider (element data store); internal.
Definition gui_default_handlers.h:84
bool editMode
set by a clean click: in-place text editing
Definition gui_default_handlers.h:87
float startValue
put back by Escape and a cancelled label drag
Definition gui_default_handlers.h:86
PointerDrag drag
the press on the bar
Definition gui_default_handlers.h:85
A registered style, as StyleManager::Register returns it: indices into the shared style pools,...
Definition gui_style_ref.h:25
T ComponentType
Definition gui_type_dimensions.h:14
static T & GetComponent(T &value, int)
Definition gui_type_dimensions.h:16