comp_state icon indicating copy to clipboard operation
comp_state copied to clipboard

Examples/Getting Started

Open wyhinton opened this issue 4 years ago • 1 comments

Hello,

Thanks for your work on this project, it seems promising!

I'm interested in using this crate with fltk-rs. As you state in the docs, comp_state is GUI agnostic, right? As in you can supply your own GUI framework and implement comp_state for your components.

I was wondering if the example in the docs might be elaborated on, or if we might have some more generic examples. For example, here are some questions I have about the example:

use comp_state::{topo, use_state};
#[topo::nested]
fn my_button() -> Node<Msg> {
    let count = use_state(|| 3);

    div![
        count,
        button![count.mouse_ev(Ev::Click, |count, _| *count += 1), "Click me"],
    ]
}
  • What is the div! macro?
  • How would we use our button in main()?
  • What are the necessary imports to make the example run?
  • Why does my_button return a Node<Msg> and what is the use of this return value?

wyhinton avatar Jun 25 '21 18:06 wyhinton

I managed to get an example working with fltk-rs:

use fltk::{app::*, frame::*, window::*, image::*, table::*, button::*, input::*, enums::*, group::*, prelude::*};
use comp_state::{topo, use_state, use_state_current, StateAccess, CloneState};

#[derive(Clone)]
pub struct Counter {
    count: StateAccess<i32>
}
pub struct GlobalEvents{}

impl GlobalEvents{
    pub const COUNTER_UPDATE: i32 = 41;
}

impl Counter {
    #[topo::nested]
    pub fn new(val: i32, id: &'static str) -> Self {
        //initialize counter state
        let count = use_state(|| val);
        let mut pack = Pack::new(0,0,100,150, None);
        pack.set_frame(FrameType::BorderFrame);
        let mut but_inc = Button::default().with_size(0, 40).with_label("+");
        but_inc.set_color(Color::Green);


        let mut frame = Frame::default()
        .with_size(0, 40)
        .with_label(&val.to_string());
        frame.set_frame(FrameType::FlatBox);
        frame.set_color(Color::Dark2);
        frame.set_label_color(Color::White);

        //decrement button
        let mut but_dec = Button::default().with_size(0, 40).with_label("-");
        but_dec.set_color(Color::Red);
        pack.end();

        let mut frame_cl = frame.clone();

        but_inc.set_callback(move|widg|{
            dbg!("got push ");
            let test = count.update(move|c|{
                *c +=1;
            });
            //now that our state is updated, do the frame callback
            frame_cl.do_callback();
            //emit an event that can be globally accessed
            let _ = app::handle_main(GlobalEvents::COUNTER_UPDATE);
        });     

        
        let mut frame_cl_2 = frame.clone();
        but_dec.set_callback(move|widg|{
            let test = count.update(move|c|{
                *c -=1;
            });
            frame_cl_2.do_callback();
            let _ = app::handle_main(GlobalEvents::COUNTER_UPDATE);
        });     

        frame.set_callback(move|widg|{
            dbg!("got frame callback");
            let test = CloneState::get(&count);
            dbg!(test);
            dbg!(format!("value at frame {}", test));
            widg.set_label(&test.to_string());
            widg.redraw();
        });


        Counter {
            count: count
        }

    }
    pub fn value(&self)->i32{
        return CloneState::get(&self.count);
    }
}


fn main() {
    let app = app::App::default();
    app::swap_frame_type(FrameType::FlatBox);

    let mut wind = Window::default().with_size(500, 300).with_label("Counter");
    let mut container = Pack::new(150,100, 200, 200, None);
    container.set_spacing(20);
    container.set_type(PackType::Horizontal);

    let c1 = Counter::new(0, "Counter 1");
    let c2 = Counter::new(10, "Counter 2");
    dbg!(c1.value());
    dbg!(c2.value());
    container.end();    

    let label_pack= Pack::new(100,60,300,40,"App State");
    let mut state_frame= Frame::default().with_label("Click a Counter!").with_size(300,20).with_pos(100, 20);

    //whenver counter is clicked, update the value    
    state_frame.handle(move |widg, ev| 
      if ev == GlobalEvents::COUNTER_UPDATE.into(){
          let state_str = format!("Counter 1 Val: {}, Counter 2 Val: {}", c1.value(), c2.value());
          widg.set_label(&state_str);
        true
    } else {
        false
    });
    state_frame.set_frame(FrameType::FlatBox);
    state_frame.set_color(Color::Green);
    label_pack.end();

    wind.end();
    wind.show();
    app.run().unwrap();
}

wyhinton avatar Jun 26 '21 03:06 wyhinton