#![warn(unused_extern_crates)]
use std::sync::LazyLock;
use env_logger;
use log;
use nsys::gl;
use gooey::*;
const LOG_FILENAME : &str = "toggle-test.log";
const _FPS_MAX : u64 = 360;
const fn log_level_default() -> log::LevelFilter {
log::LevelFilter::Info
}
static MENU_BINDINGS : LazyLock <interface::controller::Bindings <Myapp>> =
LazyLock::new (||{
use gooey::prelude::*;
bindings::Builder::<Myapp>::new()
.buttons ([
( controls::button::Builtin::MenuNextItem.into(),
input::button::Keycode::Right.into()
),
( controls::button::Builtin::MenuPreviousItem.into(),
input::button::Keycode::Left.into()
),
( controls::button::Builtin::MenuNextItem.into(),
input::button::Keycode::Tab.into()
),
( controls::button::Builtin::MenuPreviousItem.into(),
input::Button::from (input::button::Keycode::Tab)
.with_modifiers (input::Modifiers::SHIFT)
)
].into_iter().map (Into::into).collect())
.build()
});
#[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;
}
extend_control!{
Mybuttoncontrols <interface::controller::controls::button::Release>
(interface::controller::controls::button, Button)
{
Myquit => myquit
}
}
def_callback_ids! {
MycallbackIds <Myapp> {
Quit => Myapp::quit
}
}
impl Myapp {
fn new () -> Self {
let interface = {
use strum::EnumCount;
use gooey::prelude::*;
let mut interface = presentation::Opengl::make_interface();
presentation::opengl::log_glium_info (
&interface.presentation.inner().1.glium_display);
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());
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 ([
( Mybuttoncontrols::Myquit.into(),
input::button::Keycode::Q.into()
),
( controls::button::Builtin::ActivatePointer.into(),
input::button::Mouse::Mouse1.into()
)
].into_iter().map (Into::into).collect())
.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 selection = Selection { loop_: true, .. Selection::default() };
let actions = menu::Builder::new (
interface.elements(), &screen_tiles_id
) .bindings (&*MENU_BINDINGS)
.selection (selection)
.build_actions();
let _ = interface.actions (actions);
}
let switch_builder = switch::Builder::default()
.style_fg ((switch::State::On, State::Enabled), Color::CYAN)
.style_bg ((switch::State::On, State::Enabled), Color::WHITE)
.style_fg ((switch::State::Off, State::Enabled), Color::WHITE)
.style_bg ((switch::State::Off, State::Enabled), Color::CYAN)
.style_fg ((switch::State::On, State::Focused), Color::RED)
.style_bg ((switch::State::On, State::Focused), Color::WHITE)
.style_fg ((switch::State::Off, State::Focused), Color::WHITE)
.style_bg ((switch::State::Off, State::Focused), Color::RED)
.toggle (true);
let bindings = bindings::Builder::<Myapp>::new()
.buttons (vec![
( controls::button::Builtin::ButtonPush.into(),
input::button::Keycode::Enter.into()
).into()
])
.build();
{ let layout = {
let anchor = Alignment::middle_center();
let offset = Offset::default_absolute();
let size = Size {
width: 3.into(),
height: 3.into()
};
layout::Variant::from (layout::Free { anchor, offset, size })
};
let switch = switch_builder.clone().label_on ("X".to_string()).build();
let builder = button::Builder::new (
interface.elements(), &screen_tiles_id
) .bindings (&bindings)
.frame_border (Border::default())
.frame_layout (layout.into())
.switch (switch);
let _ = build_and_return_node_id!(interface, builder);
}
{ let layout = {
let anchor = Alignment::middle_center();
let offset = Offset::default_absolute();
let size = Size {
width: 4.into(),
height: 3.into()
};
layout::Variant::from (layout::Free { anchor, offset, size })
};
let switch = switch_builder.clone()
.label_off ("\u{FF} ".to_string())
.label_on (" \u{FF}".to_string())
.build();
let builder = button::Builder::new (
interface.elements(), &screen_tiles_id
) .bindings (&bindings)
.frame_border (Border::default())
.frame_layout (layout.into())
.switch (switch);
let _ = build_and_return_node_id!(interface, builder);
}
{ let layout = {
let anchor = Alignment::middle_center();
let offset = Offset::default_absolute();
let size = Size {
width: 3.into(),
height: 4.into()
};
layout::Variant::from (layout::Free { anchor, offset, size })
};
let switch = switch_builder
.label_off (" \n\u{FF}".to_string())
.label_on ("\u{FF}\n ".to_string())
.build();
let builder = button::Builder::new (
interface.elements(), &screen_tiles_id
) .bindings (&bindings)
.frame_border (Border::default())
.frame_layout (layout.into())
.switch (switch);
let _ = build_and_return_node_id!(interface, builder);
}
{ let anchor = Alignment::middle_center();
let actions = frame::free::rearrange_absolute (
interface.elements(), &screen_tiles_id, anchor, (3, 1),
Orientation::Vertical, 1, false
);
let _ = interface.actions (actions);
}
let _ = interface.action (&screen_tiles_id, Action::Focus);
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...");
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");
}
fn quit (&mut self, _ : interface::model::Component, _ : tree::NodeId) {
self.running = false;
}
}
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");
}
fn main() {
println!("gooey size test example: main...");
report_sizes();
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...");
let mut myapp = Myapp::new();
interface::log_elements_tree!(myapp.interface());
interface::log_elements_tree_names!(myapp.interface());
while myapp.is_running() {
myapp.update();
}
log::info!("...log end");
println!("gooey size test example: ...main");
}