Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
virtual_grid.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <atomic>
5#include <cstddef>
6#include <cstdint>
7#include <functional>
8#include <memory>
9#include <optional>
10#include <typeindex>
11#include <vector>
12
13#include <pulp/view/view.hpp>
16
17namespace pulp::view {
18
33class VirtualGrid : public View {
34public:
35 enum class SelectionMode { none, single, multi };
36
37 using CellFactory = std::function<std::unique_ptr<View>(std::size_t slot)>;
38 using CellBinder = std::function<void(View& cell, std::size_t index)>;
39 using CellReleaser = std::function<void(View& cell)>;
40
42 ~VirtualGrid() override;
43
44 void set_item_count(std::size_t n);
45 std::size_t item_count() const { return item_count_; }
46
47 void set_cell_size(float width, float height);
48 float cell_width() const { return cell_w_; }
49 float cell_height() const { return cell_h_; }
50
54 int column_count() const { return column_count_; }
56 std::size_t columns() const;
57
58 void set_overscan(int rows);
59 int overscan() const { return overscan_rows_; }
60
65
67 SelectionMode selection_mode() const { return selection_mode_; }
68 const std::vector<std::size_t>& selection() const { return selection_; }
69 bool is_selected(std::size_t index) const;
71 void select_cell(std::size_t index);
72 void toggle_cell_selection(std::size_t index);
73
74 std::optional<std::size_t> focused_index() const { return focused_index_; }
75 void set_focused_index(std::size_t index);
76
77 void scroll_to_item(std::size_t index);
78 void set_scroll_y(float y);
79 void scroll_by(float dy);
80 float scroll_y() const { return scroll_y_; }
81 float content_height() const;
82 std::size_t total_rows() const;
83
84 void on_cell_activated(std::function<void(std::size_t)> cb) {
85 on_cell_activated_ = std::move(cb);
86 }
87 void on_selection_changed(std::function<void(const std::vector<std::size_t>&)> cb) {
88 on_selection_changed_ = std::move(cb);
89 }
90
91 std::size_t realized_cell_count() const { return cell_slots_.size(); }
92 View* realized_cell_at_slot(std::size_t slot);
93 const View* realized_cell_at_slot(std::size_t slot) const;
94 std::optional<std::size_t> bound_index_for_slot(std::size_t slot) const;
95 std::size_t first_realized_index() const { return first_realized_index_; }
96 std::vector<std::size_t> realized_indices() const;
97
98 const VirtualListDirtyTracker& dirty_tracker() const { return dirty_tracker_; }
100
101 void on_resized() override;
102 View* hit_test(Point local_point) override;
103 void layout_children() override;
104 bool owns_child_layout() const override { return true; }
105 void paint(canvas::Canvas& canvas) override;
106 void on_mouse_event(const MouseEvent& event) override;
107 void on_mouse_drag(Point pos) override;
108 bool on_key_event(const KeyEvent& event) override;
109 bool wants_wheel_scroll() const override;
110
111private:
112 enum class UpdateResult { unchanged, changed, interrupted };
113 struct SelectionUpdate {
114 bool changed = false;
115 bool interrupted = false;
116 };
117
118 struct CellSlot {
119 View* cell = nullptr;
120 std::optional<std::size_t> index;
121 };
122
123 std::size_t desired_pool_size() const;
124 bool clear_pool();
125 bool ensure_pool_size(std::size_t desired);
126 bool release_cell(CellSlot& slot);
127 bool update_window(bool force_rebind);
128 bool bind_slot(CellSlot& slot, std::size_t index, bool force_rebind,
129 std::uint64_t update_generation);
130 void position_slot(CellSlot& slot);
131 void update_cell_accessibility(CellSlot& slot);
132 float max_scroll_y() const;
133 bool scroll_to_item_internal(std::size_t index);
134 UpdateResult set_scroll_y_internal(float y, bool request);
135 bool apply_pending_scroll_to_item();
136 bool apply_pending_selected_cell();
137 void mark_scroll_dirty(float old_y, float new_y);
138 float grid_width() const;
139
140 std::optional<std::size_t> cell_at(Point local) const;
141 void choose_cell(std::size_t index, bool extend, bool toggle, bool claim_focus = false);
142 SelectionUpdate set_selection_sanitized(std::vector<std::size_t> next, bool notify = true);
143 void move_focus_to(std::size_t index, bool extend);
144 std::optional<std::size_t> keyboard_anchor_index() const;
145 std::size_t visible_rows() const;
146 std::size_t page_cell_delta() const;
147
148 bool scrollbar_visible() const;
149 float scrollbar_width() const;
150 float scrollbar_thumb_length() const;
151 float scrollbar_thumb_y() const;
152 bool point_in_scrollbar(Point local) const;
153 bool point_in_scrollbar_thumb(Point local) const;
154
155 std::size_t item_count_ = 0;
156 float cell_w_ = 80.0f;
157 float cell_h_ = 60.0f;
158 int column_count_ = 0; // 0 => derive from width
159 int overscan_rows_ = 2;
160 float scroll_y_ = 0.0f;
161 std::optional<std::size_t> pending_scroll_to_item_;
162 std::optional<std::size_t> pending_selected_cell_;
163
164 CellFactory cell_factory_;
165 CellBinder cell_binder_;
166 CellReleaser cell_releaser_;
167 std::vector<CellSlot> cell_slots_;
168 std::size_t first_realized_index_ = 0;
169
170 // Per-class recycling pool for released cells (planning 2.3). Mirrors
171 // VirtualList's row_pool_: opt-in cells (View::supports_reuse()) are parked
172 // on release and re-acquired before the user factory. Behavior-neutral for
173 // the default View cells the built-in grid uses.
174 ViewPool cell_pool_;
175 std::optional<std::type_index> cell_type_;
176
177 SelectionMode selection_mode_ = SelectionMode::single;
178 std::vector<std::size_t> selection_;
179 std::optional<std::size_t> focused_index_;
180 std::optional<std::size_t> selection_anchor_;
181 std::function<void(std::size_t)> on_cell_activated_;
182 std::function<void(const std::vector<std::size_t>&)> on_selection_changed_;
183
184 VirtualListDirtyTracker dirty_tracker_;
185 bool dragging_scrollbar_ = false;
186 float scrollbar_drag_offset_ = 0.0f;
187 bool pool_resize_in_progress_ = false;
188 bool destroying_ = false;
189 std::uint64_t window_generation_ = 0;
190 std::shared_ptr<std::atomic<bool>> alive_ = std::make_shared<std::atomic<bool>>(true);
191};
192
193} // namespace pulp::view
Definition canvas.hpp:240
@ toggle
Definition view.hpp:989
@ cell
Definition view.hpp:991
bool is_selected(std::size_t index) const
int column_count() const
Definition virtual_grid.hpp:54
void layout_children() override
std::function< std::unique_ptr< View >(std::size_t slot)> CellFactory
Definition virtual_grid.hpp:37
void set_item_count(std::size_t n)
std::size_t first_realized_index() const
Definition virtual_grid.hpp:95
void on_selection_changed(std::function< void(const std::vector< std::size_t > &)> cb)
Definition virtual_grid.hpp:87
std::size_t columns() const
Effective column count actually used this frame (>= 1).
void set_cell_size(float width, float height)
void toggle_cell_selection(std::size_t index)
std::vector< std::size_t > realized_indices() const
bool wants_wheel_scroll() const override
True if this widget is itself a scroll container that should consume wheel input before an ancestor s...
void select_cell(std::size_t index)
bool owns_child_layout() const override
Definition virtual_grid.hpp:104
const VirtualListDirtyTracker & dirty_tracker() const
Definition virtual_grid.hpp:98
void set_scroll_y(float y)
void set_cell_binder(CellBinder binder)
void on_cell_activated(std::function< void(std::size_t)> cb)
Definition virtual_grid.hpp:84
void set_cell_releaser(CellReleaser releaser)
void set_cell_factory(CellFactory factory)
float scroll_y() const
Definition virtual_grid.hpp:80
std::size_t total_rows() const
View * hit_test(Point local_point) override
std::function< void(View &cell, std::size_t index)> CellBinder
Definition virtual_grid.hpp:38
void paint(canvas::Canvas &canvas) override
void scroll_by(float dy)
std::size_t item_count() const
Definition virtual_grid.hpp:45
void scroll_to_item(std::size_t index)
bool on_key_event(const KeyEvent &event) override
Key event with modifiers and up/down state.
void set_selection_mode(SelectionMode mode)
std::optional< std::size_t > focused_index() const
Definition virtual_grid.hpp:74
const View * realized_cell_at_slot(std::size_t slot) const
float cell_height() const
Definition virtual_grid.hpp:49
float content_height() const
SelectionMode
Definition virtual_grid.hpp:35
@ none
Definition virtual_grid.hpp:35
@ single
Definition virtual_grid.hpp:35
@ multi
Definition virtual_grid.hpp:35
void set_overscan(int rows)
void on_mouse_drag(Point pos) override
float cell_width() const
Definition virtual_grid.hpp:48
std::size_t realized_cell_count() const
Definition virtual_grid.hpp:91
void set_column_count(int columns)
Fixed number of columns.
SelectionMode selection_mode() const
Definition virtual_grid.hpp:67
View * realized_cell_at_slot(std::size_t slot)
const std::vector< std::size_t > & selection() const
Definition virtual_grid.hpp:68
void set_focused_index(std::size_t index)
int overscan() const
Definition virtual_grid.hpp:59
void on_mouse_event(const MouseEvent &event) override
Mouse down with full event context.
std::optional< std::size_t > bound_index_for_slot(std::size_t slot) const
void on_resized() override
std::function< void(View &cell)> CellReleaser
Definition virtual_grid.hpp:39
Definition virtual_list.hpp:19
Definition affine_transform.hpp:24
Hover-cursor tracking for platform window hosts.
Definition fwd.hpp:27
@ y
Definition input_events.hpp:42
@ n
Definition input_events.hpp:40
@ height
Definition css_animation.hpp:128
@ width
Definition css_animation.hpp:127
@ changed
Definition gesture.hpp:17
Rich key event with key code, modifiers, and repeat state.
Definition input_events.hpp:193
Rich mouse/pointer event with position, modifiers, button state, pointer ID, and stylus properties.
Definition input_events.hpp:104
Definition geometry.hpp:20