ASW Lib
A.D.S. Games SDL Wrapper Library. A library targeted at Allegro4 users who want to switch to SDL3 and use modern c++.
Loading...
Searching...
No Matches
context.cpp
Go to the documentation of this file.
2
3#include <cmath>
4#include <ranges>
5
7{
8 focusables_.clear();
9 dfs(root);
10 // Keep current focus if still exists
11 if (focused_ != nullptr) {
12 auto it = std::ranges::find(focusables_, focused_);
13 if (it == focusables_.end()) {
14 set_focus(ctx, nullptr);
15 }
16 }
17 if (focused_ == nullptr && !focusables_.empty()) {
18 set_focus(ctx, focusables_.front());
19 }
20}
21
23{
24 if (focused_ == w) {
25 return;
26 }
27 if (focused_ != nullptr) {
28 focused_->on_focus_changed(ctx, false);
29 }
30 focused_ = w;
31 if (focused_ != nullptr) {
32 focused_->on_focus_changed(ctx, true);
33 }
34}
35
37{
38 if (focusables_.empty()) {
39 return;
40 }
41
42 if (focused_ == nullptr) {
43 set_focus(ctx, focusables_.front());
44 return;
45 }
46 auto it = std::ranges::find(focusables_, focused_);
47 if (it == focusables_.end()) {
48 set_focus(ctx, focusables_.front());
49 return;
50 }
51 ++it;
52 if (it == focusables_.end()) {
53 it = focusables_.begin();
54 }
55 set_focus(ctx, *it);
56}
57
59{
60 if (focusables_.empty()) {
61 return;
62 }
63
64 if (focused_ == nullptr) {
65 set_focus(ctx, focusables_.front());
66 return;
67 }
68
69 auto it = std::ranges::find(focusables_, focused_);
70 if (it == focusables_.end()) {
71 set_focus(ctx, focusables_.front());
72 return;
73 }
74
75 if (it == focusables_.begin()) {
76 it = focusables_.end();
77 }
78 --it;
79 set_focus(ctx, *it);
80}
81
82void asw::ui::FocusManager::focus_dir(Context& ctx, int dx, int dy)
83{
84 if (focusables_.empty()) {
85 return;
86 }
87
88 if (focused_ == nullptr) {
89 set_focus(ctx, focusables_.front());
90 return;
91 }
92
93 const auto& from = focused_->transform;
94 const float fx = from.get_center().x;
95 const float fy = from.get_center().y;
96
97 Widget* best = nullptr;
98 float bestScore = 1e30f;
99
100 for (Widget* w : focusables_) {
101 if (w == focused_) {
102 continue;
103 }
104 const auto& to = w->transform;
105 const float tx = to.get_center().x;
106 const float ty = to.get_center().y;
107 const float vx = tx - fx;
108 const float vy = ty - fy;
109
110 // Must be in the desired half-plane
111 if (dx != 0 && (vx * dx) <= 0.0f) {
112 continue;
113 }
114 if (dy != 0 && (vy * dy) <= 0.0f) {
115 continue;
116 }
117
118 // Score: prefer small primary-axis distance, penalize orthogonal
119 // distance.
120 const float primary = (dx != 0) ? std::abs(vx) : std::abs(vy);
121 const float ortho = (dx != 0) ? std::abs(vy) : std::abs(vx);
122
123 // Add small bias for actual Euclidean distance to break ties
124 const float dist2 = (vx * vx) + (vy * vy);
125
126 const float score = (primary * 1.0f) + (ortho * 2.0f) + (dist2 * 0.001f);
127 if (score < bestScore) {
128 bestScore = score;
129 best = w;
130 }
131 }
132
133 if (best != nullptr) {
134 set_focus(ctx, best);
135 }
136}
137
139{
140 if (w.visible && w.enabled && w.focusable) {
141 focusables_.push_back(&w);
142 }
143 for (auto const& c : w.children) {
144 dfs(*c);
145 }
146}
Shared state for the UI system.
Definition context.h:75
void focus_prev(Context &ctx)
Move focus to the previous focusable widget.
Definition context.cpp:58
void focus_dir(Context &ctx, int dx, int dy)
Move focus in a direction based on widget positions.
Definition context.cpp:82
void set_focus(Context &ctx, Widget *w)
Set focus to a specific widget.
Definition context.cpp:22
void dfs(Widget &w)
Definition context.cpp:138
void focus_next(Context &ctx)
Move focus to the next focusable widget.
Definition context.cpp:36
std::vector< Widget * > focusables_
Definition context.h:69
void rebuild(Context &ctx, Widget &root)
Rebuild the focusable widget list from the widget tree.
Definition context.cpp:6
Base class for all UI widgets.
Definition widget.h:28
bool enabled
Whether the widget is enabled.
Definition widget.h:63
bool focusable
Whether the widget can receive focus.
Definition widget.h:66
std::vector< std::unique_ptr< Widget > > children
Child widgets.
Definition widget.h:72
bool visible
Whether the widget is visible.
Definition widget.h:60
UI context and focus management for the ASW UI module.