R8.3: sheet tab strip scrolls the chosen sheet in (Gitea #8)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
9 files changed
+136
-23
No files matched your search
@@ -109,18 +109,12 @@ impl Book {
|
||||
let Some(tab) = self.active_tab() else {
|
||||
return div().into_any_element();
|
||||
};
|
||||
let Some(choices) = visible(&tab.extra.sheets) else {
|
||||
let Some(tabs) = strip(tab.id, &tab.extra.sheets) else {
|
||||
return div().into_any_element();
|
||||
};
|
||||
let this = cx.entity();
|
||||
let picked = this.clone();
|
||||
let tabs = SheetTabs::new(
|
||||
"table-sheets",
|
||||
choices,
|
||||
tab.extra.sheets.current.to_string(),
|
||||
)
|
||||
.placement(TabPlacement::Bottom)
|
||||
.on_change(move |value, _, cx| {
|
||||
let tabs = tabs.on_change(move |value, _, cx| {
|
||||
let index: usize = value.parse().expect("sheet tabs are indexes");
|
||||
picked.update(cx, |book, cx| book.show_sheet(index, cx));
|
||||
})
|
||||
@@ -310,6 +304,15 @@ impl Book {
|
||||
}
|
||||
}
|
||||
|
||||
/// Workbook `id`'s sheet tabs; each workbook keeps its own scroll.
|
||||
fn strip(id: u64, sheets: &ely_lok::Sheets) -> Option<SheetTabs> {
|
||||
let choices = visible(sheets)?;
|
||||
Some(
|
||||
SheetTabs::new(("table-sheets", id), choices, sheets.current.to_string())
|
||||
.placement(TabPlacement::Bottom),
|
||||
)
|
||||
}
|
||||
|
||||
/// Visible sheets as tabs, once the shown one is known.
|
||||
fn visible(sheets: &ely_lok::Sheets) -> Option<Vec<Choice>> {
|
||||
let shown = sheets.list.get(sheets.current)?;
|
||||
@@ -327,6 +330,10 @@ fn visible(sheets: &ely_lok::Sheets) -> Option<Vec<Choice>> {
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "tests/strip.rs"]
|
||||
mod strip_tests;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
//! Each workbook's strip shows its own chosen sheet.
|
||||
|
||||
use ely_lok::{Sheet, Sheets};
|
||||
use gpui::{
|
||||
Bounds, Context, IntoElement, Modifiers, ParentElement as _, Pixels, Render, RenderOnce as _,
|
||||
ScrollDelta, ScrollHandle, ScrollWheelEvent, Styled as _, TestAppContext, TouchPhase,
|
||||
VisualTestContext, Window, div, point, px,
|
||||
};
|
||||
|
||||
use super::strip;
|
||||
|
||||
struct Books {
|
||||
book: u64,
|
||||
sheets: Sheets,
|
||||
scroll: Option<ScrollHandle>,
|
||||
}
|
||||
|
||||
impl Render for Books {
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let tabs = strip(self.book, &self.sheets)
|
||||
.expect("tabs")
|
||||
.render(window, cx)
|
||||
.into_any_element();
|
||||
let id = gpui::ElementId::from(("table-sheets", self.book));
|
||||
let handle = window.use_keyed_state((id, "scroll"), cx, |_, _| ScrollHandle::new());
|
||||
self.scroll = Some(handle.read(cx).clone());
|
||||
div()
|
||||
.w(px(640.))
|
||||
.child(div().flex().items_center().px_2().child(tabs))
|
||||
}
|
||||
}
|
||||
|
||||
fn settle(cx: &mut VisualTestContext) {
|
||||
for _ in 0..5 {
|
||||
cx.run_until_parked();
|
||||
cx.update(|window, _| window.refresh());
|
||||
}
|
||||
cx.run_until_parked();
|
||||
}
|
||||
|
||||
/// The strip's viewport and the chosen tab in it.
|
||||
fn place(
|
||||
view: &gpui::Entity<Books>,
|
||||
cx: &mut VisualTestContext,
|
||||
) -> (Bounds<Pixels>, Bounds<Pixels>) {
|
||||
view.read_with(cx, |view, _| {
|
||||
let scroll = view.scroll.as_ref().expect("drawn");
|
||||
let mut chosen = scroll
|
||||
.bounds_for_item(view.sheets.current)
|
||||
.expect("chosen tab");
|
||||
chosen.origin += scroll.offset();
|
||||
(scroll.bounds(), chosen)
|
||||
})
|
||||
}
|
||||
|
||||
fn shown(view: &gpui::Entity<Books>, cx: &mut VisualTestContext) -> bool {
|
||||
let (viewport, chosen) = place(view, cx);
|
||||
chosen.left() >= viewport.left() && chosen.right() <= viewport.right()
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn a_switched_workbook_shows_its_chosen_sheet(cx: &mut TestAppContext) {
|
||||
cx.update(ely_gpui_component::init_for_tests);
|
||||
let sheets = Sheets {
|
||||
current: 29,
|
||||
list: (0..30)
|
||||
.map(|n| Sheet {
|
||||
name: format!("Sheet {n}"),
|
||||
visible: true,
|
||||
})
|
||||
.collect(),
|
||||
};
|
||||
let (view, cx) = cx.add_window_view(|_, _| Books {
|
||||
book: 1,
|
||||
sheets,
|
||||
scroll: None,
|
||||
});
|
||||
settle(cx);
|
||||
assert!(shown(&view, cx), "the first draw shows the chosen sheet");
|
||||
for book in [2, 1, 2] {
|
||||
cx.simulate_event(ScrollWheelEvent {
|
||||
position: point(px(60.), px(16.)),
|
||||
delta: ScrollDelta::Pixels(point(px(0.), px(50_000.))),
|
||||
modifiers: Modifiers::none(),
|
||||
touch_phase: TouchPhase::Moved,
|
||||
});
|
||||
settle(cx);
|
||||
assert!(!shown(&view, cx), "the wheel moves the chosen sheet away");
|
||||
view.update(cx, |view, cx| {
|
||||
view.book = book;
|
||||
cx.notify();
|
||||
});
|
||||
settle(cx);
|
||||
assert!(shown(&view, cx), "workbook {book} shows its chosen sheet");
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user