gooey-rs 0.12.1

Tile-based UI library with audio support
Documentation
#![warn(unused_extern_crates)]

use env_logger;
use log;
use nsys::gl;
use gooey::*;

const LOG_FILENAME      : &str = "size-test.log";
const _FPS_MAX          : u64  = 360;
const fn log_level_default() -> log::LevelFilter {
 log::LevelFilter::Info
}

////////////////////////////////////////////////////////////////////////////////
//  application                                                               //
////////////////////////////////////////////////////////////////////////////////

#[derive(Debug)]
pub struct Myapp {
  interface : Option <Interface <Self, presentation::Opengl>>,
  running   : bool
}

impl Default for Myapp {
  fn default() -> Self {
    Self::new()
  }
}

impl Application for Myapp {
  type CallbackIds     = MycallbackIds;
  type AxisControls    = interface::controller::controls::Nil;
  type ButtonControls  = Mybuttoncontrols;
  type MotionControls  = interface::controller::controls::Nil;
  type PointerControls = interface::controller::controls::Nil;
  type SystemControls  = interface::controller::controls::Nil;
  type TextControls    = interface::controller::controls::Nil;
  type WheelControls   = interface::controller::controls::Nil;
}

//  controls
extend_control!{
  Mybuttoncontrols <interface::controller::controls::button::Release>
    (interface::controller::controls::button, Button)
  {
    Myquit => myquit
  }
}
//  callbacks
def_callback_ids! {
  MycallbackIds <Myapp> {
    Quit => Myapp::quit
  }
}

impl Myapp {
  fn new () -> Self {
    // init interface
    let interface = {
      use strum::EnumCount;
      use gooey::prelude::*;
      let mut interface = presentation::Opengl::make_interface();
      // debug: log gl info
      presentation::opengl::log_glium_info (
        &interface.presentation.inner().1.glium_display);
      // load mouse pointer
      const POINTER    : &[u8; 112] = include_bytes!("../pointer.png");
      const POINTER_ID : u16 =
        gl::render::resource::DefaultTexturePointerId::COUNT as u16;
      interface.presentation.load_pointer (POINTER_ID, POINTER, [0,0].into());
      // root screen frame
      // TODO: modify existing screen?
      let (_screen_id, screen_tiles_id) = {
        let root_id = interface.focused_element_id().clone();
        let appearances = AppearancesBuilder::default()
          .pointer (State::Focused, POINTER_ID.into())
          .build();
        let Element { view, .. } = {
          let mut screen = frame::screen::PixelBuilder::<Myapp>::default()
            .anchor      (Alignment::pixel())
            .appearances (appearances)
            .clear_color (Some (Color::WHITE).into())
            .dimensions  (interface.presentation.dimensions())
            .build_element();
          screen.focus();
          screen
        };
        let screen_view = Box::new (|v : &mut View| *v = view);
        let _ = interface.action (&root_id, Action::ModifyView (screen_view));
        let tiles_id = interface.presentation.screen_tiles_id().clone();
        {
          let bindings = bindings::Builder::<Myapp>::new()
            .buttons (vec![
              ( Mybuttoncontrols::Myquit.into(),
                input::button::Keycode::Q.into()
              ).into()
            ])
            .build();
          let tiles_controller = Box::new (move |c : &mut Controller|
            c.add_bindings (&bindings)
          );
          let _ = interface.action (&tiles_id,
            Action::ModifyController (tiles_controller));
        }
        (root_id, tiles_id)
      };

      let [window_id, _, _] = {
        let appearances = AppearancesBuilder::default()
          .style_fg (State::Enabled,  Color::YELLOW)
          .style_bg (State::Enabled,  Color::BLUE)
          .style_fg (State::Focused,  Color::YELLOW)
          .style_bg (State::Focused,  Color::BLUE)
          .build();
        let layout = layout::Free {
          anchor: Alignment::middle_center(),
          .. layout::Free::default_tile()
        };
        composite::window::Builder::new (
          &mut interface, &screen_tiles_id, "HELLO WORLD".into()
        ) .border (Border::eascii_lines())
          .frame_appearances (appearances)
          .layout (layout)
          .build()
      };

      let _ = interface.action (&window_id, Action::Focus);

      interface
    };
    //log::debug!("interface: {:#?}", interface);

    Myapp {
      interface:  Some (interface),
      running:    true
    }
  }

  #[inline]
  const fn is_running (&self) -> bool {
    self.running
  }

  #[inline]
  const fn interface (&self) -> &Interface <Self, presentation::Opengl> {
    self.interface.as_ref().unwrap()
  }

  fn update (&mut self) {
    log::trace!("update...");
    // update interface and handle events
    let mut interface = self.interface.take().unwrap();
    let events = interface.update();
    for (node_id, event) in events {
      match event {
        interface::model::Event::Submit (model) => {
          let callback =
            application::callback::<Myapp> (model.callback_id.unwrap());
          callback (self, model.component, node_id);
        }
        _ => {}
      }
    }
    interface.display();
    self.interface = Some (interface);
    log::trace!("...update");
  }

  //
  //  callbacks
  //
  fn quit (&mut self, _ : interface::model::Component, _ : tree::NodeId) {
    self.running = false;
  }
}

//
//  control funs
//
/// Submit the `Quit` callback
fn myquit (
  _             : &interface::controller::controls::button::Release,
  _elements     : &Tree <interface::Element>,
  node_id       : &tree::NodeId,
  action_buffer : &mut Vec <(tree::NodeId, interface::Action)>
) {
  log::trace!("myquit...");
  action_buffer.push (
    ( node_id.clone(),
      interface::Action::SubmitCallback (MycallbackIds::Quit.into()) ));
  log::trace!("...myquit");
}

////////////////////////////////////////////////////////////////////////////////
//  main                                                                      //
////////////////////////////////////////////////////////////////////////////////

fn main() {
  println!("gooey size test example: main...");

  report_sizes();

  // log init
  let log_file = Box::new (std::fs::File::create (LOG_FILENAME).unwrap());
  env_logger::Builder::new()
    .filter_level (log_level_default())
    .parse_default_env()
    .target (env_logger::Target::Pipe (log_file))
    .init();
  println!("logging output to {LOG_FILENAME:?}");
  log::info!("log begin...");

  // create application
  let mut myapp = Myapp::new();
  interface::log_elements_tree!(myapp.interface());
  interface::log_elements_tree_names!(myapp.interface());

  // main loop
  while myapp.is_running() {
    myapp.update();
    // TODO: fps limit
  }

  log::info!("...log end");
  println!("gooey size test example: ...main");
}