home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / yacl-012.zip / ui / cntroler.cxx < prev    next >
C/C++ Source or Header  |  1995-04-04  |  18KB  |  700 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6. /*
  7.  *
  8.  *          Copyright (C) 1994, M. A. Sridhar
  9.  *  
  10.  *
  11.  *     This software is Copyright M. A. Sridhar, 1994. You are free
  12.  *     to copy, modify or distribute this software  as you see fit,
  13.  *     and to use  it  for  any  purpose, provided   this copyright
  14.  *     notice and the following   disclaimer are included  with all
  15.  *     copies.
  16.  *
  17.  *                        DISCLAIMER
  18.  *
  19.  *     The author makes no warranties, either expressed or implied,
  20.  *     with respect  to  this  software, its  quality, performance,
  21.  *     merchantability, or fitness for any particular purpose. This
  22.  *     software is distributed  AS IS.  The  user of this  software
  23.  *     assumes all risks  as to its quality  and performance. In no
  24.  *     event shall the author be liable for any direct, indirect or
  25.  *     consequential damages, even if the  author has been  advised
  26.  *     as to the possibility of such damages.
  27.  *
  28.  */
  29.  
  30.  
  31.  
  32.  
  33. #if defined(__GNUC__)
  34. #pragma implementation
  35. #endif
  36.  
  37.  
  38.  
  39. // ----------------------- Header file includes -----------------------
  40.  
  41.  
  42. #include "base/treewalk.h"
  43.  
  44. #include "ui/cntroler.h"
  45. #include "ui/applic.h"
  46. #include "ui/menu.h"
  47. #include "ui/composit.h"
  48. #include "ui/event.h"
  49. #include "ui/btngroup.h"
  50.  
  51.  
  52. #if defined(__OS2__)
  53. #include <stdlib.h>
  54. #define INCL_PM
  55. #include <os2.h>
  56. #endif
  57.  
  58.  
  59. #if defined (__X_MOTIF__)
  60. #include <X11/StringDefs.h>
  61. #include <X11/Intrinsic.h>
  62. #include <Xm/Xm.h>
  63. #include <X11/Shell.h>
  64. #include <iostream.h> // DEBUG
  65. #endif
  66.  
  67. #if defined(__GNUC__)
  68. template class CL_Binding<UI_Controller>;
  69. #endif
  70.  
  71.  
  72. // ----------------------- Typedefs ---------------------------------
  73.  
  74. typedef CL_Binding<UI_Controller> ControllerBind;
  75. typedef bool (UI_Controller::*ControllerMethod) (CL_Object&, long);
  76.  
  77. #if defined(__MS_WINDOWS__)
  78. typedef  long FAR PASCAL _export (*WinProc) (HWND, unsigned, WORD, LONG);
  79. #endif
  80.  
  81. // ----------------------- Global and static variables -------------
  82.  
  83.  
  84. char _YACLWindowClassName[] = "YACLWindow";
  85.  
  86. #if defined(__X_MOTIF__)
  87. XtAppContext _YACLXAppContext;
  88. #endif
  89.  
  90.  
  91. // ----------------------- Function prototypes ----------------------
  92.  
  93. #if defined(__MS_WINDOWS__)
  94.  
  95. void initApplicationMS (HANDLE);
  96.  
  97. #elif defined(__OS2__)
  98. MRESULT EXPENTRY YACLWindowProc (HWND, ULONG, MPARAM, MPARAM);
  99.  
  100. #elif defined(__X_MOTIF__)
  101.  
  102. // static void beep ( Widget, XEvent*, String*, unsigned int * );
  103. // static XtActionsRec actionsTable [] =
  104. // {
  105. //     {"beep", &beep}
  106. // };
  107. // 
  108. // static char defaultTranslations[] =
  109. //         "Ctrl<Key>J:    beep() \n\
  110. //          Ctrl<Key>O:    beep() \n\
  111. //          Ctrl<Key>M:    beep() \n\
  112. //          <Key> RETURN:    beep()"; 
  113. // #define FONTHEIGHT(f) ((f)->max_bounds.ascent + \
  114. //                        (f)->max_bounds.descent) 
  115. // static char _defaultTranslations[] =
  116. //     "<Btn1Down>(2+): lButtonDouble() \n\
  117. //      <Btn1Down>(2+): mButtonDouble() \n\
  118. //      <Btn1Down>(2+): rButtonDouble()";
  119. // 
  120. // static XtActionsRec actionsTable [] =
  121. // {
  122. //     {"lButtonDouble", UI_Controller::LButtonDouble}
  123. //   , {"mButtonDouble", UI_Controller::MButtonDouble}
  124. //   , {"rButtonDouble", UI_Controller::RButtonDouble}
  125. // };
  126.  
  127. #endif
  128.  
  129.  
  130.  
  131.  
  132. //
  133. //----------------------Constructor-----------------------
  134. //
  135.  
  136.  
  137.  
  138. UI_Controller::UI_Controller (UI_Application* appl)
  139. {
  140.     UI_VisualObject::_Application = appl;
  141.     _InitController();
  142. }
  143.  
  144.  
  145. void UI_Controller::_InitController ()
  146. {
  147.     widgetCount = 0;
  148.     _current = NULL;
  149.     UI_VisualObject::_Controller = this;
  150.     _viewTree    = NULL;
  151.     _root        = NULL;
  152.     _eventQueue  = new CL_ObjectSequence;
  153.     _inWaitState = FALSE;
  154.     _focus       = NULL;
  155.     _eventFilter = NULL;
  156.     _termination = NULL;
  157. #if defined(__MS_WINDOWS__)
  158.     _buttonFaceBrush = CreateSolidBrush (GetSysColor (COLOR_BTNFACE));
  159. #elif defined(__X_MOTIF_)
  160. #endif
  161. }
  162.  
  163.  
  164. UI_Controller::~UI_Controller ( )
  165. {
  166.     if ( _root != NULL )
  167.         Destroy ( _root );
  168.     _eventQueue->MakeEmpty ( );
  169.     if ( _viewTree )
  170.         delete _viewTree;
  171.     if ( _eventQueue )
  172.         delete _eventQueue;
  173. #if defined(__OS2__)
  174.     WinDestroyMsgQueue (_hmq);
  175.     WinTerminate (_hab);
  176. #elif defined(__MS_WINDOWS__)
  177.     DeleteObject ((HBRUSH) _buttonFaceBrush);
  178.     UnregisterClass ( _YACLWindowClassName, hInst );
  179.     _menuMap.DestroyContents ();
  180. #endif
  181. }
  182.  
  183.  
  184. //
  185. //-----------------Controller service methods----------------------------
  186. //
  187.  
  188.  
  189. //
  190. //--------Mouse control methods
  191. //
  192.  
  193.  
  194.  
  195.  
  196. void UI_Controller::GiveMouseTo (const UI_VisualObject& view)
  197. {
  198. #if defined(__MS_WINDOWS__)
  199.     SetCapture (view._handle);
  200. #elif defined (__OS2__)
  201.     WinSetCapture (HWND_DESKTOP, view._handle);
  202. #elif defined(__X_MOTIF__)
  203. //     _grabWindow = XtWindow (view.ViewHandle());
  204. //     XGrabButton (AppDisplay(), AnyButton, AnyModifier, _grabWindow,
  205. //                  True, 0xfffffff,
  206. //                  GrabModeAsync, GrabModeAsync, _grabWindow, None);
  207. #endif
  208. }
  209.  
  210.  
  211. void UI_Controller::ReleaseMouse()
  212. {
  213. #if defined(__MS_WINDOWS__)
  214.     ReleaseCapture();
  215. #elif defined(__OS2__)
  216.     WinSetCapture (HWND_DESKTOP, NULL);
  217. #elif defined(__X_MOTIF__)
  218. //     XUngrabButton (AppDisplay(), AnyButton, AnyModifier, _grabWindow);
  219. #endif
  220. }
  221.  
  222. void UI_Controller::GiveFocusTo (const UI_VisualObject& aView)
  223. {
  224.     UI_ViewHandle h = aView.ViewHandle ();
  225. #if defined(__MS_WINDOWS__)
  226.     if (h && h != GetFocus()) {
  227.         SetFocus (h);
  228.     }
  229. #elif defined(__OS2__)
  230.     if (h && h != WinQueryFocus (HWND_DESKTOP))
  231.         WinSetFocus (HWND_DESKTOP, h);
  232. #elif defined(__X_MOTIF__)
  233.     if (h)
  234.         XtSetKeyboardFocus (h, None);
  235. #endif
  236. }
  237.  
  238.  
  239.  
  240. UI_VisualObject* UI_Controller::operator [] (UI_ViewHandle h) 
  241. {
  242.     return (UI_VisualObject *) _visualObjMap [(long) h];
  243. }
  244.  
  245.   
  246. //
  247. //---------------------Initialize-----------------------------
  248. //
  249.  
  250. #if defined(__MS_WINDOWS__)
  251.  
  252. short UI_Controller::Initialize
  253.     (HANDLE hInstance, HANDLE hPrevInstance, LPSTR, short)
  254. {
  255.     hInst = hInstance;
  256.     hPrevInst = hPrevInstance;
  257.     if ( !hPrevInstance )
  258.         initApplicationMS (hInstance);
  259.     return 1;
  260. }
  261.  
  262. #elif defined(__X_MOTIF__)
  263.  
  264. short UI_Controller::Initialize ( int& argc, char *argv[] )
  265. {
  266.     _shell = XtVaAppInitialize (&_YACLXAppContext, _TheApplication->AppClass(),
  267.                                 NULL, 0, &argc, argv, NULL,
  268.                                 NULL
  269.                                );
  270.     Arg args [1];
  271.     short argn = 0;
  272.     XtSetArg (args [argn], XmNdeleteResponse, XmDO_NOTHING); argn++;
  273.     XtSetValues (_shell, args, argn);
  274.         // Do not destroy the shell widget in response to user
  275.         // requests; the library will take care of it.
  276.     // XtAppAddActions (_YACLXAppContext, actionsTable, XtNumber
  277.     // (actionsTable));
  278. }
  279.  
  280.  
  281. Display *UI_Controller::AppDisplay()
  282. {
  283.     return XtDisplay (_shell);
  284. }
  285.  
  286.  
  287. #elif defined(__OS2__)
  288.  
  289. void UI_Controller::_AbortPMApp (const char* msg)
  290. {
  291.     PERRINFO  pErrInfoBlk;
  292.     PSZ       pszOffSet;
  293.     void      stdprint(void);
  294.     PSZ  pszErrMsg;
  295.  
  296.     DosBeep (100, 10);
  297.     DosBeep (440, 110);
  298.     if ((pErrInfoBlk = WinGetErrorInfo (_hab)) != NULL) {
  299.         pszOffSet = ((PSZ) pErrInfoBlk) + pErrInfoBlk->offaoffszMsg;
  300.         pszErrMsg = ((PSZ )pErrInfoBlk) + *((PSHORT)pszOffSet);
  301.         CL_String sMsg = CL_String("YACL: ") + msg + CL_String (" failed:\n")
  302.             + pszErrMsg;
  303.         WinMessageBox
  304.             (HWND_DESKTOP, HWND_DESKTOP,  sMsg.AsPtr(), "YACL FATAL", 0,
  305.              MB_MOVEABLE | MB_CUACRITICAL | MB_CANCEL );
  306.         WinFreeErrorInfo (pErrInfoBlk);
  307.     }
  308. }
  309.  
  310. short UI_Controller::Initialize ()
  311. {
  312.     if ((_hab = WinInitialize (0)) == NULLHANDLE)
  313.         _AbortPMApp ("WinInitialize");
  314.     if ((_hmq = WinCreateMsgQueue (_hab, 0)) == NULLHANDLE) {
  315.         _AbortPMApp ("WinCreateMsgQueue");
  316.         WinTerminate (_hab);
  317.         return FALSE;
  318.     }
  319.     if (!WinRegisterClass (_hab, _YACLWindowClassName, YACLWindowProc,
  320.                            CS_SYNCPAINT | CS_MOVENOTIFY | CS_SIZEREDRAW, 0)) {
  321.         _AbortPMApp ("WinRegisterClass");
  322.         WinDestroyMsgQueue (_hmq);
  323.         WinTerminate (_hab);
  324.         return FALSE;
  325.     }
  326.     return TRUE;
  327. }
  328.  
  329. #endif
  330.  
  331.  
  332. void UI_Controller::MakeTopWindow (UI_CompositeVObject* rt)
  333. {
  334.     if (_root && rt != _root)
  335.         CL_Error::Fatal ("Attempt to create two top windows.");
  336.     _root = rt;
  337.  
  338.     if ( (_root->Title ()).Length () == 0 ){
  339.         CL_String title (_YACLWindowClassName);
  340.         _root->Title ()= title;
  341.     }
  342.  
  343. #if defined (__X_MOTIF__)
  344.     UI_VisualObject::_shell = _shell;    
  345. #endif
  346. }
  347.  
  348.  
  349. //
  350. // -----------------------Controller methods-------------------
  351. //
  352.  
  353.  
  354. CL_ObjectSequence UI_Controller::ChildrenOf (const UI_VObjCollection& o)
  355. {
  356.     CL_IntegerTreeNode* node = _viewTree->Node ((long) o.ViewHandle());
  357.     CL_ObjectSequence seq (node ? node->ChildCount() : 0);
  358.     if (!node)
  359.         return seq;
  360.     const CL_ObjectSequence& children = node->Children();
  361.     for (short i = 0; i < node->ChildCount(); i++)
  362.         seq[i] = (CL_Object*) ((CL_IntegerTreeNode*) children[i])->Content();
  363.     return seq;
  364. }
  365.  
  366. void UI_Controller::Register (UI_VisualObject* view)
  367. {
  368.     UI_VObjCollection* parent = view->_parent;
  369.     // _root is set when the main VisualObj is constructed. But Register is
  370.     // called only after its visual element has been created. So:
  371.     if ( _root  && (view != _root)) {
  372.         UI_ViewHandle h = parent ? parent->ViewHandle()
  373.             : _root->ViewHandle();
  374.         CL_IntegerTreeNode* v =  _viewTree->AddChild
  375.             ((long) view->ViewHandle (), (long) h);
  376.         if (!v) // Should not happen
  377.             return;
  378.         v->Content () = (long) view;
  379.     }
  380.     else {
  381.         // We're creating the root of the view tree
  382.         _root = (UI_CompositeVObject *) view;
  383.         _viewTree = new CL_IntegerTree ((long) view->ViewHandle ());
  384.  
  385.         _viewTree->Root()->Content() = (long)_root;
  386.  
  387.         if ( (_root->Title ()).Length () == 0 ) {
  388.             CL_String title (_YACLWindowClassName);
  389.             _root->Title () = title;
  390.         }
  391.     }
  392.     // Now add visual object and window pair to the map
  393.     if (!_visualObjMap.Add ((long) view->ViewHandle (), view))
  394.         CL_Error::Warning ("Controller::Register: Duplicate handle %x "
  395.                            "id %d class name '%s'", view->ViewHandle(),
  396.                            view->ViewID(), view->ClassName());
  397. }  
  398.  
  399.  
  400.  
  401. // The following two functions are meant only for debugging support. This
  402. // code might be useful in debugging, and therefore has not been deleted.
  403. // static void PrintTree (const CL_IntegerTree& tree, CL_IntegerTreeNode* node,
  404. //                        short depth = 0)
  405. // {
  406. //     if (!node)
  407. //         return;
  408. //     CL_String s (' ', depth*4);
  409. //     UI_VisualObject* v = (UI_VisualObject*) node->Content();
  410. //     CL_Error::Warning ("%sHandle %ld Id %ld ptr %lx", s.AsPtr(),
  411. //                        v->ViewHandle(), v->ViewID(), v);
  412. //     short n = node->ChildCount();
  413. //     if (n <= 0)
  414. //         return;
  415. //     CL_Error::Warning ("%s{", s.AsPtr());
  416. //     for (short i = 0; i < n; i++)
  417. //         PrintTree (tree, node->Child(i), depth+1);
  418. //     CL_Error::Warning ("%s}", s.AsPtr());
  419. // }
  420. // 
  421. // 
  422. // static void PrintMap (CL_IntPtrMap& map)
  423. // {
  424. //     CL_Error::Warning ("---------");
  425. //     CL_IntPtrMapIterator itr (map);
  426. //     while (itr.More()) {
  427. //         CL_IntPtrAssoc a = itr.Next();
  428. //         UI_VisualObject* v = (UI_VisualObject*) a.value;
  429. //         CL_Error::Warning ("%ld %lx %ld", a.key, a.value, v->ViewID());
  430. //     }
  431. //     CL_Error::Warning ("---------\n");
  432. // }
  433.  
  434.  
  435.  
  436. bool UI_Controller::Destroy (UI_VisualObject* view)
  437. {
  438.     if ( view == NULL )
  439.         return FALSE;
  440.     if ( !(_visualObjMap.IncludesKey ((long) view->ViewHandle ())) )
  441.         return FALSE;
  442.  
  443.     UI_ViewHandle vh = view->ViewHandle ();
  444.  
  445.     //    PrintTree (*_viewTree, _viewTree->Root()); // DEBUG
  446.     
  447.     // We first go through the subtree and remove all the visual objects in
  448.     // the subtree from the visualObjMap. We then destroy the removed
  449.     // objects. This ensures that if the window system sends events to the
  450.     // objects while they're being destroyed, these events are not
  451.     // dispatched because the view handles will not be in the map.
  452.     CL_ObjectSequence toDestroy;
  453.     CL_IntegerTreePostWalker walker (_viewTree->Node ((long) vh));
  454.     while (walker.More()) {
  455.         UI_VisualObject* v = (UI_VisualObject *) walker.Next()->Content ();
  456.         if (v == _current)
  457.             _current = NULL;
  458.         if (v == _focus)
  459.             _focus = NULL;
  460.         if (v) {
  461.             if (v->ViewHandle())
  462.                 _visualObjMap.Remove ((long) v->ViewHandle ());
  463.             toDestroy.Add (v);
  464.         }
  465.     }
  466.     if (view == _root) {
  467.         delete _viewTree;
  468.         _eventQueue->MakeEmpty ();
  469.         _viewTree = NULL;
  470.         _root = NULL;
  471.     }
  472.     else {
  473.         _viewTree->DestroySubtree ((long) vh);
  474.         //   PrintTree (*_viewTree, _viewTree->Root()); // DEBUG
  475.     }
  476.     short n = toDestroy.Size();
  477.     for (short i = 0; i < n; i++) {
  478.         UI_VisualObject* v = (UI_VisualObject *) toDestroy[i];
  479.         v->Finalize ();
  480.         if ( v->_created )
  481.             v->DestroyVisualElement ();
  482.         delete v;
  483.     }
  484.     // PrintMap (_visualObjMap); // DEBUG
  485.     view = NULL;
  486.  
  487.     return TRUE;
  488. }
  489.  
  490.  
  491. long UI_Controller::GetNextWidgetCount()
  492. {
  493.     return ++widgetCount;
  494. }
  495.  
  496.  
  497. bool UI_Controller::DispatchEvent (UI_Event* e)
  498. {
  499.     if (!_viewTree)
  500.         return TRUE; // No event dispatching -- the app is finished
  501.     if (_inWaitState)
  502.         return TRUE; // Do nothing if in wait state
  503.     UI_VisualObject* obj = e->Destination ();
  504.     if (e->_type == Event_GetFocus)
  505.         _focus = obj;
  506.     else if (e->_type == Event_LoseFocus)
  507.         _focus = NULL;
  508.  
  509.     bool b = TRUE;
  510.     if (obj) {
  511.         b = obj->_PrivateHandleEvent (e);
  512.         if (b)
  513.             return TRUE;
  514.         UI_VObjCollection* vObj = obj->Parent(); 
  515.         while (vObj) {
  516.             e->_dest = vObj;
  517.             b = vObj->_PrivateHandleChildEvent (*e);
  518.         if (b) break;
  519.             vObj = vObj->Parent ();
  520.         }
  521.     }
  522.     return b;
  523. }
  524.  
  525.  
  526. bool UI_Controller::ProcessSoftEvent ( UI_Event* e )
  527. {
  528.     bool done = FALSE;
  529.     switch (e->Type ()) {
  530.     case Event_Quit:
  531.         done  =  (e->Origin() == e->Destination() &&
  532.                   e->Origin() == _root );
  533.         Destroy (e->Destination ());
  534.         break;
  535.  
  536.     case Event_MakeInterface: {
  537.         UI_VisualObject* origin = e->Origin ();
  538.         if (!origin)
  539.             break;
  540. #if defined(__MS_WINDOWS__)
  541.         _MakeWindowsInterface (*e);
  542. #elif defined(__X_MOTIF__)
  543.         _MakeXInterface (*e);
  544. #elif defined(__OS2__)
  545.         _MakeOS2Interface (*e);
  546. #endif
  547.         break;
  548.     }  // End of case Event_MakeInterface
  549.         
  550.     default:
  551.         DispatchEvent (e);
  552.         break;
  553.     }
  554.     return done;
  555. }
  556.  
  557.  
  558.  
  559. void UI_Controller::DispatchSoftEvents ()
  560. {
  561.     UI_Event* e = NULL;
  562.     while ( _eventQueue->Size () > 0 ) {
  563.         e = (UI_Event*) _eventQueue->ExtractLeftmost ();
  564.         if ( !_eventFilter || _eventFilter->Execute (*e, 0) ) {
  565.             ProcessSoftEvent (e);
  566.         }
  567.         if ( _termination && _termination->Execute (*e, 0) ) {
  568.             delete e;
  569.             break;
  570.         }
  571.         delete e;
  572.     }
  573. }
  574.  
  575.  
  576.  
  577.  
  578. void UI_Controller::EventLoop (CL_AbstractBinding* termination,
  579.                                CL_AbstractBinding* filter
  580.                               )
  581. {
  582.     // Save the filters.
  583.     CL_AbstractBinding* oldEventFilter = _eventFilter;
  584.     CL_AbstractBinding* oldTermFilter  = _termination;
  585.     _eventFilter = filter;
  586.     _termination = termination;
  587.  
  588.     // Run the loop
  589.     if ( _root )
  590.         ProcessNativeEvents ();
  591.  
  592.     // Restore the filters
  593.     _eventFilter = oldEventFilter;
  594.     _termination = oldTermFilter;
  595. }
  596.  
  597.  
  598. bool UI_Controller::RootDestroyed ( CL_Object&, long )
  599. {
  600.     return _root == NULL;
  601. }
  602.  
  603.  
  604.     
  605. void UI_Controller::Run ()
  606. {
  607.     if (!_root) {
  608.         CL_Error::Warning ("UI_Controller::Run: no root window");
  609.         return;
  610.     }
  611.     // Start by cleaning up the soft events
  612.     DispatchSoftEvents ();
  613.     ControllerBind bind ( this, &UI_Controller::RootDestroyed );
  614.     EventLoop ( &bind, NULL );
  615. }
  616.  
  617.  
  618. bool UI_Controller::SetCurrentCursor (UI_Cursor& c)
  619. {
  620. #if defined (__MS_WINDOWS__)
  621.     HCURSOR h = c.Handle();
  622.     if (h) {
  623.         SetCursor (h);
  624.         return TRUE;
  625.     }
  626.     return FALSE;
  627. #elif defined(__OS2__)
  628.     if (c != UICursor_Default)
  629.         WinSetPointer (HWND_DESKTOP,
  630.                        _inWaitState ? WinQuerySysPointer
  631.                        (HWND_DESKTOP, SPTR_WAIT, FALSE)
  632.                        : c.Handle());
  633.     return TRUE;
  634. #elif defined (__X_MOTIF__)
  635.     XSetWindowAttributes attrs;
  636.     Display* dpy = XtDisplay (_shell);
  637.     attrs.cursor = (c == UICursor_Default) ? None : c.Handle();
  638.     XChangeWindowAttributes(dpy, XtWindow(_shell), CWCursor, &attrs);
  639.     XFlush(dpy);
  640.     return TRUE;
  641. #endif
  642. }
  643.  
  644.  
  645. void UI_Controller::BeginWait ()
  646. {
  647.     _inWaitState = TRUE;
  648.     _defaultCursor = UICursor_Wait;
  649.     DispatchPendingEvents ();
  650.     SetCurrentCursor (_defaultCursor);
  651. }
  652.  
  653.  
  654. void UI_Controller::EndWait ()
  655. {
  656.     _inWaitState = FALSE;
  657.     _defaultCursor = UICursor_Arrow;
  658.     SetCurrentCursor (_defaultCursor);
  659.     FlushEventQueue ();
  660. }
  661.  
  662.  
  663.         
  664.  
  665.  
  666.  
  667. void UI_Controller::AddEvent(UI_Event* anEvent)
  668. {
  669.     _eventQueue->Add ( anEvent );
  670. }
  671.  
  672.  
  673. UI_Event* UI_Controller::RemoveEvent ()
  674. {
  675.     UI_Event *e;
  676.  
  677.     if ( _eventQueue->Size () > 0 ){
  678.         e = ( UI_Event* ) _eventQueue->ExtractLeftmost ();
  679.         return e;
  680.     }
  681.     return NULL;
  682. }
  683.  
  684.  
  685. void UI_Controller::Beep ()
  686. {
  687. #if defined (__MS_WINDOWS__)
  688.     MessageBeep (MB_ICONQUESTION);
  689.     
  690. #elif defined (__X_MOTIF__)
  691.     XBell (XtDisplay (_current->_xwidget), 100);
  692.     
  693. #endif
  694. }
  695.  
  696.  
  697.  
  698.  
  699.  
  700.