use{ std::sync::{Arc, RwLock}, cgmath::{Point2, Vector2}, termion::event::{Event, Key}, nested::{ core::{ View, ViewPort, InnerViewPort, OuterViewPort, Observer, ObserverExt, ObserverBroadcast, context::{ReprTree, Object, MorphismType, MorphismMode, Context}, port::{UpdateTask}}, index::{IndexView, IndexArea}, grid::{GridWindowIterator}, sequence::{SequenceView, SequenceViewExt}, vec::{VecBuffer}, integer::{RadixProjection, DigitEditor, PosIntEditor}, terminal::{ Terminal, TerminalStyle, TerminalAtom, TerminalCompositor, TerminalEvent, make_label, TerminalView, TerminalEditor, TerminalEditorResult }, string_editor::{StringEditor}, tree_nav::{TreeNav, TreeNavResult, TreeCursor, TerminalTreeEditor}, list::{SExprView, ListCursorMode, ListEditor, ListEditorStyle}, projection::ProjectionHelper }, crate::{ process::ProcessLauncher } }; pub struct Plot { limit: usize, data: Arc>, cast: Arc>>, proj_helper: ProjectionHelper<(), Self> } impl View for Plot { type Msg = IndexArea>; } impl IndexView> for Plot { type Item = TerminalAtom; fn get(&self, pt: &Point2) -> Option { if pt.y >= 0 { if let Some(cur_val) = self.data.get(&(pt.x as usize)) { if cur_val <= self.limit { if pt.y == (self.limit - cur_val) as i16 { return Some(TerminalAtom::from( if cur_val < 4 { 'o' } else if cur_val < 8 { 'O' } else { '*' } )); } } if pt.x > 0 { if let Some(prev_val) = self.data.get(&((pt.x-1) as usize)) { if ( pt.y > (self.limit - prev_val) as i16 && pt.y < (self.limit - cur_val) as i16 ) || ( pt.y < (self.limit - prev_val) as i16 && pt.y > (self.limit - cur_val) as i16 ) { return Some(TerminalAtom::from('.')); } } } } } None } fn area(&self) -> IndexArea> { IndexArea::Range( Point2::new(0,0) ..= Point2::new( self.data.len().unwrap_or(0) as i16, self.limit as i16 ) ) } } impl Plot { pub fn new( data_port: OuterViewPort>, out_port: InnerViewPort ) -> Arc> { let mut proj_helper = ProjectionHelper::new(out_port.0.update_hooks.clone()); let proj = Arc::new(RwLock::new( Plot { data: proj_helper.new_sequence_arg( (), data_port, |s: &mut Self, idx| { let val = s.data.get(idx).unwrap_or(0); if val > s.limit { s.limit = val; s.cast.notify(&s.area()); } else { s.cast.notify(&IndexArea::Range( Point2::new(*idx as i16, 0) ..= Point2::new(*idx as i16, s.limit as i16) )); } } ), limit: 0, cast: out_port.get_broadcast(), proj_helper } )); proj.write().unwrap().proj_helper.set_proj(&proj); out_port.set_view(Some(proj.clone())); proj } }