""" Window showing info about the current glyph This example shows a floating window that displays information about the current glyph. The window knows when the user has switched the current glyph and updates accordingly. The displayed information is updated when the data within the current glyph is changed. """ import ezui from mojo.subscriber import Subscriber, registerCurrentGlyphSubscriber class CurrentGlyphWithUISubscriberDemo(Subscriber, ezui.WindowController): debug = True def build(self): content = """ * VerticalStack @stackView > * MerzView @pointsView > name @nameTextBox > contours @contoursTextBox > components @componentsTextBox > anchors @anchorsTextBox > guidelines @guidelinesTextBox """ descriptionData = dict( stackView=dict( spacing=10, alignment="leading" ), pointsView=dict( backgroundColor=(0.75, 0.75, 0.75, 1), height=300, gravity="top", delegate=self ), ) self.w = ezui.EZWindow( title="Useless Glyph Data", content=content, size=(300, "auto"), descriptionData=descriptionData, controller=self ) def started(self): self.w.open() def currentGlyphDidSetGlyph(self, info): self.currentGlyphInfoDidChange(info) self.currentGlyphContoursDidChange(info) self.currentGlyphComponentsDidChange(info) self.currentGlyphAnchorsDidChange(info) self.currentGlyphGuidelinesDidChange(info) def currentGlyphInfoDidChange(self, info): glyph = info["glyph"] text = "" if glyph is not None: text = f"This glyph is named {glyph.name}." self.w.getItem("nameTextBox").set(text) def currentGlyphContoursDidChange(self, info): glyph = info["glyph"] text = "" if glyph is not None: text = f"This glyph contains {len(glyph.contours)} contours." self.w.getItem("contoursTextBox").set(text) view = self.w.getItem("pointsView") container = view.getMerzContainer() container.clearSublayers() if glyph is not None: viewWidth = view.width() viewHeight = view.height() font = glyph.font verticalMetrics = [ font.info.descender, font.info.xHeight, font.info.capHeight, font.info.ascender ] bottom = min(verticalMetrics) top = max(verticalMetrics) contentHeight = top - bottom fitHeight = viewHeight * 0.8 scale = fitHeight / contentHeight x = (viewWidth - (glyph.width * scale)) / 2 y = (viewHeight - fitHeight) / 2 container.addSublayerTransformation((scale, 0, 0, scale, x, y), name="scale&translate") glyphLayer = container.appendRectangleSublayer( size=(glyph.width, contentHeight), fillColor=(1, 1, 1, 1) ) with glyphLayer.sublayerGroup(): for contour in glyph.contours: for point in contour.points: if point.type == "move": glyphLayer.appendSymbolSublayer( position=(point.x, point.y), imageSettings=dict( name="star", pointCount=8, size=(100, 100), fillColor=(1, 1, 0, 0.5) ) ) elif point.type == "line": glyphLayer.appendSymbolSublayer( position=(point.x, point.y), imageSettings=dict( name="rectangle", size=(40, 40), fillColor=(0, 0, 1, 0.2) ) ) elif point.type == "curve": glyphLayer.appendSymbolSublayer( position=(point.x, point.y), imageSettings=dict( name="oval", size=(50, 50), fillColor=(0, 1, 0, 0.2) ) ) elif point.type == "qcurve": glyphLayer.appendSymbolSublayer( position=(point.x, point.y), imageSettings=dict( name="triangle", size=(50, 50), fillColor=(1, 0, 0, 0.2) ) ) elif point.type == "offcurve": glyphLayer.appendSymbolSublayer( position=(point.x, point.y), imageSettings=dict( name="oval", size=(75, 75), fillColor=None, strokeColor=(0, 0, 0, 0.2), strokeWidth=1 ) ) def currentGlyphComponentsDidChange(self, info): glyph = info["glyph"] text = "" if glyph is not None: text = f"This glyph contains {len(glyph.components)} components." self.w.getItem("componentsTextBox").set(text) def currentGlyphAnchorsDidChange(self, info): glyph = info["glyph"] text = "" if glyph is not None: text = f"This glyph contains {len(glyph.anchors)} anchors." self.w.getItem("anchorsTextBox").set(text) def currentGlyphGuidelinesDidChange(self, info): glyph = info["glyph"] text = "" if glyph is not None: text = f"This glyph contains {len(glyph.guidelines)} guidelines." self.w.getItem("guidelinesTextBox").set(text) registerCurrentGlyphSubscriber(CurrentGlyphWithUISubscriberDemo)