Search code examples
dialogpaneldm-script

Dialog panels do not hide properly on switch - is there a workaround?


I have a dialog that contains two panels as shown below, created with the given code. As one can see in the right image, the second panel still contains content from the first panel.

Dialog panels

Is there any workaround to fix that?

I feel like bugs like these should be mentionend on Stackoverflow.

class TestDialog : UIFrame{
    TagGroup panel_list;
    
    /**
     * Switch to the `index`-th panel.
     */
    void switchToPanel(object self, number index){
        panel_list.DLGValue(index);
    }
    
    void switchToPanel0(object self){self.switchToPanel(0);}
    void switchToPanel1(object self){self.switchToPanel(1);}
    
    /**
     * Create the dialog content
     */
    TagGroup createContent(object self){
        panel_list = DLGCreatePanelList(0);
        
        TagGroup box, switch_button, input, panel;

        // panel 1
        box = DLGCreateBox("Panel 1");
        
        // switch panel button
        switch_button = DLGCreatePushButton("Switch to panel 2", "switchToPanel1");
        box.DLGAddElement(switch_button);
        
        // input field
        input = DLGCreateStringField("ABC");
        box.DLGAddElement(input);
        
        panel = DLGCreatePanel();
        panel.DLGAddElement(box);
        panel_list.DLGAddElement(panel);

        // panel 2
        box = DLGCreateBox("Panel 2");
        
        // switch panel button
        switch_button = DLGCreatePushButton("Switch to panel 1", "switchToPanel0");
        box.DLGAddElement(switch_button);
        
        // add a label so both boxes have different heights
        box.DLGAddElement(DLGCreateLabel(""));
        
        // input field
        input = DLGCreateStringField("DEF");
        box.DLGAddElement(input);
        
        panel = DLGCreatePanel();
        panel.DLGAddElement(box);
        panel_list.DLGAddElement(panel);
        
        TagGroup wrapper = DLGCreateGroup();
        wrapper.DLGAddElement(panel_list);

        return wrapper;
    }

    object init(object self){
        return self.super.init(self.createContent())
    }
}

alloc(TestDialog).init().pose()


Solution

  • Fix: Hide manually

    After a lot of trying out I think triggering the UIFrame::SetElementIsShown() manually fixes this issue. In the given example one can add the identifiers input0 to the first and input1 to the second input and then change the TestDialog::switchToPanel() function to the following:

    /**
    * Switch to the `index`-th panel.
    */
    void switchToPanel(object self, number index){
        panel_list.DLGValue(index);
        
        if(index == 0){
            self.setElementIsShown("input0", 1);
            self.setElementIsShown("input1", 0);
        }
        else{
            self.setElementIsShown("input0", 0);
            self.setElementIsShown("input1", 1);
        }
    }
    

    The complete code is then:

    class TestDialog : UIFrame{
        TagGroup panel_list;
        
        /**
        * Switch to the `index`-th panel.
        */
        void switchToPanel(object self, number index){
            panel_list.DLGValue(index);
            
            if(index == 0){
                self.setElementIsShown("input0", 1);
                self.setElementIsShown("input1", 0);
            }
            else{
                self.setElementIsShown("input0", 0);
                self.setElementIsShown("input1", 1);
            }
        }
        
        void switchToPanel0(object self){self.switchToPanel(0);}
        void switchToPanel1(object self){self.switchToPanel(1);}
        
        /**
         * Create the dialog content
         */
        TagGroup createContent(object self){
            panel_list = DLGCreatePanelList(0);
            
            TagGroup box, switch_button, input, panel;
    
            // panel 1
            box = DLGCreateBox("Panel 1");
            
            // switch panel button
            switch_button = DLGCreatePushButton("Switch to panel 2", "switchToPanel1");
            box.DLGAddElement(switch_button);
            
            // input field
            input = DLGCreateStringField("ABC");
            input.DLGIdentifier("input0");
            box.DLGAddElement(input);
            
            panel = DLGCreatePanel();
            panel.DLGAddElement(box);
            panel_list.DLGAddElement(panel);
    
            // panel 2
            box = DLGCreateBox("Panel 2");
            
            // switch panel button
            switch_button = DLGCreatePushButton("Switch to panel 1", "switchToPanel0");
            box.DLGAddElement(switch_button);
            
            // add a label so both boxes have different heights
            box.DLGAddElement(DLGCreateLabel(""));
            
            // input field
            input = DLGCreateStringField("DEF");
            input.DLGIdentifier("input1");
            box.DLGAddElement(input);
            
            panel = DLGCreatePanel();
            panel.DLGAddElement(box);
            panel_list.DLGAddElement(panel);
            
            TagGroup wrapper = DLGCreateGroup();
            wrapper.DLGAddElement(panel_list);
    
            return wrapper;
        }
    
        object init(object self){
            return self.super.init(self.createContent())
        }
    }
    
    alloc(TestDialog).init().pose()
    

    Workaround: Use Tabs

    I also found out that tabs work with the exact same code. So if possible one can just replace the panels with tabs.

    class TestDialog : UIFrame{
        TagGroup tab_list;
        TagGroup inputs;
        
        /**
         * Create the dialog content
         */
        TagGroup createContent(object self){
            inputs = NewTagList();
            tab_list = DLGCreateTabList(0);
            
            TagGroup box, input, tab;
    
            // panel 1
            box = DLGCreateBox("Panel 1");
            
            // input field
            input = DLGCreateStringField("ABC");
            box.DLGAddElement(input);
            // save the input field in a TagList, this creates the problem
            inputs.TagGroupInsertTagAsTagGroup(infinity(), input);
            
            tab = DLGCreateTab("Tab 1");
            tab.DLGAddElement(box);
            tab_list.DLGAddElement(tab);
    
            // panel 2
            box = DLGCreateBox("Panel 2");
            
            // add a label so both boxes have different heights
            box.DLGAddElement(DLGCreateLabel(""));
            
            // input field
            input = DLGCreateStringField("DEF");
            box.DLGAddElement(input);
            inputs.TagGroupInsertTagAsTagGroup(infinity(), input);
            
            tab = DLGCreateTab("Tab 2");
            tab.DLGAddElement(box);
            tab_list.DLGAddElement(tab);
            
            TagGroup wrapper = DLGCreateGroup();
            wrapper.DLGAddElement(tab_list);
    
            return wrapper;
        }
    
        object init(object self){
            return self.super.init(self.createContent())
        }
    }
    
    object dialog = alloc(TestDialog).Init();
    dialog.pose();