class Preview: def __init__(self): ## create a window self.w = Window((400, 400), "Preview", minSize=(100, 100)) ## add a GlyphPreview to the window self.w.preview = GlyphPreview((0, 0, -0, -0)) ## set the currentGlyph self.setGlyph(CurrentGlyph()) ## add an observer when the glyph changed in the glyph view addObserver(self, "_currentGlyphChanged", "currentGlyphChanged") ## bind a windows close callback to this object self.w.bind("close", self.windowClose) ## open the window self.w.open() def _currentGlyphChanged(self, info): ## notification callback when the glyph changed in the glyph view ## just set the new glyph in the glyph preview self.setGlyph(CurrentGlyph()) def setGlyph(self, glyph): ## setting the glyph in the glyph Preview self.w.preview.setGlyph(glyph) def windowClose(self, sender): ## remove the observer if the window closes removeObserver(self, "_currentGlyphChanged")
def __init__(self): super(VisualReporter, self).__init__() self.allFonts = AllFonts() self.sortAllFonts() self.collectFontNames() self.w = Window((0, 0, PLUGIN_WIDTH, 1), PLUGIN_TITLE) jumpingY = UI_MARGIN self.w.fontsPopUp = PopUpButton( (UI_MARGIN, jumpingY, NET_WIDTH, vanillaControlsSize['PopUpButtonRegularHeight']), self.fontNames, callback=None) jumpingY += vanillaControlsSize['PopUpButtonRegularHeight'] + UI_MARGIN self.w.reportButton = SquareButton( (UI_MARGIN, jumpingY, NET_WIDTH, vanillaControlsSize['ButtonRegularHeight'] * 1.5), 'Generate PDF Report', callback=self.reportButtonCallback) jumpingY += vanillaControlsSize['ButtonRegularHeight'] * 1.5 + UI_MARGIN self.setUpBaseWindowBehavior() addObserver(self, 'updateFontOptions', "newFontDidOpen") addObserver(self, 'updateFontOptions', "fontDidOpen") addObserver(self, 'updateFontOptions', "fontWillClose") self.w.bind("close", self.windowCloseCallback) self.w.resize(PLUGIN_WIDTH, jumpingY) self.w.open()
class BaseApp(object): u"""The BaseApp class implements generic functions for more specialize App classes. The main function of apps is to create applications (with window UI) that offers an interface to PageBot publication building scripts. This way apps can be stored and standalone desktop applications, offering more interactive feedback to non-scripting users. Also it hides code form the user, just presenting a coherent set of choices, that then build into PDF documents, websites or identity stationary. """ W, H = 400, 400 PUBLICATION_CLASS = None # Defined by inheriting publication App classes. def __init__(self): self.w = Window((100, 100, self.W, self.H), self.__class__.__name__) self.initialize() # Initialize UI and Publication instance. self.w.open() # Open the application window. def initialize(self): u"""To be implemente by inheriting app classes. Should initialize the self._doc Publication instance. """ self._doc = self.PUBLICATIONS_CLASS() self.buildUI(self._doc.getUIParameters()) def build(self, sender=None): u"""Default behavior, building the publications. To be redefined by inheriting classes if additional functions are needed.""" self._doc.solve() fileName = self._doc.title.replace(' ', '_') self._doc.export('_export/%s.pdf' % fileName)
class Test: def __init__(self): self.w = Window((400, 400), minSize=(300, 300)) self.w.e = CodeEditor((0, 0, -0, -0), t, lexer=GlyphConstructionLexer()) self.w.open()
class SymmetrifyDialog( object ): def buttonCallback( self, sender ): button = sender.getTitle() font.disableUpdateInterface() glyph.beginUndo() if button == 'S': rotate() if button == 'T': horiflip() if button == 'C': vertiflip() if button == 'H': bothflip() glyph.endUndo() font.enableUpdateInterface() self.w.close() def __init__( self, titles ): self.button = '' margin = 10 size = 40 self.w = Window( ( len( titles ) * ( margin + size ) + margin, 2 * margin + size ), "Symmetrify" ) top = margin left = margin for title in titles: button = SquareButton( ( left, top, size, size ), title, callback = self.buttonCallback ) setattr( self.w, title, button ) left += size + margin def run( self ): self.w.open()
def __init__(self): super(BaseWindowController, self).__init__() # standard settings self.settingsDict = { 'recordingFolder': False, 'showVideoAnalysis': False, 'partAge': 25, 'useCamera': False, 'timelag': 0, 'showPlot': True, 'exportData': True, 'pupilFiltering': 1, 'exportFolder': False, 'luxFolder': False } # load settings if os.path.isfile("settings.pkl"): with open('settings.pkl', 'rb') as s: self.settingsDict = pickle.load(s) self.plot = plt self.w = Window((600, 850), 'Cognitive Worklaod Pupil Analisis') self.buildWindow() self.updateInterface() self.setUpBaseWindowBehavior() self.w.open()
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()
class ParameterTester: def __init__(self): self.w = Window((300, 100)) self.w.inner = Group((10, 10, -10, -10)) p1 = VanillaSingleValueParameter('main', 10, (0, 100), 'int') p2 = VanillaSingleValueParameter('ratio', 10, (0, 100), 'int', master=p1, mode='ratio', dissociable=True) p3 = VanillaSingleValueParameter('offset', 10, (0, 100), 'int', master=p1, mode='offset', dissociable=True) self.w.inner.p1 = ParameterSliderTextInput(p1, (0, 0, -0, 22), 'master') self.w.inner.p2 = ParameterSliderTextInput(p2, (0, 25, -0, 22), 'ratio') self.w.inner.p3 = ParameterSliderTextInput(p3, (0, 50, -0, 22), 'offset') self.w.open()
class ExampleWindow: def __init__(self): self.w = Window((400, 400), minSize=(200, 200)) self.w.canvas = Canvas((M, M, -M, -M), delegate=self) self.w.open() def draw(self, rect): #NSColor.redColor().set() yellowColor.set() for n in range(50): rgba(random(), random(), random()) rect = NSMakeRect(n * 400 + M, n * 400 + M, M, M) path = NSBezierPath.bezierPathWithRect_(rect) path.fill()
def __init__(self): self.font_order = [] self.position = "left" L = 0 # left T = 0 # top W = 200 # width H = 300 # height p = 10 # padding buttonHeight = 20 title = "☎️ Hotline Glyph" self.w = Window((W, H), title, minSize=(W/3, H/3)) self.w.fileList = List( (L, T, -0, -(p * 3 + buttonHeight * 2)), self.font_order, columnDescriptions=[ {"title": "✓", "width":20}, {"title": "File name"}, ], # files showColumnTitles=False, allowsMultipleSelection=True, enableDelete=True, otherApplicationDropSettings = dict( type=NSFilenamesPboardType, operation=NSDragOperationCopy, callback=self.dropCallback), dragSettings=dict(type="RangeType", callback=self.font_list_drag_callback), selfDropSettings=dict(type="RangeType", operation=NSDragOperationMove, callback=self.font_list_drop_callback) ) self.w.editText = EditText((p, -(p * 2 + buttonHeight * 2), -p, buttonHeight)) self.w.draw = CheckBox((p, -(p + buttonHeight), -p, buttonHeight), 'show', value=True, callback=self.updateViewCallback) self.w.toLeftbutton = SquareButton((-p*6, -(p + buttonHeight), p*2, buttonHeight), "←", sizeStyle='small', callback=self.toLeft) self.w.toRightbutton = SquareButton((-p*3, -(p + buttonHeight), p*2, buttonHeight), "➝", sizeStyle='small', callback=self.toRight) addObserver(self, "drawPreviewRef", "drawBackground") addObserver(self, "drawRef", "drawPreview") self.setUpBaseWindowBehavior() # Needed for the windowCloseCallback self.w.open()
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 __init__(self): self.glyph = None # Typical RoboFont function self.updating = False pad = 10 leading = 32 y = pad w = 300 h = 400 buttonWidth = 100 buttonHeight = 48 self.w = Window((100, 100, w, h), 'Final tool window') self.w.bind('close', self.windowCloseCallback) self.w.open()
def __init__(self): self.w = Window((400, 400), "Mock Window") self.w.sheetButton = Button((10, 10, -10, 20), "Open sheet", callback=self.buttonCB) self.presets = [] self._createPresetsList()
def __init__(self): self.w = Window((180, 340), u"Touché!", minSize=(180, 340), maxSize=(1000, 898)) p = 10 w = 160 # options self.w.options = Group((0, 0, 180, 220)) buttons = { "checkSelBtn": {"text": "Check selected glyphs\nfor touching pairs", "callback": self.checkSel, "y": p}, "checkAllBtn": { "text": "Check entire font\n(can take several minutes!)", "callback": self.checkAll, "y": 60, }, } for button, data in buttons.iteritems(): setattr( self.w.options, button, SquareButton((p, data["y"], w, 40), data["text"], callback=data["callback"], sizeStyle="small"), ) self.w.options.zeroCheck = CheckBox((p, 108, w, 20), "Ignore zero-width glyphs", value=True, sizeStyle="small") self.w.options.progress = ProgressSpinner((82, 174, 16, 16), sizeStyle="small") # results self.w.results = Group((0, 220, 180, -0)) self.w.results.show(False) textBoxes = {"stats": 24, "result": 42} for box, y in textBoxes.iteritems(): setattr(self.w.results, box, TextBox((p, y, w, 14), "", sizeStyle="small")) moreButtons = { "spaceView": {"text": "View all in Space Center", "callback": self.showAllPairs, "y": 65}, "exportTxt": {"text": "Export as MM pair list", "callback": self.exportPairList, "y": 90}, } for button, data in moreButtons.iteritems(): setattr( self.w.results, button, SquareButton((p, data["y"], w, 20), data["text"], callback=data["callback"], sizeStyle="small"), ) # list and preview self.w.outputList = List( (180, 0, 188, -0), [{"left glyph": "", "right glyph": ""}], columnDescriptions=[{"title": "left glyph"}, {"title": "right glyph"}], showColumnTitles=False, allowsMultipleSelection=False, enableDelete=False, selectionCallback=self.showPair, ) self.w.preview = MultiLineView((368, 0, -0, -0), pointSize=256) self.w.open()
def openStartWindow(self): u""" Offers a 'New' and 'Open...' button. """ self.startDialog = Window(self.dialogSize, "Welcome", minSize=self.dialogSize, maxSize=self.dialogSize) self.startDialog.newText = TextBox((20, 60, 60, 30), "New") self.startDialog.newButton = Button((20, 100, 80, 20), "Create...", callback=self.new_) self.startDialog.openText = TextBox((160, 60, 60, 30), "Existing") self.startDialog.openButton = Button((160, 100, 60, 20), "Open...", callback=self.open_) self.startDialog.open()
def __init__( self, titles ): self.button = '' margin = 10 size = 40 self.w = Window( ( len( titles ) * ( margin + size ) + margin, 2 * margin + size ), "Symmetrify" ) top = margin left = margin for title in titles: button = SquareButton( ( left, top, size, size ), title, callback = self.buttonCallback ) setattr( self.w, title, button ) left += size + margin
def openWindow(self, document): u""" Controls and paper view for a document. """ self.windowSize = (document.width, document.height) w = Window(self.windowSize, minSize=(1, 1), maxSize=self.windowSize, closable=False) self.setPaper(w, document) self.setStatusBar(w, document) w.bind("should close", self.windowShouldCloseCallback) w.bind("close", self.windowCloseCallback) w.open() return w
class SymmetrifyDialog( object ): def buttonCallback( self, sender ): self.button = sender.getTitle() self.w.close() def __init__( self, titles ): self.button = '' margin = 10 size = 40 self.w = Window( ( len( titles ) * ( margin + size ) + margin, 2 * margin + size ), "Symmetrify" ) top = margin left = margin for title in titles: button = SquareButton( ( left, top, size, size ), title, callback = self.buttonCallback ) setattr( self.w, title, button ) left += size + margin def run( self ): self.w.open() while not self.button: pass return self.button
def __init__(self): ## create a window self.w = Window((400, 400), "Preview", minSize=(100, 100)) ## add a GlyphPreview to the window self.w.preview = GlyphPreview((0, 0, -0, -0)) ## set the currentGlyph self.setGlyph(CurrentGlyph()) ## add an observer when the glyph changed in the glyph view addObserver(self, "_currentGlyphChanged", "currentGlyphChanged") ## bind a windows close callback to this object self.w.bind("close", self.windowClose) ## open the window self.w.open()
def __init__( self ): x = 10 y = 10 height = 20 button_width = 30 glyphname_width = 180 gap = 6 self.w = Window( ( x + button_width + gap + glyphname_width + gap + button_width + x, y + height + y ), "insert glyph" ) self.w.center() self.w.glyphname = EditText( ( x, y, glyphname_width, height ), '') x += glyphname_width + gap self.w.alignleft = Button( ( x, y, button_width, height ), LEFT, callback = self.buttonCallback ) x += button_width + gap self.w.alignright = Button( ( x, y, button_width, height ), RIGHT, callback = self.buttonCallback ) self.w.setDefaultButton( self.w.alignleft ) self.w.alignright.bind( "\x1b", [] ) self.w.open()
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 userChecksInfoNote(font, fontState): window = Window((400, 400),"edit info.note", minSize=(100, 100)) window.textEditor = TextEditor(posSize=(0, 0, 400, 300)) noteContent = font.info.note or "" window.textEditor.set(noteContent) def handleCommit(s): editorContent = window.textEditor.get() window.close() commitInfoNote(editorContent, font, fontState) window.updateNoteButton = SquareButton(posSize=(0, 350, 100, 50), title="commit", callback=handleCommit) window.cancelButton = SquareButton(posSize=(110, 350, 130, 50), title="cancel operation", callback=lambda x: window.close()) window.open()
def openSaveDialog(self): if not self.saveDialog is None: return self.saveDialog = Window(self.saveDialogSize, "Save", minSize=self.saveDialogSize, maxSize=self.saveDialogSize) self.saveDialog.saveText = TextBox((60, 20, 280, 60), "Save changes to the document %s?" % self.currentDocument.name) self.saveDialog.dontButton = Button((60, 70, 100, 20), "Don't Save", callback=self.saveDontCallback) self.saveDialog.cancelButton = Button((260, 70, 60, 20), "Cancel", callback=self.saveCloseCallback) self.saveDialog.doButton = Button((320, 70, 60, 20), "Save", callback=self.saveDoCallback) self.saveDialog.open()
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 __init__(self): self.w = Window((400, 400)) self.w.e = CodeEditor((0, 0, -0, -0), t, lexer=GlyphConstructionLexer()) self.w.open()
from vanilla import Window, Slider, Button # or from vanilla import * w = Window((400, 300), "My new window") w.mySlider = Slider((10, 10, 200, 20)) w.myButton = Button((10, 40, 100, 20), "Click me!") w.open()
class ToucheTool: def __init__(self): self.w = Window((180, 340), u"Touché!", minSize=(180, 340), maxSize=(1000, 898)) p = 10 w = 160 # options self.w.options = Group((0, 0, 180, 220)) buttons = { "checkSelBtn": {"text": "Check selected glyphs\nfor touching pairs", "callback": self.checkSel, "y": p}, "checkAllBtn": { "text": "Check entire font\n(can take several minutes!)", "callback": self.checkAll, "y": 60, }, } for button, data in buttons.iteritems(): setattr( self.w.options, button, SquareButton((p, data["y"], w, 40), data["text"], callback=data["callback"], sizeStyle="small"), ) self.w.options.zeroCheck = CheckBox((p, 108, w, 20), "Ignore zero-width glyphs", value=True, sizeStyle="small") self.w.options.progress = ProgressSpinner((82, 174, 16, 16), sizeStyle="small") # results self.w.results = Group((0, 220, 180, -0)) self.w.results.show(False) textBoxes = {"stats": 24, "result": 42} for box, y in textBoxes.iteritems(): setattr(self.w.results, box, TextBox((p, y, w, 14), "", sizeStyle="small")) moreButtons = { "spaceView": {"text": "View all in Space Center", "callback": self.showAllPairs, "y": 65}, "exportTxt": {"text": "Export as MM pair list", "callback": self.exportPairList, "y": 90}, } for button, data in moreButtons.iteritems(): setattr( self.w.results, button, SquareButton((p, data["y"], w, 20), data["text"], callback=data["callback"], sizeStyle="small"), ) # list and preview self.w.outputList = List( (180, 0, 188, -0), [{"left glyph": "", "right glyph": ""}], columnDescriptions=[{"title": "left glyph"}, {"title": "right glyph"}], showColumnTitles=False, allowsMultipleSelection=False, enableDelete=False, selectionCallback=self.showPair, ) self.w.preview = MultiLineView((368, 0, -0, -0), pointSize=256) self.w.open() # callbacks def checkAll(self, sender=None): self.check(useSelection=False) def checkSel(self, sender=None): self.check(useSelection=True) def check(self, useSelection): self.w.results.show(False) self._resizeWindow(enlarge=False) self.checkFont(useSelection=useSelection, excludeZeroWidth=self.w.options.zeroCheck.get()) def showPair(self, sender=None): try: index = sender.getSelection()[0] glyphs = [self.f[gName] for gName in self.touchingPairs[index]] self.w.preview.set(glyphs) except IndexError: pass def showAllPairs(self, sender=None): # open all resulting pairs in Space Center rawString = "" for g1, g2 in self.touchingPairs: rawString += "/%s/%s/space" % (g1, g2) s = OpenSpaceCenter(self.f) s.setRaw(rawString) def exportPairList(self, sender=None): # Save the list of found touching pairs in a text file which can be read by MetricsMachine as a pair list path = PutFile("Choose save location", "TouchingPairs.txt") if path is not None: reportString = "#KPL:P: TouchingPairs\n" for g1, g2 in self.touchingPairs: reportString += "%s %s\n" % (g1, g2) fi = open(path, "w+") fi.write(reportString) fi.close() # checking def _hasSufficientWidth(self, g): # to ignore combining accents and the like if self.excludeZeroWidth: # also skips 1-unit wide glyphs which many use instead of 0 if g.width < 2: return False return True def _trimGlyphList(self, glyphList): newGlyphList = [] for g in glyphList: if g.box is not None and self._hasSufficientWidth(g): newGlyphList.append(g) return newGlyphList def _resizeWindow(self, enlarge=True): posSize = self.w.getPosSize() targetWidth = 700 if enlarge else 180 self.w.setPosSize((posSize[0], posSize[1], targetWidth, posSize[3])) # ok let's do this def checkFont(self, useSelection=False, excludeZeroWidth=True): f = CurrentFont() if f is not None: # initialize things self.w.options.progress.start() time0 = time.time() self.excludeZeroWidth = excludeZeroWidth self.f = f glyphNames = f.selection if useSelection else f.keys() glyphList = [f[x] for x in glyphNames] glyphList = self._trimGlyphList(glyphList) self.touchingPairs = Touche(f).findTouchingPairs(glyphList) # display output self.w.results.stats.set("%d glyphs checked" % len(glyphList)) self.w.results.result.set("%d touching pairs found" % len(self.touchingPairs)) self.w.results.show(True) outputList = [{"left glyph": g1, "right glyph": g2} for (g1, g2) in self.touchingPairs] self.w.outputList.set(outputList) if len(self.touchingPairs) > 0: self.w.outputList.setSelection([0]) else: self.w.preview.set("") outputButtons = [self.w.results.spaceView, self.w.results.exportTxt] for b in outputButtons: b.enable(False) if len(self.touchingPairs) == 0 else b.enable(True) self.w.preview.setFont(f) self.w.options.progress.stop() self._resizeWindow(enlarge=True) time1 = time.time() print u"Touché: finished checking %d glyphs in %.2f seconds" % (len(glyphList), time1 - time0) else: Message(u"Touché: Can’t find a font to check")
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 GlyphnameDialog( object): def __init__( self ): x = 10 y = 10 height = 20 button_width = 30 glyphname_width = 180 gap = 6 self.w = Window( ( x + button_width + gap + glyphname_width + gap + button_width + x, y + height + y ), "insert glyph" ) self.w.center() self.w.glyphname = EditText( ( x, y, glyphname_width, height ), '') x += glyphname_width + gap self.w.alignleft = Button( ( x, y, button_width, height ), LEFT, callback = self.buttonCallback ) x += button_width + gap self.w.alignright = Button( ( x, y, button_width, height ), RIGHT, callback = self.buttonCallback ) self.w.setDefaultButton( self.w.alignleft ) self.w.alignright.bind( "\x1b", [] ) self.w.open() def buttonCallback( self, sender ): title = sender.getTitle() glyphname = self.w.glyphname.get() if not glyphname: self.w.close() return if len( glyphname ) == 1: uni = ord(glyphname) g = font.glyphForUnicode_("%.4X" % uni) if g: glyphname = g.name other_glyph = font.glyphs[ glyphname ] if not other_glyph: for glyph in font.glyphs: if glyph.name.startswith( glyphname ): other_glyph = glyph print 'Using', glyph.name break else: print 'No matching glyph found.' self.w.close() return for layer in font.selectedLayers: glyph = layer.parent glyph.beginUndo() # deselect all for path in layer.paths: for node in path.nodes: layer.removeObjectFromSelection_( node ) # find other layer for other_layer in other_glyph.layers: if other_layer.name == layer.name: # insert paths for path in other_layer.copyDecomposedLayer().paths: if title == RIGHT: shift = layer.width - other_layer.width for node in path.nodes: node.x = node.x + shift layer.paths.append( path ) # select path layer.paths[-1].selected = True break glyph.endUndo() self.w.close()
class GlyphnameDialog( object): def __init__( self ): x = 10 y = 10 height = 20 button_width = 30 glyphname_width = 180 gap = 6 self.w = Window( ( x + button_width + gap + glyphname_width + gap + button_width + x, y + height + y ), "insert glyph" ) self.w.center() self.w.glyphname = EditText( ( x, y, glyphname_width, height ), '') x += glyphname_width + gap self.w.alignleft = Button( ( x, y, button_width, height ), LEFT, callback = self.buttonCallback ) x += button_width + gap self.w.alignright = Button( ( x, y, button_width, height ), RIGHT, callback = self.buttonCallback ) self.w.setDefaultButton( self.w.alignleft ) self.w.alignright.bind( "\x1b", [] ) self.w.open() def buttonCallback( self, sender ): alignment = sender.getTitle() glyphname = self.w.glyphname.get() if not glyphname: self.w.close() return if len( glyphname ) == 1: uni = ord(glyphname) g = font.glyphForUnicode_("%.4X" % uni) if g: glyphname = g.name other_glyph = font.glyphs[ glyphname ] if not other_glyph: for glyph in font.glyphs: if glyph.name.startswith( glyphname ): other_glyph = glyph print 'Using', glyph.name break else: print 'No matching glyph found.' self.w.close() return selected_glyphs = set( [ layer.parent for layer in font.selectedLayers ] ) for glyph in selected_glyphs: glyph.beginUndo() for layer in glyph.layers: # find other layer for other_layer in other_glyph.layers: if other_layer.name == layer.name: insert_paths( layer, other_layer, alignment ) break else: if active_layerId == layer.layerId: insert_paths( layer, other_glyph.layers[layer.associatedMasterId], alignment ) glyph.endUndo() self.w.close()
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)
from vanilla import Window, SquareButton, TextEditor import vanilla import mojo def onSubmit(sender): CurrentFont().info.note = window.textEditor.get() window.close() if CurrentFont() is None: vanilla.dialogs.message("there is no current font, operation aborted") else: window = Window((400, 400),"edit info.note", minSize=(100, 100)) window.textEditor = TextEditor(posSize=(0, 0, 400, 300)) noteContent = CurrentFont().info.note or "" window.textEditor.set(noteContent) window.updateNoteButton = SquareButton(posSize=(0, 350, 100, 50), title="update", callback=onSubmit) window.cancelButton = SquareButton(posSize=(110, 350, 100, 50), title="cancel", callback=lambda x: window.close()) window.open()
class Dialogs(object): u""" New dialog creation, for dialog closing see Callbacks class. """ # Start. def openStartWindow(self): u""" Offers a 'New' and 'Open...' button. """ self.startDialog = Window(self.dialogSize, "Welcome", minSize=self.dialogSize, maxSize=self.dialogSize) self.startDialog.newText = TextBox((20, 60, 60, 30), "New") self.startDialog.newButton = Button((20, 100, 80, 20), "Create...", callback=self.new_) self.startDialog.openText = TextBox((160, 60, 60, 30), "Existing") self.startDialog.openButton = Button((160, 100, 60, 20), "Open...", callback=self.open_) self.startDialog.open() def closeStartDialog(self): u""" Closes and clears start dialog. """ if not self.startDialog is None: self.startDialog.close() self.startDialog = None # Document. def openOpenDocumentDialog(self): u""" Open document dialog. """ self.closeStartDialog() panel = NSOpenPanel.openPanel() panel.setCanChooseDirectories_(False) panel.setCanChooseFiles_(True) panel.setAllowsMultipleSelection_(False) panel.setAllowedFileTypes_(['wf']) if panel.runModal() == NSOKButton: added, document = self.model.openDocument(panel.filenames()[0]) self.initDocument(added, document) def openNewDialog(self): u""" Opens the document canvas if it doesn't exist yet. """ self.closeStartDialog() self.setDefaultDocumentValues() size = (400, 300) self.newDialog = w = Window(size, "New Document", minSize=size, maxSize=size) w.nameText = TextBox((20, 20, 180, 20), "Name") w.nameBox = EditText((200, 20, 180, 20), callback=self.newNameCallback) w.nameBox.set(self.documentValues['documentName']) w.sizeText = TextBox((20, 40, 180, 20), "Size") values = PaperSizes.getAllPaperSizes() w.sizeComboBox = ComboBox((200, 40, 180, 20), values, callback=self.newSizeCallback) w.sizeComboBox.set(self.defaultPaperSize) w.whText = TextBox((20, 60, 220, 20), u"w×h in ㎜") width, height = PaperSizes.getSize(self.defaultPaperSize, 'mm') w.width = EditText((200, 60, 80, 20), callback=self.newWidthCallback) w.width.set(width) w.x = TextBox((285, 60, 10, 20), u"×") w.dimensionBoxHeight = EditText((300, 60, 80, 20), callback=self.newHeightCallback) w.dimensionBoxHeight.set(height) w.okayButton = Button((240, 260, 60, 20), "Okay", callback=self.newOkayCallback) #w.okayButton.getNSButton().setEnabled_(False) w.cancelButton = Button((320, 260, 60, 20), "Cancel", callback=self.newCancelCallback) w.open() def closeOpenDialog(self): if not self.openDialog is None: self.openDialog.close() self.openDialog = None # Save dialog. def openSaveDialog(self): if not self.saveDialog is None: return self.saveDialog = Window(self.saveDialogSize, "Save", minSize=self.saveDialogSize, maxSize=self.saveDialogSize) self.saveDialog.saveText = TextBox((60, 20, 280, 60), "Save changes to the document %s?" % self.currentDocument.name) self.saveDialog.dontButton = Button((60, 70, 100, 20), "Don't Save", callback=self.saveDontCallback) self.saveDialog.cancelButton = Button((260, 70, 60, 20), "Cancel", callback=self.saveCloseCallback) self.saveDialog.doButton = Button((320, 70, 60, 20), "Save", callback=self.saveDoCallback) self.saveDialog.open() def closeSaveDialog(self): self.saveDocumentDialog.close() self.saveDocumentDialog = None # Close. def windowShouldCloseCallback(self, sender): window = self.getCurrentWindow() if sender == window: self.closeDocument_(sender)