mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2026-09-18 13:26:42 +02:00
big flat
This commit is contained in:
parent
94c26f06cc
commit
fc01fd6ad3
40 changed files with 2075 additions and 1807 deletions
39
src/layout/align.rs
Normal file
39
src/layout/align.rs
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
use crate::{*, draw::*, layout::*};
|
||||
use Azimuth::*;
|
||||
|
||||
pub struct Align<T>(
|
||||
pub(crate) Option<Azimuth>,
|
||||
pub(crate) T,
|
||||
);
|
||||
|
||||
impl<S: Screen, T: Draw<S>> Draw<S> for Align<T> {
|
||||
fn layout (&self, area: XYWH<S::Unit>) -> Perhaps<XYWH<S::Unit>> {
|
||||
let XYWH(x0, y0, w0, h0) = area;
|
||||
Ok(align::<S>(area, self.1.layout(area)?, self.0))
|
||||
}
|
||||
fn draw (self, to: &mut S) -> Perhaps<XYWH<S::Unit>> {
|
||||
Ok(self.layout(to.area())?.map(|area|to.clip(area, |to|self.1.draw(to))).transpose()?.flatten())
|
||||
}
|
||||
}
|
||||
|
||||
fn align <S: Screen> (
|
||||
area0: XYWH<S::Unit>, area: Option<XYWH<S::Unit>>, azimuth: Option<Azimuth>
|
||||
) -> Option<XYWH<S::Unit>> {
|
||||
area.map(|XYWH(x, y, w, h)|{
|
||||
let XYWH(x0, y0, w0, h0) = area0;
|
||||
match azimuth {
|
||||
Some(NW) => XYWH(x0, y0, w, h),
|
||||
Some(N) => XYWH(x0 + w0.minus(w) / 2.into(), y0, w, h),
|
||||
Some(NE) => XYWH((x0 + w0).minus(w), y0, w, h),
|
||||
Some(W) => XYWH(x0, y0 + h0.minus(h) / 2.into(), w, h),
|
||||
Some(C) => XYWH(x0 + w0.minus(w) / 2.into(), y0 + h0.minus(h) / 2.into(), w, h),
|
||||
Some(E) => XYWH((x0 + w0).minus(w), y0 + h0.minus(h) / 2.into(), w, h),
|
||||
Some(SW) => XYWH(x0, (y0 + h0).minus(h), w, h),
|
||||
Some(S) => XYWH(x0 + w0.minus(w) / 2.into(), (y0 + h0).minus(h), w, h),
|
||||
Some(SE) => XYWH((x0 + w0).minus(w), (y0 + h0).minus(h), w, h),
|
||||
Some(X) => XYWH(x0 + w0.minus(w) / 2.into(), y, w, h),
|
||||
Some(Y) => XYWH(x, y0 + h0.minus(h) / 2.into(), w, h),
|
||||
None => XYWH(x, y, w, h)
|
||||
}
|
||||
})
|
||||
}
|
||||
21
src/layout/area.rs
Normal file
21
src/layout/area.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
use crate::{*, draw::*};
|
||||
|
||||
/// ```
|
||||
/// use tengri::*;
|
||||
/// let _ = area(None, "unareaed");
|
||||
/// let _ = area(XYWH(1, 2, 3, 4), "southeast");
|
||||
/// let _ = area(Some(XYWH(1, 2, 3, 4)), "southeast");
|
||||
/// ```
|
||||
pub fn area <S: Screen, T: Draw<S>, U: Into<Option<XYWH<S::Unit>>>> (
|
||||
origin: U, it: T
|
||||
) -> Area<S, T> {
|
||||
Area(origin.into(), it)
|
||||
}
|
||||
|
||||
pub struct Area<S: Screen, T: Draw<S>>(
|
||||
pub Option<XYWH<S::Unit>>,
|
||||
pub T
|
||||
);
|
||||
impl_draw!(<S: Screen, T: Draw<S>,>|self: Area<S, T>, to: S|{
|
||||
to.clip(self.0, |to|self.1.draw(to))
|
||||
});
|
||||
29
src/layout/exact.rs
Normal file
29
src/layout/exact.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
use crate::{*, draw::*};
|
||||
|
||||
/// Set size of of drawing area.
|
||||
///
|
||||
/// ```
|
||||
/// use tengri::Layout;
|
||||
/// let _ = "".exact_w(1);
|
||||
/// let _ = "".exact_h(1);
|
||||
/// let _ = "".exact_wh(1, 1);
|
||||
/// ```
|
||||
pub enum Exact<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
||||
__(PhantomData<T>),
|
||||
W(I, X),
|
||||
H(I, X),
|
||||
WH(I, X, X),
|
||||
}
|
||||
impl_draw!(<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>,>|self: Exact<T, I, X>, to: T|{
|
||||
let area: XYWH<T::Unit> = to.area();
|
||||
let (item, area) = match self {
|
||||
Self::W(item, w1) =>
|
||||
(item, XYWH(area.0, area.1, w1.into().unwrap_or(area.2), area.3)),
|
||||
Self::H(item, h1) =>
|
||||
(item, XYWH(area.0, area.1, area.2, h1.into().unwrap_or(area.3))),
|
||||
Self::WH(item, w1, h1) =>
|
||||
(item, XYWH(area.0, area.1, w1.into().unwrap_or(area.2), h1.into().unwrap_or(area.3))),
|
||||
_ => return Ok(None)
|
||||
};
|
||||
to.clip(area, |to|item.draw(to))
|
||||
});
|
||||
41
src/layout/full.rs
Normal file
41
src/layout/full.rs
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
use crate::{*, draw::*};
|
||||
|
||||
/// Use whole drawing area along one or both axes.
|
||||
///
|
||||
/// ```
|
||||
/// # fn doctest_layout_full () -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// use tengri::{Layout, Draw, XYWH};
|
||||
/// let area = XYWH(0u16, 0, 80, 25);
|
||||
/// assert_eq!("1".layout(area)?, Some(XYWH(0u16, 0, 1, 1)));
|
||||
/// assert_eq!("1".full_w().layout(area)?, Some(XYWH(0u16, 0, 80, 1)));
|
||||
/// assert_eq!("1".full_h().layout(area)?, Some(XYWH(0u16, 0, 1, 25)));
|
||||
/// assert_eq!("1".full_wh().layout(area)?, Some(XYWH(0u16, 0, 80, 25)));
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
pub enum Full<T: Screen, I: Draw<T>> {
|
||||
__(PhantomData<T>),
|
||||
W(I),
|
||||
H(I),
|
||||
WH(I),
|
||||
}
|
||||
impl_draw!(<T: Screen, I: Draw<T>,>|self: Full<T, I>, to: T|{
|
||||
let XYWH(x0, y0, w0, h0) = to.area();
|
||||
match self {
|
||||
Self::W(item) => if let Some(XYWH(_, y, _, h)) = item.layout(to.area())? {
|
||||
to.clip(XYWH(x0, y, w0, h), |to|item.draw(to))
|
||||
} else {
|
||||
Ok(None)
|
||||
},
|
||||
Self::H(item) => if let Some(XYWH(x, _, w, _)) = item.layout(to.area())? {
|
||||
to.clip(XYWH(x, y0, w, h0), |to|item.draw(to))
|
||||
} else {
|
||||
Ok(None)
|
||||
},
|
||||
Self::WH(item) => if let Some(XYWH(..)) = item.layout(to.area())? {
|
||||
to.clip(XYWH(x0, y0, w0, h0), |to|item.draw(to))
|
||||
} else {
|
||||
Ok(None)
|
||||
},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
});
|
||||
55
src/layout/max.rs
Normal file
55
src/layout/max.rs
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
use crate::{*, draw::*};
|
||||
|
||||
/// Set maximum size of of drawing area.
|
||||
///
|
||||
/// ```
|
||||
/// # fn doctest_layout_max () -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// use tengri::{Layout, Draw, XYWH};
|
||||
/// let area = XYWH(1u16, 1, 80, 25);
|
||||
/// assert_eq!("12345".max_w(1).layout(area)?, Some(XYWH(1u16, 1, 1, 1)));
|
||||
/// assert_eq!("12345".max_h(1).layout(area)?, Some(XYWH(1u16, 1, 1, 1)));
|
||||
/// assert_eq!("12345".max_wh(1, 1).layout(area)?, Some(XYWH(1u16, 1, 5, 1)));
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
pub enum Max<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>> + Copy> {
|
||||
__(PhantomData<T>),
|
||||
W(I, X),
|
||||
H(I, X),
|
||||
WH(I, X, X),
|
||||
}
|
||||
|
||||
impl<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>> + Copy> Draw<T> for Max<T, I, X> {
|
||||
fn layout (&self, area: XYWH<T::Unit>) -> Perhaps<XYWH<T::Unit>> {
|
||||
Ok(Some(match self {
|
||||
Self::W(_, max_w) => XYWH(
|
||||
area.0, area.1, (*max_w).into().map(|max|max.min(area.2)).unwrap_or(area.2),
|
||||
area.3),
|
||||
Self::H(_, max_h) => XYWH(
|
||||
area.0, area.1, area.2,
|
||||
(*max_h).into().map(|max|max.min(area.3)).unwrap_or(area.3)),
|
||||
Self::WH(_, max_w, max_h) => XYWH(
|
||||
area.0, area.1, (*max_w).into().map(|max|max.min(area.2)).unwrap_or(area.2),
|
||||
(*max_h).into().map(|max|max.min(area.3)).unwrap_or(area.3)),
|
||||
_ => return Ok(None)
|
||||
}))
|
||||
}
|
||||
fn draw (self, to: &mut T) -> Perhaps<XYWH<T::Unit>> {
|
||||
let area: XYWH<T::Unit> = to.area();
|
||||
let (item, area) = match self {
|
||||
Self::W(item, max_w) => (item, XYWH(
|
||||
area.0, area.1, max_w.into().map(|max|max.min(area.2)).unwrap_or(area.2),
|
||||
area.3
|
||||
)),
|
||||
Self::H(item, max_h) => (item, XYWH(
|
||||
area.0, area.1, area.2,
|
||||
max_h.into().map(|max|max.min(area.3)).unwrap_or(area.3)
|
||||
)),
|
||||
Self::WH(item, max_w, max_h) => (item, XYWH(
|
||||
area.0, area.1, max_w.into().map(|max|max.min(area.2)).unwrap_or(area.2),
|
||||
max_h.into().map(|max|max.min(area.3)).unwrap_or(area.3),
|
||||
)),
|
||||
_ => return Ok(None)
|
||||
};
|
||||
to.clip(area, draw(item))
|
||||
}
|
||||
}
|
||||
40
src/layout/min.rs
Normal file
40
src/layout/min.rs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
use crate::{*, draw::*};
|
||||
|
||||
/// Only draw content if area is above a certain size.
|
||||
///
|
||||
/// ```
|
||||
/// # fn doctest_layout_min () -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// use tengri::{Layout, Draw, XYWH};
|
||||
/// let area = XYWH(1u16, 1, 80, 25);
|
||||
/// assert_eq!("1".min_w(5).layout(area)?, Some(XYWH(1u16, 1, 5, 1)));
|
||||
/// assert_eq!("1".min_h(5).layout(area)?, Some(XYWH(1u16, 1, 1, 5)));
|
||||
/// assert_eq!("1".min_wh(5, 5).layout(area)?, Some(XYWH(1u16, 1, 5, 5)));
|
||||
/// assert_eq!("123456".min_w(5).layout(area)?, Some(XYWH(1u16, 1, 6, 1)));
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
pub enum Min<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
||||
__(PhantomData<T>),
|
||||
W(I, X),
|
||||
H(I, X),
|
||||
WH(I, X, X),
|
||||
}
|
||||
|
||||
impl_draw!(<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>,>|self: Min<T, I, X>, to: T|{
|
||||
match self {
|
||||
Self::__(_) => unreachable!(),
|
||||
Self::W(item, w1) if let Some(XYWH(x, y, w, h)) = item.layout(to.area())? => {
|
||||
let w = w1.into().map(|w1|w.max(w1)).unwrap_or(w);
|
||||
to.clip(XYWH(x, y, w, h), |to|item.draw(to))
|
||||
},
|
||||
Self::H(item, h1) if let Some(XYWH(x, y, w, h)) = item.layout(to.area())? => {
|
||||
let h = h1.into().map(|h1|h.max(h1)).unwrap_or(h);
|
||||
to.clip(XYWH(x, y, w, h), |to|item.draw(to))
|
||||
},
|
||||
Self::WH(item, w1, h1) if let Some(XYWH(x, y, w, h)) = item.layout(to.area())? => {
|
||||
let w = w1.into().map(|w1|w.max(w1)).unwrap_or(w);
|
||||
let h = h1.into().map(|h1|h.max(h1)).unwrap_or(h);
|
||||
to.clip(XYWH(x, y, w, h), |to|item.draw(to))
|
||||
},
|
||||
_ => Ok(None)
|
||||
}
|
||||
});
|
||||
21
src/layout/origin.rs
Normal file
21
src/layout/origin.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
use crate::{*, draw::*, layout::*};
|
||||
|
||||
pub struct Origin<T>(
|
||||
pub(crate) Option<Azimuth>,
|
||||
pub(crate) T
|
||||
);
|
||||
|
||||
impl_draw!(<S: Screen, T: Draw<S>,>|self: Origin<T>, _to: S|{
|
||||
todo!()
|
||||
});
|
||||
|
||||
/// Something that has `[0, 0]` at a particular point.
|
||||
pub trait HasOrigin {
|
||||
fn origin (&self) -> Azimuth;
|
||||
}
|
||||
|
||||
impl<T: AsRef<Azimuth>> HasOrigin for T {
|
||||
fn origin (&self) -> Azimuth {
|
||||
*self.as_ref()
|
||||
}
|
||||
}
|
||||
37
src/layout/pad.rs
Normal file
37
src/layout/pad.rs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
use crate::{*, draw::*};
|
||||
|
||||
/// Define inner drawing area.
|
||||
///
|
||||
/// ```
|
||||
/// use tengri::Layout;
|
||||
/// let _ = "".pad_w(1);
|
||||
/// let _ = "".pad_h(1);
|
||||
/// let _ = "".pad_wh(1, 1);
|
||||
/// ```
|
||||
pub enum Pad<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
||||
__(PhantomData<T>),
|
||||
W(I, X),
|
||||
H(I, X),
|
||||
WH(I, X, X),
|
||||
}
|
||||
|
||||
impl_draw!(<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>,>|self: Pad<T, I, X>, to: T|{
|
||||
let area = to.area();
|
||||
let (item, area) = match self {
|
||||
Self::W(item, w1) => {
|
||||
let w1 = w1.into().unwrap_or(T::Unit::zero());
|
||||
(item, XYWH(area.0 + w1, area.1, area.2.minus(w1 + w1), area.3))
|
||||
},
|
||||
Self::H(item, h1) => {
|
||||
let h1 = h1.into().unwrap_or(T::Unit::zero());
|
||||
(item, XYWH(area.0, area.1 + h1, area.2, area.3.minus(h1 + h1)))
|
||||
},
|
||||
Self::WH(item, w1, h1) => {
|
||||
let w1 = w1.into().unwrap_or(T::Unit::zero());
|
||||
let h1 = h1.into().unwrap_or(T::Unit::zero());
|
||||
(item, XYWH(area.0 + w1, area.1 + h1, area.2.minus(w1 + w1), area.3.minus(h1 + h1)))
|
||||
},
|
||||
_ => return Ok(None)
|
||||
};
|
||||
item.draw(to)
|
||||
});
|
||||
24
src/layout/pull.rs
Normal file
24
src/layout/pull.rs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
use crate::{*, draw::*};
|
||||
|
||||
/// Move content in the negative direction of one or both axes.
|
||||
///
|
||||
/// ```
|
||||
/// # fn doctest_layout_pull () -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// use tengri::{Layout, Draw, XYWH};
|
||||
/// let area = XYWH(1u16, 1, 80, 25);
|
||||
/// assert_eq!("1".layout(area)?, Some(XYWH(0u16, 0, 1, 1)));
|
||||
/// assert_eq!("1".pull_x(1).layout(area)?, Some(XYWH(0u16, 1, 1, 1)));
|
||||
/// assert_eq!("1".pull_y(1).layout(area)?, Some(XYWH(1u16, 0, 1, 1)));
|
||||
/// assert_eq!("1".pull_xy(1, 1).layout(area)?, Some(XYWH(0u16, 0, 1, 1)));
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
pub enum Pull<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
||||
__(PhantomData<T>),
|
||||
X(I, X),
|
||||
Y(I, X),
|
||||
XY(I, X, X),
|
||||
}
|
||||
|
||||
impl_draw!(<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>,>|self: Pull<T, I, X>, _to: T|{
|
||||
todo!()
|
||||
});
|
||||
42
src/layout/push.rs
Normal file
42
src/layout/push.rs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
use crate::{*, draw::*};
|
||||
|
||||
/// Move content in the positive direction of one or both axes.
|
||||
///
|
||||
/// ```
|
||||
/// # fn doctest_layout_push () -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// use tengri::{Layout, Draw, XYWH};
|
||||
/// let area = XYWH(0u16, 0, 80, 25);
|
||||
/// assert_eq!("1".layout(area)?, Some(XYWH(0u16, 0, 1, 1)));
|
||||
/// assert_eq!("1".push_x(1).layout(area)?, Some(XYWH(1u16, 0, 1, 1)));
|
||||
/// assert_eq!("1".push_y(1).layout(area)?, Some(XYWH(0u16, 1, 1, 1)));
|
||||
/// assert_eq!("1".push_xy(1, 1).layout(area)?, Some(XYWH(1u16, 1, 1, 1)));
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
pub enum Push<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
||||
__(PhantomData<T>),
|
||||
X(I, X),
|
||||
Y(I, X),
|
||||
XY(I, X, X),
|
||||
}
|
||||
|
||||
impl_draw!(<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>,>|self: Push<T, I, X>, to: T|{
|
||||
match self {
|
||||
Self::__(_) => unreachable!(),
|
||||
Self::X(item, x1) if let Some(XYWH(x, y, w, h)) = item.layout(to.area())? => {
|
||||
to.clip(XYWH(
|
||||
x + x1.into().unwrap_or_default(), y, w, h
|
||||
), |to|item.draw(to))
|
||||
},
|
||||
Self::Y(item, y1) if let Some(XYWH(x, y, w, h)) = item.layout(to.area())? => {
|
||||
to.clip(XYWH(
|
||||
x, y + y1.into().unwrap_or_default(), w, h
|
||||
), |to|item.draw(to))
|
||||
},
|
||||
Self::XY(item, x1, y1) if let Some(XYWH(x, y, w, h)) = item.layout(to.area())? => {
|
||||
to.clip(XYWH(
|
||||
x + x1.into().unwrap_or_default(), y + y1.into().unwrap_or_default(), w, h
|
||||
), |to|item.draw(to))
|
||||
},
|
||||
_ => Ok(None)
|
||||
}
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue