13 glm::vec2 scroll_extent(
const Kinesis::ScrollState& scroll)
noexcept
15 const float content_h = scroll.content_bounds.height();
16 const float viewport_h = scroll.viewport_bounds.height();
17 const float max_offset_y = std::max(0.F, content_h - viewport_h);
19 const float extent_frac = content_h > 0.F ? std::clamp(viewport_h / content_h, 0.F, 1.F) : 1.F;
20 const float position_frac = max_offset_y > 0.F ? std::clamp(scroll.offset.y / max_offset_y, 0.F, 1.F) : 0.F;
22 return { position_frac, extent_frac };
26 Kinesis::ScrollState& scroll,
27 MappedState<glm::vec2>&
offset,
28 std::vector<Tracked>& tracked,
30 Mapped<glm::vec2>* indicator)
32 offset.write(scroll.offset);
33 for (
auto& t : tracked) {
34 const Kinesis::AABB2D shifted = t.base_bounds.translated(scroll.offset);
35 layer.set_bounds(t.id, shifted);
36 t.reposition(shifted);
39 if (indicator && indicator->state) {
40 indicator->state->write(scroll_extent(scroll));
41 indicator->sync(&layer);
52 buf = std::move(in_buf);
69 scroll = std::make_shared<Kinesis::ScrollState>();
70 scroll->viewport_bounds = viewport;
71 scroll->content_bounds = viewport;
73 offset = std::make_shared<MappedState<glm::vec2>>();
75 m_tracked = std::make_shared<std::vector<Tracked>>();
76 m_indicator = std::make_shared<Mapped<glm::vec2>>();
86std::function<void(uint32_t, glm::vec2,
double,
double)>
91 uint32_t, glm::vec2,
double dx,
double dy)
mutable {
93 glm::vec2(
static_cast<float>(dx),
static_cast<float>(dy)) * speed);
94 reflow(*scroll_state, *scroll_offset, *tracked, surface.
layer(),
indicator.get());
111 scroll->content_bounds.max = glm::max(
scroll->content_bounds.max, base_bounds.
max);
120 m_tracked->push_back({ .id = id, .base_bounds = base_bounds, .reposition = std::move(reposition) });
149 auto scroll_state =
scroll;
150 auto scroll_offset =
offset;
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)
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;
164 Kinesis::apply_scroll(*scroll_state, { 0.F, target - scroll_state->offset.y });
165 reflow(*scroll_state, *scroll_offset, *tracked, surface.
layer(), ind.
get());
175 glm::vec3 background_color,
181 .
place(std::move(buf), surface, viewport);
virtual std::shared_ptr< RenderProcessor > get_render_processor() const
Get a RenderProcessor suitable for rendering this buffer.
void on_scroll(uint32_t id, ScrollFn fn)
Called on scroll while the cursor is over an element.
void on_drag(uint32_t id, IO::MouseButtons btn, MoveFn fn)
Called on each mouse-move event while btn is held, tracking the element where the drag began even whe...
void apply_scroll(NavigationState &st, float ticks)
Dolly eye along the current forward vector.
std::array< Kakshya::Vertex, 4 > filled_rect(Kinesis::AABB2D region, glm::vec3 color)
Generate a filled TRIANGLE_STRIP quad from an AABB2D.
AABB2D translated(glm::vec2 offset) const noexcept
Axis-aligned bounding rectangle in a 2D coordinate space.
static Scissor from(AABB2D ndc_bounds) noexcept
Construct directly from an NDC AABB2D.