Callback for standard shortcuts

I’m making a tool plugin that edits my custom data (i.e. not nodes, anchors, etc.), and want to write callbacks for standard shortcuts like command+A and so on. Is that possible? keyDown_() is never being called.

These are the methods you can add to your tool class:

def selectAll_(self, sender):
    pass

def deselectAll_(self, sender):
    pass

def invertSelection_(self, sender):
    pass

sender is whatever object called the (de)select action. That is mostly the NSMenuItem for the menu item in the main menu, but sender could also be None. For the most part, you can ignore this parameter.

You can run this script in the Macro Panel to get the method names you would need to implement to respond to certain menu items:

def walkMenu(menu):
	for item in menu.itemArray():
		if item.target() is None and item.action() is not None:
			print(item.title(), "->", item.action().replace(':', '_'))
		if submenu := item.submenu():
			walkMenu(submenu)

walkMenu(Glyphs.mainMenu())
3 Likes

Super wonderful, just what I needed!
Now, I want to do alignPoints_() and want to know which alignment rule is being selected (bottom-centred, top-right, etc.). Where can I find that info? It seems to be an app-wide value instead of document.

You can get the currently selected alignment via

alignment = Glyphs.defaults["GSTransformGridCorner"]

The value is of type GSAlignment. You can see the possible values in the docs and also use those constants in your Python code:

if alignment == GSCenterCenter:
    pass
elif alignment == GSTopLeft:
    pass
...

Thanks again! This should have been an easy one :sweat_smile:

The next one is tough:
I was told I can pack multiple plugins in one using NSPrincipalClass and PyMainFileNames entries in info.plist, but I haven’t been able to get the trick to work (nothing seems to happen). I want…

  • A tool plugin
  • A reporter plugin
  • A plugin with dialog window from Edit View

Would you know an existing sample that I can have a look, or kindly provide me with one?
I know KernKraft implements two menu items, which is encouraging but not quite how I need to do it.

See here:

The idea is that you no longer have an NSPrincipalClass and instead multiple class names in Principal Classes.

And the main python file needs to define those classes. Either directly or by importing code that defines them.

Thanks. I’m trying to draw inactive layers from a tool but it doesn’t seem possible. Can I do that?

You can draw there. Other from the plugin API directly or by applying for a custom drawing callback.

the method you are looking for is

- (void)drawLayer:(GSLayer *)layer atPoint:(NSPoint)layerOrigin asActive:(BOOL)active attributes:(NSDictionary *)attributes;

Or

- (void)drawMetricsForLayer:(GSLayer *)layer atPoint:(NSPoint)layerOrigin asActive:(BOOL)active;
1 Like

Thanks. ChatGPT tells me the equivalent function in python is drawLayer_atPoint_asActive_attributes_() which does work, but it disables drawing of the default layer contents. I’m not sure combining with needsExtraMainOutlineDrawingForInactiveLayer_() is the right approach, though returning True doesn’t do anything. I’m currently just drawing each layer’s completeBezierPath manually but want to avoid it.

If this is a subclass of the selection tool, you need to call the the super implementation:

objc.super(MyClass, self).drawLayer_atPoint_asActive_attributes_(layer, point, …)

Thanks! If I want to run that from background(), I don’t have ‘attributes’ to feed. How should I get one? (I definitely need scale, for one)

Maybe it’s sufficient to run your own code before calling super.

You only call super from the same method call.
Can you send me your code that I can have a look?

Thanks, I’ve sent invitations sent to you two. The relevant part is described in the open issue.