#!/usr/bin/env python3 from math import hypot from mojo.subscriber import Subscriber, WindowController from mojo.subscriber import registerGlyphEditorSubscriber, unregisterGlyphEditorSubscriber from mojo.roboFont import OpenWindow from vanilla import FloatingWindow, CheckBox RED = 1, 0, 0, 1 WHITE = 1, 1, 1, 1 class PointDistanceControllerPalette(WindowController): debug = True def build(self): self.w = FloatingWindow((200, 40), "PointDistanceController") self.w.checkBox = CheckBox((10, 10, -10, 20), "Display Distances", callback=self.checkBoxCallback, value=True) self.w.open() def started(self): PointDistanceController.controller = self registerGlyphEditorSubscriber(PointDistanceController) def destroy(self): unregisterGlyphEditorSubscriber(PointDistanceController) PointDistanceController.controller = None def checkBoxCallback(self, sender): if sender.get(): PointDistanceController.controller = self registerGlyphEditorSubscriber(PointDistanceController) else: PointDistanceController.controller = None unregisterGlyphEditorSubscriber(PointDistanceController) class PointDistanceController(Subscriber): debug = True def build(self): glyphEditor = self.getGlyphEditor() self.container = glyphEditor.extensionContainer( identifier="com.roboFont.PointDistanceController.foreground", location="foreground", clear=True ) self.distancesLayer = self.container.appendBaseSublayer() def destroy(self): self.container.clearSublayers() def glyphDidChangeSelection(self, info): # get the glyph from the notification glyph = info["glyph"] # get the selection selection = glyph.selection # check if the selection is more than 1 and less than 6 if 2 <= len(selection) <= 5: self.distancesLayer.setVisible(True) self.distancesLayer.clearSublayers() done = [] # loop over all the points in the selection for p in selection: # loope in a the loop again over all the points in the selection for p2 in selection: # check if the point is not the same if p == p2: continue # check if we already handled the point if set([p, p2]) in done: continue # add a line to the distances layer self.distancesLayer.appendLineSublayer( startPoint=(p.x, p.y), endPoint=(p2.x, p2.y), strokeWidth=1, strokeColor=RED ) # calculate the center point cx = p.x + (p2.x - p.x) * .5 cy = p.y + (p2.y - p.y) * .5 # calculate the distance dist = hypot(p2.x - p.x, p2.y - p.y) # store connections to avoid duplicates done.append(set([p, p2])) # create the label layer self.distancesLayer.appendTextLineSublayer( position=(cx, cy), backgroundColor=RED, text=f"{dist:.0f}" if dist % 1 == 0 else f"{dist:.2f}", font="system", weight="bold", pointSize=12, padding=(4, 1), cornerRadius=4, fillColor=WHITE, horizontalAlignment='center', verticalAlignment='center', ) else: self.distancesLayer.setVisible(False) if __name__ == '__main__': OpenWindow(PointDistanceControllerPalette)