The askMulti Dialog¶
When called in a UI-enabled environment the Python
fontforge.askMulti() method raises a modal dialog that prompts the
user to answer one or more questions, potentially organized into “categories”
displayed in separate tabs. It takes two parameters, title and specification.
The title parameter should be a string that will be displayed in the dialog
window title bar.
The specification paramter is either a Python list or dictionary object
specifying the questions. This is explained below.
Questions¶
There are four question types, corresponding to the single-question
fontforge.askString(), fontforge.askChoices(),
fontforge.openFilename(), and fontforge.saveFilename()
dialog methods. Each individual question is specified as a dictionary.
All question types use the keys type, question``, tag and align. The
type value specifies the type of question as outlined below.
The value corresponding to question is the label string, which is displayed
before the answer field. This key must be present but the value can be None
if no label is needed.
The tag is optional but either it or question must have a value. When
present its value will be used as the key corresponding to this question in the
result dictionary returned by the method. Otherwise the question value
will be used. The tag value can be any “hashable” type—that is, any type
that can serve as a key in a Python dictionary.
The align value must be boolean-evaluable (ideally True or False).
It indicates whether, when the dialog is being laid out, the label for this
question should be aligned with the other labels of the same category. When
absent the default is True. (This has no effect when the question value
is None, so if you want an aligned, empty label use a space as the
question value.)
String Questions¶
A string question displays the label followed by a text entry field. Its
type value must be “string”.
The only additional key for a string question is default, which is optional.
When the key present its value, which must be a string, will be the initial
value of the answer entry field. An example dictionary is:
{ 'type': 'string', 'question': 'Number of contours:',
'tag': 3, 'default': '4' }
Choice Questions¶
Choice questions ask the user to pick a subset of given answers. Its type
value must be “choice”. This question type has three additional dictionary
keys: answers, multiple, and checks.
The answers value must be a Python list of potential answers, each of which is
its own small dictionary. The keys to an answer dictionary are name, tag,
and default. The value of name must be the string the user will choose among.
The value of tag, when present, will be used to report the answer in the
result dictionary—when not present the name string will be used. Unlike the
question tag an answer tag value can be of any type whatsoever. The default
key is an optional key that must have a boolean-evaluable value. When True
the answer is selected when the dialog is presented.
The multiple value must be boolean-evaluable; when the key is absent the
default is False. It indicates whether the user must choose exactly one
answer or can choose multiple or, potentially, no answers. When multiple is
false there must be at most one answer for which default is True.
The checks value must also be boolean-evaluable and its default is also
False. By default a choice question is presented as in the
fontforge.askChoices() dialog, with a (potentially) scrolling
vertical list similar to pop-up menu. When checks is True and multiple
is False the answers are presented as radio buttons. When checks is True
and multiple is True the answers are presented as checkboxes. Radio
buttons and checkboxes allow better keyboard-based selection (see the
mnemonics section) and may have other advantages.
An example choice question dictionary is:
{ 'type': 'choice', 'question': 'What direction:',
'tag': 'direction', 'checks': True,
'answers': [ { 'name': 'Clockwise', 'tag': 'cw', 'default': True },
{ 'name': 'Counter-Clockwise', 'tag': 'ccw' } ]
}
Pathname Questions¶
The open pathname and save pathname questions have the respective type values
“openpath” and “savepath”. These differ from the
fontforge.openFilename() and fontforge.saveFilename()
methods in that they do not raise a file browser directly. Instead they display
an entry field, similar to a string question, followed by a button to raise a
browser, similar to the path-specifying entries in :doc:the preferences dialog
</ui/dialogs/prefs>. Each also has an optional default key for an initial
pathname value, and an optional filter key to specify a file filter. Both
must be strings. An example dictionary is:
{ 'type': 'openpath', 'question': 'Glif file:', 'tag': 'file',
'default': 'input.glif', 'filter': '*.glif' }
Categories¶
Questions are organized into categories. A category is a dictionary with
two keys: category and questions. The value of category should be a
either string to display to the user or None if no label is needed.
The value of questions must be a list of question dictionaries, as
described above. A category containing the dictionaries above looks like:
The Specification¶
The specification passed as the spec parameter can be any of:
A question dictionary
A list of question dictionaries
A category dictionary
A list of category dictionaries
In the last case each category will be given its own tab, with the category names selectable on the left side of the dialog. (Whenever there is only one category there is no list, even when the category has a name.)
The Return Value¶
When the user cancels the dialog, either with the “Cancel” button or
by closing the window, the askMulti method returns None. Otherwise
it returns a Python dictionary of results, one for each question. The
key will be the tag value or, if none was present, the question
string. For all question types other than “choice” the value is a
string. For a choice question where multiple is False the value
is the tag or name of the answer. For a multiple choice question
the value is a tuple of tag or name values. The tuple may be
empty.
A result dictionary for the collection above could be:
{3: '20', 'direction': 'ccw', 'file': '/tmp/in.glif'}
When the specification is invalid the method will throw a TypeError
or ValueError exception with information about the problem.