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

◆ indicator()

Scrollable & MayaFlux::Portal::Forma::Scrollable::indicator ( Surface &  surface,
Mapped< glm::vec2 >  el,
Kinesis::AABB2D  track 
)

Attach a caller-built element as a live, draggable scroll indicator.

Scrollable draws nothing itself. Build whatever Mapped<glm::vec2> your own geometry function produces - a bar, a squiggle, a sampled texture, anything computable from (position_frac, extent_frac) - via Portal::Forma::create<glm::vec2>, register it, and hand it here. position_frac is 0 at the top of content_bounds and 1 at the fully scrolled bottom; extent_frac is the viewport/content height ratio (how much of the content is visible at once), so a geometry function can size its own drawing without asking Scrollable anything further.

On every scroll - wheel (place()'s default wiring), scroll_by(), or dragging this same element - the live fraction pair is written to el.state and el.sync() is called, the same "call sync() straight from the handler that changed the value, no polling" idiom Collapsible's own on_press already uses. track() also refreshes extent_frac (without a Layer, so el's hit region only, not bounds_hint, can lag very slightly until the next scroll - self-corrects on the first interaction after).

Also wires on_drag on el.element.id: dragging maps the cursor's NDC y absolutely onto content offset within track, the same inverse-mapping idiom Geometry::vertical_fader uses for its own handle, routed through scroll_by() so drag and wheel scrolling stay in sync through one path. No handle-size compensation is applied, unlike vertical_fader - an indicator has no fixed rendered size for Scrollable to know about.

Parameters
surfaceSurface owning the same Layer/Context place() used.
elCaller's Mapped<glm::vec2>, already registered on surface's Layer.
trackNDC region the drag is measured against; its full height maps to the full scrollable range.
Returns
*this, for chaining - see track()'s
.

Definition at line 140 of file Scrollable.cpp.

141{
142 if (!scroll || !offset || !m_tracked || !m_indicator)
143 return *this;
144
145 *m_indicator = std::move(el);
146 m_indicator->state->write(scroll_extent(*scroll));
147 m_indicator->sync(&surface.layer());
148
149 auto scroll_state = scroll;
150 auto scroll_offset = offset;
151 auto tracked = m_tracked;
152 auto ind = m_indicator;
153
154 surface.ctx().on_drag(ind->element.id, IO::MouseButtons::Left,
155 [scroll_state, scroll_offset, tracked, ind, surface, track](uint32_t, glm::vec2 ndc) mutable {
156 const float max_offset_y = std::max(0.F,
157 scroll_state->content_bounds.height() - scroll_state->viewport_bounds.height());
158 if (max_offset_y <= 0.F)
159 return;
160
161 const float frac = std::clamp((track.max.y - ndc.y) / track.height(), 0.F, 1.F);
162 const float target = frac * max_offset_y;
163
164 Kinesis::apply_scroll(*scroll_state, { 0.F, target - scroll_state->offset.y });
165 reflow(*scroll_state, *scroll_offset, *tracked, surface.layer(), ind.get());
166 });
167
168 return *this;
169}
std::shared_ptr< MappedState< glm::vec2 > > offset
Reactive mirror of scroll->offset, bound into cursor_out. Valid after place().
std::shared_ptr< Mapped< glm::vec2 > > m_indicator
MAYAFLUX_API Scrollable & track(Layer &layer, uint32_t id, Kinesis::AABB2D base_bounds, std::function< void(Kinesis::AABB2D)> reposition, const FormaTarget &clip_buf={})
Register an element for scroll reflow.
std::shared_ptr< std::vector< Tracked > > m_tracked
std::shared_ptr< Kinesis::ScrollState > scroll
Clamped scroll offset and content/viewport extents. Valid after place().

References MayaFlux::Portal::Forma::Surface::ctx(), MayaFlux::Portal::Forma::Layer::get(), MayaFlux::Portal::Forma::Surface::layer(), MayaFlux::IO::Left, m_indicator, m_tracked, offset, MayaFlux::Portal::Forma::Context::on_drag(), scroll, and track().

Referenced by wheel_handler().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: