Uncomment List
tests and fix related problems in WindowContext
This commit is contained in:
parent
b89c4e06be
commit
702c4ce403
3 changed files with 276 additions and 383 deletions
|
@ -45,7 +45,7 @@ use crate::{
|
||||||
executor::{self, Task},
|
executor::{self, Task},
|
||||||
keymap_matcher::{self, Binding, KeymapContext, KeymapMatcher, Keystroke, MatchResult},
|
keymap_matcher::{self, Binding, KeymapContext, KeymapMatcher, Keystroke, MatchResult},
|
||||||
platform::{
|
platform::{
|
||||||
self, Appearance, FontSystem, KeyDownEvent, KeyUpEvent, ModifiersChangedEvent, MouseButton,
|
self, FontSystem, KeyDownEvent, KeyUpEvent, ModifiersChangedEvent, MouseButton,
|
||||||
PathPromptOptions, Platform, PromptLevel, WindowBounds, WindowOptions,
|
PathPromptOptions, Platform, PromptLevel, WindowBounds, WindowOptions,
|
||||||
},
|
},
|
||||||
util::post_inc,
|
util::post_inc,
|
||||||
|
@ -872,60 +872,6 @@ impl AppContext {
|
||||||
self.active_labeled_tasks.values().cloned()
|
self.active_labeled_tasks.values().cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_view(&mut self, params: RenderParams) -> Result<Box<dyn AnyRootElement>> {
|
|
||||||
todo!()
|
|
||||||
// let window_id = params.window_id;
|
|
||||||
// let view_id = params.view_id;
|
|
||||||
// let mut view = self
|
|
||||||
// .views
|
|
||||||
// .remove(&(window_id, view_id))
|
|
||||||
// .ok_or_else(|| anyhow!("view not found"))?;
|
|
||||||
// let element = view.render(params, self);
|
|
||||||
// self.views.insert((window_id, view_id), view);
|
|
||||||
// Ok(element)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn render_views(
|
|
||||||
&mut self,
|
|
||||||
window_id: usize,
|
|
||||||
titlebar_height: f32,
|
|
||||||
appearance: Appearance,
|
|
||||||
) -> HashMap<usize, Box<dyn AnyRootElement>> {
|
|
||||||
todo!()
|
|
||||||
// self.start_frame();
|
|
||||||
// #[allow(clippy::needless_collect)]
|
|
||||||
// let view_ids = self
|
|
||||||
// .views
|
|
||||||
// .keys()
|
|
||||||
// .filter_map(|(win_id, view_id)| {
|
|
||||||
// if *win_id == window_id {
|
|
||||||
// Some(*view_id)
|
|
||||||
// } else {
|
|
||||||
// None
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// .collect::<Vec<_>>();
|
|
||||||
|
|
||||||
// view_ids
|
|
||||||
// .into_iter()
|
|
||||||
// .map(|view_id| {
|
|
||||||
// (
|
|
||||||
// view_id,
|
|
||||||
// self.render_view(RenderParams {
|
|
||||||
// window_id,
|
|
||||||
// view_id,
|
|
||||||
// titlebar_height,
|
|
||||||
// hovered_region_ids: Default::default(),
|
|
||||||
// clicked_region_ids: None,
|
|
||||||
// refreshing: false,
|
|
||||||
// appearance,
|
|
||||||
// })
|
|
||||||
// .unwrap(),
|
|
||||||
// )
|
|
||||||
// })
|
|
||||||
// .collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn start_frame(&mut self) {
|
pub(crate) fn start_frame(&mut self) {
|
||||||
self.frame_count += 1;
|
self.frame_count += 1;
|
||||||
}
|
}
|
||||||
|
@ -2488,19 +2434,8 @@ impl UpdateView for AppContext {
|
||||||
where
|
where
|
||||||
T: View,
|
T: View,
|
||||||
{
|
{
|
||||||
self.update_window(handle.window_id, |cx| {
|
self.update_window(handle.window_id, |cx| cx.update_view(handle, update))
|
||||||
cx.update_any_view(handle.view_id, |view, cx| {
|
.unwrap() // TODO: Is this unwrap safe?
|
||||||
let mut cx = ViewContext::mutable(cx, handle.view_id);
|
|
||||||
update(
|
|
||||||
view.as_any_mut()
|
|
||||||
.downcast_mut()
|
|
||||||
.expect("downcast is type safe"),
|
|
||||||
&mut cx,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.unwrap() // TODO: Are these unwraps safe?
|
|
||||||
})
|
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3941,16 +3876,6 @@ impl<'a, T> DerefMut for Reference<'a, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct RenderParams {
|
|
||||||
pub window_id: usize,
|
|
||||||
pub view_id: usize,
|
|
||||||
pub titlebar_height: f32,
|
|
||||||
pub hovered_region_ids: HashSet<MouseRegionId>,
|
|
||||||
pub clicked_region_ids: Option<(HashSet<MouseRegionId>, MouseButton)>,
|
|
||||||
pub refreshing: bool,
|
|
||||||
pub appearance: Appearance,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct MouseState {
|
pub struct MouseState {
|
||||||
pub(crate) hovered: bool,
|
pub(crate) hovered: bool,
|
||||||
|
|
|
@ -14,11 +14,11 @@ use crate::{
|
||||||
text_layout::TextLayoutCache,
|
text_layout::TextLayoutCache,
|
||||||
util::post_inc,
|
util::post_inc,
|
||||||
AnyView, AnyViewHandle, AnyWeakViewHandle, AppContext, Drawable, Entity, ModelContext,
|
AnyView, AnyViewHandle, AnyWeakViewHandle, AppContext, Drawable, Entity, ModelContext,
|
||||||
ModelHandle, MouseRegion, MouseRegionId, ParentId, ReadView, RenderParams, SceneBuilder,
|
ModelHandle, MouseRegion, MouseRegionId, ParentId, ReadView, SceneBuilder, UpdateModel,
|
||||||
UpdateModel, UpdateView, UpgradeViewHandle, View, ViewContext, ViewHandle, WeakViewHandle,
|
UpdateView, UpgradeViewHandle, View, ViewContext, ViewHandle, WeakViewHandle,
|
||||||
WindowInvalidation,
|
WindowInvalidation,
|
||||||
};
|
};
|
||||||
use anyhow::bail;
|
use anyhow::{anyhow, bail, Result};
|
||||||
use collections::{HashMap, HashSet};
|
use collections::{HashMap, HashSet};
|
||||||
use pathfinder_geometry::vector::{vec2f, Vector2F};
|
use pathfinder_geometry::vector::{vec2f, Vector2F};
|
||||||
use postage::oneshot;
|
use postage::oneshot;
|
||||||
|
@ -74,7 +74,7 @@ impl Window {
|
||||||
invalidation: None,
|
invalidation: None,
|
||||||
is_fullscreen: false,
|
is_fullscreen: false,
|
||||||
platform_window,
|
platform_window,
|
||||||
rendered_views: cx.render_views(window_id, titlebar_height, appearance),
|
rendered_views: Default::default(),
|
||||||
cursor_regions: Default::default(),
|
cursor_regions: Default::default(),
|
||||||
mouse_regions: Default::default(),
|
mouse_regions: Default::default(),
|
||||||
text_layout_cache: TextLayoutCache::new(cx.font_system.clone()),
|
text_layout_cache: TextLayoutCache::new(cx.font_system.clone()),
|
||||||
|
@ -91,6 +91,9 @@ impl Window {
|
||||||
let root_view = window_context
|
let root_view = window_context
|
||||||
.build_and_insert_view(ParentId::Root, |cx| Some(build_view(cx)))
|
.build_and_insert_view(ParentId::Root, |cx| Some(build_view(cx)))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
if let Some(mut invalidation) = window_context.window.invalidation.take() {
|
||||||
|
window_context.invalidate(&mut invalidation, appearance);
|
||||||
|
}
|
||||||
window.focused_view_id = Some(root_view.id());
|
window.focused_view_id = Some(root_view.id());
|
||||||
window.root_view = Some(root_view.into_any());
|
window.root_view = Some(root_view.into_any());
|
||||||
window
|
window
|
||||||
|
@ -150,7 +153,16 @@ impl UpdateView for WindowContext<'_, '_> {
|
||||||
where
|
where
|
||||||
T: View,
|
T: View,
|
||||||
{
|
{
|
||||||
self.app_context.update_view(handle, update)
|
self.update_any_view(handle.view_id, |view, cx| {
|
||||||
|
let mut cx = ViewContext::mutable(cx, handle.view_id);
|
||||||
|
update(
|
||||||
|
view.as_any_mut()
|
||||||
|
.downcast_mut()
|
||||||
|
.expect("downcast is type safe"),
|
||||||
|
&mut cx,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.unwrap() // TODO: Is this unwrap safe?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -678,7 +690,6 @@ impl<'a: 'b, 'b> WindowContext<'a, 'b> {
|
||||||
self.window.rendered_views.remove(view_id);
|
self.window.rendered_views.remove(view_id);
|
||||||
}
|
}
|
||||||
for view_id in &invalidation.updated {
|
for view_id in &invalidation.updated {
|
||||||
let window_id = self.window_id;
|
|
||||||
let titlebar_height = self.window.titlebar_height;
|
let titlebar_height = self.window.titlebar_height;
|
||||||
let hovered_region_ids = self.window.hovered_region_ids.clone();
|
let hovered_region_ids = self.window.hovered_region_ids.clone();
|
||||||
let clicked_region_ids = self
|
let clicked_region_ids = self
|
||||||
|
@ -688,7 +699,6 @@ impl<'a: 'b, 'b> WindowContext<'a, 'b> {
|
||||||
|
|
||||||
let element = self
|
let element = self
|
||||||
.render_view(RenderParams {
|
.render_view(RenderParams {
|
||||||
window_id,
|
|
||||||
view_id: *view_id,
|
view_id: *view_id,
|
||||||
titlebar_height,
|
titlebar_height,
|
||||||
hovered_region_ids,
|
hovered_region_ids,
|
||||||
|
@ -701,39 +711,16 @@ impl<'a: 'b, 'b> WindowContext<'a, 'b> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn refresh(&mut self, invalidation: &mut WindowInvalidation, appearance: Appearance) {
|
pub fn render_view(&mut self, params: RenderParams) -> Result<Box<dyn AnyRootElement>> {
|
||||||
self.invalidate(invalidation, appearance);
|
|
||||||
|
|
||||||
let view_ids = self
|
|
||||||
.window
|
|
||||||
.rendered_views
|
|
||||||
.keys()
|
|
||||||
.copied()
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
for view_id in view_ids {
|
|
||||||
if !invalidation.updated.contains(&view_id) {
|
|
||||||
let window_id = self.window_id;
|
let window_id = self.window_id;
|
||||||
let titlebar_height = self.window.titlebar_height;
|
let view_id = params.view_id;
|
||||||
let hovered_region_ids = self.window.hovered_region_ids.clone();
|
let mut view = self
|
||||||
let clicked_region_ids = self
|
.views
|
||||||
.window
|
.remove(&(window_id, view_id))
|
||||||
.clicked_button
|
.ok_or_else(|| anyhow!("view not found"))?;
|
||||||
.map(|button| (self.window.clicked_region_ids.clone(), button));
|
let element = view.render(self, view_id);
|
||||||
let element = self
|
self.views.insert((window_id, view_id), view);
|
||||||
.render_view(RenderParams {
|
Ok(element)
|
||||||
window_id,
|
|
||||||
view_id,
|
|
||||||
titlebar_height,
|
|
||||||
hovered_region_ids,
|
|
||||||
clicked_region_ids,
|
|
||||||
refreshing: true,
|
|
||||||
appearance,
|
|
||||||
})
|
|
||||||
.unwrap();
|
|
||||||
self.window.rendered_views.insert(view_id, element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_scene(&mut self) -> Scene {
|
pub fn build_scene(&mut self) -> Scene {
|
||||||
|
@ -854,32 +841,6 @@ impl<'a: 'b, 'b> WindowContext<'a, 'b> {
|
||||||
self.window.platform_window.prompt(level, msg, answers)
|
self.window.platform_window.prompt(level, msg, answers)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_view<T, F>(&mut self, parent: &AnyViewHandle, build_view: F) -> ViewHandle<T>
|
|
||||||
where
|
|
||||||
T: View,
|
|
||||||
F: FnOnce(&mut ViewContext<T>) -> T,
|
|
||||||
{
|
|
||||||
if parent.window_id == self.window_id {
|
|
||||||
self.build_and_insert_view(ParentId::View(parent.view_id), |cx| Some(build_view(cx)))
|
|
||||||
.unwrap()
|
|
||||||
} else {
|
|
||||||
self.app_context.add_view(parent, build_view)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_option_view<T, F>(
|
|
||||||
&mut self,
|
|
||||||
parent_handle: impl Into<AnyViewHandle>,
|
|
||||||
build_view: F,
|
|
||||||
) -> Option<ViewHandle<T>>
|
|
||||||
where
|
|
||||||
T: View,
|
|
||||||
F: FnOnce(&mut ViewContext<T>) -> Option<T>,
|
|
||||||
{
|
|
||||||
let parent_handle = parent_handle.into();
|
|
||||||
self.build_and_insert_view(ParentId::View(parent_handle.view_id), build_view)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn replace_root_view<V, F>(&mut self, build_root_view: F) -> ViewHandle<V>
|
pub fn replace_root_view<V, F>(&mut self, build_root_view: F) -> ViewHandle<V>
|
||||||
where
|
where
|
||||||
V: View,
|
V: View,
|
||||||
|
@ -923,6 +884,15 @@ impl<'a: 'b, 'b> WindowContext<'a, 'b> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct RenderParams {
|
||||||
|
pub view_id: usize,
|
||||||
|
pub titlebar_height: f32,
|
||||||
|
pub hovered_region_ids: HashSet<MouseRegionId>,
|
||||||
|
pub clicked_region_ids: Option<(HashSet<MouseRegionId>, MouseButton)>,
|
||||||
|
pub refreshing: bool,
|
||||||
|
pub appearance: Appearance,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
|
||||||
pub enum Axis {
|
pub enum Axis {
|
||||||
#[default]
|
#[default]
|
||||||
|
|
|
@ -648,267 +648,265 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{elements::Empty, geometry::vector::vec2f, Entity};
|
use crate::{elements::Empty, geometry::vector::vec2f, Entity};
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
|
use std::env;
|
||||||
|
|
||||||
#[crate::test(self)]
|
#[crate::test(self)]
|
||||||
fn test_layout(cx: &mut crate::AppContext) {
|
fn test_layout(cx: &mut crate::AppContext) {
|
||||||
todo!()
|
cx.add_window(Default::default(), |cx| {
|
||||||
// let (_, view) = cx.add_window(Default::default(), |_| TestView);
|
let mut view = TestView;
|
||||||
// let constraint = SizeConstraint::new(vec2f(0., 0.), vec2f(100., 40.));
|
let constraint = SizeConstraint::new(vec2f(0., 0.), vec2f(100., 40.));
|
||||||
|
let elements = Rc::new(RefCell::new(vec![(0, 20.), (1, 30.), (2, 100.)]));
|
||||||
|
let state = ListState::new(elements.borrow().len(), Orientation::Top, 1000.0, {
|
||||||
|
let elements = elements.clone();
|
||||||
|
move |_, ix, _| {
|
||||||
|
let (id, height) = elements.borrow()[ix];
|
||||||
|
TestElement::new(id, height).boxed()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// let elements = Rc::new(RefCell::new(vec![(0, 20.), (1, 30.), (2, 100.)]));
|
let mut list = List::new(state.clone());
|
||||||
|
let (size, _) = list.layout(constraint, &mut view, cx);
|
||||||
|
assert_eq!(size, vec2f(100., 40.));
|
||||||
|
assert_eq!(
|
||||||
|
state.0.borrow().items.summary().clone(),
|
||||||
|
ListItemSummary {
|
||||||
|
count: 3,
|
||||||
|
rendered_count: 3,
|
||||||
|
unrendered_count: 0,
|
||||||
|
height: 150.
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// let state = view.update(cx, |_, cx| {
|
state.0.borrow_mut().scroll(
|
||||||
// ListState::new(elements.borrow().len(), Orientation::Top, 1000.0, cx, {
|
&ListOffset {
|
||||||
// let elements = elements.clone();
|
item_ix: 0,
|
||||||
// move |_, ix, _| {
|
offset_in_item: 0.,
|
||||||
// let (id, height) = elements.borrow()[ix];
|
},
|
||||||
// TestElement::new(id, height).boxed()
|
40.,
|
||||||
// }
|
vec2f(0., -54.),
|
||||||
// })
|
true,
|
||||||
// });
|
&mut view,
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
|
||||||
// let mut list = List::new(state.clone());
|
let (_, logical_scroll_top) = list.layout(constraint, &mut view, cx);
|
||||||
// let (size, _) = list.layout(
|
assert_eq!(
|
||||||
// constraint,
|
logical_scroll_top,
|
||||||
// &mut presenter.build_layout_context(vec2f(100., 40.), false, cx),
|
ListOffset {
|
||||||
// );
|
item_ix: 2,
|
||||||
// assert_eq!(size, vec2f(100., 40.));
|
offset_in_item: 4.
|
||||||
// assert_eq!(
|
}
|
||||||
// state.0.borrow().items.summary().clone(),
|
);
|
||||||
// ListItemSummary {
|
assert_eq!(state.0.borrow().scroll_top(&logical_scroll_top), 54.);
|
||||||
// count: 3,
|
|
||||||
// rendered_count: 3,
|
|
||||||
// unrendered_count: 0,
|
|
||||||
// height: 150.
|
|
||||||
// }
|
|
||||||
// );
|
|
||||||
|
|
||||||
// state.0.borrow_mut().scroll(
|
elements.borrow_mut().splice(1..2, vec![(3, 40.), (4, 50.)]);
|
||||||
// &ListOffset {
|
elements.borrow_mut().push((5, 60.));
|
||||||
// item_ix: 0,
|
state.splice(1..2, 2);
|
||||||
// offset_in_item: 0.,
|
state.splice(4..4, 1);
|
||||||
// },
|
assert_eq!(
|
||||||
// 40.,
|
state.0.borrow().items.summary().clone(),
|
||||||
// vec2f(0., -54.),
|
ListItemSummary {
|
||||||
// true,
|
count: 5,
|
||||||
// &mut presenter.build_event_context(&mut Default::default(), cx),
|
rendered_count: 2,
|
||||||
// );
|
unrendered_count: 3,
|
||||||
// let (_, logical_scroll_top) = list.layout(
|
height: 120.
|
||||||
// constraint,
|
}
|
||||||
// &mut presenter.build_layout_context(vec2f(100., 40.), false, cx),
|
);
|
||||||
// );
|
|
||||||
// assert_eq!(
|
|
||||||
// logical_scroll_top,
|
|
||||||
// ListOffset {
|
|
||||||
// item_ix: 2,
|
|
||||||
// offset_in_item: 4.
|
|
||||||
// }
|
|
||||||
// );
|
|
||||||
// assert_eq!(state.0.borrow().scroll_top(&logical_scroll_top), 54.);
|
|
||||||
|
|
||||||
// elements.borrow_mut().splice(1..2, vec![(3, 40.), (4, 50.)]);
|
let (size, logical_scroll_top) = list.layout(constraint, &mut view, cx);
|
||||||
// elements.borrow_mut().push((5, 60.));
|
assert_eq!(size, vec2f(100., 40.));
|
||||||
// state.splice(1..2, 2);
|
assert_eq!(
|
||||||
// state.splice(4..4, 1);
|
state.0.borrow().items.summary().clone(),
|
||||||
// assert_eq!(
|
ListItemSummary {
|
||||||
// state.0.borrow().items.summary().clone(),
|
count: 5,
|
||||||
// ListItemSummary {
|
rendered_count: 5,
|
||||||
// count: 5,
|
unrendered_count: 0,
|
||||||
// rendered_count: 2,
|
height: 270.
|
||||||
// unrendered_count: 3,
|
}
|
||||||
// height: 120.
|
);
|
||||||
// }
|
assert_eq!(
|
||||||
// );
|
logical_scroll_top,
|
||||||
|
ListOffset {
|
||||||
|
item_ix: 3,
|
||||||
|
offset_in_item: 4.
|
||||||
|
}
|
||||||
|
);
|
||||||
|
assert_eq!(state.0.borrow().scroll_top(&logical_scroll_top), 114.);
|
||||||
|
|
||||||
// let (size, logical_scroll_top) = list.layout(
|
view
|
||||||
// constraint,
|
});
|
||||||
// &mut presenter.build_layout_context(vec2f(100., 40.), false, cx),
|
|
||||||
// );
|
|
||||||
// assert_eq!(size, vec2f(100., 40.));
|
|
||||||
// assert_eq!(
|
|
||||||
// state.0.borrow().items.summary().clone(),
|
|
||||||
// ListItemSummary {
|
|
||||||
// count: 5,
|
|
||||||
// rendered_count: 5,
|
|
||||||
// unrendered_count: 0,
|
|
||||||
// height: 270.
|
|
||||||
// }
|
|
||||||
// );
|
|
||||||
// assert_eq!(
|
|
||||||
// logical_scroll_top,
|
|
||||||
// ListOffset {
|
|
||||||
// item_ix: 3,
|
|
||||||
// offset_in_item: 4.
|
|
||||||
// }
|
|
||||||
// );
|
|
||||||
// assert_eq!(state.0.borrow().scroll_top(&logical_scroll_top), 114.);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[crate::test(self, iterations = 10, seed = 0)]
|
#[crate::test(self, iterations = 10)]
|
||||||
fn test_random(cx: &mut crate::AppContext, mut rng: StdRng) {
|
fn test_random(cx: &mut crate::AppContext, mut rng: StdRng) {
|
||||||
todo!()
|
let operations = env::var("OPERATIONS")
|
||||||
// let operations = env::var("OPERATIONS")
|
.map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
|
||||||
// .map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
|
.unwrap_or(10);
|
||||||
// .unwrap_or(10);
|
|
||||||
|
|
||||||
// let (window_id, view) = cx.add_window(Default::default(), |_| TestView);
|
cx.add_window(Default::default(), |cx| {
|
||||||
// let mut next_id = 0;
|
let mut view = TestView;
|
||||||
// let elements = Rc::new(RefCell::new(
|
|
||||||
// (0..rng.gen_range(0..=20))
|
|
||||||
// .map(|_| {
|
|
||||||
// let id = next_id;
|
|
||||||
// next_id += 1;
|
|
||||||
// (id, rng.gen_range(0..=200) as f32 / 2.0)
|
|
||||||
// })
|
|
||||||
// .collect::<Vec<_>>(),
|
|
||||||
// ));
|
|
||||||
// let orientation = *[Orientation::Top, Orientation::Bottom]
|
|
||||||
// .choose(&mut rng)
|
|
||||||
// .unwrap();
|
|
||||||
// let overdraw = rng.gen_range(1..=100) as f32;
|
|
||||||
|
|
||||||
// let state = view.update(cx, |_, cx| {
|
let mut next_id = 0;
|
||||||
// ListState::new(elements.borrow().len(), orientation, overdraw, cx, {
|
let elements = Rc::new(RefCell::new(
|
||||||
// let elements = elements.clone();
|
(0..rng.gen_range(0..=20))
|
||||||
// move |_, ix, _| {
|
.map(|_| {
|
||||||
// let (id, height) = elements.borrow()[ix];
|
let id = next_id;
|
||||||
// TestElement::new(id, height).boxed()
|
next_id += 1;
|
||||||
// }
|
(id, rng.gen_range(0..=200) as f32 / 2.0)
|
||||||
// })
|
})
|
||||||
// });
|
.collect::<Vec<_>>(),
|
||||||
|
));
|
||||||
|
let orientation = *[Orientation::Top, Orientation::Bottom]
|
||||||
|
.choose(&mut rng)
|
||||||
|
.unwrap();
|
||||||
|
let overdraw = rng.gen_range(1..=100) as f32;
|
||||||
|
|
||||||
// let mut width = rng.gen_range(0..=2000) as f32 / 2.;
|
let state = ListState::new(elements.borrow().len(), orientation, overdraw, {
|
||||||
// let mut height = rng.gen_range(0..=2000) as f32 / 2.;
|
let elements = elements.clone();
|
||||||
// log::info!("orientation: {:?}", orientation);
|
move |_, ix, _| {
|
||||||
// log::info!("overdraw: {}", overdraw);
|
let (id, height) = elements.borrow()[ix];
|
||||||
// log::info!("elements: {:?}", elements.borrow());
|
TestElement::new(id, height).boxed()
|
||||||
// log::info!("size: ({:?}, {:?})", width, height);
|
}
|
||||||
// log::info!("==================");
|
});
|
||||||
|
|
||||||
// let mut last_logical_scroll_top = None;
|
let mut width = rng.gen_range(0..=2000) as f32 / 2.;
|
||||||
// for _ in 0..operations {
|
let mut height = rng.gen_range(0..=2000) as f32 / 2.;
|
||||||
// match rng.gen_range(0..=100) {
|
log::info!("orientation: {:?}", orientation);
|
||||||
// 0..=29 if last_logical_scroll_top.is_some() => {
|
log::info!("overdraw: {}", overdraw);
|
||||||
// let delta = vec2f(0., rng.gen_range(-overdraw..=overdraw));
|
log::info!("elements: {:?}", elements.borrow());
|
||||||
// log::info!(
|
log::info!("size: ({:?}, {:?})", width, height);
|
||||||
// "Scrolling by {:?}, previous scroll top: {:?}",
|
log::info!("==================");
|
||||||
// delta,
|
|
||||||
// last_logical_scroll_top.unwrap()
|
|
||||||
// );
|
|
||||||
// state.0.borrow_mut().scroll(
|
|
||||||
// last_logical_scroll_top.as_ref().unwrap(),
|
|
||||||
// height,
|
|
||||||
// delta,
|
|
||||||
// true,
|
|
||||||
// &mut presenter.build_event_context(&mut Default::default(), cx),
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// 30..=34 => {
|
|
||||||
// width = rng.gen_range(0..=2000) as f32 / 2.;
|
|
||||||
// log::info!("changing width: {:?}", width);
|
|
||||||
// }
|
|
||||||
// 35..=54 => {
|
|
||||||
// height = rng.gen_range(0..=1000) as f32 / 2.;
|
|
||||||
// log::info!("changing height: {:?}", height);
|
|
||||||
// }
|
|
||||||
// _ => {
|
|
||||||
// let mut elements = elements.borrow_mut();
|
|
||||||
// let end_ix = rng.gen_range(0..=elements.len());
|
|
||||||
// let start_ix = rng.gen_range(0..=end_ix);
|
|
||||||
// let new_elements = (0..rng.gen_range(0..10))
|
|
||||||
// .map(|_| {
|
|
||||||
// let id = next_id;
|
|
||||||
// next_id += 1;
|
|
||||||
// (id, rng.gen_range(0..=200) as f32 / 2.)
|
|
||||||
// })
|
|
||||||
// .collect::<Vec<_>>();
|
|
||||||
// log::info!("splice({:?}, {:?})", start_ix..end_ix, new_elements);
|
|
||||||
// state.splice(start_ix..end_ix, new_elements.len());
|
|
||||||
// elements.splice(start_ix..end_ix, new_elements);
|
|
||||||
// for (ix, item) in state.0.borrow().items.cursor::<()>().enumerate() {
|
|
||||||
// if let ListItem::Rendered(element) = item {
|
|
||||||
// let (expected_id, _) = elements[ix];
|
|
||||||
// element.with_metadata(|metadata: Option<&usize>| {
|
|
||||||
// assert_eq!(*metadata.unwrap(), expected_id);
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let mut list = List::new(state.clone());
|
let mut last_logical_scroll_top = None;
|
||||||
// let window_size = vec2f(width, height);
|
for _ in 0..operations {
|
||||||
// let (size, logical_scroll_top) = list.layout(
|
match rng.gen_range(0..=100) {
|
||||||
// SizeConstraint::new(vec2f(0., 0.), window_size),
|
0..=29 if last_logical_scroll_top.is_some() => {
|
||||||
// &mut presenter.build_layout_context(window_size, false, cx),
|
let delta = vec2f(0., rng.gen_range(-overdraw..=overdraw));
|
||||||
// );
|
log::info!(
|
||||||
// assert_eq!(size, window_size);
|
"Scrolling by {:?}, previous scroll top: {:?}",
|
||||||
// last_logical_scroll_top = Some(logical_scroll_top);
|
delta,
|
||||||
|
last_logical_scroll_top.unwrap()
|
||||||
|
);
|
||||||
|
state.0.borrow_mut().scroll(
|
||||||
|
last_logical_scroll_top.as_ref().unwrap(),
|
||||||
|
height,
|
||||||
|
delta,
|
||||||
|
true,
|
||||||
|
&mut view,
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
30..=34 => {
|
||||||
|
width = rng.gen_range(0..=2000) as f32 / 2.;
|
||||||
|
log::info!("changing width: {:?}", width);
|
||||||
|
}
|
||||||
|
35..=54 => {
|
||||||
|
height = rng.gen_range(0..=1000) as f32 / 2.;
|
||||||
|
log::info!("changing height: {:?}", height);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let mut elements = elements.borrow_mut();
|
||||||
|
let end_ix = rng.gen_range(0..=elements.len());
|
||||||
|
let start_ix = rng.gen_range(0..=end_ix);
|
||||||
|
let new_elements = (0..rng.gen_range(0..10))
|
||||||
|
.map(|_| {
|
||||||
|
let id = next_id;
|
||||||
|
next_id += 1;
|
||||||
|
(id, rng.gen_range(0..=200) as f32 / 2.)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
log::info!("splice({:?}, {:?})", start_ix..end_ix, new_elements);
|
||||||
|
state.splice(start_ix..end_ix, new_elements.len());
|
||||||
|
elements.splice(start_ix..end_ix, new_elements);
|
||||||
|
for (ix, item) in state.0.borrow().items.cursor::<()>().enumerate() {
|
||||||
|
if let ListItem::Rendered(element) = item {
|
||||||
|
let (expected_id, _) = elements[ix];
|
||||||
|
element.borrow().with_metadata(|metadata: Option<&usize>| {
|
||||||
|
assert_eq!(*metadata.unwrap(), expected_id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// let state = state.0.borrow();
|
let mut list = List::new(state.clone());
|
||||||
// log::info!("items {:?}", state.items.items(&()));
|
let window_size = vec2f(width, height);
|
||||||
|
let (size, logical_scroll_top) = list.layout(
|
||||||
|
SizeConstraint::new(vec2f(0., 0.), window_size),
|
||||||
|
&mut view,
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
assert_eq!(size, window_size);
|
||||||
|
last_logical_scroll_top = Some(logical_scroll_top);
|
||||||
|
|
||||||
// let scroll_top = state.scroll_top(&logical_scroll_top);
|
let state = state.0.borrow();
|
||||||
// let rendered_top = (scroll_top - overdraw).max(0.);
|
log::info!("items {:?}", state.items.items(&()));
|
||||||
// let rendered_bottom = scroll_top + height + overdraw;
|
|
||||||
// let mut item_top = 0.;
|
|
||||||
|
|
||||||
// log::info!(
|
let scroll_top = state.scroll_top(&logical_scroll_top);
|
||||||
// "rendered top {:?}, rendered bottom {:?}, scroll top {:?}",
|
let rendered_top = (scroll_top - overdraw).max(0.);
|
||||||
// rendered_top,
|
let rendered_bottom = scroll_top + height + overdraw;
|
||||||
// rendered_bottom,
|
let mut item_top = 0.;
|
||||||
// scroll_top,
|
|
||||||
// );
|
|
||||||
|
|
||||||
// let mut first_rendered_element_top = None;
|
log::info!(
|
||||||
// let mut last_rendered_element_bottom = None;
|
"rendered top {:?}, rendered bottom {:?}, scroll top {:?}",
|
||||||
// assert_eq!(state.items.summary().count, elements.borrow().len());
|
rendered_top,
|
||||||
// for (ix, item) in state.items.cursor::<()>().enumerate() {
|
rendered_bottom,
|
||||||
// match item {
|
scroll_top,
|
||||||
// ListItem::Unrendered => {
|
);
|
||||||
// let item_bottom = item_top;
|
|
||||||
// assert!(item_bottom <= rendered_top || item_top >= rendered_bottom);
|
|
||||||
// item_top = item_bottom;
|
|
||||||
// }
|
|
||||||
// ListItem::Removed(height) => {
|
|
||||||
// let (id, expected_height) = elements.borrow()[ix];
|
|
||||||
// assert_eq!(
|
|
||||||
// *height, expected_height,
|
|
||||||
// "element {} height didn't match",
|
|
||||||
// id
|
|
||||||
// );
|
|
||||||
// let item_bottom = item_top + height;
|
|
||||||
// assert!(item_bottom <= rendered_top || item_top >= rendered_bottom);
|
|
||||||
// item_top = item_bottom;
|
|
||||||
// }
|
|
||||||
// ListItem::Rendered(element) => {
|
|
||||||
// let (expected_id, expected_height) = elements.borrow()[ix];
|
|
||||||
// element.with_metadata(|metadata: Option<&usize>| {
|
|
||||||
// assert_eq!(*metadata.unwrap(), expected_id);
|
|
||||||
// });
|
|
||||||
// assert_eq!(element.size().y(), expected_height);
|
|
||||||
// let item_bottom = item_top + element.size().y();
|
|
||||||
// first_rendered_element_top.get_or_insert(item_top);
|
|
||||||
// last_rendered_element_bottom = Some(item_bottom);
|
|
||||||
// assert!(item_bottom > rendered_top || item_top < rendered_bottom);
|
|
||||||
// item_top = item_bottom;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// match orientation {
|
let mut first_rendered_element_top = None;
|
||||||
// Orientation::Top => {
|
let mut last_rendered_element_bottom = None;
|
||||||
// if let Some(first_rendered_element_top) = first_rendered_element_top {
|
assert_eq!(state.items.summary().count, elements.borrow().len());
|
||||||
// assert!(first_rendered_element_top <= scroll_top);
|
for (ix, item) in state.items.cursor::<()>().enumerate() {
|
||||||
// }
|
match item {
|
||||||
// }
|
ListItem::Unrendered => {
|
||||||
// Orientation::Bottom => {
|
let item_bottom = item_top;
|
||||||
// if let Some(last_rendered_element_bottom) = last_rendered_element_bottom {
|
assert!(item_bottom <= rendered_top || item_top >= rendered_bottom);
|
||||||
// assert!(last_rendered_element_bottom >= scroll_top + height);
|
item_top = item_bottom;
|
||||||
// }
|
}
|
||||||
// }
|
ListItem::Removed(height) => {
|
||||||
// }
|
let (id, expected_height) = elements.borrow()[ix];
|
||||||
// }
|
assert_eq!(
|
||||||
|
*height, expected_height,
|
||||||
|
"element {} height didn't match",
|
||||||
|
id
|
||||||
|
);
|
||||||
|
let item_bottom = item_top + height;
|
||||||
|
assert!(item_bottom <= rendered_top || item_top >= rendered_bottom);
|
||||||
|
item_top = item_bottom;
|
||||||
|
}
|
||||||
|
ListItem::Rendered(element) => {
|
||||||
|
let (expected_id, expected_height) = elements.borrow()[ix];
|
||||||
|
let element = element.borrow();
|
||||||
|
element.with_metadata(|metadata: Option<&usize>| {
|
||||||
|
assert_eq!(*metadata.unwrap(), expected_id);
|
||||||
|
});
|
||||||
|
assert_eq!(element.size().y(), expected_height);
|
||||||
|
let item_bottom = item_top + element.size().y();
|
||||||
|
first_rendered_element_top.get_or_insert(item_top);
|
||||||
|
last_rendered_element_bottom = Some(item_bottom);
|
||||||
|
assert!(item_bottom > rendered_top || item_top < rendered_bottom);
|
||||||
|
item_top = item_bottom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match orientation {
|
||||||
|
Orientation::Top => {
|
||||||
|
if let Some(first_rendered_element_top) = first_rendered_element_top {
|
||||||
|
assert!(first_rendered_element_top <= scroll_top);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Orientation::Bottom => {
|
||||||
|
if let Some(last_rendered_element_bottom) = last_rendered_element_bottom {
|
||||||
|
assert!(last_rendered_element_bottom >= scroll_top + height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
view
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TestView;
|
struct TestView;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue