def __init__(self):
        self.filters = PenBallFiltersManager()
        self.filters.loadFiltersFromJSON('/'.join([LOCALPATH, JSONFILE]))
        self.glyphNames = []
        self.observedGlyphs = []
        self.cachedFont = RFont(showUI=False)
        self.currentFont = CurrentFont()
        filtersList = self.filters.keys()
        if len(filtersList) > 0:
            self.currentFilterName = filtersList[0]
        else:
            self.currentFilterName = None
        self.fill = True

        self.observers = [
            ('fontChanged', 'fontBecameCurrent'),
            ('fontChanged', 'fontDidOpen'),
            ('fontChanged', 'fontDidClose'),
        ]

        self.w = Window((100, 100, 800, 500), 'PenBall Wizard v{0}'.format(__version__), minSize=(500, 400))
        self.w.filtersPanel = Group((0, 0, 300, -0))
        self.w.filtersPanel.filtersList = List((0, 0, -0, -40), filtersList, selectionCallback=self.filterSelectionChanged, doubleClickCallback=self.filterEdit, allowsMultipleSelection=False, allowsEmptySelection=False, rowHeight=22)
        self.w.filtersPanel.controls = Group((0, -40, -0, 0))
        self.w.filtersPanel.addFilter = SquareButton((0, -40, 100, 40), 'Add filter', sizeStyle='small', callback=self.addFilter)
        self.w.filtersPanel.addFilterChain = SquareButton((100, -40, 100, 40), 'Add operations', sizeStyle='small', callback=self.addFilterChain)
        self.w.filtersPanel.removeFilter = SquareButton((-100, -40, 100, 40), 'Remove filter', sizeStyle='small', callback=self.removeFilter)
        self.w.textInput = EditText((300, 0, -90, 22), '', callback=self.stringInput)
        self.w.generate = SquareButton((-90, 0, 90, 22), 'Generate', callback=self.generateGlyphsToFont, sizeStyle='small')
        self.w.preview = MultiLineView((300, 22, -0, -0))
        self.w.switchFillStroke = SquareButton((-75, -40, 60, 25), 'Stroke', callback=self.switchFillStroke, sizeStyle='small')
        displayStates = self.w.preview.getDisplayStates()
        for key in ['Show Metrics','Upside Down','Stroke','Beam','Inverse','Water Fall','Multi Line']:
            displayStates[key] = False
        for key in ['Fill','Single Line']:
            displayStates[key] = True
        self.w.preview.setDisplayStates(displayStates)

        for callback, event in self.observers:
            addObserver(self, callback, event)

        self.updateControls()

        self.w.bind('close', self.end)
        self.launchWindow()
        self.w.open()
    def _BuildUI(self, font):
        self.w = Window((792, 612))

        self.w.editText = EditText((10, 10, -10, 24),
                                   callback=self.editTextCallback)

        self.w.lineView = MultiLineView(
            (0, 40, -0, -0),
            pointSize=104,
            lineHeight=130,
            selectionCallback=self.lineViewSelectionCallback)

        #self.w.lineView.setFont(font)

        self.drawLines()

        print self.w.lineView.getDisplayStates()
Example #3
0
    def __init__(self, font):
        self.font = None
        self._glyphs = []

        statusBarHeight = 20

        self.w = Window((900, 700), "Glyph Builder", minSize=(400, 400))
        self.w.getNSWindow().setCollectionBehavior_(
            128)  # NSWindowCollectionBehaviorFullScreenPrimary

        toolbarItems = [
            dict(
                itemIdentifier="save",
                label="Save",
                imageNamed="toolbarScriptSave",
                callback=self.saveFile,
            ),
            dict(
                itemIdentifier="open",
                label="Open",
                imageNamed="toolbarScriptOpen",
                callback=self.openFile,
            ),
            dict(itemIdentifier=NSToolbarSpaceItemIdentifier),
            dict(
                itemIdentifier="reload",
                label="Update",
                imageNamed="toolbarScriptReload",
                callback=self.reload,
            ),
            dict(itemIdentifier=NSToolbarSpaceItemIdentifier),
            dict(
                itemIdentifier="analyse",
                label="Analyse",
                imageNamed="prefToolbarSort",
                callback=self.analyse,
            ),
            dict(itemIdentifier=NSToolbarFlexibleSpaceItemIdentifier),
            dict(itemIdentifier="buildGlyphs",
                 label="Build Glyphs",
                 imageNamed="toolbarRun",
                 callback=self.generateGlyphs),
        ]
        self.w.addToolbar(toolbarIdentifier="GlyphBuilderControllerToolbar",
                          toolbarItems=toolbarItems,
                          addStandardItems=False)

        self.constructions = CodeEditor((0, 0, -0, -0),
                                        constructions,
                                        lexer=GlyphConstructionLexer())
        # self.constructions.wrapWord(False) # in only availbel in the RoboFont 1.7 beta

        self.constructions.getNSScrollView().setBorderType_(NSNoBorder)
        self.preview = MultiLineView(
            (0, 0, -0, -0),
            pointSize=50,
            lineHeight=500,
            applyKerning=False,
            displayOptions={
                "Beam": False,
                "displayMode": "Multi Line"
            },
            selectionCallback=self.previewSelectionCallback)

        self.analyser = AnalyserTextEditor((0, 0, -0, -0), readOnly=True)
        self.analyserPreview = Group((0, 0, -0, -0))

        constructionColor = NSColor.colorWithCalibratedRed_green_blue_alpha_(
            0, 0, 0, .6)
        self.analyserPreview.construction = GlyphPreview(
            (0, 0, -0, -0),
            contourColor=constructionColor,
            componentColor=constructionColor)
        self.analyserPreview.construction.getNSView()._buffer = 100
        originColor = NSColor.colorWithCalibratedRed_green_blue_alpha_(
            1, 0, 0, .6)
        self.analyserPreview.origin = GlyphPreview((0, 0, -0, -0),
                                                   contourColor=originColor,
                                                   componentColor=originColor)
        self.analyserPreview.origin.getNSView()._buffer = 100

        self.analyserPreview.build = Button((10, -30, -10, 20),
                                            "Build",
                                            sizeStyle="small",
                                            callback=self.buildSingleGlyph)
        self.analyserPreview.build.enable(False)

        paneDescriptions = [
            dict(view=self.analyser,
                 identifier="analyserText",
                 canCollapse=False,
                 minSize=100),
            dict(view=self.analyserPreview,
                 identifier="analyserPreview",
                 canCollapse=False,
                 minSize=100),
        ]
        self.analyserSplit = Splitter((0, 0, -0, -statusBarHeight),
                                      paneDescriptions=paneDescriptions,
                                      drawBorderLine=False,
                                      isVertical=False,
                                      dividerThickness=1)

        paneDescriptions = [
            dict(view=self.constructions,
                 identifier="constructions",
                 canCollapse=False,
                 minSize=200,
                 maxSize=600,
                 liveResizeable=False),
            dict(view=self.preview,
                 identifier="preview",
                 canCollapse=False,
                 minSize=300,
                 liveResizeable=True),
            dict(view=self.analyserSplit,
                 identifier="analyser",
                 canCollapse=True,
                 minSize=100,
                 maxSize=300,
                 liveResizeable=False)
        ]
        self.w.split = Splitter((0, 0, -0, -statusBarHeight),
                                paneDescriptions=paneDescriptions,
                                drawBorderLine=False,
                                dividerThickness=1)
        # self.w.split.showPane("analyser", True)

        self.w.statusBar = StatusBar(
            (0, -statusBarHeight, -0, statusBarHeight))
        self.w.statusBar.hiddenReload = Button((0, 0, -0, -0), "Reload",
                                               self.reload)
        button = self.w.statusBar.hiddenReload.getNSButton()
        button.setBezelStyle_(NSRoundRectBezelStyle)
        button.setAlphaValue_(0)
        self.w.statusBar.hiddenReload.bind("\r", ["command"])

        self.w.statusBar.hiddenSave = Button((0, 0, -0, -0), "Reload",
                                             self.saveFile)
        button = self.w.statusBar.hiddenSave.getNSButton()
        button.setBezelStyle_(NSRoundRectBezelStyle)
        button.setAlphaValue_(0)
        self.w.statusBar.hiddenSave.bind("s", ["command"])

        self.subscribeFont(font)
        self.setUpBaseWindowBehavior()

        addObserver(self, "fontBecameCurrent", "fontBecameCurrent")
        addObserver(self, "fontResignCurrent", "fontResignCurrent")
        self.w.open()
Example #4
0
class GlyphBuilderController(BaseWindowController):

    fileNameKey = "%s.lastSavedFileName" % defaultKey

    def __init__(self, font):
        self.font = None
        self._glyphs = []

        statusBarHeight = 20

        self.w = Window((900, 700), "Glyph Builder", minSize=(400, 400))
        self.w.getNSWindow().setCollectionBehavior_(
            128)  # NSWindowCollectionBehaviorFullScreenPrimary

        toolbarItems = [
            dict(
                itemIdentifier="save",
                label="Save",
                imageNamed="toolbarScriptSave",
                callback=self.saveFile,
            ),
            dict(
                itemIdentifier="open",
                label="Open",
                imageNamed="toolbarScriptOpen",
                callback=self.openFile,
            ),
            dict(itemIdentifier=NSToolbarSpaceItemIdentifier),
            dict(
                itemIdentifier="reload",
                label="Update",
                imageNamed="toolbarScriptReload",
                callback=self.reload,
            ),
            dict(itemIdentifier=NSToolbarSpaceItemIdentifier),
            dict(
                itemIdentifier="analyse",
                label="Analyse",
                imageNamed="prefToolbarSort",
                callback=self.analyse,
            ),
            dict(itemIdentifier=NSToolbarFlexibleSpaceItemIdentifier),
            dict(itemIdentifier="buildGlyphs",
                 label="Build Glyphs",
                 imageNamed="toolbarRun",
                 callback=self.generateGlyphs),
        ]
        self.w.addToolbar(toolbarIdentifier="GlyphBuilderControllerToolbar",
                          toolbarItems=toolbarItems,
                          addStandardItems=False)

        self.constructions = CodeEditor((0, 0, -0, -0),
                                        constructions,
                                        lexer=GlyphConstructionLexer())
        # self.constructions.wrapWord(False) # in only availbel in the RoboFont 1.7 beta

        self.constructions.getNSScrollView().setBorderType_(NSNoBorder)
        self.preview = MultiLineView(
            (0, 0, -0, -0),
            pointSize=50,
            lineHeight=500,
            applyKerning=False,
            displayOptions={
                "Beam": False,
                "displayMode": "Multi Line"
            },
            selectionCallback=self.previewSelectionCallback)

        self.analyser = AnalyserTextEditor((0, 0, -0, -0), readOnly=True)
        self.analyserPreview = Group((0, 0, -0, -0))

        constructionColor = NSColor.colorWithCalibratedRed_green_blue_alpha_(
            0, 0, 0, .6)
        self.analyserPreview.construction = GlyphPreview(
            (0, 0, -0, -0),
            contourColor=constructionColor,
            componentColor=constructionColor)
        self.analyserPreview.construction.getNSView()._buffer = 100
        originColor = NSColor.colorWithCalibratedRed_green_blue_alpha_(
            1, 0, 0, .6)
        self.analyserPreview.origin = GlyphPreview((0, 0, -0, -0),
                                                   contourColor=originColor,
                                                   componentColor=originColor)
        self.analyserPreview.origin.getNSView()._buffer = 100

        self.analyserPreview.build = Button((10, -30, -10, 20),
                                            "Build",
                                            sizeStyle="small",
                                            callback=self.buildSingleGlyph)
        self.analyserPreview.build.enable(False)

        paneDescriptions = [
            dict(view=self.analyser,
                 identifier="analyserText",
                 canCollapse=False,
                 minSize=100),
            dict(view=self.analyserPreview,
                 identifier="analyserPreview",
                 canCollapse=False,
                 minSize=100),
        ]
        self.analyserSplit = Splitter((0, 0, -0, -statusBarHeight),
                                      paneDescriptions=paneDescriptions,
                                      drawBorderLine=False,
                                      isVertical=False,
                                      dividerThickness=1)

        paneDescriptions = [
            dict(view=self.constructions,
                 identifier="constructions",
                 canCollapse=False,
                 minSize=200,
                 maxSize=600,
                 liveResizeable=False),
            dict(view=self.preview,
                 identifier="preview",
                 canCollapse=False,
                 minSize=300,
                 liveResizeable=True),
            dict(view=self.analyserSplit,
                 identifier="analyser",
                 canCollapse=True,
                 minSize=100,
                 maxSize=300,
                 liveResizeable=False)
        ]
        self.w.split = Splitter((0, 0, -0, -statusBarHeight),
                                paneDescriptions=paneDescriptions,
                                drawBorderLine=False,
                                dividerThickness=1)
        # self.w.split.showPane("analyser", True)

        self.w.statusBar = StatusBar(
            (0, -statusBarHeight, -0, statusBarHeight))
        self.w.statusBar.hiddenReload = Button((0, 0, -0, -0), "Reload",
                                               self.reload)
        button = self.w.statusBar.hiddenReload.getNSButton()
        button.setBezelStyle_(NSRoundRectBezelStyle)
        button.setAlphaValue_(0)
        self.w.statusBar.hiddenReload.bind("\r", ["command"])

        self.w.statusBar.hiddenSave = Button((0, 0, -0, -0), "Reload",
                                             self.saveFile)
        button = self.w.statusBar.hiddenSave.getNSButton()
        button.setBezelStyle_(NSRoundRectBezelStyle)
        button.setAlphaValue_(0)
        self.w.statusBar.hiddenSave.bind("s", ["command"])

        self.subscribeFont(font)
        self.setUpBaseWindowBehavior()

        addObserver(self, "fontBecameCurrent", "fontBecameCurrent")
        addObserver(self, "fontResignCurrent", "fontResignCurrent")
        self.w.open()

    def subscribeFont(self, font):
        self.unsubscribeFont()
        self.font = font
        if font is not None:
            self.preview.setFont(font)
            self.font.naked().addObserver(self, "fontChanged", "Font.Changed")
        self.constructionsCallback(self.constructions)

    def unsubscribeFont(self):
        if self.font is not None:
            self.preview.setFont(None)
            self.preview.set([])
            self.font.removeObserver(self, notification="Font.Changed")
            self.font = None

    def constructionsCallback(self, sender, update=True):
        if self.font is None:
            return

        font = self.font.naked()

        self.glyphConstructorFont = GlyphConstructorFont(font)

        self._glyphs = []
        errors = []

        try:
            constructions = ParseGlyphConstructionListFromString(
                sender.get(), font)
        except GlyphBuilderError as err:
            constructions = []
            errors.append(str(err))

        for construction in constructions:
            if not construction:
                glyph = self.preview.createNewLineGlyph()
            elif construction in self.glyphConstructorFont.glyphsDone:
                glyph = self.glyphConstructorFont.glyphsDone[construction]
            else:
                try:
                    constructionGlyph = GlyphConstructionBuilder(
                        construction,
                        self.glyphConstructorFont,
                        characterMap=None)
                except GlyphBuilderError as err:
                    errors.append(str(err))
                    continue

                if constructionGlyph.name is None:
                    errors.append(construction)
                    continue

                if RoboFontVersion < "2.0":
                    glyph = font._instantiateGlyphObject()
                else:
                    glyph = font.layers.defaultLayer.instantiateGlyphObject()
                glyph.name = constructionGlyph.name
                glyph.unicode = constructionGlyph.unicode
                glyph.note = constructionGlyph.note
                glyph.markColor = constructionGlyph.markColor
                if RoboFontVersion < "2.0":
                    glyph.setParent(self.glyphConstructorFont)
                    glyph.dispatcher = font.dispatcher
                else:
                    glyph._font = weakref.ref(self.glyphConstructorFont)
                    # glyph._dispatcher = font._dispatcher

                glyph.width = constructionGlyph.width
                constructionGlyph.draw(glyph.getPen())

                self.glyphConstructorFont.glyphsDone[glyph.name] = glyph

            self._glyphs.append(glyph)

        if errors:
            print("Errors:")
            print("\n".join(errors))

        if update:
            self.preview.set(self._glyphs)

        self.analyser.set(analyseConstructions(font, self._glyphs))

    # preview

    def previewSelectionCallback(self, sender):
        def _niceNumber(value):
            i = int(value)
            if i == value:
                return "%i" % value
            else:
                return "%.2f" % value

        glyph = sender.getSelectedGlyph()

        if glyph is not None and glyph.name is None:
            glyph = None

        status = []

        if glyph is not None:
            width = _niceNumber(glyph.width)
            leftMargin = _niceNumber(glyph.leftMargin)
            rightMargin = _niceNumber(glyph.rightMargin)

            status = [
                glyph.name,
                "width: %s left: %s right: %s" %
                (width, leftMargin, rightMargin),
                "components: %s" % (", ".join(
                    [component.baseGlyph for component in glyph.components]))
            ]
            if glyph.unicode:
                status.append("unicode: %04X" % glyph.unicode)
            if glyph.note:
                status.append("note: %s" %
                              (glyph.note[:30] +
                               (glyph.note[30:] and unichr(0x2026))))
            if glyph.markColor:
                status.append("mark: %s" %
                              ", ".join([str(c) for c in glyph.markColor]))

        self.w.statusBar.set(status)

        self.analyserPreview.construction.setGlyph(glyph)

        self.analyserPreview.build.enable(glyph is not None)

        if glyph is not None:
            self.analyserPreview.build.setTitle("Build %s" % glyph.name)
        else:
            self.analyserPreview.build.setTitle("Build")

        if glyph is not None and glyph.name in self.font:
            self.analyserPreview.origin.setGlyph(self.font[glyph.name])
        else:
            self.analyserPreview.origin.setGlyph(None)

    def buildSingleGlyph(self, sender):
        glyph = self.preview.getSelectedGlyph()
        if glyph is None:
            return
        if self.font is None:
            return

        dest = self.font.newGlyph(glyph.name)
        dest.clear()

        glyph.draw(dest.getPen())

        dest.unicode = glyph.unicode
        dest.note = glyph.note
        if glyph.markColor:
            dest.markColor = glyph.markColor
        dest.width = glyph.width

    # toolbar

    def generateGlyphs(self, sender):
        self.reload(update=False)

        if not self._glyphs:
            return

        if self.font is None:
            return

        BuildGlyphsSheet(self._glyphs, self.font, self.w)

    def reload(self, sender=None, update=True):
        self.constructionsCallback(self.constructions, update)

    def _saveFile(self, path):
        if self.font is not None:
            self.font.lib[self.fileNameKey] = os.path.splitext(
                os.path.basename(path))[0]
        txt = self.constructions.get()
        f = open(path, "w")
        f.write(txt)
        f.close()

    def saveFile(self, sender=None):
        preferredName = None
        if self.font is not None and self.font.path is not None:
            preferredName = os.path.splitext(os.path.basename(
                self.font.path))[0]
            if self.fileNameKey in self.font.lib.keys():
                # see if we have saved this file before and use that as first choice
                preferredName = self.font.lib.get(self.fileNameKey)
        self.showPutFile(["glyphConstruction"],
                         fileName=preferredName,
                         callback=self._saveFile)

    def _openFile(self, paths):
        if paths:
            path = paths[0]
            f = open(path, "r")
            txt = f.read()
            f.close()

            self.constructions.set(txt)

    def openFile(self, sender=None):
        directory = fileName = None
        if self.font is not None and self.font.path is not None:
            if self.fileNameKey in self.font.lib.keys():
                fileName = self.font.lib.get(self.fileNameKey, "")
                fileName += ".glyphConstruction"
                directory = os.path.dirname(self.font.path)
                fileName = os.path.join(directory, fileName)
                directory = None
        getFile(fileTypes=["glyphConstruction"],
                parentWindow=self.w.getNSWindow(),
                directory=directory,
                fileName=fileName,
                resultCallback=self._openFile)
        # self.showGetFile(["glyphConstruction"], callback=self._openFile)

    def analyse(self, sender=None):
        self.w.split.togglePane("analyser", False)
        self.reload()

    # notifications

    def fontChanged(self, notification):
        self.reload()

    def fontBecameCurrent(self, notification):
        font = notification["font"]
        self.subscribeFont(font)

    def fontResignCurrent(self, notification):
        self.unsubscribeFont()

    def windowCloseCallback(self, sender):
        self.unsubscribeFont()
        removeObserver(self, "fontBecameCurrent")
        removeObserver(self, "fontResignCurrent")
        super(GlyphBuilderController, self).windowCloseCallback(sender)
Example #5
0
    def __init__(self):
        self.font = CurrentFont()
        self.glyph = CurrentGlyph()
        self.upm = self.font.info.unitsPerEm
        self.rf3 = int(roboFontVersion.split(".")[0]) >= 3
        if self.rf3:
            self.layer = CurrentLayer()
        # key: glyph name -- value: list containing assembled glyphs
        self.glyphPreviewCacheDict = {}
        # key: anchor name -- value: list of mark glyph names
        self.anchorsOnMarksDict = {}
        # key: anchor name -- value: list of base glyph names
        self.anchorsOnBasesDict = {}
        self.CXTanchorsOnBasesDict = {}
        # key: mark glyph name -- value: anchor name
        # NOTE: It's expected that each mark glyph only has one type of anchor
        self.marksDict = {}
        self.fillAnchorsAndMarksDicts()
        # list of glyph names that will be displayed in the UI list
        self.glyphNamesList = []
        # list of glyph names selected in the UI list
        self.selectedGlyphNamesList = []
        # list of the glyph objects that should be inserted
        # before and after the accented glyphs
        self.extraGlyphsList = []

        self.Blue, self.Alpha = 1, 0.6

        self.font.naked().addObserver(self, "fontWasModified", "Font.Changed")
        addObserver(self, "_fontWillClose", "fontWillClose")
        addObserver(self, "_currentFontChanged", "fontResignCurrent")
        addObserver(self, "_currentGlyphChanged", "currentGlyphChanged")
        addObserver(self, "_drawFill", "draw")
        addObserver(self, "_drawFill", "drawInactive")
        addObserver(self, "_previewFill", "drawPreview")
        # observer for the draw event
        addObserver(self, "_drawGlyphs", "draw")
        # draw the glyphs when the glyph window is not in focus
        addObserver(self, "_drawGlyphs", "drawInactive")
        addObserver(self, "_drawGlyphs", "drawPreview")

        integerNumFormatter = NSNumberFormatter.alloc().init()
        integerNumFormatter.setAllowsFloats_(False)
        integerNumFormatter.setGeneratesDecimalNumbers_(False)

        intPosMinZeroNumFormatter = NSNumberFormatter.alloc().init()
        intPosMinZeroNumFormatter.setAllowsFloats_(False)
        intPosMinZeroNumFormatter.setGeneratesDecimalNumbers_(False)
        intPosMinZeroNumFormatter.setMinimum_(NSNumber.numberWithInt_(0))

        intPosMinOneNumFormatter = NSNumberFormatter.alloc().init()
        intPosMinOneNumFormatter.setAllowsFloats_(False)
        intPosMinOneNumFormatter.setGeneratesDecimalNumbers_(False)
        intPosMinOneNumFormatter.setMinimum_(NSNumber.numberWithInt_(1))

        self.textSize = getExtensionDefault("%s.%s" %
                                            (extensionKey, "textSize"))
        if not self.textSize:
            self.textSize = 150

        self.lineHeight = getExtensionDefault("%s.%s" %
                                              (extensionKey, "lineHeight"))
        if not self.lineHeight:
            self.lineHeight = 200

        self.extraSidebearings = getExtensionDefault(
            "%s.%s" % (extensionKey, "extraSidebearings"))
        if not self.extraSidebearings:
            self.extraSidebearings = [0, 0]

        self.extraGlyphs = getExtensionDefault("%s.%s" %
                                               (extensionKey, "extraGlyphs"))
        if not self.extraGlyphs:
            self.extraGlyphs = ''

        posSize = getExtensionDefault("%s.%s" % (extensionKey, "posSize"))
        if not posSize:
            posSize = (100, 100, 1200, 400)

        self.calibrateMode = getExtensionDefault(
            "%s.%s" % (extensionKey, "calibrateMode"))
        if not self.calibrateMode:
            self.calibrateMode = False

        calibrateModeStrings = getExtensionDefault(
            "%s.%s" % (extensionKey, "calibrateModeStrings"))
        if not calibrateModeStrings:
            calibrateModeStrings = {
                'group1.baseInput': 'dotlessi o s',
                'group1.markInput': 'dieresis circumflex macron breve caron',
                'group2.baseInput': 'I O S',
                'group2.markInput': 'dieresis.cap circumflex.cap macron.cap '
                'breve.cap caron.cap',
                'group3.baseInput': 'I.sc O.sc S.sc',
                'group3.markInput': 'dieresis circumflex macron breve caron',
                'group4.baseInput': '',
                'group4.markInput': '',
            }

        # -- Window --
        self.w = FloatingWindow(posSize, extensionName, minSize=(500, 400))
        self.w.fontList = List((10, 10, 190, -41),
                               self.glyphNamesList,
                               selectionCallback=self.listSelectionCallback)
        if roboFontVersion < '1.7':
            # use the full width of the column
            self.w.fontList.getNSTableView().sizeToFit()
        self.w.fontList.show(not self.calibrateMode)
        self.w.lineView = MultiLineView((210, 10, -10, -41),
                                        pointSize=self.textSize,
                                        lineHeight=self.lineHeight,
                                        displayOptions={
                                            "Beam": False,
                                            "displayMode": "Multi Line"
                                        })
        self.w.lineView.setFont(self.font)
        # -- Calibration Mode --
        baseLabel = "Bases"
        markLabel = "Marks"
        width, height = 190, 140
        self.cm = Group((0, 0, 0, 0))
        # ---
        self.cm.group1 = Group((5, height * 0, width, height - 10))
        self.cm.group1.baseLabel = TextBox((0, 0, width, 20), baseLabel)
        self.cm.group1.baseInput = EditText(
            (0, 21, width, 22),
            calibrateModeStrings['group1.baseInput'],
            callback=self.updateCalibrateMode,
            continuous=False)
        self.cm.group1.markLabel = TextBox((0, 50, width, 20), markLabel)
        self.cm.group1.markInput = EditText(
            (0, 71, width, 44),
            calibrateModeStrings['group1.markInput'],
            callback=self.updateCalibrateMode,
            continuous=False)
        self.cm.group1.divider = HorizontalLine((0, -1, -0, 1))
        # ---
        self.cm.group2 = Group((5, height * 1, width, height - 10))
        self.cm.group2.baseLabel = TextBox((0, 0, width, 20), baseLabel)
        self.cm.group2.baseInput = EditText(
            (0, 21, width, 22),
            calibrateModeStrings['group2.baseInput'],
            callback=self.updateCalibrateMode,
            continuous=False)
        self.cm.group2.markLabel = TextBox((0, 50, width, 20), markLabel)
        self.cm.group2.markInput = EditText(
            (0, 71, width, 44),
            calibrateModeStrings['group2.markInput'],
            callback=self.updateCalibrateMode,
            continuous=False)
        self.cm.group2.divider = HorizontalLine((0, -1, -0, 1))
        # ---
        self.cm.group3 = Group((5, height * 2, width, height - 10))
        self.cm.group3.baseLabel = TextBox((0, 0, width, 20), baseLabel)
        self.cm.group3.baseInput = EditText(
            (0, 21, width, 22),
            calibrateModeStrings['group3.baseInput'],
            callback=self.updateCalibrateMode,
            continuous=False)
        self.cm.group3.markLabel = TextBox((0, 50, width, 20), markLabel)
        self.cm.group3.markInput = EditText(
            (0, 71, width, 44),
            calibrateModeStrings['group3.markInput'],
            callback=self.updateCalibrateMode,
            continuous=False)
        self.cm.group3.divider = HorizontalLine((0, -1, -0, 1))
        # ---
        self.cm.group4 = Group((5, height * 3, width, height - 10))
        self.cm.group4.baseLabel = TextBox((0, 0, width, 20), baseLabel)
        self.cm.group4.baseInput = EditText(
            (0, 21, width, 22),
            calibrateModeStrings['group4.baseInput'],
            callback=self.updateCalibrateMode,
            continuous=False)
        self.cm.group4.markLabel = TextBox((0, 50, width, 20), markLabel)
        self.cm.group4.markInput = EditText(
            (0, 71, width, 44),
            calibrateModeStrings['group4.markInput'],
            callback=self.updateCalibrateMode,
            continuous=False)
        # ---
        view = DefconAppKitTopAnchoredNSView.alloc().init()
        view.addSubview_(self.cm.getNSView())
        view.setFrame_(((0, 0), (width + 10, height * 4 - 23)))
        self.cm.setPosSize((0, 0, width + 10, height * 4 - 22))
        self.w.scrollView = ScrollView((5, 10, width + 10, -41),
                                       view,
                                       drawsBackground=False,
                                       hasHorizontalScroller=False)
        self.w.scrollView.getNSScrollView().setBorderType_(NSNoBorder)
        # NSScrollElasticityNone
        self.w.scrollView.getNSScrollView().setVerticalScrollElasticity_(1)
        self.w.scrollView.show(self.calibrateMode)

        # -- Footer --
        self.w.footer = Group((10, -32, -10, -10))
        self.w.footer.calibrateModeCheck = CheckBox(
            (0, 0, 200, -0),
            "Calibration Mode",
            callback=self.calibrateModeCallback,
            value=self.calibrateMode)
        self.w.footer.textSizeLabel = TextBox((200, 2, 100, -0), "Text Size")
        self.w.footer.textSize = EditText((260, 0, 35, -0),
                                          self.textSize,
                                          callback=self.textSizeCallback,
                                          continuous=False,
                                          formatter=intPosMinOneNumFormatter)
        self.w.footer.lineHeightLabel = TextBox((310, 2, 100, -0),
                                                "Line Height")
        self.w.footer.lineHeight = EditText((385, 0, 35, -0),
                                            self.lineHeight,
                                            callback=self.lineHeightCallback,
                                            continuous=False,
                                            formatter=integerNumFormatter)
        self.w.footer.extraSidebearingsLabel = TextBox((436, 2, 180, -0),
                                                       "Extra Sidebearings")
        self.w.footer.extraSidebearingsChar = TextBox((592, 2, 20, -0), "&")
        self.w.footer.extraSidebearingLeft = EditText(
            (557, 0, 35, -0),
            self.extraSidebearings[0],
            callback=self.extraSidebearingsCallback,
            continuous=False,
            formatter=intPosMinZeroNumFormatter)
        self.w.footer.extraSidebearingRight = EditText(
            (604, 0, 35, -0),
            self.extraSidebearings[1],
            callback=self.extraSidebearingsCallback,
            continuous=False,
            formatter=intPosMinZeroNumFormatter)
        self.w.footer.extraGlyphsLabel = TextBox((655, 2, 180, -0),
                                                 "Extra Glyphs")
        self.w.footer.extraGlyphs = EditText((739, 0, -0, -0),
                                             self.extraGlyphs,
                                             callback=self.extraGlyphsCallback,
                                             continuous=False)

        # trigger the initial state and contents of the window
        self.extraGlyphsCallback()  # calls self.updateExtensionWindow()

        self.w.bind("close", self.windowClose)
        self.w.open()
        self.w.makeKey()
Example #6
0
    def __init__(self, ):
        self.obfuscated = False
        self.events = [
            ('updateFontList','fontDidOpen'),
            ('updateFontList','fontDidClose')
        ]
        self.builtGlyphs = {}
        self.copiedDefinitions = None
        self.fonts = fonts = AllFonts()
        self.controlGlyph = 'H'

        if not len(fonts):
            print '## Derivative Glyph Builder ##\nNo open fonts.'
            return

        f = fonts[0]
        self.collectFontData(f)

        m = 20
        self.w = FloatingWindow((700, 700), 'Derivative Glyphs Builder %s' % (DGBVersion), minSize=(600, 700))
        self.w.inner = Group((m, m, -m, -15))
#        self.w.inner.fontName = TextBox((0, 0, -0, 20), '%s %s' % (f.info.familyName.upper(), f.info.styleName.upper()))
        self.w.inner.fonts = PopUpButton((0, 0, -250, 20), listFontNames(fonts), callback=self.changeCurrentFont)
        self.w.inner.derivatives = List((0, 35, -360, 330),
            self.buildDerivativesUIList(self.derivatives),
            selectionCallback=self.selectDerivativeGlyph,
            editCallback=self.editDerivativeGlyphNames,
            columnDescriptions=[{'title':'Derivative Glyph', 'width':130}, {'title':'Base Glyphs'}])

        self.w.inner.addDefinition = SquareButton((0, 365, -500, 20), 'Add', callback=self.addDefinition, sizeStyle='small')
        self.w.inner.removeDefinition = SquareButton((-500, 365, 140, 20), 'Remove', callback=self.removeDefinition, sizeStyle='small')
        self.w.inner.definition = Box((-340, 35, -0, 350))
        m = 15
        self.w.inner.definition.inner = Group((m, m, -m, 0))

        self.w.inner.previewTop = HorizontalLine((0, 399, -0, 1))
        self.w.inner.preview = MultiLineView((0, 400, -0, -40), hasHorizontalScroller=True, hasVerticalScroller=False)
        self.w.inner.previewBottom = HorizontalLine((0, -40, -0, 1))
        self.w.inner.preview.setDisplayMode('Single Line')
        displayStates = self.w.inner.preview.getDisplayStates()
        displayStates['Show Metrics'] = True
        self.w.inner.preview.setDisplayStates(displayStates)
        self.w.inner.preview.setCanSelect(True)

        self.w.inner.preview._glyphLineView._italicAngle = self.tempFont.info.italicAngle
        self.w.inner.preview._glyphLineView._italicSlantOffset = self.tempFont.lib['com.typemytype.robofont.italicSlantOffset']

        self.w.inner.controlGlyphTitle = TextBox((0, -18, 80, 14), 'Control glyph', sizeStyle='small')
        self.w.inner.controlGlyph = EditText((80, -22, 90, 22), text='H', callback=self.changeControlGlyph, continuous=False)

        self.w.inner.buildSelectedGlyphs = Button((-200, -22, 200, 20), 'Build selected glyphs', callback=self.buildSelectedGlyphs)

        self.w.inner.copySelectedDefinitions = Button((-230, 0, 120, 20), 'Copy', callback=self.copySelectedDefinitions)
        self.w.inner.pasteDefinitions = Button((-100, 0, 100, 20), 'Paste', callback=self.pasteDefinitions)
        self.w.inner.pasteDefinitions.enable(False)

        self.buildDefinitionSheet()

        for callback, event in self.events:
            addObserver(self, callback, event)

        self.w.bind('close', self.endOperations)
        self.w.open()
Example #7
0
    def __init__(self):
        self.w = Window((180, 340),
                        u'Touché!',
                        minSize=(180, 340),
                        maxSize=(1000, 898))
        p = 10
        w = 160

        # options
        self.w.options = Group((0, 0, 180, 220))

        buttons = {
            "checkSelBtn": {
                "text": "Check selected glyphs\nfor touching pairs",
                "callback": self.checkSel,
                "y": p
            },
            "checkAllBtn": {
                "text": "Check entire font\n(can take several minutes!)",
                "callback": self.checkAll,
                "y": 60
            }
        }
        for button, data in buttons.items():
            setattr(
                self.w.options, button,
                SquareButton((p, data["y"], w, 40),
                             data["text"],
                             callback=data["callback"],
                             sizeStyle="small"))

        self.w.options.zeroCheck = CheckBox((p, 108, w, 20),
                                            "Ignore zero-width glyphs",
                                            value=True,
                                            sizeStyle="small")
        self.w.options.progress = ProgressSpinner((82, 174, 16, 16),
                                                  sizeStyle="small")

        # results
        self.w.results = Group((0, 220, 180, -0))
        self.w.results.show(False)

        textBoxes = {"stats": 24, "result": 42}
        for box, y in textBoxes.items():
            setattr(self.w.results, box,
                    TextBox((p, y, w, 14), "", sizeStyle="small"))

        moreButtons = {
            "spaceView": {
                "text": "View all in Space Center",
                "callback": self.showAllPairs,
                "y": 65
            },
            "exportTxt": {
                "text": "Export as MM pair list",
                "callback": self.exportPairList,
                "y": 90
            }
        }
        for button, data in moreButtons.items():
            setattr(
                self.w.results, button,
                SquareButton((p, data["y"], w, 20),
                             data["text"],
                             callback=data["callback"],
                             sizeStyle="small"))

        # list and preview
        self.w.outputList = List((180, 0, 188, -0), [{
            "left glyph": "",
            "right glyph": ""
        }],
                                 columnDescriptions=[{
                                     "title": "left glyph"
                                 }, {
                                     "title": "right glyph"
                                 }],
                                 showColumnTitles=False,
                                 allowsMultipleSelection=False,
                                 enableDelete=False,
                                 selectionCallback=self.showPair)
        self.w.preview = MultiLineView((368, 0, -0, -0), pointSize=256)

        self.w.open()
Example #8
0
    def __init__(self, RCJKI):
        self.RCJKI = RCJKI
        self.w = Window((800, 300), "Text Center", minSize = (400, 320))
        self.w.leftInput = EditText(
            (0, 0, 60, 20),
            "",
            callback = self.inputCallback
            )
        self.w.input = EditText(
            (60, 0, -60, 20),
            "",
            callback = self.inputCallback
            )
        self.pointsSize = [9, 10, 11, 12, 14, 16, 18, 20, 24, 30, 36, 48, 60, 72, 96, 144, 256, 512, 1024],
        self.w.pointSize = ComboBox(
            (-60, 0, -0, 20),
            *self.pointsSize,
            callback = self.pointSizeCallback
            )
        self.w.pointSize.set(72)
        self.displayOptions = {
                'displayMode': 'Multi Line', #
                'Show Kerning': True, 
                'Multi Line': True, #
                'xHeight Cut': False, 
                'Water Fall': False, #
                'Single Line': True, #
                'Inverse': False, 
                'Show Metrics': False, 
                'Left to Right': True, 
                'Right to Left': False, 
                'Center': False, # 
                'Upside Down': False, 
                'Stroke': False, 
                'Fill': False, 
                'Beam': False, 
                'Guides': False, 
                'Blues': False, 
                'Family Blues': False, 
                'Show Control glyphs': True, 
                'Show Space Matrix': True, 
                'Show Template Glyphs': True, 
                'showLayers': []
                }
        self.w.multiLineView = MultiLineView(
            (200, 20, -0, -0),
            pointSize=72,
            displayOptions = self.displayOptions
            )
        self.w.multiLineView.setFont(self.RCJKI.currentFont._fullRFont)
        self.w.multiLineView.setLineHeight(200)

        self.sourcesList = []
        if self.RCJKI.currentFont.fontVariations:
            self.sourcesList = [dict(Axis = x, PreviewValue = 0) for x in self.RCJKI.currentFont.fontVariations]

        slider = SliderListCell(minValue = 0, maxValue = 1)
        self.w.sourcesList = List(
            (0, 20, 200, 90),
            self.sourcesList, 
            columnDescriptions = [
                    {"title": "Axis", "editable": False, "width": 60},
                    {"title": "PreviewValue", "cell": slider}],
            showColumnTitles = False,
            editCallback = self.sourcesListEditCallback,
            allowsMultipleSelection = False
            )

        self.accordionViewDescriptions = [

                        dict(label="Display options", 
                            view=displayModeGroup((0, 0, -0, -0), self), 
                            size=100, 
                            collapsed=True, 
                            canResize=0),

                        dict(label="Glyphs that use:", 
                            view=GlyphUsingDC((0, 0, -0, -0), self), 
                            size=180, 
                            collapsed=True, 
                            canResize=1),

                        dict(label="Deep components that use:", 
                            view=DCUsingAE((0, 0, -0, -0), self), 
                            size=180, 
                            collapsed=True, 
                            canResize=1),
                       ]

        self.w.accordionView = AccordionView((0, 120, 200, -0),
            self.accordionViewDescriptions,
            )

        self.observer()
        self.w.open()
        self.w.bind("close", self.windowWillClose)
    def __init__(self, font):    
        self.font = None
        self._glyphs = []
        
        statusBarHeight = 20
                        
        self.w = Window((900, 700), "Glyph Builder", minSize=(400, 400))
        
        if NSApp().runningOnLion():
            self.w.getNSWindow().setCollectionBehavior_(128) #NSWindowCollectionBehaviorFullScreenPrimary
        
        toolbarItems = [
                        dict(itemIdentifier="save",
                            label="Save",
                            imageNamed="toolbarScriptSave",
                            callback=self.saveFile,
                            ),
                        dict(itemIdentifier="open",
                            label="Open",
                            imageNamed="toolbarScriptOpen",
                            callback=self.openFile,
                            ),
                        dict(itemIdentifier=NSToolbarSpaceItemIdentifier),
                        dict(itemIdentifier="reload",
                            label="Update",
                            imageNamed="toolbarScriptReload",
                            callback=self.reload,
                            ),
                        dict(itemIdentifier=NSToolbarSpaceItemIdentifier),
                        dict(itemIdentifier="analyse",
                            label="Analyse",
                            imageNamed="prefToolbarSort",
                            callback=self.analyse,
                            ),
                        dict(itemIdentifier=NSToolbarFlexibleSpaceItemIdentifier),
                        dict(itemIdentifier="buildGlyphs",
                             label="Build Glyphs",
                             imageNamed="toolbarRun",
                             callback=self.generateGlyphs
                             ),
                        ]
        toolbar = self.w.addToolbar(toolbarIdentifier="GlyphBuilderControllerToolbar", toolbarItems=toolbarItems, addStandardItems=False)
        
        self.constructions = CodeEditor((0, 0, -0, -0),constructions, lexer=GlyphConstructionLexer())
        #self.constructions.wrapWord(False) # in only availbel in the RoboFont 1.7 beta
        
        self.constructions.getNSScrollView().setBorderType_(NSNoBorder)
        self.preview = MultiLineView((0, 0, -0, -0), 
                                     pointSize=50, 
                                     lineHeight=500, 
                                     applyKerning=False, 
                                     displayOptions={"Beam" : False,
                                                     "displayMode" : "Multi Line"},
                                     selectionCallback=self.previewSelectionCallback)

        
        self.analyser = AnalyserTextEditor((0, 0, -0, -0), readOnly=True)
        self.analyserPreview = Group((0, 0, -0, -0))
        
        
        self.analyserPreview.construction = GlyphPreview((0, 0, -0, -0), contourColor=NSColor.redColor(), componentColor=NSColor.redColor())
        self.analyserPreview.construction.getNSView()._buffer = 100
        self.analyserPreview.origin = GlyphPreview((0, 0, -0, -0),contourColor=NSColor.blackColor(), componentColor=NSColor.blackColor())
        self.analyserPreview.origin.getNSView()._buffer = 100
        
        self.analyserPreview.build = Button((10, -25, -10, 19), "Build", sizeStyle="small", callback=self.buildSingleGlyph) 
        self.analyserPreview.build.enable(False)
        
        paneDescriptions = [
                    dict(view=self.analyser, identifier="analyserText", canCollapse=False, minSize=100),
                    dict(view=self.analyserPreview, identifier="analyserPreview", canCollapse=False, minSize=100),
                    ]
        
        self.analyserSplit = Splitter((0, 0, -0, -statusBarHeight), paneDescriptions=paneDescriptions, drawBorderLine=False, isVertical=False, dividerThickness=1)
        
        
        paneDescriptions = [
                    dict(view=self.constructions, identifier="constructions", canCollapse=False, minSize=200, maxSize=600, liveResizeable=False),
                    dict(view=self.preview, identifier="preview", canCollapse=False, minSize=300, liveResizeable=True),
                    dict(view=self.analyserSplit, identifier="analyser", canCollapse=True, minSize=100, maxSize=300, liveResizeable=False)
                    ]
        
        self.w.split = Splitter((0, 0, -0, -statusBarHeight), paneDescriptions=paneDescriptions, drawBorderLine=False, dividerThickness=1)
        #self.w.split.showPane("analyser", True)
        
        self.w.statusBar = StatusBar((0, -statusBarHeight, -0, statusBarHeight))
        self.w.statusBar.hiddenReload = Button((0, 0, -0, -0), "Reload", self.reload)
        button = self.w.statusBar.hiddenReload.getNSButton()
        button.setBezelStyle_(NSRoundRectBezelStyle)
        button.setAlphaValue_(0)
        self.w.statusBar.hiddenReload.bind("\r", ["command"])
        
        self.w.statusBar.hiddenSave = Button((0, 0, -0, -0), "Reload", self.saveFile)
        button = self.w.statusBar.hiddenSave.getNSButton()
        button.setBezelStyle_(NSRoundRectBezelStyle)
        button.setAlphaValue_(0)
        self.w.statusBar.hiddenSave.bind("s", ["command"])
                    
        self.subscribeFont(font)
        self.setUpBaseWindowBehavior()
        
        addObserver(self, "fontBecameCurrent", "fontBecameCurrent")
        addObserver(self, "fontResignCurrent", "fontResignCurrent")
        self.w.open()
class GlyphBuilderController(BaseWindowController):
    
    def __init__(self, font):    
        self.font = None
        self._glyphs = []
        
        statusBarHeight = 20
                        
        self.w = Window((900, 700), "Glyph Builder", minSize=(400, 400))
        
        if NSApp().runningOnLion():
            self.w.getNSWindow().setCollectionBehavior_(128) #NSWindowCollectionBehaviorFullScreenPrimary
        
        toolbarItems = [
                        dict(itemIdentifier="save",
                            label="Save",
                            imageNamed="toolbarScriptSave",
                            callback=self.saveFile,
                            ),
                        dict(itemIdentifier="open",
                            label="Open",
                            imageNamed="toolbarScriptOpen",
                            callback=self.openFile,
                            ),
                        dict(itemIdentifier=NSToolbarSpaceItemIdentifier),
                        dict(itemIdentifier="reload",
                            label="Update",
                            imageNamed="toolbarScriptReload",
                            callback=self.reload,
                            ),
                        dict(itemIdentifier=NSToolbarSpaceItemIdentifier),
                        dict(itemIdentifier="analyse",
                            label="Analyse",
                            imageNamed="prefToolbarSort",
                            callback=self.analyse,
                            ),
                        dict(itemIdentifier=NSToolbarFlexibleSpaceItemIdentifier),
                        dict(itemIdentifier="buildGlyphs",
                             label="Build Glyphs",
                             imageNamed="toolbarRun",
                             callback=self.generateGlyphs
                             ),
                        ]
        toolbar = self.w.addToolbar(toolbarIdentifier="GlyphBuilderControllerToolbar", toolbarItems=toolbarItems, addStandardItems=False)
        
        self.constructions = CodeEditor((0, 0, -0, -0),constructions, lexer=GlyphConstructionLexer())
        #self.constructions.wrapWord(False) # in only availbel in the RoboFont 1.7 beta
        
        self.constructions.getNSScrollView().setBorderType_(NSNoBorder)
        self.preview = MultiLineView((0, 0, -0, -0), 
                                     pointSize=50, 
                                     lineHeight=500, 
                                     applyKerning=False, 
                                     displayOptions={"Beam" : False,
                                                     "displayMode" : "Multi Line"},
                                     selectionCallback=self.previewSelectionCallback)

        
        self.analyser = AnalyserTextEditor((0, 0, -0, -0), readOnly=True)
        self.analyserPreview = Group((0, 0, -0, -0))
        
        
        self.analyserPreview.construction = GlyphPreview((0, 0, -0, -0), contourColor=NSColor.redColor(), componentColor=NSColor.redColor())
        self.analyserPreview.construction.getNSView()._buffer = 100
        self.analyserPreview.origin = GlyphPreview((0, 0, -0, -0),contourColor=NSColor.blackColor(), componentColor=NSColor.blackColor())
        self.analyserPreview.origin.getNSView()._buffer = 100
        
        self.analyserPreview.build = Button((10, -25, -10, 19), "Build", sizeStyle="small", callback=self.buildSingleGlyph) 
        self.analyserPreview.build.enable(False)
        
        paneDescriptions = [
                    dict(view=self.analyser, identifier="analyserText", canCollapse=False, minSize=100),
                    dict(view=self.analyserPreview, identifier="analyserPreview", canCollapse=False, minSize=100),
                    ]
        
        self.analyserSplit = Splitter((0, 0, -0, -statusBarHeight), paneDescriptions=paneDescriptions, drawBorderLine=False, isVertical=False, dividerThickness=1)
        
        
        paneDescriptions = [
                    dict(view=self.constructions, identifier="constructions", canCollapse=False, minSize=200, maxSize=600, liveResizeable=False),
                    dict(view=self.preview, identifier="preview", canCollapse=False, minSize=300, liveResizeable=True),
                    dict(view=self.analyserSplit, identifier="analyser", canCollapse=True, minSize=100, maxSize=300, liveResizeable=False)
                    ]
        
        self.w.split = Splitter((0, 0, -0, -statusBarHeight), paneDescriptions=paneDescriptions, drawBorderLine=False, dividerThickness=1)
        #self.w.split.showPane("analyser", True)
        
        self.w.statusBar = StatusBar((0, -statusBarHeight, -0, statusBarHeight))
        self.w.statusBar.hiddenReload = Button((0, 0, -0, -0), "Reload", self.reload)
        button = self.w.statusBar.hiddenReload.getNSButton()
        button.setBezelStyle_(NSRoundRectBezelStyle)
        button.setAlphaValue_(0)
        self.w.statusBar.hiddenReload.bind("\r", ["command"])
        
        self.w.statusBar.hiddenSave = Button((0, 0, -0, -0), "Reload", self.saveFile)
        button = self.w.statusBar.hiddenSave.getNSButton()
        button.setBezelStyle_(NSRoundRectBezelStyle)
        button.setAlphaValue_(0)
        self.w.statusBar.hiddenSave.bind("s", ["command"])
                    
        self.subscribeFont(font)
        self.setUpBaseWindowBehavior()
        
        addObserver(self, "fontBecameCurrent", "fontBecameCurrent")
        addObserver(self, "fontResignCurrent", "fontResignCurrent")
        self.w.open()
    
    def subscribeFont(self, font):
        self.unsubscribeFont()
        self.font = font
        if font is not None:
            self.preview.setFont(font)
            self.font.naked().addObserver(self, "fontChanged", "Font.Changed")
        self.constructionsCallback(self.constructions)
    
    def unsubscribeFont(self):
        if self.font is not None:
            self.preview.setFont(None)
            self.preview.set([])
            self.font.removeObserver(self, notification="Font.Changed")
            self.font = None
    
    def constructionsCallback(self, sender, update=True):
        if self.font is None:
            return
        
        font = self.font.naked()
        
        self.glyphConstructorFont = GlyphConstructorFont(font)
        
        self._glyphs = []
        errors = []
        
        try:
            constructions = ParseGlyphConstructionListFromString(sender.get())
        except GlyphBuilderError, err:
            constructions = []
            errors.append(str(err))
                        
        for construction in constructions:
            if not construction:
                glyph = self.preview.createNewLineGlyph()
            elif construction in self.glyphConstructorFont.glyphsDone:
                glyph = self.glyphConstructorFont.glyphsDone[construction]
            else:
                try:
                    constructionGlyph = GlyphConstructionBuilder(construction, self.glyphConstructorFont)
                except GlyphBuilderError, err:
                    errors.append(str(err))
                    continue
                
                if constructionGlyph.name is None:
                    errors.append(construction)
                    continue
                
                glyph = font._instantiateGlyphObject()
                glyph.name = constructionGlyph.name
                glyph.unicode = constructionGlyph.unicode
                glyph.note = constructionGlyph.note
                glyph.mark = constructionGlyph.mark
                glyph.setParent(self.glyphConstructorFont)
                glyph.dispatcher = font.dispatcher

                glyph.width = constructionGlyph.width
                constructionGlyph.draw(glyph.getPen())

                self.glyphConstructorFont.glyphsDone[glyph.name] = glyph
            
            self._glyphs.append(glyph)
Example #11
0
    def __init__(self):
        self.value = 150
        self.w = vanilla.Window((700, 210),
                                "Interpol Steps Preview",
                                minSize=(100, 200))

        self.w.infoOutput = TextBox((460, 8, -70, 20),
                                    "Open 2 Fonts + select a glyph.",
                                    alignment="right",
                                    sizeStyle="mini")
        self.w.button = Button((-65, 2, 60, 20),
                               "Options",
                               sizeStyle="small",
                               callback=self.toggleOptions)
        self.d = Drawer((125, 200),
                        self.w,
                        minSize=(125, 100),
                        maxSize=(125, 200),
                        preferredEdge='right',
                        trailingOffset=15,
                        leadingOffset=0)
        self.d.fontSize = TextBox(
            (8, 5, 50, 10),
            "FONTSIZE",
            sizeStyle="mini",
        )
        self.d.lineHeight = TextBox(
            (62, 5, 100, 10),
            "LINEHEIGHT",
            sizeStyle="mini",
        )
        self.d.button3 = SquareButton((10, 20, 25, 18),
                                      "-",
                                      sizeStyle="small",
                                      callback=self.ChangePointSizeMinus)
        self.d.button4 = SquareButton((35, 20, 25, 18),
                                      "+",
                                      sizeStyle="small",
                                      callback=self.ChangePointSizePlus)
        self.d.button5 = SquareButton((65, 20, 25, 18),
                                      "-",
                                      sizeStyle="small",
                                      callback=self.ChangeLineheightMinus)
        self.d.button6 = SquareButton((90, 20, 25, 18),
                                      "+",
                                      sizeStyle="small",
                                      callback=self.ChangeLineheightPlus)
        self.d.interpolStepsText = TextBox((55, 50, 100, 20),
                                           "Interpol Steps",
                                           sizeStyle="mini")
        self.d.extrapolStepsText = TextBox((55, 75, 100, 20),
                                           "Extrapol Steps",
                                           sizeStyle="mini")
        self.d.interpolStepper = EditIntStepper((10, 45, 45, 22),
                                                4,
                                                callback=self.glyphChanged,
                                                minValue=1,
                                                maxValue=30,
                                                sizeStyle='regular')
        self.d.extrapolStepper = EditIntStepper((10, 70, 45, 22),
                                                1,
                                                callback=self.glyphChanged,
                                                minValue=0,
                                                maxValue=20,
                                                sizeStyle='regular')
        self.d.checkBoxInfo = TextBox((10, 98, 100, 20),
                                      "Display Options:",
                                      sizeStyle="mini")
        self.d.checkBoxMetrics = CheckBox((10, 110, 130, 20),
                                          "Metrics",
                                          sizeStyle="small",
                                          callback=self.Metrics)
        self.d.checkBoxR2L = CheckBox((10, 125, 130, 20),
                                      "Right to Left",
                                      sizeStyle="small",
                                      callback=self.R2L)
        self.d.checkBoxInverse = CheckBox((10, 140, 130, 20),
                                          "Inverse",
                                          sizeStyle="small",
                                          callback=self.Inverse)
        self.d.checkBoxStroke = CheckBox((10, 155, 130, 20),
                                         "Stroke",
                                         sizeStyle="small",
                                         callback=self.Stroke)
        self.w.glyphLineView = MultiLineView((0, 25, 0, 0))
        self.w.stemWidthOutputText = TextBox((10, 8, 500, 20),
                                             "Beam Y-Pos:",
                                             sizeStyle="mini")
        self.w.stemWidthBeamX = EditText((70, 3, 30, 19),
                                         "200",
                                         sizeStyle="small",
                                         callback=self.stepsCallback)
        self.w.stemWidthOutput = TextBox(
            (105, 8, -205, 13),
            "Measurements of the 1st stem will be displayed here.",
            sizeStyle="mini")

        events.addObserver(self, "glyphChanged", "currentGlyphChanged")
        self.setUpBaseWindowBehavior()
        self.w.open()
        self.d.open()

        self.listOfValues = []
class GlyphBuilderController(BaseWindowController):

    fileNameKey = "%s.lastSavedFileName" % defaultKey

    def __init__(self, font):
        self.font = None
        self._glyphs = []

        statusBarHeight = 20

        self.w = Window((900, 700), "Glyph Builder", minSize=(400, 400))
        self.w.getNSWindow().setCollectionBehavior_(128)  # NSWindowCollectionBehaviorFullScreenPrimary

        toolbarItems = [
            dict(
                itemIdentifier="save",
                label="Save",
                imageNamed="toolbarScriptSave",
                callback=self.saveFile,
            ),
            dict(
                itemIdentifier="open",
                label="Open",
                imageNamed="toolbarScriptOpen",
                callback=self.openFile,
            ),
            dict(itemIdentifier=NSToolbarSpaceItemIdentifier),
            dict(
                itemIdentifier="reload",
                label="Update",
                imageNamed="toolbarScriptReload",
                callback=self.reload,
            ),
            dict(itemIdentifier=NSToolbarSpaceItemIdentifier),
            dict(
                itemIdentifier="analyse",
                label="Analyse",
                imageNamed="prefToolbarSort",
                callback=self.analyse,
            ),
            dict(itemIdentifier=NSToolbarFlexibleSpaceItemIdentifier),
            dict(
                itemIdentifier="buildGlyphs",
                label="Build Glyphs",
                imageNamed="toolbarRun",
                callback=self.generateGlyphs
            ),
        ]
        self.w.addToolbar(toolbarIdentifier="GlyphBuilderControllerToolbar", toolbarItems=toolbarItems, addStandardItems=False)

        self.constructions = CodeEditor((0, 0, -0, -0), constructions, lexer=GlyphConstructionLexer())
        # self.constructions.wrapWord(False) # in only availbel in the RoboFont 1.7 beta

        self.constructions.getNSScrollView().setBorderType_(NSNoBorder)
        self.preview = MultiLineView(
            (0, 0, -0, -0),
            pointSize=50,
            lineHeight=500,
            applyKerning=False,
            displayOptions={
                "Beam": False,
                "displayMode": "Multi Line"
            },
            selectionCallback=self.previewSelectionCallback
        )

        self.analyser = AnalyserTextEditor((0, 0, -0, -0), readOnly=True)
        self.analyserPreview = Group((0, 0, -0, -0))

        constructionColor = NSColor.colorWithCalibratedRed_green_blue_alpha_(0, 0, 0, .6)
        self.analyserPreview.construction = GlyphPreview((0, 0, -0, -0), contourColor=constructionColor, componentColor=constructionColor)
        self.analyserPreview.construction.getNSView()._buffer = 100
        originColor = NSColor.colorWithCalibratedRed_green_blue_alpha_(1, 0, 0, .6)
        self.analyserPreview.origin = GlyphPreview((0, 0, -0, -0), contourColor=originColor, componentColor=originColor)
        self.analyserPreview.origin.getNSView()._buffer = 100

        self.analyserPreview.build = Button((10, -25, -10, 19), "Build", sizeStyle="small", callback=self.buildSingleGlyph)
        self.analyserPreview.build.enable(False)

        paneDescriptions = [
            dict(view=self.analyser, identifier="analyserText", canCollapse=False, minSize=100),
            dict(view=self.analyserPreview, identifier="analyserPreview", canCollapse=False, minSize=100),
        ]
        self.analyserSplit = Splitter((0, 0, -0, -statusBarHeight), paneDescriptions=paneDescriptions, drawBorderLine=False, isVertical=False, dividerThickness=1)

        paneDescriptions = [
            dict(view=self.constructions, identifier="constructions", canCollapse=False, minSize=200, maxSize=600, liveResizeable=False),
            dict(view=self.preview, identifier="preview", canCollapse=False, minSize=300, liveResizeable=True),
            dict(view=self.analyserSplit, identifier="analyser", canCollapse=True, minSize=100, maxSize=300, liveResizeable=False)
        ]
        self.w.split = Splitter((0, 0, -0, -statusBarHeight), paneDescriptions=paneDescriptions, drawBorderLine=False, dividerThickness=1)
        # self.w.split.showPane("analyser", True)

        self.w.statusBar = StatusBar((0, -statusBarHeight, -0, statusBarHeight))
        self.w.statusBar.hiddenReload = Button((0, 0, -0, -0), "Reload", self.reload)
        button = self.w.statusBar.hiddenReload.getNSButton()
        button.setBezelStyle_(NSRoundRectBezelStyle)
        button.setAlphaValue_(0)
        self.w.statusBar.hiddenReload.bind("\r", ["command"])

        self.w.statusBar.hiddenSave = Button((0, 0, -0, -0), "Reload", self.saveFile)
        button = self.w.statusBar.hiddenSave.getNSButton()
        button.setBezelStyle_(NSRoundRectBezelStyle)
        button.setAlphaValue_(0)
        self.w.statusBar.hiddenSave.bind("s", ["command"])

        self.subscribeFont(font)
        self.setUpBaseWindowBehavior()

        addObserver(self, "fontBecameCurrent", "fontBecameCurrent")
        addObserver(self, "fontResignCurrent", "fontResignCurrent")
        self.w.open()

    def subscribeFont(self, font):
        self.unsubscribeFont()
        self.font = font
        if font is not None:
            self.preview.setFont(font)
            self.font.naked().addObserver(self, "fontChanged", "Font.Changed")
        self.constructionsCallback(self.constructions)

    def unsubscribeFont(self):
        if self.font is not None:
            self.preview.setFont(None)
            self.preview.set([])
            self.font.removeObserver(self, notification="Font.Changed")
            self.font = None

    def constructionsCallback(self, sender, update=True):
        if self.font is None:
            return

        font = self.font.naked()

        self.glyphConstructorFont = GlyphConstructorFont(font)

        self._glyphs = []
        errors = []

        try:
            constructions = ParseGlyphConstructionListFromString(sender.get(), font)
        except GlyphBuilderError as err:
            constructions = []
            errors.append(str(err))

        for construction in constructions:
            if not construction:
                glyph = self.preview.createNewLineGlyph()
            elif construction in self.glyphConstructorFont.glyphsDone:
                glyph = self.glyphConstructorFont.glyphsDone[construction]
            else:
                try:
                    constructionGlyph = GlyphConstructionBuilder(construction, self.glyphConstructorFont)
                except GlyphBuilderError as err:
                    errors.append(str(err))
                    continue

                if constructionGlyph.name is None:
                    errors.append(construction)
                    continue

                if RoboFontVersion < "2.0":
                    glyph = font._instantiateGlyphObject()
                else:
                    glyph = font.layers.defaultLayer.instantiateGlyphObject()
                glyph.name = constructionGlyph.name
                glyph.unicode = constructionGlyph.unicode
                glyph.note = constructionGlyph.note
                glyph.markColor = constructionGlyph.markColor
                if RoboFontVersion < "2.0":
                    glyph.setParent(self.glyphConstructorFont)
                    glyph.dispatcher = font.dispatcher
                else:
                    glyph._font = weakref.ref(self.glyphConstructorFont)
                    # glyph._dispatcher = font._dispatcher

                glyph.width = constructionGlyph.width
                constructionGlyph.draw(glyph.getPen())

                self.glyphConstructorFont.glyphsDone[glyph.name] = glyph

            self._glyphs.append(glyph)

        if errors:
            print("Errors:")
            print("\n".join(errors))

        if update:
            self.preview.set(self._glyphs)

        self.analyser.set(analyseConstructions(font, self._glyphs))

    # preview

    def previewSelectionCallback(self, sender):

        def _niceNumber(value):
            i = int(value)
            if i == value:
                return "%i" % value
            else:
                return "%.2f" % value

        glyph = sender.getSelectedGlyph()

        if glyph is not None and glyph.name is None:
            glyph = None

        status = []

        if glyph is not None:
            width = _niceNumber(glyph.width)
            leftMargin = _niceNumber(glyph.leftMargin)
            rightMargin = _niceNumber(glyph.rightMargin)

            status = [
                glyph.name,
                "width: %s left: %s right: %s" % (width, leftMargin, rightMargin),
                "components: %s" % (", ".join([component.baseGlyph for component in glyph.components]))
            ]
            if glyph.unicode:
                status.append("unicode: %04X" % glyph.unicode)
            if glyph.note:
                status.append("note: %s" % (glyph.note[:30] + (glyph.note[30:] and unichr(0x2026))))
            if glyph.markColor:
                status.append("mark: %s" % ", ".join([str(c) for c in glyph.markColor]))

        self.w.statusBar.set(status)

        self.analyserPreview.construction.setGlyph(glyph)

        self.analyserPreview.build.enable(glyph is not None)

        if glyph is not None:
            self.analyserPreview.build.setTitle("Build %s" % glyph.name)
        else:
            self.analyserPreview.build.setTitle("Build")

        if glyph is not None and glyph.name in self.font:
            self.analyserPreview.origin.setGlyph(self.font[glyph.name])
        else:
            self.analyserPreview.origin.setGlyph(None)

    def buildSingleGlyph(self, sender):
        glyph = self.preview.getSelectedGlyph()
        if glyph is None:
            return
        if self.font is None:
            return

        dest = self.font.newGlyph(glyph.name)
        dest.clear()

        glyph.draw(dest.getPen())

        dest.unicode = glyph.unicode
        dest.note = glyph.note
        if glyph.markColor:
            dest.markColor = glyph.markColor
        dest.width = glyph.width

    # toolbar

    def generateGlyphs(self, sender):
        self.reload(update=False)

        if not self._glyphs:
            return

        if self.font is None:
            return

        BuildGlyphsSheet(self._glyphs, self.font, self.w)

    def reload(self, sender=None, update=True):
        self.constructionsCallback(self.constructions, update)

    def _saveFile(self, path):
        if self.font is not None:
            self.font.lib[self.fileNameKey] = os.path.splitext(os.path.basename(path))[0]
        txt = self.constructions.get()
        f = open(path, "w")
        f.write(txt)
        f.close()

    def saveFile(self, sender=None):
        preferredName = None
        if self.font is not None and self.font.path is not None:
            preferredName = os.path.splitext(os.path.basename(self.font.path))[0]
            if self.fileNameKey in self.font.lib.keys():
                # see if we have saved this file before and use that as first choice
                preferredName = self.font.lib.get(self.fileNameKey)
        self.showPutFile(["glyphConstruction"], fileName=preferredName, callback=self._saveFile)

    def _openFile(self, paths):
        if paths:
            path = paths[0]
            f = open(path, "r")
            txt = f.read()
            f.close()

            self.constructions.set(txt)

    def openFile(self, sender=None):
        directory = fileName = None
        if self.font is not None and self.font.path is not None:
            if self.fileNameKey in self.font.lib.keys():
                fileName = self.font.lib.get(self.fileNameKey, "")
                fileName += ".glyphConstruction"
                directory = os.path.dirname(self.font.path)
                fileName = os.path.join(directory, fileName)
                directory = None
        getFile(fileTypes=["glyphConstruction"], parentWindow=self.w.getNSWindow(), directory=directory, fileName=fileName, resultCallback=self._openFile)
        # self.showGetFile(["glyphConstruction"], callback=self._openFile)

    def analyse(self, sender=None):
        self.w.split.togglePane("analyser", False)
        self.reload()

    # notifications

    def fontChanged(self, notification):
        self.reload()

    def fontBecameCurrent(self, notification):
        font = notification["font"]
        self.subscribeFont(font)

    def fontResignCurrent(self, notification):
        self.unsubscribeFont()

    def windowCloseCallback(self, sender):
        self.unsubscribeFont()
        removeObserver(self, "fontBecameCurrent")
        removeObserver(self, "fontResignCurrent")
        super(GlyphBuilderController, self).windowCloseCallback(sender)
    def __init__(self):
        self.filters = PenBallFiltersManager()
        # self.filters.loadFiltersFromJSON('/'.join([LOCALPATH, JSONFILE]))
        filtersList = getExtensionDefault(
            '{0}.filtersList'.format(PENBALLWIZARD_EXTENSIONKEY), [])
        self.filters.loadFiltersList(filtersList)
        self.glyphNames = []
        self.observedGlyphs = []
        self.currentFont = CurrentFont()
        self.initCachedFont()
        filtersList = self.filters.keys()
        if len(filtersList) > 0:
            self.currentFilterName = filtersList[0]
        else:
            self.currentFilterName = None
        self.fill = True

        self.observers = [
            ('fontChanged', 'fontBecameCurrent'),
            ('fontChanged', 'fontDidOpen'),
            ('fontChanged', 'fontDidClose'),
        ]

        self.displaySettingsRecord = {
            1: ('✓ Fill', True),
            2: ('Stroke', False),
            3: ('Inverse', False),
        }

        self.w = Window((100, 100, 800, 500),
                        'PenBall Wizard v{0}'.format(__version__),
                        minSize=(500, 400))
        self.w.filtersPanel = Group((0, 0, 300, -0))
        self.w.filtersPanel.filtersList = List(
            (0, 0, -0, -80),
            filtersList,
            selectionCallback=self.filterSelectionChanged,
            doubleClickCallback=self.filterEdit,
            allowsMultipleSelection=False,
            allowsEmptySelection=False,
            rowHeight=22)
        self.w.filtersPanel.controls = Group((0, -80, -0, 0))
        self.w.filtersPanel.addFilter = SquareButton((0, -80, 100, 40),
                                                     'Add filter',
                                                     sizeStyle='small',
                                                     callback=self.addFilter)
        self.w.filtersPanel.addFilterChain = SquareButton(
            (100, -80, 100, 40),
            'Add operations',
            sizeStyle='small',
            callback=self.addFilterChain)
        self.w.filtersPanel.removeFilter = SquareButton(
            (-100, -80, 100, 40),
            'Remove filter',
            sizeStyle='small',
            callback=self.removeFilter)
        self.w.textInput = EditText((300, 0, -75, 22),
                                    '',
                                    callback=self.stringInput)
        self.w.generate = SquareButton((0, -40, 300, -0),
                                       'Generate',
                                       callback=self.buildGenerationSheet,
                                       sizeStyle='small')
        self.w.displaySettings = PopUpButton(
            (-70, 3, -10, 15),
            self.makeDisplaySettingsMenuItems(),
            sizeStyle='mini',
            callback=self.changeDisplaySettings)
        self.w.displaySettings.getNSPopUpButton().setPullsDown_(True)
        self.w.displaySettings.getNSPopUpButton().setBordered_(False)
        self.w.preview = MultiLineView((300, 22, -0, -0))
        self.updatePreview()
        displayStates = self.w.preview.getDisplayStates()
        for key in [
                'Show Metrics', 'Upside Down', 'Stroke', 'Beam', 'Inverse',
                'Water Fall', 'Multi Line'
        ]:
            displayStates[key] = False
        for key in ['Fill', 'Single Line']:
            displayStates[key] = True
        self.w.preview.setDisplayStates(displayStates)

        for callback, event in self.observers:
            addObserver(self, callback, event)

        self.updateControls()

        self.w.bind('close', self.end)
        self.launchWindow()
        self.w.open()
Example #14
0
    def __init__(self):
        super(MultiFontMetricsWindow, self).__init__()

        # ui vars
        originLeft = 0
        originRight = 0
        width = 956
        height = 640

        netWidth = width - MARGIN_LFT - MARGIN_RGT
        jumpingY = MARGIN_TOP

        # let's see if there are opened fonts (fontDB, ctrlFontsList, fontsOrder)
        self.loadFontsOrder()
        self.updateUnicodeMinimum()

        # defining plugin windows
        self.w = Window((originLeft, originRight, width, height),
                        "Multi Font Metrics Window",
                        minSize=(800, 400))
        self.w.bind('resize', self.mainWindowResize)

        switchButtonWdt = 140
        self.w.switchButton = PopUpButton(
            (MARGIN_LFT, jumpingY, switchButtonWdt,
             vanillaControlsSize['PopUpButtonRegularHeight']),
            self.textModeOptions,
            sizeStyle='regular',
            callback=self.switchButtonCallback)

        # free text
        textCtrlX = MARGIN_LFT + MARGIN_COL + switchButtonWdt
        self.w.typewriterCtrl = Typewriter(
            (textCtrlX, jumpingY, -(RIGHT_COLUMN + MARGIN_COL + MARGIN_RGT),
             vanillaControlsSize['EditTextRegularHeight']),
            self.unicodeMinimum,
            callback=self.typewriterCtrlCallback)
        self.w.typewriterCtrl.show(False)

        # strings ctrls
        self.w.textStringsControls = TextStringsControls(
            (textCtrlX, jumpingY, -(RIGHT_COLUMN + MARGIN_COL + MARGIN_RGT),
             vanillaControlsSize['PopUpButtonRegularHeight'] + 1),
            self.unicodeMinimum,
            callback=self.textStringsControlsCallback)
        self.stringDisplayMode, self.glyphNamesToDisplay = self.w.textStringsControls.get(
        )

        # multi line
        jumpingY += vanillaControlsSize['ButtonRegularHeight'] + MARGIN_ROW

        self.calcSpacingMatrixHeight()
        self.multiLineOptions = {
            'Show Kerning': self.applyKerning,
            'Center': False,
            'Show Space Matrix': False,
            'Single Line': False,
            'displayMode': u'Multi Line',
            'Stroke': False,
            'xHeight Cut': False,
            'Upside Down': False,
            'Beam': False,
            'Water Fall': False,
            'Inverse': False,
            'Show Template Glyphs': True,
            'Multi Line': True,
            'Right to Left': False,
            'Show Metrics': self.showMetrics,
            'Show Control glyphs': True,
            'Fill': True,
            'Left to Right': self.leftToRight
        }
        self.w.lineView = MultiLineView(
            (MARGIN_LFT, jumpingY, -(RIGHT_COLUMN + MARGIN_COL + MARGIN_RGT),
             -MARGIN_BTM - MARGIN_HALFROW - self.spacingMatrixHeight),
            pointSize=self.bodySize,
            lineHeight=self.lineHeight,
            doubleClickCallback=self.lineViewDoubleClickCallback,
            selectionCallback=self.lineViewSelectionCallback,
            bordered=True,
            applyKerning=self.applyKerning,
            hasHorizontalScroller=False,
            hasVerticalScroller=True,
            displayOptions=self.multiLineOptions,
            updateUserDefaults=False,
            menuForEventCallback=None)

        # static options
        # body
        self.w.bodyCtrl = ComboBoxWithCaption(
            (-(RIGHT_COLUMN + MARGIN_RGT), jumpingY, RIGHT_COLUMN,
             vanillaControlsSize['ComboBoxSmallHeight'] + 1),
            'Body Size:',
            self.bodySizeOptions,
            '{}'.format(self.bodySize),
            sizeStyle='small',
            callback=self.bodyCtrlCallback)

        # line height
        jumpingY += vanillaControlsSize['ComboBoxSmallHeight'] + int(
            MARGIN_HALFROW)
        self.w.lineHgtCtrl = ComboBoxWithCaption(
            (-(RIGHT_COLUMN + MARGIN_RGT), jumpingY, RIGHT_COLUMN,
             vanillaControlsSize['ComboBoxSmallHeight'] + 1),
            'Line Height:',
            self.lineHeightOptions,
            '{}'.format(self.lineHeight),
            sizeStyle='small',
            callback=self.lineHgtCtrlCallback)

        # show metrics
        jumpingY += vanillaControlsSize['ComboBoxSmallHeight'] + MARGIN_ROW
        self.w.showMetricsCheck = CheckBox(
            (-(RIGHT_COLUMN + MARGIN_RGT), jumpingY, RIGHT_COLUMN,
             vanillaControlsSize['CheckBoxSmallHeight']),
            "Show Metrics",
            value=self.showMetrics,
            sizeStyle='small',
            callback=self.showMetricsCheckCallback)

        # show kerning checkbox
        jumpingY += vanillaControlsSize['CheckBoxSmallHeight'] + MARGIN_ROW * .3
        self.w.applyKerningCheck = CheckBox(
            (-(RIGHT_COLUMN + MARGIN_RGT), jumpingY, RIGHT_COLUMN,
             vanillaControlsSize['CheckBoxSmallHeight']),
            "Show Kerning",
            value=self.applyKerning,
            sizeStyle='small',
            callback=self.applyKerningCheckCallback)

        jumpingY += vanillaControlsSize['CheckBoxSmallHeight'] + MARGIN_ROW * .3
        self.w.leftToRightCheck = CheckBox(
            (-(RIGHT_COLUMN + MARGIN_RGT), jumpingY, RIGHT_COLUMN,
             vanillaControlsSize['CheckBoxSmallHeight']),
            "Left to right",
            value=self.leftToRight,
            sizeStyle='small',
            callback=self.leftToRightCheckCallback)

        # separationLine
        jumpingY += vanillaControlsSize['CheckBoxSmallHeight'] + int(
            MARGIN_HALFROW)
        self.w.separationLineOne = HorizontalLine(
            (-(RIGHT_COLUMN + MARGIN_RGT), jumpingY, RIGHT_COLUMN, 1))

        jumpingY += int(MARGIN_HALFROW)
        fontsOrderControllerHeight = FONT_ROW_HEIGHT * len(self.fontsOrder) + 2
        self.w.fontsOrderController = FontsOrderController(
            (-(RIGHT_COLUMN + MARGIN_RGT), jumpingY, RIGHT_COLUMN,
             fontsOrderControllerHeight),
            self.fontsOrder,
            callback=self.fontsOrderControllerCallback)

        jumpingY += fontsOrderControllerHeight
        self.w.separationLineTwo = HorizontalLine(
            (-(RIGHT_COLUMN + MARGIN_RGT), jumpingY, RIGHT_COLUMN, 1))

        # joystick
        jumpingY += MARGIN_HALFROW
        self.w.joystick = SpacingJoystick(
            (-(RIGHT_COLUMN + MARGIN_RGT), jumpingY, RIGHT_COLUMN, 0),
            verticalMode=self.verticalMode,
            marginCallback=self.joystickMarginCallback,
            verticalCallback=self.joystickVerticalCallback)

        # edit metrics
        self.w.spacingMatrix = SpacingMatrix(
            (MARGIN_LFT, -(MARGIN_BTM + self.spacingMatrixHeight),
             self.w.getPosSize()[2] - MARGIN_LFT - MARGIN_RGT,
             self.spacingMatrixHeight),
            glyphNamesToDisplay=self.glyphNamesToDisplay,
            verticalMode=self.verticalMode,
            fontsOrder=self.fontsOrder,
            callback=self.spacingMatrixCallback)

        # add observer
        addObserver(self, 'newFontOpened', "newFontDidOpen")
        addObserver(self, 'openCloseFontCallback', "fontDidOpen")
        addObserver(self, 'openCloseFontCallback', "fontDidClose")

        # lit up!
        self.updateSubscriptions()
        self.updateLineView()
        self.setUpBaseWindowBehavior()
        self.w.open()