Beispiel #1
0
class CopyKerning:

    def __init__(self):
        if AllFonts() is None:
            from vanilla.dialogs import message
            message("No fonts open.", "Open or create a font to copy data to and fro.")
            return

        self.sourceFontList = AllFonts()
        self.destinationFontList = AllFonts()
        self.source_font = self.sourceFontList[0]
        self.destination_fonts = None
        self.groups = None
        self.kerning = None

        ## create a window
        self.w = Window((400, 500), "Copy Groups and Kerning", minSize=(500, 600))
        self.w.sourceTitle = TextBox((15, 20, 200, 20), "Source Font:")
        self.w.sourceFont = PopUpButton((15, 42, 340, 20), [f.info.familyName + ' ' + f.info.styleName for f in self.sourceFontList], callback=self.sourceCallback)
        self.w.desTitle = TextBox((15, 76, 200, 20), "Destination Fonts:")
        self.w.destinationFonts = FontList((15, 96, -15, -115), self.destinationFontList, selectionCallback=self.desCallback)
        self.w.copyButton = Button((-215, -40, 200, 20), 'Copy Groups & Kerning', callback=self.copyCallback)
        self.w.line = HorizontalLine((10, -60, -10, 1))
        self._updateDest()
        ## open the window
        self.w.open()

    def _updateDest(self):
        des = list(self.sourceFontList)
        des.remove(self.source_font)
        self.w.destinationFonts.set(des)

    def copyKerning(self, groups, kerning, source_font, destination_fonts):
        kerning = source_font.kerning.asDict()
        groups = source_font.groups
        for font in destination_fonts:
            font.groups.update(groups)
            font.kerning.update(kerning)

    def sourceCallback(self, sender):
        self.source_font = self.sourceFontList[sender.get()]
        self._updateDest()

    def desCallback(self, sender):
        self.destination_fonts = [sender.get()[x] for x in sender.getSelection()]

    def copyCallback(self, sender):
        self.sheet = Sheet((300, 50), self.w)
        self.sheet.bar = ProgressBar((10, 20, -10, 10), isIndeterminate=True, sizeStyle="small")
        self.sheet.open()
        self.sheet.bar.start()
        self.copyKerning(self.groups, self.kerning, self.source_font, self.destination_fonts)
        self.sheet.bar.stop()
        self.sheet.close()
        del self.sheet
        self.w.close()
Beispiel #2
0
 def copyCallback(self, sender):
     self.sheet = Sheet((300, 50), self.w)
     self.sheet.bar = ProgressBar((10, 20, -10, 10), isIndeterminate=True, sizeStyle="small")
     self.sheet.open()
     self.sheet.bar.start()
     self.copyGlyphs(self.glyphs, self.source_font, self.destination_fonts, self.doOverwrite, self.doMarkGlyphs)
     self.sheet.bar.stop()
     self.sheet.close()
     del self.sheet
     self.w.close()
Beispiel #3
0
 def show_notification_sheet(self, text, size=(300, 80)):
     self.w.notification = Sheet(size, self.parent.w)
     self.w.notification.text = TextBox((15, 15, -50, -15), text)
     self.w.notification.closeButton = Button(
         (-115, -37, 100, 22),
         'Close',
         callback=self.close_notification_sheet)
     self.w.notification.setDefaultButton(
         self.parent.w.notification.closeButton)
     self.w.notification.open()
Beispiel #4
0
 def copyCallback(self, sender):
     self.sheet = Sheet((300, 50), self.w)
     self.sheet.bar = ProgressBar((10, 20, -10, 10), isIndeterminate=True, sizeStyle="small")
     self.sheet.open()
     self.sheet.bar.start()
     self.copyGlyphs(self.glyphs, self.source_font, self.destination_fonts, self.doOverwrite, self.doMarkGlyphs)
     self.sheet.bar.stop()
     self.sheet.close()
     del self.sheet
     self.w.close()
Beispiel #5
0
 def copyCallback(self, sender):
     self.sheet = Sheet((300, 50), self.w)
     self.sheet.bar = ProgressBar((10, 20, -10, 10), isIndeterminate=True, sizeStyle="small")
     self.sheet.open()
     self.sheet.bar.start()
     self.copyKerning(self.groups, self.kerning, self.source_font, self.destination_fonts)
     self.sheet.bar.stop()
     self.sheet.close()
     del self.sheet
     self.w.close()
 def add_recipient(self, sender):
     self.window.sheet = Sheet((250, 89), self.window)
     self.window.sheet.recipient = EditText((15, 15, -15, 22),
                                            "",
                                            placeholder="Email Address")
     self.window.sheet.cancel_button = Button((-190, 52, 80, 22),
                                              'Cancel',
                                              callback=self.close_sheet)
     self.window.sheet.create_button = Button(
         (-95, 52, 80, 22), 'Add', callback=self.create_recipient)
     self.window.sheet.setDefaultButton(self.window.sheet.create_button)
     self.window.sheet.open()
    def buildFilterGroupSheet(self, filterName='', makeNew=False):

        subfilters = self.filters[filterName].subfilters if filterName in self.filters else []
        subfilterItems = [{'filterName': subfilterName, 'mode': subfilterMode if subfilterMode is not None else '', 'source': source if source is not None else ''} for subfilterName, subfilterMode, source in subfilters]

        self.filterSheet = Sheet((0, 0, 400, 350), self.w)
        self.filterSheet.new = makeNew
        self.filterSheet.index = self.filters[filterName].index if not makeNew else -1
        applyTitle = 'Add Operation' if filterName == '' else 'Update Operation'
        self.filterSheet.apply = SquareButton((-145, -37, 130, 22), applyTitle, callback=self.processFilterGroup, sizeStyle='small')
        self.filterSheet.cancel = SquareButton((-210, -37, 60, 22), 'Cancel', callback=self.closeFilterSheet, sizeStyle='small')

        y = 20
        self.filterSheet.nameTitle = TextBox((15, y, 100, 22), 'Filter Name')
        self.filterSheet.name = EditText((125, y, -15, 22), filterName)
        y += 22

        columns = [
            {'title': 'filterName', 'editable': True, 'width': 140},
            {'title': 'mode', 'editable': True, 'width': 89},
            {'title': 'source', 'editable': True, 'width': 100}
        ]

        buttonSize = 20
        gutter = 7

        y += 20
        self.filterSheet.subfilters = List((15 + buttonSize + gutter, y, -15, -52), subfilterItems, columnDescriptions=columns, allowsMultipleSelection=False, allowsEmptySelection=False)
        self.filterSheet.addSubfilter = SquareButton((15, -52-(buttonSize*2)-gutter, buttonSize, buttonSize), '+', sizeStyle='small', callback=self.addSubfilter)
        self.filterSheet.removeSubfilter = SquareButton((15, -52-buttonSize, buttonSize, buttonSize), '-', sizeStyle='small', callback=self.removeSubfilter)
        if len(subfilters) == 0:
            self.filterSheet.removeSubfilter.enable(False)
        y += 75
        self.filterSheet.moveSubfilterUp = SquareButton((15, y, buttonSize, buttonSize), u'⇡', sizeStyle='small', callback=self.moveSubfilterUp)
        self.filterSheet.moveSubfilterDown = SquareButton((15, y + buttonSize + gutter, buttonSize, buttonSize), u'⇣', sizeStyle='small', callback=self.moveSubfilterDown)

        if filterName == '':
            self.currentFilterName = ''
Beispiel #8
0
    def _warning(self, sender, warning, prefKey):
        if self.prefs.get(prefKey):
            self.warning = Sheet((400, 140), self.w)
            self.warning.img = ImageView((10, 10, 60, 60))
            self.warning.img.setImage(imageNamed=NSImageNameCaution)
            self.warning.txt = TextBox((70, 10, -10, -40),
                                       "Warning\n" + warning)

            callback = partial(self._changePref,
                               key=prefKey,
                               value=not self.prefs.get(prefKey))
            self.warning.check = CheckBox((70, 80, -10, 20),
                                          "Always show this warning",
                                          value=self.prefs.get(prefKey),
                                          callback=callback)

            self.warning.closeButton = Button((10, 110, -10, 20),
                                              "I understand",
                                              callback=self._closeWarning)
            self.warning.setDefaultButton(self.warning.closeButton)
            self.warning.center()
            self.w.list.enable(False)
            self.warning.open()
Beispiel #9
0
 def show_subscriber_sheet(self, sender):
     self.window.sheet = Sheet((250, 107), self.window)
     self.window.sheet.name = EditText((15, 15, -15, 22),
                                       "",
                                       placeholder="Name")
     self.window.sheet.email_address = EditText((15, 43, -15, 22),
                                                "",
                                                placeholder="Email Address")
     self.window.sheet.cancel_button = Button((-190, 70, 80, 22),
                                              'Cancel',
                                              callback=self.close_sheet)
     self.window.sheet.create_button = Button(
         (-95, 70, 80, 22), 'Add', callback=self.create_subscriber)
     self.window.sheet.setDefaultButton(self.window.sheet.create_button)
     self.window.sheet.open()
    def buildFilterSheet(self, filterName='', makeNew=False):
        sheetFields = {
            'file': '',
            'module': '',
            'filterObjectName': '',
            'limits': {},
            'arguments': {},
        }
        if filterName != '':
            filterDict = self.filters[filterName].getFilterDict()
            for key in filterDict:
                if key == "arguments":
                    entry = OrderedDict(filterDict[key])
                else:
                    entry = filterDict[key]
                sheetFields[key] = entry

        self.filterSheet = Sheet((0, 0, 400, 350), self.w)
        self.filterSheet.new = makeNew
        self.filterSheet.index = self.filters[filterName].index if not makeNew else -1
        applyTitle = 'Add Filter' if filterName == '' else 'Update Filter'
        self.filterSheet.apply = SquareButton((-115, -37, 100, 22), applyTitle, callback=self.processFilter, sizeStyle='small')
        self.filterSheet.cancel = SquareButton((-205, -37, 80, 22), 'Cancel', callback=self.closeFilterSheet, sizeStyle='small')

        y = 20
        self.filterSheet.nameTitle = TextBox((15, y, 100, 22), 'Filter Name')
        self.filterSheet.name = EditText((125, y, -15, 22), filterName)
        y += 22

        tabs = ['module','file']
        selectedTab = 0 if len(sheetFields['module']) >= len(sheetFields['file']) else 1
        filterObjectName = sheetFields['filterObjectName']

        y += 20
        self.filterSheet.importPath = Tabs((15, y, -15, 75), tabs)
        self.filterSheet.importPath.set(selectedTab)
        modulePathTab = self.filterSheet.importPath[0]
        filePathTab = self.filterSheet.importPath[1]

        modulePathTab.pathInput = EditText((10, 10, -10, -10), sheetFields['module'])
        filePathTab.pathInput = EditText((10, 10, -110, -10), sheetFields['file'])
        filePathTab.fileInput = SquareButton((-100, 10, 90, -10), u'Add File…', sizeStyle='small', callback=self.getFile)
        y += 75

        y += 10
        self.filterSheet.filterObjectTitle = TextBox((15, y, 100, 22), 'Filter Object (pen, function)')
        self.filterSheet.filterObject = EditText((125, y, -15, 22), filterObjectName)
        y += 22

        y += 20
        columns = [
            {'title': 'argument', 'width': 160, 'editable':True},
            {'title': 'value', 'width': 71, 'editable':True},
            {'title': 'min', 'width': 49, 'editable':True},
            {'title': 'max', 'width': 49, 'editable':True}
        ]

        arguments = sheetFields['arguments']
        limits = sheetFields['limits']

        argumentItems = []

        for key, value in arguments.items():
            if isinstance(value, bool):
                value = str(value)
            elif isinstance(value, float):
                value = round(value, 2)
            argItem = {
                'argument': key,
                'value': value
                }
            if key in limits:
                minimum, maximum = sheetFields['limits'][key]
                argItem['min'] = minimum
                argItem['max'] = maximum

            argumentItems.append(argItem)

        buttonSize = 20
        gutter = 7
        self.filterSheet.arguments = List((15 + buttonSize + gutter, y, -15, -52), argumentItems, columnDescriptions=columns, allowsMultipleSelection=False, allowsEmptySelection=False)
        self.filterSheet.addArgument = SquareButton((15, -52-(buttonSize*2)-gutter, buttonSize, buttonSize), '+', sizeStyle='small', callback=self.addArgument)
        self.filterSheet.removeArgument = SquareButton((15, -52-buttonSize, buttonSize, buttonSize), '-', sizeStyle='small', callback=self.removeArgument)
        if len(argumentItems) == 0:
            self.filterSheet.removeArgument.enable(False)

        if filterName == '':
            self.currentFilterName = ''
class PenBallWizardController(object):

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

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

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

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

        self.updateControls()

        self.w.bind('close', self.end)
        self.launchWindow()
        self.w.open()

    def generateGlyphsToFont(self, sender):
        newFont = RFont(showUI=False)
        font = self.currentFont
        filterName = self.currentFilterName
        currentFilter = self.filters[filterName]
        if font is not None:
            glyphs = [font[glyphName] for glyphName in font.selection if glyphName in font]
            for glyph in glyphs:
                if len(glyph.components) > 0:
                    for comp in glyph.components:
                        baseGlyphName = comp.baseGlyph
                        baseGlyph = font[baseGlyphName]
                        baseFilteredGlyph = currentFilter(baseGlyph)
                        newFont.insertGlyph(baseFilteredGlyph, baseGlyphName)
                        newFont[baseGlyphName].unicode = baseFilteredGlyph.unicode
                filteredGlyph = currentFilter(glyph)
                if filteredGlyph is not None:
                    newFont.insertGlyph(filteredGlyph, glyph.name)
            newFont.showUI()

    def generateGlyphsToLayer(self, layerName):
        font = self.currentFont
        filterName = self.currentFilterName
        currentFilter = self.filters[filterName]
        if font is not None:
            glyphs = [font[glyphName] for glyphName in font.selection if glyphName in font]
            for glyph in glyphs:
                if len(glyph.components) == 0:
                    layerGlyph = glyph.getLayer(layerName)
                    filteredGlyph = currentFilter(glyph)
                    if filteredGlyph is not None:
                        layerGlyph.appendGlyph(filteredGlyph)

    def updateFiltersList(self, selectedIndex=0):
        filtersList = self.filters.keys()
        self.w.filtersPanel.filtersList.set(filtersList)
        self.w.filtersPanel.filtersList.setSelection([selectedIndex])

    def setArgumentValue(self, sender):
        value = sender.get()
        valueType = sender.type
        if valueType == 'bool':
            value = bool(value)
        key = sender.name
        if self.currentFilterName is not None:
            self.filters.setArgumentValue(self.currentFilterName, key, value)
            self.resetRepresentations()
        self.updatePreview()

    def resetRepresentations(self):
        font = self.currentFont
        self.cachedFont = RFont(showUI=False)
        if font is not None:
            for glyphName in self.glyphNames:
                if glyphName in font:
                    font[glyphName].naked().destroyAllRepresentations()

    def processGlyphs(self):
        font = self.currentFont
        if font is not None:
            sourceGlyphs = []
            for glyphName in self.glyphNames:
                if glyphName in font:
                    glyph = font[glyphName]
                    if glyph not in self.observedGlyphs:
                        glyph.addObserver(self, 'glyphChanged', 'Glyph.Changed')
                        self.observedGlyphs.append(glyph)
                    sourceGlyphs.append(glyph)
            filterName = self.currentFilterName
            filteredGlyphs = self.filterGlyphs(filterName, sourceGlyphs, self.cachedFont)
            return filteredGlyphs
        return []

    def filterGlyphs(self, filterName, glyphs, font):
        currentFilter = self.filters[filterName]
        filteredGlyphs = []
        for glyph in glyphs:
            if len(glyph.components) > 0:
                for comp in glyph.components:
                    baseGlyphName = comp.baseGlyph
                    baseGlyph = glyph.getParent()[baseGlyphName]
                    baseFilteredGlyph = currentFilter(baseGlyph)
                    if baseFilteredGlyph is not None:
                        font.insertGlyph(baseFilteredGlyph, baseGlyphName)
            filteredGlyph = currentFilter(glyph)
            if filteredGlyph is not None:
                font.insertGlyph(filteredGlyph, glyph.name)
                filteredGlyphs.append(font[glyph.name])
        return filteredGlyphs

    def updatePreview(self, notification=None):
        glyphs = self.processGlyphs()
        self.w.preview.setFont(self.cachedFont)
        self.w.preview.set(glyphs)

    def updateControls(self):
        if self.currentFilterName is not None:
            if hasattr(self.w.filtersPanel, 'controls'):
                delattr(self.w.filtersPanel, 'controls')
            currentFilter = self.filters[self.currentFilterName]
            self.w.filtersPanel.controls = Group((0, 0, 0, 0))
            hasSubfilters = self.filters.hasSubfilters(self.currentFilterName)

            if hasSubfilters:
                argumentBlocks = [(subfilterName, self.filters[subfilterName].arguments) for subfilterName, mode, source in currentFilter.subfilters]
            else:
                argumentBlocks = [(currentFilter.name, currentFilter.arguments)]

            gap = 5
            height = gap
            end = 0
            lineheight = 27
            top = 35
            boxes = 0

            for j, (filterName, arguments)  in enumerate(argumentBlocks):
                if len(arguments) > 0:
                    blockfilterName = '{0}{1}'.format(filterName, j)
                    setattr(self.w.filtersPanel.controls, blockfilterName, Box((5, 5, 0, 0)))
                    block = getattr(self.w.filtersPanel.controls, blockfilterName)
                    if hasSubfilters:
                        _, filterMode, filterSource = currentFilter.subfilters[j]
                        modes = '({0}) [{1}]'.format(filterMode, filterSource)
                        block.modes = TextBox((-150, 11, -8, 12), modes, alignment='right', sizeStyle='mini')
                    block.title = TextBox((8, 8, -150, 22), filterName.upper())
                    start = height
                    boxHeight = top

                    for i, (arg, value) in enumerate(arguments.items()):
                        valueType = None

                        if hasSubfilters:
                            argumentName = currentFilter.joinSubfilterArgumentName(filterName, arg, j)
                            if argumentName in currentFilter.arguments:
                                value = currentFilter.arguments[argumentName]
                            else:
                                value = self.filters[filterName].arguments[argumentName]
                                currentFilter.setArgumentValue(argumentName, value)
                        else:
                            argumentName = arg

                        limits = currentFilter.getLimits(argumentName)
                        if limits is None: limits = (0, 100)

                        if isinstance(value, bool):
                            setattr(block, arg, CheckBox((8, top + (i*lineheight), -8, 22), arg, value=value, callback=self.setArgumentValue, sizeStyle='small'))
                            valueType = 'bool'
                        elif isinstance(value, (str, unicode)):
                            setattr(block, arg, EditText((8, top + (i*lineheight), -8, 22), value, callback=self.setArgumentValue, sizeStyle='small'))
                        elif isinstance(value, (int, float)):
                            parameter = VanillaSingleValueParameter(arg, value, limits=limits)
                            setattr(block, arg, ParameterSliderTextInput(parameter, (8, top + (i*lineheight), -8, 22), title=arg, callback=self.setArgumentValue))

                        control = getattr(block, arg)
                        control.name = argumentName
                        control.type = valueType

                        boxHeight += lineheight

                    boxHeight += 12
                    block.setPosSize((5, start, -5, boxHeight))
                    height += boxHeight + gap

            height += 40

            self.w.filtersPanel.filtersList.setPosSize((0, 0, -0, -height))
            self.w.filtersPanel.controls.setPosSize((0, -height, -0, -45))

    def stringInput(self, sender):
        text = sender.get()
        if self.currentFont is not None:
            cmap = self.currentFont.getCharacterMapping()
            self.glyphNames = splitText(text, cmap)
        else:
            self.glyphNames = []
        self.updatePreview()

    def filterEdit(self, sender):
        filterName = self.currentFilterName
        if self.filters.hasSubfilters(filterName):
            self.buildFilterGroupSheet(filterName)
        else:
            self.buildFilterSheet(filterName)
        self.filterSheet.open()

    # def buildGenerationSheet(self, sender):
    #     self.generationSheet = Sheet((0, 0, 400, 350), self.w)
    #     self.generationSheet.title = TextBox((15, 15, -15, 22), u'Generate selected glyphs to:')

    def buildFilterSheet(self, filterName='', makeNew=False):
        sheetFields = {
            'file': '',
            'module': '',
            'filterObjectName': '',
            'limits': {},
            'arguments': {},
        }
        if filterName != '':
            filterDict = self.filters[filterName].getFilterDict()
            for key in filterDict:
                if key == "arguments":
                    entry = OrderedDict(filterDict[key])
                else:
                    entry = filterDict[key]
                sheetFields[key] = entry

        self.filterSheet = Sheet((0, 0, 400, 350), self.w)
        self.filterSheet.new = makeNew
        self.filterSheet.index = self.filters[filterName].index if not makeNew else -1
        applyTitle = 'Add Filter' if filterName == '' else 'Update Filter'
        self.filterSheet.apply = SquareButton((-115, -37, 100, 22), applyTitle, callback=self.processFilter, sizeStyle='small')
        self.filterSheet.cancel = SquareButton((-205, -37, 80, 22), 'Cancel', callback=self.closeFilterSheet, sizeStyle='small')

        y = 20
        self.filterSheet.nameTitle = TextBox((15, y, 100, 22), 'Filter Name')
        self.filterSheet.name = EditText((125, y, -15, 22), filterName)
        y += 22

        tabs = ['module','file']
        selectedTab = 0 if len(sheetFields['module']) >= len(sheetFields['file']) else 1
        filterObjectName = sheetFields['filterObjectName']

        y += 20
        self.filterSheet.importPath = Tabs((15, y, -15, 75), tabs)
        self.filterSheet.importPath.set(selectedTab)
        modulePathTab = self.filterSheet.importPath[0]
        filePathTab = self.filterSheet.importPath[1]

        modulePathTab.pathInput = EditText((10, 10, -10, -10), sheetFields['module'])
        filePathTab.pathInput = EditText((10, 10, -110, -10), sheetFields['file'])
        filePathTab.fileInput = SquareButton((-100, 10, 90, -10), u'Add File…', sizeStyle='small', callback=self.getFile)
        y += 75

        y += 10
        self.filterSheet.filterObjectTitle = TextBox((15, y, 100, 22), 'Filter Object (pen, function)')
        self.filterSheet.filterObject = EditText((125, y, -15, 22), filterObjectName)
        y += 22

        y += 20
        columns = [
            {'title': 'argument', 'width': 160, 'editable':True},
            {'title': 'value', 'width': 71, 'editable':True},
            {'title': 'min', 'width': 49, 'editable':True},
            {'title': 'max', 'width': 49, 'editable':True}
        ]

        arguments = sheetFields['arguments']
        limits = sheetFields['limits']

        argumentItems = []

        for key, value in arguments.items():
            if isinstance(value, bool):
                value = str(value)
            elif isinstance(value, float):
                value = round(value, 2)
            argItem = {
                'argument': key,
                'value': value
                }
            if key in limits:
                minimum, maximum = sheetFields['limits'][key]
                argItem['min'] = minimum
                argItem['max'] = maximum

            argumentItems.append(argItem)

        buttonSize = 20
        gutter = 7
        self.filterSheet.arguments = List((15 + buttonSize + gutter, y, -15, -52), argumentItems, columnDescriptions=columns, allowsMultipleSelection=False, allowsEmptySelection=False)
        self.filterSheet.addArgument = SquareButton((15, -52-(buttonSize*2)-gutter, buttonSize, buttonSize), '+', sizeStyle='small', callback=self.addArgument)
        self.filterSheet.removeArgument = SquareButton((15, -52-buttonSize, buttonSize, buttonSize), '-', sizeStyle='small', callback=self.removeArgument)
        if len(argumentItems) == 0:
            self.filterSheet.removeArgument.enable(False)

        if filterName == '':
            self.currentFilterName = ''

    def buildFilterGroupSheet(self, filterName='', makeNew=False):

        subfilters = self.filters[filterName].subfilters if filterName in self.filters else []
        subfilterItems = [{'filterName': subfilterName, 'mode': subfilterMode if subfilterMode is not None else '', 'source': source if source is not None else ''} for subfilterName, subfilterMode, source in subfilters]

        self.filterSheet = Sheet((0, 0, 400, 350), self.w)
        self.filterSheet.new = makeNew
        self.filterSheet.index = self.filters[filterName].index if not makeNew else -1
        applyTitle = 'Add Operation' if filterName == '' else 'Update Operation'
        self.filterSheet.apply = SquareButton((-145, -37, 130, 22), applyTitle, callback=self.processFilterGroup, sizeStyle='small')
        self.filterSheet.cancel = SquareButton((-210, -37, 60, 22), 'Cancel', callback=self.closeFilterSheet, sizeStyle='small')

        y = 20
        self.filterSheet.nameTitle = TextBox((15, y, 100, 22), 'Filter Name')
        self.filterSheet.name = EditText((125, y, -15, 22), filterName)
        y += 22

        columns = [
            {'title': 'filterName', 'editable': True, 'width': 140},
            {'title': 'mode', 'editable': True, 'width': 89},
            {'title': 'source', 'editable': True, 'width': 100}
        ]

        buttonSize = 20
        gutter = 7

        y += 20
        self.filterSheet.subfilters = List((15 + buttonSize + gutter, y, -15, -52), subfilterItems, columnDescriptions=columns, allowsMultipleSelection=False, allowsEmptySelection=False)
        self.filterSheet.addSubfilter = SquareButton((15, -52-(buttonSize*2)-gutter, buttonSize, buttonSize), '+', sizeStyle='small', callback=self.addSubfilter)
        self.filterSheet.removeSubfilter = SquareButton((15, -52-buttonSize, buttonSize, buttonSize), '-', sizeStyle='small', callback=self.removeSubfilter)
        if len(subfilters) == 0:
            self.filterSheet.removeSubfilter.enable(False)
        y += 75
        self.filterSheet.moveSubfilterUp = SquareButton((15, y, buttonSize, buttonSize), u'⇡', sizeStyle='small', callback=self.moveSubfilterUp)
        self.filterSheet.moveSubfilterDown = SquareButton((15, y + buttonSize + gutter, buttonSize, buttonSize), u'⇣', sizeStyle='small', callback=self.moveSubfilterDown)

        if filterName == '':
            self.currentFilterName = ''

    def addArgument(self, sender):
        argumentsList = self.filterSheet.arguments.get()
        argumentsList.append({'argument': 'rename me', 'value': 50, 'min': 0, 'max': 100})
        if len(argumentsList) > 0:
            self.filterSheet.removeArgument.enable(True)
        self.filterSheet.arguments.set(argumentsList)

    def removeArgument(self, sender):
        argumentsList = self.filterSheet.arguments.get()
        if len(argumentsList) == 0:
            self.filterSheet.removeArgument.enable(False)
        selection = self.filterSheet.arguments.getSelection()[0]
        argumentsList.pop(selection)
        self.filterSheet.arguments.set(argumentsList)

    def addSubfilter(self, sender):
        subfiltersList = self.filterSheet.subfilters.get()
        subfilterDict = {'filterName': '{enter filter name}', 'mode': '', 'source': ''}
        subfiltersList.append(subfilterDict)
        if len(subfiltersList) > 0:
            self.filterSheet.removeSubfilter.enable(True)
        self.filterSheet.subfilters.set(subfiltersList)

    def removeSubfilter(self, sender):
        subfiltersList = self.filterSheet.subfilters.get()
        if len(subfiltersList) == 0:
            self.filterSheet.removeSubfilter.enable(False)
        selection = self.filterSheet.subfilters.getSelection()[0]
        subfiltersList.pop(selection)
        self.filterSheet.subfilters.set(subfiltersList)

    def moveSubfilterUp(self, sender):
        subfiltersList = self.filterSheet.subfilters.get()
        nItems = len(subfiltersList)
        if nItems > 1:
            selection = self.filterSheet.subfilters.getSelection()[0]
            if selection > 0:
                itemToMove = subfiltersList.pop(selection)
                subfiltersList.insert(selection-1, itemToMove)
                self.filterSheet.subfilters.set(subfiltersList)

    def moveSubfilterDown(self, sender):
        subfiltersList = self.filterSheet.subfilters.get()
        nItems = len(subfiltersList)
        if nItems > 1:
            selection = self.filterSheet.subfilters.getSelection()[0]
            if selection < nItems-1:
                itemToMove = subfiltersList.pop(selection)
                subfiltersList.insert(selection+1, itemToMove)
                self.filterSheet.subfilters.set(subfiltersList)

    def getFile(self, sender):
        path = getFile(fileTypes=['py'], allowsMultipleSelection=False, resultCallback=self.loadFilePath, parentWindow=self.filterSheet)

    def loadFilePath(self, paths):
        path = paths[0]
        self.filterSheet.importPath[1].pathInput.set(path)

    def closeFilterSheet(self, sender):
        self.filterSheet.close()
        delattr(self, 'filterSheet')

    def processFilter(self, sender):
        argumentsList = self.filterSheet.arguments.get()
        filterName = self.filterSheet.name.get()
        index = self.filterSheet.index
        filterDict = {}

        if len(filterName) > 0:
            sourceIndex = self.filterSheet.importPath.get()
            mode = ['module','file'][sourceIndex]
            importString = self.filterSheet.importPath[sourceIndex].pathInput.get()

            if len(importString) > 0:
                filterDict[mode] = importString

                filterObjectName = self.filterSheet.filterObject.get()
                filterDict['filterObjectName'] = filterObjectName

                if len(filterObjectName) > 0:

                    for argItem in argumentsList:
                        if 'argument' in argItem:
                            key = argItem['argument']
                            if 'value' in argItem:
                                value = self.parseValue(argItem['value'])
                                if 'arguments' not in filterDict:
                                    filterDict['arguments'] = OrderedDict()
                                filterDict['arguments'][key] = value
                                if 'min' in argItem and 'max' in argItem and isinstance(value, (float, int)):
                                    try:
                                        mini, maxi = float(argItem['min']), float(argItem['max'])
                                        if 'limits' not in filterDict:
                                            filterDict['limits'] = {}
                                        filterDict['limits'][key] = (mini, maxi)
                                    except:
                                        pass

                    if filterName in self.filters:
                        self.filters.setFilter(filterName, filterDict)

                    elif self.filterSheet.new == False:
                        index = self.filterSheet.index
                        self.filters.changeFilterNameByIndex(index, filterName)
                        self.filters.setFilter(filterName, filterDict)

                    elif self.filterSheet.new == True:
                        self.filters.setFilter(filterName, filterDict)

                    self.closeFilterSheet(sender)
                    self.updateFiltersList(index)
                    self.updateControls()
                    self.resetRepresentations()
                    self.updatePreview()

    def processFilterGroup(self, sender):
        filterName = self.filterSheet.name.get()
        subfiltersList = self.filterSheet.subfilters.get()
        isNew = self.filterSheet.new
        index = self.filterSheet.index
        subfilters = []

        for item in subfiltersList:
            subfilterName = item['filterName'] if 'filterName' in item else ''
            mode = item['mode'] if 'mode' in item else None
            source = item['source'] if 'source' in item else None
            try:
                source = int(source)
            except:
                pass
            subfilters.append((subfilterName, mode, source))

        if filterName in self.filters:
            self.filters.updateFilterChain(filterName, subfilters)
        elif not isNew:
            self.filters.changeFilterNameByIndex(index, filterName)
            self.filters.updateFilterChain(filterName, subfilters)
        elif isNew:
            self.filters.setFilterChain(filterName, subfilters)

        self.closeFilterSheet(sender)
        self.updateFiltersList(index)
        self.updateControls()
        self.resetRepresentations()
        self.updatePreview()

    def addFilter(self, sender):
        self.buildFilterSheet(makeNew=True)
        self.filterSheet.open()

    def addFilterChain(self, sender):
        self.buildFilterGroupSheet(makeNew=True)
        self.filterSheet.open()

    def addExternalFilter(self, filterName, filterDict):
        self.filters.addFilter(filterName, filterDict)
        self.updateFiltersList()

    def removeFilter(self, sender):
        filterName = self.currentFilterName
        self.filters.removeFilter(filterName)
        self.updateFiltersList()

    def filterSelectionChanged(self, sender):
        selectedFilterName = self.getSelectedFilterName()
        self.cachedFont = RFont(showUI=False)
        self.currentFilterName = selectedFilterName
        self.updateControls()
        self.updatePreview()

    def getSelectedFilterName(self):
        filtersList = self.w.filtersPanel.filtersList
        filterNamesList = filtersList.get()
        if len(filterNamesList):
            selectedIndices = filtersList.getSelection()
            if len(selectedIndices):
                selection = filtersList.getSelection()[0]
                return filterNamesList[selection]
        return None

    def switchFillStroke(self, sender):
        self.fill = not self.fill
        displayStates = self.w.preview.getDisplayStates()
        if self.fill == True:
            sender.setTitle('Stroke')
            displayStates['Fill'] = True
            displayStates['Stroke'] = False
        elif self.fill == False:
            sender.setTitle('Fill')
            displayStates['Fill'] = False
            displayStates['Stroke'] = True
        self.w.preview.setDisplayStates(displayStates)

    def parseValue(self, value):
        if isinstance(value, bool):
            value = bool(value)
        elif isinstance(value, (str, unicode)) and value.lower() == 'true':
            value = True
        elif isinstance(value, (str, unicode)) and value.lower() == 'false':
            value = False
        elif value is not '' or value is not None:
            try:
                value = float(value)
            except:
                pass
        return value

    def fontChanged(self, notification):
        if 'font' in notification:
            self.releaseObservedGlyphs()
            self.stringInput(self.w.textInput)
            self.currentFont = notification['font']
            self.cachedFont = RFont(showUI=False)
            self.updatePreview()

    def releaseObservedGlyphs(self):
        for glyph in self.observedGlyphs:
            glyph.removeObserver(self, 'Glyph.Changed')
        self.observedGlyphs = []

    def glyphChanged(self, notification):
        glyph = notification.object
        glyph.destroyAllRepresentations()
        self.updatePreview()

    def launchWindow(self):
        postEvent("PenBallWizardSubscribeFilter", subscribeFilter=self.addExternalFilter)

    def end(self, notification):
        self.filters.saveFiltersToJSON('/'.join([LOCALPATH, JSONFILE]))
        self.releaseObservedGlyphs()
        for callback, event in self.observers:
            removeObserver(self, event)
Beispiel #12
0
class Unicron(object):
    def __init__(self):
        self.locations = [
            'User Agents', 'Global Agents', 'Global Daemons', 'System Agents',
            'System Daemons'
        ]
        self.listItems = []
        self.selected = {}

        # Preferences
        self.homedir = os.path.expanduser('~')
        self.prefsFolder = self.homedir + "/Library/Preferences/"
        self.prefsFile = "de.nelsonfritsch.unicron.plist"

        if os.path.isfile(self.prefsFolder + self.prefsFile):
            self.prefs = self._loadPrefs(self)
        else:
            self.prefs = dict(showSystemWarning=True, windowStyle='System')
            self._savePrefs(self)

        # Preferences Window
        self.prefsWindow = Window((300, 105), 'Preferences')

        self.styles = ['System', 'Light', 'Dark']
        self.prefsWindow.styleTxt = TextBox((10, 10, -10, 20), "Window Style:")
        self.prefsWindow.style = PopUpButton((30, 35, -10, 20),
                                             self.styles,
                                             callback=self.prefsSetStyle)

        self.prefsWindow.restore = Button((10, 75, -10, 20),
                                          'Restore Warnings',
                                          callback=self.prefsRestoreWarnings)

        # Main Window
        minsize = 285
        self.w = Window((minsize, 400),
                        'Unicron',
                        closable=True,
                        fullSizeContentView=True,
                        titleVisible=False,
                        minSize=(minsize, minsize),
                        maxSize=(600, 1200),
                        autosaveName="UnicronMainWindow")

        self.pathList = NSPopUpButton.alloc().initWithFrame_(
            ((0, 0), (160, 20)))
        self.pathList.addItemsWithTitles_(self.locations)

        refreshIcon = NSImage.alloc().initWithSize_((32, 32))
        sourceImage = NSImage.imageNamed_(NSImageNameRefreshTemplate)

        w, h = sourceImage.size()

        if w > h:
            diffx = 0
            diffy = w - h
        else:
            diffx = h - w
            diffy = 0

        maxSize = max([w, h])
        refreshIcon.lockFocus()
        sourceImage.drawInRect_fromRect_operation_fraction_(
            NSMakeRect(diffx, diffy + 4, 22, 22),
            NSMakeRect(0, 0, maxSize, maxSize), NSCompositeSourceOver, 1)
        refreshIcon.unlockFocus()
        refreshIcon.setTemplate_(True)

        toolbarItems = [
            dict(itemIdentifier="Daemons",
                 label="Daemons",
                 toolTip="Daemon Group",
                 view=self.pathList,
                 callback=self.populateList),
            dict(itemIdentifier="image",
                 label="Image",
                 imageObject=refreshIcon,
                 callback=self.populateList),
        ]
        self.w.addToolbar("Unicron Toolbar",
                          toolbarItems=toolbarItems,
                          displayMode="icon")

        self.w.blend = Group((0, 0, 0, 0), blendingMode='behindWindow')

        self.listColumnDescriptions = [{
            'title': '',
            'key': 'image',
            'width': 25,
            'typingSensitive': True,
            'allowsSorting': True,
            'cell': ImageListCell()
        }, {
            'title': 'Name',
            'key': 'name',
            'typingSensitive': True,
            'allowsSorting': True,
        }]
        self.rowHeight = 20
        self.w.list = List((0, 37, -0, 0),
                           items=self.listItems,
                           columnDescriptions=self.listColumnDescriptions,
                           showColumnTitles=True,
                           allowsEmptySelection=True,
                           allowsMultipleSelection=False,
                           autohidesScrollers=True,
                           drawFocusRing=False,
                           rowHeight=self.rowHeight,
                           selectionCallback=self._selectionCallback,
                           menuCallback=self._menuCallback)

        self.w.list._nsObject.setBorderType_(NSNoBorder)

        self.w.statusbar = Group((0, -26, 0, 0), blendingMode='behindWindow')
        self.w.statusbar.border = HorizontalLine((0, 0, 0, 1))

        self.w.counter = TextBox((16, -20, -16, 15),
                                 '',
                                 alignment='center',
                                 sizeStyle='small')
        self.populateList(self)
        self.w.rowIndicator = Group((0, 0, 0, 10))

        self.prefsSetStyle(self)

        self.w.open()

    def prefsSetStyle(self, sender):
        style = self.prefsWindow.style.getItem()
        self._changePref(self, 'windowStyle', style)

        if style == 'System':
            style = NSUserDefaults.standardUserDefaults().stringForKey_(
                'AppleInterfaceStyle')
        if style == 'Dark':
            winAppearance = 'NSAppearanceNameVibrantDark'
        else:
            winAppearance = 'NSAppearanceNameVibrantLight'
        appearance = NSAppearance.appearanceNamed_(winAppearance)
        self.w._window.setAppearance_(appearance)
        self.prefsWindow._window.setAppearance_(appearance)

    def prefsRestoreWarnings(self, sender):
        self._changePref(self, 'showSystemWarning', True)

    def populateList(self, sender):
        self.selected.clear()
        self.w.list._removeSelection()
        item = self.pathList.titleOfSelectedItem()

        for i in range(len(self.w.list)):
            del self.w.list[0]

        thisItem = {}
        image = None
        id = os.getuid()
        systemWarning = "You should not edit or remove existing system's daemons. These jobs are required for a working macOS system."

        if item != 'Active Daemons':
            if item == 'User Agents':
                homedir = os.path.expanduser('~')
                path = homedir + '/Library/LaunchAgents'
                # If the folder doesn't exist in the user folder, create it
                try:
                    os.listdir(path)
                except:
                    os.mkdir(path)
            elif item == 'Global Agents':
                path = '/Library/LaunchAgents'
            elif item == 'Global Daemons':
                path = '/Library/LaunchDaemons'
            elif item == 'System Agents':
                path = '/System/Library/LaunchAgents'
                self._warning(self, systemWarning, "showSystemWarning")
            elif item == 'System Daemons':
                path = '/System/Library/LaunchDaemons'
                self._warning(self, systemWarning, "showSystemWarning")

            items = []
            files = os.listdir(path)
            count = 0

            for file in files:
                if file.endswith('.plist'):
                    file = file.replace('.plist', '')
                    try:
                        pid = launchd.LaunchdJob(file).pid
                    except:
                        pid = False
                    if launchd.LaunchdJob(file).exists() and pid != None:
                        image = NSImage.imageNamed_(NSImageNameStatusAvailable)
                    elif launchd.LaunchdJob(file).exists() and pid == None:
                        image = NSImage.imageNamed_(
                            NSImageNameStatusPartiallyAvailable)
                    else:
                        image = NSImage.imageNamed_(NSImageNameStatusNone)
                    state = True
                    thisItem['image'] = image
                    thisItem['name'] = file
                    self.w.list.append(thisItem)
                    count += 1
            self.w.counter.set(str(count) + ' Jobs')

    def _showInFinder(self, sender):
        file = self.selected['file']
        subprocess.call(['open', '-R', '%s' % file],
                        cwd='/',
                        shell=False,
                        universal_newlines=False)

    def _loadUnloadDaemon(self, sender, command):
        self.w.list.scrollToSelection()
        name = self.selected['name']
        path = self.selected['file']

        if bool(launchd.LaunchdJob(name).exists()):
            try:
                subprocess.call(
                    ['launchctl', 'unload', '%s' % path],
                    cwd='/',
                    shell=False,
                    universal_newlines=False)
            except:
                return
        else:
            try:
                subprocess.call(
                    ['launchctl', 'load', '%s' % path],
                    cwd='/',
                    shell=False,
                    universal_newlines=False)
            except:
                return

        self.populateList(self)

    def _removeDaemon(self, sender):
        self._loadUnloadDaemon(self, 'unload')
        self._loadUnloadDaemon(self, 'remove')

    # def addGroup(self, sender, key, value):

    def _selectionCallback(self, sender):
        try:
            if not self.w.list.getSelection():
                # Application did not finish loading yet
                pass
            else:
                # Get job name
                self.selected.clear()
                job = sender.get()[self.w.list.getSelection()[0]]
                self.selected['name'] = job['name']
                self.valueGroups = []
                # Get job path and file location
                item = self.pathList.titleOfSelectedItem()

                if 'User' in item:
                    import getpass
                    username = getpass.getuser()
                    user = username
                    path = '/Users/%s/Library/Launch' % username
                elif 'Global' in item:
                    user = '******'
                    path = '/Library/Launch'
                elif 'System' in item:
                    user = '******'
                    path = '/System/Library/Launch'
                if 'Agents' in item:
                    path += 'Agents/'
                else:
                    path += 'Daemons/'

                self.selected['path'] = path
                self.selected['file'] = str(self.selected['path'].replace(
                    ' ', '\ ')) + job['name'].replace(' ', '\ ') + '.plist'
                f = open(self.selected['file'], "r")
                self.selected['raw'] = str(f.read())
                self.selected['short'] = (
                    self.selected['name'][:32] + '…') if len(
                        self.selected['name']) > 32 else self.selected['name']
                # Get status
                if job['image'] == NSImage.imageNamed_(NSImageNameStatusNone):
                    status = None
                else:
                    status = 'Available'
                self.selected['status'] = status

                index = sender.getSelection()[0]
                relativeRect = sender.getNSTableView().rectOfRow_(index)

                self.pop = Popover((300, 100))

                self.pop.tabs = Tabs((20, 40, -20, -20),
                                     ["Editor", "Raw View"])
                self.pop.tabs._nsObject.setTabViewType_(NSNoTabsNoBorder)

                self.pop.tabBtn = SegmentedButton(
                    (10, 10, -10, 20),
                    [dict(title="Editor"),
                     dict(title="Raw View")],
                    callback=self._segmentPressed,
                    selectionStyle='one')
                self.pop.tabBtn.set(0)

                self.edit = self.pop.tabs[0]

                self.rawEdit = self.pop.tabs[1]
                self.rawEdit.editor = TextEditor((0, 0, -0, -45),
                                                 text=self.selected['raw'])

                self.selected['dict'] = launchd.plist.read(
                    self.selected['name'])

                # TODO: Add stackview to scrollview as group
                # Waiting for merge into master: https://github.com/robotools/vanilla/issues/132
                self.edit.stack = VerticalStackGroup((0, 0, -0, -45))

                for idx, (key, value) in enumerate(
                        sorted(self.selected['dict'].items())):
                    group = ValueGroup((0, 0, -0, -0),
                                       sender=self,
                                       key=key,
                                       value=value,
                                       idx=idx)
                    self.valueGroups.append(group)
                    self.edit.stack.addView(
                        self.valueGroups[idx], 300,
                        self.valueGroups[idx].getPosSize()[3])

                self.pop.save = Button((20, -50, -20, 40),
                                       "Save",
                                       callback=self._savePlist)
                self.pop.save.enable(False)
                self.pop.open(parentView=sender.getNSTableView(),
                              preferredEdge='right',
                              relativeRect=relativeRect)
        except:
            pass

    # TODO
    def _savePlist(self, sender):
        return

    def _segmentPressed(self, sender):
        self.pop.tabs.set(self.pop.tabBtn.get())

    def _menuCallback(self, sender):
        items = []

        items.append(dict(title=self.selected['short'], enabled=False))
        items.append("----")
        if self.selected['status'] == None:
            load, able = 'Load', 'Enable'
        else:
            load, able = 'Unload', 'Disable'

        loadCallback = partial(self._loadUnloadDaemon, command=load)
        ableCallback = partial(self._loadUnloadDaemon, command=able)
        items.append(dict(title=load, callback=loadCallback))
        items.append(dict(title=able, callback=ableCallback))
        items.append(dict(title="Show in Finder", callback=self._showInFinder))
        items.append(dict(title="Refresh list", callback=self.populateList))

        return items

    def _loadPrefs(self, sender):
        with open(self.prefsFolder + self.prefsFile, 'rb') as fp:
            self.prefs = plistlib.load(fp)
        return self.prefs

    def _savePrefs(self, sender):
        with open(self.prefsFolder + self.prefsFile, 'wb') as fp:
            plistlib.dump(self.prefs, fp)

    def _changePref(self, sender, key, value):
        self.prefs[key] = value
        self._savePrefs(self)

    def _warning(self, sender, warning, prefKey):
        if self.prefs.get(prefKey):
            self.warning = Sheet((400, 140), self.w)
            self.warning.img = ImageView((10, 10, 60, 60))
            self.warning.img.setImage(imageNamed=NSImageNameCaution)
            self.warning.txt = TextBox((70, 10, -10, -40),
                                       "Warning\n" + warning)

            callback = partial(self._changePref,
                               key=prefKey,
                               value=not self.prefs.get(prefKey))
            self.warning.check = CheckBox((70, 80, -10, 20),
                                          "Always show this warning",
                                          value=self.prefs.get(prefKey),
                                          callback=callback)

            self.warning.closeButton = Button((10, 110, -10, 20),
                                              "I understand",
                                              callback=self._closeWarning)
            self.warning.setDefaultButton(self.warning.closeButton)
            self.warning.center()
            self.w.list.enable(False)
            self.warning.open()

    def _closeWarning(self, sender):
        self.warning.close()
        self.w.list.enable(True)
        del self.warning
Beispiel #13
0
class CopyGlyphs:

    def __init__(self):
        self.doMarkGlyphs = 0
        self.doOverwrite = 1
        self.sourceFontList = AllFonts()
        self.destinationFontList = AllFonts()
        self.source_font = self.sourceFontList[0]
        self.destination_fonts = None
        self.glyphs = None
        self.mark = NSColor.redColor()
        
        ## create a window
        self.w = Window((700, 500), "Copy Glyphs", minSize=(700, 500))
        self.w.sourceTitle = TextBox((15, 20, 200, 20), "Source Font:")
        self.w.sourceFont = PopUpButton((15, 42, -410, 20), [f.info.familyName + ' ' + f.info.styleName for f in self.sourceFontList], callback=self.sourceCallback)
        self.w.glyphs = GlyphCollectionView((16, 70, -410, -65), initialMode="list", enableDelete=False, allowDrag=False, selectionCallback=self.glyphCallback)
        self._sortGlyphs(self.source_font)
        self.w.desTitle = TextBox((-400, 20, 200, 20), "Destination Fonts:")
        self.w.destinationFonts = FontList((-400, 42, -15, -115), self.destinationFontList, selectionCallback=self.desCallback)
        self.w.overwrite = CheckBox((-395, -105, 130, 22), "Overwrite glyphs", callback=self.overwriteCallback, value=self.doOverwrite)
        self.w.markGlyphs = CheckBox((-395, -84, 100, 22), "Mark Glyphs", callback=self.markCallback, value=self.doMarkGlyphs)
        self.w.copyButton = Button((-115, -40, 100, 20), 'Copy Glyphs', callback=self.copyCallback)
        self.w.line = HorizontalLine((10, -50, -10, 1))
        self._updateDest()
        ## open the window
        self.w.open()
    
    def _updateDest(self):
        des = list(self.sourceFontList)
        des.remove(self.source_font)
        self.w.destinationFonts.set(des)
    
    def _sortGlyphs(self, font):
        gs = font.keys()
        gs.sort()
        self.w.glyphs.set([font[x] for x in gs])

    def _altName(self, font, glyph):
        name = glyph + '.copy'
        count = 1
        while name in font.keys():
            name = name + str(count)
            count += 1
        return name
        
    def copyGlyphs(self, glyphs, source_font, destination_fonts, overwrite, mark):
        for glyph in glyphs:
            for font in destination_fonts:
                if glyph in font.keys() and overwrite == 0:
                    n = self._altName(font, glyph)
                else:
                    n = glyph
                
                font.insertGlyph(source_font[glyph], name=n)
                
                if mark == 1:
                    font[n].mark = NSColorToRgba(self.mark)

    def overwriteCallback(self, sender):
        self.doOverwrite = sender.get()

    def markCallback(self, sender):
        self.doMarkGlyphs = sender.get()
        if self.doMarkGlyphs == 1:
            self.w.colorWell = ColorWell((-265, -85, 100, 23), callback=self.colorCallback, color=self.mark)
        else:
            del self.w.colorWell
        
    def colorCallback(self, sender):
        self.mark = sender.get()
    
    def sourceCallback(self, sender):
        self.source_font = self.sourceFontList[sender.get()]
        self._sortGlyphs(self.source_font)
        self._updateDest()
 
    def glyphCallback(self, sender):
        self.glyphs = [self.w.glyphs[x].name for x in sender.getSelection()]
        
    def desCallback(self, sender):
        self.destination_fonts = [sender.get()[x] for x in sender.getSelection()]
        
    def copyCallback(self, sender):
        self.sheet = Sheet((300, 50), self.w)
        self.sheet.bar = ProgressBar((10, 20, -10, 10), isIndeterminate=True, sizeStyle="small")
        self.sheet.open()
        self.sheet.bar.start()
        self.copyGlyphs(self.glyphs, self.source_font, self.destination_fonts, self.doOverwrite, self.doMarkGlyphs)
        self.sheet.bar.stop()
        self.sheet.close()
        del self.sheet
        self.w.close()
Beispiel #14
0
class CopyGlyphs:

    def __init__(self):
        self.doMarkGlyphs = 0
        self.doOverwrite = 1
        self.sourceFontList = AllFonts()
        self.destinationFontList = AllFonts()
        self.source_font = self.sourceFontList[0]
        self.destination_fonts = None
        self.glyphs = None
        self.mark = NSColor.redColor()

        sl = []
        for f in self.sourceFontList:
            if f.info.familyName != None:
                fn = f.info.familyName
            else:
                fn = "None"
            if f.info.styleName != None:
                fs = f.info.styleName
            else:
                fs = "None"
            sl.append(fn+" "+fs)

        ## create a window
        self.w = Window((700, 500), "Copy Glyphs", minSize=(700, 500))
        self.w.sourceTitle = TextBox((15, 20, 200, 20), "Source Font:")
        self.w.sourceFont = PopUpButton((15, 42, -410, 20), sl, callback=self.sourceCallback)
        self.w.glyphs = GlyphCollectionView((16, 70, -410, -65), initialMode="list", enableDelete=False, allowDrag=False, selectionCallback=self.glyphCallback)
        self._sortGlyphs(self.source_font)
        self.w.desTitle = TextBox((-400, 20, 200, 20), "Destination Fonts:")
        self.w.destinationFonts = FontList((-400, 42, -15, -115), self.destinationFontList, selectionCallback=self.desCallback)
        self.w.overwrite = CheckBox((-395, -105, 130, 22), "Overwrite glyphs", callback=self.overwriteCallback, value=self.doOverwrite)
        self.w.markGlyphs = CheckBox((-395, -84, 100, 22), "Mark Glyphs", callback=self.markCallback, value=self.doMarkGlyphs)
        self.w.copyButton = Button((-115, -40, 100, 20), 'Copy Glyphs', callback=self.copyCallback)
        self.w.line = HorizontalLine((10, -50, -10, 1))
        self._checkSelection()
        self._updateDest()
        ## open the window
        self.w.open()

    def _updateDest(self):
        des = list(self.sourceFontList)
        des.remove(self.source_font)
        self.w.destinationFonts.set(des)

    def _sortGlyphs(self, font):
        gs = font.keys()        
        self.w.glyphs.set([font[x] for x in sorted(gs)])

    def _altName(self, font, glyph):
        name = glyph + '.copy'
        count = 1
        while name in font.keys():
            name = name + str(count)
            count += 1
        return name


    def _checkSelection(self):
        if self.glyphs == None or len(self.glyphs) == 0:
            if len(self.source_font.selection) != 0:
                self.glyphs = self.source_font.selection
                select = []
                for i, g in enumerate(self.w.glyphs):
                    if g.name in self.glyphs:
                        select.append(i)
                print(select)
                self.w.glyphs.setSelection(select)
        print(self.glyphs)


    def copyGlyphs(self, glyphs, source_font, destination_fonts, overwrite, mark):
        for glyph in glyphs:
            for font in destination_fonts:
                if glyph in font.keys() and overwrite == 0:
                    n = self._altName(font, glyph)
                else:
                    n = glyph

                font.insertGlyph(source_font[glyph], name=n)

                if mark == 1:
                    font[n].mark = NSColorToRgba(self.mark)

    def overwriteCallback(self, sender):
        self.doOverwrite = sender.get()

    def markCallback(self, sender):
        self.doMarkGlyphs = sender.get()
        if self.doMarkGlyphs == 1:
            self.w.colorWell = ColorWell((-265, -85, 100, 23), callback=self.colorCallback, color=self.mark)
        else:
            del self.w.colorWell

    def colorCallback(self, sender):
        self.mark = sender.get()

    def sourceCallback(self, sender):
        self.source_font = self.sourceFontList[sender.get()]
        self._sortGlyphs(self.source_font)
        self._checkSelection()
        self._updateDest()

    def glyphCallback(self, sender):
        self.glyphs = [self.w.glyphs[x].name for x in sender.getSelection()]

    def desCallback(self, sender):
        self.destination_fonts = [sender.get()[x] for x in sender.getSelection()]

    def copyCallback(self, sender):
        self.sheet = Sheet((300, 50), self.w)
        self.sheet.bar = ProgressBar((10, 20, -10, 10), isIndeterminate=True, sizeStyle="small")
        self.sheet.open()
        self.sheet.bar.start()
        self.copyGlyphs(self.glyphs, self.source_font, self.destination_fonts, self.doOverwrite, self.doMarkGlyphs)
        self.sheet.bar.stop()
        self.sheet.close()
        del self.sheet
        self.w.close()
Beispiel #15
0
    def __init__(self, mainWindow, presetsList):
        self.presets = presetsList
        self.presetNames = [preset.name for preset in self.presets]
        self.selectedPreset = None
        self.selectedGroupIndex = None

        gutter = 10
        left = 10
        row = 10
        colWidth = 275
        listHeight = 115
        col2Left = left + colWidth + gutter
        btnWidth = 85
        btnHeight = 22
        boxWidth = btnWidth * 2 + 15
        windowWidth = col2Left + boxWidth + 10

        self.w = Sheet((windowWidth, 550), mainWindow)

        self.w.presetsText = TextBox((left, row, colWidth, 20),
                                     "Presets:",
                                     sizeStyle="small")

        row += 17
        self.w.presetsList = List((left, row, colWidth, listHeight),
                                  items=self.presetNames,
                                  allowsSorting=False,
                                  allowsMultipleSelection=False,
                                  allowsEmptySelection=False,
                                  selectionCallback=self.updatePresetInfo)

        self.w.presetCtrls = Box((col2Left, row, boxWidth, listHeight))

        boxLeft = 0
        boxRow = 0
        self.w.presetCtrls.edit = TextBox((boxLeft, boxRow, btnWidth, 20),
                                          "Edit:",
                                          sizeStyle="small")
        boxRow += 15
        self.w.presetCtrls.newBtn = Button((boxLeft, boxRow, btnWidth, btnHeight),
                                           "New",
                                           sizeStyle="small",
                                           callback=self.testerCB)

        boxRow += 22
        self.w.presetCtrls.dupeBtn = Button((boxLeft, boxRow, btnWidth, btnHeight),
                                            "Duplicate",
                                            sizeStyle="small",
                                            callback=self.testerCB)

        boxRow += 22
        self.w.presetCtrls.renameBtn = Button((boxLeft, boxRow, btnWidth, btnHeight),
                                              "Rename",
                                              sizeStyle="small",
                                              callback=self.testerCB)

        boxRow += 22
        self.w.presetCtrls.delBtn = Button((boxLeft, boxRow, btnWidth, btnHeight),
                                           "Delete",
                                           sizeStyle="small",
                                           callback=self.testerCB)

        boxRow = 0
        boxLeft += btnWidth + 7
        self.w.presetCtrls.importText = TextBox((boxLeft, boxRow, btnWidth, 20),
                                                "Import:",
                                                sizeStyle="small")

        boxRow += 15
        self.w.presetCtrls.importJSON = Button((boxLeft, boxRow, btnWidth, btnHeight),
                                               "JSON",
                                               sizeStyle="small",
                                               callback=self.testerCB)
        boxRow += 22
        self.w.presetCtrls.importGroups = Button((boxLeft, boxRow, btnWidth, btnHeight),
                                                 "Proof groups",
                                                 sizeStyle="small",
                                                 callback=self.testerCB)

        row += listHeight + 12
        self.w.proofGroupsText = TextBox((left, row, colWidth, 20),
                                         "Proof groups:",
                                         sizeStyle="small")

        row += 17
        listHeight = 150
        self.w.proofGroupNames = List((left, row, colWidth, listHeight),
                                      items=[],
                                      allowsSorting=False,
                                      allowsMultipleSelection=False,
                                      selectionCallback=self.updateGroupContents)

        self.w.groupCtrls = Box((col2Left, row, boxWidth, listHeight))

        boxLeft = 0
        boxRow = 0
        self.w.groupCtrls.newBtn = Button((boxLeft, boxRow, btnWidth, btnHeight),
                                          "New",
                                          sizeStyle="small",
                                          callback=self.testerCB)

        boxRow += 22
        self.w.groupCtrls.dupeBtn = Button((boxLeft, boxRow, btnWidth, btnHeight),
                                           "Duplicate",
                                           sizeStyle="small",
                                           callback=self.testerCB)

        boxRow += 22
        self.w.groupCtrls.rename = Button((boxLeft, boxRow, btnWidth, btnHeight),
                                          "Rename",
                                          sizeStyle="small",
                                          callback=self.testerCB)

        boxRow += 22
        self.w.groupCtrls.delBtn = Button((boxLeft, boxRow, btnWidth, btnHeight),
                                          "Delete",
                                          sizeStyle="small",
                                          callback=self.testerCB)

        boxRow = 22
        boxLeft += btnWidth + 7 + (btnWidth / 2 - 15)
        self.w.groupCtrls.upBtn = Button((boxLeft, boxRow, 30, btnHeight),
                                         "↑",
                                         sizeStyle="small",
                                         callback=self.testerCB)
        boxRow += 22
        self.w.groupCtrls.dnBtn = Button((boxLeft, boxRow, 30, btnHeight),
                                         "↓",
                                         sizeStyle="small",
                                         callback=self.testerCB)



        row += listHeight + 12
        self.w.groupContentsText = TextBox((left, row, colWidth, 20),
                                           "Group contents:",
                                           sizeStyle="small")

        row += 17
        self.w.groupContents = TextEditor((left, row, -10, -36),
                                          text="",
                                          readOnly=True,
                                          callback=self.editGroupContents)
        self.w.groupContents.getNSTextView().setFont_(monoFont)


        # self.w.renameText = TextBox((left, row, colWidth, 20),
        #                             "Rename preset:",
        #                             sizeStyle="small")

        # self.w.renameEdit = EditText((left, row, colWidth, btnHeight))
        row += 17
        self.w.okButton = Button((windowWidth/2 - btnWidth/2, -31, btnWidth, btnHeight),
                                 "OK",
                                 callback=self.closeCB)

        self.w.setDefaultButton(self.w.okButton)

        self.updatePresetInfo()
Beispiel #16
0
class PresetsEditor:
    def __init__(self, mainWindow, presetsList):
        self.presets = presetsList
        self.presetNames = [preset.name for preset in self.presets]
        self.selectedPreset = None
        self.selectedGroupIndex = None

        gutter = 10
        left = 10
        row = 10
        colWidth = 275
        listHeight = 115
        col2Left = left + colWidth + gutter
        btnWidth = 85
        btnHeight = 22
        boxWidth = btnWidth * 2 + 15
        windowWidth = col2Left + boxWidth + 10

        self.w = Sheet((windowWidth, 550), mainWindow)

        self.w.presetsText = TextBox((left, row, colWidth, 20),
                                     "Presets:",
                                     sizeStyle="small")

        row += 17
        self.w.presetsList = List((left, row, colWidth, listHeight),
                                  items=self.presetNames,
                                  allowsSorting=False,
                                  allowsMultipleSelection=False,
                                  allowsEmptySelection=False,
                                  selectionCallback=self.updatePresetInfo)

        self.w.presetCtrls = Box((col2Left, row, boxWidth, listHeight))

        boxLeft = 0
        boxRow = 0
        self.w.presetCtrls.edit = TextBox((boxLeft, boxRow, btnWidth, 20),
                                          "Edit:",
                                          sizeStyle="small")
        boxRow += 15
        self.w.presetCtrls.newBtn = Button((boxLeft, boxRow, btnWidth, btnHeight),
                                           "New",
                                           sizeStyle="small",
                                           callback=self.testerCB)

        boxRow += 22
        self.w.presetCtrls.dupeBtn = Button((boxLeft, boxRow, btnWidth, btnHeight),
                                            "Duplicate",
                                            sizeStyle="small",
                                            callback=self.testerCB)

        boxRow += 22
        self.w.presetCtrls.renameBtn = Button((boxLeft, boxRow, btnWidth, btnHeight),
                                              "Rename",
                                              sizeStyle="small",
                                              callback=self.testerCB)

        boxRow += 22
        self.w.presetCtrls.delBtn = Button((boxLeft, boxRow, btnWidth, btnHeight),
                                           "Delete",
                                           sizeStyle="small",
                                           callback=self.testerCB)

        boxRow = 0
        boxLeft += btnWidth + 7
        self.w.presetCtrls.importText = TextBox((boxLeft, boxRow, btnWidth, 20),
                                                "Import:",
                                                sizeStyle="small")

        boxRow += 15
        self.w.presetCtrls.importJSON = Button((boxLeft, boxRow, btnWidth, btnHeight),
                                               "JSON",
                                               sizeStyle="small",
                                               callback=self.testerCB)
        boxRow += 22
        self.w.presetCtrls.importGroups = Button((boxLeft, boxRow, btnWidth, btnHeight),
                                                 "Proof groups",
                                                 sizeStyle="small",
                                                 callback=self.testerCB)

        row += listHeight + 12
        self.w.proofGroupsText = TextBox((left, row, colWidth, 20),
                                         "Proof groups:",
                                         sizeStyle="small")

        row += 17
        listHeight = 150
        self.w.proofGroupNames = List((left, row, colWidth, listHeight),
                                      items=[],
                                      allowsSorting=False,
                                      allowsMultipleSelection=False,
                                      selectionCallback=self.updateGroupContents)

        self.w.groupCtrls = Box((col2Left, row, boxWidth, listHeight))

        boxLeft = 0
        boxRow = 0
        self.w.groupCtrls.newBtn = Button((boxLeft, boxRow, btnWidth, btnHeight),
                                          "New",
                                          sizeStyle="small",
                                          callback=self.testerCB)

        boxRow += 22
        self.w.groupCtrls.dupeBtn = Button((boxLeft, boxRow, btnWidth, btnHeight),
                                           "Duplicate",
                                           sizeStyle="small",
                                           callback=self.testerCB)

        boxRow += 22
        self.w.groupCtrls.rename = Button((boxLeft, boxRow, btnWidth, btnHeight),
                                          "Rename",
                                          sizeStyle="small",
                                          callback=self.testerCB)

        boxRow += 22
        self.w.groupCtrls.delBtn = Button((boxLeft, boxRow, btnWidth, btnHeight),
                                          "Delete",
                                          sizeStyle="small",
                                          callback=self.testerCB)

        boxRow = 22
        boxLeft += btnWidth + 7 + (btnWidth / 2 - 15)
        self.w.groupCtrls.upBtn = Button((boxLeft, boxRow, 30, btnHeight),
                                         "↑",
                                         sizeStyle="small",
                                         callback=self.testerCB)
        boxRow += 22
        self.w.groupCtrls.dnBtn = Button((boxLeft, boxRow, 30, btnHeight),
                                         "↓",
                                         sizeStyle="small",
                                         callback=self.testerCB)



        row += listHeight + 12
        self.w.groupContentsText = TextBox((left, row, colWidth, 20),
                                           "Group contents:",
                                           sizeStyle="small")

        row += 17
        self.w.groupContents = TextEditor((left, row, -10, -36),
                                          text="",
                                          readOnly=True,
                                          callback=self.editGroupContents)
        self.w.groupContents.getNSTextView().setFont_(monoFont)


        # self.w.renameText = TextBox((left, row, colWidth, 20),
        #                             "Rename preset:",
        #                             sizeStyle="small")

        # self.w.renameEdit = EditText((left, row, colWidth, btnHeight))
        row += 17
        self.w.okButton = Button((windowWidth/2 - btnWidth/2, -31, btnWidth, btnHeight),
                                 "OK",
                                 callback=self.closeCB)

        self.w.setDefaultButton(self.w.okButton)

        self.updatePresetInfo()

    def closeCB(self, sender):
        self.w.close()

    def testerCB(self, sender):
        print("hit: %s" % sender)

    def updatePresetInfo(self, sender=None):
        """
        Update self.w.proofGroupNames and self.w.renameEdit,
        and reset proofGroupNames selection and groupContents
        when user selects preset from list
        """
        if sender is None:
            selectionIndex = 0
        else:
            if not sender.getSelection():
                return
            selectionIndex = sender.getSelection()[0]
        self.selectedPreset = self.presets[selectionIndex]

        self.w.proofGroupNames.set(self.selectedPreset.groupNames)
        self.w.proofGroupNames.setSelection([])
        self._resetGroupContents()

    def updateGroupContents(self, sender):
        """
        Update groupContents when user selects a proof group
        """
        if not sender.getSelection():
            self._resetGroupContents()
            return
        self.selectedGroupIndex = sender.getSelection()[0]
        selectedGroup = self.selectedPreset.groups[self.selectedGroupIndex]

        self.w.groupContents.set("\n".join(selectedGroup.contents))
        self.w.groupContents.getNSTextView().setEditable_(True)

    def editGroupContents(self, sender):
        """
        Set group contents to new contents
        """
        newContents = sender.get().split("\n")
        self.selectedPreset.groups[self.selectedGroupIndex].contents = newContents

    def _resetGroupContents(self):
        """
        Set w.groupContents to empty string and
        make it readOnly
        """
        self.w.groupContents.set("")
        self.w.groupContents.getNSTextView().setEditable_(False)