pub mod form;
pub mod scroll_view;
pub mod scrollbar;
pub mod split_view;
pub mod stack_view;
pub use form::{MacForm, MacFormUi};
pub use scroll_view::{MacScrollView, MacScrollViewOutput};
pub use scrollbar::render_overlay_thumb;
pub use split_view::{MacSplitOrientation, MacSplitView};
pub use stack_view::{
MacStackAlignment, MacStackOrientation, MacStackUi, MacStackView, MacStackViewOutput,
};
use egui::{Pos2, Rect, Response, Sense, Ui, Vec2};
#[inline]
pub fn subpixel_snap(logical: f32, scale_factor: f32) -> f32 {
let s = scale_factor.max(f32::EPSILON);
(logical * s + 0.5).floor() / s
}
#[inline]
pub fn subpixel_snap_pos(pos: Pos2, scale_factor: f32) -> Pos2 {
Pos2::new(
subpixel_snap(pos.x, scale_factor),
subpixel_snap(pos.y, scale_factor),
)
}
#[inline]
pub fn subpixel_snap_rect(rect: Rect, scale_factor: f32) -> Rect {
let min = subpixel_snap_pos(rect.min, scale_factor);
let max = subpixel_snap_pos(rect.max, scale_factor);
Rect::from_min_max(min, max)
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct MacFrame {
pub origin: Pos2,
pub size: Vec2,
}
impl MacFrame {
pub fn new(x: f32, y: f32, w: f32, h: f32) -> Self {
Self {
origin: Pos2::new(x, y),
size: Vec2::new(w, h),
}
}
pub fn to_rect(&self) -> Rect {
Rect::from_min_size(self.origin, self.size)
}
}
pub struct MacFixedView<'a> {
pub ui: &'a mut Ui,
pub container_rect: Rect,
subview_count: usize,
}
impl<'a> MacFixedView<'a> {
pub fn new(ui: &'a mut Ui, container_rect: Rect) -> Self {
Self {
ui,
container_rect,
subview_count: 0,
}
}
pub fn subview_rect(&self, rel_origin: Pos2, size: Vec2) -> Rect {
Rect::from_min_size(
Pos2::new(
self.container_rect.left() + rel_origin.x,
self.container_rect.top() + rel_origin.y,
),
size,
)
}
pub fn subview<R>(
&mut self,
rel_origin: Pos2,
size: Vec2,
add_contents: impl FnOnce(&mut Ui) -> R,
) -> R {
let idx = self.subview_count;
self.subview_count += 1;
let rect = self.subview_rect(rel_origin, size);
let mut child = self.ui.new_child(
egui::UiBuilder::new()
.id_salt(("fixed_subview", idx))
.max_rect(rect),
);
child.set_clip_rect(rect.intersect(self.ui.clip_rect()));
add_contents(&mut child)
}
pub fn finish(self) -> Response {
self.ui.allocate_rect(self.container_rect, Sense::hover())
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct MacRow {
pub y_offset: f32,
pub height: f32,
pub cursor_x: f32,
pub item_spacing: f32,
pub container_width: f32,
}
impl MacRow {
pub fn new(y_offset: f32, height: f32, container_width: f32, item_spacing: f32) -> Self {
Self {
y_offset,
height,
cursor_x: 0.0,
item_spacing,
container_width,
}
}
pub fn allocate_cell(&mut self, width: f32) -> (f32, f32, f32, f32) {
let x = self.cursor_x;
let y = self.y_offset;
let h = self.height;
self.cursor_x += width + self.item_spacing;
(x, y, width, h)
}
pub fn remaining_width(&self) -> f32 {
(self.container_width - self.cursor_x).max(0.0)
}
}
pub fn is_window_active(ctx: &egui::Context) -> bool {
ctx.input(|i| {
i.focused
&& i.viewport().focused.unwrap_or(true)
&& !i.viewport().minimized.unwrap_or(false)
})
}