use super::text::DWrite;
use crate::event::Rect;
use crate::primitives::sidebar_panel::{SidebarPanel, SidebarPanelLayout, SidebarPanelMeasure};
use crate::primitives::toolbar::{measure_button, ToolbarItemMeasure};
#[cfg(test)]
use crate::theme::Theme;
#[cfg(test)]
use crate::types::WidgetId;
pub fn win_sidebar_panel_layout(
dwrite: &DWrite,
line_height: f32,
rect: Rect,
panel: &SidebarPanel,
) -> SidebarPanelLayout {
panel.layout(rect, SidebarPanelMeasure::new(line_height, 0.0), |btn| {
ToolbarItemMeasure::new(measure_button(dwrite, btn))
})
}
#[cfg(test)]
mod tests {
use super::*;
use crate::primitives::sidebar_panel::SidebarPanelHit;
use crate::primitives::toolbar::{Toolbar, ToolbarButton};
use crate::win::testing::HeadlessSurface;
const W: f32 = 240.0;
const H: f32 = 120.0;
fn paint(
surface: &HeadlessSurface,
dwrite: &DWrite,
line_height: f32,
rect: Rect,
panel: &SidebarPanel,
hovered_toolbar_id: Option<&WidgetId>,
pressed_toolbar_id: Option<&WidgetId>,
) -> SidebarPanelLayout {
let theme = Theme::default();
surface
.paint(|target| {
let mut raw = super::super::surface::D2dSurface {
target,
dwrite: Some(dwrite),
};
crate::primitives::sidebar_panel::native_surface_paint::paint(
panel,
&mut raw,
&theme,
rect,
line_height,
hovered_toolbar_id,
pressed_toolbar_id,
);
})
.map(|_| win_sidebar_panel_layout(dwrite, line_height, rect, panel))
.expect("paint sidebar panel")
}
fn mk_action(id: &str, label: &str) -> ToolbarButton {
ToolbarButton::Action {
id: WidgetId::new(id),
label: label.into(),
icon: None,
key_hint: None,
enabled: true,
is_active: false,
tooltip: String::new(),
}
}
fn panel_with_toolbar() -> SidebarPanel {
SidebarPanel {
id: WidgetId::new("sb"),
toolbar: Some(Toolbar {
id: WidgetId::new("sb:toolbar"),
buttons: vec![mk_action("a", "Refine"), mk_action("b", "Drop")],
bg: None,
focused_index: None,
}),
toolbar_height: None,
}
}
fn panel_without_toolbar() -> SidebarPanel {
SidebarPanel {
id: WidgetId::new("sb"),
toolbar: None,
toolbar_height: None,
}
}
#[test]
fn text_ok_round_trip_click_hits_toolbar_button() {
let panel = panel_with_toolbar();
let surface = HeadlessSurface::new(W as u32, H as u32).expect("create surface");
let (dwrite, _, line_height) = DWrite::new("Segoe UI", 10.0, None).expect("create DWrite");
let rect = Rect::new(0.0, 0.0, W, H);
let layout = paint(&surface, &dwrite, line_height, rect, &panel, None, None);
let tb = layout.toolbar_bounds.expect("toolbar slot reserved");
let hit = layout.hit_test(tb.x + 2.0, tb.y + tb.height / 2.0);
assert_eq!(
hit,
SidebarPanelHit::ToolbarButton(WidgetId::new("a")),
"expected first toolbar button hit"
);
}
#[test]
fn no_toolbar_click_hits_content_local_coords() {
let panel = panel_without_toolbar();
let surface = HeadlessSurface::new(W as u32, H as u32).expect("create surface");
let (dwrite, _, line_height) = DWrite::new("Segoe UI", 10.0, None).expect("create DWrite");
let rect = Rect::new(10.0, 5.0, W - 10.0, H - 5.0);
let layout = paint(&surface, &dwrite, line_height, rect, &panel, None, None);
assert!(layout.toolbar_bounds.is_none());
assert_eq!(layout.content_bounds, rect);
match layout.hit_test(rect.x + 3.0, rect.y + 4.0) {
SidebarPanelHit::Content { x, y } => {
assert!((x - 3.0).abs() < 0.01 && (y - 4.0).abs() < 0.01);
}
other => panic!("expected Content hit, got {other:?}"),
}
}
#[test]
fn no_paint_layout_matches_paint_layout() {
let panel = panel_with_toolbar();
let rect = Rect::new(0.0, 0.0, W, H);
let (dwrite, _, line_height) = DWrite::new("Segoe UI", 10.0, None).expect("create DWrite");
let surface = HeadlessSurface::new(W as u32, H as u32).expect("create surface");
let painted = paint(&surface, &dwrite, line_height, rect, &panel, None, None);
let no_paint = win_sidebar_panel_layout(&dwrite, line_height, rect, &panel);
assert_eq!(painted, no_paint);
}
}