use super::should_not_use;
use super::Alignment;
use super::ControlLayout;
use super::Coordinate16;
use super::Dimension16;
use super::Dock;
use super::Error;
use super::Layout;
use super::Pivot;
#[derive(Copy, Clone, PartialEq, Debug)]
pub(super) struct PointAndSizeLayout {
pub x: Coordinate16,
pub y: Coordinate16,
pub width: Dimension16,
pub height: Dimension16,
pub align: Alignment,
pub anchor: Alignment,
}
impl PointAndSizeLayout {
#[inline]
pub(super) fn new_docked(params: &Layout) -> Result<Self, Error> {
should_not_use!(params.x, Error::XYParameterUsedWithDock);
should_not_use!(params.y, Error::XYParameterUsedWithDock);
should_not_use!(params.a_top, Error::AnchorParameterUsedWithDock);
should_not_use!(params.a_bottom, Error::AnchorParameterUsedWithDock);
should_not_use!(params.a_left, Error::AnchorParameterUsedWithDock);
should_not_use!(params.a_right, Error::AnchorParameterUsedWithDock);
should_not_use!(params.pivot, Error::PivotParameterUsedWithDock);
should_not_use!(params.align, Error::AlignParameterUsedWithDock);
match params.dock.unwrap() {
Dock::Left => {
should_not_use!(params.height, Error::HeightParameterUsedWithLeftOrRightDock);
Ok(PointAndSizeLayout {
x: Coordinate16::Absolute(0),
y: Coordinate16::Absolute(0),
width: params.width.unwrap_or(Dimension16::Absolute(0)),
height: Dimension16::Percentage(10000),
align: Alignment::TopLeft,
anchor: Alignment::TopLeft,
})
}
Dock::Right => {
should_not_use!(params.height, Error::HeightParameterUsedWithLeftOrRightDock);
Ok(PointAndSizeLayout {
x: Coordinate16::Absolute(0),
y: Coordinate16::Absolute(0),
width: params.width.unwrap_or(Dimension16::Absolute(0)),
height: Dimension16::Percentage(10000),
align: Alignment::TopRight,
anchor: Alignment::TopRight,
})
}
Dock::Top => {
should_not_use!(params.width, Error::WidthParameterUsedWithTopOrBottomDock);
Ok(PointAndSizeLayout {
x: Coordinate16::Absolute(0),
y: Coordinate16::Absolute(0),
width: Dimension16::Percentage(10000),
height: params.height.unwrap_or(Dimension16::Absolute(0)),
align: Alignment::TopLeft,
anchor: Alignment::TopLeft,
})
}
Dock::Bottom => {
should_not_use!(params.width, Error::WidthParameterUsedWithTopOrBottomDock);
Ok(PointAndSizeLayout {
x: Coordinate16::Absolute(0),
y: Coordinate16::Absolute(0),
width: Dimension16::Percentage(10000),
height: params.height.unwrap_or(Dimension16::Absolute(0)),
align: Alignment::BottomLeft,
anchor: Alignment::BottomLeft,
})
}
Dock::Fill => {
should_not_use!(params.width, Error::WidthOrHeightParameterUsedWithDockFill);
should_not_use!(params.height, Error::WidthOrHeightParameterUsedWithDockFill);
Ok(PointAndSizeLayout {
x: Coordinate16::Absolute(0),
y: Coordinate16::Absolute(0),
width: Dimension16::Percentage(10000),
height: Dimension16::Percentage(10000),
align: Alignment::TopLeft,
anchor: Alignment::TopLeft,
})
}
}
}
pub(super) fn new_aligned(params: &Layout) -> Result<Self, Error> {
should_not_use!(params.x, Error::XYParameterUsedWithAlign);
should_not_use!(params.y, Error::XYParameterUsedWithAlign);
should_not_use!(params.a_top, Error::AnchorParameterUsedWithAlign);
should_not_use!(params.a_bottom, Error::AnchorParameterUsedWithAlign);
should_not_use!(params.a_left, Error::AnchorParameterUsedWithAlign);
should_not_use!(params.a_right, Error::AnchorParameterUsedWithAlign);
should_not_use!(params.dock, Error::DockParameterUsedWithAlign);
should_not_use!(params.pivot, Error::PivotParameterUsedWithAlign);
Ok(PointAndSizeLayout {
x: Coordinate16::Absolute(0),
y: Coordinate16::Absolute(0),
width: params.width.unwrap_or(Dimension16::Absolute(0)),
height: params.height.unwrap_or(Dimension16::Absolute(0)),
align: params.align.unwrap(),
anchor: params.align.unwrap(),
})
}
#[inline]
pub(super) fn new_xy(params: &Layout) -> Result<Self, Error> {
should_not_use!(params.a_left, Error::AnchorParameterUsedWithXY);
should_not_use!(params.a_right, Error::AnchorParameterUsedWithXY);
should_not_use!(params.a_top, Error::AnchorParameterUsedWithXY);
should_not_use!(params.a_bottom, Error::AnchorParameterUsedWithXY);
let a = match params.pivot.unwrap_or(Pivot::TopLeft) {
Pivot::TopLeft => Alignment::TopLeft,
Pivot::TopCenter => Alignment::TopCenter,
Pivot::TopRight => Alignment::TopRight,
Pivot::CenterRight => Alignment::CenterRight,
Pivot::BottomRight => Alignment::BottomRight,
Pivot::BottomCenter => Alignment::BottomCenter,
Pivot::BottomLeft => Alignment::BottomLeft,
Pivot::CenterLeft => Alignment::CenterLeft,
Pivot::Center => Alignment::Center,
};
Ok(PointAndSizeLayout {
x: params.x.unwrap(),
y: params.y.unwrap(),
width: params.width.unwrap_or(Dimension16::Absolute(1)),
height: params.height.unwrap_or(Dimension16::Absolute(1)),
align: a,
anchor: Alignment::TopLeft,
})
}
#[inline]
pub(super) fn new_corner_anchor(params: &Layout, anchor: Alignment) -> Result<Self, Error> {
should_not_use!(params.x, Error::CornerAnchorParameterUsedWithXY);
should_not_use!(params.y, Error::CornerAnchorParameterUsedWithXY);
should_not_use!(params.pivot, Error::CornerAnchorParameterUsedWithPivot);
Ok(PointAndSizeLayout {
x: match anchor {
Alignment::TopLeft | Alignment::BottomLeft => params.a_left.unwrap(),
Alignment::TopRight | Alignment::BottomRight => params.a_right.unwrap(),
_ => unreachable!("Internal error --> this point should not ne reached"),
},
y: match anchor {
Alignment::TopLeft | Alignment::TopRight => params.a_top.unwrap(),
Alignment::BottomLeft | Alignment::BottomRight => params.a_bottom.unwrap(),
_ => unreachable!("Internal error --> this point should not ne reached"),
},
width: params.width.unwrap_or(Dimension16::Absolute(1)),
height: params.height.unwrap_or(Dimension16::Absolute(1)),
align: anchor,
anchor,
})
}
#[inline]
pub(super) fn update_control_layout(&self, control_layout: &mut ControlLayout, parent_width: u16, parent_height: u16) {
control_layout.resize(self.width.absolute(parent_width), self.height.absolute(parent_height));
let mut x = self.x.absolute(parent_width);
let mut y = self.y.absolute(parent_height);
match self.anchor {
Alignment::TopLeft => {}
Alignment::TopCenter => x = (parent_width / 2) as i32,
Alignment::TopRight => x = (parent_width as i32) - x,
Alignment::CenterRight => {
x = (parent_width as i32) - x;
y = (parent_height / 2) as i32;
}
Alignment::BottomRight => {
x = (parent_width as i32) - x;
y = (parent_height as i32) - y;
}
Alignment::BottomCenter => {
x = (parent_width / 2) as i32;
y = (parent_height as i32) - y;
}
Alignment::BottomLeft => y = (parent_height as i32) - y,
Alignment::CenterLeft => y = (parent_height / 2) as i32,
Alignment::Center => {
x = (parent_width / 2) as i32;
y = (parent_height / 2) as i32;
}
}
match self.align {
Alignment::TopLeft => {}
Alignment::TopCenter => x -= (control_layout.width() / 2) as i32,
Alignment::TopRight => x -= control_layout.width() as i32,
Alignment::CenterRight => {
x -= control_layout.width() as i32;
y -= (control_layout.height() / 2) as i32;
}
Alignment::BottomRight => {
x -= control_layout.width() as i32;
y -= control_layout.height() as i32;
}
Alignment::BottomCenter => {
x -= (control_layout.width() / 2) as i32;
y -= control_layout.height() as i32;
}
Alignment::BottomLeft => y -= control_layout.height() as i32,
Alignment::CenterLeft => y -= (control_layout.height() / 2) as i32,
Alignment::Center => {
x -= (control_layout.width() / 2) as i32;
y -= (control_layout.height() / 2) as i32;
}
}
control_layout.set_position(x, y);
}
}