Modified Pop Up Menu



  • Hi,

    I'm trying to create a pop-up menu with a modified layout. Currently, the default layout of c4d.gui.ShowPopupDialog is vertical. I was looking forward to a columnar layout where its easier to see everything.

    You can see an illustration of what I am after here:
    https://www.dropbox.com/s/8dhs505yz34lap3/c4d140_modified_popup_menu.mp4?dl=0

    A few notable behaviors are that

    1. modified columnar layout
    2. it disappears once you click a command (pop-up)

    I initially thought the DLG_TYPE_ASYNC_POPUPEDIT or DLG_TYPE_ASYNC_POPUP_RESIZEABLE would do the trick but unfortunately, when you click a command, the dialog does not disappear.

    You can see an illustration code below:

    import c4d
    import os
    from c4d import gui, plugins, bitmaps, utils, documents
    
    
    PLUGIN_ID   = 1011325
    
    MAIN_TAB    = 10001
    MY_BUTTON   = 11002
    
    class MyDialog(gui.GeDialog):
    
        def get_all_objects(op):
    
          output = []
    
          while op:
              output.append(op)
              get_all_objects(op.GetDown())
              op = op.GetNext()
          return output
    
    
        def CreateLayout(self):
    
          self.GroupBegin(id=1013, flags=c4d.BFH_SCALEFIT, cols=5, rows=4)  
          self.AddButton(MY_BUTTON, c4d.BFV_MASK, initw=100, name="Button1")
          self.AddButton(MY_BUTTON, c4d.BFV_MASK, initw=100, name="Button2")
          self.AddButton(MY_BUTTON, c4d.BFV_MASK, initw=100, name="Button3")
          self.AddButton(MY_BUTTON, c4d.BFV_MASK, initw=100, name="Button4")
          self.AddButton(MY_BUTTON, c4d.BFV_MASK, initw=100, name="Button5")
          self.AddButton(MY_BUTTON, c4d.BFV_MASK, initw=100, name="Button6")
    
          self.GroupEnd()
    
          return True
    
    
        def Command(self, id, msg):
    
            if (id == MY_BUTTON):
                print "Button is clicked"
                return True
    
            return True
    
    class MyMenuPlugin(plugins.CommandData):
    
        dialog = None
        def Execute(self, doc):
        # create the dialog
           if self.dialog is None:
              self.dialog = MyDialog()
    
           return self.dialog.Open(dlgtype=c4d.DLG_TYPE_ASYNC_POPUPEDIT, pluginid=PLUGIN_ID, defaultw=200, defaulth=150, xpos=-1, ypos=-1)
    
        def RestoreLayout(self, sec_ref):
        # manage the dialog
           if self.dialog is None:
              self.dialog = MyDialog()
           return self.dialog.Restore(pluginid=PLUGIN_ID, secret=sec_ref)
    
    
    if __name__ == "__main__":
    
        okyn = plugins.RegisterCommandPlugin(PLUGIN_ID, "BT Popup",0, None, "Python Menu", MyMenuPlugin())
        if (okyn):
            print "Utilities Pop Up"
    
    

    Thank you for looking at my problem



  • Hi,

    @bentraje said in Modified Pop Up Menu:

    I initially thought the DLG_TYPE_ASYNC_POPUPEDIT or DLG_TYPE_ASYNC_POPUP_RESIZEABLE would do the trick but unfortunately, when you click a command, the dialog does not disappear.

    To programmatically close a dialog you have to invoke GeDialog.Close(). So if you want to mimic a popup menu, you should do that after the button event handling.

    all_button_ids = [ID_BUTTON_1, ID_BUTTON_2, ...]
    
    def Command(self, id, msg):
        
        if id == ID_BUTTON_1:
            # your button logic ...
    
        if id in all_button_ids:
            self.Close()
    

    Cheers
    zipit



  • @zipit said in Modified Pop Up Menu:

    if id in all_button_ids:

    Thanks for the response. I tried adding it. It didn't error out but it also didn't close.

    You can see the current code here:

    import c4d
    import os
    from c4d import gui, plugins, bitmaps, utils, documents
    
    
    PLUGIN_ID   = 1011325
    
    MAIN_TAB    = 10001
    MY_BUTTON   = 11002
    
    all_button_ids = [MY_BUTTON]
    
    class MyDialog(gui.GeDialog):
    
        def get_all_objects(op):
    
          output = []
    
          while op:
              output.append(op)
              get_all_objects(op.GetDown())
              op = op.GetNext()
          return output
    
    
        def CreateLayout(self):
    
          self.GroupBegin(id=1013, flags=c4d.BFH_SCALEFIT, cols=5, rows=4)  
          self.AddButton(MY_BUTTON, c4d.BFV_MASK, initw=100, name="Button1")
          self.AddButton(MY_BUTTON, c4d.BFV_MASK, initw=100, name="Button2")
          self.AddButton(MY_BUTTON, c4d.BFV_MASK, initw=100, name="Button3")
          self.AddButton(MY_BUTTON, c4d.BFV_MASK, initw=100, name="Button4")
          self.AddButton(MY_BUTTON, c4d.BFV_MASK, initw=100, name="Button5")
          self.AddButton(MY_BUTTON, c4d.BFV_MASK, initw=100, name="Changed")
    
          self.GroupEnd()
    
          return True
    
    
        def Command(self, id, msg):
    
            if (id == MY_BUTTON):
                print "Button is clicked"
                return True
    
            if id in all_button_ids:
                self.Close()
                return True
    
            return True
    
    class MyMenuPlugin(plugins.CommandData):
    
        dialog = None
        def Execute(self, doc):
        # create the dialog
           if self.dialog is None:
              self.dialog = MyDialog()
    
           return self.dialog.Open(dlgtype=c4d.DLG_TYPE_ASYNC_POPUPEDIT, pluginid=PLUGIN_ID, defaultw=200, defaulth=150, xpos=-1, ypos=-1)
    
        def RestoreLayout(self, sec_ref):
        # manage the dialog
           if self.dialog is None:
              self.dialog = MyDialog()
           return self.dialog.Restore(pluginid=PLUGIN_ID, secret=sec_ref)
    
    
    if __name__ == "__main__":
    
        okyn = plugins.RegisterCommandPlugin(PLUGIN_ID, "BT Popup",0, None, "Python Menu", MyMenuPlugin())
        if (okyn):
            print "Utilities Pop Up"
    


  • @bentraje said in Modified Pop Up Menu:

    Thanks for the response. I tried adding it. It didn't error out but it also didn't close

    Unreached code. You return true when MY_BUTTON is clicked, and never get to the self.Close() part.
    (You can remove two of the three returns from that method.)



  • Hi,

    as @Cairyn said the problem is unreachable code. I also just saw now that you did assign the same ID to all your buttons in your CreateLayout(). Ressource and dialog element IDs should be unique. I would generally recommend to define your dialogs using a resource, but here is an example on how to do it in code.

    BUTTON_BASE_ID = 1000
    BUTTON_NAMES = ["Button1", "Button2", "Button3", "Button4", "Button5"]
    BUTTON_DATA = {BUTTON_BASE_ID + i: name for i, name in enumerate(BUTTON_NAMES)}
    
    class MyDialog(gui.GeDialog):
    
        def CreateLayout(self):
            """
            """
            self.GroupBegin(id=1013, flags=c4d.BFH_SCALEFIT, cols=5, rows=4)
            for element_id, element_name in BUTTON_DATA.items():
                self.AddButton(element_id, c4d.BFV_MASK, initw=100, 
                               name=element_name)
            self.GroupEnd()
            return True
    
        def Command(self, id, msg):
            """
            """
            if id == BUTTON_BASE_ID:
                print "First button has been clicked"
            elif id == BUTTON_BASE_ID + 1:
                print "Second button has been clicked"
            # ...
            if id in BUTTON_DATA.keys(): # or just if id in BUTTON_DATA
                self.Close()
            return True
    


  • @Cairyn and @zipit

    Thanks for the clarification. Your solution works as expected.



  • Hello,

    Thanks for sharing your answer @zipit and @Cairyn

    Cheers,
    Manuel


Log in to reply