pub mod popup_item_list;
pub mod segmented_control;
pub mod source_list;
pub mod stepper;
pub mod toolbar;
pub mod value_spinbox;
pub mod window_chrome;
pub use popup_item_list::{PopupAnchor, PopupItem, PopupItemList};
pub use segmented_control::{MacSegment, MacSegmentedControl};
pub use source_list::{MacSourceList, SourceListRow, SourceListSection};
pub use stepper::MacStepper;
pub use toolbar::{MacToolbar, MacToolbarItem, ToolbarItemDisplayMode, ToolbarItemKind};
pub use value_spinbox::ValueSpinBox;
pub use window_chrome::{MacWindowChrome, WindowChromeButton};
mod shared;
pub(crate) use shared::{centred_band, centred_size, draw_focus_ring, palette};
pub use shared::{
mac_stepper_height, MAC_SEGMENTED_CONTROL_HEIGHT, MAC_SEGMENTED_DEFAULT_WIDTH,
MAC_SEGMENT_LABEL_INSET, MAC_SOURCE_LIST_DEFAULT_HEIGHT, MAC_SOURCE_LIST_DEFAULT_WIDTH,
MAC_SOURCE_LIST_ROW_HEIGHT, MAC_SOURCE_LIST_SECTION_HEIGHT, MAC_STEPPER_WIDTH,
MAC_TITLE_BAR_HEIGHT, MAC_TOOLBAR_DEFAULT_WIDTH, MAC_TOOLBAR_HEIGHT, MAC_TOOLBAR_INSET,
MAC_TOOLBAR_ITEM_PADDING, MAC_TRAFFIC_LIGHT_GAP, MAC_TRAFFIC_LIGHT_INSET,
};
#[cfg(test)]
pub(crate) mod test_support {
use crate::core::{Color, Font, Size};
use crate::render::{
PaintBackend, RenderCommand, ShapedText, SoftwarePaintBackend, SoftwareRenderConfig,
TextMetrics,
};
pub(crate) struct Recorder {
pub(crate) commands: Vec<RenderCommand>,
inner: SoftwarePaintBackend,
}
impl Recorder {
pub(crate) fn new(width: u32, height: u32) -> Self {
Self {
commands: Vec::new(),
inner: SoftwarePaintBackend::new(Size::new(width, height), 1.0),
}
}
pub(crate) fn begin_frame(&mut self, clear: Color) {
self.inner.begin_frame(clear);
}
pub(crate) fn end_frame(&mut self) {
self.inner.end_frame();
}
}
impl PaintBackend for Recorder {
fn begin_frame(&mut self, clear: Color) {
self.inner.begin_frame(clear);
}
fn end_frame(&mut self) {
self.inner.end_frame();
}
fn execute_command(&mut self, command: &RenderCommand) {
self.commands.push(command.clone());
self.inner.execute_command(command);
}
fn size(&self) -> Size {
self.inner.size()
}
fn set_size(&mut self, size: Size) {
self.inner.set_size(size);
}
fn dpi_scale(&self) -> f32 {
self.inner.dpi_scale()
}
fn set_dpi_scale(&mut self, scale: f32) {
self.inner.set_dpi_scale(scale);
}
fn measure_text(&self, text: &str, font: &Font) -> TextMetrics {
self.inner.measure_text(text, font)
}
fn shape_text(&self, text: &str, font: &Font) -> crate::compat::Rc<ShapedText> {
self.inner.shape_text(text, font)
}
fn frame_rgba(&self) -> &[u8] {
self.inner.frame_rgba()
}
fn apply_render_config(&mut self, config: SoftwareRenderConfig) {
self.inner.apply_render_config(config);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::core::Rect;
#[cfg(full_widgets)]
#[test]
fn every_control_paints_visibly_and_follows_the_theme() {
const NAMES: [&str; 5] = [
"mac_segmented_control",
"mac_source_list",
"mac_stepper",
"mac_toolbar",
"mac_window_chrome",
];
let _guard = crate::theme::theme_test_guard();
crate::widget::census::install_preset_appearances();
let rows = crate::widget::census::census_all_controls();
for name in NAMES {
let row = rows
.iter()
.find(|row| row.name == name)
.unwrap_or_else(|| panic!("{name} is not in the rendering census"));
assert!(row.light.non_background > 0, "{name} painted nothing at the census geometry");
assert!(
row.visible_against_its_surface(),
"{name} paints in the colour of the surface it sits on"
);
assert!(
row.differs_between_appearances(),
"{name} renders identically in light and dark, so its chrome is hardcoded"
);
}
}
#[test]
fn the_centred_band_stays_inside_its_rectangle() {
let rect = Rect::new(10, 20, 240, 120);
let band = centred_band(rect, MAC_SEGMENTED_CONTROL_HEIGHT);
assert_eq!(band.width, rect.width);
assert_eq!(band.height, MAC_SEGMENTED_CONTROL_HEIGHT);
assert!(band.y >= rect.y);
assert!(band.bottom() <= rect.bottom());
}
#[test]
fn a_band_taller_than_its_rectangle_is_clamped() {
let rect = Rect::new(0, 0, 100, 10);
let band = centred_band(rect, MAC_TOOLBAR_HEIGHT);
assert_eq!(band.height, 10);
assert_eq!(band.y, 0);
}
#[test]
fn a_fixed_size_control_is_clamped_and_centred() {
let rect = Rect::new(0, 0, 240, 120);
let stepper = centred_size(rect, MAC_STEPPER_WIDTH, mac_stepper_height());
assert_eq!(stepper.width, MAC_STEPPER_WIDTH);
assert_eq!(stepper.height, mac_stepper_height());
assert_eq!(stepper.x, (240 - MAC_STEPPER_WIDTH as i32) / 2);
let narrow = centred_size(Rect::new(0, 0, 10, 10), MAC_STEPPER_WIDTH, mac_stepper_height());
assert_eq!(narrow.width, 10);
assert_eq!(narrow.height, 10);
}
}