28 return x < other.x + other.w &&
x +
w > other.x &&
29 y < other.y + other.h &&
y +
h > other.y;
33 const float nx = std::min(
x, other.x);
34 const float ny = std::min(
y, other.y);
38 std::max(
x +
w, other.x + other.w) - nx,
39 std::max(
y +
h, other.y + other.h) - ny
47 if (rect.
w <= 0.0f || rect.
h <= 0.0f)
return;
48 dirty_rects_.push_back(rect);
61 bool is_dirty()
const {
return full_repaint_ || !dirty_rects_.empty(); }
63 const std::vector<Rect>&
dirty_rects()
const {
return dirty_rects_; }
67 full_repaint_ =
false;
72 if (dirty_rects_.empty())
return {};
74 for (std::size_t
i = 1;
i < dirty_rects_.size(); ++
i) {
83 full_repaint_threshold_ = full_repaint_threshold;
89 void coalesce_if_needed() {
90 if (dirty_rects_.size() > max_rects_) coalesce();
91 if (viewport_w_ <= 0.0f || viewport_h_ <= 0.0f)
return;
93 float total_area = 0.0f;
94 for (
const auto& rect : dirty_rects_) total_area += rect.area();
95 if (total_area > viewport_w_ * viewport_h_ * full_repaint_threshold_) {
104 for (std::size_t
i = 0;
i < dirty_rects_.size(); ++
i) {
105 for (std::size_t
j =
i + 1;
j < dirty_rects_.size(); ++
j) {
106 auto combined = dirty_rects_[
i].merged(dirty_rects_[
j]);
107 const float sum_area = dirty_rects_[
i].area() + dirty_rects_[
j].area();
108 if (combined.area() < sum_area * 1.5f ||
109 dirty_rects_[
i].intersects(dirty_rects_[
j])) {
110 dirty_rects_[
i] = combined;
111 dirty_rects_.erase(dirty_rects_.begin() +
static_cast<long>(
j));
121 std::vector<Rect> dirty_rects_;
122 bool full_repaint_ =
true;
123 float viewport_w_ = 0.0f;
124 float viewport_h_ = 0.0f;
125 float full_repaint_threshold_ = 0.6f;
126 std::uint64_t frame_count_ = 0;
127 static constexpr std::size_t max_rects_ = 16;
139 using RowFactory = std::function<std::unique_ptr<View>(std::size_t slot)>;
143 std::function<std::optional<std::size_t>(std::string_view query,
144 std::size_t from_index)>;
165 const std::vector<std::size_t>&
selection()
const {
return selection_; }
181 on_row_activated_ = std::move(cb);
184 on_selection_changed_ = std::move(cb);
187 type_to_search_ = std::move(handler);
213 enum class UpdateResult { unchanged,
changed, interrupted };
214 struct SelectionUpdate {
215 bool changed =
false;
216 bool interrupted =
false;
221 std::optional<std::size_t> index;
224 std::size_t desired_pool_size()
const;
226 bool ensure_pool_size(std::size_t desired);
227 bool release_row(RowSlot& slot);
228 bool update_window(
bool force_rebind);
229 bool bind_slot(RowSlot& slot, std::size_t index,
bool force_rebind,
230 std::uint64_t update_generation);
231 void position_slot(RowSlot& slot);
232 void update_row_accessibility(RowSlot& slot);
233 float max_scroll_y()
const;
234 bool scroll_to_row_internal(std::size_t index);
235 UpdateResult set_scroll_y_internal(
float y,
bool request);
236 bool apply_pending_scroll_to_row();
237 bool apply_pending_selected_row();
238 void mark_scroll_dirty(
float old_y,
float new_y);
239 float row_width()
const;
241 std::optional<std::size_t> row_at(Point local)
const;
242 void choose_row(std::size_t index,
bool extend,
bool toggle,
bool claim_focus =
false);
243 SelectionUpdate set_selection_sanitized(std::vector<std::size_t> next,
bool notify =
true);
244 void move_focus_to(std::size_t index,
bool extend);
245 std::optional<std::size_t> keyboard_anchor_index()
const;
246 std::size_t page_row_delta()
const;
248 bool scrollbar_visible()
const;
249 float scrollbar_width()
const;
250 float scrollbar_thumb_length()
const;
251 float scrollbar_thumb_y()
const;
252 bool point_in_scrollbar(Point local)
const;
253 bool point_in_scrollbar_thumb(Point local)
const;
255 std::size_t row_count_ = 0;
256 float row_height_ = 24.0f;
257 int overscan_rows_ = 3;
258 float scroll_y_ = 0.0f;
259 std::optional<std::size_t> pending_scroll_to_row_;
260 std::optional<std::size_t> pending_selected_row_;
265 std::vector<RowSlot> row_slots_;
266 std::size_t first_realized_index_ = 0;
276 std::optional<std::type_index> row_type_;
279 std::vector<std::size_t> selection_;
280 std::optional<std::size_t> focused_index_;
281 std::optional<std::size_t> selection_anchor_;
282 std::function<void(std::size_t)> on_row_activated_;
283 std::function<void(
const std::vector<std::size_t>&)> on_selection_changed_;
285 std::string type_buffer_;
287 VirtualListDirtyTracker dirty_tracker_;
288 bool dragging_scrollbar_ =
false;
289 float scrollbar_drag_offset_ = 0.0f;
290 bool pool_resize_in_progress_ =
false;
291 bool destroying_ =
false;
292 std::uint64_t window_generation_ = 0;
293 std::shared_ptr<std::atomic<bool>> alive_ = std::make_shared<std::atomic<bool>>(
true);
Definition canvas.hpp:240
@ toggle
Definition view.hpp:989
@ row
Definition view.hpp:991
Definition virtual_list.hpp:19
bool needs_full_repaint() const
Definition virtual_list.hpp:62
void invalidate(float x, float y, float w, float h)
Definition virtual_list.hpp:52
void invalidate(const Rect &rect)
Definition virtual_list.hpp:46
void invalidate_all()
Definition virtual_list.hpp:56
void clear()
Definition virtual_list.hpp:65
const std::vector< Rect > & dirty_rects() const
Definition virtual_list.hpp:63
void set_viewport(float width, float height, float full_repaint_threshold=0.6f)
Definition virtual_list.hpp:80
Rect bounds() const
Definition virtual_list.hpp:71
bool is_dirty() const
Definition virtual_list.hpp:61
std::uint64_t frame_count() const
Definition virtual_list.hpp:86
bool owns_child_layout() const override
Definition virtual_list.hpp:204
void on_mouse_event(const MouseEvent &event) override
Mouse down with full event context.
void layout_children() override
SelectionMode
Definition virtual_list.hpp:137
@ none
Definition virtual_list.hpp:137
@ single
Definition virtual_list.hpp:137
@ multi
Definition virtual_list.hpp:137
void set_row_binder(RowBinder binder)
void scroll_to_row(std::size_t index)
std::size_t realized_row_count() const
Definition virtual_list.hpp:191
float row_height() const
Definition virtual_list.hpp:153
void set_row_releaser(RowReleaser releaser)
std::function< std::unique_ptr< View >(std::size_t slot)> RowFactory
Definition virtual_list.hpp:139
std::optional< std::size_t > focused_index() const
Definition virtual_list.hpp:171
bool on_key_event(const KeyEvent &event) override
Key event with modifiers and up/down state.
SelectionMode selection_mode() const
Definition virtual_list.hpp:164
bool is_selected(std::size_t index) const
void paint(canvas::Canvas &canvas) override
void on_row_activated(std::function< void(std::size_t)> cb)
Definition virtual_list.hpp:180
std::optional< std::size_t > bound_index_for_slot(std::size_t slot) const
void set_scroll_y(float y)
float content_height() 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...
std::size_t first_realized_index() const
Definition virtual_list.hpp:195
void set_focused_index(std::size_t index)
void set_row_factory(RowFactory factory)
void set_row_height(float px)
const View * realized_row_at_slot(std::size_t slot) const
View * hit_test(Point local_point) override
void on_mouse_drag(Point pos) override
void clear_type_to_search_buffer()
Definition virtual_list.hpp:189
void on_resized() override
void toggle_row_selection(std::size_t index)
void set_selection_mode(SelectionMode mode)
std::function< void(View &row, std::size_t index)> RowBinder
Definition virtual_list.hpp:140
std::vector< std::size_t > realized_indices() const
void on_selection_changed(std::function< void(const std::vector< std::size_t > &)> cb)
Definition virtual_list.hpp:183
void set_type_to_search(TypeToSearchHandler handler)
Definition virtual_list.hpp:186
std::function< std::optional< std::size_t >(std::string_view query, std::size_t from_index)> TypeToSearchHandler
Definition virtual_list.hpp:142
void on_text_input(const TextInputEvent &event) override
Text input from keyboard/IME (separate from key events).
const std::vector< std::size_t > & selection() const
Definition virtual_list.hpp:165
std::function< void(View &row)> RowReleaser
Definition virtual_list.hpp:141
void select_row(std::size_t index)
void set_row_count(std::size_t n)
void set_overscan(int rows)
float scroll_y() const
Definition virtual_list.hpp:177
View * realized_row_at_slot(std::size_t slot)
int overscan() const
Definition virtual_list.hpp:156
const VirtualListDirtyTracker & dirty_tracker() const
Definition virtual_list.hpp:198
std::size_t row_count() const
Definition virtual_list.hpp:150
Definition affine_transform.hpp:24
Hover-cursor tracking for platform window hosts.
Definition fwd.hpp:27
@ px
Absolute pixels.
Definition geometry.hpp:393
@ h
Definition input_events.hpp:39
@ j
Definition input_events.hpp:40
@ y
Definition input_events.hpp:42
@ n
Definition input_events.hpp:40
@ i
Definition input_events.hpp:40
@ x
Definition input_events.hpp:41
@ w
Definition input_events.hpp:41
@ 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
Text input from IME or keyboard composition (separate from KeyEvent).
Definition input_events.hpp:210
Definition virtual_list.hpp:21
bool intersects(const Rect &other) const
Definition virtual_list.hpp:27
Rect merged(const Rect &other) const
Definition virtual_list.hpp:32
float w
Definition virtual_list.hpp:24
float y
Definition virtual_list.hpp:23
float x
Definition virtual_list.hpp:22
float h
Definition virtual_list.hpp:25
float area() const
Definition virtual_list.hpp:43