Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possible dead locking when spawning dialogs in the same app #11

Open
realtica opened this issue Apr 4, 2022 · 5 comments
Open

Possible dead locking when spawning dialogs in the same app #11

realtica opened this issue Apr 4, 2022 · 5 comments

Comments

@realtica
Copy link

realtica commented Apr 4, 2022

Hello, I'm trying to change the number of cols and rows at runtime, with:

                table.set_opts(TableOpts {
                    cell_align: enums::Align::Wrap,
                    editable: false,
                    rows: 55,
                    cols: 66,
                    ..Default::default()
                });

Is there any other way to change those?
I've tried with:
table.set_rows(55);
But, not working.

@MoAlyousef
Copy link
Collaborator

set_opts should work. Can you confirm this code works for you:

use fltk::{
    app, button,
    prelude::{GroupExt, WidgetExt, WidgetBase},
    window,
};
use fltk_table::{SmartTable, TableOpts};

fn main() {
    let app = app::App::default().with_scheme(app::Scheme::Gtk);
    let mut wind = window::Window::default().with_size(800, 600);

    let mut table = SmartTable::default()
    .with_size(790, 590)
    .center_of_parent()
    .with_opts(TableOpts {
        rows: 5,
        cols: 5,
        editable: true,
        ..Default::default()
    });
    let mut btn = button::Button::new(100, 400, 80, 30, "Click");
    wind.end();
    wind.show();

    table.set_cell_value(3, 4, "10");

    btn.set_callback(move |_| {
        table.set_opts(
            TableOpts {
                rows: 6,
                cols: 6,
                editable: true,
                ..Default::default()
            }
        );
    });

    app.run().unwrap();
}

You might need to call table.redraw() after it.

@realtica
Copy link
Author

realtica commented Apr 4, 2022

Hello, I not sure if the problem is the Dialog or the Table:
Steps to reproduce the error: Open the Dialog, close it then select an Item, and try to open the Dialog again.
Now, comment the table.set_opts(); And everything is OK

// use fltk::{app, button::Button, frame::Frame, group::Flex, prelude::*, window::Window};
use fltk::{prelude::*, *};
use fltk_evented::Listener;
use fltk_table::{SmartTable, TableOpts};

fn main() {
    let a = app::App::default();
    app::set_font_size(20);

    let mut wind = window::Window::default()
        .with_size(260, 400)
        .center_screen()
        .with_label("Counter");
    let flex = group::Flex::default()
        .with_size(220, 360)
        .center_of_parent()
        .column();
    let but_inc: Listener<_> = button::Button::default().with_label("Open dialog").into();
    let mut hold_browser: Listener<_> = browser::HoldBrowser::default().into();
    let mut table = SmartTable::default()
        .center_of_parent()
        .with_opts(TableOpts {
            rows: 30,
            cols: 15,
            editable: true,
            ..Default::default()
        });
    flex.end();
    wind.make_resizable(true);
    wind.end();
    wind.show();

    while a.wait() {
        if but_inc.triggered() {
            MyDialog::default();
            hold_browser.clear();
            hold_browser.add("item A");
            hold_browser.add("item b");
            hold_browser.add("item C");
        }
        if hold_browser.triggered() {
            table.set_opts(TableOpts {
                cell_align: enums::Align::Wrap,
                editable: false,
                rows: 30,
                cols: 15,
                ..Default::default()
            });
            for i in 0..30 {
                for j in 0..15 {
                    table.set_cell_value(i, j, &(i + j).to_string());
                }
            }
            table.redraw();
        }
        // frame.set_label(&val.to_string());
    }
    a.run().unwrap();
}

pub struct MyDialog {
    inp: input::Input,
}

impl MyDialog {
    pub fn default() -> Self {
        let mut win = window::Window::default()
            .with_size(400, 100)
            .with_label("My Dialog");
        let mut pack = group::Pack::default()
            .with_size(300, 30)
            .center_of_parent()
            .with_type(group::PackType::Horizontal);
        pack.set_spacing(20);
        frame::Frame::default()
            .with_size(80, 0)
            .with_label("Enter name:");
        let mut inp = input::Input::default().with_size(100, 0);
        let mut ok = button::Button::default().with_size(80, 0).with_label("Ok");
        pack.end();
        win.end();
        win.make_modal(true);
        win.show();
        ok.set_callback({
            let mut win = win.clone();
            move |_| {
                win.hide();
            }
        });
        while win.shown() {
            app::wait();
        }
        Self { inp }
    }
    pub fn value(&self) -> String {
        self.inp.value()
    }
}

@MoAlyousef
Copy link
Collaborator

MoAlyousef commented Apr 4, 2022

It might be that the table is dead locking, I'll have to investigate further.
Anyways, the issue is reproducible with the following:

use fltk::{prelude::*, *};
use fltk_table::{SmartTable, TableOpts};

fn main() {
    let a = app::App::default();
    app::set_font_size(20);

    let mut wind = window::Window::default()
        .with_size(260, 400)
        .center_screen()
        .with_label("Counter");
    let flex = group::Flex::default()
        .with_size(220, 360)
        .center_of_parent()
        .column();
    let mut but_inc= button::Button::default().with_label("Open dialog");
    let mut hold_browser= browser::HoldBrowser::default();
    let mut table = SmartTable::default()
        .center_of_parent()
        .with_opts(TableOpts {
            rows: 30,
            cols: 15,
            editable: true,
            ..Default::default()
        });
    flex.end();
    wind.make_resizable(true);
    wind.end();
    wind.show();

    but_inc.set_callback({
            let mut hold_browser = hold_browser.clone();
        move |_| {
        MyDialog::default();
        hold_browser.clear();
        hold_browser.add("item A");
        hold_browser.add("item b");
        hold_browser.add("item C");
    }});

    hold_browser.set_callback(move |_| {
        table.set_opts(TableOpts {
            cell_align: enums::Align::Wrap,
            editable: false,
            rows: 30,
            cols: 15,
            ..Default::default()
        });
        for i in 0..30 {
            for j in 0..15 {
                table.set_cell_value(i, j, &(i + j).to_string());
            }
        }
        table.redraw();
    });
    a.run().unwrap();
}

@MoAlyousef MoAlyousef changed the title change number of cols and rows at runtime Possible dead locking when spawning dialogs in the same app Apr 4, 2022
@realtica
Copy link
Author

realtica commented Apr 4, 2022

Thanks! I hope so much this will have a solution, because I don't know how to wrap variables.., that is the reason why fltk-evented help me a lot.

@MoAlyousef
Copy link
Collaborator

MoAlyousef commented Apr 9, 2022

I've tried replacing std::sync::Mutex with parking_lot::Mutex and enabling deadlock_detection and it seems there are no deadlocks. I think the issue is mainly is within FLTK but I can't pinpoint it. A workaround is to not create a window with each button trigger, instead spawn the dialog as a hidden window, and show it when the button is triggered:

use fltk::{prelude::*, *};
use fltk_evented::Listener;
use fltk_table::{SmartTable, TableOpts};

fn main() {
    let a = app::App::default();
    app::set_font_size(20);
    let mut dlg = MyDialog::default();

    let mut wind = window::Window::default()
        .with_size(260, 400)
        .center_screen()
        .with_label("Counter");
    let flex = group::Flex::default()
        .with_size(220, 360)
        .center_of_parent()
        .column();
    let but_inc: Listener<_> = button::Button::default().with_label("Open dialog").into();
    let mut hold_browser: Listener<_> = browser::HoldBrowser::default().into();
    let mut table = SmartTable::default()
        .center_of_parent()
        .with_opts(TableOpts {
            rows: 30,
            cols: 15,
            editable: true,
            ..Default::default()
        });
    flex.end();
    wind.make_resizable(true);
    wind.end();
    wind.show();

    while a.wait() {
        if but_inc.triggered() {
            dlg.show();
            while dlg.shown() {
                a.wait();
            }
            hold_browser.clear();
            hold_browser.add("item A");
            hold_browser.add("item b");
            hold_browser.add("item C");
        }
        if hold_browser.triggered() {
            table.set_opts(TableOpts {
                cell_align: enums::Align::Wrap,
                editable: false,
                rows: 30,
                cols: 15,
                ..Default::default()
            });
            for i in 0..30 {
                for j in 0..15 {
                    table.set_cell_value(i, j, &(i + j).to_string());
                }
            }
        }
    }
}

pub struct MyDialog {
    win: window::Window,
    inp: input::Input,
}

impl MyDialog {
    pub fn default() -> Self {
        let mut win = window::Window::default()
            .with_size(400, 100)
            .with_label("My Dialog");
        let mut pack = group::Pack::default()
            .with_size(300, 30)
            .center_of_parent()
            .with_type(group::PackType::Horizontal);
        pack.set_spacing(20);
        frame::Frame::default()
            .with_size(80, 0)
            .with_label("Enter name:");
        let mut inp = input::Input::default().with_size(100, 0);
        let mut ok = button::Button::default().with_size(80, 0).with_label("Ok");
        pack.end();
        win.end();
        win.make_modal(true);
        win.hide();
        ok.set_callback({
            let mut win = win.clone();
            move |_| {
                win.hide();
            }
        });
        Self { win, inp }
    }
    pub fn value(&self) -> String {
        self.inp.value()
    }
    pub fn show(&mut self) {
        self.win.show();
    }
    pub fn hide(&mut self) {
        self.win.hide();
    }
    pub fn shown(&self) -> bool {
        self.win.shown()
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants