Extending The User Interface

Once a plugin has been loaded it will normally extend or modify the application user interface in some way by adding new elements such as menu items or toolbar buttons.

On activation a plugin will receive a reference to the application main form from which it can access the main user interface elements:

mainForm.MainMenu
mainForm.MainToolbar
mainForm.StatusBar

Working with the user interface requires a knowledge of Windows Forms techniques but the modular nature of QuickSharp applications introduces some extra complexity.

Menus

Plugins can add new menu and toolbar items simply by adding them to the main menu and toolbar objects accessed from the main form. To simplify this QuickSharp provides the MenuTools helper class which can be used to create menu and toolbar items in single statements. The following example illustrates adding a menu item.

ToolStripMenuItem toolMenu = mainForm.GetMenuItemByName(
    QuickSharp.Core.Constants.UI_TOOLS_MENU);

int index = toolMenu.DropDownItems.IndexOfKey(
    QuickSharp.Core.Constants.UI_TOOLS_MENU_OPTIONS);

if (index == -1) index = 0;

ToolStripMenuItem item = MenuTools.CreateMenuItem(
    "ExampleMenuItem", "Example Menu Item",
    null, Keys.None, null, ExampleMenuItem_Click, true);

toolMenu.DropDownItems.Insert(index, item);

A new menu item is created and added to the main Tools menu in the position before the existing Options item. Note how the Tools menu is retrieved and the insert location determined; if it isn't found the new item is inserted at the top of the menu.

The positioning of menu items (and toolbar buttons) is influenced by the order in which plugins are loaded. If two independent plugins both add items to the same menu the order in which the items appear can change as other plugin dependencies affect their loading order.

When inserting new menu items care must be also taken that the reference points chosen, in this case the Options item, will always be present when the new item is added. In this case it is a safe bet as the Options item is supplied by the core and should be present in every application. In other cases, particularly when extending menu groups provided by other plugins, use plugin dependencies to ensure that the required menus are loaded before attempting to use them as reference points for new items.

It is common practice to separate groups of menu items to provide visual association of related functions. However, manually inserting separators into menus can create inconsistent layouts and cause duplicated or missing separators if several plugins attempt to create a single group of items.

A more elegant way to separate items is to set a flag on a menu item indicating that it should be followed by a separator. This can be added explicitly to the menu item by setting its Tag property:

item.Tag = new ToolStripItemTag() { IncludeSeparator = true };

Or can be set by passing 'true' as the final parameter in the MenuTools method as in the example above.

Menu separators are created only when all plugins have been loaded; the core will 'walk' the menu tree and add separators where they are indicated. This allows separators to be placed after a menu item without the risk of additional items becoming inserted between them. It is good practice to complete any group of related menu items with a separator. If the group appears at the end of a menu the final separator will be automatically removed.

Toolbars

Like menus, extending the main toolbar is simple a matter of creating a new button and determining where to add it to the existing button collection. Again a MenuTools helper method is available to create the button, in this example the new button is simply added to the end of the toolbar.

ToolStripButton button = MenuTools.CreateToolbarButton(
    "ExampleToolbarButton", "Example Toolbar Button",
    Resources.ButtonImage, ExampleToolbarButton_Click, true);

mainForm.MainToolbar.Items.Add(button);

As with menus, toolbar separators can be added by setting a flag on the button object. In this example the final parameter is set to true to indicate that a separator is required. To preserve the correct order the separator is only added once all plugins have been loaded; in this case the separator is added before the button meaning that for groups of buttons the separator should be added to the first button.

Status bar

Once the status bar has been accessed from its main form property it can be modified using any Windows Forms technique applicable to a status bar control. QuickSharp does not provide any special facilities for this but does provide access to the status bar text message.

To set this text use the StatusBarMessage property of the MainForm class or the SetStatusBarMessage helper methods.

mainForm.StatusBarMessage = "Ready";
mainForm.SetStatusBarMessage("Ready");
mainForm.SetStatusBarMessage("Ready", 5);

The helper function accepts an optional second parameter which is a timeout in seconds. When this expires the text message is cleared. Setting this to 0 will cause the message to be displayed permanently and is equivalent to omitting the parameter or using the text property directly.