MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches

◆ place() [2/2]

Dropdown & MayaFlux::Portal::Forma::Dropdown::place ( Surface &  surface,
LayoutCursor &  cursor,
float  x_min,
float  x_max,
float  row_h 
)

Register the header and its option rows and wire their input.

Advances cursor by row_h. With no options, logs a warning and leaves the struct unplaced.

Parameters
surfaceSurface to register on.
cursorLayout cursor. Advanced by row_h on return.
x_minLeft edge in NDC.
x_maxRight edge in NDC.
row_hHeight of the header and of each option row, in NDC units.
Returns
*this, with results populated.

Definition at line 22 of file Dropdown.cpp.

26{
27 if (m_labels.empty()) {
29 "Dropdown::place: no options");
30 return *this;
31 }
32
33 auto& ctx = surface.ctx();
34 const auto layer_ptr = surface.layer_ptr();
35
36 const Kinesis::AABB2D advanced = cursor.advance(row_h);
37 const Kinesis::AABB2D header_rect {
38 .min = { x_min, advanced.min.y },
39 .max = { x_max, advanced.max.y },
40 };
41
42 const auto labels = std::make_shared<std::vector<std::string>>(m_labels);
43 const size_t initial = std::min(m_initial, labels->size() - 1);
44 const auto dims = std::make_shared<glm::uvec2>(
45 row_pixel_dims(surface.window(), x_min, x_max, row_h));
46
47 auto header = internal::add_text_row(surface, header_label(labels->at(initial), false), header_rect, *dims);
48 const uint32_t hid = header.first;
49 const auto& header_row = header.second;
50
51 auto selected_state = std::make_shared<MappedState<size_t>>();
52 selected_state->write(initial);
53 auto open_state = std::make_shared<MappedState<bool>>();
54 open_state->write(false);
55
56 auto refresh_header = [header_row, labels, selected_state, open_state, dims]() {
57 header_row->set_text(
58 internal::row_caption(header_label(labels->at(selected_state->value), open_state->value)),
60 };
61
62 auto set_open = [layer_ptr, hid, open_state, refresh_header](bool next) {
63 open_state->write(next);
64 for (const uint32_t rel_id : layer_ptr->related_ids(hid))
65 layer_ptr->set_visible(rel_id, next);
66 if (next)
67 layer_ptr->bring_to_front(hid);
68 refresh_header();
69 };
70
71 auto choose = [selected_state, set_open, callback = m_on_select](size_t index) {
72 selected_state->write(index);
73 set_open(false);
74 if (callback)
76 };
77
78 const auto count = static_cast<uint32_t>(labels->size());
79 const uint32_t visible = std::min(count, m_max_visible);
80 const float list_top = header_rect.min.y;
81
82 const auto text_batch = internal::atelier().create_buffer(
83 surface.render_config({ .additional_textures = { { "text", nullptr } } }));
84
85 std::optional<Scrollable> panel;
86 std::function<void(uint32_t, glm::vec2, double, double)> wheel;
87 if (count > visible) {
89 panel = make_scrollable(
90 std::move(panel_buf), surface,
91 { .min = { x_min, list_top - row_h * static_cast<float>(visible) }, .max = { x_max, list_top } },
92 glm::vec3(internal::row_idle_color()));
93 wheel = panel->wheel_handler(surface);
94 layer_ptr->relate(hid, panel->viewport_id);
95 }
96
97 const auto rows = std::make_shared<std::vector<std::shared_ptr<Element>>>();
98
99 for (uint32_t i = 0; i < count; ++i) {
100 const float top = list_top - row_h * static_cast<float>(i);
101 const Kinesis::AABB2D row_rect { .min = { x_min, top - row_h }, .max = { x_max, top } };
102
103 auto made = internal::add_text_row(surface, labels->at(i), row_rect, *dims, text_batch);
104 const uint32_t id = made.first;
105 const auto& row = made.second;
106 rows->push_back(row);
107
108 internal::hover_text_row(surface, id, row, labels->at(i), dims);
109 ctx.on_press(id, IO::MouseButtons::Left, [choose, i](uint32_t, glm::vec2) { choose(i); });
110
111 if (panel) {
112 ctx.on_scroll(id, wheel);
113 panel->track(
114 *layer_ptr, id, row_rect,
115 [row](Kinesis::AABB2D shifted) { row->retarget(shifted); },
116 row->buffer);
117 } else {
118 layer_ptr->relate(hid, id);
119 }
120 }
121
122 ctx.on_press(hid, IO::MouseButtons::Left,
123 [open_state, set_open](uint32_t, glm::vec2) { set_open(!open_state->value); });
124
125 ctx.on_resize(hid,
126 [window = surface.window(), x_min, x_max, row_h, dims, labels, rows, refresh_header](uint32_t, uint32_t) {
127 *dims = row_pixel_dims(window, x_min, x_max, row_h);
128 refresh_header();
129 const auto idle = internal::row_press_params(*dims, internal::row_idle_color());
130 for (size_t i = 0; i < rows->size(); ++i)
131 rows->at(i)->set_text(internal::row_caption(labels->at(i)), idle);
132 });
133
134 set_open(false);
135
137 ElementRef { layer_ptr, hid }, selected_state, header_row->buffer.buffer());
138
139 header_id = hid;
140 selected = std::move(selected_state);
141 open = std::move(open_state);
142 header_bounds = header_rect;
143 cursor_out = cursor;
144 return *this;
145}
#define MF_WARN(comp, ctx,...)
uint32_t rows
PickCallback callback
Definition Picker.cpp:22
std::weak_ptr< Core::Window > window
Definition Picker.cpp:23
uint32_t index
Definition VKDevice.cpp:122
size_t count
void register_element(const ElementRef &ref, std::shared_ptr< MappedState< T > > state, std::shared_ptr< Buffers::FormaBuffer > buffer, std::function< float(T)> project={})
Register a MappedState<T> so that MappedState overloads and outbound bindings can resolve to the corr...
Definition Bridge.hpp:378
static FormaTarget slice_of(const std::shared_ptr< Buffers::FormaBuffer > &buffer, std::optional< Graphics::PrimitiveTopology > topology=std::nullopt)
A new empty slice of buffer, drawn after the others.
Definition Target.cpp:19
std::shared_ptr< Buffers::FormaBuffer > create_buffer(Graphics::RenderConfig render)
The single buffer construction path.
Definition Atelier.cpp:117
Bridge & bridge()
Bridge instance constructed during initialize.
Definition Atelier.cpp:80
@ API
API calls from external code.
@ Portal
High-level user-facing API layer.
Text::PressParams row_press_params(glm::uvec2 dims, glm::vec4 background)
White text over background, laid out at dims pixels.
Definition TextRow.cpp:18
std::pair< uint32_t, std::shared_ptr< Element > > add_text_row(Surface &surface, std::string_view label, Kinesis::AABB2D bounds, glm::uvec2 dims, const std::shared_ptr< Buffers::FormaBuffer > &batch)
Register a clickable text row on surface.
Definition TextRow.cpp:28
Atelier & atelier()
Accessor for the process-wide Atelier.
Definition Atelier.hpp:304
void hover_text_row(Surface &surface, uint32_t id, const std::shared_ptr< Element > &row, std::string_view label, const std::shared_ptr< glm::uvec2 > &dims)
Highlight a row's background while the cursor is over it.
Definition TextRow.cpp:49
std::string row_caption(std::string_view label)
Caption drawn for a row labelled label.
Definition TextRow.cpp:13
std::pair< std::weak_ptr< Layer >, uint32_t > ElementRef
Layer-scoped element identity.
Definition Bridge.hpp:34
Scrollable make_scrollable(FormaTarget buf, Surface &surface, Kinesis::AABB2D viewport, glm::vec3 background_color, float wheel_speed)
Construct a scrollable viewport.
glm::uvec2 row_pixel_dims(const std::shared_ptr< Core::Window > &window, float x_min, float x_max, float row_h)
Convert an NDC row rect into integer pixel dimensions.
Definition Entry.cpp:12
std::shared_ptr< MappedState< size_t > > selected
Index of the chosen option. Valid after place().
Definition Dropdown.hpp:36
std::function< void(size_t)> m_on_select
Called with the index each time a row is chosen.
Definition Dropdown.hpp:60
std::vector< std::string > m_labels
Option captions, in display order.
Definition Dropdown.hpp:51
uint32_t m_max_visible
Rows shown at once before the list scrolls. Default: 8.
Definition Dropdown.hpp:57
Dropdown & initial(size_t index)
Definition Dropdown.hpp:68
std::shared_ptr< MappedState< bool > > open
Whether the list is showing. Valid after place().
Definition Dropdown.hpp:39
uint32_t header_id
Element id of the header strip. Valid after place().
Definition Dropdown.hpp:33
Kinesis::AABB2D header_bounds
NDC region occupied by the header strip. Valid after place().
Definition Dropdown.hpp:45
size_t m_initial
Index chosen before any interaction. Default: 0.
Definition Dropdown.hpp:54
LayoutCursor cursor_out
Cursor positioned below the header. Valid after place().
Definition Dropdown.hpp:42
MAYAFLUX_API std::function< void(uint32_t, glm::vec2, double, double)> wheel_handler(Surface &surface) const
A self-contained wheel-scroll handler bound to this Scrollable's own state.

References MayaFlux::Portal::Forma::internal::add_text_row(), MayaFlux::Portal::Forma::LayoutCursor::advance(), MayaFlux::Journal::API, MayaFlux::Portal::Forma::internal::atelier(), callback, count, MayaFlux::Portal::Forma::internal::Atelier::create_buffer(), MayaFlux::Portal::Forma::Surface::ctx(), index, initial(), MayaFlux::Portal::Forma::Surface::layer_ptr(), m_initial, m_labels, m_max_visible, m_on_select, MayaFlux::Kinesis::AABB2D::max, MF_WARN, MayaFlux::Kinesis::AABB2D::min, MayaFlux::Journal::Portal, MayaFlux::Portal::Forma::Surface::render_config(), MayaFlux::Portal::Forma::internal::row_caption(), MayaFlux::Portal::Forma::internal::row_idle_color(), MayaFlux::Portal::Forma::row_pixel_dims(), MayaFlux::Portal::Forma::internal::row_press_params(), and MayaFlux::Portal::Forma::Surface::window().

+ Here is the call graph for this function: