Dialogs tripping up in Vala
Question: I've been experimenting with Vala programming recently. I've got pretty
extensive experience programming in other languages, but in recent years have
stuck mainly with scripting languages like Python, Tcl and Perl. I was
impressed by the clean look of Elementary OS, which is what started me looking
into Vala, and I must say that my first impressions are very positive.
However, I have hit a snag with Dialog programming, which I thought more
experienced Vala programmers might be able to help with. In my latest test
program I use a Dialog-based routine to obtain a value (getYesNo), and then
display a string describing that value to screen using another Dialog-based
routine (showDialog). Both routines work correctly when used independently,
but when used together as described the display event is held back until a
second call is made to the value-obtaining routine. This sounds like the sort
of situation that a call to "flush_events" would solve in Perl or Tcl. But how
can I deal with it in Vala? Or is there a way to avoid it happening in the
first place?

Code:

    
    
    using Gtk;
    using Posix;
    
    public class DialogTestWindow: ApplicationWindow {
    
        private int RESPONSE;
        private Toolbar tbMain = new Toolbar();
        private ToolButton bAbout = new ToolButton(new Image.from_icon_name
            ("help-about",IconSize.SMALL_TOOLBAR),null);
        private ToolButton bDoIt = new ToolButton(new Image.from_icon_name
            ("media-record",IconSize.SMALL_TOOLBAR),null);
        private ToolButton bQuit = new ToolButton(new Image.from_icon_name
            ("application-exit",IconSize.SMALL_TOOLBAR),null);
    
        internal DialogTestWindow(DialogTest app) {
            Object(application: app, title: "DialogTest");
            this.window_position = WindowPosition.CENTER;
            this.set_default_size(720,480);
    // ---- Set up Toolbar ----------------------------------------------------
            tbMain.get_style_context().add_class(STYLE_CLASS_PRIMARY_TOOLBAR);
            bQuit.is_important = true;
            bQuit.clicked.connect(onQuit);
            tbMain.add(bQuit);
            bAbout.is_important = true;
            bAbout.clicked.connect(onAbout);
            tbMain.add(bAbout);
            bDoIt.is_important = true;
            bDoIt.clicked.connect(onDoIt);
            tbMain.add(bDoIt);
    // ---- Pack Toolbar etc into vBox on main window -------------------------
            Box vbMain = new Box(Orientation.VERTICAL,0);
            vbMain.pack_start(tbMain,false,true,0);
            this.add(vbMain);
            this.show_all();
            printf("Started\n");
        }
    // ==== getYesNo ==========================================================
        private void getYesNo(string message) {
            Dialog dialog = new Dialog.with_buttons
                ("Get",this,DialogFlags.MODAL,
                Stock.YES,ResponseType.YES,Stock.NO,ResponseType.NO,null);
            var content = dialog.get_content_area();
    // warning: assignment from incompatible pointer type
    // [enabled by default]
            Label label = new Label(message);
            label.set_line_wrap(true);
            content.add(label);
            dialog.response.connect((id)=>{
                printf("response id=%i\n",id);
                RESPONSE = id;
                dialog.destroy();
            });
            dialog.show_all();
        }
    // ==== onAbout ===========================================================
        private void onAbout() {
            Dialog dialog = new Dialog.with_buttons
                ("About",this,DialogFlags.MODAL,
                Stock.OK,ResponseType.OK,null);
            var content = dialog.get_content_area();
    // warning: assignment from incompatible pointer type
    // [enabled by default]
            Label label = new Label("This program tests pop-up dialogs");
            content.add(label);
            dialog.response.connect(()=>{dialog.destroy();});
            dialog.show_all();
        }
    // ==== onDoIt ============================================================
        private void onDoIt() {
            getYesNo("Well?");
            if (RESPONSE==ResponseType.YES) showDialog("YES!");
        }
    // ==== onQuit ============================================================
        private void onQuit() {
            printf("Ending\n");
            exit(-1);
        }
    // ==== showDialog ========================================================
        private void showDialog(string message) {
            Dialog dialog = new Dialog.with_buttons
                ("Show",this,DialogFlags.MODAL,
                Stock.OK,ResponseType.OK,null);
            var content = dialog.get_content_area();
    // warning: assignment from incompatible pointer type
    // [enabled by default]
            Label label = new Label(message);
            label.set_line_wrap(true);
            content.add(label);
            dialog.response.connect((id)=>{dialog.destroy();});
            dialog.show_all();
        }
    
    }
    
    public class DialogTest: Gtk.Application {
        internal DialogTest() {
            Object(application_id: "org.test.DialogTest");
        }
        protected override void activate() {
            new DialogTestWindow(this).show();
        }
    }
    
    extern void exit(int exit_code);
    
    public int main(string[] args) {
        return new DialogTest().run(args);
    }
    


Answer: Use Gtk.Dialog.run, not Gtk.Widget.show_all. That will block the main loop
until the dialog returns a result instead of displaying the two dialogs
simultaneously.

