transform and components
This commit is contained in:
+52
-7
@@ -1,15 +1,20 @@
|
|||||||
use std::any::Any;
|
use std::{
|
||||||
|
any::{Any, TypeId},
|
||||||
|
collections::HashMap,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
events::EventManager,
|
events::EventManager,
|
||||||
extensions::{Extension, ExtensionManager},
|
extensions::{Extension, ExtensionManager},
|
||||||
render_scope::RenderScope,
|
render_scope::RenderScope,
|
||||||
|
style::Transform,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod events;
|
pub mod events;
|
||||||
pub mod extensions;
|
pub mod extensions;
|
||||||
pub mod macros;
|
pub mod macros;
|
||||||
pub mod render_scope;
|
pub mod render_scope;
|
||||||
|
pub mod style;
|
||||||
pub mod text;
|
pub mod text;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
|
||||||
@@ -21,8 +26,39 @@ pub trait Element {
|
|||||||
fn as_any(self: Box<Self>) -> Box<dyn Any>;
|
fn as_any(self: Box<Self>) -> Box<dyn Any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait Component {
|
||||||
|
fn as_any(&self) -> &dyn Any;
|
||||||
|
fn as_any_mut(&mut self) -> &mut dyn Any;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Widget(pub Box<dyn Element>, HashMap<TypeId, Box<dyn Component>>);
|
||||||
|
|
||||||
|
impl Widget {
|
||||||
|
pub fn component<C: Component + 'static>(&mut self, c: C) -> &mut Self {
|
||||||
|
self.1.entry(c.type_id()).or_insert_with(|| Box::new(c));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_component<C: Component + 'static>(&mut self, c: C) -> &mut Self {
|
||||||
|
self.1.insert(c.type_id(), Box::new(c));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get<C: Component + 'static>(&self) -> Option<&C> {
|
||||||
|
self.1
|
||||||
|
.get(&TypeId::of::<C>())
|
||||||
|
.and_then(|c| c.as_any().downcast_ref::<C>())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_mut<C: Component + 'static>(&mut self) -> Option<&mut C> {
|
||||||
|
self.1
|
||||||
|
.get_mut(&TypeId::of::<C>())
|
||||||
|
.and_then(|c| c.as_any_mut().downcast_mut::<C>())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Screen {
|
pub struct Screen {
|
||||||
pub elements: Vec<Box<dyn Element>>,
|
pub elements: Vec<Widget>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Screen {
|
impl Screen {
|
||||||
@@ -32,8 +68,10 @@ impl Screen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw<E: Element + 'static>(&mut self, element: E) {
|
pub fn draw<E: Element + 'static>(&mut self, element: E) -> &mut Widget {
|
||||||
self.elements.push(Box::new(element));
|
self.elements
|
||||||
|
.push(Widget(Box::new(element), HashMap::new()));
|
||||||
|
self.elements.last_mut().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(
|
pub fn run(
|
||||||
@@ -41,10 +79,11 @@ impl Screen {
|
|||||||
events: &mut EventManager,
|
events: &mut EventManager,
|
||||||
extensions: &mut ExtensionManager,
|
extensions: &mut ExtensionManager,
|
||||||
) -> std::io::Result<()> {
|
) -> std::io::Result<()> {
|
||||||
let mut scope = RenderScope {};
|
let mut scope = RenderScope::new();
|
||||||
|
|
||||||
for elem in &mut self.elements {
|
for elem in &mut self.elements {
|
||||||
elem.init(events);
|
elem.component(Transform::new());
|
||||||
|
elem.0.init(events);
|
||||||
}
|
}
|
||||||
|
|
||||||
extensions.init(self, events);
|
extensions.init(self, events);
|
||||||
@@ -52,8 +91,14 @@ impl Screen {
|
|||||||
loop {
|
loop {
|
||||||
extensions.tick_start(self, events);
|
extensions.tick_start(self, events);
|
||||||
|
|
||||||
|
utils::clear().unwrap();
|
||||||
for elem in &mut self.elements {
|
for elem in &mut self.elements {
|
||||||
elem.render(&mut scope);
|
scope.clear();
|
||||||
|
elem.0.render(&mut scope);
|
||||||
|
if let Some(t) = elem.get() {
|
||||||
|
scope.set_transform(t);
|
||||||
|
}
|
||||||
|
scope.draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
extensions.tick_end(self, events);
|
extensions.tick_end(self, events);
|
||||||
|
|||||||
@@ -35,3 +35,53 @@ macro_rules! event {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! component {
|
||||||
|
($name:ident) => {
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct $name;
|
||||||
|
|
||||||
|
impl $crate::Component for $name {
|
||||||
|
fn as_any(&self) -> &dyn std::any::Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
($name:ident {$($inner:tt)*}) => {
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct $name {
|
||||||
|
$($inner)*
|
||||||
|
}
|
||||||
|
|
||||||
|
impl $crate::Component for $name {
|
||||||
|
fn as_any(&self) -> &dyn std::any::Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
($name:ident ($($inner:tt)*)) => {
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct $name ($($inner)*);
|
||||||
|
|
||||||
|
impl $crate::Component for $name {
|
||||||
|
fn as_any(&self) -> &dyn std::any::Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
+4
-2
@@ -1,6 +1,7 @@
|
|||||||
use osui::{
|
use osui::{
|
||||||
events::EventManager,
|
events::EventManager,
|
||||||
extensions::{keypress::KeyPressExtension, ExtensionManager},
|
extensions::{keypress::KeyPressExtension, ExtensionManager},
|
||||||
|
style::Transform,
|
||||||
Screen,
|
Screen,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -8,10 +9,11 @@ fn main() {
|
|||||||
let mut screen = Screen::new();
|
let mut screen = Screen::new();
|
||||||
let mut extensions = ExtensionManager::new();
|
let mut extensions = ExtensionManager::new();
|
||||||
let mut events = EventManager::new();
|
let mut events = EventManager::new();
|
||||||
|
|
||||||
extensions.add(KeyPressExtension);
|
extensions.add(KeyPressExtension);
|
||||||
|
|
||||||
screen.draw("Hello, World".to_string());
|
screen
|
||||||
|
.draw("Hello, World".to_string())
|
||||||
|
.component(Transform::new());
|
||||||
|
|
||||||
screen.run(&mut events, &mut extensions).unwrap();
|
screen.run(&mut events, &mut extensions).unwrap();
|
||||||
}
|
}
|
||||||
|
|||||||
+50
-2
@@ -1,7 +1,55 @@
|
|||||||
pub struct RenderScope {}
|
use crate::{
|
||||||
|
style::{RawTransform, Transform},
|
||||||
|
utils,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum RenderMethod {
|
||||||
|
Text(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct RenderScope {
|
||||||
|
transform: RawTransform,
|
||||||
|
render_stack: Vec<RenderMethod>,
|
||||||
|
width: u16,
|
||||||
|
height: u16,
|
||||||
|
parent_width: u16,
|
||||||
|
parent_height: u16,
|
||||||
|
}
|
||||||
|
|
||||||
impl RenderScope {
|
impl RenderScope {
|
||||||
|
pub fn new() -> RenderScope {
|
||||||
|
RenderScope {
|
||||||
|
transform: RawTransform::new(),
|
||||||
|
render_stack: Vec::new(),
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
parent_width: 0,
|
||||||
|
parent_height: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_transform(&mut self, transform: &Transform) {
|
||||||
|
transform.use_dimensions(&mut self.transform);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn draw_text(&mut self, text: &str) {
|
pub fn draw_text(&mut self, text: &str) {
|
||||||
println!("{text}");
|
self.render_stack.push(RenderMethod::Text(text.to_string()));
|
||||||
|
let (w, h) = utils::str_size(text);
|
||||||
|
self.width = std::cmp::max(self.width, w);
|
||||||
|
self.height = std::cmp::max(self.height, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw(&self) {
|
||||||
|
for m in &self.render_stack {
|
||||||
|
match m {
|
||||||
|
RenderMethod::Text(t) => {
|
||||||
|
println!("\x1b[{};{}H{t}", self.transform.y + 1, self.transform.x + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear(&mut self) {
|
||||||
|
self.render_stack.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
use crate::component;
|
||||||
|
|
||||||
|
pub struct RawTransform {
|
||||||
|
pub x: u16,
|
||||||
|
pub y: u16,
|
||||||
|
pub width: u16,
|
||||||
|
pub height: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum Position {
|
||||||
|
Center,
|
||||||
|
Const(u16),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum Dimension {
|
||||||
|
Auto,
|
||||||
|
Const(u16),
|
||||||
|
}
|
||||||
|
|
||||||
|
component!(Transform {
|
||||||
|
pub x: Position,
|
||||||
|
pub y: Position,
|
||||||
|
pub width: Dimension,
|
||||||
|
pub height: Dimension,
|
||||||
|
});
|
||||||
|
|
||||||
|
impl Transform {
|
||||||
|
pub fn new() -> Transform {
|
||||||
|
Transform {
|
||||||
|
x: Position::Const(0),
|
||||||
|
y: Position::Const(0),
|
||||||
|
width: Dimension::Auto,
|
||||||
|
height: Dimension::Auto,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn center() -> Transform {
|
||||||
|
Transform {
|
||||||
|
x: Position::Center,
|
||||||
|
y: Position::Center,
|
||||||
|
width: Dimension::Auto,
|
||||||
|
height: Dimension::Auto,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn position(x: Position, y: Position) -> Transform {
|
||||||
|
Transform {
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
width: Dimension::Auto,
|
||||||
|
height: Dimension::Auto,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn use_dimensions(&self, raw: &mut RawTransform) {
|
||||||
|
self.width.use_dimension(&mut raw.width);
|
||||||
|
self.height.use_dimension(&mut raw.height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RawTransform {
|
||||||
|
pub fn new() -> RawTransform {
|
||||||
|
RawTransform {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Dimension {
|
||||||
|
pub fn use_dimension(&self, r: &mut u16) {
|
||||||
|
match self {
|
||||||
|
Dimension::Auto => {}
|
||||||
|
Dimension::Const(n) => *r = *n,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user