GithubHelp home page GithubHelp logo

egui-modal's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

egui-modal's Issues

ModalState should be derived as Deserialize

Simple error occurs when egaui serde feature is on:

error[E0277]: the trait bound `for<'a> ModalState: serde::de::Deserialize<'a>` is not satisfied
   --> /home/xxx/.cargo/registry/src/github.com-1ecc6299db9ec823/egui-modal-0.1.6/src/modal.rs:128:20
    |
128 |         ctx.data().get_persisted(id).unwrap_or_default()
    |                    ^^^^^^^^^^^^^ the trait `for<'a> serde::de::Deserialize<'a>` is not implemented for `ModalState`
    |
    = help: the following other types implement trait `serde::de::Deserialize<'de>`:
              &'a [u8]
              &'a std::path::Path
              &'a str
              ()
              (T0, T1)
              (T0, T1, T2)
              (T0, T1, T2, T3)
              (T0, T1, T2, T3, T4)
            and 225 others
    = note: required because of the requirements on the impl of `SerializableAny` for `ModalState`
note: required by a bound in `IdTypeMap::get_persisted`
   --> /home/xxx/.cargo/registry/src/github.com-1ecc6299db9ec823/egui-0.19.0/src/util/id_type_map.rs:370:29
    |
370 |     pub fn get_persisted<T: SerializableAny>(&mut self, id: Id) -> Option<T> {
    |                             ^^^^^^^^^^^^^^^ required by this bound in `IdTypeMap::get_persisted`

setting a default modal height

continuing discussion from #5 and using solution from #5 (comment)

basic implementation looks like this:

image

not too desirable, ideally the contents of the frame would be centered and the title and buttons would be at top and bottom, respectively

Focus is not bounded in modal window

When a modal window is open, the user should not be able to interact with elements outside of this window.

Reproducing:

  • cargo run --example example
  • Open modal
  • Use tab key to change focus

[suggestion] bevy_egui support

I was hoping I could drop this into a bevy_egui app, which I am building to learn bevy (perhaps I'm the wrong person to get very detailed into what people would want!). But this indicates:

error[E0308]: mismatched types
--> src/menu.rs:100:14
|
100 | Modal::new(contexts.ctx_mut(), LOAD_MAP_MODAL_TITLE).show(|ui| {
| ---------- ^^^^^^^^^^^^^^^^^^ expected &Context, found &mut Context
| |
| arguments to this function are incorrect
|
= note: bevy_egui::egui::Context and egui::context::Context have similar names, but are actually distinct types

new() should only take id as parameter.

I am making a desktop using egui and really like your modal library, but I am having a problem. The new() for Modal takes ctx and id as parameters. This is causing me some problems, as I am defining different parts of UI in different files.

Say I have a module (a file) app.rs in which I define eframe::App which has the update() and all. And I have different files for different sections of the app like a settings dialog for which I want to use Modal.

Now in app I have,

pub struct App {
    dark_mode: bool,
    is_side_panel_open: bool,
    is_window_fullscreen: bool,
    waveform_viewer: WaveformViewer,
    preferences_dialog: PreferencesDialog,
}

where WaveformViewer is a egui::Window and I have a new() method for all sections like this and are initialized this like,

impl App {
    pub fn new() -> Self {
        Self {
            dark_mode: true,
            is_side_panel_open: false,
            is_window_fullscreen: false,
            waveform_viewer: WaveformViewwer::new(),
            preferences_dialog: PreferencesDialog::new(),
        }
    }

    // other methods..
}

now in order to call new() from the PreferencesDialog I need to have something like this,

pub struct PreferencesDialog {
    dialog: Modal,
    is_open: bool,
}

which I can initialize like this,

impl PreferencesDialog {
    pub fn new(ctx: &egui::Context) -> Self {
        Self {
            dialog: Modal::new(ctx, "preferences_dialog"),
            is_open: false,
        }
    }

now here comes the problem.. if I don't take ctx as an argument in new() I can't have dialog as a data member of PreferencesDialog and if I do I can't call it in my App::new().

But say I don't do any of this, then I have to initialize PreferencesDialog::new(ctx, id) directly in update and I won't be able to query other data and/or methods from PreferencesDialog outside update().

I think perhaps you should have a set_ctx() instead of directly taking ctx as an argument in the new().

Calling `Modal::close()` inside a `Ui::input_mut()` results in a deadlock

In my application, I wanted to allow keyboard shortcuts to interact with/close the modal as well. This was my first attempt:

let modal = Modal::new(ui.ctx(), "confirmation_modal");
// shows the dialog if needed, as tracked by modal-internal state
modal.show(|ui| {
    // <snip> add other UI...
    modal.buttons(ui, |ui| {
        if confirmation_modal.button(ui, "Cancel (N)").clicked() {
            state.confirmation_modal_state.result = Some(ConfirmationAction::DoNothing);
        }
        if confirmation_modal.button(ui, "Delete New (Del)").clicked() {
            state.confirmation_modal_state.result = Some(ConfirmationAction::DeleteNew);
        }
        if confirmation_modal.button(ui, "Move Anyway (M)").clicked() {
            state.confirmation_modal_state.result = Some(ConfirmationAction::CopyAnyway);
        }
        if confirmation_modal
            .button(ui, "Replace Existing (R)")
            .clicked()
        {
            state.confirmation_modal_state.result = Some(ConfirmationAction::ReplaceOld);
        }
    });

    ui.input_mut(|input| {
        if input.consume_key(Modifiers::CTRL, Key::R) {
            state.confirmation_modal_state.result = Some(ConfirmationAction::ReplaceOld);
            modal.close();
        } else if input.consume_key(Modifiers::CTRL, Key::M) {
            state.confirmation_modal_state.result = Some(ConfirmationAction::CopyAnyway);
            modal.close();
        } else if input.consume_key(Modifiers::CTRL, Key::Delete) {
            state.confirmation_modal_state.result = Some(ConfirmationAction::DeleteNew);
            modal.close();
        } else if input.consume_key(Modifiers::CTRL, Key::N) {
            state.confirmation_modal_state.result = Some(ConfirmationAction::DoNothing);
            modal.close();
        }
    });
});

However, this caused deadlocks when any of the consume_key calls returned true. I worked around this issue by changing to the following:

    let should_close = ui.input_mut(|input| {
        if input.consume_key(Modifiers::CTRL, Key::R) {
            state.confirmation_modal_state.result = Some(ConfirmationAction::ReplaceOld);
            true
        } else if input.consume_key(Modifiers::CTRL, Key::M) {
            state.confirmation_modal_state.result = Some(ConfirmationAction::CopyAnyway);
            true
        } else if input.consume_key(Modifiers::CTRL, Key::Delete) {
            state.confirmation_modal_state.result = Some(ConfirmationAction::DeleteNew);
            true
        } else if input.consume_key(Modifiers::CTRL, Key::N) {
            state.confirmation_modal_state.result = Some(ConfirmationAction::DoNothing);
            true
        } else {
            false
        }
    });

    if should_close {
        modal.close();
    }

I believe this is because modal.close(); internally writes to the context IdTypeMap, which is also locked by input_mut.

I'm not sure what the best solution is, unfortunately. Adding documentation to Modal::close could be helpful, but easily miss-able.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.