home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
yacl-012.zip
/
ui
/
xrtglbtn.cxx
< prev
next >
Wrap
C/C++ Source or Header
|
1995-04-04
|
8KB
|
265 lines
/*
*
* Copyright (C) 1994, M. A. Sridhar
*
*
* This software is Copyright M. A. Sridhar, 1994. You are free
* to copy, modify or distribute this software as you see fit,
* and to use it for any purpose, provided this copyright
* notice and the following disclaimer are included with all
* copies.
*
* DISCLAIMER
*
* The author makes no warranties, either expressed or implied,
* with respect to this software, its quality, performance,
* merchantability, or fitness for any particular purpose. This
* software is distributed AS IS. The user of this software
* assumes all risks as to its quality and performance. In no
* event shall the author be liable for any direct, indirect or
* consequential damages, even if the author has been advised
* as to the possibility of such damages.
*
*/
#if defined(__GNUC__)
#pragma implementation
#endif
#include "ui/xrtglbtn.h"
#include "ui/xrbtngrp.h"
#include "ui/cntroler.h"
#include "base/integer.h"
#include "base/intset.h"
#if defined (__X_MOTIF__)
#include <Xm/ToggleB.h>
#endif
//------------------------------------------------------------------
// CLASS ExOrToggleButton
//------------------------------------------------------------------
#if defined(__MS_WINDOWS__)
#include <windows.h>
#define EXOR_TOGGLE_BUTTON_STYLE \
BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE
#elif defined(__OS2__)
#define EXOR_TOGGLE_BUTTON_STYLE BS_AUTORADIOBUTTON | WS_VISIBLE
#endif
#if defined(__MS_WINDOWS__)
// We have to subclass the button *after* the Ctl3d subclass in order to
// paint its background properly.
#define PROP1 "YACL_XRBTN_PROP1"
#define PROP2 "YACL_XRBTN_PROP2"
static long FAR PASCAL _export BtnProc (HWND hWnd, unsigned msg, WORD
wParam, LONG lParam)
{
// This feels like a hack; should really use the Controller's
// TranslateNativeEvent.
int low = GetProp (hWnd, PROP1);
int hi = GetProp (hWnd, PROP2);
if (!low || !hi)
return DefWindowProc (hWnd, msg, wParam, lParam);
if (msg == WM_KEYDOWN &&
(wParam == VK_UP || wParam == VK_DOWN || wParam == VK_LEFT ||
wParam == VK_RIGHT)) {
// ----^^^^^^^^------
// Yet another hack. Windows sends WM_CHAR messages to *both* this
// subclassing proc and the main event loop in ProcessNativeEvents.
// But it doesn't send WM_CHAR if an arrow key is typed. So we send
// the arrow key to the button group parent.
UI_Controller& ctrl = _TheApplication->Controller();
UI_VisualObject* v = ctrl[hWnd];
UI_Event* e = new UI_Event (Event_KeyTyped, v, v);
e->key = wParam;
ctrl.AddEvent (e);
}
else
if (msg == WM_ERASEBKGND) {
// Catch the ERASEBKGND message *before* it gets to the button, and
// fill its background with grey:
RECT rect;
GetClientRect (hWnd, &rect);
HBRUSH brush = GetClassWord (GetParent (hWnd), GCW_HBRBACKGROUND);
FillRect ((HDC) wParam, &rect, brush);
// Now just call the real proc, pretending that no painting was
// done, and let it do its thing:
}
FARPROC realProc = (FARPROC) MAKELONG (low, hi);
return CallWindowProc (realProc, hWnd, msg, wParam, lParam);
}
static void _SubclassButton (long handle)
{
FARPROC RealProc = (FARPROC) SetWindowLong (handle, GWL_WNDPROC, (long)
BtnProc);
SetProp (handle, PROP1, LOWORD (RealProc));
SetProp (handle, PROP2, HIWORD (RealProc));
}
#endif
UI_ExOrToggleButton::UI_ExOrToggleButton
( UI_VObjCollection* parent, const UI_Rectangle& shape,
UI_ViewID id
)
: UI_SimpleVObject (parent, shape, id)
{
#if defined(__MS_WINDOWS__) || defined(__OS2__)
_style = EXOR_TOGGLE_BUTTON_STYLE;
#endif
_model = new CL_Integer;
}
#if defined(__MS_WINDOWS__)
UI_ExOrToggleButton::UI_ExOrToggleButton
(UI_CompositeVObject* parent, UI_ViewID id, UI_ViewHandle handle)
: UI_SimpleVObject (parent, id, handle)
{
_model = new CL_Integer;
_borderShown = FALSE;
}
#endif
void UI_ExOrToggleButton::_PrivateInitialize ()
{
UI_SimpleVObject::_PrivateInitialize ();
_ModelChanged (*this, 1); // Dummy call to force initial setting
#if defined(__MS_WINDOWS__)
_SubclassButton (_handle);
#elif defined (__X_MOTIF__)
Arg args [2];
XtSetArg (args [0], XmNindicatorType , XmONE_OF_MANY);
XtSetArg (args [1], XmNvisibleWhenOff, TRUE);
XtSetValues (_xwidget, args, 2);
#endif
}
CL_Object& UI_ExOrToggleButton::Model ()
{
#if defined (__MS_WINDOWS__)
if (_handle > 0)
_SetModelValue (CL_Integer (SendMessage (_handle, BM_GETCHECK, 0,
0L)));
#elif defined(__OS2__)
if (_handle) {
long val = (long) WinSendMsg (_handle, BM_QUERYCHECK, 0, 0L);
_SetModelValue (CL_Integer (val));
}
#elif defined (__X_MOTIF__)
if (_xwidget)
_SetModelValue (CL_Integer ((short)XmToggleButtonGetState (_xwidget)));
#endif
return *_model;
}
bool UI_ExOrToggleButton::MakeVisualElement ()
{
bool b = UI_SimpleVObject::MakeVisualElement ();
#if defined(__X_MOTIF__)
XtAddCallback (_xwidget, XmNvalueChangedCallback,
&UI_ExOrToggleButton::SelectionCallback, (XtPointer)
this);
XtVaSetValues (_xwidget, XmNalignment, XmALIGNMENT_BEGINNING, NULL);
// If we try to set the alignment at creation time (i.e., in
// _SetupStyle), Motif complains!
#endif
return b;
}
#if defined (__X_MOTIF__)
void UI_ExOrToggleButton::SelectionCallback (Widget w, void* client,
void* call)
{
UI_ExOrToggleButton* btn = (UI_ExOrToggleButton *) client;
int value = ((XmToggleButtonCallbackStruct*) call)->set;
btn->_SetModelValue (CL_Integer(value));
_Controller->AddEvent (new UI_Event (Event_Select, btn, btn));
// Now ensure that at most one of the buttons is on:
UI_VObjCollection* parent = btn->Parent();
CL_ObjectSequence siblings = _Controller->ChildrenOf (*parent);
short n = siblings.Size();
for (short i = 0; i < n; i++) {
UI_VisualObject* v = (UI_VisualObject*) siblings[i];
if (v != btn && v->WindowClass() == btn->WindowClass()) {
// ------- ^^^^^^^^^^^^^^^^^^^ --------------
// We're using type identification here, unfortunately
v->Model() = CL_Integer(0);
}
}
}
#endif
bool UI_ExOrToggleButton::_ModelChanged (CL_Object&, long)
{
#if defined(__MS_WINDOWS__)
if(_handle > 0) {
SendMessage (_handle, BM_SETCHECK,
((CL_Integer*) _model)->Value () > 0 ? 1 : 0, 0
);
}
#elif defined(__OS2__)
if (_handle) {
MPARAM val = MPFROM2SHORT (((CL_Integer *) _model)->Value () > 0
? TRUE : FALSE, 0);
WinSendMsg (_handle, BM_SETCHECK, val, NULL);
}
#elif defined(__X_MOTIF__)
if (_xwidget) {
bool state = (((CL_Integer *) _model)->Value () > 0 ? TRUE : FALSE);
Arg arg[1];
XtSetArg (arg [0], XmNset, state);
XtSetValues (_xwidget, arg, 1);
}
#endif
return TRUE;
}
UI_WindowClass UI_ExOrToggleButton::WindowClass () const
{
#if defined(__MS_WINDOWS__)
return "button";
#elif defined(__OS2__)
return WC_BUTTON;
#elif defined(__X_MOTIF__)
return xmToggleButtonWidgetClass;
#endif
}