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 between0
and1
.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 ofimageName
andimagePath
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. Ifcolors
isNone
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 whenname
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 whenname
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 throughconvertEquationStringToNumber
.returnValidity
IfTrue
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. isvalueToStringConverter
isNone
the value will ve converted withstr(value)
A dictionary will be created with the following key/value pairs:value
The original object value.string
The value converted to a string withvalueToStringConverter
.
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 atattributedString
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 fromlastResortResortAttributes
. If the final attributes matchlastResortResortAttributes
, the plain Python string will be returned.lastResortAttributes
should be created by sending attributes throughmakeLastResortAttributes
. 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.