use crate::event::Rect as QRect;
use crate::primitives::layout_metrics::pixel_split_layout;
use crate::primitives::split::{Split, SplitLayout};
#[cfg(test)]
use crate::theme::Theme;
pub fn mac_split_layout(split: &Split, x: f64, y: f64, w: f64, h: f64) -> SplitLayout {
let bounds = QRect::new(x as f32, y as f32, w as f32, h as f32);
pixel_split_layout(split, bounds)
}
#[cfg(test)]
mod tests {
use super::super::headless::BitmapSurface;
use super::super::text::make_font;
use super::super::MacBackend;
use super::*;
use crate::event::Viewport;
use crate::primitives::split::{SplitDirection, SplitHit};
use crate::types::WidgetId;
use crate::Backend;
const W: u32 = 200;
const H: u32 = 120;
fn sample_split(direction: SplitDirection) -> Split {
Split {
id: WidgetId::new("split"),
direction,
ratio: 0.5,
first_min: 0.0,
second_min: 0.0,
}
}
fn paint_via_backend(split: &Split) -> (BitmapSurface, SplitLayout) {
let surface = BitmapSurface::new(W, H);
surface.fill(1.0, 1.0, 1.0, 1.0);
let mut backend = MacBackend::new();
backend.set_current_font(make_font("Menlo", 14.0).expect("Menlo installed"));
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_split(QRect::new(0.0, 0.0, W as f32, H as f32), split);
*layout.borrow_mut() = Some(l);
});
backend.end_frame();
(surface, layout.into_inner().unwrap())
}
#[test]
fn horizontal_divider_paints_separator() {
let split = sample_split(SplitDirection::Horizontal);
let (surface, layout) = paint_via_backend(&split);
let theme = Theme::default();
let d = layout.divider_bounds;
let px = (d.x + d.width / 2.0) as u32;
let py = (d.y + d.height / 2.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 vertical_divider_paints_separator() {
let split = sample_split(SplitDirection::Vertical);
let (surface, layout) = paint_via_backend(&split);
let theme = Theme::default();
let d = layout.divider_bounds;
let px = (d.x + d.width / 2.0) as u32;
let py = (d.y + d.height / 2.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 pane_areas_left_unpainted_outside_divider() {
let split = sample_split(SplitDirection::Horizontal);
let (surface, _layout) = paint_via_backend(&split);
let (r, g, b, _) = surface.pixel(10, H / 2);
assert_eq!((r, g, b), (255, 255, 255), "left pane should be unpainted");
}
fn hit_test_resolves_divider_and_panes_at(origin_x: f64, origin_y: f64) {
let split = sample_split(SplitDirection::Horizontal);
let layout = mac_split_layout(&split, origin_x, origin_y, W as f64, H as f64);
let d = layout.divider_bounds;
let hit = layout.hit_test(d.x + d.width / 2.0, d.y + d.height / 2.0);
assert!(
matches!(hit, SplitHit::Divider(_)),
"divider hit was {:?}",
hit
);
let hit = layout.hit_test(origin_x as f32 + 10.0, origin_y as f32 + 10.0);
assert!(
matches!(hit, SplitHit::FirstPane(_)),
"first pane hit was {:?}",
hit
);
let hit = layout.hit_test(origin_x as f32 + W as f32 - 10.0, origin_y as f32 + 10.0);
assert!(
matches!(hit, SplitHit::SecondPane(_)),
"second pane hit was {:?}",
hit
);
}
#[test]
fn hit_test_resolves_divider_and_panes() {
hit_test_resolves_divider_and_panes_at(0.0, 0.0);
}
#[test]
fn hit_test_resolves_divider_and_panes_at_nonzero_origin() {
hit_test_resolves_divider_and_panes_at(7.0, 13.0);
}
#[test]
fn min_size_clamps_ratio() {
let split = Split {
id: WidgetId::new("split"),
direction: SplitDirection::Horizontal,
ratio: 0.1,
first_min: (W as f32) * 0.4,
second_min: 0.0,
};
let (_surface, layout) = paint_via_backend(&split);
assert!(
layout.resolved_ratio > 0.3,
"resolved_ratio {} should be clamped above 0.3 to honour first_min",
layout.resolved_ratio,
);
}
}