1#![doc(
31 html_logo_url = "https://raw.githubusercontent.com/deinstapel/cursive-multiplex/master/assets/cursive-multiplex.png"
32)]
33
34#[macro_use]
35extern crate log;
36
37mod actions;
38mod error;
39mod id;
40mod node;
41mod path;
42
43use cursive_core::direction::{Absolute, Direction};
44use cursive_core::event::{AnyCb, Event, EventResult, Key, MouseButton, MouseEvent};
45use cursive_core::view::{CannotFocus, Selector, View, ViewNotFound};
46use cursive_core::{Printer, Vec2};
47pub use error::*;
48pub use id::Id;
49use node::Node;
50pub use path::Path;
51use std::collections::VecDeque;
52use std::convert::TryFrom;
53
54#[derive(Debug, PartialEq, Clone)]
55enum Orientation {
56 Vertical,
57 Horizontal,
58}
59
60pub struct Mux {
62 tree: indextree::Arena<Node>,
63 root: indextree::NodeId,
64 default_split_ratio: f32,
65 focus: indextree::NodeId,
66 history: VecDeque<(indextree::NodeId, indextree::NodeId, Absolute)>,
67 history_length: usize,
68 invalidated: bool,
69 focus_up: Event,
70 focus_down: Event,
71 focus_left: Event,
72 focus_right: Event,
73 resize_left: Event,
74 resize_right: Event,
75 resize_up: Event,
76 resize_down: Event,
77 zoom: Event,
78 zoomed: bool,
79}
80
81impl View for Mux {
82 fn draw(&self, printer: &Printer) {
83 debug!("Current Focus: {}", self.focus);
84 debug!("Is the current pane focused? {}", self.zoomed);
85 if self.zoomed {
87 if let Some(focused) = self.tree.get(self.focus) {
88 focused.get().draw(printer);
89 }
90 } else {
91 self.rec_draw(printer, self.root)
92 }
93 }
94
95 fn needs_relayout(&self) -> bool {
96 self.invalidated
97 }
98
99 fn required_size(&mut self, constraint: Vec2) -> Vec2 {
100 constraint
101 }
102
103 fn layout(&mut self, constraint: Vec2) {
104 self.invalidated = false;
105 if self.zoomed {
106 if let Some(focused) = self.tree.get_mut(self.focus) {
107 focused.get_mut().layout_view(constraint);
108 }
109 } else {
110 self.rec_layout(self.root, constraint, Vec2::zero());
111 }
112 }
113
114 fn take_focus(&mut self, _source: Direction) -> Result<EventResult, CannotFocus> {
115 Ok(EventResult::consumed())
116 }
117
118 fn focus_view(&mut self, _: &Selector) -> Result<EventResult, ViewNotFound> {
119 Ok(EventResult::consumed())
120 }
121
122 fn call_on_any<'a>(&mut self, slct: &Selector, cb: AnyCb<'a>) {
123 let nodes: Vec<Id> = self.root.descendants(&self.tree).collect();
124 for node in nodes {
125 if let Some(node_c) = self.tree.get_mut(node) {
126 node_c.get_mut().call_on_any(slct, cb);
127 }
128 }
129 }
130
131 fn on_event(&mut self, evt: Event) -> EventResult {
132 let mut result = EventResult::Ignored;
134 if let Event::Mouse {
135 offset,
136 position,
137 event: MouseEvent::Press(MouseButton::Left),
138 } = evt
139 {
140 if let Some(off_pos) = position.checked_sub(offset) {
141 if let Some(pane) = self.clicked_pane(off_pos) {
142 if let Ok(res) = self.tree.get_mut(pane).unwrap().get_mut().take_focus() {
143 if self.focus != pane {
144 result = res;
145 self.focus = pane;
146 self.invalidated = true;
147 }
148 }
149 }
150 }
151 }
152 let result = result.and(
153 self.tree
154 .get_mut(self.focus)
155 .unwrap()
156 .get_mut()
157 .on_event(evt.clone(), self.zoomed),
158 );
159 match result {
160 EventResult::Ignored => match evt {
161 _ if self.focus_left == evt => self.move_focus(Absolute::Left),
162 _ if self.focus_right == evt => self.move_focus(Absolute::Right),
163 _ if self.focus_up == evt => self.move_focus(Absolute::Up),
164 _ if self.focus_down == evt => self.move_focus(Absolute::Down),
165 _ if self.resize_left == evt => self.resize(Absolute::Left),
166 _ if self.resize_right == evt => self.resize(Absolute::Right),
167 _ if self.resize_up == evt => self.resize(Absolute::Up),
168 _ if self.resize_down == evt => self.resize(Absolute::Down),
169 _ if self.zoom == evt => self.zoom_focus(),
170 _ => EventResult::Ignored,
171 },
172 result => result,
173 }
174 }
175}
176
177impl Mux {
178 pub fn new() -> Self {
186 let mut new_tree = indextree::Arena::new();
187 let new_root = new_tree.new_node(Node::new_empty(Orientation::Horizontal, 0.5));
188 Mux {
189 tree: new_tree,
190 root: new_root,
191 default_split_ratio: 0.5,
192 history: VecDeque::new(),
193 history_length: 50,
194 invalidated: true,
195 focus: new_root,
196 focus_up: Event::Alt(Key::Up),
197 focus_down: Event::Alt(Key::Down),
198 focus_left: Event::Alt(Key::Left),
199 focus_right: Event::Alt(Key::Right),
200 resize_left: Event::Ctrl(Key::Left),
201 resize_right: Event::Ctrl(Key::Right),
202 resize_up: Event::Ctrl(Key::Up),
203 resize_down: Event::Ctrl(Key::Down),
204 zoom: Event::CtrlChar('x'),
205 zoomed: false,
206 }
207 }
208
209 pub fn active_view(&self) -> Option<&dyn View> {
210 self.tree
211 .get(self.focus)
212 .map(|node| node.get())
213 .and_then(|node| node.view.as_deref())
214 }
215
216 pub fn active_view_mut(&mut self) -> Option<&mut dyn View> {
217 self.tree
218 .get_mut(self.focus)
219 .map(|node| node.get_mut())
220 .and_then(|node| node.view.as_deref_mut())
221 }
222
223 pub fn with_default_split_ratio<T: Into<f32>>(mut self, split: T) -> Self {
226 self.default_split_ratio = split.into().clamp(0.0, 1.0);
227 self.tree.get_mut(self.root).unwrap().get_mut().split_ratio = self.default_split_ratio;
228 self
229 }
230
231 pub fn set_default_split_ratio<T: Into<f32>>(&mut self, split: T) {
234 self.default_split_ratio = split.into().clamp(0.0, 1.0);
235 self.tree.get_mut(self.root).unwrap().get_mut().split_ratio = self.default_split_ratio;
236 }
237
238 pub fn with_move_focus_up(mut self, evt: Event) -> Self {
240 self.focus_up = evt;
241 self
242 }
243 pub fn with_move_focus_down(mut self, evt: Event) -> Self {
245 self.focus_down = evt;
246 self
247 }
248 pub fn with_move_focus_left(mut self, evt: Event) -> Self {
250 self.focus_left = evt;
251 self
252 }
253 pub fn with_move_focus_right(mut self, evt: Event) -> Self {
255 self.focus_right = evt;
256 self
257 }
258 pub fn with_resize_up(mut self, evt: Event) -> Self {
260 self.resize_up = evt;
261 self
262 }
263 pub fn with_resize_down(mut self, evt: Event) -> Self {
265 self.resize_down = evt;
266 self
267 }
268 pub fn with_resize_left(mut self, evt: Event) -> Self {
270 self.resize_left = evt;
271 self
272 }
273 pub fn with_resize_right(mut self, evt: Event) -> Self {
275 self.resize_right = evt;
276 self
277 }
278
279 pub fn with_zoom(mut self, evt: Event) -> Self {
281 self.zoom = evt;
282 self
283 }
284
285 pub fn set_move_focus_up(&mut self, evt: Event) {
287 self.focus_up = evt;
288 }
289 pub fn set_move_focus_down(&mut self, evt: Event) {
291 self.focus_down = evt;
292 }
293 pub fn set_move_focus_left(&mut self, evt: Event) {
295 self.focus_left = evt;
296 }
297 pub fn set_move_focus_right(&mut self, evt: Event) {
299 self.focus_right = evt;
300 }
301 pub fn set_resize_up(&mut self, evt: Event) {
303 self.resize_up = evt;
304 }
305 pub fn set_resize_down(&mut self, evt: Event) {
307 self.resize_down = evt;
308 }
309 pub fn set_resize_left(&mut self, evt: Event) {
311 self.resize_left = evt;
312 }
313 pub fn set_resize_right(&mut self, evt: Event) {
315 self.resize_right = evt;
316 }
317
318 pub fn set_zoom(&mut self, evt: Event) {
320 self.zoom = evt;
321 }
322
323 pub fn with_focus(mut self, id: Id) -> Self {
325 let nodes: Vec<Id> = self.root.descendants(&self.tree).collect();
326 if nodes.contains(&id) {
327 self.focus = id;
328 self.invalidated = true;
329 }
330 self
331 }
332
333 pub fn set_focus(&mut self, id: Id) {
335 let nodes: Vec<Id> = self.root.descendants(&self.tree).collect();
336 if nodes.contains(&id) {
337 self.focus = id;
338 self.invalidated = true;
339 }
340 }
341
342 pub fn focus(&self) -> Id {
356 self.focus
357 }
358
359 fn rec_layout(&mut self, root: Id, constraint: Vec2, start_point: Vec2) {
360 match root.children(&self.tree).count() {
361 1 => self.rec_layout(
362 root.children(&self.tree).next().unwrap(),
363 constraint,
364 start_point,
365 ),
366 2 => {
367 let left = root.children(&self.tree).next().unwrap();
368 let right = root.children(&self.tree).last().unwrap();
369 let const1;
370 let const2;
371 let root_data = &self.tree.get(root).unwrap().get();
372 let orit = root_data.orientation.clone();
373 match orit {
374 Orientation::Horizontal => {
375 const1 = Vec2::new(
376 Mux::add_offset(
377 (constraint.x as f32 * root_data.split_ratio) as usize,
378 root_data.split_ratio_offset,
379 ),
380 constraint.y,
381 );
382 const2 = Vec2::new(
383 {
384 let size = Mux::add_offset(
385 (constraint.x as f32 * root_data.split_ratio) as usize,
386 -root_data.split_ratio_offset,
387 );
388 if constraint.x % 2 == 0 {
389 match size.checked_sub(1) {
390 Some(res) => res,
391 None => size,
392 }
393 } else {
394 size
395 }
396 },
397 constraint.y,
398 );
399 }
400 Orientation::Vertical => {
401 const1 = Vec2::new(
402 constraint.x,
403 Mux::add_offset(
404 (constraint.y as f32 * root_data.split_ratio) as usize,
405 root_data.split_ratio_offset,
406 ),
407 );
408 const2 = Vec2::new(constraint.x, {
409 let size = Mux::add_offset(
410 (constraint.y as f32 * root_data.split_ratio) as usize,
411 -root_data.split_ratio_offset,
412 );
413 if constraint.y % 2 == 0 {
414 match size.checked_sub(1) {
415 Some(res) => res,
416 None => size,
417 }
418 } else {
419 size
420 }
421 });
422 }
423 }
424 self.tree
425 .get_mut(root)
426 .unwrap()
427 .get_mut()
428 .layout_view(constraint);
429 self.rec_layout(left, const1, start_point);
430 self.rec_layout(
431 right,
432 const2,
433 match orit {
434 Orientation::Vertical => start_point + const1.keep_y(),
435 Orientation::Horizontal => start_point + const1.keep_x(),
436 },
437 );
438 }
439 0 => {
440 self.tree
441 .get_mut(root)
442 .unwrap()
443 .get_mut()
444 .layout_view(constraint);
445 self.tree
446 .get_mut(root)
447 .unwrap()
448 .get_mut()
449 .set_pos(start_point);
450 }
451 _ => debug!("Illegal Number of Child Nodes"),
452 }
453 }
454
455 fn add_offset(split: usize, offset: i16) -> usize {
456 if offset < 0 {
457 match usize::try_from(offset.abs()) {
458 Ok(u) => {
459 if split < u {
460 split
461 } else {
462 split - u
463 }
464 }
465 Err(_) => split,
466 }
467 } else {
468 match usize::try_from(offset) {
469 Ok(u) => split + u,
470 Err(_) => split,
471 }
472 }
473 }
474
475 fn rec_draw(&self, printer: &Printer, root: Id) {
476 match root.children(&self.tree).count() {
477 1 => self.rec_draw(printer, root.children(&self.tree).next().unwrap()),
478 2 => {
479 debug!("Print Children Nodes");
480 let left = root.children(&self.tree).next().unwrap();
481 let right = root.children(&self.tree).last().unwrap();
482 let printer1;
483 let printer2;
484 let root_data = &self.tree.get(root).unwrap().get();
485 match root_data.orientation {
486 Orientation::Horizontal => {
487 printer1 = printer.cropped(Vec2::new(
488 Mux::add_offset(
489 (printer.size.x as f32 * root_data.split_ratio) as usize,
490 root_data.split_ratio_offset,
491 ),
492 printer.size.y,
493 ));
494 printer2 = printer
495 .offset(Vec2::new(
496 Mux::add_offset(
497 (printer.size.x as f32 * root_data.split_ratio) as usize,
498 root_data.split_ratio_offset,
499 ) + 1,
500 0,
501 ))
502 .cropped(Vec2::new(
503 Mux::add_offset(
504 (printer.size.x as f32 * root_data.split_ratio) as usize,
505 -root_data.split_ratio_offset,
506 ),
507 printer.size.y,
508 ));
509 }
510 Orientation::Vertical => {
511 printer1 = printer.cropped(Vec2::new(
512 printer.size.x,
513 Mux::add_offset(
514 (printer.size.y as f32 * root_data.split_ratio) as usize,
515 root_data.split_ratio_offset,
516 ),
517 ));
518 printer2 = printer
519 .offset(Vec2::new(
520 0,
521 Mux::add_offset(
522 (printer.size.y as f32 * root_data.split_ratio) as usize,
523 root_data.split_ratio_offset,
524 ) + 1,
525 ))
526 .cropped(Vec2::new(
527 printer.size.x,
528 Mux::add_offset(
529 (printer.size.y as f32 * root_data.split_ratio) as usize,
530 -root_data.split_ratio_offset,
531 ),
532 ));
533 }
534 }
535 match self.tree.get(root).unwrap().get().orientation {
536 Orientation::Vertical => {
537 if printer.size.y > 1 {
538 printer.print_hline(
539 Vec2::new(
540 0,
541 Mux::add_offset(
542 (printer.size.y as f32 * root_data.split_ratio) as usize,
543 root_data.split_ratio_offset,
544 ),
545 ),
546 printer.size.x,
547 "─",
548 );
549 }
550 }
551 Orientation::Horizontal => {
552 if printer.size.x > 1 {
553 printer.print_vline(
554 Vec2::new(
555 Mux::add_offset(
556 (printer.size.x as f32 * root_data.split_ratio) as usize,
557 root_data.split_ratio_offset,
558 ),
559 0,
560 ),
561 printer.size.y,
562 "│",
563 );
564 }
565 }
566 }
567 self.rec_draw(&printer1, left);
568 self.rec_draw(&printer2, right);
569 }
570 0 => {
571 self.tree
572 .get(root)
573 .unwrap()
574 .get()
575 .draw(&printer.focused(self.focus == root));
576 }
577 _ => debug!("Illegal Number of Child Nodes"),
578 }
579 }
580}
581
582impl Default for Mux {
583 fn default() -> Self {
584 Mux::new()
585 }
586}
587
588#[cfg(test)]
589mod tree {
590 use super::Mux;
591 use cursive_core::event::{Event, EventResult, Key};
592 use cursive_core::traits::View;
593 use cursive_core::views::DummyView;
594
595 #[test]
596 fn test_remove() {
597 let mut test_mux = Mux::new();
599 let node1 = test_mux.add_below(DummyView, test_mux.root).unwrap();
600 let node2 = test_mux.add_below(DummyView, node1).unwrap();
601 let node3 = test_mux.add_below(DummyView, node2).unwrap();
602
603 print_tree(&test_mux);
604 test_mux.remove_id(node3).unwrap();
605 print_tree(&test_mux);
606 match test_mux.remove_id(node3) {
607 Ok(_) => {
608 print_tree(&test_mux);
609 println!("Delete should have removed: {}", node3);
610 assert!(false);
611 }
612 Err(_) => {}
613 }
614 }
615
616 #[test]
617 fn test_switch() {
618 let mut mux = Mux::new();
619 let node1 = mux.add_right_of(DummyView, mux.root).unwrap();
620 let node2 = mux.add_right_of(DummyView, node1).unwrap();
621 let node3 = mux.add_left_of(DummyView, node2).unwrap();
622
623 mux.switch_views(node1, node3).unwrap();
624 }
625
626 #[test]
627 fn test_zoom() {
628 let mut mux = Mux::new();
629 let node1 = mux.add_right_of(DummyView, mux.root).unwrap();
630 let node2 = mux.add_right_of(DummyView, node1).unwrap();
631 let _node3 = mux.add_left_of(DummyView, node2).unwrap();
632
633 match mux.on_event(mux.zoom.clone()) {
634 EventResult::Consumed(_) => {}
635 EventResult::Ignored => assert!(false),
636 }
637 }
638
639 #[test]
640 fn test_nesting() {
641 println!("Nesting Test");
642
643 let mut mux = Mux::new();
644
645 let mut nodes = Vec::new();
646
647 for _ in 0..10 {
648 print_tree(&mux);
649 match mux.add_right_of(
650 DummyView,
651 if let Some(x) = nodes.last() {
652 *x
653 } else {
654 mux.root
655 },
656 ) {
657 Ok(node) => {
658 nodes.push(node);
659 }
660 Err(_) => {
661 assert!(false);
662 }
663 }
664 match mux.add_right_of(DummyView, *nodes.last().unwrap()) {
665 Ok(node) => {
666 nodes.push(node);
667 }
668 Err(_) => {
669 assert!(false);
670 }
671 }
672 }
673
674 for node in nodes.iter() {
675 mux.focus = *node;
676 direction_test(&mut mux);
677 }
678 }
679
680 fn print_tree(mux: &Mux) {
681 print!("Current Tree: ");
682 for node in mux.root.descendants(&mux.tree) {
683 print!("{},", node);
684 }
685 println!();
686 }
687
688 fn direction_test(mux: &mut Mux) {
689 mux.on_event(Event::Key(Key::Up));
691 mux.on_event(Event::Key(Key::Left));
692 mux.on_event(Event::Key(Key::Down));
693 mux.on_event(Event::Key(Key::Right));
694 mux.on_event(Event::Key(Key::Up));
695 mux.on_event(Event::Key(Key::Left));
696 mux.on_event(Event::Key(Key::Left));
697 mux.on_event(Event::Key(Key::Down));
698 mux.on_event(Event::Key(Key::Right));
699 mux.on_event(Event::Key(Key::Up));
700 mux.on_event(Event::Key(Key::Left));
701 }
702}