1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
#[macro_use] extern crate log; extern crate chrono; extern crate termit_ion as termion; extern crate unicode_segmentation; pub mod color; pub mod command; pub mod geometry; pub mod graphics; pub mod input; pub mod mion; pub mod screen; pub mod widget; use self::widget::*; use crate::command::*; use crate::geometry::*; use crate::input::*; use crate::screen::Screen; use std::fmt; use std::io; use std::mem; use std::sync::mpsc::{Receiver, Sender, TryRecvError}; pub trait GUI { fn react(&mut self) -> io::Result<()>; } pub trait GrinApp { fn run(&mut self) -> io::Result<()>; fn quit(&mut self); } pub struct Grin<GUI, Root> { command: Sender<GrinCommand>, input: Receiver<Result<GrinInput, io::Error>>, quitting: bool, gui: GUI, size: Point, root: Root, inputs: Vec<GrinInput>, } impl<GUI, Root> Grin<GUI, Root> { pub fn new( gui: GUI, command: Sender<GrinCommand>, input: Receiver<Result<GrinInput, io::Error>>, root: Root, ) -> Self { Self { command, input, gui, root, quitting: false, size: Default::default(), inputs: vec![], } } } impl<GUI, Root> Grin<GUI, Root> where Root: Widget, { fn receive_inputs(&mut self) -> io::Result<()> { loop { let input = self.input.try_recv(); match input { Err(TryRecvError::Empty) => break, Err(TryRecvError::Disconnected) => { error!("ui disconnected"); self.quit_priv(); break; } Ok(input) => { match input { Ok(GrinInput::Resize(size)) => self.size = size, Ok(GrinInput::Key(KeyEvent { key: Key::Char(' '), .. })) => { info!("quit!"); self.quit_priv(); break; } _ => {} } self.log(format!("Input: {:?}", input)); if let Ok(input) = input { self.inputs.push(input); } } } } Ok(()) } fn handle_inputs(&mut self) -> io::Result<()> { let inputs = mem::replace(&mut self.inputs, vec![]); let mut screen = Screen::new(self.size); { self.root.arrange(screen.get_area()); self.root.consume(inputs); self.root.render(&mut screen)?; } for drawing in screen.into_iter() { self.command.send(GrinCommand::Draw(drawing)).map_err(|e| { io::Error::new( io::ErrorKind::Other, format!("Failed to send command, {}", e), ) })?; } Ok(()) } } impl<UI, Root> GrinApp for Grin<UI, Root> where UI: GUI, Root: Widget, { fn run(&mut self) -> io::Result<()> { self.send(GrinCommand::ShowCursor(false)); while !self.quitting { self.gui.react()?; self.receive_inputs()?; if !self.inputs.is_empty() { self.handle_inputs()?; } } Ok(()) } fn quit(&mut self) { self.quit_priv() } } impl<UI, Root> Grin<UI, Root> { fn quit_priv(&mut self) { self.quitting = true; self.send(GrinCommand::Quit); } fn send(&mut self, event: GrinCommand) { let dbg = format!("{:?}", event); self.command .send(event) .unwrap_or_else(|e| error!("unable to send grin event {:?}. {}", dbg, e)) } fn log<T: fmt::Display>(&mut self, what: T) { info!("{}", what) } } impl<UI, Root> Drop for Grin<UI, Root> { fn drop(&mut self) { self.quit_priv() } }