diff --git a/crates/tek_core/examples/demo.rs b/crates/tek_core/examples/demo.rs index 470930a9..91405159 100644 --- a/crates/tek_core/examples/demo.rs +++ b/crates/tek_core/examples/demo.rs @@ -36,22 +36,27 @@ impl Demo { impl Content for Demo { type Engine = Tui; fn content (&self) -> impl Widget { - Align::Center(Layers::new(|add|{ + Layers::new(|add|{ add(&FillBg(Color::Rgb(128,0,0)))?; - add(&Outset::XY(2, 2, Align::Center(Split::down(|add|{ - add(&Layers::new(|add|{ - add(&FillBg(Color::Rgb(0,128,0)))?; - add(&Outset::XY(2, 2, Align::Center("12345")))?; - add(&Align::Center("FOO")) - }))?; - add(&Layers::new(|add|{ - add(&Outset::XY(2, 2, Align::Center("1234567")))?; - add(&Align::Center("BAR"))?; - add(&FillBg(Color::Rgb(0,0,128))) - }))?; - Ok(()) - })))) - })) + add(&Outset::X(1, "foo"))?; + Ok(()) + }) + //Align::Y(Layers::new(|add|{ + //add(&FillBg(Color::Rgb(128,0,0)))?; + //add(&Outset::X(1, Align::Center(Split::down(|add|{ + //add(&Align::X(Layers::new(|add|{ + //add(&FillBg(Color::Rgb(0,128,0)))?; + //add(&Outset::Y(1, Align::Center("12345")))?; + //add(&Align::Center("FOO")) + //})))?; + //add(&Layers::new(|add|{ + //add(&Outset::XY(1, 1, Align::Center("1234567")))?; + //add(&Align::Center("BAR"))?; + //add(&FillBg(Color::Rgb(0,0,128))) + //}))?; + //Ok(()) + //})))) + //})) } } diff --git a/crates/tek_core/src/engine.rs b/crates/tek_core/src/engine.rs index ccf39fb3..d3bdd65c 100644 --- a/crates/tek_core/src/engine.rs +++ b/crates/tek_core/src/engine.rs @@ -351,6 +351,10 @@ impl Direction { pub enum Align { /// Draw at center of container Center(L), + /// Draw at center of X axis + X(L), + /// Draw at center of Y axis + Y(L), /// Draw at upper left corner of contaier NW(L), /// Draw at center of upper edge of container @@ -373,6 +377,8 @@ impl Align { pub fn inner (&self) -> &T { match self { Self::Center(inner) => inner, + Self::X(inner) => inner, + Self::Y(inner) => inner, Self::NW(inner) => inner, Self::N(inner) => inner, Self::NE(inner) => inner, @@ -396,6 +402,18 @@ impl> Widget for Align { let result = [outer_area.x() + offset_x, outer_area.y() + offset_y, w, h]; result.into() }), + Self::X(_) => self.inner().layout(outer_area)?.map(|inner_area|{ + let [_, y, w, h] = inner_area.xywh(); + let offset_x = (outer_area.w() - w) / 2.into(); + let result = [outer_area.x() + offset_x, y, w, h]; + result.into() + }), + Self::Y(_) => self.inner().layout(outer_area)?.map(|inner_area|{ + let [x, _, w, h] = inner_area.xywh(); + let offset_y = (outer_area.h() / 2.into()) - (h / 2.into()); + let result = [x, outer_area.y() + offset_y, w, h]; + result.into() + }), Self::NW(_) => { todo!() }, Self::N(_) => { todo!() }, Self::NE(_) => { todo!() }, @@ -583,7 +601,7 @@ impl Outset { } /// Move origin point of drawing area -pub enum Offset { +pub enum Plus { /// Move origin to the right X(N, T), /// Move origin downwards @@ -592,7 +610,7 @@ pub enum Offset { XY(N, N, T), } -impl Offset { +impl Plus { fn inner (&self) -> &T { match self { Self::X(_, i) => i, Self::Y(_, i) => i, Self::XY(_, _, i) => i, } } @@ -604,7 +622,7 @@ impl Offset { } } -impl> Widget for Offset { +impl> Widget for Plus { type Engine = E; fn layout (&self, to: E::Area) -> Perhaps { Ok(self.inner().layout(to)?.map(|to|match *self { @@ -618,6 +636,42 @@ impl> Widget for Offset { } } +/// Move origin point of drawing area +pub enum Minus { + /// Move origin to the right + X(N, T), + /// Move origin downwards + Y(N, T), + /// Move origin to the right and downwards + XY(N, N, T), +} + +impl Minus { + fn inner (&self) -> &T { + match self { Self::X(_, i) => i, Self::Y(_, i) => i, Self::XY(_, _, i) => i, } + } + fn x (&self) -> N { + match self { Self::X(x, _) => *x, Self::Y(_, _) => N::default(), Self::XY(x, _, _) => *x } + } + fn y (&self) -> N { + match self { Self::X(_, _) => N::default(), Self::Y(y, _) => *y, Self::XY(_, y, _) => *y } + } +} + +impl> Widget for Minus { + type Engine = E; + fn layout (&self, to: E::Area) -> Perhaps { + Ok(self.inner().layout(to)?.map(|to|match *self { + Self::X(x, _) => [to.x().minus(x), to.y(), to.w(), to.h()], + Self::Y(y, _) => [to.x(), to.y().minus(y), to.w(), to.h()], + Self::XY(x, y, _) => [to.x().minus(x), to.y().minus(y), to.w(), to.h()] + }.into())) + } + fn render (&self, to: &mut E) -> Perhaps { + Ok(self.layout(to.area())?.map(|a|to.render_in(a, self.inner())).transpose()?.flatten()) + } +} + /// A component that may contain [Focusable] components. pub trait Focus : Widget + Handle { fn focus (&self) -> usize; diff --git a/crates/tek_core/src/lib.rs b/crates/tek_core/src/lib.rs index e26d00e2..cb1f541e 100644 --- a/crates/tek_core/src/lib.rs +++ b/crates/tek_core/src/lib.rs @@ -62,7 +62,16 @@ pub trait Number: Send + Sync + Copy + Div + Ord + PartialEq + Eq + Debug + Display + Default - + From {} + + From +{ + fn minus (self, other: Self) -> Self { + if self >= other { + self - other + } else { + 0.into() + } + } +} impl Number for T where T: Send + Sync + Copy diff --git a/crates/tek_core/src/test.rs b/crates/tek_core/src/test.rs index 01fe8c98..a6b6d144 100644 --- a/crates/tek_core/src/test.rs +++ b/crates/tek_core/src/test.rs @@ -14,51 +14,68 @@ impl Widget for TestArea { } #[test] -fn test_misc () -> Usually<()> { +fn test_0 () -> Usually<()> { let area: [u16;4] = [0, 0, 10, 10]; let test = TestArea(4, 4); assert_eq!(test.layout(area)?, Some([0, 0, 4, 4])); - assert_eq!(Align::Center(test).layout(area)?, - Some([3, 3, 4, 4])); - assert_eq!(Align::Center(Split::down(|add|{ - add(&test)?; - add(&test) - })).layout(area)?, - Some([3, 1, 4, 8])); - assert_eq!(Align::Center(Split::down(|add|{ - add(&Outset::XY(2, 2, test))?; - add(&test) - })).layout(area)?, - Some([2, 0, 6, 10])); - assert_eq!(Align::Center(Split::down(|add|{ - add(&Outset::XY(2, 2, test))?; - add(&Inset::XY(2, 2, test)) - })).layout(area)?, - Some([2, 1, 6, 8])); - assert_eq!(Split::down(|add|{ - add(&Outset::XY(2, 2, test))?; - add(&Inset::XY(2, 2, test)) - }).layout(area)?, - Some([0, 0, 6, 8])); - assert_eq!(Split::right(|add|{ - add(&Split::down(|add|{ - add(&Outset::XY(2, 2, test))?; - add(&Inset::XY(2, 2, test)) - }))?; - add(&Align::Center(TestArea(2 ,2))) - }).layout(area)?, - Some([0, 0, 8, 8])); + assert_eq!(Outset::X(1, test).layout(area)?, + Some([0, 0, 6, 4])); + assert_eq!(Align::X(test).layout(area)?, + Some([3, 0, 4, 4])); + assert_eq!(Align::X(Outset::X(1, test)).layout(area)?, + Some([2, 0, 6, 4])); + assert_eq!(Outset::X(1, Align::X(test)).layout(area)?, + Some([2, 0, 6, 4])); Ok(()) } +//#[test] +//fn test_misc () -> Usually<()> { + //let area: [u16;4] = [0, 0, 10, 10]; + //let test = TestArea(4, 4); + //assert_eq!(test.layout(area)?, + //Some([0, 0, 4, 4])); + //assert_eq!(Align::Center(test).layout(area)?, + //Some([3, 3, 4, 4])); + //assert_eq!(Align::Center(Split::down(|add|{ + //add(&test)?; + //add(&test) + //})).layout(area)?, + //Some([3, 1, 4, 8])); + //assert_eq!(Align::Center(Split::down(|add|{ + //add(&Outset::XY(2, 2, test))?; + //add(&test) + //})).layout(area)?, + //Some([2, 0, 6, 10])); + //assert_eq!(Align::Center(Split::down(|add|{ + //add(&Outset::XY(2, 2, test))?; + //add(&Inset::XY(2, 2, test)) + //})).layout(area)?, + //Some([2, 1, 6, 8])); + //assert_eq!(Split::down(|add|{ + //add(&Outset::XY(2, 2, test))?; + //add(&Inset::XY(2, 2, test)) + //}).layout(area)?, + //Some([0, 0, 6, 8])); + //assert_eq!(Split::right(|add|{ + //add(&Split::down(|add|{ + //add(&Outset::XY(2, 2, test))?; + //add(&Inset::XY(2, 2, test)) + //}))?; + //add(&Align::Center(TestArea(2 ,2))) + //}).layout(area)?, + //Some([0, 0, 8, 8])); + //Ok(()) +//} + //#[test] //fn test_offset () -> Usually<()> { //let area: [u16;4] = [50, 50, 100, 100]; //let test = TestArea(3, 3); - //assert_eq!(Offset::X(1, test).layout(area)?, Some([51, 50, 3, 3])); - //assert_eq!(Offset::Y(1, test).layout(area)?, Some([50, 51, 3, 3])); - //assert_eq!(Offset::XY(1, 1, test).layout(area)?, Some([51, 51, 3, 3])); + //assert_eq!(Plus::X(1, test).layout(area)?, Some([51, 50, 3, 3])); + //assert_eq!(Plus::Y(1, test).layout(area)?, Some([50, 51, 3, 3])); + //assert_eq!(Plus::XY(1, 1, test).layout(area)?, Some([51, 51, 3, 3])); //Ok(()) //} diff --git a/crates/tek_core/src/tui.rs b/crates/tek_core/src/tui.rs index 9f80aa97..2bdfbc21 100644 --- a/crates/tek_core/src/tui.rs +++ b/crates/tek_core/src/tui.rs @@ -487,7 +487,7 @@ where if h >= to.h() { return Ok(()) } - let area = Offset::Y(h, component as &dyn Widget).layout(to)?; + let area = Plus::Y(h, component as &dyn Widget).layout(to)?; if let Some([_, _, width, height]) = area { h += height; w = w.max(width) @@ -500,7 +500,7 @@ where if w >= to.w() { return Ok(()) } - let area = Offset::X(w, component as &dyn Widget).layout(to)?; + let area = Plus::X(w, component as &dyn Widget).layout(to)?; if let Some([_, _, width, height]) = area { w += width; h = h.max(height) @@ -522,7 +522,7 @@ where if h >= area.h() { return Ok(()) } - let area = Offset::Y(h, component as &dyn Widget).render(to)?; + let area = Plus::Y(h, component as &dyn Widget).render(to)?; if let Some([_, _, width, height]) = area { h += height; w = w.max(width) @@ -535,7 +535,7 @@ where if w >= area.w() { return Ok(()) } - let area = Offset::X(w, component as &dyn Widget).render(to)?; + let area = Plus::X(w, component as &dyn Widget).render(to)?; if let Some([_, _, width, height]) = area { w += width; h = h.max(height) @@ -578,31 +578,45 @@ where } } -impl> Widget for Inset { +impl> Content for Inset { type Engine = Tui; - fn layout (&self, to: [u16;4]) -> Perhaps<[u16;4]> { - Align::Center(match self { - Self::X(x, inner) => Shrink::X(*x + *x, inner as &dyn Widget), - Self::Y(y, inner) => Shrink::X(*y + *y, inner as &dyn Widget), - Self::XY(x, y, inner) => Shrink::XY(*x, *y, inner as &dyn Widget), - }).layout(to) - } - fn render (&self, to: &mut Tui) -> Perhaps<[u16;4]> { - Ok(self.layout(to.area())?.map(|a|to.render_in(a, self.inner())).transpose()?.flatten()) + fn content (&self) -> impl Widget { + match self { + Self::X(x, inner) => + Plus::X(*x, Shrink::X(*x + *x, Align::X(inner as &dyn Widget))), + Self::Y(y, inner) => + Plus::Y(*y, Shrink::X(*y + *y, Align::Y(inner as &dyn Widget))), + Self::XY(x, y, inner) => + Plus::XY(*x, *y, Shrink::XY(*x, *y, Align::Center(inner as &dyn Widget))), + } } } -impl> Widget for Outset { +//impl> Widget for Inset { + //type Engine = Tui; + //fn layout (&self, to: [u16;4]) -> Perhaps<[u16;4]> { + //match self { + //Self::X(x, inner) => Shrink::X(*x + *x, Align::Center(inner as &dyn Widget)), + //Self::Y(y, inner) => Shrink::X(*y + *y, Align::Center(inner as &dyn Widget)), + //Self::XY(x, y, inner) => Shrink::XY(*x, *y, Align::Center(inner as &dyn Widget)), + //}.layout(to) + //} + //fn render (&self, to: &mut Tui) -> Perhaps<[u16;4]> { + //Ok(self.layout(to.area())?.map(|a|to.render_in(a, self.inner())).transpose()?.flatten()) + //} +//} + +impl> Content for Outset { type Engine = Tui; - fn layout (&self, to: [u16;4]) -> Perhaps<[u16;4]> { - Align::Center(match self { - Self::X(x, inner) => Grow::X(*x + *x, inner as &dyn Widget), - Self::Y(y, inner) => Grow::X(*y + *y, inner as &dyn Widget), - Self::XY(x, y, inner) => Grow::XY(*x, *y, inner as &dyn Widget), - }).layout(to) - } - fn render (&self, to: &mut Tui) -> Perhaps<[u16;4]> { - Ok(self.layout(to.area())?.map(|a|to.render_in(a, self.inner())).transpose()?.flatten()) + fn content (&self) -> impl Widget { + match *self { + Self::X(x, ref inner) => + Grow::X(x + x, inner as &dyn Widget), + Self::Y(y, ref inner) => + Grow::Y(y + y, inner as &dyn Widget), + Self::XY(x, y, ref inner) => + Grow::XY(x, y, inner as &dyn Widget), + } } }