Skip to content

Commit 24ed229

Browse files
committed
table view displaying only needed cells
1 parent 17cf548 commit 24ed229

File tree

7 files changed

+118
-23
lines changed

7 files changed

+118
-23
lines changed

deps/ui/src/layout/placer.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::{
66

77
use gm::{axis::Axis, flat::Size, IntoF32};
88
use itertools::Itertools;
9-
use refs::{Own, Rglica, ToRglica};
9+
use refs::{Rglica, ToRglica};
1010

1111
use crate::{
1212
layout::{layout_rule::LayoutRule, Anchor, Tiling},
@@ -507,15 +507,15 @@ impl Placer {
507507
}
508508
}
509509

510-
fn place_vertically(views: &mut [Own<dyn View>], margin: f32) {
510+
fn place_vertically(views: Vec<WeakView>, margin: f32) {
511511
distribute::<{ Axis::Y }>(views, margin);
512512
}
513513

514-
fn place_horizontally(views: &mut [Own<dyn View>], margin: f32) {
514+
fn place_horizontally(views: Vec<WeakView>, margin: f32) {
515515
distribute::<{ Axis::X }>(views, margin);
516516
}
517517

518-
fn distribute<const AXIS: Axis>(views: &mut [Own<dyn View>], margin: f32) {
518+
fn distribute<const AXIS: Axis>(mut views: Vec<WeakView>, margin: f32) {
519519
let Some(mut last) = views.last_mut().map(|v| v.weak_view()) else {
520520
return;
521521
};
@@ -537,7 +537,7 @@ fn distribute<const AXIS: Axis>(views: &mut [Own<dyn View>], margin: f32) {
537537

538538
let mut last_pos: f32 = 0.0;
539539

540-
for view in views.iter_mut() {
540+
for view in &mut views {
541541
let mut frame = *view.frame();
542542

543543
frame.set_position::<AXIS>(last_pos);
@@ -551,7 +551,7 @@ fn distribute<const AXIS: Axis>(views: &mut [Own<dyn View>], margin: f32) {
551551
}
552552
}
553553

554-
fn distribute_with_ratio(size: Size, views: &mut [Own<dyn View>], ratios: &[f32]) {
554+
fn distribute_with_ratio(size: Size, mut views: Vec<WeakView>, ratios: &[f32]) {
555555
let total_ratio = 1.0 / ratios.iter().sum::<f32>();
556556

557557
for i in 0..ratios.len() {

deps/ui/src/view/view_subviews.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ pub trait ViewSubviews {
1313
fn __manually_set_superview(&mut self, superview: WeakView);
1414
fn superview(&self) -> &WeakView;
1515
fn subviews(&self) -> &[Own<dyn View>];
16-
fn subviews_mut(&mut self) -> &mut [Own<dyn View>];
16+
fn subviews_mut(&mut self) -> Vec<WeakView>;
1717
fn remove_from_superview(&mut self);
1818
fn take_from_superview(&mut self) -> Own<dyn View>;
1919
fn remove_all_subviews(&mut self);
@@ -45,8 +45,8 @@ impl<T: ?Sized + View> ViewSubviews for T {
4545
&self.base().subviews
4646
}
4747

48-
fn subviews_mut(&mut self) -> &mut [Own<dyn View>] {
49-
&mut self.base_mut().subviews
48+
fn subviews_mut(&mut self) -> Vec<WeakView> {
49+
self.base_mut().subviews.iter().map(Own::weak).collect()
5050
}
5151

5252
fn remove_from_superview(&mut self) {

deps/ui/ui_views/src/basic/scroll_view.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use gm::flat::Size;
22
use refs::Weak;
3-
use ui::{view, Sub, UIManager, ViewCallbacks, ViewData, ViewFrame, ViewSetup};
3+
use ui::{view, Sub, UIManager, ViewCallbacks, ViewData, ViewFrame, ViewSetup, ViewSubviews};
4+
use vents::Event;
45
mod test_engine {
56
pub(crate) use refs;
67
pub(crate) use ui;
@@ -12,6 +13,21 @@ use crate::Slider;
1213
pub struct ScrollView {
1314
slider: Sub<Slider>,
1415
pub content_size: Size,
16+
pub on_scroll: Event<f32>,
17+
}
18+
19+
impl ScrollView {
20+
pub fn remove_all_subviews(&mut self) {
21+
let slider_addr = self.slider.addr();
22+
23+
for mut view in self.subviews_mut() {
24+
if view.addr() == slider_addr {
25+
continue;
26+
}
27+
28+
view.remove_from_superview();
29+
}
30+
}
1531
}
1632

1733
impl ViewSetup for ScrollView {
@@ -22,6 +38,7 @@ impl ViewSetup for ScrollView {
2238
let val = 1.0 - val;
2339
let range = self.content_size.height - self.height();
2440
self.content_offset.y = -range * val;
41+
self.on_scroll.trigger(self.content_offset.y);
2542
});
2643

2744
UIManager::on_scroll(self, move |scroll| {
@@ -59,5 +76,7 @@ impl ScrollView {
5976
self.content_offset.y = self.content_offset.y.clamp(-range, 0.0);
6077
let slider_val = -self.content_offset.y / range;
6178
self.slider.set_value_without_event(1.0 - slider_val);
79+
80+
self.on_scroll.trigger(self.content_offset.y);
6281
}
6382
}

deps/ui/ui_views/src/complex/spinner.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ impl Spinner {
143143
let animation = UIAnimation::new(Animation::new(0.8, 0.0, 0.4), |sp, val| {
144144
let color = sp.color();
145145
sp.set_color(color.with_alpha(val));
146-
for dot in sp.subviews_mut() {
146+
for mut dot in sp.subviews_mut() {
147147
let color = *dot.color();
148148
dot.set_color(color.with_alpha(val));
149149
}

deps/ui/ui_views/src/complex/table_view/table_view.rs

+27-4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use gm::LossyConvert;
12
use refs::{weak_from_ref, Weak};
23
use ui::{view, Sub, ViewCallbacks, ViewData, ViewFrame, ViewSetup, ViewSubviews};
34

@@ -26,6 +27,13 @@ impl ViewCallbacks for TableView {
2627
impl ViewSetup for TableView {
2728
fn setup(self: Weak<Self>) {
2829
self.scroll.place().back();
30+
self.scroll.on_scroll.sub(move || {
31+
self.layout_cells();
32+
});
33+
34+
self.size_changed().sub(move || {
35+
self.layout_cells();
36+
})
2937
}
3038
}
3139

@@ -37,13 +45,28 @@ impl TableView {
3745
}
3846

3947
impl TableView {
40-
pub fn layout_cells(mut self: Weak<Self>) {
41-
let number_of_cells = self.data.number_of_cells() as f32;
48+
fn layout_cells(mut self: Weak<Self>) {
49+
self.scroll.remove_all_subviews();
50+
51+
let number_of_cells = self.data.number_of_cells();
52+
let cell_height = self.data.cell_height();
4253

43-
let total_height = number_of_cells * self.data.cell_height();
54+
let total_height = number_of_cells as f32 * cell_height;
4455
self.scroll.content_size.height = total_height;
4556

46-
for i in 0..self.data.number_of_cells() {
57+
let number_of_cells_fits: usize = (self.height() / cell_height).ceil().lossy_convert();
58+
59+
let offset = self.scroll.content_offset.y;
60+
61+
let first_index: usize = (-offset / cell_height).floor().lossy_convert();
62+
63+
let mut last_index = first_index + number_of_cells_fits + 1;
64+
65+
if last_index > number_of_cells {
66+
last_index = number_of_cells;
67+
}
68+
69+
for i in first_index..last_index {
4770
let mut cell = self.data.make_cell();
4871

4972
cell.place()

test_engine/src/app.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ impl App {
192192
view.calculate_absolute_frame();
193193
view.update();
194194
view.trigger_events();
195-
for view in view.subviews_mut() {
195+
for mut view in view.subviews_mut() {
196196
Self::update_view(view.deref_mut());
197197
}
198198
}

ui_test/src/views/complex/table_view.rs

+60-7
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
use std::{any::Any, ops::Deref};
22

33
use anyhow::Result;
4+
use log::debug;
45
use test_engine::{
56
refs::{Own, Weak},
67
ui::{
78
view, AfterSetup, Color, Container, Label, Sub, TableData, TableView, View, ViewData, ViewSetup,
89
ViewSubviews,
910
},
10-
App,
11+
ui_test::inject_touches,
12+
wait_for_next_frame, App,
1113
};
1214

1315
#[view]
@@ -17,9 +19,8 @@ struct TestTableView {
1719

1820
impl ViewSetup for TestTableView {
1921
fn setup(self: Weak<Self>) {
20-
self.table.place().all_sides(150);
22+
self.table.place().lr(280).tb(0);
2123
self.table.set_data_source(self.deref());
22-
self.table.layout_cells();
2324
}
2425
}
2526

@@ -29,7 +30,7 @@ impl TableData for TestTableView {
2930
}
3031

3132
fn number_of_cells(&self) -> usize {
32-
500
33+
2_000_000
3334
}
3435

3536
fn make_cell(&self) -> Own<dyn View> {
@@ -51,16 +52,68 @@ impl TableData for TestTableView {
5152

5253
fn setup_cell(&self, cell: &mut dyn Any, index: usize) {
5354
let label = cell.downcast_mut::<Label>().unwrap();
54-
label.set_text(format!("Cell number: {index}"));
55+
label.set_text(format!("Cell number: {}", index + 1));
5556
}
5657
}
5758

5859
pub async fn test_table_view() -> Result<()> {
59-
let mut _view = App::init_test_view::<TestTableView>().await;
60+
let view = App::init_test_view::<TestTableView>().await;
6061

6162
App::set_window_size((1000, 1000));
6263

63-
//record_ui_test().await;
64+
wait_for_next_frame().await;
65+
wait_for_next_frame().await;
66+
wait_for_next_frame().await;
67+
68+
assert_eq!(
69+
view.table.scroll.subviews().last().unwrap().downcast::<Label>().unwrap().text(),
70+
"Cell number: 26"
71+
);
72+
73+
inject_touches(
74+
"
75+
865 126 m
76+
877 111 m
77+
745 74 m
78+
680 41 m
79+
691 28 m
80+
696 28 m
81+
699 27 m
82+
699 27 b
83+
698 36 m
84+
697 66 m
85+
697 123 m
86+
694 186 m
87+
693 228 m
88+
692 272 m
89+
692 323 m
90+
693 384 m
91+
696 422 m
92+
701 473 m
93+
707 536 m
94+
710 653 m
95+
707 736 m
96+
698 783 m
97+
691 820 m
98+
685 868 m
99+
678 925 m
100+
676 959 m
101+
675 978 m
102+
674 994 m
103+
674 1003 m
104+
672 994 e
105+
669 983 m
106+
678 896 m
107+
",
108+
)
109+
.await;
110+
111+
assert_eq!(
112+
view.table.scroll.subviews().last().unwrap().downcast::<Label>().unwrap().text(),
113+
"Cell number: 2000000"
114+
);
115+
116+
debug!("Table view test: OK");
64117

65118
Ok(())
66119
}

0 commit comments

Comments
 (0)