diff --git a/egui/src/align.rs b/egui/src/align.rs index e4540055..a0834d6d 100644 --- a/egui/src/align.rs +++ b/egui/src/align.rs @@ -50,50 +50,66 @@ impl Default for Align { } } -pub type Align2 = (Align, Align); +// ---------------------------------------------------------------------------- -pub const LEFT_BOTTOM: Align2 = (Align::Min, Align::Max); -pub const LEFT_CENTER: Align2 = (Align::Min, Align::Center); -pub const LEFT_TOP: Align2 = (Align::Min, Align::Min); -pub const CENTER_BOTTOM: Align2 = (Align::Center, Align::Max); -pub const CENTER_CENTER: Align2 = (Align::Center, Align::Center); -pub const CENTER_TOP: Align2 = (Align::Center, Align::Min); -pub const RIGHT_BOTTOM: Align2 = (Align::Max, Align::Max); -pub const RIGHT_CENTER: Align2 = (Align::Max, Align::Center); -pub const RIGHT_TOP: Align2 = (Align::Max, Align::Min); +#[derive(Clone, Copy, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))] +pub struct Align2(pub [Align; 2]); -/// Used e.g. to anchor a piece of text to a part of the rectangle. -/// Give a position within the rect, specified by the aligns -pub(crate) fn anchor_rect(rect: Rect, anchor: (Align, Align)) -> Rect { - let x = match anchor.0 { - Align::Min => rect.left(), - Align::Center => rect.left() - 0.5 * rect.width(), - Align::Max => rect.left() - rect.width(), - }; - let y = match anchor.1 { - Align::Min => rect.top(), - Align::Center => rect.top() - 0.5 * rect.height(), - Align::Max => rect.top() - rect.height(), - }; - Rect::from_min_size(pos2(x, y), rect.size()) +impl Align2 { + pub const LEFT_BOTTOM: Align2 = Align2([Align::Min, Align::Max]); + pub const LEFT_CENTER: Align2 = Align2([Align::Min, Align::Center]); + pub const LEFT_TOP: Align2 = Align2([Align::Min, Align::Min]); + pub const CENTER_BOTTOM: Align2 = Align2([Align::Center, Align::Max]); + pub const CENTER_CENTER: Align2 = Align2([Align::Center, Align::Center]); + pub const CENTER_TOP: Align2 = Align2([Align::Center, Align::Min]); + pub const RIGHT_BOTTOM: Align2 = Align2([Align::Max, Align::Max]); + pub const RIGHT_CENTER: Align2 = Align2([Align::Max, Align::Center]); + pub const RIGHT_TOP: Align2 = Align2([Align::Max, Align::Min]); } -/// e.g. center a size within a given frame -pub fn align_size_within_rect(align: (Align, Align), size: Vec2, frame: Rect) -> Rect { - let x = match align.0 { - Align::Min => frame.left(), - Align::Center => frame.center().x - size.x / 2.0, - Align::Max => frame.right() - size.x, - }; - let y = match align.1 { - Align::Min => frame.top(), - Align::Center => frame.center().y - size.y / 2.0, - Align::Max => frame.bottom() - size.y, - }; +impl Align2 { + pub fn x(self) -> Align { + self.0[0] + } + pub fn y(self) -> Align { + self.0[1] + } - Rect::from_min_size(Pos2::new(x, y), size) + /// Used e.g. to anchor a piece of text to a part of the rectangle. + /// Give a position within the rect, specified by the aligns + pub(crate) fn anchor_rect(self, rect: Rect) -> Rect { + let x = match self.x() { + Align::Min => rect.left(), + Align::Center => rect.left() - 0.5 * rect.width(), + Align::Max => rect.left() - rect.width(), + }; + let y = match self.y() { + Align::Min => rect.top(), + Align::Center => rect.top() - 0.5 * rect.height(), + Align::Max => rect.top() - rect.height(), + }; + Rect::from_min_size(pos2(x, y), rect.size()) + } + + /// e.g. center a size within a given frame + pub fn align_size_within_rect(self, size: Vec2, frame: Rect) -> Rect { + let x = match self.x() { + Align::Min => frame.left(), + Align::Center => frame.center().x - size.x / 2.0, + Align::Max => frame.right() - size.x, + }; + let y = match self.y() { + Align::Min => frame.top(), + Align::Center => frame.center().y - size.y / 2.0, + Align::Max => frame.bottom() - size.y, + }; + + Rect::from_min_size(Pos2::new(x, y), size) + } } pub fn center_size_in_rect(size: Vec2, frame: Rect) -> Rect { - align_size_within_rect(CENTER_CENTER, size, frame) + Align2::CENTER_CENTER.align_size_within_rect(size, frame) } diff --git a/egui/src/layout.rs b/egui/src/layout.rs index f2c64cdf..59088366 100644 --- a/egui/src/layout.rs +++ b/egui/src/layout.rs @@ -496,6 +496,7 @@ impl Layout { impl Layout { /// Shows where the next widget is going to be placed pub(crate) fn debug_paint_cursor(&self, region: &Region, painter: &crate::Painter) { + use crate::align::Align2; use crate::paint::*; let cursor = region.cursor; @@ -510,19 +511,19 @@ impl Layout { match self.main_dir { Direction::LeftToRight => { painter.arrow(cursor, vec2(l, 0.0), stroke); - align = (Align::Min, Align::Min); + align = Align2::LEFT_TOP; } Direction::RightToLeft => { painter.arrow(cursor, vec2(-l, 0.0), stroke); - align = (Align::Max, Align::Min); + align = Align2::RIGHT_TOP; } Direction::TopDown => { painter.arrow(cursor, vec2(0.0, l), stroke); - align = (Align::Min, Align::Min); + align = Align2::LEFT_TOP; } Direction::BottomUp => { painter.arrow(cursor, vec2(0.0, -l), stroke); - align = (Align::Min, Align::Max); + align = Align2::LEFT_BOTTOM; } } diff --git a/egui/src/paint/command.rs b/egui/src/paint/command.rs index e702b587..72120e1f 100644 --- a/egui/src/paint/command.rs +++ b/egui/src/paint/command.rs @@ -1,7 +1,7 @@ use { super::{fonts::TextStyle, Color32, Fonts, Galley, Triangles}, crate::{ - align::{anchor_rect, Align}, + align::Align2, math::{Pos2, Rect}, *, }, @@ -127,14 +127,14 @@ impl PaintCmd { pub fn text( fonts: &Fonts, pos: Pos2, - anchor: (Align, Align), + anchor: Align2, text: impl Into, text_style: TextStyle, color: Color32, ) -> Self { let font = &fonts[text_style]; let galley = font.layout_multiline(text.into(), f32::INFINITY); - let rect = anchor_rect(Rect::from_min_size(pos, galley.size), anchor); + let rect = anchor.anchor_rect(Rect::from_min_size(pos, galley.size)); Self::Text { pos: rect.min, galley, diff --git a/egui/src/painter.rs b/egui/src/painter.rs index 857a35df..8a3849c0 100644 --- a/egui/src/painter.rs +++ b/egui/src/painter.rs @@ -1,5 +1,5 @@ use crate::{ - align::{anchor_rect, Align, LEFT_TOP}, + align::Align2, layers::PaintCmdIdx, math::{Pos2, Rect, Vec2}, paint::{Fonts, Galley, PaintCmd, Stroke, TextStyle}, @@ -135,14 +135,14 @@ impl Painter { pub fn debug_rect(&mut self, rect: Rect, color: Color32, text: impl Into) { self.rect_stroke(rect, 0.0, (1.0, color)); let text_style = TextStyle::Monospace; - self.text(rect.min, LEFT_TOP, text.into(), text_style, color); + self.text(rect.min, Align2::LEFT_TOP, text.into(), text_style, color); } pub fn error(&self, pos: Pos2, text: impl std::fmt::Display) -> Rect { let text_style = TextStyle::Monospace; let font = &self.fonts()[text_style]; let galley = font.layout_multiline(format!("🔥 {}", text), f32::INFINITY); - let rect = anchor_rect(Rect::from_min_size(pos, galley.size), LEFT_TOP); + let rect = Align2::LEFT_TOP.anchor_rect(Rect::from_min_size(pos, galley.size)); let frame_rect = rect.expand(2.0); self.add(PaintCmd::Rect { rect: frame_rect, @@ -253,14 +253,14 @@ impl Painter { pub fn text( &self, pos: Pos2, - anchor: (Align, Align), + anchor: Align2, text: impl Into, text_style: TextStyle, text_color: Color32, ) -> Rect { let font = &self.fonts()[text_style]; let galley = font.layout_multiline(text.into(), f32::INFINITY); - let rect = anchor_rect(Rect::from_min_size(pos, galley.size), anchor); + let rect = anchor.anchor_rect(Rect::from_min_size(pos, galley.size)); self.galley(rect.min, galley, text_style, text_color); rect } diff --git a/egui_demo_lib/src/frame_history.rs b/egui_demo_lib/src/frame_history.rs index 2214358d..3b2a24b0 100644 --- a/egui_demo_lib/src/frame_history.rs +++ b/egui_demo_lib/src/frame_history.rs @@ -91,7 +91,7 @@ impl FrameHistory { cmds.push(PaintCmd::text( ui.fonts(), pos2(rect.left(), y), - align::LEFT_BOTTOM, + egui::align::Align2::LEFT_BOTTOM, text, TextStyle::Monospace, Color32::WHITE,