Simple example tool ↩
The script below demonstrates how interactive tools work. The tool doesn’t do anything useful – it just shows how to react to mouse and keyboard events, and prints out some information for each event that is triggered.
from mojo.events import BaseEventTool
from mojo.drawingTools import *
class MyTool(BaseEventTool):
def setup(self):
self.position = None
self.size = 20
self.shape = oval
self.color = 1, 0, 0, 0.5
def becomeActive(self):
print("tool became active")
def becomeInactive(self):
print("tool became inactive")
def mouseDown(self, point, clickCount):
# getGLyph returns the current glyph as an RGlyph object
print("mouse down", self.getGlyph(), clickCount)
self.size *= 4
def rightMouseDown(self, point, event):
print("right mouse down")
def mouseDragged(self, point, delta):
print("mouse dragged")
self.position = point
def rightMouseDragged(self, point, delta):
print("right mouse dragged")
def mouseUp(self, point):
print("mouse up")
self.size *= 0.25
def keyDown(self, event):
# getModifiers returns a dict with all modifiers:
# Shift, Command, Alt, Option
print("key down", self.getModifiers())
def keyUp(self, event):
print("key up")
def mouseMoved(self, point):
self.position = point
self.refreshView()
def modifiersChanged(self):
print("modifiers changed")
# get modifier keys
modifiers = self.getModifiers()
# define shape based on 'shift' key:
# > if 'shift' is pressed, shape is a rectangle
if modifiers['shiftDown']:
self.shape = rect
# > otherwise, shape is an oval
else:
self.shape = oval
# change color based on 'option' key:
# > if 'option' is pressed, color is blue
if modifiers['optionDown']:
self.color = 0, 0, 1, 0.5
# > otherwise, color is red
else:
self.color = 1, 0, 0, 0.5
# tell the glyph view to update
self.refreshView()
def draw(self, scale):
# print("drawing...", self.isDragging())
if self.position is not None:
# calculate shape position from center
x = self.position.x - self.size*0.5
y = self.position.y - self.size*0.5
# set shape color
fill(*self.color)
stroke(None)
# draw shape
self.shape(x, y, self.size, self.size)
def drawBackground(self, scale):
# print("drawing background...")
pass
# def getDefaultCursor(self):
# # sets the cursor. (default is an arrow)
# return a NSCursor
# def getToolbarIcon(self):
# # sets the toolbar icon. (default is an arrow)
# return a NSImage
def getToolbarTip(self):
return "My Tool Tip"
# notifications
def viewDidChangeGlyph(self):
print("view changed glyph")
def preferencesChanged(self):
print("preferences changed")
Installing a tool
Tools can be installed into the Glyph Editor’s toolbar with installTool
:
from mojo.events import installTool
installTool(MyTool())
To make your tool available when RoboFont restarts, create an installation script and save it as a start-up script.
Testing a tool during development
Below is a simple helper to use while working on your own interactive tools. It provides a dialog to install/uninstall a custom tool during development, without having to restart RoboFont.
from vanilla import FloatingWindow, CheckBox
from defconAppKit.windows.baseWindow import BaseWindowController
from mojo.events import installTool, uninstallTool, getToolOrder
class MyToolActivator(BaseWindowController):
def __init__(self, tool):
self.w = FloatingWindow((123, 44), 'MyTool')
self.w.button = CheckBox((10, 10, -10, 24), 'activate', value=True, callback=self.activateToolCallback)
self.tool = tool
# install the tool
installTool(self.tool)
# initialize the window
self.setUpBaseWindowBehavior()
self.w.open()
def activateToolCallback(self, sender):
# if the tool is not installed, install it
if sender.get():
installTool(self.tool)
# if the tool is installed, uninstall it
else:
uninstallTool(self.tool)
def windowCloseCallback(self, sender):
# if the tool is active, remove it
tools = getToolOrder()
if self.tool.__class__.__name__ in tools:
uninstallTool(self.tool)
super(MyToolActivator, self).windowCloseCallback(sender)
MyToolActivator(MyTool())