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

Generated on Tue Dec 14 13:18:16 2004 for TNTsdk by  doxygen 1.3.8-20040913