use gtk4::cairo::Context;
use gtk4::pango;
use crate::primitives::status_bar::{StatusBar, StatusBarLayout};
use crate::theme::Theme;
use crate::types::WidgetId;
#[allow(clippy::too_many_arguments)]
pub fn draw_status_bar(
cr: &Context,
pango_layout: &pango::Layout,
x: f64,
y: f64,
width: f64,
line_height: f64,
bar: &StatusBar,
theme: &Theme,
hovered_id: Option<&WidgetId>,
pressed_id: Option<&WidgetId>,
) -> StatusBarLayout {
let mut surface = super::surface::CairoSurface {
cr,
layout: Some(pango_layout),
translucent_fill: true,
};
crate::primitives::status_bar::native_surface_paint::paint(
bar,
&mut surface,
theme,
x as f32,
y as f32,
width as f32,
line_height as f32,
hovered_id,
pressed_id,
)
}
pub const MIN_GAP_PX: f32 = 16.0;
#[cfg(test)]
mod tests {
use super::*;
use crate::primitives::status_bar::{StatusBarHit, StatusBarSegment};
use crate::types::Color;
use pangocairo::cairo::{Context as CairoContext, Format, ImageSurface};
fn headless_cairo_and_pango() -> (ImageSurface, pango::Layout) {
let surface = ImageSurface::create(Format::ARgb32, 200, 200).expect("create ImageSurface");
let cr = CairoContext::new(&surface).expect("Context::new");
let layout = pangocairo::functions::create_layout(&cr);
(surface, layout)
}
fn test_bar() -> StatusBar {
StatusBar {
id: WidgetId::new("sb"),
left_segments: vec![StatusBarSegment {
text: "Ready".into(),
fg: Color::rgb(255, 255, 255),
bg: Color::rgb(0, 0, 0),
bold: false,
action_id: Some(WidgetId::new("sb:action")),
}],
right_segments: vec![],
}
}
fn round_trip_at(x: f64, y: f64) {
let (surface, pango_layout) = headless_cairo_and_pango();
let cr = CairoContext::new(&surface).expect("Context::new");
let theme = Theme::default();
let bar = test_bar();
let mut raw = crate::gtk::surface::CairoSurface {
cr: &cr,
layout: Some(&pango_layout),
translucent_fill: true,
};
let at_origin = crate::primitives::status_bar::native_surface_paint::paint(
&bar, &mut raw, &theme, 0.0, 0.0, 100.0, 20.0, None, None,
);
let mut raw = crate::gtk::surface::CairoSurface {
cr: &cr,
layout: Some(&pango_layout),
translucent_fill: true,
};
let shifted = crate::primitives::status_bar::native_surface_paint::paint(
&bar, &mut raw, &theme, x as f32, y as f32, 100.0, 20.0, None, None,
);
assert_eq!(
at_origin, shifted,
"LOCAL status_bar_layout must not shift segment bounds by x/y"
);
let seg = shifted.visible_segments[0];
let cx = seg.bounds.x + 1.0;
let cy = seg.bounds.y + 1.0;
assert_eq!(
shifted.hit_test(cx, cy),
StatusBarHit::Segment(bar.left_segments[0].action_id.clone().unwrap())
);
}
#[test]
fn paint_and_click_round_trip() {
round_trip_at(0.0, 0.0);
}
#[test]
fn paint_and_click_round_trip_at_nonzero_origin() {
round_trip_at(7.0, 13.0);
}
}