gooey/presentation/
mod.rs

1//! Presentation layer.
2//!
3//! The `Presentation` trait defines required methods for getting input and
4//! displaying `View` data.
5//!
6//! A concrete `Presentation` type instance is a member of the main `Interface`
7//! structure.
8//!
9//! Calling `Interface::update()` will run `Presentation::get_input()` and
10//! pass the `Input` to the focused `Controller` component for handling.
11//!
12//! Any changes to `View` component data will result in `Display` events being
13//! generated and calling `Interface::display()` will run
14//! `Presentation::display_view()` with those `Display` values collected in the
15//! last update.
16
17use crate::{Application, Interface, Tree};
18use crate::tree::NodeId;
19use crate::interface::{view, Element, View};
20
21pub mod headless;
22pub use headless::Headless;
23
24// graphics
25// TODO: crossterm backend
26#[cfg(feature="curses")]
27#[cfg_attr(docsrs, doc(cfg(feature="curses")))]
28pub mod curses;
29#[cfg(feature="curses")]
30#[cfg_attr(docsrs, doc(cfg(feature="curses")))]
31pub use self::curses::Curses;
32#[cfg(feature="opengl")]
33#[cfg_attr(docsrs, doc(cfg(feature="opengl")))]
34pub mod opengl;
35#[cfg(feature="opengl")]
36#[cfg_attr(docsrs, doc(cfg(feature="opengl")))]
37pub use self::opengl::Opengl;
38// audio
39#[cfg(feature="fmod")]
40#[cfg_attr(docsrs, doc(cfg(feature="fmod")))]
41pub mod fmod;
42#[cfg(feature="fmod")]
43#[cfg_attr(docsrs, doc(cfg(feature="fmod")))]
44pub use self::fmod::Fmod;
45
46/// Implements a means of getting input and displaying view data
47pub trait Presentation {
48  fn with_root (root : View, id : NodeId) -> Self;
49  /// Overridable constructor allowing the presentation backend to do custom
50  /// initialization of the interface, e.g. initializing the root screen element
51  /// of a graphical interface.
52  fn make_interface <A : Application> () -> Interface <A, Self>
53    where Self : Sized
54  {
55    Interface::with_root (Element::default())
56  }
57  fn get_input (&mut self, input_buffer : &mut Vec <view::Input>);
58  fn display_view <V : AsRef <View>> (&mut self,
59    view_tree      : &Tree <V>,
60    display_values : std::vec::Drain <(NodeId, view::Display)>);
61}
62
63/// Marker trait for backends with graphics capabilities
64pub trait Graphics : Presentation { }
65/// Marker trait for backends with audio capabilities
66pub trait Audio    : Presentation { }
67/// Get the graphics component from a capable backend
68pub trait HasGraphics <G : Graphics> {
69  fn graphics (&mut self) -> &mut G;
70}
71/// A presentation backend with both graphics and audio components
72// TODO: HasAudio trait ?
73#[derive(Debug)]
74pub struct Composite <G : Graphics, A : Audio> {
75  pub graphics    : G,
76  pub audio       : A,
77  display_buffers : (
78    Vec <(NodeId, view::Display)>, Vec <(NodeId, view::Display)> )
79}
80impl <G, A> Presentation for Composite <G, A> where
81  G : Graphics,
82  A : Audio
83{
84  fn with_root (root : View, id : NodeId) -> Self {
85    let graphics        = G::with_root (root.clone(), id.clone());
86    let audio           = A::with_root (root, id);
87    let display_buffers = (vec![], vec![]);
88    Composite { graphics, audio, display_buffers }
89  }
90  /// Uses the graphical presentation backend to create an initialized interface
91  fn make_interface <APP : Application> () -> Interface <APP, Self>
92    where Self : Sized
93  {
94    let graphical = G::make_interface();
95    let root      = graphical.root_node().data().view.clone();
96    let root_id   = graphical.root_id().clone();
97    graphical.swap_presentation (|graphics| {
98      let audio           = A::with_root (root, root_id);
99      let display_buffers = (vec![], vec![]);
100      Composite { graphics, audio, display_buffers }
101    })
102  }
103  fn get_input (&mut self, input_buffer : &mut Vec <view::Input>) {
104    self.graphics.get_input (input_buffer);
105    self.audio.get_input (input_buffer);
106  }
107  fn display_view <V : AsRef <View>> (&mut self,
108    view_tree      : &Tree <V>,
109    display_values : std::vec::Drain <(NodeId, view::Display)>
110  ) {
111    self.display_buffers.0 = display_values.collect();
112    self.display_buffers.1 = self.display_buffers.0.clone();
113    self.graphics.display_view (view_tree, self.display_buffers.0.drain(..));
114    self.audio.display_view    (view_tree, self.display_buffers.1.drain(..));
115  }
116}
117
118impl <G, A> HasGraphics <G> for Composite <G, A> where
119  G : Graphics,
120  A : Audio
121{
122  fn graphics (&mut self) -> &mut G {
123    &mut self.graphics
124  }
125}
126
127impl <G : Graphics> HasGraphics <G> for G {
128  fn graphics (&mut self) -> &mut G {
129    self
130  }
131}