Add helper struct Align2

This commit is contained in:
Emil Ernerfeldt 2021-01-10 10:51:16 +01:00
parent 1b3a5e5b50
commit 72ed94fcb3
5 changed files with 68 additions and 51 deletions

View file

@ -50,50 +50,66 @@ impl Default for Align {
} }
} }
pub type Align2 = (Align, Align); // ----------------------------------------------------------------------------
pub const LEFT_BOTTOM: Align2 = (Align::Min, Align::Max); #[derive(Clone, Copy, Debug, PartialEq)]
pub const LEFT_CENTER: Align2 = (Align::Min, Align::Center); #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub const LEFT_TOP: Align2 = (Align::Min, Align::Min); #[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
pub const CENTER_BOTTOM: Align2 = (Align::Center, Align::Max); pub struct Align2(pub [Align; 2]);
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);
/// Used e.g. to anchor a piece of text to a part of the rectangle. impl Align2 {
/// Give a position within the rect, specified by the aligns pub const LEFT_BOTTOM: Align2 = Align2([Align::Min, Align::Max]);
pub(crate) fn anchor_rect(rect: Rect, anchor: (Align, Align)) -> Rect { pub const LEFT_CENTER: Align2 = Align2([Align::Min, Align::Center]);
let x = match anchor.0 { 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]);
}
impl Align2 {
pub fn x(self) -> Align {
self.0[0]
}
pub fn y(self) -> Align {
self.0[1]
}
/// 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::Min => rect.left(),
Align::Center => rect.left() - 0.5 * rect.width(), Align::Center => rect.left() - 0.5 * rect.width(),
Align::Max => rect.left() - rect.width(), Align::Max => rect.left() - rect.width(),
}; };
let y = match anchor.1 { let y = match self.y() {
Align::Min => rect.top(), Align::Min => rect.top(),
Align::Center => rect.top() - 0.5 * rect.height(), Align::Center => rect.top() - 0.5 * rect.height(),
Align::Max => rect.top() - rect.height(), Align::Max => rect.top() - rect.height(),
}; };
Rect::from_min_size(pos2(x, y), rect.size()) Rect::from_min_size(pos2(x, y), rect.size())
} }
/// e.g. center a size within a given frame /// e.g. center a size within a given frame
pub fn align_size_within_rect(align: (Align, Align), size: Vec2, frame: Rect) -> Rect { pub fn align_size_within_rect(self, size: Vec2, frame: Rect) -> Rect {
let x = match align.0 { let x = match self.x() {
Align::Min => frame.left(), Align::Min => frame.left(),
Align::Center => frame.center().x - size.x / 2.0, Align::Center => frame.center().x - size.x / 2.0,
Align::Max => frame.right() - size.x, Align::Max => frame.right() - size.x,
}; };
let y = match align.1 { let y = match self.y() {
Align::Min => frame.top(), Align::Min => frame.top(),
Align::Center => frame.center().y - size.y / 2.0, Align::Center => frame.center().y - size.y / 2.0,
Align::Max => frame.bottom() - size.y, Align::Max => frame.bottom() - size.y,
}; };
Rect::from_min_size(Pos2::new(x, y), size) Rect::from_min_size(Pos2::new(x, y), size)
}
} }
pub fn center_size_in_rect(size: Vec2, frame: Rect) -> Rect { 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)
} }

View file

@ -496,6 +496,7 @@ impl Layout {
impl Layout { impl Layout {
/// Shows where the next widget is going to be placed /// Shows where the next widget is going to be placed
pub(crate) fn debug_paint_cursor(&self, region: &Region, painter: &crate::Painter) { pub(crate) fn debug_paint_cursor(&self, region: &Region, painter: &crate::Painter) {
use crate::align::Align2;
use crate::paint::*; use crate::paint::*;
let cursor = region.cursor; let cursor = region.cursor;
@ -510,19 +511,19 @@ impl Layout {
match self.main_dir { match self.main_dir {
Direction::LeftToRight => { Direction::LeftToRight => {
painter.arrow(cursor, vec2(l, 0.0), stroke); painter.arrow(cursor, vec2(l, 0.0), stroke);
align = (Align::Min, Align::Min); align = Align2::LEFT_TOP;
} }
Direction::RightToLeft => { Direction::RightToLeft => {
painter.arrow(cursor, vec2(-l, 0.0), stroke); painter.arrow(cursor, vec2(-l, 0.0), stroke);
align = (Align::Max, Align::Min); align = Align2::RIGHT_TOP;
} }
Direction::TopDown => { Direction::TopDown => {
painter.arrow(cursor, vec2(0.0, l), stroke); painter.arrow(cursor, vec2(0.0, l), stroke);
align = (Align::Min, Align::Min); align = Align2::LEFT_TOP;
} }
Direction::BottomUp => { Direction::BottomUp => {
painter.arrow(cursor, vec2(0.0, -l), stroke); painter.arrow(cursor, vec2(0.0, -l), stroke);
align = (Align::Min, Align::Max); align = Align2::LEFT_BOTTOM;
} }
} }

View file

@ -1,7 +1,7 @@
use { use {
super::{fonts::TextStyle, Color32, Fonts, Galley, Triangles}, super::{fonts::TextStyle, Color32, Fonts, Galley, Triangles},
crate::{ crate::{
align::{anchor_rect, Align}, align::Align2,
math::{Pos2, Rect}, math::{Pos2, Rect},
*, *,
}, },
@ -127,14 +127,14 @@ impl PaintCmd {
pub fn text( pub fn text(
fonts: &Fonts, fonts: &Fonts,
pos: Pos2, pos: Pos2,
anchor: (Align, Align), anchor: Align2,
text: impl Into<String>, text: impl Into<String>,
text_style: TextStyle, text_style: TextStyle,
color: Color32, color: Color32,
) -> Self { ) -> Self {
let font = &fonts[text_style]; let font = &fonts[text_style];
let galley = font.layout_multiline(text.into(), f32::INFINITY); 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 { Self::Text {
pos: rect.min, pos: rect.min,
galley, galley,

View file

@ -1,5 +1,5 @@
use crate::{ use crate::{
align::{anchor_rect, Align, LEFT_TOP}, align::Align2,
layers::PaintCmdIdx, layers::PaintCmdIdx,
math::{Pos2, Rect, Vec2}, math::{Pos2, Rect, Vec2},
paint::{Fonts, Galley, PaintCmd, Stroke, TextStyle}, 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<String>) { pub fn debug_rect(&mut self, rect: Rect, color: Color32, text: impl Into<String>) {
self.rect_stroke(rect, 0.0, (1.0, color)); self.rect_stroke(rect, 0.0, (1.0, color));
let text_style = TextStyle::Monospace; 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 { pub fn error(&self, pos: Pos2, text: impl std::fmt::Display) -> Rect {
let text_style = TextStyle::Monospace; let text_style = TextStyle::Monospace;
let font = &self.fonts()[text_style]; let font = &self.fonts()[text_style];
let galley = font.layout_multiline(format!("🔥 {}", text), f32::INFINITY); 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); let frame_rect = rect.expand(2.0);
self.add(PaintCmd::Rect { self.add(PaintCmd::Rect {
rect: frame_rect, rect: frame_rect,
@ -253,14 +253,14 @@ impl Painter {
pub fn text( pub fn text(
&self, &self,
pos: Pos2, pos: Pos2,
anchor: (Align, Align), anchor: Align2,
text: impl Into<String>, text: impl Into<String>,
text_style: TextStyle, text_style: TextStyle,
text_color: Color32, text_color: Color32,
) -> Rect { ) -> Rect {
let font = &self.fonts()[text_style]; let font = &self.fonts()[text_style];
let galley = font.layout_multiline(text.into(), f32::INFINITY); 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); self.galley(rect.min, galley, text_style, text_color);
rect rect
} }

View file

@ -91,7 +91,7 @@ impl FrameHistory {
cmds.push(PaintCmd::text( cmds.push(PaintCmd::text(
ui.fonts(), ui.fonts(),
pos2(rect.left(), y), pos2(rect.left(), y),
align::LEFT_BOTTOM, egui::align::Align2::LEFT_BOTTOM,
text, text,
TextStyle::Monospace, TextStyle::Monospace,
Color32::WHITE, Color32::WHITE,