Skip to content
AP Orlebeke edited this page Nov 27, 2019 · 9 revisions

Index

Segmented Controls

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.

Organization Models

Option #1: Organize based on documentation

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.

Option #2: Organize based on app preference menu

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.

Creating Segmented Controls

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>

Core Components

Segmented controls are similar to the format of individual preferences in that:

  1. They must have a defined pfm_name
  2. 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.

Menu Names & Ordering Menus

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:

Example Menu Structure

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.

Organizing Preferences into Menus

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!

Example Menu Name Mismatch

Ordering Preferences in Menus

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>

Nested Segmented Controls