/* * RSLMenuBar is a derivation of MenuBar for holding the top-level menus. All * of the PulldownMenu and MenuItem subclasses are also defined here. See the * users manual for a complete description of the command menus. * * Additional comments below describe the menu classes used in RSLMenuBar. */ #ifndef menusIncluded #define menusIncluded #include #include "std-macros++.h" #include "exception.h" #include "browser.h" #include "trans-interface.h" #include "entity.h" #include "strlist.h" #include "menudialogs.h" extern "C" bool IsMainListEmpty(); class RSLMenuBar; class FileMenu; class ModulesMenu; class ComponentsMenu; class InstancesMenu; class InstanceofMenu; class ParentsMenu; class OpsMenu; class InsMenu; class OutsMenu; class LinksMenu; class OptionsMenu; class TranslatorFlagsSubMenu; class CloseMenuItem; class ExposeMenuItem; class FileListSubMenu; class RSLBrowser; class FileDialog; class FileListDialog; class SearchDialog; class ParentsComponentMenuItem; class ParentsClassMenuItem; class TransInterface; class StateVisibleMenuBar; class TransientMenusMenuItem; class RSLMenuBar : public MonoScene { friend class TransientMenusMenuItem; public: RSLMenuBar(RSLBrowser* browser, TransInterface* ti, exception* exitExc); void InstallModules(EntityStructList* el); /* * Install a new set of names in the Modules pulldown. */ StateVisibleMenuBar* UpdateObjMenuBar(EntityStruct* es); /* * Update the menubar when an object is the newly selected entity. */ StateVisibleMenuBar* UpdateOpMenuBar(EntityStruct* es); /* * Update the menubar when an operation is the newly selected entity. */ StateVisibleMenuBar* UpdateModuleMenuBar(EntityStruct* es); /* * Return to the intial menubar when a module is the newly selected * (pseudo)entity. */ void UpdateFileMenuList(StrList* filenamelist); /* * Update the pullrighters used to list current open files (in File.Close * and File.Expose) (sort of). */ void AddToFileMenuList(const char* filename); void DeleteFromFileMenuList(const char* filename); void UpdateArgMenuList(int argc, char** argv); private: /* * Each of the UpdateXXX function changes the menu XXX in response to a * new entity selection made by the user. * * NOTE: at present these would just be one liners, so they're not used. * Mayber later. * ModulesMenu* UpdateModules(); ComponentsMenu* UpdateComponents(EntityStructList* el); InstancesMenu* UpdateInstances(); ParentsMenu* UpdateParents(); OpsMenu* UpdateOperations(); InsMenu* UpdateInputs(); OutsMenu* UpdateOutputs(); */ StateVisibleMenuBar* ComposeObjUpdates(); /* * After each indiv menu has been updated, put them in a menubar. If * transient menus mode is on, install only non-null menus. */ StateVisibleMenuBar* ComposeOpUpdates(); /* * As ComposeOpUpdates, but install ins and outs instead of ops menu. */ StateVisibleMenuBar* ComposeTransientObjUpdates(); /* * Little bro of ComposeObjUpdates(). */ StateVisibleMenuBar* ComposeTransientOpUpdates(); /* * Ibid. */ void Init(exception* exitExc); /* * Init all of the menus. Generally: * * File and Options menus have fixed format. * * Modules menu initially contains all modules found in command * line files. * * All other menus are initially empty. */ void InitPulldowns(exception* exitExc); void InitBars(); void InitScene(); void InitDialogs(); StateVisibleMenuBar* InitInit(); StateVisibleMenuBar* InitObj(); StateVisibleMenuBar* InitOp(); StateVisibleMenuBar* InitTransient(); FileMenu* InitFile(exception* exitExc); ModulesMenu* InitModules(); ComponentsMenu* InitComponents(); ParentsMenu* InitParents(); InstancesMenu* InitInstances(); InstanceofMenu* InitInstanceof(); OpsMenu* InitOperations(); InsMenu* InitInputs(); OutsMenu* InitOutputs(); LinksMenu* InitLinks(); OptionsMenu* InitOptions(); /* * Data members. */ /* * Alternate menubars; easier this way than trying to use Include(,int). */ StateVisibleMenuBar* initBar; StateVisibleMenuBar* objBar; StateVisibleMenuBar* opBar; StateVisibleMenuBar* transientBar; StateVisibleMenuBar* curBar; /* * Simple outer container for current menubar. */ HBox* box; /* * Pulldownmenus. */ FileMenu* file; ModulesMenu* modules; ComponentsMenu* components; ParentsMenu* parents; InstancesMenu* instances; InstanceofMenu* instanceof; OpsMenu* operations; InsMenu* inputs; OutsMenu* outputs; LinksMenu* links; OptionsMenu* options; /* * Pullright submenus. */ TranslatorFlagsSubMenu* transflagssubmenu; CloseMenuItem* closesubmenu; ExposeMenuItem* exposesubmenu; /* * Dialogs. */ FileDialog* fileDialog; FileListDialog* filelistDialog; SearchDialog* fsearchDialog; SearchDialog* bsearchDialog; SearchDialog* gsearchDialog; /* * Browser relatives. */ RSLBrowser* browser; TransInterface* ti; }; /* * StateVisibleMenuBar is necessary because the object-oriented, shared-state * programming paradigm is utterly f***ed. Here's the deal: * * (a) Items in a menubar share a common state, which is that of the menubar * itself. * (b) The proper activation of items within a menubar rely on this common * state in order to display the proper behavior. Viz., during button * down, traversing between the items should activate the items. Iv's * implementatin of this behavior relies on the shared state. * (c) If one item (i.e., pulldown) is included in more than one menubar, it * shares state only with other items in the last bar in which it was * included. I.e., it cannot share state with items in more than one * menubar, therefore it can only exhibit the proper behavior in one * menubar at a time. * (d) This problem could be fixed by putting new copies of items within * differenct menubars. However, this copying solution would be quite * painful and expensive in RSLMenuBar, particularly when transient menus * is enabled. * (e) The other solution, which is possible here because only one menubar is * visible at one time, is to change the state values of each menubar * item to the state of the currently visible menubar. * (f) In order to implement solution (e), we must subclass iv's MenuBar * class, since the state within is protected and there is no access * function provided. This is inconsistent with class Control which * does have public access and modify functions for the contained state. * * * And what's wrong with this, in case its' not obvious? In two words, it's * referentially opaque. In fact, it is probably the most referentially opaque * implmentation I have ever seen. To whit: * * (a) The fact that items in a menubar even have a state is three * inheritance levels and two files deep: * * MenuBar(in menu.h)->Menu(in menu.h)->Control(in control.h) * * (b) The fact that a menubar shares its state with the items within it is * buried in the implementation (menu.c:MenuBar::Include). There is no * way to determine this sharing from the specification. * * (c) The state-based implementation of menubar behavior is quite convoluted * (see control.c:Control::Enter and ::Leave). */ class StateVisibleMenuBar : public MenuBar { public: StateVisibleMenuBar() {} ControlState* GetState(); void FixStates(); }; /* * A NameListPulldownMenu is a pulldown with a private member that points to an * aux string list. The string list contains elems with an rsl name as data * and the symtab entry for the name as aux data. * * NameListMenuItem also contains a pointer back to the top-level browser * object for the purpose of accessing other elements of the display, and * for calling UpdateCurEntity. * * The NameListMenuItems that reside in a namelist pulldown contain pointers to * the individual string list elems. Specifically, the ith namelist menu item * contains a pointer to the ith elem in the aux string list pointed to by the * parent namelist pulldown. This threading is done to facilitate reasonably * efficient retrieval of src loc info for the names listed as items of the * pulldown. */ class NameListPulldownMenu : public PulldownMenu { public: NameListPulldownMenu(const char* name, RSLBrowser* browser); NameListPulldownMenu* InstallNames(EntityStructList* names); /* * Cruise the given str list and install the names. */ /* ClearScene(); */ int Size() { return namelist->Len(); } protected: EntityStructList* namelist; RSLBrowser* browser; }; class NameListMenuItem : public MenuItem { public: NameListMenuItem(const char* name, EntityStruct* es, RSLBrowser* browser); virtual void Do(); protected: EntityStruct* es; RSLBrowser* browser; }; /* * Here are all of the top-level pulldown menus. */ class FileMenu : public PulldownMenu { public: FileMenu(char* name) : PulldownMenu(name) {} }; class FileListSubMenu : public PullrightMenu { public: FileListSubMenu(const char* name) : PullrightMenu(name) {} }; class ModulesMenu : public NameListPulldownMenu { public: ModulesMenu(const char* name, RSLBrowser* browser) : NameListPulldownMenu(name, browser) {} ModulesMenu* InstallNames(EntityStructList* newnames); private: bool ChkMain(EntityStruct* es); }; class ComponentsMenu : public NameListPulldownMenu { public: ComponentsMenu(const char* name, RSLBrowser* browser) : NameListPulldownMenu(name, browser) {} }; class ParentsMenu : public NameListPulldownMenu { public: ParentsMenu(const char* name, RSLBrowser* browser) : NameListPulldownMenu(name, browser) {} }; class InstancesMenu : public NameListPulldownMenu { public: InstancesMenu(const char* name, RSLBrowser* browser) : NameListPulldownMenu(name, browser) {} }; class InstanceofMenu : public NameListPulldownMenu { public: InstanceofMenu(const char* name, RSLBrowser* browser) : NameListPulldownMenu(name, browser) {} }; class OpsMenu : public NameListPulldownMenu { public: OpsMenu(const char* name, RSLBrowser* browser) : NameListPulldownMenu(name, browser) {} }; class InsMenu : public NameListPulldownMenu { public: InsMenu(const char* name, RSLBrowser* browser) : NameListPulldownMenu(name, browser) {} }; class OutsMenu : public NameListPulldownMenu { public: OutsMenu(const char* name, RSLBrowser* browser) : NameListPulldownMenu(name, browser) {} }; class LinksMenu : public PulldownMenu { public: LinksMenu(const char* name, RSLBrowser* browser); LinksMenu* InstallNames(EntityStructList* links); int Size() { return namelist->Len(); } protected: EntityStructList* namelist; RSLBrowser* browser; }; class OptionsMenu : public PulldownMenu { public: OptionsMenu(const char* name) : PulldownMenu(name) {} }; class TranslatorFlagsSubMenu : public PullrightMenu { public: TranslatorFlagsSubMenu(const char* name) : PullrightMenu(name) {} }; class CloseSubMenuMenuItem : public MenuItem { public: CloseSubMenuMenuItem(const char* name, RSLBrowser* browser); ~CloseSubMenuMenuItem(); void Do(); private: char* name; RSLBrowser* browser; }; class ExposeSubMenuMenuItem : public MenuItem { public: ExposeSubMenuMenuItem(const char* name, RSLBrowser* browser, CloseSubMenuMenuItem* sibling); ~ExposeSubMenuMenuItem(); void Do(); const char* GetName(); CloseSubMenuMenuItem* GetSibling(); private: char* name; CloseSubMenuMenuItem* sibling; RSLBrowser* browser; }; /* * File menu items. */ class OpenMenuItem : public MenuItem { public: OpenMenuItem(RSLBrowser* browser, FileDialog* dialog); void Do(); private: char* prevopenfile; RSLBrowser* browser; FileDialog* dialog; }; class CloseMenuItem : public FileListSubMenu { public: CloseMenuItem(RSLBrowser* browser) : FileListSubMenu("Close ->") {this->browser = browser;} private: RSLBrowser* browser; FileListDialog* dialog; /* Dormant */ }; class ExposeMenuItem : public FileListSubMenu { public: ExposeMenuItem(RSLBrowser* browser) : FileListSubMenu("Expose ->") {this->browser = browser;} private: RSLBrowser* browser; FileListDialog* dialog; /* Dormant */ }; class SaveMenuItem : public MenuItem { public: SaveMenuItem(RSLBrowser* browser); void Do(); private: RSLBrowser* browser; }; class SaveAsMenuItem : public MenuItem { public: SaveAsMenuItem(RSLBrowser* browser, FileDialog* dialog); void Do(); private: const char* prevsavedfile; RSLBrowser* browser; FileDialog* dialog; }; class SaveAllMenuItem : public MenuItem { public: SaveAllMenuItem(RSLBrowser* browser); void Do(); private: RSLBrowser* browser; }; class RescanMenuItem : public MenuItem { public: RescanMenuItem(RSLBrowser* browser); void Do(); private: RSLBrowser* browser; }; class SearchForwMenuItem : public MenuItem { public: SearchForwMenuItem(RSLBrowser* browser, SearchDialog* dialog); void Do(); private: RSLBrowser* browser; SearchDialog* dialog; }; class SearchBackMenuItem : public MenuItem { public: SearchBackMenuItem(RSLBrowser* browser, SearchDialog* dialog); void Do(); private: RSLBrowser* browser; SearchDialog* dialog; }; class GotoLineMenuItem : public MenuItem { public: GotoLineMenuItem(RSLBrowser* browser, SearchDialog* dialog); void Do(); private: RSLBrowser* browser; SearchDialog* dialog; }; class QuitMenuItem : public MenuItem { public: QuitMenuItem(RSLBrowser* browser, exception* exitExc); void Do(); private: RSLBrowser* browser; exception* exitExc; }; class TestMenuItem : public MenuItem { public: TestMenuItem(RSLBrowser* browser); void Do(); private: RSLBrowser* browser; }; /* * The menu items for pulldowns that contain name lists are declared uniformly * as NameListMenuItems. These are: Modules, Components, Parents, Instances, * Instanceof, Ops, Ins, Outs, and the Links submenuts. The implementation of * each may be a little different, but the decls are the same. */ class ModulesMenuItem : public NameListMenuItem { public: ModulesMenuItem(char* name, EntityStruct* es, RSLBrowser* browser) : NameListMenuItem(name, es, browser) {}; void Do(); }; class ComponentsMenuItem : public NameListMenuItem { public: ComponentsMenuItem(char* name, EntityStruct* es, RSLBrowser* browser) : NameListMenuItem(name, es, browser) {}; void Do(); }; class ParentsMenuItem : public NameListMenuItem { public: ParentsMenuItem(char* name, EntityStruct* es, RSLBrowser* browser) : NameListMenuItem(name, es, browser) {}; void Do(); }; class InstancesMenuItem : public NameListMenuItem { public: InstancesMenuItem(char* name, EntityStruct* es, RSLBrowser* browser) : NameListMenuItem(name, es, browser) {}; void Do(); }; class InstanceofMenuItem : public NameListMenuItem { public: InstanceofMenuItem(char* name, EntityStruct* es, RSLBrowser* browser) : NameListMenuItem(name, es, browser) {}; void Do(); }; class OpsMenuItem : public NameListMenuItem { public: OpsMenuItem(char* name, EntityStruct* es, RSLBrowser* browser) : NameListMenuItem(name, es, browser) {}; void Do(); }; class InsMenuItem : public NameListMenuItem { public: InsMenuItem(char* name, EntityStruct* es, RSLBrowser* browser) : NameListMenuItem(name, es, browser) {}; void Do(); }; class OutsMenuItem : public NameListMenuItem { public: OutsMenuItem(char* name, EntityStruct* es, RSLBrowser* browser) : NameListMenuItem(name, es, browser) {}; void Do(); }; /* * Link menu items are each pullrighters, with LinkNameListMenuItems as items. */ class LinksMenuItem : public PullrightMenu { public: LinksMenuItem(const char* name, RSLBrowser* browser); LinksMenuItem* InstallNames(EntityStructList* names, char* parentname); /* * Just like NameListMenuItem::InstallNames with the exception of passing * parentname, which is used to determine if the link is a picture or * not. */ /* ClearScene(); */ private: EntityStructList* namelist; RSLBrowser* browser; }; /* * A LinkNameListMenuItem is a NameListMenuItem, with the addition of field * that indicates whether the item is a picture link. This field is used when * following a link to determine whether the link leads to an entity in the * text browser or a picture in the graphic browser. See the implemenation of * LinkNameListMenuItem::Do. */ class LinkNameListMenuItem : public NameListMenuItem { public: LinkNameListMenuItem(const char* name, EntityStruct* es, RSLBrowser* browser, char* parentname); /* * A la NameListMenuItem constructor, with the addition of setting * isGraphic member based on value of parentname. Viz., if parentname * is "picture" then isGraphic is set to true, else false. */ virtual void Do(); private: bool isGraphic; }; /* * A ToggleMenuItem is a specialization of MenuItem that contains a couple * strings that indicate its toggle states. As the item is selected, the text * of its name changes by appending the other of the toggle states. In this * way, the name of the currently displayed state is opposite of the current * state value. */ class ToggleMenuItem : public MenuItem { public: ToggleMenuItem(char* str, char* state0Val, char* state1Val, bool prependVal = false, bool initState = false, RSLBrowser* browser = null); protected: RSLBrowser* browser; void Toggle(); /* * Toggle state and displayed name. */ private: bool state; /* false => state0 is current */ bool prepend; /* true => prepend state name; false => append it */ char* name; /* base string value */ char* fullname; /* name with current state {pre,ap}pended */ char* state0; /* string value for state 0 */ char* state1; /* string value for state 1 */ void DisplayName(); }; /* * Options menu items. */ class EditBrowseModeMenuItem : public ToggleMenuItem { public: EditBrowseModeMenuItem(RSLBrowser* browser) : ToggleMenuItem("Edit Mode","Off","On",false,false,browser) {}; void Do(); }; class TransientMenusMenuItem : public ToggleMenuItem { public: TransientMenusMenuItem(RSLBrowser* browser, RSLMenuBar* parent) : ToggleMenuItem("Transient Menus","Off","On",false,false,browser) {this->parent = parent;} void Do(); private: RSLMenuBar* parent; }; class AutoGraphicsMenuItem : public ToggleMenuItem { public: AutoGraphicsMenuItem(RSLBrowser* browser) : ToggleMenuItem("Auto Graphics","Off","On",false,false,browser) {}; void Do(); }; class TranslatorFlagsMenuItem : public TranslatorFlagsSubMenu { public: TranslatorFlagsMenuItem(RSLBrowser* browser) : TranslatorFlagsSubMenu("Translator Flags ->") {this->browser = browser;} private: RSLBrowser* browser; }; class RedrawMenuItem : public MenuItem { public: RedrawMenuItem(RSLBrowser* browser) : MenuItem("Redraw") {this->browser = browser;}; void Do(); private: RSLBrowser* browser; }; #endif