redox-os / orbtk

The Rust UI-Toolkit.
MIT License
3.78k stars 188 forks source link

Newbie question about TextBox widget #238

Closed thivmcthiv closed 4 years ago

thivmcthiv commented 4 years ago

So I am basically trying to make a gui for a command line aes and blowfish encryptor/decryptor, and I have a textbox where the user would input the path to a file that will be encrypted with a random key and nonce, but I don't know how to access the file path that was inputed in the textbox. I am relatively new to rust, so I'm not very familiar with how docs.rs works, but I tried my best to find the answer there, but I still can't figure out how to do this.

I gather that I have to have

Button::new()
    .text("Encrypt with AES")
    .on_click(
    move |_,id| {
        // Set MainViewState.action to Some(Action::AesEncrypt(*value here*))
    }
    )
.build(ctx)

and there should be a way to do this using the update function for implementation of State for MainViewState right? which would possibly look something like this based kindof on how the widgets example did things:

use orbtk::prelude::*;

#[derive(Debug, Clone)]
pub struct Aes {
    pub key: String,
    pub nonce: String,
    pub entity: Entity,
    pub path: String
}

#[derive(Debug, Clone)]
pub struct Blowfish {
    pub key: String,
    pub entity: Entity
}

#[derive(Debug, Clone)]
pub enum Action {
    AesEncrypt(Aes),
    Blowfish(Blowfish)
    //add feilds for decrypting
}

#[derive(AsAny)]
pub struct MainViewState {
    action: Option<Action>
}

impl Default for MainViewState {
    fn default() -> Self {
        MainViewState { action: None }
    }
}

impl State for MainViewState {
    fn update(&mut self, _: &mut Registry, _: &mut Context) {
        if self.action.is_some() {
            match &self.action {
                Some(a) => {
                    match a {
                        Action::AesEncrypt(aes) => {
                            //spawn a thread to do the enrypting
                            println!("encrypting with aes");
                        }
                        Action::Blowfish(blowfish) => {
                            //spawn a thread to do the encrypting
                            println!("encrypting with blowfish");
                        }
                    }
                }
                None => {
                    //this code should never be executed
                    println!("no action")
                }
            }
        }
    }
}

What is the best way to access the text inside of a textbox in a situation like this?

kivimango commented 4 years ago

First, you have to set an id to your Textbox e.g.:

TextBox::new()
.id("my_textbox")
.build(ctx)

Then, in your init() method of MainViewSate you save the Entity of your Textbox to the MainViewState like: (based on the TextBox id): let self.textbox = ctx.entity_of_child("my_textbox) (this code assumes that the TextBox is a child of the MainView).

Then, you can do in update(): let txt_box_value = ctx.get_widget(self.textbox).get::<String16>("text"); (give me the value of the text property of the widget identified by self.textbox as a type of String16)

thivmcthiv commented 4 years ago

and what if the text box isn't a child of MainView?

thivmcthiv commented 4 years ago

How could you get the Entity for a child of a child? I know there is a way to get the BuildContext for a Context with the .build_context() method, but can I get the Context for an Entity, so that I could do something like this:

let self.textbox = ctx.entity_of_child("my_container").context().entity_of_child("my_textbox")

where the .context() method returns the Context for the Entity of the child my_container, and then we could call entity_of_child() again, to get the Entity of a child of my_container. Is there a way to do this?

kivimango commented 4 years ago

How could you get the Entity for a child of a child? I know there is a way to get the BuildContext for a Context with the .build_context() method, but can I get the Context for an Entity, so that I could do something like this:

let self.textbox = ctx.entity_of_child("my_container").context().entity_of_child("my_textbox")

where the .context() method returns the Context for the Entity of the child my_container, and then we could call entity_of_child() again, to get the Entity of a child of my_container. Is there a way to do this?

  1. save the entity of the first child into the state struct in init(): self.first_child = ctx.entity_of_child("my_container");

  2. change the context into the first child in update(): Then you can access the children of the first child.

    ctx.entity = first_child;
    let second_child = ctx.entity_of_child(first_child);

or if you make a gist i can contribute to it

thivmcthiv commented 4 years ago

That worked perfectly! thank you so much for the help!