Tool Settings
'Tool Settings' refers to the App UI widget containing settings for the active tool. By default, the Tool Settings display in a bar at the top of the application window, but the widget can also be a floating dialog or docked into the left or right panel.
Tools have two options for populating the Tool Settings widget. The tool can register their own React-based ToolUiProvider to display the UI components for its settings. An alternate approach is for the tool to publish information about the properties it uses for settings and allow the 'DefaultToolSettings' provider to generate the necessary UI components.
Default ToolSettings Provider
Any Tool derived from Interactive tool can implement the method supplyToolSettingsProperties
to supply an array of DialogItem
objects that define the property definitions and its position with a grid layout. The DefaultToolSettings provider will then automatically generate a type editor for the type of data required and show that editor in the row and column specified. Unless suppressed via an EditorParams
, a label will be generated using the displayLabel
for the property and shown in the column to the left of the editor.
Example of Tool Defining properties to be shown in Tool Setting Zone
export class SampleToolWithSetting extends PrimitiveTool {
public static toolId = "SampleToolWithSetting";
// --- some code removed for brevity ---
// is set the tool uses specified length value, if not tool calculates value an reports it back to UI via syncLengthInUi
private _useLengthProperty: DialogProperty<boolean> | undefined;
public get useLengthProperty() {
if (!this._useLengthProperty)
this._useLengthProperty = new DialogProperty<boolean>(
PropertyDescriptionHelper.buildLockPropertyDescription("useLength"), false);
return this._useLengthProperty;
}
public get useLength(): boolean { return this.useLengthProperty.value; }
public set useLength(value: boolean) { this.useLengthProperty.value = value; }
// length value to be used by tool if useLength is true
private _lengthProperty: DialogProperty<number> | undefined;
public get lengthProperty() {
if (!this._lengthProperty)
this._lengthProperty = new DialogProperty<number>(new LengthDescription("length", "Length")),
0.1, undefined, !this.useLength);
return this._lengthProperty;
}
public get length(): number { return this.lengthProperty.value; }
public set length(value: number) { this.lengthProperty.value = value; }
// Called by UI code to get list of properties to display in Tool Setting zone
public supplyToolSettingsProperties(): DialogItem[] | undefined {
const toolSettings = new Array<DialogItem>();
this._lengthProperty.isDisabled = !this.useLength; // enable length field when checkbox is checked
const useLengthLock = this._useLengthProperty.toDialogItem({ rowPriority: 2, columnIndex: 0 });
toolSettings.push(this._lengthProperty.toDialogItem({ rowPriority: 2, columnIndex: 1 }, useLengthLock));
}
return toolSettings;
}
// Respond to user changes in the tool settings UI components
public async applyToolSettingPropertyChange(updatedValue: DialogPropertySyncItem): Promise<boolean> {
if (updatedValue.propertyName === this.useLengthProperty.name) {
this.useLength = updatedValue.value.value as boolean;
IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, this.useLengthProperty.item);
this.syncLengthState();
} else if (updatedValue.propertyName === this.lengthProperty.name) {
if (!updatedValue.value.value) {
this.syncLengthState(); // force UI to redisplay last valid value
return false;
}
this.length = updatedValue.value.value as number;
IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, this.lengthProperty.item);
return true;
}
return false;
}
// Refresh the UI with the latest values from the tool
private syncLengthInUi(): void {
this._lengthProperty.displayValue = (this.lengthProperty.description as LengthDescription).format(this.length);
this._lengthProperty.isDisabled = !this.useLength;
this.syncToolSettingsProperties([this.lengthProperty.syncItem]);
}
}
Example using ToolSettings helper methods to simplify setting up properties for Tool Settings UI
export class ToolWithSettings extends PrimitiveTool {
public static override toolId = "ToolWithSettings";
// --- some code removed for brevity ---
// ------------- use length toggle ---------------
private _useLengthProperty: DialogProperty<boolean> | undefined;
public get useLengthProperty() {
if (!this._useLengthProperty)
this._useLengthProperty = new DialogProperty<boolean>(PropertyDescriptionHelper.buildLockPropertyDescription("useLength"), false);
return this._useLengthProperty;
}
// ------------- Length (persisted in meters) ---------------
private _lengthProperty: DialogProperty<number> | undefined;
public get lengthProperty() {
if (!this._lengthProperty)
this._lengthProperty = new DialogProperty<number>(new LengthDescription("length"), 1.5, undefined, !this.useLengthProperty.value);
return this._lengthProperty;
}
/** Used to supply DefaultToolSettingProvider with a list of properties used to generate ToolSettings. If undefined then no ToolSettings will be displayed */
public override supplyToolSettingsProperties(): DialogItem[] | undefined {
this.initializeToolSettingPropertyValues([
this.useLengthProperty,
this.lengthProperty,
]);
const toolSettings = new Array<DialogItem>();
const lengthLock = this.useLengthProperty.toDialogItem({ rowPriority: 1, columnIndex: 0 });
toolSettings.push(this.lengthProperty.toDialogItem({ rowPriority: 2, columnIndex: 2 }, lengthLock));
return toolSettings;
}
/** Override to return the property that is disabled/enabled if the supplied property is a lock property. */
protected override getToolSettingPropertyLocked(property: DialogProperty<any>): DialogProperty<any> | undefined {
return (property === this.useLengthProperty ? this.lengthProperty : undefined);
}
/** Used to allow Tool to react to ToolSettings changes in UI */
public override async applyToolSettingPropertyChange(updatedValue: DialogPropertySyncItem): Promise<boolean> {
return this.changeToolSettingPropertyValue(updatedValue);
}
}
Informing Tool of property changes
When a user interacts with any of the generated type editors in the Tool Settings Widget, the changes are sent back to the active tool by calling its applyToolSettingPropertyChange
method, passing in the name of the changed property and the property's new value.
Informing the UI of property changes made by the Tool
If the 'Active' Tool updates a property that is being displayed by a type editor in the Tool Settings Widget, it can call its syncToolSettingsProperties
method and supply an array of DialogPropertySyncItem
objects to specify new values to display in the UI. This is commonly done when the Tool is in a dynamics loop and recalculating values to display in the UI.
Classes and Interfaces used the the Default Tool Settings Provider
The following classes defined within the appui-abstract package are used by the Default Tool Settings Provider.
- DialogItem
- PropertyRecord
- PropertyDescription
- DialogItemValue
- DialogPropertySyncItem
- EditorPosition
- PropertyEditorParamTypes
- PropertyValue
API Reference
Last Updated: 18 May, 2022