Ejemplo n.º 1
0
    def getGlyphs(self):

        glyphs = []

        # font window selection
        if self.w.selectedGlyphs.get():
            font = CurrentFont()
            if font is not None:
                glyphs += font.selectedGlyphs

        # current glyph window
        if self.w.currentGlyph.get():
            glyphWindow = CurrentGlyphWindow()
            if glyphWindow is not None:
                g = glyphWindow.getGlyph()
                if g is not None and g not in glyphs:
                    glyphs += [RGlyph(g)]

        # space center selection
        if self.w.spaceCenter.get():
            spaceCenter = CurrentSpaceCenter(currentFontOnly=True)
            if spaceCenter is not None:
                g = spaceCenter.glyphLineView.getSelected()
                if g is not None and g not in glyphs:
                    glyphs += [RGlyph(g)]

        return glyphs
class GlyphMetricsUI(object):
    def __init__(self):
        # debug
        windowname = 'Debug Glyph Metrics UI'
        windows = [w for w in NSApp().orderedWindows() if w.isVisible()]
        for window in windows:
            print(window.title())
            if window.title() == windowname:
                window.close()
        if debug == True:
            self.debug = Window((333, 33), windowname)
            self.debug.bind('close', self.windowSideuiClose)
            self.debug.open()
        # setup
        self.showButtons = False
        self.sbui = None
        # add interface
        addObserver(self, 'addInterface', 'glyphWindowWillOpen')
        addObserver(self, 'updateSelfWindow', 'currentGlyphChanged')
        # toggle visibility of tool ui
        addObserver(self, 'showSideUIonDraw', 'draw')
        addObserver(self, 'hideSideUIonPreview', 'drawPreview')
        # remove UI and window manager when glyph window closes
        # addObserver(self, "observerGlyphWindowWillClose", "glyphWindowWillClose")
        # subscribe to glyph changes
        addObserver(self, "viewDidChangeGlyph", "viewDidChangeGlyph")

    # def observerGlyphWindowWillClose(self, notification):
    #     self.window = notification['window']
    #     self.cleanup(self.window)
    #     del windowViewManger[notification['window']]
    #     del lll[notification['window']]
    #     del ccc[notification['window']]
    #     del rrr[notification['window']]

    def windowSideuiClose(self, sender):
        self.window.removeGlyphEditorSubview(self.sbui)
        removeObserver(self, 'glyphWindowWillOpen')
        removeObserver(self, 'glyphWindowWillClose')
        removeObserver(self, 'glyphWindowWillClose')
        removeObserver(self, 'currentGlyphChanged')
        removeObserver(self, 'draw')
        removeObserver(self, 'drawPreview')
        removeObserver(self, 'viewDidChangeGlyph')

    def cleanup(self, w):
        try:
            w.removeGlyphEditorSubview(self.sbui)
        except:
            return

    def addInterface(self, notification):
        self.window = notification['window']
        # self.cleanup(self.window)

        # CONTAINER
        xywh = (margin, -55, -margin, height)
        self.sbui = CanvasGroup(xywh, delegate=CanvasStuff(self.window))

        # LEFT
        x, y, w, h = xywh = (0, -height, dfltLwidth, height)
        this = self.sbui.L = Group(xywh)

        # text input
        xywh = (x, y + 3, width * 1.5, height * .75)
        this.Ltext = EditText(xywh,
                              placeholder='angledLeftMargin',
                              sizeStyle='mini',
                              continuous=False,
                              callback=self.setSB)
        # quick mod buttons
        xywh = (x + width * 1.5 + (gap * 1), y, width, height)
        this.Lminus = Button(xywh,
                             iconminus,
                             sizeStyle='mini',
                             callback=self.setLminus)
        this.Lminus.getNSButton().setToolTip_('Adjust LSB -' + str(unit))
        xywh = (x + width * 2.5 + (gap * 2), y, width, height)
        this.Lplus = Button(xywh,
                            iconplus,
                            sizeStyle='mini',
                            callback=self.setLplus)
        this.Lplus.getNSButton().setToolTip_('Adjust LSB +' + str(unit))
        xywh = (x + width * 3.5 + (gap * 3), y, width, height)
        this.Lround = Button(xywh,
                             iconround,
                             sizeStyle='mini',
                             callback=self.setLround)
        this.Lround.getNSButton().setToolTip_('Round LSB to ' + str(unit))
        xywh = (x + width * 4.5 + (gap * 4), y, width, height)
        this.Lright = Button(xywh,
                             iconcopyR,
                             sizeStyle='mini',
                             callback=self.setLright)
        this.Lright.getNSButton().setToolTip_('Copy Right Value')
        # stylize
        this.Ltext.getNSTextField().setBezeled_(False)
        this.Ltext.getNSTextField().setBackgroundColor_(NSColor.clearColor())
        self.flatButt(this.Lminus)
        self.flatButt(this.Lplus)
        self.flatButt(this.Lround)
        self.flatButt(this.Lright)

        # RIGHT
        x, y, w, h = xywh = (-dfltRwidth, y, dfltRwidth, h)
        this = self.sbui.R = Group(xywh)
        # text input
        xywh = (-x - width * 1.5, y + 3, width * 1.5, height * .75)
        this.Rtext = EditText(xywh,
                              placeholder='angledRightMargin',
                              sizeStyle='mini',
                              continuous=False,
                              callback=self.setSB)
        # quick mod buttons
        xywh = (-x - width * 5.5 - (gap * 4), y, width, height)
        this.Rleft = Button(xywh,
                            iconcopyL,
                            sizeStyle='mini',
                            callback=self.setRleft)
        this.Rleft.getNSButton().setToolTip_('Copy Left Value')
        xywh = (-x - width * 4.5 - (gap * 3), y, width, height)
        this.Rround = Button(xywh,
                             iconround,
                             sizeStyle='mini',
                             callback=self.setRround)
        this.Rround.getNSButton().setToolTip_('Round RSB to ' + str(unit))
        xywh = (-x - width * 3.5 - (gap * 2), y, width, height)
        this.Rminus = Button(xywh,
                             iconminus,
                             sizeStyle='mini',
                             callback=self.setRminus)
        this.Rminus.getNSButton().setToolTip_('Adjust RSB -' + str(unit))
        xywh = (-x - width * 2.5 - (gap * 1), y, width, height)
        this.Rplus = Button(xywh,
                            iconplus,
                            sizeStyle='mini',
                            callback=self.setRplus)
        this.Rplus.getNSButton().setToolTip_('Adjust RSB +' + str(unit))
        # stylize
        this.Rtext.getNSTextField().setBezeled_(False)
        this.Rtext.getNSTextField().setBackgroundColor_(NSColor.clearColor())
        this.Rtext.getNSTextField().setAlignment_(NSTextAlignmentRight)
        self.flatButt(this.Rminus)
        self.flatButt(this.Rplus)
        self.flatButt(this.Rround)
        self.flatButt(this.Rleft)

        # CENTER
        winX, winY, winW, winH = self.window.getVisibleRect()
        winW = winW - margin * 5
        x, y, w, h = xywh = ((winW / 2) - (dfltCwidth / 2), y, dfltCwidth, h)
        this = self.sbui.C = Group(xywh)
        x = 0

        # text input
        c = (dfltCwidth / 2)
        xywh = (c - (width * .75), y + 3, width * 1.5, height * .75)
        this.Ctext = EditText(xywh,
                              placeholder='width',
                              sizeStyle='mini',
                              continuous=False,
                              callback=self.setSB)
        # quick mod buttons
        xywh = (c - (width * .75) - width * 2 - (gap * 2), y, width, height)
        this.Ccenter = Button(xywh,
                              iconcenter,
                              sizeStyle='mini',
                              callback=self.setCcenter)
        this.Ccenter.getNSButton().setToolTip_('Center on Width')
        xywh = (c - (width * .75) - width - (gap * 1), y, width, height)
        this.Cround = Button(xywh,
                             iconround,
                             sizeStyle='mini',
                             callback=self.setCround)
        this.Cround.getNSButton().setToolTip_('Round Width to ' + str(unit))
        xywh = (c + (width * .75) + (gap * 1), y, width, height)
        this.Cminus = Button(xywh,
                             iconminus,
                             sizeStyle='mini',
                             callback=self.setCminus)
        this.Cminus.getNSButton().setToolTip_('Adjust Width -' + str(2 * unit))
        xywh = (c + (width * .75) + width + (gap * 2), y, width, height)
        this.Cplus = Button(xywh,
                            iconplus,
                            sizeStyle='mini',
                            callback=self.setCplus)
        this.Cplus.getNSButton().setToolTip_('Adjust Width +' + str(2 * unit))
        # stylize
        this.Ctext.getNSTextField().setBezeled_(False)
        this.Ctext.getNSTextField().setBackgroundColor_(NSColor.clearColor())
        this.Ctext.getNSTextField().setAlignment_(NSTextAlignmentCenter)
        self.flatButt(this.Cminus)
        self.flatButt(this.Cplus)
        self.flatButt(this.Cround)
        self.flatButt(this.Ccenter)

        # hide
        self.sbui.L.Lminus.show(False)
        self.sbui.L.Lround.show(False)
        self.sbui.L.Lplus.show(False)
        self.sbui.L.Lright.show(False)
        self.sbui.R.Rminus.show(False)
        self.sbui.R.Rround.show(False)
        self.sbui.R.Rplus.show(False)
        self.sbui.R.Rleft.show(False)
        self.sbui.C.Cminus.show(False)
        self.sbui.C.Cround.show(False)
        self.sbui.C.Ccenter.show(False)
        self.sbui.C.Cplus.show(False)

        # make it real
        self.sbWatcherInitialize()
        self.window.addGlyphEditorSubview(self.sbui)
        self.updateValues()
        self.buildMatchBase()
        windowViewManger[self.window] = self.sbui

    def updateSelfWindow(self, notification):
        self.window = CurrentGlyphWindow()
        self.buildMatchBase()
        self.updateValues()

    def showSideUIonDraw(self, notification):
        self.sbWatcher()
        sbui = windowViewManger.get(self.window)
        if sbui is not None:
            sbui.show(True)

    def hideSideUIonPreview(self, notification):
        sbui = windowViewManger.get(self.window)
        if sbui is not None:
            sbui.show(False)

    def updateValues(self, notification=None):
        try:
            g = self.window.getGlyph()
            f = g.font
            sbui = windowViewManger.get(self.window)
            sbui.L.Ltext.set(str(g.angledLeftMargin))
            sbui.R.Rtext.set(str(g.angledRightMargin))
            sbui.C.Ctext.set(str(g.width))
        except Exception as e:
            # if debug == True:
            #     print('Exception updateValues', e)
            return

    # hack sidebearings changed observer
    # used when things redraw
    def sbWatcherInitialize(self):
        g = self.window.getGlyph()
        f = g.font
        if g is not None:
            lll[self.window] = g.angledLeftMargin
            ccc[self.window] = g.width
            rrr[self.window] = g.angledRightMargin

    def sbWatcher(self):
        g = CurrentGlyph()
        if g is not None:
            f = g.font
            if lll[self.window] != None and ccc[self.window] != None and rrr[
                    self.window] != None:
                if lll[self.window] != g.angledLeftMargin or ccc[
                        self.window] != g.width or rrr[
                            self.window] != g.angledRightMargin:
                    lll[self.window] = g.angledLeftMargin
                    ccc[self.window] = g.width
                    rrr[self.window] = g.angledRightMargin
                    self.updateValues()
                    self.buildMatchBase()

    def setSB(self, sender):
        changeAttribute = sender.getPlaceholder()
        g = self.window.getGlyph()
        f = g.font
        v = sender.get()
        if is_number(v):
            if debug == True:
                print('value is a number')
            g.prepareUndo('Change ' + changeAttribute + ' SB')
            setattr(g, changeAttribute, float(v))
            g.performUndo()
            self.updateValues()
        elif v in f:
            if debug == True:
                print('value is a glyph')
            g.prepareUndo('Change ' + changeAttribute + ' SB')
            sb = getattr(f[v], changeAttribute)
            setattr(g, changeAttribute, sb)
            g.performUndo()
            self.updateValues()
        else:
            if debug == True:
                print('value is not a number or a glyph')
            return

    def setLminus(self, sender):
        g = self.window.getGlyph()
        if g is None:
            return
        g.prepareUndo('➖ Left SB')
        g.angledLeftMargin += -1 * unit
        g.performUndo()
        self.updateValues()

    def setLround(self, sender):
        g = self.window.getGlyph()
        if g is None:
            return
        g.prepareUndo('Round Left SB')
        g.angledLeftMargin = int(unit *
                                 round(float(g.angledLeftMargin) / unit))
        g.performUndo()
        self.updateValues()

    def setLplus(self, sender):
        g = self.window.getGlyph()
        if g is None:
            return
        g.prepareUndo('➕ Left SB')
        g.angledLeftMargin += unit
        g.performUndo()
        self.updateValues()

    def setLright(self, sender):
        g = self.window.getGlyph()
        if g is None:
            return
        g.prepareUndo('Copy Right SB')
        g.angledLeftMargin = g.angledRightMargin
        g.performUndo()
        self.updateValues()

    def setLmatch(self, sender):
        g = self.window.getGlyph()
        if g is None:
            return
        g.prepareUndo('Match Left SB')
        f = g.font
        gmatch = sender.getTitle()
        if f[gmatch] is not None:
            g.angledLeftMargin = f[gmatch].angledLeftMargin
        g.performUndo()
        self.updateValues()

    def setRminus(self, sender):
        g = self.window.getGlyph()
        if g is None:
            return
        g.prepareUndo('➖ Right SB')
        g.angledRightMargin += -1 * unit
        g.performUndo()
        self.updateValues()

    def setRround(self, sender):
        g = self.window.getGlyph()
        if g is None:
            return
        g.prepareUndo('Round Right SB')
        g.angledRightMargin = int(unit *
                                  round(float(g.angledRightMargin) / unit))
        g.performUndo()
        self.updateValues()

    def setRplus(self, sender):
        g = self.window.getGlyph()
        if g is None:
            return
        g.prepareUndo('➕ Right SB')
        g.angledRightMargin += unit
        g.performUndo()
        self.updateValues()

    def setRmatch(self, sender):
        g = self.window.getGlyph()
        if g is None:
            return
        g.prepareUndo('Match Right SB')
        gmatch = sender.getTitle()
        f = g.font
        if f[gmatch] is not None:
            g.angledRightMargin = f[gmatch].angledRightMargin
        g.performUndo()
        self.updateValues()

    def setRleft(self, sender):
        g = self.window.getGlyph()
        if g is None:
            return
        g.prepareUndo('Copy Left SB')
        g.angledRightMargin = g.angledLeftMargin
        g.performUndo()
        self.updateValues()

    def setCminus(self, sender):
        g = self.window.getGlyph()
        if g is None:
            return
        g.prepareUndo('➖ Width')
        # use whole units, not floats
        oldwidth = g.width
        leftby = unit
        g.angledLeftMargin += -1 * leftby
        g.width = oldwidth - unit * 2
        g.performUndo()
        self.updateValues()

    def setCround(self, sender):
        g = self.window.getGlyph()
        if g is None:
            return
        g.prepareUndo('Round Width')
        g.width = int(unit * round(float(g.width) / unit))
        g.performUndo()
        self.updateValues()

    def setCcenter(self, sender):
        g = self.window.getGlyph()
        if g is None:
            return
        g.prepareUndo('Center on Width')
        # use whole units, not floats
        padding = g.angledLeftMargin + g.angledRightMargin
        gwidth = g.width
        g.angledLeftMargin = int(padding / 2)
        g.width = gwidth
        g.performUndo()
        self.updateValues()

    def setCplus(self, sender):
        g = self.window.getGlyph()
        if g is None:
            return
        g.prepareUndo('➕ Width')
        # use whole units, not floats
        oldwidth = g.width
        leftby = unit
        g.angledLeftMargin += leftby
        g.width = oldwidth + unit * 2
        g.performUndo()
        self.updateValues()

    def setCmatch(self, sender):
        g = self.window.getGlyph()
        if g is None:
            return
        g.prepareUndo('Match Width')
        f = g.font
        gmatch = sender.getTitle()
        if f[gmatch] is not None:
            g.width = f[gmatch].width
        g.performUndo()
        self.updateValues()

    def flatButt(self, this, match=False):
        this = this.getNSButton()
        this.setBezelStyle_(buttstyle)
        this.setBordered_(False)
        this.setWantsLayer_(True)
        this.setBackgroundColor_(NSColor.whiteColor())
        if match == True:
            this.setBackgroundColor_(
                NSColor.colorWithCalibratedRed_green_blue_alpha_(
                    .9, 1, .85, 1))

    def buildMatchBase(self, notification=None):
        self.newheight = height
        try:
            g = self.window.getGlyph()
            f = g.font
            # remove old buttons
            for i in range(10):
                if hasattr(self.sbui.L, 'buttobj_%s' % i):
                    delattr(self.sbui.L, 'buttobj_%s' % i)
                    delattr(self.sbui.R, 'buttobj_%s' % i)
                    delattr(self.sbui.C, 'buttobj_%s' % i)

            # add button for each component
            self.uniquecomponents = []
            for c in g.components:
                if c.baseGlyph not in self.uniquecomponents:
                    self.uniquecomponents.append(c.baseGlyph)

            for i, c in enumerate(self.uniquecomponents):
                row = i + 1
                yy = -height * (row + 1) - 3

                xywh = (0, yy, width * 5.5 + (gap * 4), height)
                buttobj = Button(xywh,
                                 c,
                                 sizeStyle='mini',
                                 callback=self.setLmatch)
                setattr(self.sbui.L, 'buttobj_%s' % i, buttobj)
                this = getattr(self.sbui.L, 'buttobj_%s' % i)
                this.getNSButton().setAlignment_(NSTextAlignmentLeft)
                this.getNSButton().setToolTip_('Match LSB of ' + c)

                xywh = (-width * 5.5 - (gap * 4), yy, width * 5.5 + (gap * 4),
                        height)
                buttobj = Button(xywh,
                                 c,
                                 sizeStyle='mini',
                                 callback=self.setRmatch)
                setattr(self.sbui.R, 'buttobj_%s' % i, buttobj)
                this = getattr(self.sbui.R, 'buttobj_%s' % i)
                this.getNSButton().setAlignment_(NSTextAlignmentRight)
                this.getNSButton().setToolTip_('Match RSB of ' + c)

                xywh = ((dfltLwidth / 2) - (width * 2.75 + (gap * 2)), yy,
                        width * 5.5 + (gap * 4), height)
                buttobj = Button(xywh,
                                 c,
                                 sizeStyle='mini',
                                 callback=self.setCmatch)
                setattr(self.sbui.C, 'buttobj_%s' % i, buttobj)
                this = getattr(self.sbui.C, 'buttobj_%s' % i)
                this.getNSButton().setToolTip_('Match Width of ' + c)

            for i, c in enumerate(self.uniquecomponents):
                try:
                    this = getattr(self.sbui.L, 'buttobj_%s' % i)
                    # hide if hidden
                    if self.showButtons == False:
                        this.show(False)
                    # check if metrics match base glyphs
                    if int(f[c].angledLeftMargin) == int(g.angledLeftMargin):
                        self.flatButt(this, True)
                    else:
                        self.flatButt(this)

                    this = getattr(self.sbui.R, 'buttobj_%s' % i)
                    if self.showButtons == False:
                        this.show(False)
                    if int(f[c].angledRightMargin) == int(g.angledRightMargin):
                        self.flatButt(this, True)
                    else:
                        self.flatButt(this)

                    this = getattr(self.sbui.C, 'buttobj_%s' % i)
                    if self.showButtons == False:
                        this.show(False)
                    if f[c].width == g.width:
                        self.flatButt(this, True)
                    else:
                        self.flatButt(this)

                except Exception as e:
                    return

            # change height of canvas to fit buttons
            self.newheight = height * (len(self.uniquecomponents) + 2)
            newy = -55 - height * (len(self.uniquecomponents))
            self.sbui.setPosSize((margin, newy, -margin, self.newheight))
            self.sbui.L.setPosSize((0, 0, dfltLwidth, self.newheight))
            self.sbui.R.setPosSize(
                (-dfltRwidth, 0, dfltRwidth, self.newheight))
            winX, winY, winW, winH = self.window.getVisibleRect()
            winW = winW - margin * 5
            offsetcenter = (winW / 2) - (width * 2.25)
            self.sbui.C.setPosSize(
                (offsetcenter, 0, width * 5 + 12, self.newheight))

        except Exception as e:
            return

    #############################################
    # watch for glyph changes
    #############################################

    def viewDidChangeGlyph(self, notification):
        self.glyph = CurrentGlyph()
        self.unsubscribeGlyph()
        self.subscribeGlyph()
        self.glyphChanged()

    def subscribeGlyph(self):
        self.glyph.addObserver(self, 'glyphChanged', 'Glyph.Changed')

    def unsubscribeGlyph(self):
        if self.glyph is None:
            return
        self.glyph.removeObserver(self, 'Glyph.Changed')

    def glyphChanged(self, notification=None):
        self.updateValues()