feat(ui): refine Graphite visuals and center navigation content
This commit is contained in:
1 parent
cc3b6f903f
commit
1e34ec47ad
14 files changed
+646
-121
No files matched your search
@@ -1021,10 +1021,10 @@ fn sidebar_collapses_at_the_breakpoint_and_compact_navigation_dismisses() {
|
||||
let compact = width < 960.;
|
||||
assert_eq!(bounds.sidebar.is_none(), compact);
|
||||
assert_eq!(bounds.toggle.is_some(), compact);
|
||||
assert_eq!(bounds.page.unwrap().x, if compact { 0. } else { 204. });
|
||||
assert_eq!(bounds.page.unwrap().x, if compact { 0. } else { 208. });
|
||||
assert_eq!(
|
||||
bounds.page.unwrap().width,
|
||||
if compact { width } else { width - 204. }
|
||||
if compact { width } else { width - 208. }
|
||||
);
|
||||
}
|
||||
let _ = app.update(Message::Sidebar(true));
|
||||
@@ -1084,3 +1084,173 @@ fn sidebar_collapses_at_the_breakpoint_and_compact_navigation_dismisses() {
|
||||
);
|
||||
assert!(app.pending.is_empty() && !app.saving);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn appearance_cards_reflow_without_overlap_and_keep_every_destination() {
|
||||
#[derive(Default)]
|
||||
struct Cards {
|
||||
bounds: std::collections::HashMap<usize, Rectangle>,
|
||||
}
|
||||
impl Operation for Cards {
|
||||
fn traverse(&mut self, children: &mut dyn FnMut(&mut dyn Operation)) {
|
||||
children(self);
|
||||
}
|
||||
fn container(&mut self, id: Option<&widget::Id>, bounds: Rectangle) {
|
||||
for page in Page::ALL {
|
||||
if id == Some(&widget::Id::new(format!("settings-hub-{}", page as usize))) {
|
||||
self.bounds.insert(page as usize, bounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let runtime = tokio::runtime::Builder::new_current_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap();
|
||||
let renderer = runtime
|
||||
.block_on(<cosmic::Renderer as Headless>::new(
|
||||
Font::default(),
|
||||
Pixels(14.),
|
||||
Some("tiny-skia"),
|
||||
))
|
||||
.unwrap();
|
||||
let app = App::init(
|
||||
Core::default(),
|
||||
(
|
||||
"/unused/overview.kdl".into(),
|
||||
Snapshot::parse(String::new()),
|
||||
None,
|
||||
),
|
||||
)
|
||||
.0;
|
||||
for width in [480., 720., 960., 1280., 1800.] {
|
||||
let mut view = app.page_view();
|
||||
let mut tree = Tree::new(&view);
|
||||
let node = view.as_widget_mut().layout(
|
||||
&mut tree,
|
||||
&renderer,
|
||||
&layout::Limits::new(Size::ZERO, Size::new(width, 760.)),
|
||||
);
|
||||
let mut cards = Cards::default();
|
||||
view.as_widget_mut()
|
||||
.operate(&mut tree, Layout::new(&node), &renderer, &mut cards);
|
||||
assert_eq!(
|
||||
cards.bounds.len(),
|
||||
14,
|
||||
"{width}: all settings destinations must be reachable"
|
||||
);
|
||||
for bounds in cards.bounds.values() {
|
||||
assert!(
|
||||
bounds.x >= 0. && bounds.x + bounds.width <= width + 0.5,
|
||||
"{width}: {bounds:?}"
|
||||
);
|
||||
assert!(bounds.width > 200. && bounds.height > 40.);
|
||||
}
|
||||
let general = cards.bounds[&(Page::General as usize)];
|
||||
let complete = cards.bounds[&(Page::Configuration as usize)];
|
||||
if width <= 720. {
|
||||
assert!((general.x - complete.x).abs() < 0.5);
|
||||
assert!(complete.y >= general.y + general.height);
|
||||
} else {
|
||||
assert!((general.y - complete.y).abs() < 0.5);
|
||||
assert!(complete.x >= general.x + general.width + 8.);
|
||||
}
|
||||
let rectangles = cards.bounds.values().collect::<Vec<_>>();
|
||||
for (i, a) in rectangles.iter().enumerate() {
|
||||
for b in &rectangles[i + 1..] {
|
||||
assert!(
|
||||
a.intersection(*b).is_none(),
|
||||
"{width}: cards overlap: {a:?} {b:?}"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sidebar_rows_center_inside_the_full_button_hit_area() {
|
||||
#[derive(Default)]
|
||||
struct Centers {
|
||||
buttons: std::collections::HashMap<usize, Rectangle>,
|
||||
parts: Vec<(usize, Rectangle)>,
|
||||
}
|
||||
impl Operation for Centers {
|
||||
fn traverse(&mut self, children: &mut dyn FnMut(&mut dyn Operation)) {
|
||||
children(self);
|
||||
}
|
||||
fn focusable(
|
||||
&mut self,
|
||||
id: Option<&widget::Id>,
|
||||
bounds: Rectangle,
|
||||
_: &mut dyn cosmic::iced::advanced::widget::operation::Focusable,
|
||||
) {
|
||||
for page in Page::ALL {
|
||||
if id
|
||||
== Some(&widget::Id::new(format!(
|
||||
"settings-nav-button-{}",
|
||||
page as usize
|
||||
)))
|
||||
{
|
||||
self.buttons.insert(page as usize, bounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
fn container(&mut self, id: Option<&widget::Id>, bounds: Rectangle) {
|
||||
for page in Page::ALL {
|
||||
for part in ["content", "icon", "label", "marker"] {
|
||||
if id
|
||||
== Some(&widget::Id::new(format!(
|
||||
"settings-nav-{part}-{}",
|
||||
page as usize
|
||||
)))
|
||||
{
|
||||
self.parts.push((page as usize, bounds));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let runtime = tokio::runtime::Builder::new_current_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap();
|
||||
let renderer = runtime
|
||||
.block_on(<cosmic::Renderer as Headless>::new(
|
||||
Font::default(),
|
||||
Pixels(14.),
|
||||
Some("tiny-skia"),
|
||||
))
|
||||
.unwrap();
|
||||
let mut app = App::init(
|
||||
Core::default(),
|
||||
(
|
||||
"/unused/navigation-centers.kdl".into(),
|
||||
Snapshot::parse(String::new()),
|
||||
None,
|
||||
),
|
||||
)
|
||||
.0;
|
||||
for selected in [Page::Windows, Page::Keyboard, Page::Accessibility] {
|
||||
app.page = selected;
|
||||
let mut view = app.page_view();
|
||||
let mut tree = Tree::new(&view);
|
||||
let node = view.as_widget_mut().layout(
|
||||
&mut tree,
|
||||
&renderer,
|
||||
&layout::Limits::new(Size::ZERO, Size::new(1280., 760.)),
|
||||
);
|
||||
let mut centers = Centers::default();
|
||||
view.as_widget_mut()
|
||||
.operate(&mut tree, Layout::new(&node), &renderer, &mut centers);
|
||||
assert_eq!(centers.buttons.len(), 15);
|
||||
assert_eq!(centers.parts.len(), 60);
|
||||
for (page, part) in ¢ers.parts {
|
||||
let button = centers.buttons[page];
|
||||
assert_eq!(button.height, 36.);
|
||||
assert!(
|
||||
((part.y + part.height / 2.) - (button.y + button.height / 2.)).abs() < 0.51,
|
||||
"page {page}: content {part:?} is not centered in {button:?}"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user