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);
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)
}

View file

@ -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;
}
}

View file

@ -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<String>,
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,

View file

@ -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<String>) {
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<String>,
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
}

View file

@ -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,