mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-12 13:24:19 +00:00
Implement and test splice
for ListState
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
parent
2c3ba00d3e
commit
03b7c3c8c6
1 changed files with 93 additions and 5 deletions
|
@ -4,7 +4,7 @@ use crate::{
|
||||||
Element,
|
Element,
|
||||||
};
|
};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::sync::Arc;
|
use std::{ops::Range, sync::Arc};
|
||||||
|
|
||||||
use crate::ElementBox;
|
use crate::ElementBox;
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ pub struct List {
|
||||||
state: ListState,
|
state: ListState,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct ListState(Arc<Mutex<StateInner>>);
|
pub struct ListState(Arc<Mutex<StateInner>>);
|
||||||
|
|
||||||
struct StateInner {
|
struct StateInner {
|
||||||
|
@ -26,7 +27,7 @@ enum ElementHeight {
|
||||||
Ready(f32),
|
Ready(f32),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default, PartialEq)]
|
||||||
struct ElementHeightSummary {
|
struct ElementHeightSummary {
|
||||||
count: usize,
|
count: usize,
|
||||||
pending_count: usize,
|
pending_count: usize,
|
||||||
|
@ -42,6 +43,12 @@ struct PendingCount(usize);
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
struct Height(f32);
|
struct Height(f32);
|
||||||
|
|
||||||
|
impl List {
|
||||||
|
pub fn new(state: ListState) -> Self {
|
||||||
|
Self { state }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Element for List {
|
impl Element for List {
|
||||||
type LayoutState = ();
|
type LayoutState = ();
|
||||||
|
|
||||||
|
@ -82,8 +89,7 @@ impl Element for List {
|
||||||
|
|
||||||
drop(old_heights);
|
drop(old_heights);
|
||||||
state.heights = new_heights;
|
state.heights = new_heights;
|
||||||
|
(constraint.max, ())
|
||||||
todo!()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint(
|
fn paint(
|
||||||
|
@ -127,6 +133,33 @@ impl ListState {
|
||||||
heights,
|
heights,
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn splice(
|
||||||
|
&self,
|
||||||
|
old_range: Range<usize>,
|
||||||
|
new_elements: impl IntoIterator<Item = ElementBox>,
|
||||||
|
) {
|
||||||
|
let state = &mut *self.0.lock();
|
||||||
|
|
||||||
|
let mut old_heights = state.heights.cursor::<Count, ()>();
|
||||||
|
let mut new_heights = old_heights.slice(&Count(old_range.start), Bias::Right, &());
|
||||||
|
old_heights.seek_forward(&Count(old_range.end), Bias::Right, &());
|
||||||
|
|
||||||
|
let mut len = 0;
|
||||||
|
let old_elements = state.elements.splice(
|
||||||
|
old_range,
|
||||||
|
new_elements.into_iter().map(|e| {
|
||||||
|
len += 1;
|
||||||
|
e
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
drop(old_elements);
|
||||||
|
|
||||||
|
new_heights.extend((0..len).map(|_| ElementHeight::Pending), &());
|
||||||
|
new_heights.push_tree(old_heights.suffix(&()), &());
|
||||||
|
drop(old_heights);
|
||||||
|
state.heights = new_heights;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ElementHeight {
|
impl ElementHeight {
|
||||||
|
@ -158,6 +191,7 @@ impl sum_tree::Summary for ElementHeightSummary {
|
||||||
type Context = ();
|
type Context = ();
|
||||||
|
|
||||||
fn add_summary(&mut self, summary: &Self, _: &()) {
|
fn add_summary(&mut self, summary: &Self, _: &()) {
|
||||||
|
self.count += summary.count;
|
||||||
self.pending_count += summary.pending_count;
|
self.pending_count += summary.pending_count;
|
||||||
self.height += summary.height;
|
self.height += summary.height;
|
||||||
}
|
}
|
||||||
|
@ -175,6 +209,12 @@ impl<'a> sum_tree::Dimension<'a, ElementHeightSummary> for Count {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> sum_tree::SeekDimension<'a, ElementHeightSummary> for Count {
|
||||||
|
fn cmp(&self, other: &Self, _: &()) -> std::cmp::Ordering {
|
||||||
|
self.0.cmp(&other.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> sum_tree::Dimension<'a, ElementHeightSummary> for PendingCount {
|
impl<'a> sum_tree::Dimension<'a, ElementHeightSummary> for PendingCount {
|
||||||
fn add_summary(&mut self, summary: &'a ElementHeightSummary, _: &()) {
|
fn add_summary(&mut self, summary: &'a ElementHeightSummary, _: &()) {
|
||||||
self.0 += summary.pending_count;
|
self.0 += summary.pending_count;
|
||||||
|
@ -196,10 +236,58 @@ impl<'a> sum_tree::Dimension<'a, ElementHeightSummary> for Height {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::{elements::*, geometry::vector::vec2f};
|
||||||
|
|
||||||
#[crate::test(self)]
|
#[crate::test(self)]
|
||||||
fn test_layout(cx: &mut crate::MutableAppContext) {
|
fn test_layout(cx: &mut crate::MutableAppContext) {
|
||||||
let mut presenter = cx.build_presenter(0, 20.0);
|
let mut presenter = cx.build_presenter(0, 20.0);
|
||||||
let layout_cx = presenter.layout_cx(cx);
|
let mut layout_cx = presenter.layout_cx(cx);
|
||||||
|
let state = ListState::new(vec![item(20.), item(30.), item(10.)]);
|
||||||
|
let mut list = List::new(state.clone()).boxed();
|
||||||
|
|
||||||
|
let size = list.layout(
|
||||||
|
SizeConstraint::new(vec2f(0., 0.), vec2f(100., 40.)),
|
||||||
|
&mut layout_cx,
|
||||||
|
);
|
||||||
|
assert_eq!(size, vec2f(100., 40.));
|
||||||
|
assert_eq!(
|
||||||
|
state.0.lock().heights.summary(),
|
||||||
|
ElementHeightSummary {
|
||||||
|
count: 3,
|
||||||
|
pending_count: 0,
|
||||||
|
height: 60.
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
state.splice(1..2, vec![item(40.), item(50.)]);
|
||||||
|
state.splice(3..3, vec![item(60.)]);
|
||||||
|
assert_eq!(
|
||||||
|
state.0.lock().heights.summary(),
|
||||||
|
ElementHeightSummary {
|
||||||
|
count: 5,
|
||||||
|
pending_count: 3,
|
||||||
|
height: 30.
|
||||||
|
}
|
||||||
|
);
|
||||||
|
let size = list.layout(
|
||||||
|
SizeConstraint::new(vec2f(0., 0.), vec2f(100., 40.)),
|
||||||
|
&mut layout_cx,
|
||||||
|
);
|
||||||
|
assert_eq!(size, vec2f(100., 40.));
|
||||||
|
assert_eq!(
|
||||||
|
state.0.lock().heights.summary(),
|
||||||
|
ElementHeightSummary {
|
||||||
|
count: 5,
|
||||||
|
pending_count: 0,
|
||||||
|
height: 180.
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn item(height: f32) -> ElementBox {
|
||||||
|
ConstrainedBox::new(Empty::new().boxed())
|
||||||
|
.with_height(height)
|
||||||
|
.with_width(100.)
|
||||||
|
.boxed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue