R5.1: in a table, ElyDoc's panel shows the Table group first (component 9ff403d keys folds by title); three rounds, R3 PASS

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
ZacharyZhang-NYandClaude Opus 5.5 committed 2026-10-13 23:37:47 -04:00
1 parent c3f6684a46
commit b5bfb77ba0
12 files changed
+131 -30

No files matched your search

+7 -7
View File
@@ -250,15 +250,15 @@ impl Render for Props {
let grid = if graphic {
grid.group(self.object_group(cx))
} else {
let grid = grid
.group(self.text_group(window, cx))
.group(self.paragraph_group(cx))
.group(self.style_group(cx))
.group(self.page_group(cx));
match self.state(".uno:DeleteTable", cx).as_deref() {
// In a table, its group leads, as in Word.
let grid = match self.state(".uno:DeleteTable", cx).as_deref() {
Some("enabled") => grid.group(self.table_group(cx)),
_ => grid,
}
};
grid.group(self.text_group(window, cx))
.group(self.paragraph_group(cx))
.group(self.style_group(cx))
.group(self.page_group(cx))
};
div()
.size_full()
+7 -2
View File
@@ -2,7 +2,7 @@
use ely_gpui_component::{data_display::PropertyGroup, primitives::IconName};
use ely_office::panel::{Panel, color_state, font_box, palette, row, size_menu, toggle};
use gpui::{App, Context, SharedString, Window};
use gpui::{App, Context, InteractiveElement, ParentElement, SharedString, Window, div};
use super::Props;
use crate::docs::Docs;
@@ -77,7 +77,12 @@ impl Props {
PropertyGroup::new(tip("doc.props.text"))
.row(tip("doc.props.font"), font)
.row(tip("doc.props.size"), size_menu(self, "doc-props-size", cx))
.row(tip("doc.props.effects"), effects)
.row(
tip("doc.props.effects"),
div()
.debug_selector(|| "doc-props-text".into())
.child(effects),
)
.row(
tip("doc.props.color"),
palette(&this, "format.color", (color, AUTOMATIC), None, cx),
+8 -6
View File
@@ -2,7 +2,7 @@
use ely_gpui_component::{buttons::Button, data_display::PropertyGroup, theme::ControlSize};
use ely_office::panel::{button, color_state, palette, row, send, toggle};
use gpui::{AnyElement, Context, IntoElement, SharedString};
use gpui::{AnyElement, Context, InteractiveElement, IntoElement, ParentElement, SharedString, div};
use super::Props;
use crate::docs::Docs;
@@ -14,11 +14,13 @@ impl Props {
PropertyGroup::new(tip("doc.props.table"))
.row(
tip("doc.props.rows"),
row([
button(self, "table.row_above", "doc.props.above_row", why, cx),
button(self, "table.row_below", "doc.props.below_row", why, cx),
button(self, "table.delete_rows", "doc.props.delete", why, cx),
]),
div()
.debug_selector(|| "doc-props-table".into())
.child(row([
button(self, "table.row_above", "doc.props.above_row", why, cx),
button(self, "table.row_below", "doc.props.below_row", why, cx),
button(self, "table.delete_rows", "doc.props.delete", why, cx),
])),
)
.row(
tip("doc.props.columns"),
+80
View File
@@ -1,5 +1,6 @@
use std::{cell::RefCell, rc::Rc};
use ely_gpui_component::theme::Theme;
use ely_lok::LokError;
use ely_office::panel::Panel as _;
use gpui::{Entity, TestAppContext};
@@ -296,3 +297,82 @@ fn quick_spacing_edits_keep_each_other() {
"both quick edits land"
);
}
/// A window root that shows the panel.
struct Shown(Entity<Props>);
impl gpui::Render for Shown {
fn render(
&mut self,
_: &mut gpui::Window,
_: &mut gpui::Context<Self>,
) -> impl gpui::IntoElement {
use gpui::{ParentElement as _, Styled as _};
gpui::div().size_full().child(self.0.clone())
}
}
/// The top of the element marked `selector`.
fn top(cx: &mut gpui::VisualTestContext, selector: &'static str) -> Option<gpui::Pixels> {
// Past reduced motion's 1ms folds.
for _ in 0..3 {
std::thread::sleep(std::time::Duration::from_millis(2));
cx.update(|window, _| window.refresh());
cx.run_until_parked();
}
cx.debug_bounds(selector).map(|bounds| bounds.origin.y)
}
#[test]
fn in_a_table_the_table_group_comes_first_and_folds_stay_put() {
const DOWN: i32 = 1024;
const UP: i32 = 1025;
let dir = tempfile::tempdir().expect("a temp dir");
let mut cx = TestAppContext::single();
let Some(docs) = docs(&mut cx, dir.path()) else {
eprintln!("SKIP: no LOK build");
return;
};
cx.update(|cx| {
ely_gpui_component::init_for_tests(cx);
Theme::update(cx, |theme| theme.reduced_motion = true);
});
blank(&mut cx, &docs);
type_into(&mut cx, &docs, "Table");
let props = panel(&mut cx, &docs);
let window = cx.add_window(|_, _| Shown(props.clone()));
let mut shown = gpui::VisualTestContext::from_window(window.into(), &cx);
assert_eq!(
top(&mut shown, "doc-props-table"),
None,
"no table, no group"
);
let header = gpui::point(gpui::px(10.0), gpui::px(12.0));
shown.simulate_click(header, gpui::Modifiers::none());
assert_eq!(top(&mut shown, "doc-props-text"), None, "Text folds");
shown.simulate_click(header, gpui::Modifiers::none());
assert!(top(&mut shown, "doc-props-text").is_some(), "Text opens");
with_window(&mut cx, &docs, |docs, _, cx| {
docs.insert_table(3.0, 2.0, cx)
});
let in_table = |app: &gpui::App| props.read(app).state(".uno:DeleteTable", app);
settle(&cx, |app| in_table(app).as_deref() == Some("enabled"));
let table = top(&mut shown, "doc-props-table").expect("the table group");
let text = top(&mut shown, "doc-props-text").expect("the text group");
assert!(table < text, "the table group leads: {table:?} vs {text:?}");
keys(&mut cx, &docs, &[UP]);
settle(&cx, |app| in_table(app).as_deref() != Some("enabled"));
shown.simulate_click(header, gpui::Modifiers::none());
assert_eq!(top(&mut shown, "doc-props-text"), None, "Text folds again");
keys(&mut cx, &docs, &[DOWN]);
settle(&cx, |app| in_table(app).as_deref() == Some("enabled"));
assert!(top(&mut shown, "doc-props-table").is_some(), "Table opens");
assert_eq!(top(&mut shown, "doc-props-text"), None, "Text stays folded");
keys(&mut cx, &docs, &[UP]);
settle(&cx, |app| in_table(app).as_deref() != Some("enabled"));
assert_eq!(
top(&mut shown, "doc-props-text"),
None,
"and after the table"
);
}