home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / yacl-012.zip / ui / dialog.cxx < prev    next >
C/C++ Source or Header  |  1995-04-06  |  10KB  |  371 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. #if defined(__GNUC__)
  32. #pragma implementation
  33. #endif
  34.  
  35.  
  36.  
  37. #include "ui/dialog.h"
  38. #include "ui/cntroler.h"
  39.  
  40. #if defined(__MS_WINDOWS__)
  41. #include <ctl3d.h>
  42. #endif
  43.  
  44. #if defined(__GNUC__) && __GNUC_MINOR__ >= 6
  45. template class CL_Binding<UI_Dialog>;
  46. #endif
  47.  
  48. class DialogEvent: public CL_Object {
  49.  
  50.     // An encapsulation of a visual-object/event-type pair
  51.     
  52. public:
  53.     DialogEvent (UI_ViewID id, UI_EventType type)
  54.     : _id (id), _type (type) {};
  55.  
  56.     ~DialogEvent () {};
  57.     
  58.     short Compare (const CL_Object& o) const;
  59.  
  60.     void operator = (const CL_Object& o)
  61.         { _id = ((const DialogEvent&) o)._id;
  62.           _type = ((const DialogEvent&) o)._type;};
  63.  
  64.     const char* ClassName() const {return "DialogEvent";};
  65.     
  66. protected:
  67.     UI_ViewID     _id;
  68.     UI_EventType  _type;
  69. };
  70.  
  71.  
  72. short DialogEvent::Compare (const CL_Object& o) const
  73. {
  74.     const DialogEvent& d = (const DialogEvent&) o;
  75.     if (_id == d._id) {
  76.         if (_type == d._type)
  77.             return 0;
  78.         return _type < d._type ? -1 : 1;
  79.     }
  80.     return _id < d._id ? -1 : 1;
  81. }
  82.  
  83.  
  84. typedef CL_Binding<UI_Dialog> DialogBind;
  85.  
  86.  
  87.  
  88. UI_Dialog::UI_Dialog
  89.     (UI_CompositeVObject* parent, UI_ViewDescriptor* vd,
  90.      const UI_Rectangle& shape,   UI_DialogEventDescriptor* qd,
  91.      UI_ViewID id
  92.     )
  93. : UI_CompositeVObject (parent, vd, FALSE, shape, id)
  94. {
  95. #if defined(__MS_WINDOWS__)
  96.     _style = WS_VISIBLE | WS_SYSMENU | WS_CAPTION | DS_MODALFRAME;
  97.     Set3DLook();
  98. #elif defined(__OS2__)
  99.     _style = FCF_TITLEBAR | FCF_SYSMENU | FCF_DLGBORDER;
  100. #endif
  101.     _Init (qd);
  102. }
  103.  
  104.  
  105. void UI_Dialog::_Init (UI_DialogEventDescriptor* qd)
  106. {
  107.     _closed = FALSE;
  108.     _modalState = FALSE;
  109.     if (!qd) {
  110.         AddDialogEvent (UI_IDOK,     Event_Select);
  111.         AddDialogEvent (UI_IDCANCEL, Event_Select);
  112.     }
  113.     else {
  114.         for (short i = 0; qd[i].id != -1 && qd[i].type != View_None; i++) 
  115.             AddDialogEvent (qd[i].id, qd[i].type);
  116.     }
  117.     _lastEvent.id = -1;
  118. }
  119.  
  120.  
  121.  
  122. #if defined(__MS_WINDOWS__)
  123. UI_Dialog::UI_Dialog (UI_CompositeVObject* parent, const char* rsrc,
  124.                       UI_DialogEventDescriptor* qd, UI_ViewID id)
  125. : UI_CompositeVObject(parent, rsrc, id)
  126. {
  127.     Set3DLook ();
  128.     _Init (qd);
  129. }
  130. #endif
  131.  
  132.  
  133.  
  134. UI_Dialog::~UI_Dialog()
  135. {
  136.     _dialogEvents.DestroyContents();
  137. }
  138.  
  139.  
  140.  
  141.  
  142. #if defined(__MS_WINDOWS__)
  143. struct DialogBoxHeader {
  144.     DWORD s; BYTE n; WORD x, y, cx, cy;
  145.     char mnu[1];
  146.     char cls[1];
  147.     char caption[1];
  148.     WORD pt;
  149.     char face[1];
  150. };
  151. #endif
  152.  
  153.  
  154. #if defined(__MS_WINDOWS__)
  155. struct SysFontStruct {
  156.     short width, height;
  157. };
  158.  
  159. static SysFontStruct _SysFontSizes ()
  160. {
  161.     HFONT hFont = GetStockObject (SYSTEM_FONT);
  162.     HDC dc = CreateDC ("DISPLAY", NULL, NULL, NULL);
  163.     HFONT old = SelectObject (dc, hFont);
  164.     TEXTMETRIC tm;
  165.     GetTextMetrics (dc, &tm);
  166.     SelectObject (dc, old);
  167.     DeleteObject (hFont);
  168.     DeleteDC (dc);
  169.     SysFontStruct st;
  170.     st.width  = tm.tmAveCharWidth;
  171.     st.height = tm.tmHeight;
  172.     return st;
  173. }
  174.  
  175. static SysFontStruct _SysFont = _SysFontSizes();
  176. #endif
  177.  
  178.  
  179. bool UI_Dialog::MakeVisualElement ()
  180. {
  181.  
  182. #ifdef __MS_WINDOWS__
  183.     if (CreatedViaResource ())
  184.         return UI_CompositeVObject::MakeVisualElement ();
  185.     long x, y, w, h;
  186.  
  187.     x = _shape.Origin().XCoord();
  188.     y = _shape.Origin().YCoord();
  189.     w = _shape.Width();
  190.     h = _shape.Height();
  191.  
  192.     RECT rect;
  193.     rect.left    = x;
  194.     rect.top     = y;
  195.     rect.right   = x + w;
  196.     rect.bottom  = y + h;
  197.     AdjustWindowRect (&rect, _style, FALSE);
  198.     if (!_visible)
  199.         _style &= ~WS_VISIBLE;
  200.     HGLOBAL hMem = GlobalAlloc (GHND, sizeof (DialogBoxHeader) +
  201.                                 _title.Size() + 1);
  202.     DialogBoxHeader* hdr = (DialogBoxHeader*) GlobalLock (hMem);
  203.     if (hdr) {
  204.         hdr->n = 0;
  205.         short fontWidth = _SysFont.width;
  206.         if (fontWidth <= 0)
  207.             fontWidth = 4;
  208.         short fontHeight = _SysFont.height;
  209.         if (fontHeight <= 0)
  210.             fontHeight = 8;
  211.         hdr->x = rect.left * 4 / fontWidth;
  212.         hdr->y = rect.top * 8 / fontHeight;
  213.         hdr->cx = (rect.right - rect.left + 1) * 4 / fontWidth;
  214.         hdr->cy = (rect.bottom - rect.top + 1) * 8 / fontHeight;
  215.         hdr->cls[0] = '\0';
  216.         hdr->mnu[0] = '\0';
  217.           hdr->caption[0] = '\0';
  218.         hdr->pt = 0;
  219.         hdr->face[0] = '\0';
  220.         // For some reason, the dimensions set up in the hdr structure
  221.         // don't match up on all displays. So we make the dialog
  222.         // initially invisible, call SetWindowPos, and then let the
  223.         // controller make it visible.
  224.         hdr->s = _style & ~WS_VISIBLE;
  225.         _handle = CreateDialogIndirectParam
  226.             (_Application->ProcessId(), hdr,
  227.              _parent ? _parent->ViewHandle() : NULL,
  228.              (FARPROC) YACLDialogProc, 0L);
  229.         SetWindowPos (_handle, NULL, rect.left, rect.top,
  230.                       rect.right - rect.left + 1,
  231.                       rect.bottom - rect.top + 1, 0);
  232.         SendMessage (_handle, WM_SETTEXT,  0, (long)(const char*)_title);
  233.         GlobalFree (hMem);
  234.         Ctl3dSubclassDlgEx (_handle, CTL3D_ALL);
  235.     }
  236.     if (!_handle) {
  237.         CL_Error::Warning ("Window creation failed: id %ld class %s",
  238.                            ViewID(), ClassName());
  239.         return FALSE;
  240.     }
  241. //     SetProp (_handle, _YACLWindowClassName, 1); // Needed to identify these
  242. //                                                  // windows
  243.     return TRUE;
  244.  
  245. #elif defined(__X_MOTIF__)
  246.     return UI_CompositeVObject::MakeVisualElement ();
  247. #elif defined (__OS2__)
  248.     return UI_CompositeVObject::MakeVisualElement ();
  249. #endif
  250. }
  251.  
  252.  
  253.  
  254. UI_DialogEventDescriptor UI_Dialog::ExecuteModal ()
  255. {
  256.     _lastEvent.id = -1;
  257.     _modalState   = TRUE;
  258. // #ifdef __MS_WINDOWS__
  259. //     // Gray out the "Close" in the system menu
  260. //     HMENU h = GetSystemMenu (_handle, FALSE);
  261. //     if (h)
  262. //         EnableMenuItem (h, SC_CLOSE, FALSE);
  263. // #endif
  264.  
  265.     _Controller->DispatchPendingEvents (); // Flush the event queue
  266.     DialogBind filterBind (this, &UI_Dialog::EventFilter);
  267.     DialogBind finishBind (this, &UI_Dialog::RunFinished);
  268.  
  269.     _Controller->EventLoop (&finishBind, &filterBind);
  270.     _modalState = FALSE;
  271.     return _lastEvent;
  272. }
  273.  
  274.  
  275.  
  276. bool UI_Dialog::_DialogEventOccurred (CL_Object& obj, long)
  277. {
  278.     UI_Event& e = (UI_Event&) obj;
  279.     DialogEvent t (e.Origin()->ViewID(), e.Type());
  280.     if (_dialogEvents.Includes (&t)) {
  281.         _lastEvent.id   = e.Origin()->ViewID();
  282.         _lastEvent.type = e.Type();
  283.     }
  284.     return TRUE;
  285. }
  286.  
  287.  
  288.  
  289. static bool IsAncestor (UI_VisualObject* a, UI_VisualObject* b)
  290. {
  291.     // Check if a is an ancestor of b
  292.     if (!a || !b)
  293.         return FALSE;
  294.     while (b && b != a)
  295.         b = b->Parent();
  296.     return b == a;
  297. }
  298.  
  299.  
  300. // #include <iostream.h> // DEBUG
  301. bool UI_Dialog::EventFilter (CL_Object& event, long)
  302. {
  303.     UI_Event* e = &(UI_Event&) event;
  304.     UI_VisualObject* origin = e->Origin();
  305.     UI_VisualObject* dest = e->Destination();
  306.     bool b = (origin == this || dest == this || !origin || !dest
  307.               || e->Type() == Event_MouseMove
  308.               || e->Type() == Event_ViewEnter
  309.               || e->Type() == Event_ViewLeave);
  310.     b |=  IsAncestor (this, origin);
  311. #if defined(__MS_WINDOWS__)
  312.     if (!b && e->Type() == Event_LButtonRelease)
  313.         _Controller->Beep();
  314. #endif
  315. //     cout << "EventFilter: event " << e->Type() << " VObj " <<
  316. //         origin->ClassName() << " id " << origin->ViewID() << " label '" <<
  317. //         origin->Title() << "' returns " << b << endl;
  318.     if (origin == this && dest == this && e->Type() == Event_CloseDown) {
  319.         _closed = TRUE;
  320.         if (!_parent)
  321.             _Application->Destroy (this);
  322.     }
  323.     return b;
  324. }
  325.  
  326.  
  327.  
  328. bool UI_Dialog::RunFinished (CL_Object&, long)
  329. {
  330.     return _lastEvent.id != -1 || _closed;
  331. }
  332.  
  333.  
  334. bool UI_Dialog::AddDialogEvent (UI_ViewID id, UI_EventType type)
  335. {
  336.     DialogBind bind   (this, &UI_Dialog::_DialogEventOccurred);
  337.     AddEventDependent (type, bind, 0); // Last parameter unused
  338.     DialogEvent* d = new DialogEvent (id, type);
  339.     if (_dialogEvents.Add (d))
  340.         return TRUE;
  341.     delete d;
  342.     return FALSE;
  343. }
  344.  
  345.  
  346. bool UI_Dialog::RemoveDialogEvent (UI_ViewID id, UI_EventType type)
  347. {
  348.     DialogBind bind      (this, &UI_Dialog::_DialogEventOccurred);
  349.     RemoveEventDependent (type, bind);
  350.     DialogEvent d (id, type);
  351.     DialogEvent* p = (DialogEvent*) _dialogEvents.Remove (&d);
  352.     if (p) {
  353.         delete p;
  354.         return TRUE;
  355.     }
  356.     return FALSE;
  357. }
  358.  
  359.  
  360.  
  361. void UI_Dialog::CloseDown ()
  362. {
  363.     if (InModalState()) {
  364.         if (WantToQuit ())
  365.             _closed = TRUE;
  366.     }
  367.     else if (WantToQuit())
  368.         _Application->Destroy (this);
  369. }
  370.  
  371.