mirror of
https://github.com/storytold/wordcraft.git
synced 2026-11-08 03:09:51 -06:00
* #4753: Styles pane scroll bar keeps clear of the a / ¶ markers The Styles pane list used egui's default floating scroll bar, which is drawn over the right edge of the rows; on hover it widens to 10 pt with a translucent track and covers the right-aligned "a" and "¶" style-type markers. The list now uses a solid scroll bar, which takes a column of its own beside the rows (as in the TOC options dialog and vectorcraft#2232's menus). Its handle keeps the text colour: the solid preset fills it with the button colour, which is white on the pane's white track and would leave the handle invisible. The regression test draws the pane with the app theme, hovers the bar and checks that no scroll bar rectangle meets a marker and that the handle stands out from the track. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * #4753: Styles pane scroll bar test hovers the bar and checks dark too The test now takes the hover point from the pane's own right edge instead of the harness size (kittest insets the UI, so the old point sat just outside the bar), asserts the pointer is on the bar, and runs in the dark appearance as well as the light one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Martin Ball <martin.ball@ucscaregroup.co.uk>
This commit is contained in:
co-authored by
Claude Opus 5.5
Martin Ball
parent
bc0f691c13
commit
b61aee61ba
@@ -72,6 +72,9 @@ pub(super) fn styles(app: &mut WordApp, ui: &mut Ui) {
|
||||
if ui.selectable_label(app.session.view.style_inspector, tl!("Style Inspector")).clicked() {
|
||||
let _ = app.run("styles.inspector", json!({}));
|
||||
}
|
||||
// A solid scroll bar takes its own room beside the list instead of floating over the a / ¶ markers.
|
||||
// Its handle keeps the text colour: the solid default fills it like a button, white on white here.
|
||||
ui.spacing_mut().scroll = egui::style::ScrollStyle { foreground_color: true, ..egui::style::ScrollStyle::solid() };
|
||||
ui.separator();
|
||||
let mut list: Vec<(String, String, bool, bool)> = app
|
||||
.session
|
||||
|
||||
@@ -468,3 +468,59 @@ fn a_long_comment_card_keeps_its_buttons_and_the_next_card_in_view() {
|
||||
assert_eq!(go_to.len(), 2, "one Go to button per card");
|
||||
assert!(go_to.iter().all(|r| r.max.y < 900.0), "both cards' buttons are in view: {go_to:?}");
|
||||
}
|
||||
|
||||
/// #4753: the Styles pane's scroll bar has a column of its own, so with the pointer over it the
|
||||
/// "a" and "¶" markers at the right of each row stay clear of it; its handle still shows, light
|
||||
/// or dark.
|
||||
#[test]
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn the_styles_pane_scroll_bar_leaves_the_style_markers_clear() {
|
||||
use egui_kittest::kittest::Queryable;
|
||||
for appearance in [crate::theme::Appearance::Light, crate::theme::Appearance::Dark] {
|
||||
let app = crate::WordApp::new(wordcraft_engine::Session::new(wordcraft_doc::Document::from_text("Hello")), crate::Services::default());
|
||||
let size = egui::vec2(240.0, 400.0);
|
||||
let right = std::rc::Rc::new(std::cell::Cell::new(0.0));
|
||||
let edge = right.clone();
|
||||
let mut fonts = false;
|
||||
let mut h = egui_kittest::Harness::builder().with_size(size).build_ui_state(
|
||||
move |ui, app: &mut crate::WordApp| {
|
||||
if !fonts {
|
||||
crate::theme::install_fonts(ui.ctx());
|
||||
crate::theme::apply(ui.ctx(), appearance);
|
||||
fonts = true;
|
||||
return;
|
||||
}
|
||||
edge.set(ui.max_rect().right());
|
||||
super::styles(app, ui);
|
||||
},
|
||||
app,
|
||||
);
|
||||
h.run_steps(4);
|
||||
// On the bar, along the pane's right edge, where it is at its widest.
|
||||
h.hover_at(egui::pos2(right.get() - 3.0, size.y - 60.0));
|
||||
h.run_steps(20);
|
||||
let markers: Vec<egui::Rect> = h.get_all_by_label("¶").chain(h.get_all_by_label("a")).map(|n| n.rect()).collect();
|
||||
assert!(markers.len() > 5, "{appearance:?}: the list shows its markers: {markers:?}");
|
||||
// Only a scroll bar is a narrow, tall filled rectangle along the list's right edge.
|
||||
let bars: Vec<(egui::Rect, egui::Color32)> = h
|
||||
.output()
|
||||
.shapes
|
||||
.iter()
|
||||
.filter_map(|c| match &c.shape {
|
||||
egui::Shape::Rect(r) if r.fill.a() > 0 && r.rect.width() < 20.0 && r.rect.height() > 3.0 * r.rect.width() => {
|
||||
Some((r.rect.intersect(c.clip_rect), r.fill))
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
assert!(bars.iter().any(|(b, _)| b.x_range().contains(right.get() - 3.0)), "{appearance:?}: the pointer is on the bar: {bars:?}");
|
||||
let covered: Vec<_> = markers.iter().filter(|m| bars.iter().any(|(b, _)| b.intersects(**m))).collect();
|
||||
assert!(covered.is_empty(), "{appearance:?}: the scroll bar {bars:?} covers markers {covered:?}");
|
||||
// The track is the pane's field colour; the handle stands out from it.
|
||||
let track = h.ctx.global_style().visuals.extreme_bg_color;
|
||||
assert!(
|
||||
bars.iter().any(|(_, fill)| fill.r().abs_diff(track.r()) > 60),
|
||||
"{appearance:?}: the handle shows against the track {track:?}: {bars:?}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user