summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClementTsang <cjhtsang@uwaterloo.ca>2021-12-12 20:51:09 -0500
committerClementTsang <cjhtsang@uwaterloo.ca>2021-12-12 20:51:09 -0500
commit37b3d235b998cebf864fa31d1f5ee533cf1cc6e7 (patch)
treead2f7a6c810fa47b7479db4bc846165282508203
parent58f78731b33242a576939c9b6a5ea9db9504bee2 (diff)
First display!
-rw-r--r--src/bin/main.rs2
-rw-r--r--src/tuice/application.rs16
-rw-r--r--src/tuice/component/base/flex.rs2
-rw-r--r--src/tuice/context.rs8
-rw-r--r--src/tuice/layout/build_layout.rs8
-rw-r--r--src/tuice/runtime.rs36
6 files changed, 54 insertions, 18 deletions
diff --git a/src/bin/main.rs b/src/bin/main.rs
index f39ef474..3fcc9ce5 100644
--- a/src/bin/main.rs
+++ b/src/bin/main.rs
@@ -102,7 +102,7 @@ fn main() -> Result<()> {
// TODO: [Threads, Panic] Make this close all the child threads too!
panic::set_hook(Box::new(|info| panic_hook(info)));
- tuice::launch_with_application(app, receiver);
+ tuice::launch_with_application(app, receiver, &mut terminal)?; // FIXME: Move terminal construction INSIDE
// I think doing it in this order is safe...
*thread_termination_lock.lock().unwrap() = true;
diff --git a/src/tuice/application.rs b/src/tuice/application.rs
index 6fd2e34b..540c8a3c 100644
--- a/src/tuice/application.rs
+++ b/src/tuice/application.rs
@@ -1,5 +1,7 @@
use std::{fmt::Debug, sync::mpsc::Receiver};
+use tui::Terminal;
+
use super::{
runtime::{self, RuntimeEvent},
Element, Event,
@@ -32,9 +34,13 @@ pub trait Application: Sized {
fn global_event_handler(&mut self, event: Event, messages: &mut Vec<Self::Message>) {}
}
-/// Launches some application with tuice.
-pub fn launch_with_application<A: Application + 'static>(
- application: A, receiver: Receiver<RuntimeEvent<A::Message>>,
-) {
- runtime::launch(application, receiver);
+/// Launches some application with tuice. Note this will take over the calling thread.
+pub fn launch_with_application<A, B>(
+ application: A, receiver: Receiver<RuntimeEvent<A::Message>>, terminal: &mut Terminal<B>,
+) -> anyhow::Result<()>
+where
+ A: Application + 'static,
+ B: tui::backend::Backend,
+{
+ runtime::launch(application, receiver, terminal)
}
diff --git a/src/tuice/component/base/flex.rs b/src/tuice/component/base/flex.rs
index 4faa2757..fc7c8844 100644
--- a/src/tuice/component/base/flex.rs
+++ b/src/tuice/component/base/flex.rs
@@ -49,7 +49,7 @@ impl<'a, Message> FlexElement<'a, Message> {
}
pub(crate) fn layout(&self, bounds: Bounds, node: &mut LayoutNode) -> Size {
- todo!()
+ self.element.layout(bounds, node)
}
}
diff --git a/src/tuice/context.rs b/src/tuice/context.rs
index 43540e44..f40742e3 100644
--- a/src/tuice/context.rs
+++ b/src/tuice/context.rs
@@ -8,7 +8,13 @@ pub struct DrawContext<'a> {
}
impl<'a> DrawContext<'_> {
- pub(crate) fn new() {}
+ /// Creates a new [`DrawContext`], with the offset set to `(0, 0)`.
+ pub(crate) fn root(root: &'a LayoutNode) -> DrawContext<'a> {
+ DrawContext {
+ current_node: root,
+ current_offset: (0, 0),
+ }
+ }
pub(crate) fn rect(&self) -> Rect {
self.current_node.rect
diff --git a/src/tuice/layout/build_layout.rs b/src/tuice/layout/build_layout.rs
index 241bfd9e..d9fdddae 100644
--- a/src/tuice/layout/build_layout.rs
+++ b/src/tuice/layout/build_layout.rs
@@ -2,13 +2,13 @@ use tui::layout::Rect;
use crate::tuice::{Bounds, Element, LayoutNode, TmpComponent};
-pub fn build_layout_tree<Message>(area: Rect, root: &Element<'_, Message>) -> LayoutNode {
- let mut root_layout_node = LayoutNode::from_rect(area);
+pub fn build_layout_tree<Message>(rect: Rect, root: &Element<'_, Message>) -> LayoutNode {
+ let mut root_layout_node = LayoutNode::from_rect(rect);
let bounds = Bounds {
min_width: 0,
min_height: 0,
- max_width: area.width,
- max_height: area.height,
+ max_width: rect.width,
+ max_height: rect.height,
};
let _ = root.layout(bounds, &mut root_layout_node);
diff --git a/src/tuice/runtime.rs b/src/tuice/runtime.rs
index e5d1048b..1666c21d 100644
--- a/src/tuice/runtime.rs
+++ b/src/tuice/runtime.rs
@@ -1,10 +1,10 @@
use std::sync::mpsc::Receiver;
-use tui::layout::Rect;
+use tui::{backend::Backend, layout::Rect, Terminal};
use crate::tuice::Status;
-use super::{Application, Event, TmpComponent};
+use super::{build_layout_tree, Application, Element, Event, TmpComponent};
#[derive(Clone, Copy, Debug)]
pub enum RuntimeEvent<Message> {
@@ -13,10 +13,15 @@ pub enum RuntimeEvent<Message> {
Custom(Message),
}
-pub(crate) fn launch<A: Application + 'static>(
- mut application: A, receiver: Receiver<RuntimeEvent<A::Message>>,
-) {
+pub(crate) fn launch<A, B>(
+ mut application: A, receiver: Receiver<RuntimeEvent<A::Message>>, terminal: &mut Terminal<B>,
+) -> anyhow::Result<()>
+where
+ A: Application + 'static,
+ B: Backend,
+{
let mut user_interface = application.view();
+ draw(&mut user_interface, terminal)?;
while !application.is_terminated() {
if let Ok(event) = receiver.recv() {
@@ -38,7 +43,7 @@ pub(crate) fn launch<A: Application + 'static>(
}
user_interface = application.view();
- // FIXME: Draw!
+ draw(&mut user_interface, terminal)?;
}
RuntimeEvent::Custom(message) => {
application.update(message);
@@ -48,6 +53,8 @@ pub(crate) fn launch<A: Application + 'static>(
height: _,
} => {
user_interface = application.view();
+ // FIXME: Also nuke any cache and the like...
+ draw(&mut user_interface, terminal)?;
}
}
} else {
@@ -56,4 +63,21 @@ pub(crate) fn launch<A: Application + 'static>(
}
application.destroy();
+
+ Ok(())
+}
+
+fn draw<M, B>(user_interface: &mut Element<'_, M>, terminal: &mut Terminal<B>) -> anyhow::Result<()>
+where
+ B: Backend,
+{
+ terminal.draw(|frame| {
+ let rect = frame.size();
+ let layout = build_layout_tree(rect, &user_interface);
+ let context = super::DrawContext::root(&layout);
+
+ user_interface.draw(context, frame);
+ })?;
+
+ Ok(())
}