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")
Example #2
0
    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()
Example #3
0
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)
Example #4
0
 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()
Example #5
0
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()
Example #7
0
class CopyKerning:

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

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

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

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

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

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

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

    def copyCallback(self, sender):
        self.sheet = Sheet((300, 50), self.w)
        self.sheet.bar = ProgressBar((10, 20, -10, 10), isIndeterminate=True, sizeStyle="small")
        self.sheet.open()
        self.sheet.bar.start()
        self.copyKerning(self.groups, self.kerning, self.source_font, self.destination_fonts)
        self.sheet.bar.stop()
        self.sheet.close()
        del self.sheet
        self.w.close()
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()
Example #9
0
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()
Example #10
0
    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()
Example #11
0
 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()
Example #12
0
 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()
Example #13
0
 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()
Example #14
0
    def __init__(self):
        self.w = Window((180, 340), u"Touché!", minSize=(180, 340), maxSize=(1000, 898))
        p = 10
        w = 160

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

        buttons = {
            "checkSelBtn": {"text": "Check selected glyphs\nfor touching pairs", "callback": self.checkSel, "y": p},
            "checkAllBtn": {
                "text": "Check entire font\n(can take several minutes!)",
                "callback": self.checkAll,
                "y": 60,
            },
        }
        for button, data in buttons.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()
Example #15
0
 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()
Example #16
0
	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
Example #17
0
 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
Example #18
0
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()
Example #22
0
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()
Example #23
0
    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()
Example #24
0
    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()
Example #27
0
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")
Example #28
0
class CopyGlyphs:

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

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

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

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