First display!

This commit is contained in:
ClementTsang 2021-12-12 20:51:09 -05:00
parent 58f78731b3
commit 37b3d235b9
6 changed files with 54 additions and 18 deletions

View File

@ -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;

View File

@ -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)
}

View File

@ -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)
}
}

View File

@ -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

View File

@ -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);

View File

@ -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(())
}