checkbox or slider in additionContextualMenuItems?



  • Hi Guys,
    As in the topic: I'm creating tool based on BaseEventTool. is it possible to add checkbox and slider objects to the right click menu?
    If yes, then how?

    any help would be great :)


  • admin

    you need to provide a NSMenuItem with a view, which will be the controller: a checkBox or slider.

    I can make an example next week, as I’m on the road!



  • Hi @frederik,
    I've been trying to have fun with AppKit etc, but I wasn't able to build those NSMenuItems. Could you show an example? It would be super nice of you.


  • admin

    hope this makes sense

    import AppKit
    import vanilla
    from mojo.UI import MenuBuilder
    
    def callback(sender):
        print(sender)
    
    def sliderCallback(sender):
        print(sender.get())
    
    sliderMenuItem = AppKit.NSMenuItem.alloc().initWithTitle_action_keyEquivalent_("slider", '', '')
    slider = vanilla.Slider((0, 0, 100, 30), callback=sliderCallback) 
    view = slider.getNSSlider()
    view.setFrame_(((0, 0), (100, 30)))
    sliderMenuItem.setView_(view)
    
    
    builder = MenuBuilder([
        ("test", callback), 
        ("test 2", callback),
        ("test 3", callback),
        
        sliderMenuItem,
    ])
    
    menu = builder.getMenu()
    print(menu)
    
    name = "My Menu With Slider"
    
    # get the menu bar
    menubar = AppKit.NSApp().mainMenu()
    
    newItem = menubar.itemWithTitle_(name)
    if not newItem:
        # if not, create one and append it before `Help`
        newItem = AppKit.NSMenuItem.alloc().initWithTitle_action_keyEquivalent_(name, '', '')
        menubar.insertItem_atIndex_(newItem, menubar.numberOfItems()-1)
    
    
    menu.setTitle_(name)
    # set the menu as submenu
    newItem.setSubmenu_(menu)
    


  • Sweet! it is clear, looks like it works. Thank you so much.

    question a bit off topic: is it possible to add custom menu items to default RF tools, like edit tool?

    I was thinking about creating the one functionality in right-click menu, and I think that it would be waste of space in the glyph window toolbar If I would create additional tool only to have this small function build into right click menu.


  • admin

    yes there is a notification for that :)

    subscribe to:

    • for glyphs glyphAdditionContextualMenuItems
    • for guides guideAdditionContextualMenuItems
    • for images imageAdditionContextualMenuItems
    • in the glyph cell view fontOverviewAdditionContextualMenuItems

    good luck!



  • This post is deleted!


  • Hi again,
    I have three questions regarding code below (which is an attempt of implementation of the set of checkboxes in glyphAdditionContextualMenuItems):

    1. in general: do I do everything right?
    2. if yes, then why only last of the checkboxes can send callback?
    3. the most unnecessary question – how to make those checkboxes looks nice as those default? (without white background for the checkbox, the same size, margins etc.)

    Cheers,
    Thanks in advance

    import AppKit
    from mojo.events import addObserver, removeObserver, EditingTool
    import vanilla 
    from mojo.extensions import setExtensionDefault, getExtensionDefault
    class Test:
        key = "com.usr.additionContextualMenuItemsEditTool"
        
        def __init__(self):
            self.items = {'customCheckBox1': False, 'customCheckBox2': False, 'customCheckBox3': False}
            self.w = vanilla.FloatingWindow((0,0,100,100))
            self.w.bind("close",self.closing)
            self.w.open()
            addObserver(self, "glyphAdditionContextualMenuItemsCB", "glyphAdditionContextualMenuItems")
    
            
        def closing(self, info):
            removeObserver(self, "glyphAdditionContextualMenuItems")
    
        def loadSettings(self):
            # loading settings
            zero_settings = self.items
            settings = getExtensionDefault(self.key)
            if settings:
                for name in settings:
                    self.items[name] = settings[name]
                else:
                    self.items = zero_settings
            else:
                self.items = zero_settings
                
        def savingSettings(self):
            setExtensionDefault(self.key, self.items)
    
            
        def glyphAdditionContextualMenuItemsCB(self, info):
            menuItems = info['additionContextualMenuItems']
            tool = info["tool"]
            self.loadSettings()
            if isinstance(tool, EditingTool):
                
                for title in self.items:
                    value = self.items[title]
                    checkboxMenuItem = AppKit.NSMenuItem.alloc().initWithTitle_action_keyEquivalent_("regular", '', '')
                    self.checkbox = vanilla.CheckBox((0, 0, 100, 30), title, value=value, callback=self.checkboxCallback) 
                    
                    view = self.checkbox.getNSButton()
                    view.setFrame_(((0, 0), (200, 30)))
                    checkboxMenuItem.setView_(view)
                    menuItems += [checkboxMenuItem]
                
                
        def checkboxCallback(self, obj):
            value = False
            if obj.get() == 1:
                value = True 
            self.items[obj.getTitle()] = value
            self.savingSettings()
            
            
    Test()
    


  • I fixed the 2nd issue (if yes, then why only last of the checkboxes can send callback?). But I'm not sure if everything is alright, isn't this code too messy?:

    import AppKit
    from mojo.events import addObserver, removeObserver, EditingTool
    import vanilla 
    from mojo.extensions import setExtensionDefault, getExtensionDefault
    class Test:
        key = "com.usr.additionContextualMenuItemsEditTool"
        
        def __init__(self):
            self.items = {'customCheckBox1': False, 'customCheckBox2': False, 'customCheckBox3': False}
            self.w = vanilla.FloatingWindow((0,0,100,100))
            self.w.bind("close",self.closing)
            self.w.open()
            addObserver(self, "glyphAdditionContextualMenuItemsCB", "glyphAdditionContextualMenuItems")
    
            
        def closing(self, info):
            removeObserver(self, "glyphAdditionContextualMenuItems")
    
        def loadSettings(self):
            # loading settings
            zero_settings = self.items
            settings = getExtensionDefault(self.key)
            if settings:
                for name in settings:
                    self.items[name] = settings[name]
                else:
                    self.items = zero_settings
            else:
                self.items = zero_settings
                
        def savingSettings(self):
            setExtensionDefault(self.key, self.items)
    
            
        def glyphAdditionContextualMenuItemsCB(self, info):
            menuItems = info['additionContextualMenuItems']
            tool = info["tool"]
            self.loadSettings()
            if isinstance(tool, EditingTool):
                
                for title in self.items:
                    objName = title.replace(" ","_")
                    value = self.items[title]
                    checkboxMenuItem = AppKit.NSMenuItem.alloc().initWithTitle_action_keyEquivalent_("regular", '', '')
                    checkbox = vanilla.CheckBox((0, 0, 100, 30), title, value=value, callback=self.checkboxCallback) 
                    setattr(self, objName, checkbox)
                    view = checkbox.getNSButton()
                    view.setFrame_(((0, 0), (200, 30)))
                    checkboxMenuItem.setView_(view)
                    menuItems += [checkboxMenuItem]
                
                
        def checkboxCallback(self, obj):
            value = False
            if obj.get() == 1:
                value = True 
            self.items[obj.getTitle()] = value
            self.savingSettings()
            
            
    Test()
    

  • admin

    hello @RafaŁ-Buchner,

    two suggestions to improve your code:

    • getExtensionDefault has a fallback argument which you can use to pass the default values:

      def loadSettings(self):
          settings = getExtensionDefault(self.key, fallback=self.items)
      
    • here’s how you can make the added menu items look the same as the default ones:

      MenuTextAttributes = {AppKit.NSFontAttributeName: AppKit.NSFont.menuFontOfSize_(14)}
      t =  AppKit.NSAttributedString.alloc().initWithString_attributes_(title, MenuTextAttributes)
      checkbox = vanilla.CheckBox((0, 0, 100, 22), t, value=value, callback=self.checkboxCallback) 
      

    I haven’t used glyphAdditionContextualMenuItems myself yet, so maybe there are other things I am not seeing…

    hope this helps! cheers



  • Cool! Thanks a million!



  • Hey guys, somehow I cannot roll out the popUpButton menu item.

    Any idea how can I do that?

    import AppKit
    import vanilla
    from mojo.UI import MenuBuilder
    
    def callback(sender):
        print(sender)
    
    def popUpButtonCallback(sender):
        print(sender.get())
    
    popUpButtonMenuItem = AppKit.NSMenuItem.alloc().initWithTitle_action_keyEquivalent_("popUpButton", '', '')
    popUpButton = vanilla.PopUpButton((0, 0, 100, 30), ['a','b','v'] ,callback=popUpButtonCallback) 
    view = popUpButton.getNSPopUpButton()
    view.setFrame_(((0, 0), (100, 30)))
    popUpButtonMenuItem.setView_(view)
    
    
    builder = MenuBuilder([
        ("test", callback), 
        ("test 2", callback),
        ("test 3", callback),
        
        popUpButtonMenuItem,
    ])
    
    menu = builder.getMenu()
    print(menu)
    
    name = "My Menu With popUpButton"
    
    # get the menu bar
    menubar = AppKit.NSApp().mainMenu()
    
    newItem = menubar.itemWithTitle_(name)
    if not newItem:
        # if not, create one and append it before `Help`
        newItem = AppKit.NSMenuItem.alloc().initWithTitle_action_keyEquivalent_(name, '', '')
        menubar.insertItem_atIndex_(newItem, menubar.numberOfItems()-1)
    
    
    menu.setTitle_(name)
    # set the menu as submenu
    newItem.setSubmenu_(menu)