Imagine that you have several type-families in development. The UFO source files are kept in separate subfolders of a main folder, each named after the family it contains.

This example shows a simple dialog for browsing through the family folders, and makes it easy to open selected fonts.

The code could be extended to do more than just opening the selected fonts: setting font infos, generating fonts etc.

import os
from vanilla import *
from vanilla.dialogs import getFolder

class FontLibraryBrowser(object):

    # UI layout attributes
    padding = 10
    buttonHeight = 20
    columnFamilies = 120
    columnFonts = 200
    listHeight = 240
    width = columnFamilies + columnFonts + padding*3
    height = listHeight + buttonHeight*2 + padding*4

    # root folder for families
    rootFolder = None

    # current family
    family = None

    def __init__(self):
        self.w = FloatingWindow((self.width, self.height), "myFontLibrary")

        # a button to get the root folder
        x = y = self.padding
        self.w.getFolderButton = Button(
                (x, y, -self.padding, self.buttonHeight),
                "get root folder...",
                callback=self.getFolderCallback,
            )

        # list of folders in root folder
        y += self.buttonHeight + self.padding
        self.w.families = List(
                (x, y, self.columnFamilies, self.listHeight),
                [],
                selectionCallback=self.getFontsCallback,
                allowsMultipleSelection=False,
             )

        # list of fonts in folder
        x += self.columnFamilies + self.padding
        self.w.fonts = List(
                (x, y, self.columnFonts, self.listHeight),
                [],
             )

        # open selected fonts
        x = self.padding
        y += self.listHeight + self.padding
        self.w.openFontsButton = Button(
                (x, y, -self.padding, self.buttonHeight),
                "open selected fonts",
                callback=self.openFontsCallback
            )

        # open the dialog
        self.w.open()

    # ---------
    # callbacks
    # ---------

    def getFolderCallback(self, sender):
        '''Get the main folder where all family folders live.'''

        # open a dialog to select the root folder
        folder = getFolder()

        # no folder selected
        if folder is None:
            return

        # get folder
        else:
            self.rootFolder = folder[0]

        # update families list
        self.updateFamiliesList()

    def getFontsCallback(self, sender):
        '''Get UFOs in current family folder.'''

        # get families
        families = sender.get()

        if not len(families):
            return

        # get selected family
        selection = sender.getSelection()

        if not len(selection):
            return

        self.family = families[selection[0]]

        # list all ufos in family folder
        self.updateFontsList()

    def openFontsCallback(self, sender):
        '''Open selected fonts in current family.'''

        # get fonts
        allFonts = self.w.fonts.get()

        if not len(allFonts):
            return

        # get selection
        fontsSelection = self.w.fonts.getSelection()

        if not len(fontsSelection):
            return

        # get selected fonts
        selectedFonts = [f for i, f in enumerate(allFonts) if i in fontsSelection]

        # open selected fonts
        familyFolder = os.path.join(self.rootFolder, self.family)
        for font in selectedFonts:
            # get ufo path for font
            ufoPath = os.path.join(familyFolder, '%s.ufo' % font)
            # open ufo
            print('opening %s/%s.ufo...' % (self.family, font))
            OpenFont(ufoPath)

    # ---------
    # functions
    # ---------

    def updateFamiliesList(self):
        '''Update the list of families in the UI.'''

        # get subfolders
        subFolders = []
        for f in os.listdir(self.rootFolder):
            fileOrFolder = os.path.join(self.rootFolder, f)
            if os.path.isdir(fileOrFolder):
                subFolders.append(f)

        # update families list
        self.w.families.set(subFolders)

    def updateFontsList(self):
        '''Update the list of fonts in the UI.'''

        # get folder for family
        familyFolder = os.path.join(self.rootFolder, self.family)

        # get ufos in folder
        ufos = [os.path.splitext(f)[0] for f in os.listdir(familyFolder) if os.path.splitext(f)[-1] == '.ufo']

        # update fonts list
        self.w.fonts.set(ufos)

# ---------------
# open the dialog
# ---------------

FontLibraryBrowser()

Last edited on 27/03/2018