Example #1
0
class JumpToLineWindow(BaseWindowController):

    lineNumber = None

    def __init__(self, callback):
        super(JumpToLineWindow, self).__init__()
        self.callback = callback

        # init the window
        self.w = FloatingWindow((WINDOW_WIDTH, 0), 'Jump to line')

        # edit text caption
        jumpingY = MARGIN_TOP
        self.w.caption = TextBox((MARGIN_LFT, jumpingY + 3, NET_WIDTH * .6,
                                  vanillaControlsSize['TextBoxRegularHeight']),
                                 'Jump to line:')

        self.w.lineEdit = EditText(
            (MARGIN_LFT + NET_WIDTH * .6, jumpingY, -MARGIN_RGT,
             vanillaControlsSize['EditTextRegularHeight']),
            continuous=False)

        jumpingY += vanillaControlsSize['EditTextRegularHeight'] + MARGIN_INT
        self.w.cancelButton = Button(
            (-(BUTTON_WIDTH * 2 + MARGIN_INT + MARGIN_RGT), jumpingY,
             BUTTON_WIDTH, vanillaControlsSize['ButtonRegularHeight']),
            'Cancel',
            callback=self.cancelButtonCallback)

        self.w.okButton = Button(
            (-(BUTTON_WIDTH + MARGIN_RGT), jumpingY, BUTTON_WIDTH,
             vanillaControlsSize['ButtonRegularHeight']),
            'Ok',
            callback=self.okButtonCallback)

        jumpingY += vanillaControlsSize['ButtonRegularHeight'] + MARGIN_BTM
        self.setUpBaseWindowBehavior()
        self.w.resize(WINDOW_WIDTH, jumpingY)

    def get(self):
        try:
            self.lineNumber = int(self.w.lineEdit.get())
        except ValueError:
            self.w.lineEdit.set('')
            self.lineNumber = None
        return self.lineNumber

    def enable(self, value):
        if value is True:
            self.w.center()
            self.w.show()
        else:
            self.w.hide()

    def cancelButtonCallback(self, sender):
        self.w.show(False)

    def okButtonCallback(self, sender):
        self.callback(self)
Example #2
0
class AccentedMaker(BaseWindowController):

    fontOptions = []
    whichFont = None
    actions = ['Place Anchors', 'Build Accents']
    whichAction = actions[0]
    whichGlyphList = None
    markEditedGlyphs = False
    markColor = glyphCollectionColors[glyphCollectionColors.keys()[0]]

    uppercaseAccents = False

    def __init__(self):
        super(AccentedMaker, self).__init__()
        self.initLogger()

        self.fontOptions = ['All Fonts', 'Current Font'] + AllFonts()
        self.whichFont = self.fontOptions[0]
        self.pluginHeight = PLUGIN_HEIGHT

        self.loadAccentedData()
        self.parseGlyphListsFromAccentedData()

        firstKey = self.glyphLists[self.whichAction].keys()[0]
        self.whichGlyphList = self.glyphLists[self.whichAction][firstKey]

        self.w = FloatingWindow((0, 0, PLUGIN_WIDTH, self.pluginHeight),
                                PLUGIN_TITLE)

        self.w.sharedCtrls = SharedCtrls(
            (MARGIN_HOR, MARGIN_VER, NET_WIDTH, 104),
            fontOptions=self.fontOptions,
            whichFont=self.whichFont,
            actions=self.actions,
            whichAction=self.whichAction,
            glyphLists=self.glyphLists,
            whichGlyphList=self.whichGlyphList,
            markColor=self.markColor,
            markEditedGlyphs=self.markEditedGlyphs,
            callback=self.sharedCtrlsCallback)
        self.w.separationLine = HorizontalLine(
            (MARGIN_HOR, self.w.sharedCtrls.getPosSize()[3] + MARGIN_ROW,
             NET_WIDTH, vanillaControlsSize['HorizontalLineThickness']))

        dependantCtrlsHgt = MARGIN_VER + self.w.sharedCtrls.getPosSize(
        )[3] + MARGIN_ROW
        self.w.anchorsCtrls = AnchorsCtrls(
            (MARGIN_HOR, dependantCtrlsHgt, NET_WIDTH, 76),
            callbackAttrs=self.anchorsVarsCallback,
            placeCallback=self.anchorsPlaceCallback,
            deleteCallback=self.anchorsDeleteCallback)

        self.w.buildingCtrls = BuildingCtrls(
            (MARGIN_HOR, dependantCtrlsHgt, NET_WIDTH, 50),
            self.uppercaseAccents,
            callbackAttrs=self.buildingVarsCallback,
            callbackCheck=self.checkAccentedCallback,
            callbackBuild=self.buildAccentedCallback)
        self.w.buildingCtrls.show(False)

        addObserver(self, 'updateFontOptions', "newFontDidOpen")
        addObserver(self, 'updateFontOptions', "fontDidOpen")
        addObserver(self, 'updateFontOptions', "fontWillClose")
        self.w.bind("close", self.windowCloseCallback)
        self.setUpBaseWindowBehavior()
        self.adjustPluginHeight()
        self.w.open()

    def initLogger(self):
        # create a logger
        self.accentedLogger = logging.getLogger('accentedLogger')
        # create file handler which logs info messages
        fileBasedHandler = logging.FileHandler('accentedLettersMaker.log')
        fileBasedHandler.setLevel(logging.INFO)
        # create console handler with a higher log level, only errors
        consoleHandler = logging.StreamHandler()
        consoleHandler.setLevel(logging.ERROR)
        # create formatter and add it to the handlers
        formatter = logging.Formatter(
            u'%(asctime)s | %(levelname)s | line: %(lineno)d | %(funcName)s | %(message)s'
        )
        fileBasedHandler.setFormatter(formatter)
        consoleHandler.setFormatter(formatter)
        # add the handlers to the logger
        self.accentedLogger.addHandler(fileBasedHandler)
        self.accentedLogger.addHandler(consoleHandler)

    # deal with font data
    def prepareFontsToAction(self):
        if self.whichFont == 'All Fonts':
            fontsToProcess = AllFonts()
        elif self.whichFont == 'Current Font':
            fontsToProcess = [CurrentFont()]
        else:
            fontsToProcess = [self.whichFont]
        return fontsToProcess

    def deleteAnchors(self):
        self.accentedLogger.info(
            START_FUNC.format(funcName=self.deleteAnchors.__name__))
        fontsToProcess = self.prepareFontsToAction()
        for eachFont in fontsToProcess:
            self.accentedLogger.info(
                START_FONT.format(familyName=eachFont.info.familyName,
                                  styleName=eachFont.info.styleName))
            for eachGlyphName in self.whichGlyphList:
                eachGlyph = eachFont[eachGlyphName]
                if self.markEditedGlyphs is True:
                    if version[0] == '2':
                        eachGlyph.markColor = self.markColor
                    else:
                        eachGlyph.mark = self.markColor

                for eachAnchor in eachGlyph.anchors:
                    eachGlyph.removeAnchor(eachAnchor)
                    self.accentedLogger.info(
                        REMOVE_ANCHOR.format(anchorName=self.anchorName,
                                             glyphName=eachGlyphName))
        self.accentedLogger.info(
            END_FUNC.format(funcName=self.deleteAnchors.__name__))

    def placeAnchors(self):
        assert self.anchorName is not None, '[WARNING] no anchor name provided'
        assert self.anchorHeight is not None, '[WARNING] no anchor height provided'
        self.accentedLogger.info(
            START_FUNC.format(funcName=self.placeAnchors.__name__))

        fontsToProcess = self.prepareFontsToAction()
        for eachFont in fontsToProcess:
            self.accentedLogger.info(
                START_FONT.format(familyName=eachFont.info.familyName,
                                  styleName=eachFont.info.styleName))
            for eachGlyphName in self.whichGlyphList:
                if eachGlyphName in eachFont:
                    eachGlyph = eachFont[eachGlyphName]
                    if self.markEditedGlyphs is True:
                        if version[0] == '2':
                            eachGlyph.markColor = self.markColor
                        else:
                            eachGlyph.mark = self.markColor

                    if selectAnchorByName(eachGlyph, self.anchorName):
                        anchorToDel = selectAnchorByName(
                            eachGlyph, self.anchorName)
                        eachGlyph.removeAnchor(anchorToDel)

                    if version[0] == '2':
                        xMin, yMin, xMax, yMax = eachGlyph.bounds
                    else:
                        xMin, yMin, xMax, yMax = eachGlyph.box

                    if eachFont.info.italicAngle:
                        anchorAngle = radians(-eachFont.info.italicAngle)
                    else:
                        anchorAngle = radians(0)

                    tangentOffset = tan(anchorAngle) * self.anchorHeight
                    anchorX = (
                        eachGlyph.width - eachGlyph.angledLeftMargin -
                        eachGlyph.angledRightMargin
                    ) / 2 + eachGlyph.angledLeftMargin + tangentOffset
                    eachGlyph.appendAnchor(self.anchorName,
                                           (anchorX, self.anchorHeight))
                    self.accentedLogger.info(
                        APPEND_ANCHOR.format(anchorName=self.anchorName,
                                             anchorX=anchorX,
                                             anchorHeight=self.anchorHeight,
                                             glyphName=eachGlyphName))
                else:
                    self.accentedLogger.error(
                        GLYPH_NOT_IN_FONT.format(
                            glyphName=eachGlyphName,
                            familyName=eachFont.info.familyName,
                            styleName=eachFont.info.styleName))
        self.accentedLogger.info(
            END_FUNC.format(funcName=self.placeAnchors.__name__))

    def checkAccented(self, isPrinting=True):
        report = []
        notReady = OrderedDict()

        fontsToProcess = self.prepareFontsToAction()
        for eachFont in fontsToProcess:
            toSkip = []
            report.append('Checking {} {}'.format(eachFont.info.familyName,
                                                  eachFont.info.styleName))
            for eachAccentedName, eachBaseName, eachAccentName, eachAnchorName in self.whichGlyphList:

                # base glyph
                if eachFont.has_key(eachBaseName) is False:
                    report.append(
                        BUILD_MISSING_GLYPH.format(
                            glyphName=eachBaseName,
                            accentedName=eachAccentedName))
                    if eachAccentedName not in toSkip:
                        toSkip.append(eachAccentedName)
                else:
                    eachBaseGlyph = eachFont[eachBaseName]
                    if not eachBaseGlyph.anchors:
                        report.append(
                            NO_ANCHORS.format(glyphName=eachBaseName))
                        if eachAccentedName not in toSkip:
                            toSkip.append(eachAccentedName)
                        if version[0] == '2':
                            eachBaseGlyph.markColor = ERROR_MARK_COLOR
                        else:
                            eachBaseGlyph.mark = ERROR_MARK_COLOR
                    else:
                        for eachAnchor in eachBaseGlyph.anchors:
                            if eachAnchor.name == eachAnchorName:
                                break
                        else:
                            report.append(
                                BUILD_MISSING_ANCHOR.format(
                                    anchorName=eachAnchorName,
                                    glyphName=eachBaseName,
                                    accentedName=eachAccentedName))
                            if eachAccentedName not in toSkip:
                                toSkip.append(eachAccentedName)
                            if version[0] == '2':
                                eachBaseGlyph.markColor = ERROR_MARK_COLOR
                            else:
                                eachBaseGlyph.mark = ERROR_MARK_COLOR

                # accent
                if eachFont.has_key(eachAccentName) is False:
                    report.append(
                        BUILD_MISSING_GLYPH.format(
                            glyphName=eachAccentName,
                            accentedName=eachAccentedName))
                    if eachAccentedName not in toSkip:
                        toSkip.append(eachAccentedName)
                else:
                    eachAccentGlyph = eachFont[eachAccentName]
                    if not eachAccentGlyph.anchors:
                        report.append(
                            NO_ANCHORS.format(glyphName=eachAccentName))
                        if eachAccentedName not in toSkip:
                            toSkip.append(eachAccentedName)
                        if version[0] == '2':
                            eachAccentGlyph.markColor = ERROR_MARK_COLOR
                        else:
                            eachAccentGlyph.mark = ERROR_MARK_COLOR
                    else:
                        for eachAnchor in eachAccentGlyph.anchors:
                            if eachAnchor.name == '_{}'.format(eachAnchorName):
                                break
                        else:
                            report.append(
                                BUILD_MISSING_ANCHOR.format(
                                    anchorName=eachAnchorName,
                                    glyphName=eachAccentName,
                                    accentedName=eachAccentedName))
                            if eachAccentedName not in toSkip:
                                toSkip.append(eachAccentedName)
                            if version[0] == '2':
                                eachAccentGlyph.markColor = ERROR_MARK_COLOR
                            else:
                                eachAccentGlyph.mark = ERROR_MARK_COLOR

            notReady['{} {}'.format(eachFont.info.familyName,
                                    eachFont.info.styleName)] = toSkip
            report.append('End checking {} {}'.format(eachFont.info.familyName,
                                                      eachFont.info.styleName))
            report.append('\n\n')

        if isPrinting is True:
            self.accentedLogger.error('\n'.join(report))

        return notReady

    def buildAccented(self):
        notReady = self.checkAccented(isPrinting=False)
        self.accentedLogger.info(
            START_FUNC.format(funcName=self.buildAccented.__name__))

        fontsToProcess = self.prepareFontsToAction()
        for eachFont in fontsToProcess:
            self.accentedLogger.info(
                START_FONT.format(familyName=eachFont.info.familyName,
                                  styleName=eachFont.info.styleName))
            for eachAccentedName, eachBaseName, eachAccentName, eachAnchorName in self.whichGlyphList:
                if eachAccentedName in notReady['{} {}'.format(
                        eachFont.info.familyName, eachFont.info.styleName)]:
                    self.accentedLogger.error(
                        NOT_READY.format(fontName='{} {}'.format(
                            eachFont.info.familyName, eachFont.info.styleName),
                                         accentedName=eachAccentedName))
                    continue

                eachBaseGlyph = eachFont[eachBaseName]
                eachBaseAnchor = selectAnchorByName(eachBaseGlyph,
                                                    eachAnchorName)

                eachAccentGlyph = eachFont[eachAccentName]
                eachAccentAnchor = selectAnchorByName(
                    eachAccentGlyph, '_{}'.format(eachAnchorName))

                if eachFont.has_key(eachAccentedName) is False:
                    eachAccentedGlyph = eachFont.newGlyph(eachAccentedName)
                else:
                    eachAccentedGlyph = eachFont[eachAccentedName]
                    eachAccentedGlyph.clear()

                eachAccentedGlyph.width = eachBaseGlyph.width
                eachAccentedGlyph.appendComponent(eachBaseName, (0, 0), (1, 1))

                accentOffsetX, accentOffsetY = eachBaseAnchor.x - eachAccentAnchor.x, eachBaseAnchor.y - eachAccentAnchor.y
                eachAccentedGlyph.appendComponent(
                    eachAccentName, (accentOffsetX, accentOffsetY), (1, 1))

                self.accentedLogger.info(
                    BUILT_GLYPH.format(accentedName=eachAccentedName,
                                       baseName=eachBaseName,
                                       accentName=eachAccentName,
                                       anchorName=eachAnchorName))

                if self.markEditedGlyphs is True:
                    if version[0] == '2':
                        eachAccentedGlyph.markColor = self.markColor
                    else:
                        eachAccentedGlyph.mark = self.markColor

        self.accentedLogger.info(
            END_FUNC.format(funcName=self.buildAccented.__name__))

    # deal with table data
    def loadAccentedData(self):
        self.accentedData = [[cell.strip() for cell in row.split('\t')]
                             for row in open(TABLE_PATH, 'r').readlines()]

    def parseGlyphListsFromAccentedData(self):
        assert self.accentedData is not None
        self.glyphLists = OrderedDict()

        # anchors
        self.glyphLists['Place Anchors'] = OrderedDict()
        accentsTop = []
        _ = [
            accentsTop.append(row[2]) for row in self.accentedData
            if row[3] == 'top' and row[2] not in accentsTop
        ]
        self.glyphLists['Place Anchors']['ACC TOP'] = accentsTop

        accentsBtm = []
        _ = [
            accentsBtm.append(row[2]) for row in self.accentedData
            if row[3] == 'bottom' and row[2] not in accentsBtm
        ]
        self.glyphLists['Place Anchors']['ACC BTM'] = accentsBtm

        accentsCaseTop = ['{}.case'.format(name) for name in accentsTop]
        self.glyphLists['Place Anchors']['ACC CASE TOP'] = accentsCaseTop

        accentsCaseBtm = ['{}.case'.format(name) for name in accentsBtm]
        self.glyphLists['Place Anchors']['ACC CASE BTM'] = accentsCaseBtm

        ucBaseTop = []
        _ = [
            ucBaseTop.append(row[1]) for row in self.accentedData if
            row[1][0].isupper() and row[3] == 'top' and row[1] not in ucBaseTop
        ]
        self.glyphLists['Place Anchors']['UC TOP'] = ucBaseTop

        ucBaseBtm = []
        _ = [
            ucBaseBtm.append(row[1]) for row in self.accentedData
            if row[1][0].isupper() and row[3] == 'bottom'
            and row[1] not in ucBaseBtm
        ]
        self.glyphLists['Place Anchors']['UC BTM'] = ucBaseBtm

        lcBaseTop = []
        _ = [
            lcBaseTop.append(row[1]) for row in self.accentedData if
            row[1][0].islower() and row[3] == 'top' and row[1] not in lcBaseTop
        ]
        self.glyphLists['Place Anchors']['LC TOP'] = lcBaseTop

        lcBaseBtm = []
        _ = [
            lcBaseBtm.append(row[1]) for row in self.accentedData
            if row[1][0].islower() and row[3] == 'bottom'
            and row[1] not in lcBaseBtm
        ]
        self.glyphLists['Place Anchors']['LC BTM'] = lcBaseBtm

        # build
        self.glyphLists['Build Accents'] = OrderedDict()
        self.glyphLists['Build Accents']['ALL'] = self.accentedData
        buildUC = [
            row for row in self.accentedData if row[1][0].isupper() is True
        ]
        self.glyphLists['Build Accents']['UC'] = buildUC
        buildLC = [
            row for row in self.accentedData if row[1][0].islower() is True
        ]
        self.glyphLists['Build Accents']['LC'] = buildLC

    # ui
    def adjustPluginHeight(self):
        if self.whichAction == 'Place Anchors':
            self.pluginHeight = MARGIN_VER + self.w.sharedCtrls.getPosSize(
            )[3] + MARGIN_ROW + self.w.anchorsCtrls.getPosSize(
            )[3] + MARGIN_VER
        else:
            self.pluginHeight = MARGIN_VER + self.w.sharedCtrls.getPosSize(
            )[3] + MARGIN_ROW + self.w.buildingCtrls.getPosSize(
            )[3] + MARGIN_VER
        lft, top, wdt, hgt = self.w.getPosSize()
        self.w.resize(wdt, self.pluginHeight)

    def switchDependantCtrl(self):
        if self.whichAction == 'Place Anchors':
            self.w.anchorsCtrls.show(True)
            self.w.buildingCtrls.show(False)
        else:
            self.w.anchorsCtrls.show(False)
            self.w.buildingCtrls.show(True)

    # observers
    def updateFontOptions(self, sender):
        self.fontOptions = ['All Fonts', 'Current Font'] + AllFonts()
        self.w.sharedCtrls.setFontOptions(self.fontOptions)

    # callbacks
    def sharedCtrlsCallback(self, sender):
        self.whichFont = sender.getWhichFont()
        self.whichAction = sender.getWhichAction()
        self.switchDependantCtrl()
        self.adjustPluginHeight()

        self.whichGlyphList = sender.getWhichGlyphList()
        self.markEditedGlyphs, self.markColor = sender.getMarkEditedGlyphs()

    def anchorsVarsCallback(self, sender):
        self.anchorHeight = sender.getHeight()
        self.anchorName = sender.getName()

    def anchorsPlaceCallback(self, sender):
        self.placeAnchors()

    def anchorsDeleteCallback(self, sender):
        self.deleteAnchors()

    def buildingVarsCallback(self, sender):
        self.uppercaseAccents = sender.getUppercaseAccents()

    def checkAccentedCallback(self, sender):
        self.checkAccented()

    def buildAccentedCallback(self, sender):
        self.buildAccented()

    def windowCloseCallback(self, sender):
        removeObserver(self, "newFontDidOpen")
        removeObserver(self, "fontDidOpen")
        removeObserver(self, "fontWillClose")
        super(AccentedMaker, self).windowCloseCallback(sender)
Example #3
0
class SpeedPunkPrefWindow(object):

	def __init__(self, parent):
		self.parent = parent
		self.w = FloatingWindow((150, 130), "Speed Punk %s" % VERSION,
								closable = False,
								autosaveName = 'de_yanone_speedPunk_%s.prefWindow' % (environment),
								)
		self.w.illustrationPositionRadioGroup = RadioGroup((10, 10, -10, 40),
								["Outside of glyph", "Outer side of curve"],
								callback=self.radioGroupCallback,
								sizeStyle = "small")

		self.w.curveGainTextBox = TextBox((10, 60, -10, 17), "Gain",
							sizeStyle = "mini")

		self.w.curveGainSlider = Slider((10, 70, -10, 25),
							tickMarkCount=5,
							callback=self.curveGainSliderCallback,
							sizeStyle = "small",
							minValue = curveGain[0],
							maxValue = curveGain[1],
							value = self.parent.getPreference('curveGain'))
		
		self.w.illustrationPositionRadioGroup.set(self.parent.getPreference('illustrationPositionIndex'))

		self.w.faderCheckBox = CheckBox((10, 100, -10, 17), "Fader",
							sizeStyle = "small",
							callback = self.faderCheckBoxCallback)

		self.w.faderSlider = Slider((10, 125, -10, 25),
							sizeStyle = "small",
							minValue = 0,
							maxValue = 1.0,
							value = 1.0,
							callback = self.faderSliderCallback)

		self.w.gradientImage = ImageView((10, 150, -10, 15))
		self.w.histogramImage = ImageView((10, 150, -10, 15))

	def radioGroupCallback(self, sender):
		self.parent.setPreference('illustrationPositionIndex', sender.get())
		self.parent.RefreshView()

	def curveGainSliderCallback(self, sender):
		self.parent.setPreference('curveGain', sender.get())
		self.parent.RefreshView()

	def faderSliderCallback(self, sender):
		self.parent.setPreference('fader', sender.get())
		self.parent.RefreshView()

	def faderCheckBoxCallback(self, sender):
		self.parent.setPreference('useFader', sender.get())
		self.parent.RefreshView()
		if sender.get():
			self.w.faderCheckBox.setPosSize(((10, 105, -10, 17)))
			self.w.resize(150, 175, animate=True)
		else:
			self.w.faderCheckBox.setPosSize(((10, 100, -10, 17)))
			self.w.resize(150, 130, animate=True)
Example #4
0
class SpeedPunkPrefWindow(object):

	def __init__(self, parent):
		self.parent = parent
		self.w = FloatingWindow((150, 130), "Speed Punk %s" % VERSION,
								closable = False,
								autosaveName = 'de_yanone_speedPunk_%s.prefWindow' % (environment),
								)
		self.w.illustrationPositionRadioGroup = RadioGroup((10, 10, -10, 40),
								(
									Glyphs.localize({
										'en': 'Outside of glyph',
										'de': 'Außen an Form',
										'fr': 'Éxterieur de la forme',
										'es': 'Exterior del glifo',
										'pt': 'Fora do glifo',
									}),
									Glyphs.localize({
										'en': 'Outer side of curve',
										'de': 'Außen am Pfad',
										'fr': 'Éxterieur de la courbe',
										'es': 'Exterior del trazo',
										'pt': 'Fora da curva',
									}),
								),
								callback=self.radioGroupCallback,
								sizeStyle = "small")

		self.w.curveGainTextBox = TextBox((10, 60, -10, 17),
							Glyphs.localize({
								'en': 'Gain',
								'de': 'Stärke',
								'fr': 'Volume',
								'es': 'Volumen',
								'pt': 'Volume',
							}),
							sizeStyle = "mini")

		self.w.curveGainSlider = Slider((10, 70, -10, 25),
							tickMarkCount=5,
							callback=self.curveGainSliderCallback,
							sizeStyle = "small",
							minValue = curveGain[0],
							maxValue = curveGain[1],
							value = self.parent.getPreference('curveGain'))
		
		self.w.illustrationPositionRadioGroup.set(self.parent.getPreference('illustrationPositionIndex'))

		self.w.faderCheckBox = CheckBox((10, 100, -10, 17),
							Glyphs.localize({
								'en': 'Fade',
								'de': 'Ausblenden',
								'fr': 'Opacité',
								'es': 'Opacidad',
								'pt': 'Opacidade',
							}),
							sizeStyle = "small",
							callback = self.faderCheckBoxCallback)

		self.w.faderSlider = Slider((10, 125, -10, 25),
							sizeStyle = "small",
							minValue = 0,
							maxValue = 1.0,
							value = 1.0,
							callback = self.faderSliderCallback)

		self.w.gradientImage = ImageView((10, 150, -10, 15))
		self.w.histogramImage = ImageView((10, 150, -10, 15))

	def radioGroupCallback(self, sender):
		self.parent.setPreference('illustrationPositionIndex', sender.get())
		self.parent.RefreshView()

	def curveGainSliderCallback(self, sender):
		self.parent.setPreference('curveGain', sender.get())
		self.parent.RefreshView()

	def faderSliderCallback(self, sender):
		self.parent.setPreference('fader', sender.get())
		self.parent.RefreshView()

	def faderCheckBoxCallback(self, sender):
		self.parent.setPreference('useFader', sender.get())
		self.parent.RefreshView()
		if sender.get():
			self.w.faderCheckBox.setPosSize(((10, 105, -10, 17)))
			self.w.resize(150, 175, animate=True)
		else:
			self.w.faderCheckBox.setPosSize(((10, 100, -10, 17)))
			self.w.resize(150, 130, animate=True)
class Adhesiontext(BaseWindowController):

	def __init__(self):
		flushAlign = 76
		firstRowY = 12
		rowOffsetY = 30
		firstCheckY = 135
		checkOffsetY = 27
		rightMarginX = -12
		self.windowWidth = 410
		self.windowHeightWithoutOptions = 45
		self.windowHeightWithOptions = 280
		self.scriptIsRTL = False

		windowPos = getExtensionDefault("%s.%s" % (extensionKey, "windowPos"))
		if not windowPos:
			windowPos = (100, 100)

		self.optionsVisible = getExtensionDefault("%s.%s" % (extensionKey, "optionsVisible"))
		if self.optionsVisible:
			optionsButtonSign = '-'
			windowHeight = self.windowHeightWithOptions
		else:
			self.optionsVisible = False # needs to be set because the first time the extension runs self.optionsVisible will be None
			optionsButtonSign = '+'
			windowHeight = self.windowHeightWithoutOptions

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

		self.sliderValue = getExtensionDefault("%s.%s" % (extensionKey, "sliderValue"))
		if not self.sliderValue:
			self.sliderValue = 25

		self.scriptsIndex = getExtensionDefault("%s.%s" % (extensionKey, "scriptsIndex"))
		if not self.scriptsIndex:
			self.scriptsIndex = 0

		self.langsIndex = getExtensionDefault("%s.%s" % (extensionKey, "langsIndex"))
		if not self.langsIndex:
			self.langsIndex = 0


		self.w = FloatingWindow((windowPos[0], windowPos[1], self.windowWidth, windowHeight), "adhesiontext")

		# 1st row
		self.w.labelChars = TextBox((10, firstRowY, flushAlign, 20), "Characters:", alignment="right")
		self.w.chars = EditText((flushAlign +15, firstRowY -1, 199, 22), self.chars, callback=self.charsCallback)
		self.w.button = Button((300, firstRowY, 68, 20), "Get text", callback=self.buttonCallback)
		self.w.spinner = FixedSpinner((325, firstRowY, 20, 20), displayWhenStopped=False)
		self.w.optionsButton = SquareButton((378, firstRowY +1, 18, 18), optionsButtonSign, sizeStyle="small", callback=self.optionsCallback)
		# set the initial state of the button according to the content of the chars EditText
		if len(self.w.chars.get()): self.w.button.enable(True)
		else: self.w.button.enable(False)
		# keep track of the content of chars EditText
		self.previousChars = self.w.chars.get()

		# 2nd row
		self.w.labelWords = TextBox((10, firstRowY + rowOffsetY, flushAlign, 20), "Words:", alignment="right")
		self.w.wordCount = TextBox((flushAlign +12, firstRowY + rowOffsetY, 40, 20), alignment="left")
		self.w.slider = Slider((flushAlign +47, firstRowY + rowOffsetY +1, 165, 20), value=self.sliderValue, minValue=5, maxValue=200, callback=self.sliderCallback)
		# set the initial wordCount value according to the position of the slider
		self.w.wordCount.set(int(self.w.slider.get()))

		# 3rd row
		self.w.labelScripts = TextBox((10, firstRowY + rowOffsetY *2, flushAlign, 20), "Script:", alignment="right")
		self.w.scriptsPopup = PopUpButton((flushAlign +15, firstRowY + rowOffsetY *2, 150, 20), scriptsNameList, callback=self.scriptsCallback)
		self.w.scriptsPopup.set(self.scriptsIndex)

		# 4th row
		self.w.labelLangs = TextBox((10, firstRowY + rowOffsetY *3, flushAlign, 20), "Language:", alignment="right")
		self.w.langsPopup = PopUpButton((flushAlign +15, firstRowY + rowOffsetY *3, 150, 20), [])
		# set the initial list of languages according to the script value
		self.w.langsPopup.setItems(langsNameDict[scriptsNameList[self.w.scriptsPopup.get()]])
		self.w.langsPopup.set(self.langsIndex)

		self.punctCheck = getExtensionDefault("%s.%s" % (extensionKey, "punctCheck"))
		if not self.punctCheck:
			self.punctCheck = 0

		self.figsCheck = getExtensionDefault("%s.%s" % (extensionKey, "figsCheck"))
		if not self.figsCheck:
			self.figsCheck = 0

		self.figsPopup = getExtensionDefault("%s.%s" % (extensionKey, "figsPopup"))
		if not self.figsPopup:
			self.figsPopup = 0

		self.trimCheck = getExtensionDefault("%s.%s" % (extensionKey, "trimCheck"))
		if not self.trimCheck:
			self.trimCheck = 0

		self.caseCheck = getExtensionDefault("%s.%s" % (extensionKey, "caseCheck"))
		if not self.caseCheck:
			self.caseCheck = 0

		self.casingCheck = getExtensionDefault("%s.%s" % (extensionKey, "casingCheck"))
		if not self.casingCheck:
			self.casingCheck = 0

		self.casingPopup = getExtensionDefault("%s.%s" % (extensionKey, "casingPopup"))
		if not self.casingPopup:
			self.casingPopup = 0

		# 1st checkbox
		self.w.punctCheck = CheckBox((flushAlign +15, firstCheckY, 130, 20), "Add punctuation")
		self.w.punctCheck.set(self.punctCheck)

		# 2nd checkbox
		self.w.figsCheck = CheckBox((flushAlign +15, firstCheckY + checkOffsetY, 120, 20), "Insert numbers", callback=self.figsCallback)
		self.w.figsCheck.set(self.figsCheck)
		self.w.figsPopup = PopUpButton((210, firstCheckY + checkOffsetY, 90, 20), figOptionsList)
		self.w.figsPopup.set(self.figsPopup)
		# enable or disable the figure options PopUp depending on the figures CheckBox
		if scriptsNameList[self.w.scriptsPopup.get()] in enableFigOptionList:
			self.w.figsPopup.show(True)
			if self.w.figsCheck.get():
				self.w.figsPopup.enable(True)
			else:
				self.w.figsPopup.enable(False)
		else:
			self.w.figsPopup.show(False)

		# 3rd checkbox
		self.w.trimCheck = CheckBoxPlus((flushAlign +15, firstCheckY + checkOffsetY *2, 120, 20), "Trim accents")
		self.w.trimCheck.set(self.trimCheck)
		if scriptsNameList[self.w.scriptsPopup.get()] in enableTrimCheckList:
			self.w.trimCheck.enable(True)
		else:
			self.w.trimCheck.enable(False)

		# 4th checkbox
		self.w.caseCheck = CheckBoxPlus((flushAlign +15, firstCheckY + checkOffsetY *3, 120, 20), "Ignore casing")
		self.w.caseCheck.set(self.caseCheck)
		if scriptsNameList[self.w.scriptsPopup.get()] in enableCaseCheckList:
			self.w.caseCheck.enable(True)
		else:
			self.w.caseCheck.enable(False)

		# 5th checkbox
		self.w.casingCheck = CheckBoxPlus((flushAlign +15, firstCheckY + checkOffsetY *4, 115, 20), "Change casing", callback=self.casingCallback)
		self.w.casingCheck.set(self.casingCheck)
		if scriptsNameList[self.w.scriptsPopup.get()] in enableCaseCheckList:
			self.w.casingCheck.enable(True)
		else:
			self.w.casingCheck.enable(False)
		self.w.casingPopup = PopUpButton((210, firstCheckY + checkOffsetY *4, 90, 20), casingNameList)
		self.w.casingPopup.set(self.casingPopup)
		# enable or disable the casing PopUp depending on the casing CheckBox
		if self.w.casingCheck.get() and self.w.casingCheck.isEnable():
			self.w.casingPopup.enable(True)
		else:
			self.w.casingPopup.enable(False)

		self.nsTextField = self.w.chars.getNSTextField()
		self.w.setDefaultButton(self.w.button)
		self.w.bind("close", self.windowClose)
		self.w.open()
		self.w.makeKey()

	def windowClose(self, sender):
		self.saveExtensionDefaults()

	def saveExtensionDefaults(self):
		setExtensionDefault("%s.%s" % (extensionKey, "windowPos"), self.w.getPosSize()[0:2])
		setExtensionDefault("%s.%s" % (extensionKey, "optionsVisible"), self.optionsVisible)
		setExtensionDefault("%s.%s" % (extensionKey, "chars"), self.w.chars.get())
		setExtensionDefault("%s.%s" % (extensionKey, "sliderValue"), int(self.w.slider.get()))
		setExtensionDefault("%s.%s" % (extensionKey, "scriptsIndex"), int(self.w.scriptsPopup.get()))
		setExtensionDefault("%s.%s" % (extensionKey, "langsIndex"), int(self.w.langsPopup.get()))
		setExtensionDefault("%s.%s" % (extensionKey, "punctCheck"), self.w.punctCheck.get())
		setExtensionDefault("%s.%s" % (extensionKey, "figsCheck"), self.w.figsCheck.get())
		setExtensionDefault("%s.%s" % (extensionKey, "figsPopup"), self.w.figsPopup.get())
		setExtensionDefault("%s.%s" % (extensionKey, "trimCheck"), self.w.trimCheck.get())
		setExtensionDefault("%s.%s" % (extensionKey, "caseCheck"), self.w.caseCheck.get())
		setExtensionDefault("%s.%s" % (extensionKey, "casingCheck"), self.w.casingCheck.get())
		setExtensionDefault("%s.%s" % (extensionKey, "casingPopup"), self.w.casingPopup.get())

	def buttonCallback(self, sender):
		sender.enable(False)
		self.w.spinner.start()
		self.getText()
		self.w.spinner.stop()
		sender.enable(True)

	def optionsCallback(self, sender):
		sign = sender.getTitle()
		if sign == "+":
			sender.setTitle("-")
			self.w.resize(self.windowWidth, self.windowHeightWithOptions, animate=True)
			self.optionsVisible = True
		else:
			sender.setTitle("+")
			self.w.resize(self.windowWidth, self.windowHeightWithoutOptions, animate=True)
			self.optionsVisible = False

	def charsCallback(self, sender):
		charsContent = sender.get()
		if len(charsContent):
			self.w.button.enable(True)
			nsTextView = self.nsTextField.currentEditor() # NOTE: the field editor is only available when NSTextField is in editing mode.

			# when only one glyph is selected and copied, the contents of the clipboard are the glyph's XML
			# instead of its unicode character or its name; therefore, post-process the pasted content.
			if xmlHeader in charsContent:
				caretIndex = charsContent.index(xmlHeader)
				codepointString = re_glyphUnicode.search(charsContent)
				glyphName = re_glyphName.search(charsContent)

				if codepointString:
					replacement = unichr(eval('0x' + codepointString.group(1)))
				elif glyphName:
					replacement = '/' + glyphName.group(1)
				else:
					replacement = ''

				# replace the glyph's XML by its unicode character or its name
				self.w.chars.set(re_glyph.sub(replacement, charsContent))
				# restore the location of the caret
				location = caretIndex + len(replacement)
				nsTextView.setSelectedRange_((location, 0))
				# update the variable
				charsContent = sender.get()

			caretIndex = nsTextView.selectedRanges()[0].rangeValue().location

			# Limit the number of characters
			numeralWasFound = self.stringHasNumeral(charsContent)
			if len(charsContent) > maxChars or numeralWasFound:
				NSBeep()
				if numeralWasFound:
					self.showMessage("Sorry, numerals are not allowed.", "")
				else:
					self.showMessage("You've reached the maximum \rnumber of characters.", "The limit is %d." % maxChars)
				# restore the content of chars EditText to the previous string
				sender.set(self.previousChars)
				# restore the focus on the chars EditText and restore the location of the caret
				caretIndexAdjust = len(self.previousChars) - len(charsContent)
				self.w.getNSWindow().makeFirstResponder_(self.nsTextField)
				nsTextView.setSelectedRange_((caretIndex + caretIndexAdjust, 0))

			# update the stored string
			self.previousChars = sender.get()

		else:
			self.w.button.enable(False)

	def sliderCallback(self, sender):
		self.w.wordCount.set(int(sender.get()))

	def scriptsCallback(self, sender):
		self.w.langsPopup.setItems(langsNameDict[scriptsNameList[sender.get()]])
		# toggle RTL/LTR
		if scriptsNameList[sender.get()] in rightToLeftList:
			self.scriptIsRTL = True
			self.nsTextField.setBaseWritingDirection_(NSWritingDirectionRightToLeft)
			self.nsTextField.setAlignment_(NSRightTextAlignment)
		else:
			self.scriptIsRTL = False
			self.nsTextField.setBaseWritingDirection_(NSWritingDirectionLeftToRight)
			self.nsTextField.setAlignment_(NSLeftTextAlignment)
		# restore the focus on the chars EditText
		self.w.getNSWindow().makeFirstResponder_(self.nsTextField)
		# toggle figsPopup
		if scriptsNameList[sender.get()] in enableFigOptionList:
			self.w.figsPopup.show(True)
			if self.w.figsCheck.get():
				self.w.figsPopup.enable(True)
			else:
				self.w.figsPopup.enable(False)
		else:
			self.w.figsPopup.show(False)
		# toggle trimCheck
		if scriptsNameList[sender.get()] in enableTrimCheckList:
			self.w.trimCheck.enable(True)
		else:
			self.w.trimCheck.enable(False)
		# toggle caseCheck and casingCheck
		if scriptsNameList[sender.get()] in enableCaseCheckList:
			self.w.caseCheck.enable(True)
			self.w.casingCheck.enable(True)
			if self.w.casingCheck.get():
				self.w.casingPopup.enable(True)
		else:
			self.w.caseCheck.enable(False)
			self.w.casingCheck.enable(False)
			self.w.casingPopup.enable(False)

	def figsCallback(self, sender):
		if sender.get():
			self.w.figsPopup.enable(True)
		else:
			self.w.figsPopup.enable(False)

	def casingCallback(self, sender):
		if sender.get():
			self.w.casingPopup.enable(True)
		else:
			self.w.casingPopup.enable(False)

	def stringHasNumeral(self, string):
		if re_numeral.search(string):
			return True
		return False

	def isConnected(self):
		try:
			urlopen(url, timeout=3)
			return True
		except URLError:
			pass
		return False

	def getText(self):
		if CurrentFont() is None:
			NSBeep()
			self.showMessage("Open a font first.", "")
			return

		if not self.isConnected():
			NSBeep()
			self.showMessage("Required internet connection not found.", "")
			return

		values = {'chars' : self.w.chars.get().encode('utf-8'),
				  'script' : scriptsTagDict[scriptsNameList[self.w.scriptsPopup.get()]],
				  'tb' : langsTagDict[langsNameDict[scriptsNameList[self.w.scriptsPopup.get()]][self.w.langsPopup.get()]] }

		if self.w.punctCheck.get():
			values['punct'] = True
		if self.w.figsCheck.get():
			values['figs'] = True
			if self.w.figsPopup.isVisible():
				figsOptTagsList = ["dflt", "locl"]
				values['figsOpt'] = figsOptTagsList[self.w.figsPopup.get()]
		if self.w.trimCheck.get() and self.w.trimCheck.isEnable():
			values['trim'] = True
		if self.w.caseCheck.get() and self.w.caseCheck.isEnable():
			values['case'] = True
		if self.w.casingCheck.get() and self.w.casingCheck.isEnable():
			values['casing'] = casingNameList[self.w.casingPopup.get()].lower()

		data = urlencode(values)
		data = data.encode('utf-8')
		print(data)
		request = Request(url, data)
		response = urlopen(request)
		text = response.read()
		textU = unicode(text, 'utf-8')

		if (msgStr in textU):
			textU = textU.replace(msgStr, "")
			NSBeep()
			self.showMessage(textU, "")
			return

		elif (wrnStr in textU):
			resultIndex = textU.find(rsltStr)
			secmsgIndex = textU.find(sndStr)
			frstmsgU = textU[:secmsgIndex].replace(wrnStr, "")
			scndmsgU = textU[secmsgIndex:resultIndex].replace(sndStr, "")
			textU = textU[resultIndex:].replace(rsltStr, "")
			NSBeep()
			self.showMessage(frstmsgU, scndmsgU)

		textList = textU.split()
		trimmedText = ' '.join(textList[:int(self.w.slider.get())])

		if CurrentSpaceCenter() is None:
			OpenSpaceCenter(CurrentFont(), newWindow=False)

		sp = CurrentSpaceCenter()
		print(trimmedText)
		sp.setRaw(trimmedText)

		# Toggle RTL-LTR
		try:
			sp.setLeftToRight(not self.scriptIsRTL)
			sp.setInputWritingDirection('Right to Left' if self.scriptIsRTL else 'Left to Right')
		except AttributeError:
			pass

		return
Example #6
0
class VariableController(object):
    def __init__(self, attributes, callback, document=None):
        self._callback = callback
        self._attributes = None
        self.w = FloatingWindow((250, 50))
        self.buildUI(attributes)
        self.w.open()
        if document:
            self.w.assignToDocument(document)
        self.w.setTitle("Variables")

    def buildUI(self, attributes):
        if self._attributes == attributes:
            return
        self._attributes = attributes
        if hasattr(self.w, "ui"):
            del self.w.ui
        self.w.ui = ui = vanilla.Group((0, 0, -0, -0))
        y = 10
        labelSize = 100
        gutter = 5
        for attribute in self._attributes:
            uiElement = attribute["ui"]
            name = attribute["name"]
            args = dict(attribute.get("args", {}))
            height = 19
            # adjust the height if a radioGroup is vertical
            if uiElement == "RadioGroup":
                if args.get("isVertical", True):
                    height = height * len(args.get("titles", [""]))
            # create a label for every ui element except a checkbox
            if uiElement not in ("CheckBox", "Button"):
                # create the label view
                label = vanilla.TextBox((0, y + 2, labelSize - gutter, height),
                                        "%s:" % name,
                                        alignment="right",
                                        sizeStyle="small")
                # set the label view
                setattr(ui, "%sLabel" % name, label)
            else:
                args["title"] = name
            # check the provided args and add required keys
            if uiElement == "ColorWell":
                # a color well needs a color to be set
                # no size style
                if "color" not in args:
                    args["color"] = AppKit.NSColor.blackColor()
            elif uiElement == "TextEditor":
                # different control height
                # no size style
                height = attribute.get("height", 75)
            else:
                # all other get a size style
                args["sizeStyle"] = "small"
            # create the control view
            attr = getattr(vanilla, uiElement)((labelSize, y, -10, height),
                                               callback=self.changed,
                                               **args)
            # set the control view
            setattr(ui, name, attr)
            y += height + 6
        # resize the window according the provided ui elements
        self.w.resize(250, y)

    def changed(self, sender):
        self.documentWindowToFront()
        if self._callback:
            self._callback()

    def get(self):
        data = {}
        for attribute in self._attributes:
            if attribute["ui"] in ("Button", ):
                continue
            name = attribute["name"]
            data[name] = getattr(self.w.ui, name).get()
        return data

    def show(self):
        self.w.show()

    def documentWindowToFront(self, sender=None):
        self.w.makeKey()
Example #7
0
class VFB2UFO(BaseWindowController):

    inputOptions = ['Single File', 'Multiple files from a Folder']
    chosenMode = inputOptions[0]

    conversionOptions = ["From VFB to UFO", "From UFO to VFB"]
    suffix2conversionOption = {
        "From VFB to UFO": '.vfb',
        "From UFO to VFB": '.ufo'
    }
    chosenSuffix = suffix2conversionOption[conversionOptions[0]]

    def __init__(self):
        super(VFB2UFO, self).__init__()
        self.w = FloatingWindow((PLUGIN_WIDTH, 2), PLUGIN_TITLE)
        self.jumpingY = MARGIN_VER

        # options button
        self.w.optionsPopUp = PopUpButton(
            (MARGIN_HOR, self.jumpingY, NET_WIDTH,
             vanillaControlsSize['PopUpButtonRegularHeight']),
            self.inputOptions,
            callback=self.optionsPopUpCallback)
        self.jumpingY += vanillaControlsSize[
            'PopUpButtonRegularHeight'] + MARGIN_HOR

        # suffix option
        self.w.suffixRadio = RadioGroup(
            (MARGIN_HOR, self.jumpingY, NET_WIDTH,
             vanillaControlsSize['ButtonRegularHeight'] * 2),
            ["From VFB to UFO", "From UFO to VFB"],
            callback=self.suffixRadioCallback)
        self.w.suffixRadio.set(0)
        self.w.suffixRadio.enable(False)
        self.jumpingY += vanillaControlsSize[
            'ButtonRegularHeight'] * 2 + MARGIN_HOR

        # convert button
        self.w.convertButton = Button(
            (MARGIN_HOR, self.jumpingY, NET_WIDTH,
             vanillaControlsSize['ButtonRegularHeight']),
            'Choose file and convert',
            callback=self.convertButtonCallback)
        self.jumpingY += vanillaControlsSize['ButtonRegularHeight'] + MARGIN_HOR

        self.w.resize(PLUGIN_WIDTH, self.jumpingY)
        self.setUpBaseWindowBehavior()
        self.w.open()

    def optionsPopUpCallback(self, sender):
        self.chosenMode = self.inputOptions[sender.get()]
        if self.chosenMode == 'Single File':
            self.w.suffixRadio.enable(False)
            self.w.convertButton.setTitle('Choose file and convert')
        else:
            self.w.suffixRadio.enable(True)
            self.w.convertButton.setTitle('Choose folder and convert')

    def suffixRadioCallback(self, sender):
        self.chosenSuffix = self.suffix2conversionOption[
            self.conversionOptions[sender.get()]]

    def convertButtonCallback(self, sender):
        if self.chosenMode == 'Single File':
            inputPath = getFile('Choose the file to convert')[0]
            if inputPath.endswith('.vfb') or inputPath.endswith('.ufo'):
                executeCommand(['vfb2ufo', '-fo', inputPath], shell=True)
            else:
                message('input file path is not correct')
        else:
            inputFolder = getFolder('Choose a folder with files to convert')[0]
            if inputFolder:
                for eachPath in catchFilesAndFolders(inputFolder,
                                                     self.chosenSuffix):
                    executeCommand(['vfb2ufo', '-fo', eachPath], shell=True)
            else:
                message('input folder path is not correct')
Example #8
0
class Labeler(object):

    labelCltrIndex = 0

    def __init__(self):

        # init window
        self.w = FloatingWindow((PLUGIN_WIDTH, 300), 'labeler.py')

        self.jumpingY = MARGIN_VER
        self.w.labelCtrl_0 = LabelCtrl((MARGIN_HOR, self.jumpingY, NET_WIDTH, vanillaControlsSize['EditTextRegularHeight']),
                                       index=self.labelCltrIndex,
                                       callback=self.labelCtrlsCallback)
        self.jumpingY += vanillaControlsSize['EditTextRegularHeight'] + MARGIN_VER

        self.w.separation = HorizontalLine((MARGIN_HOR, self.jumpingY, NET_WIDTH, vanillaControlsSize['HorizontalLineThickness']))
        self.w.clearButton = SquareButton((MARGIN_HOR, self.jumpingY+vanillaControlsSize['HorizontalLineThickness'] + MARGIN_VER, NET_WIDTH, vanillaControlsSize['ButtonRegularHeight']),
                                          'Clear Glyph Labels',
                                          sizeStyle='small',
                                          callback=self.clearButtonCallback)

        # resize window
        self._computeWindowHeight()
        self.w.resize(PLUGIN_WIDTH, self.windowHeight)

        # open window
        self.w.open()

    def _computeWindowHeight(self):
        self.windowHeight = self.jumpingY + vanillaControlsSize['ButtonRegularHeight'] + vanillaControlsSize['HorizontalLineThickness'] + MARGIN_VER*2

    def _updateCtrlsPos(self):
        self.w.separation.setPosSize((MARGIN_HOR, self.jumpingY, NET_WIDTH, vanillaControlsSize['HorizontalLineThickness']))
        self.w.clearButton.setPosSize((MARGIN_HOR, self.jumpingY+vanillaControlsSize['HorizontalLineThickness'] + MARGIN_VER, NET_WIDTH, vanillaControlsSize['ButtonRegularHeight']))

    def labelCtrlsCallback(self, sender):
        lastAction, labelName = sender.get()

        if lastAction == 'attach':
            attachLabelToSelectedPoints(labelName)

        elif lastAction == 'add':
            self.labelCltrIndex += 1
            labelCtrl = LabelCtrl((MARGIN_HOR, self.jumpingY, NET_WIDTH, vanillaControlsSize['EditTextRegularHeight']),
                                  index=self.labelCltrIndex,
                                  callback=self.labelCtrlsCallback)
            setattr(self.w, 'labelCtrl_{:d}'.format(labelCtrl.index), labelCtrl)

            self.jumpingY += vanillaControlsSize['EditTextRegularHeight'] + MARGIN_VER
            self._computeWindowHeight()
            self._updateCtrlsPos()
            self.w.resize(PLUGIN_WIDTH, self.windowHeight)

        elif lastAction == 'subtract':
            delattr(self.w, 'labelCtrl_{:d}'.format(labelCtrl.index))
            self.jumpingY -= vanillaControlsSize['EditTextRegularHeight'] + MARGIN_VER
            self.w.resize(PLUGIN_WIDTH, self.windowHeight)

        # else: # None


    def clearButtonCallback(self, sender):
        myGlyph = CurrentGlyph()
        for eachContour in myGlyph:
            for eachPt in eachContour.points:
                if eachPt.name is not None:
                    eachPt.name = None
        myGlyph.update()
Example #9
0
class SidebearingsLinker(BaseWindowController):

    allFonts = []

    servantSubscriptions = []
    masterSubscriptions = []
    displayedSubscriptions = []

    currentRow = None
    selectedFont = None

    def __init__(self, willOpen=True):
        super(SidebearingsLinker, self).__init__()

        # collecting fonts
        self.allFonts = AllFonts()
        if self.allFonts != []:
            self.selectedFont = self.allFonts[0]

        # interface
        self.w = FloatingWindow((PLUGIN_WIDTH, PLUGIN_HEIGHT), PLUGIN_TITLE)

        jumpingY = MARGIN_VER
        self.w.fontPopUp = PopUpButton(
            (MARGIN_HOR, jumpingY, NET_WIDTH,
             vanillaControlsSize['PopUpButtonRegularHeight']),
            getNamesFrom(self.allFonts),
            callback=self.fontPopUpCallback)

        jumpingY += vanillaControlsSize['PopUpButtonRegularHeight'] + MARGIN_ROW
        self.w.canvas = CanvasGroup(
            (MARGIN_HOR, jumpingY, NET_WIDTH, CANVAS_HEIGHT), delegate=self)

        jumpingY += CANVAS_HEIGHT + MARGIN_ROW
        linksColumnDescriptions = [{
            "title": "left",
            'key': 'lft',
            'width': LIST_WIDE_COL
        }, {
            "title": "active",
            "cell": CheckBoxListCell(),
            'key': 'lftActive',
            'width': LIST_NARROW_COL
        }, {
            "title": "glyph",
            'key': 'servant',
            'width': LIST_WIDE_COL,
            "editable": False
        }, {
            "title": "active",
            "cell": CheckBoxListCell(),
            'key': 'rgtActive',
            'width': LIST_NARROW_COL
        }, {
            "title": "right",
            'key': 'rgt',
            'width': LIST_WIDE_COL
        }]

        if self.selectedFont is not None:
            links = loadLinksFromFont(self.selectedFont)
        else:
            links = []

        self.w.linksList = List(
            (MARGIN_HOR, jumpingY, NET_WIDTH, 200),
            links,
            showColumnTitles=False,
            allowsMultipleSelection=False,
            drawVerticalLines=True,
            columnDescriptions=linksColumnDescriptions,
            selectionCallback=self.selectionLinksListCallback,
            editCallback=self.editLinksListCallback)

        if self.selectedFont is not None:
            self.w.linksList.setSelection([0])
            self.currentRow = self.w.linksList[0]
            self.matchDisplayedSubscriptions()

        jumpingY += self.w.linksList.getPosSize()[3] + MARGIN_ROW
        buttonWidth = (NET_WIDTH - MARGIN_HOR) / 2
        self.w.linkAllButton = SquareButton(
            (MARGIN_HOR, jumpingY, buttonWidth,
             vanillaControlsSize['ButtonRegularHeight'] * 1.5),
            'Link All',
            callback=self.linkAllButtonCallback)

        self.w.unlockAllButton = SquareButton(
            (MARGIN_HOR * 2 + buttonWidth, jumpingY, buttonWidth,
             vanillaControlsSize['ButtonRegularHeight'] * 1.5),
            'Unlink All',
            callback=self.unlockAllButtonCallback)

        jumpingY += vanillaControlsSize[
            'ButtonRegularHeight'] * 1.5 + MARGIN_ROW
        self.w.separationLineOne = HorizontalLine(
            (MARGIN_HOR, jumpingY, NET_WIDTH,
             vanillaControlsSize['HorizontalLineThickness']))

        jumpingY += MARGIN_ROW
        self.w.pushIntoFontButton = SquareButton(
            (MARGIN_HOR, jumpingY, buttonWidth,
             vanillaControlsSize['ButtonRegularHeight'] * 1.5),
            'Push into font',
            callback=self.pushIntoFontButtonCallback)
        self.w.pushIntoFontButton.enable(False)

        self.w.clearLibsButton = SquareButton(
            (MARGIN_HOR * 2 + buttonWidth, jumpingY, buttonWidth,
             vanillaControlsSize['ButtonRegularHeight'] * 1.5),
            'Clear Libs',
            callback=self.clearLibsButtonCallback)

        jumpingY += vanillaControlsSize[
            'ButtonRegularHeight'] * 1.5 + MARGIN_ROW
        self.w.loadFromTable = SquareButton(
            (MARGIN_HOR, jumpingY, buttonWidth,
             vanillaControlsSize['ButtonRegularHeight'] * 1.5),
            'Load from table',
            callback=self.loadFromTableCallback)
        self.w.loadFromTable.enable(True)

        self.w.exportTable = SquareButton(
            (MARGIN_HOR * 2 + buttonWidth, jumpingY, buttonWidth,
             vanillaControlsSize['ButtonRegularHeight'] * 1.5),
            'Export table',
            callback=self.exportTableCallback)
        self.w.exportTable.enable(True)

        jumpingY += vanillaControlsSize[
            'ButtonRegularHeight'] * 1.5 + MARGIN_VER * 2
        self.w.resize(PLUGIN_WIDTH, jumpingY)

        self.setUpBaseWindowBehavior()

        if self.selectedFont is not None:
            self.matchSubscriptions()
            result = askYesNo('Warning',
                              'Do you want to align servants to masters?')
            if bool(result) is True:
                self._alignServantsToMasters()

        addObserver(self, "drawOnGlyphCanvas", "draw")
        addObserver(self, "drawOnGlyphCanvas", "drawInactive")
        addObserver(self, 'fontDidOpenCallback', 'fontDidOpen')
        addObserver(self, 'fontDidCloseCallback', 'fontDidClose')
        if willOpen is True:
            self.w.open()

    # drawing callbacks
    def drawOnGlyphCanvas(self, infoDict):
        glyphOnCanvas = infoDict['glyph']
        scalingFactor = infoDict['scale']
        bodySize = .25
        horizontalOffset = 80

        if PLUGIN_LIB_NAME in glyphOnCanvas.lib:
            thisLib = glyphOnCanvas.lib[PLUGIN_LIB_NAME]
        else:
            return None

        lftGlyph = None
        if thisLib['lft'] != '':
            lftGlyph = self.selectedFont[thisLib['lft']]

        rgtGlyph = None
        if thisLib['rgt'] != '':
            rgtGlyph = self.selectedFont[thisLib['rgt']]

        try:
            dt.fill(*GRAY)

            if lftGlyph is not None:
                dt.save()
                dt.translate(-lftGlyph.width * bodySize - horizontalOffset,
                             -self.selectedFont.info.unitsPerEm * bodySize)

                # glyph
                dt.scale(bodySize)
                dt.drawGlyph(lftGlyph)

                # lock
                if thisLib['lftActive'] is True:
                    txt = u'🔒'
                else:
                    txt = u'🔓'
                dt.fontSize(300)
                txtWdt, txtHgt = dt.textSize(txt)
                dt.text(txt, (-txtWdt, 0))
                dt.restore()

            if rgtGlyph is not None:
                dt.save()
                dt.translate(glyphOnCanvas.width + horizontalOffset,
                             -self.selectedFont.info.unitsPerEm * bodySize)
                dt.scale(bodySize)
                dt.drawGlyph(rgtGlyph)

                # lock
                if thisLib['rgtActive'] is True:
                    txt = u'🔒'
                else:
                    txt = u'🔓'
                dt.fontSize(300)
                dt.text(txt, (rgtGlyph.width, 0))

                dt.restore()

        except Exception as error:
            print(error)

    def draw(self):
        try:
            if self.selectedFont is not None and self.currentRow is not None:
                scalingFactor = CANVAS_HEIGHT / (
                    self.selectedFont.info.unitsPerEm + UPM_MARGIN)

                if self.currentRow['lft'] in self.selectedFont:
                    lftGlyph = self.selectedFont[self.currentRow['lft']]
                    if lftGlyph is not None:
                        drawReferenceGlyph(aGlyph=lftGlyph,
                                           scalingFactor=scalingFactor,
                                           startingX=NET_WIDTH * (1 / 6),
                                           left=True,
                                           right=False)

                    drawLock(closed=self.currentRow['lftActive'],
                             startingX=NET_WIDTH * (2 / 6),
                             glyphQuota=self.selectedFont.info.xHeight,
                             scalingFactor=scalingFactor)

                if self.currentRow['servant'] in self.selectedFont:
                    servantGlyph = self.selectedFont[
                        self.currentRow['servant']]
                    if servantGlyph is not None:
                        drawReferenceGlyph(aGlyph=servantGlyph,
                                           scalingFactor=scalingFactor,
                                           startingX=NET_WIDTH * (3 / 6),
                                           left=True,
                                           right=True)

                if self.currentRow['rgt'] in self.selectedFont:
                    rgtGlyph = self.selectedFont[self.currentRow['rgt']]
                    if rgtGlyph is not None:
                        drawReferenceGlyph(aGlyph=rgtGlyph,
                                           scalingFactor=scalingFactor,
                                           startingX=NET_WIDTH * (5 / 6),
                                           right=True)

                    drawLock(closed=self.currentRow['rgtActive'],
                             startingX=NET_WIDTH * (4 / 6),
                             glyphQuota=self.selectedFont.info.xHeight,
                             scalingFactor=scalingFactor)

        except Exception as error:
            print(error)

    # observers
    def unsubscribeGlyphs(self):
        for eachGlyph in self.servantSubscriptions:
            eachGlyph.removeObserver(self, "Glyph.WidthChanged")
        self.servantSubscriptions = list()
        for eachGlyph in self.masterSubscriptions:
            eachGlyph.removeObserver(self, "Glyph.WidthChanged")
        self.masterSubscriptions = list()

    def unsubscribeDisplayedGlyphs(self):
        for eachGlyph in self.displayedSubscriptions:
            eachGlyph.removeObserver(self, "Glyph.Changed")
        self.displayedSubscriptions = list()

    def matchDisplayedSubscriptions(self):
        self.unsubscribeDisplayedGlyphs()

        if self.currentRow['lft'] != '':
            lftGlyph = self.selectedFont[self.currentRow['lft']]
            if lftGlyph not in self.displayedSubscriptions:
                lftGlyph.addObserver(self, 'displayedGlyphChanged',
                                     'Glyph.Changed')
                self.displayedSubscriptions.append(lftGlyph)

        if self.currentRow['rgt'] != '':
            rgtGlyph = self.selectedFont[self.currentRow['rgt']]
            if rgtGlyph not in self.displayedSubscriptions:
                rgtGlyph.addObserver(self, 'displayedGlyphChanged',
                                     'Glyph.Changed')
                self.displayedSubscriptions.append(rgtGlyph)

        if self.currentRow['servant'] != '':
            servantGlyph = self.selectedFont[self.currentRow['servant']]
            if servantGlyph not in self.displayedSubscriptions:
                servantGlyph.addObserver(self, 'displayedGlyphChanged',
                                         'Glyph.Changed')
                self.displayedSubscriptions.append(servantGlyph)

    def matchSubscriptions(self):
        self.unsubscribeGlyphs()

        for servantGlyph in self.selectedFont:
            if PLUGIN_LIB_NAME in servantGlyph.lib:
                thisLib = servantGlyph.lib[PLUGIN_LIB_NAME]

                if (thisLib['lft'] != '' and thisLib['lftActive'] is True) or (
                        thisLib['rgt'] != '' and thisLib['rgtActive'] is True):
                    if servantGlyph not in self.servantSubscriptions:
                        servantGlyph.addObserver(self, "servantGlyphChanged",
                                                 "Glyph.WidthChanged")
                        self.servantSubscriptions.append(servantGlyph)

                    # servants
                    if thisLib['lftActive'] is True and thisLib['lft'] != '':
                        lftMaster = self.selectedFont[thisLib['lft']]
                        if lftMaster not in self.masterSubscriptions:
                            lftMaster.addObserver(self, "masterGlyphChanged",
                                                  "Glyph.WidthChanged")
                            self.masterSubscriptions.append(lftMaster)

                    if thisLib['rgtActive'] is True and thisLib['rgt'] != '':
                        rgtMaster = self.selectedFont[thisLib['rgt']]
                        if rgtMaster not in self.masterSubscriptions:
                            rgtMaster.addObserver(self, "masterGlyphChanged",
                                                  "Glyph.WidthChanged")
                            self.masterSubscriptions.append(rgtMaster)

    def servantGlyphChanged(self, notification):
        glyph = notification.object
        warningMessage = 'The glyph <{servantName}> is linked to <{masterName}>, do you want to broke the link?'

        if PLUGIN_LIB_NAME in glyph.lib:
            thisLib = glyph.lib[PLUGIN_LIB_NAME]

            if thisLib['lftActive'] is True:
                lftMaster = self.selectedFont[thisLib['lft']]
                if glyph.leftMargin != lftMaster.leftMargin:
                    result = askYesNo(
                        'Warning',
                        warningMessage.format(servantName=glyph.name,
                                              masterName=lftMaster.name))
                    if bool(result) is False:
                        glyph.leftMargin = lftMaster.leftMargin
                        thisLib['lftActive'] = True
                    else:
                        thisLib['lftActive'] = False

            if thisLib['rgtActive'] is True:
                rgtMaster = self.selectedFont[thisLib['rgt']]
                if glyph.rightMargin != rgtMaster.rightMargin:
                    result = askYesNo(
                        'Warning',
                        warningMessage.format(servantName=glyph.name,
                                              masterName=rgtMaster.name))
                    if bool(result) is False:
                        glyph.rightMargin = rgtMaster.rightMargin
                        thisLib['rgtActive'] = True
                    else:
                        thisLib['rgtActive'] = False

            links = loadLinksFromFont(self.selectedFont)
            self.w.linksList.set(links)
        self.w.canvas.update()

    def masterGlyphChanged(self, notification):
        masterGlyph = notification.object
        for eachGlyph in self.selectedFont:
            if PLUGIN_LIB_NAME in eachGlyph.lib:
                thisLib = eachGlyph.lib[PLUGIN_LIB_NAME]
                if thisLib['lft'] == masterGlyph.name and thisLib[
                        'lftActive'] is True:
                    eachGlyph.leftMargin = masterGlyph.leftMargin
                if thisLib['rgt'] == masterGlyph.name and thisLib[
                        'rgtActive'] is True:
                    eachGlyph.rightMargin = masterGlyph.rightMargin
        self.w.canvas.update()

    def displayedGlyphChanged(self, notification):
        self.w.canvas.update()

    # callbacks
    def fontDidOpenCallback(self, notification):
        self.allFonts = AllFonts()

        if self.selectedFont is not None:
            previousFontName = self.w.fontPopUp.getItems()[
                self.w.fontPopUp.get()]
        else:
            self.selectedFont = self.allFonts[0]
            previousFontName = None

        newNames = getNamesFrom(self.allFonts)
        self.w.fontPopUp.setItems(newNames)

        if previousFontName is not None:
            self.w.fontPopUp.set(newNames.index(previousFontName))

        links = loadLinksFromFont(self.selectedFont)
        self.w.linksList.set(links)
        self.w.linksList.setSelection([0])
        self.currentRow = self.w.linksList[self.w.linksList.getSelection()[0]]
        self.matchSubscriptions()
        self.matchDisplayedSubscriptions()

    def fontDidCloseCallback(self, notification):
        self.allFonts = AllFonts()

        if self.selectedFont is None and self.allFonts != []:
            self.selectedFont = self.allFonts[0]
            links = loadLinksFromFont(self.selectedFont)
            self.w.linksList.set(links)

        currentFontName = self.w.fontPopUp.getItems()[self.w.fontPopUp.get()]
        newNames = getNamesFrom(self.allFonts)
        self.w.fontPopUp.setItems(newNames)

        if self.allFonts != []:
            if currentName in newNames:
                self.w.fontPopUp.set(newNames.index(currentName))
            else:
                self.w.fontPopUp.set(
                    newNames.index(os.path.basename(self.selectedFont)))

    def fontPopUpCallback(self, sender):
        if self._compareLibsToList() is False:
            result = askYesNo(
                'Some changes were not pushed into font, would you like to do it now? Otherwise the changes will be lost'
            )
            if bool(result) is True:
                self.pushIntoFontButtonCallback(sender=None)
        self.selectedFont = self.allFonts[sender.get()]
        links = loadLinksFromFont(self.selectedFont)
        self.w.linksList.set(links)

    def selectionLinksListCallback(self, sender):
        if sender.getSelection() == []:
            sender.setSelection([0])
        self.currentRow = sender[sender.getSelection()[0]]
        self.matchDisplayedSubscriptions()
        self.w.canvas.update()

    def editLinksListCallback(self, sender):
        self.w.canvas.update()
        self.w.pushIntoFontButton.enable(not self._compareLibsToList())

    def linkAllButtonCallback(self, sender):
        for eachRow in self.w.linksList:
            if eachRow['lft'] != '':
                eachRow['lftActive'] = True
            if eachRow['rgt'] != '':
                eachRow['rgtActive'] = True

    def unlockAllButtonCallback(self, sender):
        for eachRow in self.w.linksList:
            if eachRow['lft'] is not None:
                eachRow['lftActive'] = False
            if eachRow['rgt'] is not None:
                eachRow['rgtActive'] = False

    def pushIntoFontButtonCallback(self, sender):
        for eachRow in self.w.linksList:
            eachGlyph = self.selectedFont[eachRow['servant']]
            newLib = {
                'lft': eachRow['lft'],
                'lftActive': bool(eachRow['lftActive']),
                'rgt': eachRow['rgt'],
                'rgtActive': bool(eachRow['rgtActive'])
            }

            if newLib['lft'] == '' and newLib['rgt'] == '':
                if PLUGIN_LIB_NAME in eachGlyph.lib:
                    del eachGlyph.lib[PLUGIN_LIB_NAME]
            else:
                eachGlyph.lib[PLUGIN_LIB_NAME] = newLib

        self.matchSubscriptions()
        self._alignServantsToMasters()
        self.w.pushIntoFontButton.enable(False)

    def clearLibsButtonCallback(self, sender):
        for eachGlyph in self.selectedFont:
            if PLUGIN_LIB_NAME in eachGlyph.lib:
                del eachGlyph.lib[PLUGIN_LIB_NAME]
        selectionIndex = self.w.linksList.getSelection()
        links = loadLinksFromFont(self.selectedFont)
        self.w.linksList.set(links)
        self.w.linksList.setSelection(selectionIndex)

    def loadFromTableCallback(self, sender):
        loadingPath = getFile("Select table with linked sidebearings")
        if loadingPath is None:
            return None

        with open(loadingPath[0], 'r') as linksTable:
            rawTable = [item for item in linksTable.readlines()]

        changedItems = []
        toBeLinksList = list(self.selectedFont.glyphOrder)
        for indexRow, eachRow in enumerate(rawTable):
            lft, lftActive, servant, rgtActive, rgt = [
                item.strip() for item in eachRow.split('\t')
            ]
            servantResult = self._isGlyphNameAllowed(servant)
            lftResult = self._isGlyphNameAllowed(lft)
            rgtResult = self._isGlyphNameAllowed(rgt)

            if all([servantResult, lftResult, rgtResult]) is False:
                message(
                    'Line {} contains a mistake'.format(indexRow + 1),
                    'One or more glyphs [lft:<{}> servant:<{}> rgt:<{}>] are not allowed in this font'
                    .format(lft, servant, rgt))
                return None

            if servant in toBeLinksList:
                servantIndex = toBeLinksList.index(servant)
                toBeLinksList[servantIndex] = {
                    'lft': lft,
                    'lftActive': True if lftActive == 'True' else False,
                    'servant': servant,
                    'rgt': rgt,
                    'rgtActive': True if rgtActive == 'True' else False
                }
                changedItems.append(servantIndex)

        for eachUnchangedIndex in [
                ii for ii in range(len(toBeLinksList))
                if ii not in changedItems
        ]:
            toBeLinksList[eachUnchangedIndex] = {
                'lft': '',
                'lftActive': False,
                'servant': toBeLinksList[eachUnchangedIndex],
                'rgt': '',
                'rgtActive': False
            }

        self.w.linksList.set(toBeLinksList)
        self._compareLibsToList()

    def exportTableCallback(self, sender):
        savingPath = putFile("")
        if savingPath is None:
            return None

        with open(savingPath, 'w') as linksTable:
            for eachRow in self.w.linksList:
                if eachRow['lft'] != '' or eachRow['rgt'] != '':
                    linksTable.write(
                        '{lft}\t{lftActive}\t{servant}\t{rgtActive}\t{rgt}\n'.
                        format(**eachRow))

    def windowCloseCallback(self, sender):
        self.unsubscribeGlyphs()
        self.unsubscribeDisplayedGlyphs()
        removeObserver(self, 'fontDidOpen')
        removeObserver(self, 'fontDidClose')
        removeObserver(self, "draw")
        removeObserver(self, "drawInactive")
        super(SidebearingsLinker, self).windowCloseCallback(sender)

    # private methods
    def _isGlyphNameAllowed(self, glyphName):
        if glyphName == '':
            return True
        elif glyphName not in self.selectedFont:
            return False
        else:
            return True

    def _compareLibsToList(self):
        inFont = loadLinksFromFont(self.selectedFont)
        return inFont == [item for item in self.w.linksList]

    def _alignServantsToMasters(self):
        for eachGlyph in self.selectedFont:
            if PLUGIN_LIB_NAME in eachGlyph.lib:
                thisLib = eachGlyph.lib[PLUGIN_LIB_NAME]

                if thisLib['lftActive'] is True and thisLib['lft'] != '':
                    lftMaster = self.selectedFont[thisLib['lft']]
                    eachGlyph.leftMargin = lftMaster.leftMargin

                if thisLib['rgtActive'] is True and thisLib['rgt'] != '':
                    rgtMaster = self.selectedFont[thisLib['rgt']]
                    eachGlyph.rightMargin = rgtMaster.rightMargin
Example #10
0
class AscenderDescenderCalculator(BaseWindowController):

    lowerExtreme = None
    higherExtreme = None

    is_hhea = False
    is_vhea = False
    is_osTwo = False
    is_usWin = False

    def __init__(self):
        super(AscenderDescenderCalculator, self).__init__()
        self.w = FloatingWindow((0, 0, PLUGIN_WIDTH, PLUGIN_HEIGHT),
                                PLUGIN_TITLE)

        jumpingY = MARGIN_VER
        self.w.calcButton = SquareButton(
            (MARGIN_HOR, jumpingY, NET_WIDTH,
             vanillaControlsSize['ButtonRegularHeight'] * 1.5),
            'Measure Extremes',
            callback=self.calcButtonCallback)

        jumpingY += vanillaControlsSize[
            'ButtonRegularHeight'] * 1.5 + MARGIN_ROW
        self.w.topCaption = TextBox(
            (MARGIN_HOR, jumpingY, NET_WIDTH,
             vanillaControlsSize['TextBoxRegularHeight']), 'Top: None')

        jumpingY += vanillaControlsSize['TextBoxRegularHeight'] + MARGIN_ROW
        self.w.btmCaption = TextBox(
            (MARGIN_HOR, jumpingY, NET_WIDTH,
             vanillaControlsSize['TextBoxRegularHeight']), 'Bottom: None')

        jumpingY += vanillaControlsSize['TextBoxRegularHeight']
        self.w.separationLine = HorizontalLine(
            (MARGIN_HOR, jumpingY, NET_WIDTH,
             vanillaControlsSize['TextBoxRegularHeight']))

        jumpingY += vanillaControlsSize['TextBoxRegularHeight'] + MARGIN_ROW
        self.w.check_hhea = CheckBox(
            (MARGIN_HOR, jumpingY, NET_WIDTH,
             vanillaControlsSize['CheckBoxRegularHeight']),
            'hhea table',
            value=self.is_hhea,
            callback=self.check_hheaCallback)

        jumpingY += vanillaControlsSize['CheckBoxRegularHeight'] + MARGIN_ROW
        self.w.check_vhea = CheckBox(
            (MARGIN_HOR, jumpingY, NET_WIDTH,
             vanillaControlsSize['CheckBoxRegularHeight']),
            'vhea table',
            value=self.is_vhea,
            callback=self.check_vheaCallback)

        jumpingY += vanillaControlsSize['CheckBoxRegularHeight'] + MARGIN_ROW
        self.w.check_osTwo = CheckBox(
            (MARGIN_HOR, jumpingY, NET_WIDTH,
             vanillaControlsSize['CheckBoxRegularHeight']),
            'OS/2 table',
            value=self.is_osTwo,
            callback=self.check_osTwoCallback)

        jumpingY += vanillaControlsSize['CheckBoxRegularHeight'] + MARGIN_ROW
        self.w.check_usWin = CheckBox(
            (MARGIN_HOR, jumpingY, NET_WIDTH,
             vanillaControlsSize['CheckBoxRegularHeight']),
            'usWin table',
            value=self.is_usWin,
            callback=self.check_usWinCallback)

        jumpingY += vanillaControlsSize['CheckBoxRegularHeight'] + MARGIN_ROW
        self.w.writeButton = SquareButton(
            (MARGIN_HOR, jumpingY, NET_WIDTH,
             vanillaControlsSize['ButtonRegularHeight'] * 1.5),
            'Write values into fonts',
            callback=self.writeButtonCallback)

        jumpingY += vanillaControlsSize[
            'ButtonRegularHeight'] * 1.5 + MARGIN_VER * 1.5
        self.w.resize(PLUGIN_WIDTH, jumpingY)
        self.setUpBaseWindowBehavior()
        self.w.open()

    def calcButtonCallback(self, sender):
        self.lowerExtreme, self.higherExtreme = findFamilyExtremes(AllFonts())
        self.updateCaptions()

    def updateCaptions(self):
        self.w.topCaption.set(
            'Highest: {ex.y} ({ex.glyphName}, {ex.styleName})'.format(
                ex=self.higherExtreme))
        self.w.btmCaption.set(
            'Lowest: {ex.y} ({ex.glyphName}, {ex.styleName})'.format(
                ex=self.lowerExtreme))

    def check_hheaCallback(self, sender):
        self.is_hhea = bool(sender.get())

    def check_vheaCallback(self, sender):
        self.is_vhea = bool(sender.get())

    def check_osTwoCallback(self, sender):
        self.is_osTwo = bool(sender.get())

    def check_usWinCallback(self, sender):
        self.is_usWin = bool(sender.get())

    def writeButtonCallback(self, sender):

        if self.lowerExtreme is not None and self.higherExtreme is not None:

            for eachFont in AllFonts():
                if self.is_hhea is True:
                    eachFont.info.openTypeHheaAscender = self.higherExtreme.y
                    eachFont.info.openTypeHheaDescender = self.lowerExtreme.y

                if self.is_vhea is True:
                    eachFont.info.openTypeVheaVertTypoAscender = self.higherExtreme.y
                    eachFont.info.openTypeVheaVertTypoDescender = self.lowerExtreme.y

                if self.is_osTwo is True:
                    eachFont.info.openTypeOS2TypoAscender = self.higherExtreme.y
                    eachFont.info.openTypeOS2TypoDescender = self.lowerExtreme.y

                if self.is_usWin is True:
                    eachFont.info.openTypeOS2WinAscent = self.higherExtreme.y
                    eachFont.info.openTypeOS2WinDescent = self.lowerExtreme.y

        else:
            message('Calc Extremes first!')
Example #11
0
class Adhesiontext(BaseWindowController):
    def __init__(self):
        flushAlign = 76
        firstRowY = 12
        rowOffsetY = 30
        firstCheckY = 135
        checkOffsetY = 27
        rightMarginX = -12
        self.windowWidth = 410
        self.windowHeightWithoutOptions = 45
        self.windowHeightWithOptions = 280
        self.scriptIsRTL = False

        windowPos = getExtensionDefault("%s.%s" % (extensionKey, "windowPos"))
        if not windowPos:
            windowPos = (100, 100)

        self.optionsVisible = getExtensionDefault(
            "%s.%s" % (extensionKey, "optionsVisible"))
        if self.optionsVisible:
            optionsButtonSign = '-'
            windowHeight = self.windowHeightWithOptions
        else:
            self.optionsVisible = False  # needs to be set because the first time the extension runs self.optionsVisible will be None
            optionsButtonSign = '+'
            windowHeight = self.windowHeightWithoutOptions

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

        self.sliderValue = getExtensionDefault("%s.%s" %
                                               (extensionKey, "sliderValue"))
        if not self.sliderValue:
            self.sliderValue = 25

        self.scriptsIndex = getExtensionDefault("%s.%s" %
                                                (extensionKey, "scriptsIndex"))
        if not self.scriptsIndex:
            self.scriptsIndex = 0

        self.langsIndex = getExtensionDefault("%s.%s" %
                                              (extensionKey, "langsIndex"))
        if not self.langsIndex:
            self.langsIndex = 0

        self.w = FloatingWindow(
            (windowPos[0], windowPos[1], self.windowWidth, windowHeight),
            "adhesiontext")

        # 1st row
        self.w.labelChars = TextBox((10, firstRowY, flushAlign, 20),
                                    "Characters:",
                                    alignment="right")
        self.w.chars = EditText((flushAlign + 15, firstRowY - 1, 199, 22),
                                self.chars,
                                callback=self.charsCallback)
        self.w.button = Button((300, firstRowY, 68, 20),
                               "Get text",
                               callback=self.buttonCallback)
        self.w.spinner = FixedSpinner((325, firstRowY, 20, 20),
                                      displayWhenStopped=False)
        self.w.optionsButton = SquareButton((378, firstRowY + 1, 18, 18),
                                            optionsButtonSign,
                                            sizeStyle="small",
                                            callback=self.optionsCallback)
        # set the initial state of the button according to the content of the chars EditText
        if len(self.w.chars.get()): self.w.button.enable(True)
        else: self.w.button.enable(False)
        # keep track of the content of chars EditText
        self.previousChars = self.w.chars.get()

        # 2nd row
        self.w.labelWords = TextBox(
            (10, firstRowY + rowOffsetY, flushAlign, 20),
            "Words:",
            alignment="right")
        self.w.wordCount = TextBox(
            (flushAlign + 12, firstRowY + rowOffsetY, 40, 20),
            alignment="left")
        self.w.slider = Slider(
            (flushAlign + 47, firstRowY + rowOffsetY + 1, 165, 20),
            value=self.sliderValue,
            minValue=5,
            maxValue=200,
            callback=self.sliderCallback)
        # set the initial wordCount value according to the position of the slider
        self.w.wordCount.set(int(self.w.slider.get()))

        # 3rd row
        self.w.labelScripts = TextBox(
            (10, firstRowY + rowOffsetY * 2, flushAlign, 20),
            "Script:",
            alignment="right")
        self.w.scriptsPopup = PopUpButton(
            (flushAlign + 15, firstRowY + rowOffsetY * 2, 150, 20),
            scriptsNameList,
            callback=self.scriptsCallback)
        self.w.scriptsPopup.set(self.scriptsIndex)

        # 4th row
        self.w.labelLangs = TextBox(
            (10, firstRowY + rowOffsetY * 3, flushAlign, 20),
            "Language:",
            alignment="right")
        self.w.langsPopup = PopUpButton(
            (flushAlign + 15, firstRowY + rowOffsetY * 3, 150, 20), [])
        # set the initial list of languages according to the script value
        self.w.langsPopup.setItems(
            langsNameDict[scriptsNameList[self.w.scriptsPopup.get()]])
        self.w.langsPopup.set(self.langsIndex)

        self.punctCheck = getExtensionDefault("%s.%s" %
                                              (extensionKey, "punctCheck"))
        if not self.punctCheck:
            self.punctCheck = 0

        self.figsCheck = getExtensionDefault("%s.%s" %
                                             (extensionKey, "figsCheck"))
        if not self.figsCheck:
            self.figsCheck = 0

        self.figsPopup = getExtensionDefault("%s.%s" %
                                             (extensionKey, "figsPopup"))
        if not self.figsPopup:
            self.figsPopup = 0

        self.trimCheck = getExtensionDefault("%s.%s" %
                                             (extensionKey, "trimCheck"))
        if not self.trimCheck:
            self.trimCheck = 0

        self.caseCheck = getExtensionDefault("%s.%s" %
                                             (extensionKey, "caseCheck"))
        if not self.caseCheck:
            self.caseCheck = 0

        self.casingCheck = getExtensionDefault("%s.%s" %
                                               (extensionKey, "casingCheck"))
        if not self.casingCheck:
            self.casingCheck = 0

        self.casingPopup = getExtensionDefault("%s.%s" %
                                               (extensionKey, "casingPopup"))
        if not self.casingPopup:
            self.casingPopup = 0

        # 1st checkbox
        self.w.punctCheck = CheckBox((flushAlign + 15, firstCheckY, 130, 20),
                                     "Add punctuation")
        self.w.punctCheck.set(self.punctCheck)

        # 2nd checkbox
        self.w.figsCheck = CheckBox(
            (flushAlign + 15, firstCheckY + checkOffsetY, 120, 20),
            "Insert numbers",
            callback=self.figsCallback)
        self.w.figsCheck.set(self.figsCheck)
        self.w.figsPopup = PopUpButton(
            (210, firstCheckY + checkOffsetY, 90, 20), figOptionsList)
        self.w.figsPopup.set(self.figsPopup)
        # enable or disable the figure options PopUp depending on the figures CheckBox
        if scriptsNameList[self.w.scriptsPopup.get()] in enableFigOptionList:
            self.w.figsPopup.show(True)
            if self.w.figsCheck.get():
                self.w.figsPopup.enable(True)
            else:
                self.w.figsPopup.enable(False)
        else:
            self.w.figsPopup.show(False)

        # 3rd checkbox
        self.w.trimCheck = CheckBoxPlus(
            (flushAlign + 15, firstCheckY + checkOffsetY * 2, 120, 20),
            "Trim accents")
        self.w.trimCheck.set(self.trimCheck)
        if scriptsNameList[self.w.scriptsPopup.get()] in enableTrimCheckList:
            self.w.trimCheck.enable(True)
        else:
            self.w.trimCheck.enable(False)

        # 4th checkbox
        self.w.caseCheck = CheckBoxPlus(
            (flushAlign + 15, firstCheckY + checkOffsetY * 3, 120, 20),
            "Ignore casing")
        self.w.caseCheck.set(self.caseCheck)
        if scriptsNameList[self.w.scriptsPopup.get()] in enableCaseCheckList:
            self.w.caseCheck.enable(True)
        else:
            self.w.caseCheck.enable(False)

        # 5th checkbox
        self.w.casingCheck = CheckBoxPlus(
            (flushAlign + 15, firstCheckY + checkOffsetY * 4, 115, 20),
            "Change casing",
            callback=self.casingCallback)
        self.w.casingCheck.set(self.casingCheck)
        if scriptsNameList[self.w.scriptsPopup.get()] in enableCaseCheckList:
            self.w.casingCheck.enable(True)
        else:
            self.w.casingCheck.enable(False)
        self.w.casingPopup = PopUpButton(
            (210, firstCheckY + checkOffsetY * 4, 90, 20), casingNameList)
        self.w.casingPopup.set(self.casingPopup)
        # enable or disable the casing PopUp depending on the casing CheckBox
        if self.w.casingCheck.get() and self.w.casingCheck.isEnable():
            self.w.casingPopup.enable(True)
        else:
            self.w.casingPopup.enable(False)

        self.nsTextField = self.w.chars.getNSTextField()
        self.w.setDefaultButton(self.w.button)
        self.w.bind("close", self.windowClose)
        self.w.open()
        self.w.makeKey()

    def windowClose(self, sender):
        self.saveExtensionDefaults()

    def saveExtensionDefaults(self):
        setExtensionDefault("%s.%s" % (extensionKey, "windowPos"),
                            self.w.getPosSize()[0:2])
        setExtensionDefault("%s.%s" % (extensionKey, "optionsVisible"),
                            self.optionsVisible)
        setExtensionDefault("%s.%s" % (extensionKey, "chars"),
                            self.w.chars.get())
        setExtensionDefault("%s.%s" % (extensionKey, "sliderValue"),
                            int(self.w.slider.get()))
        setExtensionDefault("%s.%s" % (extensionKey, "scriptsIndex"),
                            int(self.w.scriptsPopup.get()))
        setExtensionDefault("%s.%s" % (extensionKey, "langsIndex"),
                            int(self.w.langsPopup.get()))
        setExtensionDefault("%s.%s" % (extensionKey, "punctCheck"),
                            self.w.punctCheck.get())
        setExtensionDefault("%s.%s" % (extensionKey, "figsCheck"),
                            self.w.figsCheck.get())
        setExtensionDefault("%s.%s" % (extensionKey, "figsPopup"),
                            self.w.figsPopup.get())
        setExtensionDefault("%s.%s" % (extensionKey, "trimCheck"),
                            self.w.trimCheck.get())
        setExtensionDefault("%s.%s" % (extensionKey, "caseCheck"),
                            self.w.caseCheck.get())
        setExtensionDefault("%s.%s" % (extensionKey, "casingCheck"),
                            self.w.casingCheck.get())
        setExtensionDefault("%s.%s" % (extensionKey, "casingPopup"),
                            self.w.casingPopup.get())

    def buttonCallback(self, sender):
        sender.enable(False)
        self.w.spinner.start()
        self.getText()
        self.w.spinner.stop()
        sender.enable(True)

    def optionsCallback(self, sender):
        sign = sender.getTitle()
        if sign == "+":
            sender.setTitle("-")
            self.w.resize(self.windowWidth,
                          self.windowHeightWithOptions,
                          animate=True)
            self.optionsVisible = True
        else:
            sender.setTitle("+")
            self.w.resize(self.windowWidth,
                          self.windowHeightWithoutOptions,
                          animate=True)
            self.optionsVisible = False

    def charsCallback(self, sender):
        charsContent = sender.get()
        if len(charsContent):
            self.w.button.enable(True)
            nsTextView = self.nsTextField.currentEditor(
            )  # NOTE: the field editor is only available when NSTextField is in editing mode.

            # when only one glyph is selected and copied, the contents of the clipboard are the glyph's XML
            # instead of its unicode character or its name; therefore, post-process the pasted content.
            if xmlHeader in charsContent:
                caretIndex = charsContent.index(xmlHeader)
                codepointString = re_glyphUnicode.search(charsContent)
                glyphName = re_glyphName.search(charsContent)

                if codepointString:
                    replacement = unichr(eval('0x' + codepointString.group(1)))
                elif glyphName:
                    replacement = '/' + glyphName.group(1)
                else:
                    replacement = ''

                # replace the glyph's XML by its unicode character or its name
                self.w.chars.set(re_glyph.sub(replacement, charsContent))
                # restore the location of the caret
                location = caretIndex + len(replacement)
                nsTextView.setSelectedRange_((location, 0))
                # update the variable
                charsContent = sender.get()

            caretIndex = nsTextView.selectedRanges()[0].rangeValue().location

            # Limit the number of characters
            numeralWasFound = self.stringHasNumeral(charsContent)
            if len(charsContent) > maxChars or numeralWasFound:
                NSBeep()
                if numeralWasFound:
                    self.showMessage("Sorry, numerals are not allowed.", "")
                else:
                    self.showMessage(
                        "You've reached the maximum \rnumber of characters.",
                        "The limit is %d." % maxChars)
                # restore the content of chars EditText to the previous string
                sender.set(self.previousChars)
                # restore the focus on the chars EditText and restore the location of the caret
                caretIndexAdjust = len(self.previousChars) - len(charsContent)
                self.w.getNSWindow().makeFirstResponder_(self.nsTextField)
                nsTextView.setSelectedRange_(
                    (caretIndex + caretIndexAdjust, 0))

            # update the stored string
            self.previousChars = sender.get()

        else:
            self.w.button.enable(False)

    def sliderCallback(self, sender):
        self.w.wordCount.set(int(sender.get()))

    def scriptsCallback(self, sender):
        self.w.langsPopup.setItems(
            langsNameDict[scriptsNameList[sender.get()]])
        # toggle RTL/LTR
        if scriptsNameList[sender.get()] in rightToLeftList:
            self.scriptIsRTL = True
            self.nsTextField.setBaseWritingDirection_(
                NSWritingDirectionRightToLeft)
            self.nsTextField.setAlignment_(NSRightTextAlignment)
        else:
            self.scriptIsRTL = False
            self.nsTextField.setBaseWritingDirection_(
                NSWritingDirectionLeftToRight)
            self.nsTextField.setAlignment_(NSLeftTextAlignment)
        # restore the focus on the chars EditText
        self.w.getNSWindow().makeFirstResponder_(self.nsTextField)
        # toggle figsPopup
        if scriptsNameList[sender.get()] in enableFigOptionList:
            self.w.figsPopup.show(True)
            if self.w.figsCheck.get():
                self.w.figsPopup.enable(True)
            else:
                self.w.figsPopup.enable(False)
        else:
            self.w.figsPopup.show(False)
        # toggle trimCheck
        if scriptsNameList[sender.get()] in enableTrimCheckList:
            self.w.trimCheck.enable(True)
        else:
            self.w.trimCheck.enable(False)
        # toggle caseCheck and casingCheck
        if scriptsNameList[sender.get()] in enableCaseCheckList:
            self.w.caseCheck.enable(True)
            self.w.casingCheck.enable(True)
            if self.w.casingCheck.get():
                self.w.casingPopup.enable(True)
        else:
            self.w.caseCheck.enable(False)
            self.w.casingCheck.enable(False)
            self.w.casingPopup.enable(False)

    def figsCallback(self, sender):
        if sender.get():
            self.w.figsPopup.enable(True)
        else:
            self.w.figsPopup.enable(False)

    def casingCallback(self, sender):
        if sender.get():
            self.w.casingPopup.enable(True)
        else:
            self.w.casingPopup.enable(False)

    def stringHasNumeral(self, string):
        if re_numeral.search(string):
            return True
        return False

    def isConnected(self):
        try:
            urlopen(url, timeout=3)
            return True
        except URLError:
            pass
        return False

    def getText(self):
        if CurrentFont() is None:
            NSBeep()
            self.showMessage("Open a font first.", "")
            return

        if not self.isConnected():
            NSBeep()
            self.showMessage("Required internet connection not found.", "")
            return

        values = {
            'chars':
            self.w.chars.get().encode('utf-8'),
            'script':
            scriptsTagDict[scriptsNameList[self.w.scriptsPopup.get()]],
            'tb':
            langsTagDict[langsNameDict[scriptsNameList[
                self.w.scriptsPopup.get()]][self.w.langsPopup.get()]]
        }

        if self.w.punctCheck.get():
            values['punct'] = True
        if self.w.figsCheck.get():
            values['figs'] = True
            if self.w.figsPopup.isVisible():
                figsOptTagsList = ["dflt", "locl"]
                values['figsOpt'] = figsOptTagsList[self.w.figsPopup.get()]
        if self.w.trimCheck.get() and self.w.trimCheck.isEnable():
            values['trim'] = True
        if self.w.caseCheck.get() and self.w.caseCheck.isEnable():
            values['case'] = True
        if self.w.casingCheck.get() and self.w.casingCheck.isEnable():
            values['casing'] = casingNameList[self.w.casingPopup.get()].lower()

        data = urlencode(values)
        data = data.encode('utf-8')
        print(data)
        request = Request(url, data)
        response = urlopen(request)
        text = response.read()
        textU = unicode(text, 'utf-8')

        if (msgStr in textU):
            textU = textU.replace(msgStr, "")
            NSBeep()
            self.showMessage(textU, "")
            return

        elif (wrnStr in textU):
            resultIndex = textU.find(rsltStr)
            secmsgIndex = textU.find(sndStr)
            frstmsgU = textU[:secmsgIndex].replace(wrnStr, "")
            scndmsgU = textU[secmsgIndex:resultIndex].replace(sndStr, "")
            textU = textU[resultIndex:].replace(rsltStr, "")
            NSBeep()
            self.showMessage(frstmsgU, scndmsgU)

        textList = textU.split()
        trimmedText = ' '.join(textList[:int(self.w.slider.get())])

        if CurrentSpaceCenter() is None:
            OpenSpaceCenter(CurrentFont(), newWindow=False)

        sp = CurrentSpaceCenter()
        print(trimmedText)
        sp.setRaw(trimmedText)

        # Toggle RTL-LTR
        try:
            sp.setLeftToRight(not self.scriptIsRTL)
            sp.setInputWritingDirection(
                'Right to Left' if self.scriptIsRTL else 'Left to Right')
        except AttributeError:
            pass

        return