#[cfg(test)]
use core_text::font::CTFont;
use crate::primitives::layout_metrics::pixel_panel_layout;
use crate::primitives::panel::{Panel, PanelLayout};
#[cfg(test)]
use crate::theme::Theme;
pub fn mac_panel_layout(
panel: &Panel,
x: f64,
y: f64,
w: f64,
h: f64,
line_height: f64,
) -> PanelLayout {
pixel_panel_layout(
panel,
x as f32,
y as f32,
w as f32,
h as f32,
line_height as f32,
)
}
#[cfg(test)]
mod tests {
use super::super::headless::BitmapSurface;
use super::super::text::make_font;
use super::super::MacBackend;
use super::*;
use crate::event::{Rect as QRect, Viewport};
use crate::primitives::panel::{PanelAction, PanelHit};
use crate::types::{StyledText, WidgetId};
use crate::Backend;
const W: u32 = 240;
const H: u32 = 160;
fn font() -> CTFont {
make_font("Menlo", 14.0).expect("Menlo installed")
}
fn sample_panel() -> Panel {
Panel {
id: WidgetId::new("panel"),
title: Some(StyledText::plain("Terminal")),
actions: vec![
PanelAction {
id: WidgetId::new("panel:close"),
icon: "×".into(),
tooltip: "Close".into(),
is_active: false,
},
PanelAction {
id: WidgetId::new("panel:max"),
icon: "â–¡".into(),
tooltip: "Maximize".into(),
is_active: false,
},
],
accent: None,
collapsed: false,
}
}
fn paint_via_backend(panel: &Panel) -> (BitmapSurface, PanelLayout) {
let surface = BitmapSurface::new(W, H);
surface.fill(0.0, 0.0, 0.0, 0.0);
let mut backend = MacBackend::new();
backend.set_current_font(font());
backend.begin_frame(Viewport::new(W as f32, H as f32, 1.0));
let layout = std::cell::RefCell::new(None);
backend.enter_frame_scope(surface.context_ptr(), |b| {
let l = b.draw_panel(QRect::new(0.0, 0.0, W as f32, H as f32), panel);
*layout.borrow_mut() = Some(l);
});
backend.end_frame();
(surface, layout.into_inner().unwrap())
}
#[test]
fn title_bar_paints_separator_bg_by_default() {
let panel = sample_panel();
let (surface, layout) = paint_via_backend(&panel);
let theme = Theme::default();
let tb = layout.title_bar_bounds.expect("title bar present");
let px = (tb.x + tb.width / 2.0) as u32;
let py = (tb.y + tb.height - 1.0) as u32;
let (r, g, b, _) = surface.pixel(px, py);
assert_eq!(
(r, g, b),
(theme.separator.r, theme.separator.g, theme.separator.b),
);
}
#[test]
fn content_bounds_excludes_title_bar() {
let panel = sample_panel();
let (_surface, layout) = paint_via_backend(&panel);
let tb = layout.title_bar_bounds.expect("title bar present");
let cb = layout.content_bounds;
assert!(
cb.y >= tb.y + tb.height,
"content should start below title bar: tb.bottom={}, content.y={}",
tb.y + tb.height,
cb.y,
);
}
#[test]
fn action_buttons_right_aligned() {
let panel = sample_panel();
let (_surface, layout) = paint_via_backend(&panel);
assert_eq!(layout.visible_actions.len(), 2);
let first = &layout.visible_actions[0];
assert!(
(first.bounds.x
- (W as f32 - crate::primitives::layout_metrics::pixel::PANEL_ACTION_BUTTON))
.abs()
< 0.5
);
}
#[test]
fn hit_test_resolves_action_vs_title_vs_content() {
let panel = sample_panel();
let (_surface, layout) = paint_via_backend(&panel);
let first_action = &layout.visible_actions[0];
let hit = layout.hit_test(
first_action.bounds.x + first_action.bounds.width * 0.5,
first_action.bounds.y + first_action.bounds.height * 0.5,
);
assert!(matches!(hit, PanelHit::Action(_)));
let tb = layout.title_bar_bounds.unwrap();
let hit = layout.hit_test(tb.x + 10.0, tb.y + tb.height * 0.5);
assert!(matches!(hit, PanelHit::TitleBar(_)), "hit was {:?}", hit);
let cb = layout.content_bounds;
let hit = layout.hit_test(cb.x + cb.width * 0.5, cb.y + cb.height * 0.5);
assert!(matches!(hit, PanelHit::Content(_)));
}
#[test]
fn hit_test_resolves_action_vs_title_vs_content_at_nonzero_origin() {
let panel = sample_panel();
let layout = mac_panel_layout(&panel, 7.0, 13.0, W as f64, H as f64, 16.0);
let first_action = &layout.visible_actions[0];
let hit = layout.hit_test(
first_action.bounds.x + first_action.bounds.width * 0.5,
first_action.bounds.y + first_action.bounds.height * 0.5,
);
assert!(matches!(hit, PanelHit::Action(_)));
let tb = layout.title_bar_bounds.unwrap();
let hit = layout.hit_test(tb.x + 10.0, tb.y + tb.height * 0.5);
assert!(matches!(hit, PanelHit::TitleBar(_)), "hit was {:?}", hit);
let cb = layout.content_bounds;
let hit = layout.hit_test(cb.x + cb.width * 0.5, cb.y + cb.height * 0.5);
assert!(matches!(hit, PanelHit::Content(_)));
}
#[test]
fn collapsed_panel_zero_content_height() {
let mut panel = sample_panel();
panel.collapsed = true;
let (_surface, layout) = paint_via_backend(&panel);
assert_eq!(layout.content_bounds.height, 0.0);
}
}