Tools

Items

ezui.makeItem(description, container=None, controller=None, descriptionData={})

Make an item from a description dictionary or a text shortcut.

The dictionary must have a "type" key that defines the class to use.

All other key/value pairs will be used to make the item.

Colors

ezui.makeColor(color)

Create a color object for use with AppKit. color may be three types:

  • A tuple of (red, green, blue, alpha) with the component values being between 0 and 1.

  • A string naming a known color. The options are below.

  • A NSColor. This is a convenience so that color type testing doesn’t have to be done elsewhere.

Named Colors:

  • "black"

  • "white"

  • "clear"

  • "blue"

  • "brown"

  • "gray"

  • "green"

  • "indigo"

  • "orange"

  • "pink"

  • "purple"

  • "red"

  • "teal"

  • "yellow"

  • "label"

  • "secondaryLabel"

  • "tertiaryLabel"

  • "quaternaryLabel"

  • "text"

  • "textBackground"

  • "selectedText"

  • "selectedTextBackground"

  • "windowBackground"

Custom colors may be registered with registerColor().

ezui.registerColor(name, color)

Register a color. Names must be unique. It is recommended that custom colors be registered with names following the reverse domain naming structure.

Images

ezui.makeImage(imagePath=None, imageName=None, symbolName=None, symbolConfiguration=None, accessibilityDescription=None, variableValue=None, template=False)

If symbolName and either of imageName and imagePath are given, symbolName will be used when symbols are available. This allows the image to be a fallback for when the OS version does not support SF Symbols.

ezui.makeSymbolConfiguration(style=None, pointSize=None, weight=None, scale=None, renderingMode=None, colors=None)
ezui.makeSymbolImageFromGlyph(glyph, height, colors=None)

Make a image with content similar in appearance to SF Symbols.

glyph may be either a defcon Glyph object or a GLIF string. The glyph data should be drawn on a 1000 UPM with the ascender metric valus at 1000 units and the descender metric value at 0 units. Overshoots are allowed.

height is the pixel height of the desired image. The width will be calculated from the glyph width, but it is recommended that the glyph width be 1000 units.

colors may be a list of (r, g, b, a) color tuples. If colors is None the default color values will be used.

Within the glyph lib, there should be data stored at the com.typesupply.ezui.symbolAttributes key. The data structure must follow this model:

{
    "format" : 0,
    "contours" : {
        "identifier" : {
                "mode" : "stroke" | "fill"
                "color" : int # the index of the color provided in the colors list
                "strokeWidth" : "thick" | "thin"
                "lineCap" : "butt" | "round" | "square"
                "lineJoin" : "miter" | "round" | "bevel"
            }
    }
    "compoundPaths" : [
        ["identifier", ...]
    ]
}

This is a sample glyph containing common elements:

show:
- standard corner radius
- (+)
- thick/thin
- line cap styles
- line join styles

A RoboFont tool for setting the data attributes within the RoboFont glyph editor can be used by doing this:

from ezui.tools import ezSymbolEditor

ezSymbolEditor.run()

Fonts

ezui.makeFont(systemStyle=None, name=None, size=None, sizeStyle='regular', weight=None, designStyle=None)

systemStyle One of the system defined styles.

  • "largeTitle"

  • "title1"

  • "title2"

  • "title3"

  • "headline"

  • "subheadline"

  • "body" (default)

  • "callout"

  • "footnote"

  • "caption1"

  • "caption2"

weight One of the system defined weight styles, only avaible when name is set to "system" or "system-monospaced";

  • "ultraLight"

  • "thin"

  • "light"

  • "regular"

  • "medium"

  • "semibold"

  • "bold"

  • "heavy"

  • "black"

designStyle One fo the system defined desing styles, only avaible when name is set to "system" or "system-bold";

  • "default"

  • "monospaced"

  • "rounded"

  • "serif"

Value Conversion and Formatting

Converting object values (ie numbers) to strings for display in an interface and then back to object values after user editing is a non-trivial task. Several items in ezui have built in support for doing this automatically. Additionally, they have support for modifying the display of the string (ie changing the color of the text).

Value Conversion

Automatic value conversion is available in some items for these value types:

  • "string" Convert from a string to a string and back.

  • "stringList" Convert from a list of strings to a single string and back.

  • "number" Convert from a number (integer or float) to a string and back.

  • "numberList" Convert from a list of numbers to a single string and back.

  • "integer" Convert from a integer to a string and back.

  • "integerList" Convert from a list of integers to a single string and back.

  • "float" Convert from a float to a string and back.

  • "floatList" Convert from a list of floats to a single string and back.

Specify these as the valueType in TextField, Table, etc. to enable the automatic conversion.

If you want to format the string, pass a stringFormatter function where allowed. This function must take a single attributes argument. The value for this will be a dictionary with the following items:

  • value The original object value.

  • string The value converted to a string.

  • font A font name or "system".

  • weight A font weight name.

  • pointSize A point size value.

  • lineHeight A line height factor.

  • figureStyle A figure style.

  • fillColor A fill color.

The full meanings and options for these are defined in Merz’s Attributed String.

That stringFormatter function may alter any of these items as needed. If the formatter wants to create a full NSAttributedString it may store this under the attributedString key in the dictionary and the stored value will be used without any further processing.

If the built-in converters do not handle a needed conversion, you may pass valueToStringConverter and stringToValueConverter functions. Refer to vanilla.List2 for the details.

Examples

A string formatter that makes negative numbers red, zero blue and positive numbers green.

def colorNumberFormatter(attributes):
    value = attributes["value"]
    if value is None:
        color = (0.5, 1, 0, 1)
    elif value < 0:
        color = (1, 0, 0, 1)
    elif value > 0:
        color = (0, 1, 0, 1)
    else:
        color = (0, 0, 1, 1)
    attributes["fillColor"] = color

Value converters that convert specific strings to emoji and back.

stringToEmojiMap = dict(
    robot="🤖",
    pen="🖋️",
    rainbow="🌈"
)
emojiToStringMap = {v : k for k, v in stringToEmojiMap.items()}
fallbackEmoji = "🥴"
fallbackString = "unknown"

def stringToEmojiConverter(value):
    emoji = stringToEmojiMap.get(value, fallbackEmoji)
    return emoji

def emojiToStringConverter(value):
    value = emojiToStringMap.get(value, fallbackString)
    return value

Deep Details

These are the low-level functions that power all of this in case you want to read the full documentation:

ezui.makeValueToStringConverter(valueType, delimiter=' ')

Make a value to string converter.

valueType must be one of the following:

  • string

  • stringList

  • number

  • numberList

  • integer

  • integerList

  • float

  • floatList

delimiter must be a string for delimiting values in a *List value type.

ezui.makeStringToValueConverter(valueType, delimiter=None, minListItems=None, maxListItems=None, fallback=None, minValue=None, maxValue=None, evaluateValueAsEquation=False, returnValidity=False)

Make a string to value converter.

valueType must be one of the following:

  • string

  • stringList

  • number

  • numberList

  • integer

  • integerList

  • float

  • floatList

delimiter The delimiter used in *List value types.

minListItems The minimum number of items in a *List value.

maxListItems The maximum number of items in a *List value.

fallback The fallback value to use when a string can not be parsed.

minValue The minimum allowed value.

maxValue The maximum allowed value.

evaluateValueAsEquation If the string should be passed through convertEquationStringToNumber.

returnValidity If True the returned value will be: (bool indicating string validity, converted value).

Number:

>>> converter = makeStringToValueConverter(
...     valueType="number",
...     minValue=-10,
...     maxValue=10,
...     fallback=9,
...     returnValidity=True
... )
>>> converter("1")
(True, 1)
>>> converter("-1")
(True, -1)
>>> converter("1.1")
(True, 1.1)
>>> converter("-1.1")
(True, -1.1)
>>> converter("0")
(True, 0)
>>> converter("XXX")
(False, 9)
>>> converter("11")
(False, 10)
>>> converter("-11")
(False, -10)

Integer:

>>> converter = makeStringToValueConverter(
...     valueType="integer",
...     minValue=-10,
...     maxValue=10,
...     fallback=9,
...     returnValidity=True
... )
>>> converter("1")
(True, 1)
>>> converter("-1")
(True, -1)
>>> converter("0")
(True, 0)
>>> converter("XXX")
(False, 9)
>>> converter("11")
(False, 10)
>>> converter("-11")
(False, -10)

Float:

>>> converter = makeStringToValueConverter(
...     valueType="float",
...     minValue=-1.1,
...     maxValue=1.1,
...     fallback=0.3,
...     returnValidity=True
... )
>>> converter("0.9")
(True, 0.9)
>>> converter("-0.9")
(True, -0.9)
>>> converter("0")
(True, 0.0)
>>> converter("XXX")
(False, 0.3)
>>> converter("2.2")
(False, 1.1)
>>> converter("-2.2")
(False, -1.1)

Number List:

>>> converter = makeStringToValueConverter(
...     valueType="numberList",
...     minValue=-10,
...     maxValue=10,
...     minListItems=2,
...     maxListItems=5,
...     fallback=[9, 8, 7],
...     returnValidity=True
... )
>>> converter("1 2.3 4")
(True, [1, 2.3, 4])
# too high
>>> converter("1 2.3 11")
(False, [9, 8, 7])
# no enough
>>> converter("1")
(False, [9, 8, 7])
# too many
>>> converter("1 2 3 4 5 6")
(False, [9, 8, 7])

Equation:

>>> converter = makeStringToValueConverter(
...     valueType="number",
...     evaluateValueAsEquation=True,
...     returnValidity=True
... )
>>> converter("2 * 2 + (2 / 2) - 0.1")
(True, 4.9)
>>> converter("xxx")
(False, None)
ezui.convertEquationStringToNumber(text)

Convert a string as an equation.

This will perform a Python eval when the string contains only these characters: +-*/()0123456789..

ezui.addFormatterToConverter(valueToStringConverter=None, stringFormatter=None, attributes={}, lastResortAttributes={'figureStyle': 'regular', 'fillColor': Catalog color: System textColor, 'font': 'system', 'lineHeight': 1.2, 'pointSize': 10, 'weight': 'regular'})

Add a string formatter to the value to string converter.

In practice, the object value will be sent to valueToStringConverter to be converted to a string. is valueToStringConverter is None the value will ve converted with str(value) A dictionary will be created with the following key/value pairs:

  • value The original object value.

  • string The value converted to a string with valueToStringConverter.

The dictionary will also contain the following key/value pairs from attributes if they are defined:

  • font

  • weight

  • pointSize

  • lineHeight

  • figureStyle

  • fillColor

The meanings for these are defined in Merz’s Attributed String.

This dictionary will be passed as the only argument to the stringFormatter function. That function is expected to take the given value, string and attributes and update the attributes in the dictionary to the final values to use for creating the attributed string. If the formatter adds a key/value pair to the dictionary at attributedString that NSAttributedString will be used as the final value and all further processing will be ignored. Any attributes not defined in the dictionary will be taken from lastResortResortAttributes. If the final attributes match lastResortResortAttributes, the plain Python string will be returned.

lastResortAttributes should be created by sending attributes through makeLastResortAttributes. This will ensure that all required keys are created.

A formatter that makes negative values red, positive values green and zero blue:

from ezui.tools.converters import (
    makeValueToStringConverter,
    addFormatterToConverter
)

def colorNumberFormatter(attributes):
    value = attributes["value"]
    if value is None:
        color = (1, 1, 0, 1)
    elif value < 0:
        color = (1, 0, 0, 1)
    elif value > 0:
        color = (0, 1, 0, 1)
    else:
        color = (0, 0, 1, 1)
    attributes["fillColor"] = color

converter = makeValueToStringConverter("number")
converter = addFormatterToConverter(
    valueToStringConverter=converter,
    stringFormatter=colorNumberFormatter
)

from math import pi

redString = converter(-pi)
blueString = converter(0)
greenString = converter(pi)

Metrics

ezui.metrics()

Common values.

  • "windowMarginH" Horizontal spacing between the frame of a window and inset items.

  • "windowMarginV" Vertical spacing between the frame of a window and inset items.

  • "windowMarginLeft" Spacing between the left of the window and inset items.

  • "windowMarginRight" Spacing between the right of the window and inset items.

  • "windowMarginTop" Spacing between the left of the window and inset items.

  • "windowMarginBottom" Spacing between the bottom of the window and inset items.

  • "boxContentMarginH" Horizontal spacing between the frame of boxes and inset items.

  • "boxContentMarginV" Vertical spacing between the frame of boxes and inset items.

  • "tabContentMarginH" Horizontal spacing between the frame of tabs and inset items.

  • "tabContentMarginV" Vertical spacing between the frame of tabs and inset items.

  • "tabContentMarginLeft" Spacing between the left of tabs and inset items.

  • "tabContentMarginRight" Spacing between the right of tabs and inset items.

  • "tabContentMarginTop" Spacing between the left of tabs and inset items.

  • "tabContentMarginBottom" Spacing between the bottom of tabs and inset items.

  • "itemSpacingH" Horizontal spacing between items.

  • "itemSpacingV" Vertical spacing between items.

Classes

ezui.registerClass(name, cls)

Register a class.

  • name must be a unique string that names your class. This is the name that will be used in the EZML with the * ItemType reference sytax.

  • cls must be a class conforming to the ezui protocol.

ezui.knownItemTypes()

Get a list of all available item types.