command.h

Go to the documentation of this file.
00001 /**
00002  * \file <mgui/command.h
00003  * \brief MGUI::COMMAND_... class definitions
00004  *
00005  * \if NODOC
00006  * $Log: command.h_v $
00007  * Revision 1.14  2005/03/31 16:57:07  fileserver!dwilliss
00008  * Rename one of our types to MIUNICODE because it conflicted with a Microsoft #define
00009  *
00010  * Revision 1.13  2003/10/03 19:58:19  linux32build!build
00011  * Doxygen
00012  *
00013  * Revision 1.12  2003/09/15 13:49:32  fileserver!dwilliss
00014  * Doxygen
00015  *
00016  * Revision 1.11  2003/04/09 20:47:55  dwilliss
00017  * Don't use _T in templates. Mac's ctype.h defines a global _T
00018  *
00019  * Revision 1.10  2002/10/10 14:25:31  mju
00020  * Exclude everything unless X or MFC.
00021  *
00022  * Revision 1.9  2002/10/09 15:43:10  mju
00023  * Move to 'mgui' folder.
00024  *
00025  * Revision 1.8  2002/09/05 21:10:38  dwilliss
00026  * Actaully implement GetMenuItems() as an inline
00027  *
00028  * Revision 1.7  2002/08/13 21:01:21  mju
00029  * Use mi32 instead of miwin.
00030  *
00031  * Revision 1.6  2001/12/13 22:22:27  mju
00032  * Change reference from DIALOG to DLG.
00033  *
00034  * Revision 1.5  2001/12/13 16:58:47  mju
00035  * Use consistent inclusion guard.
00036  * Remove references to mguicommand.h as that file includes this one.
00037  *
00038  * Revision 1.4  2001/12/13 15:13:17  dwilliss
00039  * Compiles for both WIN32_NATIVE and X now
00040  *
00041  * Revision 1.3  2001/12/04 20:10:56  dwilliss
00042  * Had a method with no declared return type.
00043  * MENU has to be a friend of COMMAND_TARGET
00044  *
00045  * Revision 1.2  2001/12/04 19:45:48  dwilliss
00046  * Slight cleanup
00047  *
00048  * Revision 1.1  2001/12/04 19:26:26  dwilliss
00049  * Initial revision
00050  * \endif
00051 **/
00052 
00053 #if !defined(INC_MGUI_COMMAND_H) && (defined(X_NATIVE) || defined(WIN32_MFC))
00054 #define  INC_MGUI_COMMAND_H
00055 
00056 #ifdef WIN32_MFC
00057 #ifndef  INC_MI32_STDAFX_H
00058 #include <mi32/stdafx.h>
00059 #endif
00060 class CCmdUI;
00061 #endif
00062 
00063 #ifndef  INC_MI32_STDDEFNS_H
00064 #include <mi32/stddefns.h>
00065 #endif
00066 
00067 #ifndef  INC_MI32_SIMPLEAR_H
00068 #include <mi32/simplear.h>
00069 #endif
00070 
00071 #ifdef X_NATIVE
00072 #ifndef INC_MI32_XDEFNS_H
00073 #include <mi32/xdefns.h>
00074 #endif
00075 #define UINT UINT32  
00076 #endif
00077 
00078 namespace MGUI {
00079 
00080 class COMMAND_ROUTER;
00081 
00082 //------------------------------------------------------------------------------------------------
00083 
00084 //! Base class for command target.
00085 //! Command targets must be attached to a COMMAND_ROUTER for command routing.  See the
00086 //! description of COMMAND_ROUTER for more information.
00087 //! Usually the COMMAND_TARGET_T template will be used instead.
00088 class COMMAND_TARGET {
00089    public:
00090 
00091       enum STATE {
00092          STATE_UNCHECKED = 0,
00093          STATE_CHECKED = 1,
00094          STATE_INDETERMINATE = 2    //!< XXX Can't actually do this in X.  Maybe just use a bool instead?
00095          };
00096 
00097 
00098 #ifdef X_NATIVE
00099       class CMDUI {
00100          //! OnUpdateUI is called with a pointer to one of these.  It is 
00101          //! similar to the CCmdUI class in MFC.  In fact, in MFC, CMDUI
00102          //! is just a typedef alias to CCmdUI
00103          public:
00104             //! Enable or disable the user-interface item
00105             void Enable (
00106                bool enable = true
00107                ) {
00108                m_tgt->Enable(enable);
00109                }
00110 
00111             //! For toggle buttons, set the current state
00112             void SetCheck (
00113                bool check = true
00114                ) {
00115                m_tgt->SetCheck(check);
00116                }
00117 
00118             //! Same as Set Check but for buttons in a radio group.
00119             //! Note that it does not enforce radio behaviour, as the
00120             //! MFC version doesn't either.  It is here for completeness.
00121             void SetRadio (
00122                bool check = true
00123                ) {
00124                SetCheck(check);
00125                }
00126 
00127             //! Change the text of an item (via resource file lookup)
00128             void SetText (
00129                const char* text
00130                );
00131 
00132             //! Change the text of an item 
00133             void SetText (
00134                const MIUNICODE* text
00135                );
00136                
00137          private:
00138             #ifndef GENERATING_DOXYGEN_OUTPUT
00139             COMMAND_TARGET* m_tgt;
00140 
00141             //! Private constructor.  Only a COMMAND_TARGET can create one
00142             CMDUI(COMMAND_TARGET* tgt) :
00143                m_tgt(tgt) {
00144                }
00145 
00146             friend class COMMAND_TARGET;
00147             #endif // GENERATING_DOXYGEN_OUTPUT
00148 
00149          };
00150       
00151 #endif
00152 #ifdef WIN32_MFC
00153       #ifndef GENERATING_DOXYGEN_OUTPUT
00154       //! For MFC, CMDUI _is_ CCmdUI
00155       typedef class CCmdUI CMDUI;
00156       #endif // GENERATING_DOXYGEN_OUTPUT
00157 #endif
00158       //! Constructor.
00159       //! XXX Not sure what good the NumIDs is in the X world.
00160       COMMAND_TARGET (
00161          COMMAND_ROUTER *router = 0,         //!< Router to attach to
00162          int NumIDs = 1                      //!< Number of sequential command IDs to assign
00163          );
00164 
00165       //! Destructor.
00166       virtual ~COMMAND_TARGET (
00167          );
00168 
00169       //! Attach target to specified router.
00170       //! Target will be detached from previous router if any.
00171       void Attach (
00172          COMMAND_ROUTER *pRouter,            //!< Router to attach to
00173          int NumIDs = 1                      //!< Number of sequential command IDs to assign
00174          );
00175 
00176       //! Detach target from router.
00177       void Detach (
00178          );
00179 
00180       //! Enable or disable the target.
00181       //! This will have no effect if you override the OnUpdateUI method.
00182       void Enable (
00183          bool enabled = true
00184          ) { 
00185 #ifdef X_NATIVE
00186          MxSetSensitive(m_widget, enabled); 
00187 #else
00188          m_enabled = enabled;
00189 #endif
00190          }
00191 
00192       //! Get first command ID associated with target.
00193       UINT16 GetCmdID (
00194          ) const { return (m_CmdID); }
00195 
00196       //! Returns true if the item is a toggle button and is checked.
00197       bool GetCheck (
00198          ) const {
00199 #ifdef X_NATIVE
00200          if (m_widget != 0) return (XmToggleButtonGetState(m_widget) != 0);
00201          return (false);
00202 #else
00203          return (m_state == STATE_CHECKED);
00204 #endif
00205          }
00206 
00207       //! Returns the current state if the item is a toggle or radio button
00208       STATE GetState (
00209          ) const {
00210 #ifdef X_NATIVE
00211          return (GetCheck() ? STATE_CHECKED : STATE_UNCHECKED);
00212 #else
00213          return m_state;
00214 #endif
00215          }
00216 
00217       //! Set the check mark state.
00218       //! This just calls SetState(), but as long as you don't need the indeterminate state,
00219       //! a bool is a lot shorter than MGUI::COMMAND_TARGET::STATE_WHATEVER
00220       //! This will have no effect if you override the OnUpdateUI method.
00221       //! (And since the X Version doesn't have an indeterminate state, who cares?
00222       void SetCheck (
00223          bool check = true
00224          ) { SetState(check ? STATE_CHECKED : STATE_UNCHECKED); }
00225 
00226       //! Set the check mark state (can be indeterminate)
00227       //! This is like SetCheck, but takes an enum so you can set it to an indeterminate state.
00228       //!
00229       //!   Possible values:
00230       //!      MGUI::COMMAND_TARGET::STATE_CHECKED
00231       //!      MGUI::COMMAND_TARGET::STATE_UNCHECKED
00232       //!      MGUI::COMMAND_TARGET::STATE_INDETERMINATE XXX
00233       //!
00234       //! Note, Indeterminate state not available in X
00235       //! This will have no effect if you override the OnUpdateUI method.
00236       void SetState (
00237          STATE state
00238          ) { 
00239 #ifdef X_NATIVE
00240          MxToggleButtonSetState(m_widget, (state == STATE_CHECKED), False); 
00241 #else
00242          m_state = state;
00243 #endif
00244          }
00245 
00246 
00247    protected:
00248 
00249       //! Called by router when command is invoked.
00250       virtual void OnCommand (
00251          UINT nID
00252          ) = 0;
00253 
00254       //! Called by router to update user interface.
00255       virtual void OnUpdateUI (
00256          CMDUI* pCmdUI
00257          );
00258 
00259    private:
00260       #ifndef GENERATING_DOXYGEN_OUTPUT
00261       UINT16 m_CmdID;
00262       COMMAND_ROUTER *m_pRouter;
00263       STATE m_state;
00264       bool m_enabled;
00265 
00266 #ifdef X_NATIVE
00267       Widget m_widget;
00268 
00269       static void CB_Activate (Widget, void*, void*);
00270 #endif
00271 
00272       //! Called by router to perform attachment.
00273       void SetRouterAndID (
00274          COMMAND_ROUTER *pRouter,
00275          int id
00276          ) { m_pRouter = pRouter; m_CmdID = (UINT16)id; }
00277 
00278 #ifdef X_NATIVE
00279       void SetWidget (
00280          Widget widget
00281          ) { m_widget = widget; }
00282       
00283       //! X Implementation only.  Call the OnUpdateIO method.
00284       void CallOnUpdateUI (
00285          ) {
00286          CMDUI cmdui(this);
00287          OnUpdateUI(&cmdui);
00288          }
00289 #endif
00290 
00291       // UNIMPLEMENTED / UNSUPPORTED
00292       COMMAND_TARGET (const COMMAND_TARGET&);
00293       COMMAND_TARGET& operator= (const COMMAND_TARGET&);
00294 
00295       friend class COMMAND_ROUTER;
00296 #ifdef X_NATIVE
00297       friend class COMMAND_TARGET::CMDUI;
00298       friend class MENU;
00299       #endif // GENERATING_DOXYGEN_OUTPUT
00300 #endif
00301    };
00302 
00303 
00304 //------------------------------------------------------------------------------------------------
00305 
00306 //! Template command target to allow method(s) in container class to be called for convenience.
00307 template <class _CT> class COMMAND_TARGET_T : public COMMAND_TARGET {
00308    public:
00309 
00310       //! Constructor.
00311       COMMAND_TARGET_T (
00312          _CT *pContainer = 0,                //!< Pointer to callback container class
00313          void (_CT::*pfOnCommandFunc)(UINT) = 0,      
00314          void (_CT::*pfOnUpdateUIFunc)(CMDUI*) = 0
00315          ): m_pContainer(pContainer), m_pfOnCommandFunc(pfOnCommandFunc), m_pfOnUpdateUIFunc(pfOnUpdateUIFunc)
00316          { }
00317 
00318       //! Set methods to call for command and updating interface.
00319       void SetFunctions (
00320          _CT *pContainer,
00321          void (_CT::*pfOnCommandFunc)(UINT),
00322          void (_CT::*pfOnUpdateUIFunc)(CMDUI*) = 0
00323          ) { m_pContainer = pContainer; m_pfOnCommandFunc = pfOnCommandFunc; m_pfOnUpdateUIFunc = pfOnUpdateUIFunc; }
00324 
00325    private:
00326       #ifndef GENERATING_DOXYGEN_OUTPUT
00327       _CT *m_pContainer;
00328       void (_CT::*m_pfOnCommandFunc)(UINT);
00329       void (_CT::*m_pfOnUpdateUIFunc)(CMDUI*);
00330 
00331       //! Called by router when command is invoked.
00332       virtual void OnCommand (
00333          UINT nID
00334          ) { if (m_pfOnCommandFunc != 0) (m_pContainer->*m_pfOnCommandFunc)(nID); }
00335 
00336       //! Called by router to update user interface.
00337       virtual void OnUpdateUI (
00338          CMDUI *pCmdUI
00339          ) { 
00340          if (m_pfOnUpdateUIFunc != 0) 
00341             (m_pContainer->*m_pfOnUpdateUIFunc)(pCmdUI); 
00342          else
00343             COMMAND_TARGET::OnUpdateUI(pCmdUI);
00344          }
00345       #endif // GENERATING_DOXYGEN_OUTPUT
00346 
00347    };
00348 
00349 
00350 //------------------------------------------------------------------------------------------------
00351 
00352 //! Command Router class.
00353 //! To make a window into a command router so that command targets can be contained in it, perform
00354 //! the following steps:
00355 //!
00356 //! 1. Add a COMMAND_ROUTER member to your class.
00357 //!
00358 //!   2. Override the MFC OnCmdMsg() method (inherited from CCmdTarget).
00359 //!
00360 //! 3. (Optional) Add a cast operator from your MFC class to COMMAND_ROUTER*.
00361 //!
00362 //!  For example, if your window is derived from CView, your class will look like:
00363 //! @code
00364 //!      class MYVIEW : public CView {
00365 //!         public:
00366 //!            ...
00367 //!            operator COMMAND_ROUTER* (
00368 //!               ) const { return (&m_CmdRouter); }
00369 //!
00370 //!            virtual BOOL OnCmdMsg (UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo);
00371 //!            ...
00372 //!         private
00373 //!            ...
00374 //!            COMMAND_ROUTER m_CmdRouter;
00375 //!            ...
00376 //!         };
00377 //! @endcode
00378 //!
00379 //! 4. Implement OnCmdMsg() as follows (assuming class named MYVIEW as above).
00380 //!
00381 //! @code
00382 //!      // [Virtual] Dynamically route command messages to targets.
00383 //!      BOOL MYVIEW::OnCmdMsg (
00384 //!         UINT nID,                           // Command ID
00385 //!         int nCode,                          // Notification code
00386 //!         void* pExtra,
00387 //!         AFX_CMDHANDLERINFO* pHandlerInfo
00388 //!         ) {
00389 //!         // Attempt to have command router handle the message.
00390 //!         if (m_CmdRouter.RouteCommandMessage(nID,nCode,pExtra,pHandlerInfo)) return (TRUE);
00391 //!         // If we didn't process the command, call the base class
00392 //!         // version of OnCmdMsg so the message-map can handle the message
00393 //!         return (CView::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo));
00394 //!         }
00395 //! @endcode
00396 //!
00397 //!
00398 //!   Note:  If you're creating a dialog with MGUI::DLG, all this has already been done for you.
00399 //!      An MGUI::DLG has an COMMAND_ROUTER and a cast operator to return a pointer to it.
00400 //!
00401 //!      Note:  For the X version, the COMMAND_ROUTER doesn't really do anything.
00402 //!         It exists in X for two reasons.
00403 //!         1.  To make the X code the same as the MFC code to avoid ugly #ifdefs
00404 //!         2.  Could add an UpdateUI method that would call the OnUpdateUI of all
00405 //!             COMMAND_TARGETS.
00406 class COMMAND_ROUTER {
00407    public:
00408 
00409       //! Constructor.
00410       COMMAND_ROUTER (
00411          );
00412 
00413       //! Destructor.
00414       ~COMMAND_ROUTER (
00415          );
00416 
00417    #ifdef WIN32_MFC
00418       //! Route command message (MFC only).
00419       //! This must be called by override of OnCmdMsg() in any class which
00420       //! supports command routing.
00421       //! @return 'true' if message handled, 'false' if not.
00422       bool RouteCommandMessage (
00423          UINT nID,
00424          int nCode,
00425          void *pExtra,
00426          AFX_CMDHANDLERINFO* pHandlerInfo
00427          );
00428    #endif
00429 
00430    private:
00431       #ifndef GENERATING_DOXYGEN_OUTPUT
00432       SIMPLE_ARRAY<COMMAND_TARGET*> m_CmdTargets;
00433 
00434       //! Attach command target to router.
00435       void AttachTarget (
00436          COMMAND_TARGET &target,
00437          int NumIDs
00438          );
00439 
00440       //! Detach command target from router.
00441       void DetachTarget (
00442          COMMAND_TARGET &target
00443          );
00444 
00445       //! UNIMPLEMENTED / UNSUPPORTED
00446       COMMAND_ROUTER (const COMMAND_ROUTER&);
00447       COMMAND_ROUTER& operator= (const COMMAND_ROUTER&);
00448 
00449    friend class COMMAND_TARGET;
00450       #endif // GENERATING_DOXYGEN_OUTPUT
00451    };
00452 
00453 
00454 //------------------------------------------------------------------------------------------------
00455 
00456 class MENU 
00457 #ifdef WIN32_MFC
00458    : public CMenu
00459 #endif
00460    {
00461    public:
00462 
00463    #ifdef X_NATIVE
00464       enum FLAGS {
00465          FLAG_None = 0,
00466          FLAG_Selected = MxMENU_SELECTED,
00467          FLAG_OneOfMany = MxMENU_ONE_OF_MANY,
00468          FLAG_Toggle = MxMENU_TOGGLE,
00469          FLAG_Disabled = MxMENU_DISABLED,
00470          FLAG_Label = MxMENU_LABEL,
00471          FLAG_Ignore = MxMENU_IGNORE,
00472          FLAG_Programmer = MxMENU_PROGRAMMER
00473          };
00474    #else
00475       enum FLAGS {
00476          FLAG_None = 0,
00477          FLAG_Selected =   0x00000001,
00478          FLAG_OneOfMany =  0x00000002,
00479          FLAG_Toggle =     0x00000004,
00480          FLAG_Disabled =   0x00000008,
00481          FLAG_Label =      0x00000010,
00482          FLAG_Ignore =     0x00000020,
00483          FLAG_Programmer = 0x00000040
00484          };
00485    #endif
00486 
00487       MENU();
00488       ~MENU();
00489 
00490       //! Append an item to the menu.
00491       //! Note that the flags are ignored in the MFC version
00492       void Append (
00493          const char* label,            //!< Label to look up in resource file
00494          COMMAND_TARGET& target,       //!< Command target to notify on selection
00495          FLAGS flags = FLAG_None       
00496          );
00497 
00498       //! Append an item to the menu.
00499       //! Note that the flags are ignored in the MFC version
00500       void Append (
00501          const MIUNICODE* label,       
00502          COMMAND_TARGET& target,       //!< Command target to notify on selection
00503          FLAGS flags = FLAG_None
00504          );
00505 
00506       //! Append a submenu (pull-right) to a menu
00507       //!
00508       //! The submenu must already have all its items added and must not
00509       //! be modified or go out of scope until we're done using it.
00510       void Append (
00511          MENU& submenu,                //!< Submenu to add
00512          const char* label             //!< Label to lookup in resource file
00513          );
00514 
00515       //! Add a separator to a menu.
00516       void AppendSeparator (
00517          );
00518 
00519    #ifdef X_NATIVE   //!< The following methods come from the CMenu base class in MFC version
00520 
00521       //! Used to specify that this is to be a menu bar.
00522       //! Menu bar can only have other menus as children
00523       //! Note: in the MFC version, you MUST call this before adding anything.
00524       //! In the X version, this really does nothing and is just here for
00525       //! completeness.
00526       void CreateMenu() {}
00527 
00528       //! Used to specify that this is to be a popup menu.
00529       //! This includes menus on a menu bar.
00530       //! Note: in the MFC version, you MUST call this before adding anything.
00531       //! In the X version, this really does nothing and is just here for
00532       //! completeness.
00533       void CreatePopupMenu() {}
00534 
00535       //! Get the array of MENUITEMS for menu creation
00536       //! X version only.
00537       MENUITEM* GetMenuItems (
00538          ) {
00539          return (m_items);
00540          }
00541 
00542       //! Pop up a popup menu (X Version).
00543       //! The function is named to match the MFC version that does the same
00544       //! thing, although the parameters are not the same.
00545       void TrackPopupMenu (
00546          Widget parent,
00547          XButtonEvent* event
00548          );
00549 
00550    #endif
00551 
00552    private:
00553       #ifndef GENERATING_DOXYGEN_OUTPUT
00554 
00555    #ifdef X_NATIVE   
00556       SIMPLE_ARRAY<MENUITEM> m_items;
00557       Widget m_popup;   //!< Used by TrackPopupMenu
00558 
00559       void Append(const MENUITEM&);
00560 
00561    #endif
00562       #endif // GENERATING_DOXYGEN_OUTPUT
00563    };
00564 
00565 
00566 
00567 //------------------------------------------------------------------------------------------------
00568 
00569 }  //! End of MGUI namespace
00570 
00571 typedef  MGUI::COMMAND_TARGET    MGUI_COMMAND_TARGET;
00572 typedef  MGUI::COMMAND_ROUTER    MGUI_COMMAND_ROUTER;
00573 
00574 #define  MGUI_COMMAND_TARGET_T   MGUI::COMMAND_TARGET_T
00575 
00576 DEFINE_ENUM_OPERATORS(MGUI::MENU::FLAGS);
00577 
00578 #endif   // INC_MGUI_COMMAND_H
00579 
00580 

Generated on Wed May 31 15:26:44 2006 for TNTsdk by  doxygen 1.3.8-20040913