home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- CMultStdPopupPane.c for TCL 1.1.2 or earlier
-
- A subclass of CStdPopupPane that
- (1) allows for the same pop-up menu to be used twice independently
- at the same time, either within one window or in separate windows.
- (2) allows for pop-up menus whose titles do not invert. Thus, you
- may have a pop-up menu whose resource has the empty string for a
- title to effectively obtain a title-less pop-up menu.
-
- When you have one pop-up menu that is used more than once within one
- window, you must create a separate pseudo-menu id for each instance
- of the pop-up menu pane. This menu id should not correspond to the
- menu id of any menu resource your application uses. This class
- “tricks” the TCL into using the pseudo-menu id for the menu; it is
- this mechanism which allows several instances of the same menu to
- function independently.
-
- If you use this class, your program must not have any menus whose
- menu id is 5368. Menus that have been deactivated are set to this
- menu id (whose number has no special significance). This prevents
- the TCL from changing all instances of a pop-up menu pane that
- appears in several different windows when the settings on a single
- such pane are changed.
-
- This class relies on the inner workings of the CBartender class.
- Thus, if CBartender changes, this class may no longer work.
- This class does work in TCL v. 1.1. Future versions of the TCL
- may include functionality that duplicates this class’s.
-
- If you create an instance of this class in a window that is already
- activated, you must activate the menu manually so that it works
- correctly.
-
- SUPERCLASS = CStdPopupPane
-
- Copyright © 1993 Michael Abramowicz. All rights reserved.
-
-
- ******************************************************************************/
-
- #include "CMultStdPopupPane.h"
- #include "CBartender.h"
-
- extern CBartender *gBartender;
-
- /******************************************************************************
- IMultStdPopupPane
-
- Create a standard popup menu pane. Works just like IStdPopupPane, but
- (1) pass to pseudoMenuID the menu id you would like to use for the
- pop-up menu. This should equal menuID if and only if the pop-up pane
- appears no more than once within any given window. Otherwise,
- pseudoMenuID should be set to some other value not used by any other
- menu. For example, you might use 4000, 4001, and 4002 as pseudo
- IDs for three instances of the same pop-up.
- (2) if this menu does not include a title that should be inverted when
- the menu is selected, pass FALSE to the includeTitle parameter.
- Otherwise, pass TRUE to obtain the default behavior.
- ******************************************************************************/
-
- void CMultStdPopupPane::IMultStdPopupPane( short menuID, short pseudoMenuID,
- Boolean includeTitle, CView *anEnclosure, CBureaucrat *aSupervisor,
- short aWidth, short aHeight, short aHEncl, short aVEncl)
- {
- short oldIndex; /* bartender index number of menu with */
- /* same pseudoMenuID */
-
- // Prevent bartender confusion by ensuring there is no other
- // menu enabled with the same pseudo menu id
-
- oldIndex = gBartender->FindMenuIndex(pseudoMenuID);
- if (oldIndex != -1) /* Check for a menu already open with this id */
- ChangeMenuID(oldIndex, kDisabledMenuID);
- /* Temporarily disable that menu */
-
- // Call a separate routine to do the work of adding the menu
- // to the bartenders list.
-
- IMultStdPopupPaneX(menuID, pseudoMenuID);
-
- // Now we perform regular standard popup pane initialization passing
- // a temporary menu id. The initialization routine will realize the
- // menu has already been added to the bartender, and not try to
- // readd it.
-
- CPopupPane::IPopupPane( pseudoMenuID, TRUE, FALSE, anEnclosure,
- aSupervisor, aWidth, aHeight, aHEncl, aVEncl,
- sizFIXEDSTICKY, sizFIXEDSTICKY);
- IStdPopupPaneX( TRUE); /* do install menu hook */
- Disable();
-
- // In case a menu was temporarily disabled, reenable it
-
- if (oldIndex != -1)
- ChangeMenuID(oldIndex, pseudoMenuID);
- /* Restore the menu id of the identical menu
- that is currently active. */
- } /* CStdPopupPane::IStdPopupPane */
-
- /******************************************************************************
- IMultStdPopupPaneX
-
- Add the appropriate menu to the bartender so that the bartender recognizes
- it through its pseudo menu id.
- ******************************************************************************/
-
- void CMultStdPopupPane::IMultStdPopupPaneX( short menuID, short pseudoMenuID)
- {
- short oldIndex, /* bartender index number of menu with menuID */
- newIndex; /* bartender index of new menu */
-
- // Prevent bartender confusion by ensuring there is no other
- // menu enabled with the same menu id
-
- oldIndex = gBartender->FindMenuIndex(menuID);
- if (oldIndex != -1) /* Check for a menu already open with this id */
- ChangeMenuID(oldIndex, kDisabledMenuID);
- /* Temporarily disable that menu */
-
- // Add the menu to the bartender.
-
- gBartender->AddMenu(menuID, FALSE, 0);
- /* Do not install menu in the menu list. */
- itsMacMenu = gBartender->FindMacMenu(menuID);
- /* Store a handle to the Toolbox menu record
- in an instance variable */
- DetachResource(itsMacMenu);
- /* Detach the menu resource from the resource fork
- so that additional copies of the Toolbox menu
- record can be kept for other menus. */
-
- // Change the menu’s ID to the pseudo ID
-
- newIndex = FindItsMenuIndex();
- /* Locate menu index based on handle to Toolbox
- menu record. */
- ChangeMenuID(newIndex, pseudoMenuID);
- /* Change the bartender’s information on the
- menu ID as well as the ID stored within the
- Toolbox menu record. */
-
- // In case a menu was temporarily disabled, reenable it
-
- if (oldIndex != -1)
- ChangeMenuID(oldIndex, menuID);
- /* Restore the menu id of the identical menu
- that is currently active. */
-
- // Record the pseudo menu id in an instance variable,
- // so that menu can be enabled and disabled properly.
- itsPseudoMenuID = pseudoMenuID;
-
- }
-
- /******************************************************************************
- IViewTemp {OVERRIDE}
-
- Create a standard popup menu pane from a view template
- ******************************************************************************/
-
- void CMultStdPopupPane::IViewTemp( CView *anEnclosure, CBureaucrat *aSupervisor,
- Ptr viewData)
- {
- MultStdPopupTemp *template = (MultStdPopupTemp*) viewData;
- short oldIndex; /* bartender index number of menu with */
- /* same pseudoMenuID */
- short menuID = template->stdPopupTemp.popupTemp.menuID,
- pseudoMenuID = template->pseudoMenuID;
-
- // Prevent bartender confusion by ensuring there is no other
- // menu enabled with the same pseudo menu id
-
- oldIndex = gBartender->FindMenuIndex(pseudoMenuID);
- if (oldIndex != -1) /* Check for a menu already open with this id */
- ChangeMenuID(oldIndex, kDisabledMenuID);
- /* Temporarily disable that menu */
-
- // Set instance variables and add the new menu to
- // the bartender.
-
- doInvertTitle = template->titlesVisible;
- IMultStdPopupPaneX( menuID, pseudoMenuID);
-
- // Initialize the pop-up menu class, skipping over
- // the immediate super-class so that the hook is
- // installed correctly.
-
- template->stdPopupTemp.popupTemp.menuID = itsPseudoMenuID;
- if (template->stdPopupTemp.hAutosizing)
- template->stdPopupTemp.popupTemp.paneTemp.width = kAutoSize;
- if (template->stdPopupTemp.vAutosizing)
- template->stdPopupTemp.popupTemp.paneTemp.height = kAutoSize;
- CPopupPane::IViewTemp( anEnclosure, aSupervisor, viewData);
- IStdPopupPaneX( TRUE); /* do install menu hook */
- Disable();
-
- // In case a menu was temporarily disabled, reenable it
-
- if (oldIndex != -1)
- ChangeMenuID(oldIndex, pseudoMenuID);
- /* Restore the menu id of the identical menu
- that is currently active. */
-
- } /* CMultStdPopupPane::IViewTemp */
-
- /******************************************************************************
- InvertTitle
-
- Invert the popup title if this popup pane includes a title.
- ******************************************************************************/
-
- void CMultStdPopupPane::InvertTitle(void)
- {
- if (doInvertTitle)
- inherited::InvertTitle();
-
- } /* CMultStdPopupPane::InvertTitle */
-
- /******************************************************************************
- Activate
-
- Enable the menu before activating it so that the bartender can recognize
- it again.
- ******************************************************************************/
-
- void CMultStdPopupPane::Activate( void)
- {
- Enable();
- inherited::Activate();
- } /* CPopupPane::Activate */
-
- /******************************************************************************
- Deactivate
-
- Disable the menu after deactivating it, so that if the bartender tries
- to recognize another menu of the same type, it does not get confused.
- ******************************************************************************/
-
- void CMultStdPopupPane::Deactivate( void)
- {
- inherited::Deactivate();
- Disable();
- } /* CPopupPane::Deactivate */
-
- /******************************************************************************
- Dispose
-
- Dispose of the detached Toolbox menu record when we are all done with
- it.
- ******************************************************************************/
-
- void CMultStdPopupPane::Dispose( void)
- {
- // The menu may not be enabled when it is disposed, so we need
- // some way of distinguishing it from other menus that may have
- // the same pseudo id.
-
- ChangeMenuID(FindItsMenuIndex(), kTemporaryMenuID);
- /* Give it a unique id */
-
- // We must dispose of the space we allocated for the menu hook.
- // Since we called DetachResource on the Toolbox menu record, the
- // Menu Manager will not do it automatically for us.
-
- DisposeHandle( (Handle) (**itsMacMenu).menuProc);
-
- // Remove the menu from the bartender’s list, and then dispose of
- // the detached Toolbox menu record.
-
- gBartender->RemoveMenu(kTemporaryMenuID);
- DisposeHandle(itsMacMenu);
-
- // Dispose of the rest of the pop-up pane.
-
- inherited::Dispose();
- }
-
- /**** I N T E R N A L M E T H O D S ****/
-
- /******************************************************************************
- Enable
-
- Set the menu id to the correct menu id (the pseudo menu id) so that
- the bartender can once again access this menu.
- ******************************************************************************/
-
- void CMultStdPopupPane::Enable( void)
- {
- ChangeMenuID(FindItsMenuIndex(), itsPseudoMenuID);
- }
-
- /******************************************************************************
- Disable
-
- Set the menu id to a menu id not used by other menus so that the bartender
- can no longer access this menu.
- ******************************************************************************/
-
- void CMultStdPopupPane::Disable( void)
- {
- ChangeMenuID(FindItsMenuIndex(), kDisabledMenuID);
- }
-
- /******************************************************************************
- ChangeMenuID
-
- Given an index within the bartender’s table, set a new menu ID,
- from both the bartender’s and the Toolbox’s perspectives.
- ******************************************************************************/
-
- void CMultStdPopupPane::ChangeMenuID(short index, short newID)
- {
- MenuEntryH menus = gBartender->theMenus;
- MenuHandle theMacMenu;
-
- (*menus)[index].MENUid = newID;
- theMacMenu = (*menus)[index].macMenu;
- if (theMacMenu && *theMacMenu)
- (**theMacMenu).menuID = newID;
- }
-
- /******************************************************************************
- FindItsMenuIndex
-
- Looks through the bartender’s table for an index entry that matches
- the Toolbox menu record stored in the itsMacMenu instance variable.
- It returns the index number of this entry.
-
- Return -1 if itsMacMenu is not found
- ******************************************************************************/
-
- short CMultStdPopupPane::FindItsMenuIndex(void)
- {
- MenuEntryH menus = gBartender->theMenus;
- /* The menu table */
- short numMenus = gBartender->numMenus;
- /* The number of menus */
- MenuEntryP theEntry; /* Pointer to menu table */
- register short i; /* Index into menu table */
-
- theEntry = *menus; /* Dereference for speed */
-
- for (i = 0; i < numMenus; i++) { /* Search thru all entries */
- if (theEntry[i].macMenu == itsMacMenu) {
- return(i); /* Match found. Exit here */
- }
- }
- /* We've fallen through the loop */
- return(-1); /* Menu is not in our table */
-
- }