mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2025-12-06 11:46:42 +01:00
Compare commits
2 commits
44ebe17c66
...
2b208e3c49
| Author | SHA1 | Date | |
|---|---|---|---|
| 2b208e3c49 | |||
| 9fb5d2d9f7 |
11 changed files with 220 additions and 198 deletions
|
|
@ -19,6 +19,8 @@ pub type Usually<T> = Result<T, Box<dyn Error>>;
|
||||||
/// Standard optional result type.
|
/// Standard optional result type.
|
||||||
pub type Perhaps<T> = Result<Option<T>, Box<dyn Error>>;
|
pub type Perhaps<T> = Result<Option<T>, Box<dyn Error>>;
|
||||||
|
|
||||||
|
#[cfg(test)] use proptest_derive::Arbitrary;
|
||||||
|
|
||||||
#[cfg(test)] #[test] fn test_stub_output () -> Usually<()> {
|
#[cfg(test)] #[test] fn test_stub_output () -> Usually<()> {
|
||||||
use crate::*;
|
use crate::*;
|
||||||
struct TestOutput([u16;4]);
|
struct TestOutput([u16;4]);
|
||||||
|
|
@ -43,3 +45,152 @@ pub type Perhaps<T> = Result<Option<T>, Box<dyn Error>>;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)] #[test] fn test_space () {
|
||||||
|
use crate::*;
|
||||||
|
assert_eq!(Area::center(&[10u16, 10, 20, 20]), [20, 20]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)] #[test] fn test_iter_map () {
|
||||||
|
struct Foo;
|
||||||
|
impl<T: Output> Content<T> for Foo {}
|
||||||
|
fn make_map <T: Output, U: Content<T> + Send + Sync> (data: &Vec<U>) -> impl Content<T> {
|
||||||
|
Map::new(||data.iter(), |foo, index|{})
|
||||||
|
}
|
||||||
|
let data = vec![Foo, Foo, Foo];
|
||||||
|
//let map = make_map(&data);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)] mod test {
|
||||||
|
use crate::*;
|
||||||
|
use proptest::{prelude::*, option::of};
|
||||||
|
use proptest::option::of;
|
||||||
|
|
||||||
|
proptest! {
|
||||||
|
#[test] fn proptest_direction (
|
||||||
|
d in prop_oneof![
|
||||||
|
Just(North), Just(South),
|
||||||
|
Just(East), Just(West),
|
||||||
|
Just(Above), Just(Below)
|
||||||
|
],
|
||||||
|
x in u16::MIN..u16::MAX,
|
||||||
|
y in u16::MIN..u16::MAX,
|
||||||
|
w in u16::MIN..u16::MAX,
|
||||||
|
h in u16::MIN..u16::MAX,
|
||||||
|
a in u16::MIN..u16::MAX,
|
||||||
|
) {
|
||||||
|
let _ = d.split_fixed([x, y, w, h], a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
proptest! {
|
||||||
|
#[test] fn proptest_size (
|
||||||
|
x in u16::MIN..u16::MAX,
|
||||||
|
y in u16::MIN..u16::MAX,
|
||||||
|
a in u16::MIN..u16::MAX,
|
||||||
|
b in u16::MIN..u16::MAX,
|
||||||
|
) {
|
||||||
|
let size = [x, y];
|
||||||
|
let _ = size.w();
|
||||||
|
let _ = size.h();
|
||||||
|
let _ = size.wh();
|
||||||
|
let _ = size.clip_w(a);
|
||||||
|
let _ = size.clip_h(b);
|
||||||
|
let _ = size.expect_min(a, b);
|
||||||
|
let _ = size.to_area_pos();
|
||||||
|
let _ = size.to_area_size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
proptest! {
|
||||||
|
#[test] fn proptest_area (
|
||||||
|
x in u16::MIN..u16::MAX,
|
||||||
|
y in u16::MIN..u16::MAX,
|
||||||
|
w in u16::MIN..u16::MAX,
|
||||||
|
h in u16::MIN..u16::MAX,
|
||||||
|
a in u16::MIN..u16::MAX,
|
||||||
|
b in u16::MIN..u16::MAX,
|
||||||
|
) {
|
||||||
|
let _: [u16;4] = <[u16;4] as Area<u16>>::zero();
|
||||||
|
let _: [u16;4] = <[u16;4] as Area<u16>>::from_position([a, b]);
|
||||||
|
let _: [u16;4] = <[u16;4] as Area<u16>>::from_size([a, b]);
|
||||||
|
let area: [u16;4] = [x, y, w, h];
|
||||||
|
let _ = area.expect_min(a, b);
|
||||||
|
let _ = area.xy();
|
||||||
|
let _ = area.wh();
|
||||||
|
let _ = area.xywh();
|
||||||
|
let _ = area.clip_h(a);
|
||||||
|
let _ = area.clip_w(b);
|
||||||
|
let _ = area.clip([a, b]);
|
||||||
|
let _ = area.set_w(a);
|
||||||
|
let _ = area.set_h(b);
|
||||||
|
let _ = area.x2();
|
||||||
|
let _ = area.y2();
|
||||||
|
let _ = area.lrtb();
|
||||||
|
let _ = area.center();
|
||||||
|
let _ = area.center_x(a);
|
||||||
|
let _ = area.center_y(b);
|
||||||
|
let _ = area.center_xy([a, b]);
|
||||||
|
let _ = area.centered();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! test_op_transform {
|
||||||
|
($fn:ident, $Op:ident) => {
|
||||||
|
proptest! {
|
||||||
|
#[test] fn $fn (
|
||||||
|
op_x in of(u16::MIN..u16::MAX),
|
||||||
|
op_y in of(u16::MIN..u16::MAX),
|
||||||
|
content in "\\PC*",
|
||||||
|
x in u16::MIN..u16::MAX,
|
||||||
|
y in u16::MIN..u16::MAX,
|
||||||
|
w in u16::MIN..u16::MAX,
|
||||||
|
h in u16::MIN..u16::MAX,
|
||||||
|
) {
|
||||||
|
if let Some(op) = match (op_x, op_y) {
|
||||||
|
(Some(x), Some(y)) => Some($Op::xy(x, y, content)),
|
||||||
|
(Some(x), None) => Some($Op::x(x, content)),
|
||||||
|
(Some(y), None) => Some($Op::y(y, content)),
|
||||||
|
_ => None
|
||||||
|
} {
|
||||||
|
assert_eq!(Content::layout(&op, [x, y, w, h]),
|
||||||
|
Render::layout(&op, [x, y, w, h]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test_op_transform!(proptest_op_fixed, Fixed);
|
||||||
|
test_op_transform!(proptest_op_min, Min);
|
||||||
|
test_op_transform!(proptest_op_max, Max);
|
||||||
|
test_op_transform!(proptest_op_push, Push);
|
||||||
|
test_op_transform!(proptest_op_pull, Pull);
|
||||||
|
test_op_transform!(proptest_op_shrink, Shrink);
|
||||||
|
test_op_transform!(proptest_op_expand, Expand);
|
||||||
|
test_op_transform!(proptest_op_margin, Margin);
|
||||||
|
test_op_transform!(proptest_op_padding, Padding);
|
||||||
|
|
||||||
|
proptest! {
|
||||||
|
#[test] fn proptest_op_bsp (
|
||||||
|
d in prop_oneof![
|
||||||
|
Just(North), Just(South),
|
||||||
|
Just(East), Just(West),
|
||||||
|
Just(Above), Just(Below)
|
||||||
|
],
|
||||||
|
a in "\\PC*",
|
||||||
|
b in "\\PC*",
|
||||||
|
x in u16::MIN..u16::MAX,
|
||||||
|
y in u16::MIN..u16::MAX,
|
||||||
|
w in u16::MIN..u16::MAX,
|
||||||
|
h in u16::MIN..u16::MAX,
|
||||||
|
) {
|
||||||
|
let bsp = Bsp(d, a, b);
|
||||||
|
assert_eq!(
|
||||||
|
Content::layout(&bsp, [x, y, w, h]),
|
||||||
|
Render::layout(&bsp, [x, y, w, h]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,3 @@ mod map; pub use self::map::*;
|
||||||
//mod reduce; pub use self::reduce::*;
|
//mod reduce; pub use self::reduce::*;
|
||||||
mod thunk; pub use self::thunk::*;
|
mod thunk; pub use self::thunk::*;
|
||||||
mod transform; pub use self::transform::*;
|
mod transform; pub use self::transform::*;
|
||||||
|
|
||||||
#[cfg(test)] use crate::*;
|
|
||||||
#[cfg(test)] #[test] fn test_ops () -> Usually<()> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -27,9 +27,12 @@
|
||||||
//! test(area, &Align::sw(two_by_four()), [10, 28, 4, 2]);
|
//! test(area, &Align::sw(two_by_four()), [10, 28, 4, 2]);
|
||||||
//! test(area, &Align::w(two_by_four()), [10, 19, 4, 2]);
|
//! test(area, &Align::w(two_by_four()), [10, 19, 4, 2]);
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Default)] pub enum Alignment { #[default] Center, X, Y, NW, N, NE, E, SE, S, SW, W }
|
#[derive(Debug, Copy, Clone, Default)]
|
||||||
|
pub enum Alignment { #[default] Center, X, Y, NW, N, NE, E, SE, S, SW, W }
|
||||||
|
|
||||||
pub struct Align<A>(Alignment, A);
|
pub struct Align<A>(Alignment, A);
|
||||||
|
|
||||||
#[cfg(feature = "dsl")]
|
#[cfg(feature = "dsl")]
|
||||||
|
|
@ -79,6 +82,7 @@ impl<A> Align<A> {
|
||||||
#[inline] pub const fn ne (a: A) -> Self { Self(Alignment::NE, a) }
|
#[inline] pub const fn ne (a: A) -> Self { Self(Alignment::NE, a) }
|
||||||
#[inline] pub const fn se (a: A) -> Self { Self(Alignment::SE, a) }
|
#[inline] pub const fn se (a: A) -> Self { Self(Alignment::SE, a) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: Output, A: Content<E>> Content<E> for Align<A> {
|
impl<E: Output, A: Content<E>> Content<E> for Align<A> {
|
||||||
fn content (&self) -> impl Render<E> {
|
fn content (&self) -> impl Render<E> {
|
||||||
&self.1
|
&self.1
|
||||||
|
|
|
||||||
|
|
@ -117,28 +117,3 @@ impl<E: Output, A: Content<E>, B: Content<E>> BspAreas<E, A, B> for Bsp<A, B> {
|
||||||
#[macro_export] macro_rules! row {
|
#[macro_export] macro_rules! row {
|
||||||
($($expr:expr),* $(,)?) => {{ let bsp = (); $(let bsp = Bsp::e(bsp, $expr);)*; bsp }};
|
($($expr:expr),* $(,)?) => {{ let bsp = (); $(let bsp = Bsp::e(bsp, $expr);)*; bsp }};
|
||||||
}
|
}
|
||||||
#[cfg(test)] mod test {
|
|
||||||
use super::*;
|
|
||||||
use proptest::prelude::*;
|
|
||||||
proptest! {
|
|
||||||
#[test] fn proptest_op_bsp (
|
|
||||||
d in prop_oneof![
|
|
||||||
Just(North), Just(South),
|
|
||||||
Just(East), Just(West),
|
|
||||||
Just(Above), Just(Below)
|
|
||||||
],
|
|
||||||
a in "\\PC*",
|
|
||||||
b in "\\PC*",
|
|
||||||
x in u16::MIN..u16::MAX,
|
|
||||||
y in u16::MIN..u16::MAX,
|
|
||||||
w in u16::MIN..u16::MAX,
|
|
||||||
h in u16::MIN..u16::MAX,
|
|
||||||
) {
|
|
||||||
let bsp = Bsp(d, a, b);
|
|
||||||
assert_eq!(
|
|
||||||
Content::layout(&bsp, [x, y, w, h]),
|
|
||||||
Render::layout(&bsp, [x, y, w, h]),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,4 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
#[inline] pub fn map_south<O: Output>(
|
|
||||||
item_offset: O::Unit,
|
|
||||||
item_height: O::Unit,
|
|
||||||
item: impl Content<O>
|
|
||||||
) -> impl Content<O> {
|
|
||||||
Push::y(item_offset, Fixed::y(item_height, Fill::x(item)))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline] pub fn map_south_west<O: Output>(
|
|
||||||
item_offset: O::Unit,
|
|
||||||
item_height: O::Unit,
|
|
||||||
item: impl Content<O>
|
|
||||||
) -> impl Content<O> {
|
|
||||||
Push::y(item_offset, Align::nw(Fixed::y(item_height, Fill::x(item))))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline] pub fn map_east<O: Output>(
|
|
||||||
item_offset: O::Unit,
|
|
||||||
item_width: O::Unit,
|
|
||||||
item: impl Content<O>
|
|
||||||
) -> impl Content<O> {
|
|
||||||
Push::x(item_offset, Align::w(Fixed::x(item_width, Fill::y(item))))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Renders items from an iterator.
|
/// Renders items from an iterator.
|
||||||
pub struct Map<E, A, B, I, F, G>
|
pub struct Map<E, A, B, I, F, G>
|
||||||
|
|
@ -148,12 +125,26 @@ impl<'a, E, A, B, I, F, G> Content<E> for Map<E, A, B, I, F, G> where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)] #[test] fn test_iter_map () {
|
#[inline] pub fn map_south<O: Output>(
|
||||||
struct Foo;
|
item_offset: O::Unit,
|
||||||
impl<T: Output> Content<T> for Foo {}
|
item_height: O::Unit,
|
||||||
fn make_map <T: Output, U: Content<T> + Send + Sync> (data: &Vec<U>) -> impl Content<T> {
|
item: impl Content<O>
|
||||||
Map::new(||data.iter(), |foo, index|{})
|
) -> impl Content<O> {
|
||||||
}
|
Push::y(item_offset, Fixed::y(item_height, Fill::x(item)))
|
||||||
let data = vec![Foo, Foo, Foo];
|
}
|
||||||
//let map = make_map(&data);
|
|
||||||
|
#[inline] pub fn map_south_west<O: Output>(
|
||||||
|
item_offset: O::Unit,
|
||||||
|
item_height: O::Unit,
|
||||||
|
item: impl Content<O>
|
||||||
|
) -> impl Content<O> {
|
||||||
|
Push::y(item_offset, Align::nw(Fixed::y(item_height, Fill::x(item))))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline] pub fn map_east<O: Output>(
|
||||||
|
item_offset: O::Unit,
|
||||||
|
item_width: O::Unit,
|
||||||
|
item: impl Content<O>
|
||||||
|
) -> impl Content<O> {
|
||||||
|
Push::x(item_offset, Align::w(Fixed::x(item_width, Fill::y(item))))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,9 @@
|
||||||
//! //FIXME:test(area, &Fixed::y(4, ()), [20, 18, 0, 4]);
|
//! //FIXME:test(area, &Fixed::y(4, ()), [20, 18, 0, 4]);
|
||||||
//! //FIXME:test(area, &Fixed::xy(4, 4, unit), [18, 18, 4, 4]);
|
//! //FIXME:test(area, &Fixed::xy(4, 4, unit), [18, 18, 4, 4]);
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
/// Defines an enum that transforms its content
|
/// Defines an enum that transforms its content
|
||||||
/// along either the X axis, the Y axis, or both.
|
/// along either the X axis, the Y axis, or both.
|
||||||
macro_rules! transform_xy {
|
macro_rules! transform_xy {
|
||||||
|
|
@ -131,6 +133,7 @@ macro_rules! transform_xy_unit {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
transform_xy!("fill/x" "fill/y" "fill/xy" |self: Fill, to|{
|
transform_xy!("fill/x" "fill/y" "fill/xy" |self: Fill, to|{
|
||||||
let [x0, y0, wmax, hmax] = to.xywh();
|
let [x0, y0, wmax, hmax] = to.xywh();
|
||||||
let [x, y, w, h] = self.content().layout(to).xywh();
|
let [x, y, w, h] = self.content().layout(to).xywh();
|
||||||
|
|
@ -138,7 +141,9 @@ transform_xy!("fill/x" "fill/y" "fill/xy" |self: Fill, to|{
|
||||||
X(_) => [x0, y, wmax, h],
|
X(_) => [x0, y, wmax, h],
|
||||||
Y(_) => [x, y0, w, hmax],
|
Y(_) => [x, y0, w, hmax],
|
||||||
XY(_) => [x0, y0, wmax, hmax],
|
XY(_) => [x0, y0, wmax, hmax],
|
||||||
}.into() });
|
}.into()
|
||||||
|
});
|
||||||
|
|
||||||
transform_xy_unit!("fixed/x" "fixed/y" "fixed/xy"|self: Fixed, area|{
|
transform_xy_unit!("fixed/x" "fixed/y" "fixed/xy"|self: Fixed, area|{
|
||||||
let [x, y, w, h] = area.xywh();
|
let [x, y, w, h] = area.xywh();
|
||||||
let fixed_area = match self {
|
let fixed_area = match self {
|
||||||
|
|
@ -152,80 +157,55 @@ transform_xy_unit!("fixed/x" "fixed/y" "fixed/xy"|self: Fixed, area|{
|
||||||
Self::Y(fh, _) => [x, y, w, *fh],
|
Self::Y(fh, _) => [x, y, w, *fh],
|
||||||
Self::XY(fw, fh, _) => [x, y, *fw, *fh],
|
Self::XY(fw, fh, _) => [x, y, *fw, *fh],
|
||||||
};
|
};
|
||||||
fixed_area });
|
fixed_area
|
||||||
|
});
|
||||||
|
|
||||||
transform_xy_unit!("min/x" "min/y" "min/xy"|self: Min, area|{
|
transform_xy_unit!("min/x" "min/y" "min/xy"|self: Min, area|{
|
||||||
let area = Render::layout(&self.content(), area);
|
let area = Render::layout(&self.content(), area);
|
||||||
match self {
|
match self {
|
||||||
Self::X(mw, _) => [area.x(), area.y(), area.w().max(*mw), area.h()],
|
Self::X(mw, _) => [area.x(), area.y(), area.w().max(*mw), area.h()],
|
||||||
Self::Y(mh, _) => [area.x(), area.y(), area.w(), area.h().max(*mh)],
|
Self::Y(mh, _) => [area.x(), area.y(), area.w(), area.h().max(*mh)],
|
||||||
Self::XY(mw, mh, _) => [area.x(), area.y(), area.w().max(*mw), area.h().max(*mh)],
|
Self::XY(mw, mh, _) => [area.x(), area.y(), area.w().max(*mw), area.h().max(*mh)],
|
||||||
}});
|
}
|
||||||
|
});
|
||||||
|
|
||||||
transform_xy_unit!("max/x" "max/y" "max/xy"|self: Max, area|{
|
transform_xy_unit!("max/x" "max/y" "max/xy"|self: Max, area|{
|
||||||
let [x, y, w, h] = area.xywh();
|
let [x, y, w, h] = area.xywh();
|
||||||
Render::layout(&self.content(), match self {
|
Render::layout(&self.content(), match self {
|
||||||
Self::X(fw, _) => [x, y, *fw, h],
|
Self::X(fw, _) => [x, y, *fw, h],
|
||||||
Self::Y(fh, _) => [x, y, w, *fh],
|
Self::Y(fh, _) => [x, y, w, *fh],
|
||||||
Self::XY(fw, fh, _) => [x, y, *fw, *fh],
|
Self::XY(fw, fh, _) => [x, y, *fw, *fh],
|
||||||
}.into())});
|
}.into())
|
||||||
|
});
|
||||||
|
|
||||||
transform_xy_unit!("shrink/x" "shrink/y" "shrink/xy"|self: Shrink, area|Render::layout(
|
transform_xy_unit!("shrink/x" "shrink/y" "shrink/xy"|self: Shrink, area|Render::layout(
|
||||||
&self.content(),
|
&self.content(),
|
||||||
[area.x(), area.y(), area.w().minus(self.dx()), area.h().minus(self.dy())].into()));
|
[area.x(), area.y(), area.w().minus(self.dx()), area.h().minus(self.dy())].into()));
|
||||||
|
|
||||||
transform_xy_unit!("expand/x" "expand/y" "expand/xy"|self: Expand, area|Render::layout(
|
transform_xy_unit!("expand/x" "expand/y" "expand/xy"|self: Expand, area|Render::layout(
|
||||||
&self.content(),
|
&self.content(),
|
||||||
[area.x(), area.y(), area.w().plus(self.dx()), area.h().plus(self.dy())].into()));
|
[area.x(), area.y(), area.w().plus(self.dx()), area.h().plus(self.dy())].into()));
|
||||||
|
|
||||||
transform_xy_unit!("push/x" "push/y" "push/xy"|self: Push, area|{
|
transform_xy_unit!("push/x" "push/y" "push/xy"|self: Push, area|{
|
||||||
let area = Render::layout(&self.content(), area);
|
let area = Render::layout(&self.content(), area);
|
||||||
[area.x().plus(self.dx()), area.y().plus(self.dy()), area.w(), area.h()] });
|
[area.x().plus(self.dx()), area.y().plus(self.dy()), area.w(), area.h()]
|
||||||
|
});
|
||||||
|
|
||||||
transform_xy_unit!("pull/x" "pull/y" "pull/xy"|self: Pull, area|{
|
transform_xy_unit!("pull/x" "pull/y" "pull/xy"|self: Pull, area|{
|
||||||
let area = Render::layout(&self.content(), area);
|
let area = Render::layout(&self.content(), area);
|
||||||
[area.x().minus(self.dx()), area.y().minus(self.dy()), area.w(), area.h()] });
|
[area.x().minus(self.dx()), area.y().minus(self.dy()), area.w(), area.h()]
|
||||||
|
});
|
||||||
|
|
||||||
transform_xy_unit!("margin/x" "margin/y" "margin/xy"|self: Margin, area|{
|
transform_xy_unit!("margin/x" "margin/y" "margin/xy"|self: Margin, area|{
|
||||||
let area = Render::layout(&self.content(), area);
|
let area = Render::layout(&self.content(), area);
|
||||||
let dx = self.dx();
|
let dx = self.dx();
|
||||||
let dy = self.dy();
|
let dy = self.dy();
|
||||||
[area.x().minus(dx), area.y().minus(dy), area.w().plus(dy.plus(dy)), area.h().plus(dy.plus(dy))] });
|
[area.x().minus(dx), area.y().minus(dy), area.w().plus(dy.plus(dy)), area.h().plus(dy.plus(dy))]
|
||||||
|
});
|
||||||
|
|
||||||
transform_xy_unit!("padding/x" "padding/y" "padding/xy"|self: Padding, area|{
|
transform_xy_unit!("padding/x" "padding/y" "padding/xy"|self: Padding, area|{
|
||||||
let area = Render::layout(&self.content(), area);
|
let area = Render::layout(&self.content(), area);
|
||||||
let dx = self.dx();
|
let dx = self.dx();
|
||||||
let dy = self.dy();
|
let dy = self.dy();
|
||||||
[area.x().plus(dx), area.y().plus(dy), area.w().minus(dy.plus(dy)), area.h().minus(dy.plus(dy)), ] });
|
[area.x().plus(dx), area.y().plus(dy), area.w().minus(dy.plus(dy)), area.h().minus(dy.plus(dy))]
|
||||||
|
});
|
||||||
#[cfg(test)] mod test_op_transform {
|
|
||||||
use super::*;
|
|
||||||
use proptest::prelude::*;
|
|
||||||
use proptest::option::of;
|
|
||||||
macro_rules! test_op_transform {
|
|
||||||
($fn:ident, $Op:ident) => {
|
|
||||||
proptest! {
|
|
||||||
#[test] fn $fn (
|
|
||||||
op_x in of(u16::MIN..u16::MAX),
|
|
||||||
op_y in of(u16::MIN..u16::MAX),
|
|
||||||
content in "\\PC*",
|
|
||||||
x in u16::MIN..u16::MAX,
|
|
||||||
y in u16::MIN..u16::MAX,
|
|
||||||
w in u16::MIN..u16::MAX,
|
|
||||||
h in u16::MIN..u16::MAX,
|
|
||||||
) {
|
|
||||||
if let Some(op) = match (op_x, op_y) {
|
|
||||||
(Some(x), Some(y)) => Some($Op::xy(x, y, content)),
|
|
||||||
(Some(x), None) => Some($Op::x(x, content)),
|
|
||||||
(Some(y), None) => Some($Op::y(y, content)),
|
|
||||||
_ => None
|
|
||||||
} {
|
|
||||||
assert_eq!(Content::layout(&op, [x, y, w, h]),
|
|
||||||
Render::layout(&op, [x, y, w, h]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
test_op_transform!(test_op_fixed, Fixed);
|
|
||||||
test_op_transform!(test_op_min, Min);
|
|
||||||
test_op_transform!(test_op_max, Max);
|
|
||||||
test_op_transform!(test_op_push, Push);
|
|
||||||
test_op_transform!(test_op_pull, Pull);
|
|
||||||
test_op_transform!(test_op_shrink, Shrink);
|
|
||||||
test_op_transform!(test_op_expand, Expand);
|
|
||||||
test_op_transform!(test_op_margin, Margin);
|
|
||||||
test_op_transform!(test_op_padding, Padding);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,3 @@ mod coordinate; pub use self::coordinate::*;
|
||||||
mod direction; pub use self::direction::*;
|
mod direction; pub use self::direction::*;
|
||||||
mod measure; pub use self::measure::*;
|
mod measure; pub use self::measure::*;
|
||||||
mod size; pub use self::size::*;
|
mod size; pub use self::size::*;
|
||||||
|
|
||||||
#[cfg(test)] #[test] fn test_space () {
|
|
||||||
use crate::*;
|
|
||||||
assert_eq!(Area::center(&[10u16, 10, 20, 20]), [20, 20]);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -96,40 +96,3 @@ impl<N: Coordinate> Area<N> for [N;4] {
|
||||||
fn w (&self) -> N { self[2] }
|
fn w (&self) -> N { self[2] }
|
||||||
fn h (&self) -> N { self[3] }
|
fn h (&self) -> N { self[3] }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)] mod test_area {
|
|
||||||
use super::*;
|
|
||||||
use proptest::prelude::*;
|
|
||||||
proptest! {
|
|
||||||
#[test] fn test_area_prop (
|
|
||||||
x in u16::MIN..u16::MAX,
|
|
||||||
y in u16::MIN..u16::MAX,
|
|
||||||
w in u16::MIN..u16::MAX,
|
|
||||||
h in u16::MIN..u16::MAX,
|
|
||||||
a in u16::MIN..u16::MAX,
|
|
||||||
b in u16::MIN..u16::MAX,
|
|
||||||
) {
|
|
||||||
let _: [u16;4] = <[u16;4] as Area<u16>>::zero();
|
|
||||||
let _: [u16;4] = <[u16;4] as Area<u16>>::from_position([a, b]);
|
|
||||||
let _: [u16;4] = <[u16;4] as Area<u16>>::from_size([a, b]);
|
|
||||||
let area: [u16;4] = [x, y, w, h];
|
|
||||||
let _ = area.expect_min(a, b);
|
|
||||||
let _ = area.xy();
|
|
||||||
let _ = area.wh();
|
|
||||||
let _ = area.xywh();
|
|
||||||
let _ = area.clip_h(a);
|
|
||||||
let _ = area.clip_w(b);
|
|
||||||
let _ = area.clip([a, b]);
|
|
||||||
let _ = area.set_w(a);
|
|
||||||
let _ = area.set_h(b);
|
|
||||||
let _ = area.x2();
|
|
||||||
let _ = area.y2();
|
|
||||||
let _ = area.lrtb();
|
|
||||||
let _ = area.center();
|
|
||||||
let _ = area.center_x(a);
|
|
||||||
let _ = area.center_y(b);
|
|
||||||
let _ = area.center_xy([a, b]);
|
|
||||||
let _ = area.centered();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,12 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
#[cfg(test)] use proptest_derive::Arbitrary;
|
|
||||||
/// A cardinal direction.
|
/// A cardinal direction.
|
||||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||||
#[cfg_attr(test, derive(Arbitrary))]
|
#[cfg_attr(test, derive(Arbitrary))]
|
||||||
pub enum Direction { North, South, East, West, Above, Below }
|
pub enum Direction {
|
||||||
|
North, South, East, West, Above, Below
|
||||||
|
}
|
||||||
|
|
||||||
impl Direction {
|
impl Direction {
|
||||||
pub fn split_fixed <N: Coordinate> (self, area: impl Area<N>, a: N) -> ([N;4],[N;4]) {
|
pub fn split_fixed <N: Coordinate> (self, area: impl Area<N>, a: N) -> ([N;4],[N;4]) {
|
||||||
let [x, y, w, h] = area.xywh();
|
let [x, y, w, h] = area.xywh();
|
||||||
|
|
@ -16,23 +19,3 @@ impl Direction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(test)] mod test {
|
|
||||||
use super::*;
|
|
||||||
use proptest::prelude::*;
|
|
||||||
proptest! {
|
|
||||||
#[test] fn proptest_direction (
|
|
||||||
d in prop_oneof![
|
|
||||||
Just(North), Just(South),
|
|
||||||
Just(East), Just(West),
|
|
||||||
Just(Above), Just(Below)
|
|
||||||
],
|
|
||||||
x in u16::MIN..u16::MAX,
|
|
||||||
y in u16::MIN..u16::MAX,
|
|
||||||
w in u16::MIN..u16::MAX,
|
|
||||||
h in u16::MIN..u16::MAX,
|
|
||||||
a in u16::MIN..u16::MAX,
|
|
||||||
) {
|
|
||||||
let _ = d.split_fixed([x, y, w, h], a);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -38,26 +38,3 @@ impl<N: Coordinate> Size<N> for [N;2] {
|
||||||
fn x (&self) -> N { self[0] }
|
fn x (&self) -> N { self[0] }
|
||||||
fn y (&self) -> N { self[1] }
|
fn y (&self) -> N { self[1] }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)] mod test_size {
|
|
||||||
use super::*;
|
|
||||||
use proptest::prelude::*;
|
|
||||||
proptest! {
|
|
||||||
#[test] fn test_size (
|
|
||||||
x in u16::MIN..u16::MAX,
|
|
||||||
y in u16::MIN..u16::MAX,
|
|
||||||
a in u16::MIN..u16::MAX,
|
|
||||||
b in u16::MIN..u16::MAX,
|
|
||||||
) {
|
|
||||||
let size = [x, y];
|
|
||||||
let _ = size.w();
|
|
||||||
let _ = size.h();
|
|
||||||
let _ = size.wh();
|
|
||||||
let _ = size.clip_w(a);
|
|
||||||
let _ = size.clip_h(b);
|
|
||||||
let _ = size.expect_min(a, b);
|
|
||||||
let _ = size.to_area_pos();
|
|
||||||
let _ = size.to_area_size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,14 @@ use std::time::Duration;
|
||||||
use std::thread::{spawn, JoinHandle};
|
use std::thread::{spawn, JoinHandle};
|
||||||
use crossterm::event::{poll, read};
|
use crossterm::event::{poll, read};
|
||||||
|
|
||||||
#[derive(Debug, Clone)] pub struct TuiIn(pub Arc<AtomicBool>, pub Event);
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct TuiIn(
|
||||||
|
/// Exit flag
|
||||||
|
pub Arc<AtomicBool>,
|
||||||
|
/// Input event
|
||||||
|
pub Event,
|
||||||
|
);
|
||||||
|
|
||||||
impl Input for TuiIn {
|
impl Input for TuiIn {
|
||||||
type Event = Event;
|
type Event = Event;
|
||||||
type Handled = bool;
|
type Handled = bool;
|
||||||
|
|
@ -49,6 +56,7 @@ impl TuiIn {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "dsl")]
|
||||||
impl DslInput for TuiIn {
|
impl DslInput for TuiIn {
|
||||||
fn matches_dsl (&self, token: &str) -> bool {
|
fn matches_dsl (&self, token: &str) -> bool {
|
||||||
if let Some(event) = KeyMatcher::new(token).build() {
|
if let Some(event) = KeyMatcher::new(token).build() {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue