-
Notifications
You must be signed in to change notification settings - Fork 149
Segmented Controls
Index
When you have a profile payload with a long list of preferences, it can be difficult to find the one(s) you're looking for.
Segmented controls allow you to separate and organize similar preferences together, and which helps users more easily find desired preferences.
There are a few different approaches to how segmented controls can be organized to make it easy for others to find.
Typically, apps that have a large number of available preferences already have detailed documentation on what they do. As such, many of these apps already have a corresponding organization scheme, which can be used in the ProfileCreator manifest.
The benefit of this method is that preference organization in ProfileCreator exactly mirrors the documentation. Furthermore, the documentation may have filters and search tools specifically designed to help users find applicable preferences.
To likewise help ProfileCreator users access this detailed documentation, it is recommended to use the
pfm_documentation_url
key within manifests to provide a button in the GUI to get to it.
However, apps that have well-documented preferences, but don't have many of them, may benefit more from option #2.
When the app in question has only a few documented preferences, no documentation at all, but supports profile-based preference management, the next best option is to refer to how preferences are organized within the app's preference menu (typically accessed with this keyboard shortcut: ⌘ + ,
)
This way as long as someone knows where the preference lives in the application preferences they can quickly find it in ProfileCreator.
The below XML dictionary is to serve as a reference point for subsequent discussions on the structure of segmented controls.
<dict>
<key>pfm_name</key>
<string>PFC_SegmentedControl_0</string>
<key>pfm_range_list_titles</key>
<array>
<string>Menu 1</string>
<string>Menu 2</string>
<string>Menu 3</string>
</array>
<key>pfm_require</key>
<string>always</string>
<key>pfm_segments</key>
<dict>
<key>Menu 1</key>
<array>
<string>Preference1</string>
<string>Preference2</string>
</array>
<key>Menu 2</key>
<array>
<string>Preference3</string>
</array>
<key>Menu 3</key>
<array>
<string>Preference4</string>
</array>
</dict>
<key>pfm_type</key>
<string>string</string>
</dict>
<! -- start of preferences -->
<dict>
<key>pfm_name</key>
<string>Preference1</string>
<key>pfm_subkeys</key>
<array>
<dict>
<key>pfm_type</key>
<string>string</string>
</dict>
</array>
<key>pfm_title</key>
<string>Preference 1</string>
<key>pfm_type</key>
<string>array</string>
</dict>
<dict>
<key>pfm_name</key>
<string>Preference2</string>
<key>pfm_title</key>
<string>Preference 2</string>
<key>pfm_type</key>
<string>boolean</string>
</dict>
<dict>
<key>pfm_description</key>
<string>A description</string>
<key>pfm_name</key>
<string>Preference4</string>
<key>pfm_title</key>
<string>Preference 4</string>
<key>pfm_type</key>
<string>boolean</string>
</dict>
<dict>
<key>pfm_description</key>
<string>Another description</string>
<key>pfm_name</key>
<string>Preference3</string>
<key>pfm_title</key>
<string>Preference 3</string>
<key>pfm_type</key>
<string>boolean</string>
</dict>
Segmented controls are similar to the format of individual preferences in that:
- They must have a defined
pfm_name
- They must have a defined
pfm_type
While the pfm_name
can be anything, the structure used by many manifests is PFC_SegementedControl_<unique_name>
The pfm_type
of segmented controls will always be string
.
Unlike the majority of preferences however, the segmented control must also include a pfm_require
key with a value of always
.
To create different menus or tabs, the pfm_range_list_titles
key is used. Each menu name is defined as a string within this array.
The order of menus (left to right) is determined by the order of the menu names in the pfm_range_list_titles
array. As a result, to order menus alphabetically these must be listed in the array in alphabetical order.
Using the example XML above, it would look like:
Menu names must also be listed in the pfm_segments
dictionary, where each menu has its own array of strings for defining preferences to be listed within each menu.
It's very important that the desired menu names in both pfm_range_list_titles
and pfm_segments
match.
While not required, it is recommended to have the order of each menu's array in pfm_segments
to match the order of menu names in pfm_range_list_titles
.
To organize preferences under one of the available menus, the pfm_segments
key is used. This dictionary should contain an array of strings for each menu. Each array should have a key name that matches the menu name entered in pfm_range_list_titles
. Refer to the example XML.
Each preference within the array for the desired menu should have its key name listed as specified in the preference's pfm_name
.
While not required, it is strongly recommended to organize preferences in each array within pfm_segments
in alphabetical order. Know that the order of preferences as listed in pfm_segments
does not affect the actual order of preferences within the menu. See ordering preferences for information.
Important note: Each array of strings key within pfm_segments
must exactly match menu names as defined in pfm_range_list_titles
. If one of the menu names do not match, all preferences meant to be listed within other menus will also appear in the non-matching menu name.
In the example image below, the menu name - Menu 1
- is instead listed as Menu1
in pfm_segments
. Spaces matter!
How preferences are ordered in the GUI is not a function of the preference order as listed in pfm_segments
. Preference order is determined by the order of the actual preferences themselves listed in the manifest.
In the example XML, Preference4
is listed before Preference3
. While this ordering isn't visible within in the GUI because they are organized under different menus, this ordering does become apparent in the previous example where there is a mismatching menu name in pfm_range_list_titles
and pfm_segments
.
It is strongly recommended to order preferences displayed within the same menu in a group together. Especially for manifests with many preferences and many menus, if preferences are not grouped together it can be challenging for others to make contributions and maintain the desired preference ordering.
Expanding on the XML example but trimmed to show only relevant info:
<! -- Menu 1 Preferences -->
<dict>
...
<key>pfm_name</key>
<string>Preference1</string>
...
</dict>
<dict>
...
<key>pfm_name</key>
<string>Preference2</string>
...
</dict>
<! -- Menu 3 Preferences -->
<dict>
...
<key>pfm_name</key>
<string>Preference4</string>
...
</dict>
<! -- Menu 2 Preferences -->
<dict>
...
<key>pfm_name</key>
<string>Preference3</string>
...
</dict>