home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / yacl-012.zip / ui / composit.cxx < prev    next >
C/C++ Source or Header  |  1995-04-04  |  30KB  |  1,025 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. #if defined(__GNUC__)
  31. #pragma implementation
  32. #endif
  33.  
  34.  
  35.  
  36. #if defined(__MS_WINDOWS__)
  37. #    include <windows.h>
  38. #    include <ctl3d.h>
  39. #    include <string.h>
  40.      BOOL CALLBACK _export EnumCallback (HWND hwnd, LPARAM param);
  41. #    define WINDOW_STYLE WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN | \
  42.      WS_BORDER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX
  43. #elif defined(__OS2__)
  44. #    define DEFAULT_COMPOSITE_STYLE \
  45.      FCF_TITLEBAR | FCF_SYSMENU | FCF_SIZEBORDER | FCF_MINMAX | FCF_TASKLIST 
  46. #elif defined(__X_MOTIF__)
  47. #    include <Xm/BulletinB.h>
  48. #    include <X11/Shell.h>
  49. #    include <Xm/Xm.h>
  50. #    include <Xm/Protocols.h>
  51. #    include <Xm/AtomMgr.h>
  52. #    include <Xm/MwmUtil.h>
  53. #    include <iostream.h> // DEBUG only
  54. #endif
  55.  
  56.  
  57. #include "ui/composit.h"
  58. #include "ui/cntroler.h"
  59. #include "ui/pushbtn.h"
  60. #include "ui/toglbtn.h"
  61. #include "ui/xrtglbtn.h"
  62. #include "ui/stred.h"
  63. #include "ui/dialog.h"
  64.  
  65. #include "ui/label.h"
  66. #include "ui/strview.h"
  67. #include "ui/textedit.h"
  68. #include "ui/scrolbar.h"
  69. #include "ui/menu.h"
  70.  
  71. #include "ui/orbtngrp.h"
  72. #include "ui/xrbtngrp.h"
  73.  
  74.  
  75. // ---------------------- UI_CompositeVObject code --------------------
  76.  
  77.  
  78. UI_CompositeVObject :: UI_CompositeVObject 
  79.      ( UI_CompositeVObject* parent, const UI_Rectangle& shape, UI_ViewID id)
  80. : UI_VObjCollection (parent, shape, id)
  81. {
  82.     _stickToParent = FALSE; // Non-sticky by default
  83.     _Init ();
  84. }
  85.  
  86. UI_CompositeVObject :: UI_CompositeVObject 
  87.      ( UI_CompositeVObject* parent, UI_ViewDescriptor* vd, bool sticky,
  88.        const UI_Rectangle& shape, UI_ViewID id
  89.      )
  90. : UI_VObjCollection (parent, shape, id)
  91. {
  92.     _stickToParent = sticky;
  93.     _Init ();
  94.     if (vd) {
  95.         for (short i = 0; vd[i].type != View_None; i++) {
  96.             if ( !CreateChild (vd[i]) )
  97.                 break;
  98.         }
  99.     }
  100. }
  101.  
  102.  
  103. typedef CL_Binding<UI_CompositeVObject> CompositeBind;
  104.  
  105. #if defined(__GNUC__)
  106. template class CL_Binding<UI_CompositeVObject>;
  107. #endif
  108.  
  109.  
  110. void UI_CompositeVObject::_Init ()
  111. {
  112.     _menuBar       = NULL;
  113.     _currentChild  = -1;
  114.     _isTabStop     = _stickToParent; 
  115.     _iconified     = FALSE;
  116.     if (!_parent) {
  117.         // Make a font for the main window
  118.         _font      = new UI_Font (this);
  119.         _ownFont   = TRUE;
  120.     }
  121.     CompositeBind bind (this, &UI_CompositeVObject::_EventOccurred);
  122. #if defined(__MS_WINDOWS__)
  123.     _3dLook = _stickToParent ? _parent->Has3DLook() : FALSE;
  124.     if (_parent == NULL) {
  125.         // Set the style of the root window
  126.         _style = WINDOW_STYLE;
  127.     }
  128.     else {
  129.         // Non-root window
  130.         if (_stickToParent) {
  131.             _style = WS_CHILD;
  132.             if (_visible)
  133.                 _style |=  WS_VISIBLE;
  134.             if (_borderShown)
  135.                 _style |= WS_BORDER;
  136.         }
  137.         else
  138.             _style = WINDOW_STYLE;
  139.     }
  140.     if (!_parent || !_stickToParent)
  141.         _id = 0;
  142.     _titleBarShown = _style & WS_CAPTION;
  143.  
  144. #elif defined(__OS2__)
  145.     _style = _stickToParent ?  WS_VISIBLE | WS_CLIPCHILDREN
  146.         : DEFAULT_COMPOSITE_STYLE;
  147.     _cursor = UICursor_Arrow;
  148. #endif
  149.  
  150. #if defined (__MS_WINDOWS__) || defined(__OS2__)
  151.     // Need focus management under Windows and OS/2
  152.     AddEventDependent (Event_ChildCreated,   bind, 1);
  153.     AddEventDependent (Event_LButtonRelease, bind, 1);
  154.     AddEventDependent (Event_KeyTyped,       bind, 1);
  155. #endif
  156.  
  157.     AddEventDependent (Event_Iconify,        bind, 1);
  158.     AddEventDependent (Event_Deiconify,      bind, 1);
  159.     _model = new CL_IntPtrMap;
  160. }
  161.  
  162.  
  163. #if defined(__MS_WINDOWS__)
  164. static UI_VObjCollection* _CurrentGroup = NULL;
  165. static UI_ViewID          _CurrentGroupId = 0;
  166. static UI_ViewHandle      _CurrentGroupHandle = 0;
  167.  
  168.  
  169. UI_CompositeVObject::UI_CompositeVObject
  170.   (UI_CompositeVObject* parent, const char *rsrc, UI_ViewID id)
  171. : UI_VObjCollection (parent, UI_Rectangle(), id)
  172. {
  173.     _menuBar       = NULL;
  174.     _stickToParent = FALSE;
  175.     _currentChild  = -1;
  176.     _rname = rsrc;
  177.     _CurrentGroup = NULL; // Used only in CreateResourceChild
  178.     _CurrentGroupId = 0;  // Ditto
  179.     _model = new CL_IntPtrMap;
  180.     _3dLook = FALSE;
  181.  
  182.     CompositeBind bind (this, &UI_CompositeVObject::_EventOccurred);
  183.     AddEventDependent (Event_ChildCreated,   bind, 1);
  184.     AddEventDependent (Event_LButtonRelease, bind, 1);
  185.     AddEventDependent (Event_KeyTyped,       bind, 1);
  186.     AddEventDependent (Event_Iconify,        bind, 1);
  187.     AddEventDependent (Event_Deiconify,      bind, 1);
  188. }
  189. #endif
  190.  
  191.  
  192. #if defined(__MS_WINDOWS__)
  193. void UI_CompositeVObject::Set3DLook ()
  194. {
  195.     _3dLook = TRUE;
  196. }
  197.  
  198. bool UI_CompositeVObject::Has3DLook () const
  199. {
  200.     return     _3dLook ? TRUE : (_parent ? _parent->Has3DLook() : FALSE);
  201. }
  202.  
  203.  
  204. #endif
  205.  
  206.  
  207. CL_Object& UI_CompositeVObject::Model ()
  208. {
  209.     // Update all the models. This is needed so that the component objects
  210.     // can update their model values from the underlying window system.
  211.     CL_IntPtrMap& model_map = *(CL_IntPtrMap*) _model;
  212.     CL_IntPtrMapIterator itr (_objMap);
  213.     while (itr.More()) {
  214.         CL_IntPtrAssoc assoc = itr.Next();
  215.         UI_VisualObject* v = (UI_VisualObject*) assoc.value;
  216.         UI_ViewID id = v->ViewID();
  217.         if (model_map.IncludesKey (id))
  218.             model_map[id] = & (v->Model());
  219.     }
  220.     return *_model;
  221. }
  222.  
  223.  
  224.  
  225. bool UI_CompositeVObject::MakeVisualElement ()
  226. {
  227.  
  228. #ifdef __MS_WINDOWS__
  229.     HANDLE hInst = _Application->ProcessId();
  230.     const char* label = (_title.Length() > 0) ? _title.AsPtr() : NULL;
  231.     if(_rname.Size ()) {
  232.         // Resource-based dialog
  233.         _handle = CreateDialogParam
  234.             (hInst, _rname.AsPtr(), _parent ? _parent->ViewHandle() : NULL,
  235.              (FARPROC) YACLDialogProc, 0L);
  236.         SendMessage (_handle, WM_SETTEXT,  0, (long) label);
  237.         _style = GetWindowLong (_handle, GWL_STYLE);
  238.         _visible = (_style & WS_VISIBLE) ? TRUE : FALSE;
  239.         return TRUE;
  240.     }
  241.  
  242.     // Generic window
  243.     RECT shapeRect = _shape.AsMSRect ();
  244.     if (!_parent || !_stickToParent)
  245.         AdjustWindowRect (&shapeRect, _style, FALSE);
  246.     short x = shapeRect.left;
  247.     short y = shapeRect.top;
  248.     short w = shapeRect.right - shapeRect.left;
  249.     short h = shapeRect.bottom - shapeRect.top;
  250.     const char* class_name = WindowClass ();
  251.     if (!_visible)
  252.         _style &= ~WS_VISIBLE;
  253.     HWND parentHandle = _parent ? _parent->ViewHandle() : 0;
  254.     _handle = CreateWindow (class_name, label, _style, x, y, w, h,
  255.                             parentHandle, _id, (HANDLE) hInst, NULL);
  256.     if (!_handle) {
  257.         CL_Error::Warning
  258.             ("YACL: VisualObject CreateWindow failed:\nClass %s ID %d",
  259.              class_name, _id);
  260.         return FALSE;
  261.     }
  262.     return TRUE;
  263.  
  264. #elif defined(__X_MOTIF__)
  265.     CL_String xname (InstanceName ());
  266.     Arg args [9];
  267.     short argn = 0;
  268.     XtSetArg (args[argn], XmNresizePolicy, XmRESIZE_NONE); argn++;
  269.     _SetupStyle (args, argn);
  270.  
  271.     struct _WidgetClassRec  *wname = WindowClass ();
  272.     if ( wname == NULL )
  273.         wname = xmBulletinBoardWidgetClass;
  274.     if (!_parent && !_shell)
  275.         CL_Error::Fatal ("Root Window Not Created");
  276.  
  277.     Widget real_parent = _parent && _stickToParent
  278.         ? _parent->ViewHandle() : _shell;
  279.     if (!_parent || _stickToParent)
  280.         _popup  = NULL;
  281.     if (!_parent) { // Creating the root window
  282.         _xwidget = XtCreateManagedWidget
  283.             ((const char*) xname, wname, real_parent, args, argn);
  284.         if (! XtIsRealized (_shell) )
  285.             XtRealizeWidget (_shell);
  286.     }
  287.     else if (_stickToParent) { // Creating a non-root sticky child
  288.         _xwidget = XtCreateWidget
  289.             ((const char*) xname, wname, real_parent, args, argn);
  290.     }
  291.     else {
  292.         XtSetArg (args [argn], XmNtitle, (char*) _title.AsPtr()); argn++;
  293.         // Set the title of the shell widget
  294.         XtSetArg (args [argn], XmNdeleteResponse, XmDO_NOTHING); argn++;
  295.         // Do not destroy the shell widget in response to user
  296.         // requests; the library will take care of it.
  297.         
  298.         _popup = XtCreatePopupShell ((const char*) (xname + "_shell"),
  299.                                      vendorShellWidgetClass,
  300.                                      _parent->ViewHandle(),
  301.                                      args, argn);
  302.         _xwidget = XtCreateManagedWidget
  303.             ((const char*) xname, wname, _popup, args, 2);
  304.         XtPopup (_popup, XtGrabNone);
  305.     };
  306.     if (!_stickToParent) {
  307.         UI_VisualObject::ViewSize minSize = MinSize();
  308.         UI_VisualObject::ViewSize maxSize = MaxSize();
  309.         XtVaSetValues (XtParent (_xwidget),
  310.                        XmNminWidth,  minSize._width,
  311.                        XmNmaxWidth,  maxSize._width,
  312.                        XmNminHeight, minSize._height,
  313.                        XmNmaxHeight, maxSize._height,
  314.                        NULL
  315.                       );
  316.     }
  317.     return TRUE;
  318.  
  319. #elif defined(__OS2__)
  320.     if (_parent && _stickToParent)
  321.         return UI_VObjCollection::MakeVisualElement ();
  322.  
  323.     // So now let's worry about stand-alone windows
  324.     HWND parentHandle =  HWND_DESKTOP;
  325.     _frameHandle = WinCreateStdWindow
  326.         (HWND_DESKTOP, 0, &_style,
  327.          WindowClass(), _title.AsPtr(), 0, 0, _id, &_handle);
  328.     // Compute the required frame rectangle; remember that _shape is
  329.     // specified assuming that YACL uses origin at top left corner, but
  330.     // OS/2 uses origin at bottom left corner.
  331.     long parentHeight = _YACLWindowHeight (parentHandle);
  332.     RECTL boundary;
  333.     long left   = _shape.Left(),   top   = _shape.Top ();
  334.     long height = _shape.Height(), width = _shape.Width ();
  335.     boundary.xLeft   = left;
  336.     boundary.yBottom = parentHeight - top - height;
  337.     boundary.xRight  = left + width - 1;
  338.     boundary.yTop    = parentHeight - top;
  339.     WinMapWindowPoints (_handle, parentHandle, (PPOINTL) &boundary, 2);
  340.     WinCalcFrameRect   (_frameHandle, &boundary, FALSE);
  341.  
  342.     // Now set up and show the window
  343.     WinSetWindowPos (_frameHandle, HWND_TOP,
  344.                      boundary.xLeft, boundary.yBottom,
  345.                      boundary.xRight - boundary.xLeft + 1,
  346.                      boundary.yTop   - boundary.yBottom + 1,
  347.                      SWP_SIZE | SWP_MOVE | SWP_ACTIVATE | SWP_SHOW
  348.                      );
  349.     return TRUE;
  350. #endif
  351. }
  352.  
  353. UI_Rectangle UI_CompositeVObject::Area () const
  354. {
  355. #if defined(__OS2__)
  356.     if (_stickToParent)
  357.         return UI_VisualObject::Area ();
  358.     RECTL rect;
  359.     WinQueryWindowRect (_frameHandle, &rect);
  360.     return _Application->YACLRect (_parent ? _parent->ViewHandle()
  361.                                    : HWND_DESKTOP,
  362.                                    rect);
  363. #else
  364.     return UI_VisualObject::Area ();
  365. #endif
  366. }
  367.  
  368.  
  369. bool UI_CompositeVObject::DestroyVisualElement ()
  370. {
  371.     DestroyDisplaySurface ();
  372.  
  373. #if defined (__MS_WINDOWS__)
  374.     if (_handle > 0) {
  375.         DestroyWindow (_handle);
  376.         return TRUE;
  377.     }
  378.     return FALSE;
  379.  
  380. #elif defined(__X_MOTIF__)
  381.     if( _xwidget !=NULL )
  382.         XtDestroyWidget (_xwidget);
  383.     if (_popup)
  384.         XtPopdown (_popup);
  385.  
  386. #elif defined(__OS2__)
  387.     WinDestroyWindow (_frameHandle);
  388.     return TRUE;
  389. #endif
  390.  
  391. }
  392.  
  393.     
  394.  
  395.  
  396. UI_VisualObject* UI_CompositeVObject::CreateChild (const UI_ViewDescriptor& vd)
  397. {
  398.     if (_objMap.IncludesKey (vd.id)) {
  399.         CL_Error::Warning ("YACL: Duplicate child id %ld for composite",
  400.                            vd.id);
  401.         return NULL;
  402.     }
  403.     UI_VisualObject* p;
  404.     UI_Rectangle shape (vd.shape.x, vd.shape.y, vd.shape.w,
  405.                         vd.shape.h);
  406.     switch (vd.type) {
  407.  
  408.     case View_OrButtonGroup:
  409.         p = new UI_OrButtonGroup (this, shape, vd.id, vd.enclosed);
  410.         p->Title () = vd.title;
  411.         break;
  412.  
  413.     case View_ExOrButtonGroup:
  414.         p = new UI_ExOrButtonGroup (this, shape, vd.id, vd.enclosed);
  415.         p->Title () = vd.title;
  416.         break;
  417.  
  418.     case View_PushButton:
  419.         p = new UI_PushButton (this, shape, vd.id);    
  420.         p->Title()= vd.title;
  421.         break;
  422.  
  423.     case View_ToggleButton:
  424.         p = new UI_ToggleButton (this, shape, vd.id);  
  425.         p->Title() = vd.title;
  426.         break; 
  427.  
  428.     case View_ExOrToggleButton:
  429.         p = new UI_ExOrToggleButton (this, shape, vd.id);  
  430.         p->Title() = vd.title;
  431.         break; 
  432.  
  433.       
  434.     case View_Label:
  435.         p = new UI_Label (this, shape, vd.id);
  436.         (CL_String&) (((UI_Label*) p)->Model ()) = vd.title;
  437.         break;
  438.  
  439.     case View_StringEditor:
  440.         p = new UI_StringEditor (this, shape, vd.id);
  441.         (CL_String&) (((UI_SimpleVObject*) p)->Model ()) = vd.title;
  442.         break;
  443.  
  444.  
  445.     case View_TextView:
  446.         p = new UI_TextEditor (this, shape, vd.id);
  447.         (CL_String&) (((UI_SimpleVObject*) p)->Model ()) = vd.title;
  448.         break;
  449.  
  450.     case View_StringView:
  451.         p = new UI_StringViewSingleSel (this, shape, vd.id);
  452.         break;
  453.     
  454.     case View_HScrollBar:
  455.         p = new UI_HScrollBar (this, shape, vd.id);
  456.         break;
  457.  
  458.     
  459.     case View_VScrollBar:
  460.         p = new UI_VScrollBar (this, shape, vd.id);
  461.         break;
  462.  
  463.  
  464.     case View_MultiSelectStringView:
  465.         p = new UI_StringViewMultiSel (this, shape, vd.id);
  466.         break;
  467.  
  468.  
  469.     case View_Composite:
  470.         p = new UI_CompositeVObject (this, vd.enclosed, TRUE, shape,
  471.                                      vd.id);
  472.         break;
  473.  
  474.  
  475.     default:
  476.         p = NULL;
  477.         break;
  478.     } // end of switch
  479.  
  480.     if ( p && vd.type != View_Composite ) {
  481.         UI_ViewID id = p->ViewID();
  482.  
  483.         if (id > 0 && id <= 32767) {
  484.             ((CL_IntPtrMap*) _model)->Add (id, &(p->Model()));
  485.             if (vd.type != View_OrButtonGroup &&
  486.                 vd.type != View_ExOrButtonGroup)
  487.                 ((UI_SimpleVObject*) p)->TabStop (vd.tab_stop);
  488.         }
  489.     }
  490.     return p;
  491. }
  492.  
  493.  
  494.  
  495.  
  496. UI_CompositeVObject::~UI_CompositeVObject()
  497. {
  498.     if (_model)
  499.         delete _model;
  500. }
  501.  
  502.  
  503.  
  504.  
  505.  
  506.  
  507.  
  508. void UI_CompositeVObject::ShowTitleBar ()
  509. {
  510. #if defined(__MS_WINDOWS__)
  511.     if (!_stickToParent) {
  512.         long l = GetWindowLong (_handle, GWL_STYLE);
  513.         SetWindowLong (_handle, GWL_STYLE, l | WS_CAPTION);
  514.         SetWindowPos  (_handle, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | 
  515.                        SWP_NOSIZE | SWP_NOMOVE | 
  516.                        SWP_NOACTIVATE | SWP_NOZORDER); // Force re-draw
  517.         _titleBarShown = TRUE;
  518.     }
  519. #elif defined(__X_MOTIF__)
  520.     if (!_stickToParent) {
  521.         Arg arg[1];
  522.         XtSetArg (arg[0], XtNtransient, FALSE);
  523.         XtSetValues (XtParent (_xwidget), arg, 1);
  524.     }
  525. #endif
  526. }
  527.  
  528.  
  529. void UI_CompositeVObject::HideTitleBar ()
  530. {
  531. #if defined(__MS_WINDOWS__)
  532.     if (!_stickToParent) {
  533.         long l = GetWindowLong (_handle, GWL_STYLE);
  534.         SetWindowLong (_handle, GWL_STYLE, l & ~WS_CAPTION);
  535.         SetWindowPos  (_handle, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | 
  536.                        SWP_NOSIZE | SWP_NOMOVE | 
  537.                        SWP_NOACTIVATE | SWP_NOZORDER); // Force re-draw
  538.         _titleBarShown = FALSE;
  539.     }
  540. #elif defined(__X_MOTIF__)
  541.     if (!_stickToParent) {
  542.         Arg arg[1];
  543.         XtSetArg (arg[0], XtNtransient, FALSE);
  544.         XtSetValues (XtParent (_xwidget), arg, 1);
  545.     }
  546. #endif
  547. }
  548.  
  549.  
  550. bool UI_CompositeVObject::IsTitleBarShown ()
  551. {
  552.     return !_stickToParent && _titleBarShown;
  553. }
  554.  
  555.  
  556.  
  557.  
  558.  
  559.  
  560.  
  561.  
  562. void UI_CompositeVObject::_PrivateInitialize()
  563. {
  564.     UI_VisualObject::_PrivateInitialize ();
  565.  
  566. #if defined(__MS_WINDOWS__)
  567.     if ( _menuBar && _menuBar->ViewHandle() > 0 )
  568.         DrawMenuBar ( _menuBar->ViewHandle() );
  569.     if(_rname.Size() > 0  && _handle)
  570.         EnumChildWindows (_handle, (FARPROC) EnumCallback, (long) this);
  571.  
  572. #elif defined(__X_MOTIF__)
  573.  
  574.     Arg args [2];
  575.     XmString xmtitle;
  576.  
  577.     xmtitle = XmStringCreate ((char*)_title.AsPtr(), XmSTRING_DEFAULT_CHARSET);
  578.  
  579.     XtSetArg    (args [0], XmNdialogTitle, xmtitle);
  580.     XtSetArg    (args [1], XmNlabelString, xmtitle);
  581.     XtSetValues (_xwidget, args, 2);
  582.  
  583.     if (!_parent || !_stickToParent) {
  584.         Atom a = XmInternAtom (XtDisplay(_shell), "WM_DELETE_WINDOW",
  585.                                FALSE);
  586.         XmAddWMProtocolCallback
  587.             (XtParent (_xwidget), a,
  588.              (XtCallbackProc)  &UI_CompositeVObject::DeleteWindowCallback,
  589.              (XtPointer) this);
  590.     }
  591.     XmStringFree (xmtitle); // No leaks allowed
  592.  
  593.     // Invalidate ();
  594. #endif
  595.     if (!_visible)
  596.         MakeInvisible();
  597. }
  598.  
  599.  
  600. #if defined (__X_MOTIF__)
  601. void UI_CompositeVObject::DeleteWindowCallback
  602.     (Widget w, void* client, void* call)
  603. {
  604.     UI_CompositeVObject* v = (UI_CompositeVObject*) client;
  605.     v->_Controller->AddEvent (new UI_Event (Event_CloseDown, v, v));
  606. }
  607. #endif
  608.  
  609.  
  610.  
  611.  
  612. //
  613. //------------------Composite Methods------------------------------
  614. //
  615.  
  616.  
  617.  
  618.  
  619. bool UI_CompositeVObject::HandleChildEvent (const UI_Event&)
  620. {
  621.     return FALSE;
  622. }
  623.  
  624.  
  625. bool UI_CompositeVObject::_EventOccurred (CL_Object& o, long)
  626. {
  627.     UI_Event& e = (UI_Event&) o;
  628.     UI_EventType type = e.Type();
  629.     UI_VisualObject* v = e.Origin();
  630.     switch (type) {
  631. #if defined(__MS_WINDOWS__) || defined(__OS2__)
  632.     // Focus management is only needed under Windows and OS/2
  633.     case Event_ChildCreated: {
  634.         if (v->Parent() != this)
  635.             break;
  636.         short pos = -1;
  637.         if (v->IsTabStop()) {
  638.             pos = _tabSequence.Add (v);
  639.             if (_currentChild == -1 && v->IsVisible() && v->IsEnabled()) {
  640.                 _currentChild = pos;
  641.                 v->TakeFocus();
  642.             }
  643.         }
  644.         break;
  645.     }
  646.     
  647.     case Event_LButtonRelease:
  648.         MoveFocusTo (e.Origin());
  649.         break;
  650.  
  651.     case Event_KeyTyped:
  652.         if (e.Type () == Event_KeyTyped && e.key == '\011') {
  653.             if (e.Destination() == this) 
  654.                 return !AdvanceFocus (e._shiftKey ? -1 : 1);
  655.             else
  656.                 return FALSE;
  657.         }
  658.         else
  659.             return TRUE;
  660.             
  661. #endif // Windows or OS2
  662.  
  663.     case Event_Iconify:
  664.         _iconified = TRUE;
  665.         break;
  666.  
  667.     case Event_Deiconify:
  668.         _iconified = FALSE;
  669.         break;
  670.     };
  671.  
  672.     return TRUE;
  673. }
  674.  
  675.  
  676.  
  677. UI_WindowClass UI_CompositeVObject::WindowClass () const
  678. {
  679. #if defined(__MS_WINDOWS__)
  680.     return _YACLWindowClassName;
  681. #elif defined(__OS2__)
  682.     return _YACLWindowClassName;
  683. #elif defined(__X_MOTIF__)
  684.     return xmBulletinBoardWidgetClass;
  685. #endif
  686. }
  687.  
  688.  
  689. #if defined(__MS_WINDOWS__)
  690.  
  691. BOOL CALLBACK _export EnumCallback (HWND hwnd, LPARAM param)
  692. {
  693.     if (!hwnd)
  694.         return FALSE;
  695.     char buffer[30];
  696.     if ((GetClassName (hwnd, buffer, 30)) == 0)
  697.         return FALSE;
  698.     ((UI_CompositeVObject*) param)->CreateResourceChild (hwnd, buffer);
  699.     return TRUE;
  700. }
  701.  
  702. bool UI_CompositeVObject::CreateResourceChild
  703.     (UI_ViewHandle hndl, const CL_String& ctrl_name)
  704. {
  705.     long n;
  706.     n = GetWindowTextLength (hndl);
  707.     char* buf = "";
  708.     CL_String mdl;   
  709.     if (n) {
  710.         buf = new char[n+1];
  711.         GetWindowText (hndl,buf,n+1);
  712.         mdl = buf;
  713.         delete buf;
  714.     }
  715.   
  716.     // Begin construction:
  717.  
  718.     UI_ViewID id = GetWindowWord (hndl, GWW_ID);
  719.     CL_String name = ctrl_name.InLowerCase ();
  720.     long ctrl_style = GetWindowLong (hndl, GWL_STYLE);
  721.     RECT clientRect;
  722.     GetClientRect (hndl, &clientRect);
  723.     UI_Rectangle shape (clientRect.left, clientRect.top,
  724.                         clientRect.right  - clientRect.left+1,
  725.                         clientRect.bottom - clientRect.top + 1);
  726.     if (name == "button") {
  727.         long style_bits = 0xff; // Depends on Windows 3.1!!
  728.         long style = ctrl_style & style_bits;
  729.         if (style != BS_GROUPBOX &&
  730.             style != BS_RADIOBUTTON && style != BS_AUTORADIOBUTTON &&
  731.             style != BS_CHECKBOX && style != BS_AUTOCHECKBOX) {
  732.             _CurrentGroup = NULL;
  733.             _CurrentGroupId = 0;
  734.         }
  735.         if (style == BS_GROUPBOX) {
  736.             _CurrentGroup = NULL;
  737.             _CurrentGroupId = id;
  738.             _CurrentGroupHandle = hndl;
  739.         }
  740.         else if (style == BS_AUTOCHECKBOX || style == BS_CHECKBOX) {
  741.             if (!_CurrentGroup && _CurrentGroupId) {
  742.                 _CurrentGroup = new UI_OrButtonGroup
  743.                     (this, _CurrentGroupId, _CurrentGroupHandle);
  744.                 initSimple (_CurrentGroup);
  745.             }
  746.             UI_ToggleButton* v = new UI_ToggleButton
  747.                 (_CurrentGroup ? _CurrentGroup : this, id, hndl);    
  748.             initSimple (v);
  749.         }
  750.         else if (style == BS_AUTORADIOBUTTON || style == BS_RADIOBUTTON) {
  751.             if (!_CurrentGroup && _CurrentGroupId) {
  752.                 _CurrentGroup = new UI_ExOrButtonGroup
  753.                     (this, _CurrentGroupId, _CurrentGroupHandle);
  754.                 initSimple (_CurrentGroup);
  755.             }
  756.             UI_ExOrToggleButton* v = new UI_ExOrToggleButton
  757.                 (_CurrentGroup ? (UI_CompositeVObject*) _CurrentGroup :
  758.                  this, id, hndl);
  759.             initSimple (v);
  760.         }
  761.         else {
  762.             // Must be a push button
  763.             UI_PushButton *v;
  764.             v = new UI_PushButton (this, id, hndl);
  765.             initSimple (v);
  766.         } 
  767.     }
  768.     else if (name == "static") {
  769.         UI_Label* v = new UI_Label (this, id, hndl);
  770.         initSimple (v);
  771.     }
  772.     else if (name == "edit") {
  773.         UI_StringEditor* v = new UI_StringEditor (this, id, hndl);
  774.         initSimple (v);
  775.     }
  776.     else if (name == "listbox") {
  777.         UI_StringView* v;
  778.         if (ctrl_style & LBS_MULTIPLESEL)
  779.             v = new UI_StringViewMultiSel  (this, id, hndl);
  780.         else
  781.             v = new UI_StringViewSingleSel (this, id, hndl);
  782.         initSimple (v);
  783.     }
  784.     return TRUE;
  785. }
  786. #endif
  787.  
  788.  
  789. void UI_CompositeVObject::initSimple (UI_VisualObject* s)
  790. {
  791.     if (s) {
  792.         ((UI_SimpleVObject*) s)->SetStyleParam();
  793.         if (s->Parent() == this) {
  794.             UI_ViewID id = s->ViewID();
  795.             if (id > 0 && id <= 32767) {
  796.                 _objMap.Add (id, s);
  797.                 ((CL_IntPtrMap*) _model)->Add (id, &(s->Model()));
  798.             }
  799.             if (s->IsTabStop()) {
  800.                 long pos = _tabSequence.Add (s);
  801.                 if (_currentChild == -1)
  802.                     _currentChild = pos;
  803.             }
  804.         }
  805.     }
  806. }
  807.  
  808.  
  809.  
  810.  
  811.  
  812.  
  813.  
  814. bool UI_CompositeVObject::UseMenuBar  (UI_MenuBar* menu)
  815. {
  816. #if defined(__MS_WINDOWS__)
  817.     if (!_menuBar) {
  818.         RECT rect = _shape.AsMSRect();
  819.         AdjustWindowRect (&rect, _style, TRUE);
  820.     }        
  821. #endif
  822.     _menuBar = menu;
  823.  
  824.     _Controller->DispatchPendingEvents (); // So that the menu is created,
  825.                                            // and its handle is available
  826. #if defined(__MS_WINDOWS__)
  827.     UI_ViewHandle hmenu = menu ? menu->ViewHandle() : 0;
  828.     SetMenu (_handle, hmenu);
  829.  
  830.     // Now recompute the client rectangle
  831.     RECT msrec;
  832.     GetClientRect (_handle, &msrec);
  833.     POINT ms_pt;
  834.     ms_pt.x = ms_pt.y = 0;
  835.     ClientToScreen (_handle, &ms_pt);
  836.     UI_Rectangle rec (ms_pt.x, ms_pt.y, msrec.right - msrec.left + 1,
  837.                       msrec.bottom - msrec.top + 1);
  838.     _SetShapeRectangle (rec);
  839. #endif
  840.     return TRUE;
  841. }
  842.  
  843.     
  844.  
  845. // Return the menu used by this composite. Return NULL if there is no
  846. // associated menu.
  847. UI_MenuBar* UI_CompositeVObject::MenuBar () const
  848. {
  849.     return _menuBar;
  850. }
  851.  
  852.  
  853. #if defined(__MS_WINDOWS__) || defined(__OS2__)
  854. void UI_CompositeVObject::TakeFocus ()
  855. {
  856.     if (_currentChild >= 0) {
  857.         UI_VisualObject* v = (UI_VisualObject*) _tabSequence[_currentChild];
  858.         if (v)
  859.             v->TakeFocus();
  860.     }
  861. }
  862.  
  863.  
  864. void UI_CompositeVObject::MoveFocusTo (UI_VisualObject* child)
  865. {
  866.     if (!(child && child->IsTabStop() && child->IsVisible() &&
  867.           child->IsEnabled()))
  868.         return;
  869.     short pos = _tabSequence.LinearSearch (child);
  870.     if (pos) {
  871.         _currentChild = pos;
  872.         child->TakeFocus();
  873.     }
  874. }
  875.  
  876. bool UI_CompositeVObject::AdvanceFocus (short n)
  877. {
  878.     long size = _tabSequence.Size();
  879.     if (n != 1 && n != -1 ||  size <= 1)
  880.         return FALSE;
  881.     short pos = _currentChild == -1 ? 0 : _currentChild + n;
  882.     UI_VisualObject* v = NULL;
  883.     if (_stickToParent) {
  884.         // Stop if hit end of sequence in either direction
  885.         for (short i = pos; i >= 0 && i < size; i += n) {
  886.             v = (UI_VisualObject*) _tabSequence[pos];
  887.             if (v->IsVisible() && v->IsEnabled() && v->IsTabStop())
  888.                 break;
  889.         }
  890.         if (i < 0 || i >= size)
  891.             return FALSE;
  892.         v->TakeFocus ();
  893.         _currentChild = i;
  894.         return TRUE;
  895.     }
  896.  
  897.     // We don't stick to our parent, so we manage all tabbing within
  898.     // ourselves.
  899.     if (pos == size)
  900.         pos = 0;
  901.     else if (pos == -1)
  902.         pos = size-1;
  903.     while (pos != _currentChild) {
  904.         v = (UI_VisualObject*) _tabSequence[pos];
  905.         if (v->IsVisible() && v->IsEnabled() && v->IsTabStop())
  906.             break;
  907.         pos = (pos + n) % size;
  908.         if (pos == -1)
  909.             pos += size;
  910.     }
  911.     if (pos != _currentChild) {
  912.         v->TakeFocus();
  913.         _currentChild = pos;
  914.     }
  915.     return TRUE;
  916. }
  917.  
  918. #endif
  919.  
  920.  
  921. UI_VisualObject* UI_CompositeVObject::RemoveChild (UI_VisualObject* view)
  922. {
  923.     if (view) {
  924.         short index = _tabSequence.LinearSearch (view);
  925.         if (index >= 0)
  926.             _tabSequence.Remove (index);
  927.     }
  928.     UI_VObjCollection::RemoveChild (view);
  929.     return view;
  930. }
  931.  
  932. void UI_CompositeVObject::AddChild (UI_VisualObject* child)
  933. {
  934.     // Called from child->UI_VisualObject::_Init
  935.     if (!child)
  936.         return;
  937.     UI_VObjCollection::AddChild (child);
  938.     UI_ViewID id = child->ViewID();
  939.     if (id > 0 && id <= 32767) {
  940.         CL_IntPtrMap& modelMap = *(CL_IntPtrMap*) _model;
  941.         modelMap.Add (id, &(child->Model()));
  942.     }
  943. }
  944.  
  945.  
  946. bool UI_CompositeVObject::_ShapeRectChanged (CL_Object& o, long v)
  947. {
  948. #if defined(__MS_WINDOWS__)
  949.     return UI_VisualObject::_ShapeRectChanged (o, v);
  950. #elif defined(__OS2__)
  951.     if (_stickToParent || _handle  <= 0)
  952.         return UI_VObjCollection::_ShapeRectChanged (o, v);
  953.     long ht = _YACLWindowHeight (_parent ? _parent->ViewHandle()
  954.                                 : HWND_DESKTOP);
  955.     SWP swp, frameSwp;
  956.     WinQueryWindowPos  (_handle, &swp);
  957.     WinQueryWindowPos  (_frameHandle, &frameSwp);
  958.     long newX = _shape.Left() - swp.x;
  959.     long newY = ht - _shape.Bottom () - swp.y;
  960.     long newW = _shape.Width()  + frameSwp.cx - swp.cx;
  961.     long newH = _shape.Height() + frameSwp.cy - swp.cy;
  962.     WinSetWindowPos (_frameHandle, HWND_TOP, newX, newY, newW, newH,
  963.                      SWP_SIZE | SWP_MOVE);
  964.     WinQueryWindowPos (_frameHandle, &frameSwp);
  965.     return TRUE;
  966. #elif defined (__X_MOTIF__)
  967.     if (!_xwidget || _stickToParent)
  968.         return UI_VisualObject::_ShapeRectChanged (o, v);
  969.     // Need to do this only for non-sticky children under X: they have a
  970.     // dialog shell, and its shape must be changed, not that of the
  971.     // Composite.
  972.     Arg arg[4];
  973.     short argn = 0;
  974.     long x = _shape.Origin().XCoord();
  975.     long y = _shape.Origin().YCoord();
  976.     long w = _shape.Width();
  977.     long h = _shape.Height();
  978.     XtSetArg (arg [ argn ], XtNx,     x); argn++;
  979.     XtSetArg (arg [ argn ], XtNy,     y); argn++;
  980.     XtSetArg (arg [ argn ], XtNheight,h); argn++;
  981.     XtSetArg (arg [ argn ], XtNwidth, w); argn++;
  982.     XtSetValues (XtParent (_xwidget), arg, argn);
  983.     return TRUE;
  984. #endif
  985.     
  986. }
  987.  
  988.  
  989. bool UI_CompositeVObject::_TitleChanged (CL_Object& o, long v)
  990. {
  991. #if defined(__MS_WINDOWS__)
  992.     return UI_VisualObject::_TitleChanged (o, v);
  993.  
  994. #elif defined(__OS2__)
  995.     if (_stickToParent)
  996.         return UI_VisualObject::_TitleChanged (o, v);
  997.     if (_frameHandle)
  998.         return (WinSetWindowText (_frameHandle, _title.AsPtr()) ? TRUE :
  999.                 FALSE);
  1000.     return TRUE;
  1001. #elif defined(__X_MOTIF__)
  1002.     if (!_xwidget || _stickToParent)
  1003.         return UI_VisualObject::_TitleChanged (o, v);
  1004.     // Need to do this only for non-sticky children under X: they have a
  1005.     // dialog shell, and its title must be changed, not that of the
  1006.     // Composite.
  1007.     Arg args [2];
  1008.     XmString xmtitle;
  1009.  
  1010.     xmtitle = XmStringCreate ((char*)_title.AsPtr(), XmSTRING_DEFAULT_CHARSET);
  1011.  
  1012.     XtSetArg    (args [0], XmNdialogTitle, xmtitle);
  1013.     XtSetArg    (args [1], XmNlabelString, xmtitle);
  1014.     XtSetValues (XtParent (_xwidget), args, 2);
  1015.  
  1016.     XmStringFree (xmtitle); // No leaks allowed
  1017.     XtVaSetValues (XtParent (_xwidget), XmNtitle,
  1018.                    (char*) _title.AsPtr(), NULL);
  1019.     return TRUE;
  1020. #endif
  1021. }
  1022.  
  1023.  
  1024.  
  1025.