Skip to content

Adding Menu Items to the WED Menu Bar

Ted N. Greene edited this page Jun 6, 2016 · 1 revision

Adding Menu Items to the WED Menu Bar

Relevant files

  • WED_Menus.h
  • WED_Menus.cpp
  • WED_DocumentWindow.cpp
  • YourAction.h/cpp

We'll use WED_Airport and WED_MetadataUpdate for concrete examples.

The Basics

1. WED_Menus.h - Add an new entries to the enum

The enum at the top of WED_Menus is a list of every menu item in WED. Add an entry to this enum.

  • The enum is organized by groups of similar actions, which submenus they will appear under, in their order in menus
  • All entries are placed here, regardless of what level of submenu they will appear in
  • The naming convention is wed_CamelCase

Here are the entries for adding a metadata key and opening the Update Metadata dialogue box.

enum {
//...
wed_AddMetadataCity,
wed_AddMetadataCountry,
wed_AddMetadataFAA,
wed_AddMetadataIATA,
wed_AddMetadataICAO,
wed_AddMetadataState,
wed_UpdateMetadata,
//...
};

2. WED_Menus.cpp - Add to a GUI_MenuItem_t array

First let's go over the members of GUI_MenuItem_t (found in GUI_Defs.h):

const char * name

  • Name shown in GUI
  • If set to "-" a separator is created instead
  • Placing an & before a letter underlines that letter for menu navigation through keyboard use. Only one per name is allowed

char key

  • The key shown next to the name
  • Does not have to be the same as the &'d letter in the menu item's name
  • Optional and is only used when modifier keys also need to be pressed (their names will be appended to it)

GUI_KeyFlags flags

  • Which modifier keys (Shift, Ctrl, Alt) need to be pressed as well
  • Optional

int checked

  • If true (1) the behaviour of the menu item is a toggle button, shown with a check mark
  • Always set to 0 in WED_Menus.cpp

int cmd

  • The corresponding menu entry declared in WED_Menus.h

Optional members not in use are marked with a 0.

Ex: kAirportMenu array

static const GUI_MenuItem_t kAirportMenu[] = {
{"&Create Airport",'A', gui_ControlFlag+gui_ShiftFlag, 0, wed_CreateApt},
//...
{"Add &Metadata",   0, 0, 0, 0},
{"Update Metadata", 0, 0, 0, wed_UpdateMetadata},
//...
{"-",               0, 0, 0, 0},
{NULL,              0, 0, 0, 0}
};
  • With &Create Airport we can see examples of using the &, key name, and defining flags
  • The last member of a Menu array is always completely NULL
  • "Add &Metadata" is the top of a submenu, it gets 0 for its cmd entry (we'll come back to this.)
  • Note how the menu is well aligned for easy reading

Adding "Update Metadata", our simple case

After adding {"Update Metadata", 0, 0, 0, wed_UpdateMetadata} we need to make WED_CanDoUpdateMetadata and WED_DoUpdateMetadata.

3. YourAction.h/cpp - Declare and define WED_CanMyAction and WED_DoMyAction

Deceleration and Implementation Semantics

WED_CanMyAction and WED_DoMyAction are not inherited members or part of an interface; they only follow conventions.

  • They can be placed in any header. Many are put in WED_GroupCommands.h/cpp
  • Parameters are up to the programmer
  • WED_CanMyAction should
    • return true(1) or false(0)
    • be very inexpensive to call
    • not have side effects
  • WED_DoMyAction should
    • be where code to perform your action goes
    • use asynchronous code for very slow operations

Ex: UpdateMetadata

int WED_CanUpdateMetadata(IResolver * resolver);
C++ void WED_DoUpdateMetadata(IResolver * resolver);
  • WED_CanUpdateMetadata returns true if the current selection is exactly one airport, false if not
  • WED_DoUpdateMetadata opens a dialog box which preforms the action

4. WED_DocumentWindow - Include calls in CanHandleCommand and HandleCommand

GUI_Commanders, such as DocumentWindow and StartWindow, have two important methods

  • int CanHandleCommand(int command, string& ioName, int& ioCheck)
  • void HandleCommand(int command)

For windows, CanHandleCommand is polled to determine which menu options will be selectable. HandleCommand is called when a menu option has been clicked. For both, simply add a case in the large switch statement.

CanHandleCommand entries are in the form of case wed_MyAction: return WED_CanMyAction();

Ex: WED_DocumentWindow

int WED_DocumentWindow::CanHandleCommand(int command, string& ioName, int& ioCheck)
{
//...
//--Add Meta Data Sub Menu-----------------
case wed_AddMetaDataCity:    return WED_CanAddMetaData(mDocument, command);
case wed_AddMetaDataCountry: return WED_CanAddMetaData(mDocument, command);
case wed_AddMetaDataFAA:     return WED_CanAddMetaData(mDocument, command);
case wed_AddMetaDataIATA:    return WED_CanAddMetaData(mDocument, command);
case wed_AddMetaDataICAO:    return WED_CanAddMetaData(mDocument, command);
case wed_AddMetaDataState:   return WED_CanAddMetaData(mDocument, command);
//----------------------------------------
case wed_UpdateMetadata:     return WED_CanUpdateMetadata(mDocument);
//...
}

HandleCommand entries are in the form of case wed_MyAction: WED_DoMyAction(); return 1;

Ex: WED_DocumentWindow::HandleCommand

int WED_DocumentWindow::HandleCommand(int command)
{
//...
//--Add Meta Data Sub Menu-----------------
case wed_AddMetaDataCity:	 WED_DoAddMetaData(mDocument, "City/Locality"); return 1;
case wed_AddMetaDataCountry: WED_DoAddMetaData(mDocument, "Country"); return 1;
case wed_AddMetaDataFAA:	 WED_DoAddMetaData(mDocument, "FAA Code"); return 1;
case wed_AddMetaDataIATA:	 WED_DoAddMetaData(mDocument, "IATA Code"); return 1;
case wed_AddMetaDataICAO:	 WED_DoAddMetaData(mDocument, "ICAO Code"); return 1;
case wed_AddMetaDataState:	 WED_DoAddMetaData(mDocument, "State/Province"); return 1;
//----------------------------------------
case wed_UpdateMetadata: WED_DoUpdateMetadata(mDocument); return 1;
//...
}

5. You're done! Test it out in WED!

(Side Tutorial) Making a Sub-Menu

This side tutorial assumes you have reviewed the above.

1. WED_Menus.h - Add enum entries

  • Do not make an enum entry for the item that will drop down the submenu
  • There are no special naming conventions for menu items placed in a submenu

2. WED_Menus.cpp - Make a new GUI_MenuItem_t array

  • Each menu is defined by a const GUI_MenuItem_t menu
  • Populate it with entries for each of your submenus
  • The naming convention is kCamelCaseMenu

Ex: Add Meta Data submenu

static const GUI_MenuItem_t kAddMetaDataMenu[] = {
{"ICAO Code",      0, 0, 0, wed_AddMetaDataIATA },
{"IATA Code",      0, 0, 0, wed_AddMetaDataICAO },
{"FAA  Code",      0, 0, 0, wed_AddMetaDataFAA },
{"City/Locality",  0, 0, 0, wed_AddMetaDataState },
{"State/Province", 0, 0, 0, wed_AddMetaDataCity },
{"Country",        0, 0, 0, wed_AddMetaDataCountry},
{NULL,             0, 0, 0, 0 }
};

3. WED_Menus.cpp - Make a menu item to drop down the new submenu

A submenu item does not have a cmd.

Ex: "Add &Metadata" inside of kAirportMenu

{"Add &Metadata", 0, 0, 0, 0 },

4. WED_Menus.cpp - Create the submenu

Inside WED_MakeMenus(GUI_Application * inApp) call GUI_Application::CreateMenu.

  • Pass in a name, follows same rules as GUI_MenuItem_t::name
  • Pass in the new GUI_MenuItem_t array
  • Pass in the parent GUI_MenuItem_t array
  • Pass in the hard coded index of the cmd-less menu item in the parent array

Ex: kAddMetadataMenu

void WED_MakeMenus(GUI_Application * inApp)
{
//...
GUI_Menu airport_menu = inApp->CreateMenu(
	"&Airport", kAirportMenu, inApp->GetMenuBar(), 0);

 GUI_Menu airport_add_meta_data_menu = inApp->CreateMenu(
	"Add &Meta Data", kAddMetaDataMenu, airport_menu,6);//This hard coded 6 is a reference to kAirportMenu[6]
//...
}

One still has to declare, define, and implement WED_CanMySubAction and WED_DoMySubAction, and hook into CanHandleCommand/HandleCommand.

5. You're done!