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()
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()
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()
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 = ''
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 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)
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
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()
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()
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()
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)