home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / yacl-012.zip / ui / xrtglbtn.cxx < prev    next >
C/C++ Source or Header  |  1995-04-04  |  8KB  |  265 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. #include "ui/xrtglbtn.h"
  39. #include "ui/xrbtngrp.h"
  40. #include "ui/cntroler.h"
  41.  
  42. #include "base/integer.h"
  43. #include "base/intset.h"
  44.  
  45. #if defined (__X_MOTIF__)
  46. #include <Xm/ToggleB.h>
  47.  
  48. #endif
  49.  
  50.  
  51. //------------------------------------------------------------------
  52. //                     CLASS ExOrToggleButton
  53. //------------------------------------------------------------------
  54.  
  55. #if defined(__MS_WINDOWS__)
  56. #include <windows.h>
  57. #define EXOR_TOGGLE_BUTTON_STYLE \
  58.     BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE
  59. #elif defined(__OS2__)
  60. #define EXOR_TOGGLE_BUTTON_STYLE BS_AUTORADIOBUTTON | WS_VISIBLE
  61. #endif
  62.  
  63. #if defined(__MS_WINDOWS__)
  64. // We have to subclass the button *after* the Ctl3d subclass in order to
  65. // paint its background properly.
  66. #define PROP1 "YACL_XRBTN_PROP1"
  67. #define PROP2 "YACL_XRBTN_PROP2"
  68. static long FAR PASCAL _export BtnProc (HWND hWnd, unsigned msg, WORD
  69.                                         wParam, LONG lParam)
  70. {
  71.     // This feels like a hack; should really use the Controller's
  72.     // TranslateNativeEvent.
  73.     int low = GetProp (hWnd, PROP1);
  74.     int hi  = GetProp (hWnd, PROP2);
  75.     if (!low || !hi)
  76.         return DefWindowProc (hWnd, msg, wParam, lParam);
  77.     if (msg == WM_KEYDOWN &&
  78.         (wParam == VK_UP || wParam == VK_DOWN || wParam == VK_LEFT ||
  79.          wParam == VK_RIGHT)) {
  80.         // ----^^^^^^^^------
  81.         // Yet another hack. Windows sends WM_CHAR messages to *both* this
  82.         // subclassing proc and the main event loop in ProcessNativeEvents.
  83.         // But it doesn't send WM_CHAR if an arrow key is typed. So we send
  84.         // the arrow key to the button group parent.
  85.         UI_Controller& ctrl = _TheApplication->Controller();
  86.         UI_VisualObject* v = ctrl[hWnd];
  87.         UI_Event* e = new UI_Event (Event_KeyTyped, v, v);
  88.         e->key = wParam;
  89.         ctrl.AddEvent (e);
  90.     }
  91.     else
  92.         if (msg == WM_ERASEBKGND) {
  93.         // Catch the ERASEBKGND message *before* it gets to the button, and
  94.         // fill its background with grey:
  95.         RECT rect;
  96.         GetClientRect (hWnd, &rect);
  97.         HBRUSH brush = GetClassWord (GetParent (hWnd), GCW_HBRBACKGROUND);
  98.         FillRect ((HDC) wParam, &rect, brush);
  99.         // Now just call the real proc, pretending that no painting was
  100.         // done, and let it do its thing:
  101.     }
  102.     FARPROC realProc = (FARPROC) MAKELONG (low, hi);
  103.     return CallWindowProc (realProc, hWnd, msg, wParam, lParam);
  104. }
  105.  
  106. static void _SubclassButton (long handle)
  107. {
  108.     FARPROC RealProc = (FARPROC) SetWindowLong (handle, GWL_WNDPROC, (long)
  109.                                                 BtnProc);
  110.     SetProp (handle, PROP1, LOWORD (RealProc));
  111.     SetProp (handle, PROP2, HIWORD (RealProc));
  112. }
  113. #endif
  114.  
  115.  
  116. UI_ExOrToggleButton::UI_ExOrToggleButton
  117.     ( UI_VObjCollection* parent, const UI_Rectangle& shape,
  118.       UI_ViewID id
  119.     )
  120. : UI_SimpleVObject (parent, shape, id)
  121. {
  122. #if defined(__MS_WINDOWS__) || defined(__OS2__)
  123.     _style = EXOR_TOGGLE_BUTTON_STYLE;
  124. #endif
  125.     _model = new CL_Integer;
  126. }
  127.  
  128.  
  129. #if defined(__MS_WINDOWS__)
  130. UI_ExOrToggleButton::UI_ExOrToggleButton
  131.     (UI_CompositeVObject* parent, UI_ViewID id, UI_ViewHandle handle) 
  132. : UI_SimpleVObject (parent, id, handle)
  133. {
  134.     _model = new CL_Integer; 
  135.     _borderShown = FALSE;
  136. }
  137. #endif
  138.  
  139.  
  140.  
  141.  
  142. void UI_ExOrToggleButton::_PrivateInitialize ()
  143. {
  144.     UI_SimpleVObject::_PrivateInitialize ();
  145.     _ModelChanged (*this, 1); // Dummy call to force initial setting
  146.  
  147. #if defined(__MS_WINDOWS__)
  148.     _SubclassButton (_handle);
  149. #elif defined (__X_MOTIF__)
  150.     Arg  args [2];
  151.     XtSetArg    (args [0], XmNindicatorType , XmONE_OF_MANY);
  152.     XtSetArg    (args [1], XmNvisibleWhenOff, TRUE);
  153.     XtSetValues   (_xwidget, args, 2);
  154. #endif
  155. }
  156.  
  157.  
  158.  
  159. CL_Object& UI_ExOrToggleButton::Model ()
  160. {
  161. #if defined (__MS_WINDOWS__)
  162.     if (_handle > 0)
  163.         _SetModelValue (CL_Integer (SendMessage (_handle, BM_GETCHECK, 0,
  164.                                                  0L)));
  165. #elif defined(__OS2__)
  166.     if (_handle) {
  167.         long val = (long) WinSendMsg (_handle, BM_QUERYCHECK, 0, 0L);
  168.         _SetModelValue (CL_Integer (val));
  169.     }
  170. #elif defined (__X_MOTIF__)
  171.     if (_xwidget)
  172.         _SetModelValue (CL_Integer ((short)XmToggleButtonGetState (_xwidget)));
  173. #endif
  174.     return *_model;
  175. }
  176.  
  177.  
  178.  
  179. bool UI_ExOrToggleButton::MakeVisualElement ()
  180. {
  181.     bool b = UI_SimpleVObject::MakeVisualElement ();
  182. #if defined(__X_MOTIF__)
  183.     XtAddCallback (_xwidget, XmNvalueChangedCallback, 
  184.                    &UI_ExOrToggleButton::SelectionCallback, (XtPointer)
  185.                    this);
  186.     XtVaSetValues (_xwidget, XmNalignment, XmALIGNMENT_BEGINNING, NULL);
  187.     // If we try to set the alignment at creation time (i.e., in
  188.     // _SetupStyle), Motif complains!
  189. #endif
  190.     return b;
  191. }
  192.  
  193.  
  194.  
  195. #if defined (__X_MOTIF__)
  196.  
  197. void UI_ExOrToggleButton::SelectionCallback (Widget w, void* client,
  198.                                              void* call)
  199. {
  200.     UI_ExOrToggleButton* btn = (UI_ExOrToggleButton *) client;
  201.     int value = ((XmToggleButtonCallbackStruct*) call)->set;
  202.     btn->_SetModelValue (CL_Integer(value));
  203.     _Controller->AddEvent (new UI_Event (Event_Select, btn, btn));
  204.  
  205.     // Now ensure that at most one of the buttons is on:
  206.     UI_VObjCollection* parent = btn->Parent();
  207.     CL_ObjectSequence siblings = _Controller->ChildrenOf (*parent);
  208.     short n = siblings.Size();
  209.     for (short i = 0; i < n; i++) {
  210.         UI_VisualObject* v = (UI_VisualObject*) siblings[i];
  211.         if (v != btn && v->WindowClass() == btn->WindowClass()) {
  212.             // ------- ^^^^^^^^^^^^^^^^^^^ --------------
  213.             // We're using type identification here, unfortunately
  214.             v->Model() = CL_Integer(0);
  215.         }
  216.     }
  217. }
  218.  
  219. #endif
  220.  
  221.  
  222.  
  223. bool UI_ExOrToggleButton::_ModelChanged (CL_Object&, long)
  224. {
  225. #if defined(__MS_WINDOWS__)
  226.     if(_handle > 0) {
  227.         SendMessage (_handle, BM_SETCHECK,
  228.                      ((CL_Integer*) _model)->Value () > 0 ? 1 : 0, 0
  229.                     );
  230.     }
  231.  
  232. #elif defined(__OS2__)
  233.     if (_handle) {
  234.         MPARAM val = MPFROM2SHORT (((CL_Integer *) _model)->Value () > 0
  235.                                    ? TRUE : FALSE, 0);
  236.         WinSendMsg (_handle, BM_SETCHECK, val, NULL);
  237.     }
  238. #elif defined(__X_MOTIF__)
  239.     if (_xwidget) {
  240.         bool state = (((CL_Integer *) _model)->Value () > 0 ? TRUE : FALSE);
  241.         Arg arg[1];
  242.         XtSetArg    (arg [0], XmNset, state);
  243.         XtSetValues (_xwidget, arg, 1);
  244.     }
  245.  
  246. #endif
  247.     return TRUE;
  248. }
  249.  
  250.  
  251.  
  252. UI_WindowClass UI_ExOrToggleButton::WindowClass () const
  253. {
  254. #if defined(__MS_WINDOWS__)
  255.     return "button";
  256. #elif defined(__OS2__)
  257.     return WC_BUTTON;
  258. #elif defined(__X_MOTIF__)
  259.     return xmToggleButtonWidgetClass;
  260. #endif
  261. }
  262.  
  263.  
  264.  
  265.