home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
yacl-012.zip
/
ui
/
dialog.cxx
< prev
next >
Wrap
C/C++ Source or Header
|
1995-04-06
|
10KB
|
371 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/dialog.h"
#include "ui/cntroler.h"
#if defined(__MS_WINDOWS__)
#include <ctl3d.h>
#endif
#if defined(__GNUC__) && __GNUC_MINOR__ >= 6
template class CL_Binding<UI_Dialog>;
#endif
class DialogEvent: public CL_Object {
// An encapsulation of a visual-object/event-type pair
public:
DialogEvent (UI_ViewID id, UI_EventType type)
: _id (id), _type (type) {};
~DialogEvent () {};
short Compare (const CL_Object& o) const;
void operator = (const CL_Object& o)
{ _id = ((const DialogEvent&) o)._id;
_type = ((const DialogEvent&) o)._type;};
const char* ClassName() const {return "DialogEvent";};
protected:
UI_ViewID _id;
UI_EventType _type;
};
short DialogEvent::Compare (const CL_Object& o) const
{
const DialogEvent& d = (const DialogEvent&) o;
if (_id == d._id) {
if (_type == d._type)
return 0;
return _type < d._type ? -1 : 1;
}
return _id < d._id ? -1 : 1;
}
typedef CL_Binding<UI_Dialog> DialogBind;
UI_Dialog::UI_Dialog
(UI_CompositeVObject* parent, UI_ViewDescriptor* vd,
const UI_Rectangle& shape, UI_DialogEventDescriptor* qd,
UI_ViewID id
)
: UI_CompositeVObject (parent, vd, FALSE, shape, id)
{
#if defined(__MS_WINDOWS__)
_style = WS_VISIBLE | WS_SYSMENU | WS_CAPTION | DS_MODALFRAME;
Set3DLook();
#elif defined(__OS2__)
_style = FCF_TITLEBAR | FCF_SYSMENU | FCF_DLGBORDER;
#endif
_Init (qd);
}
void UI_Dialog::_Init (UI_DialogEventDescriptor* qd)
{
_closed = FALSE;
_modalState = FALSE;
if (!qd) {
AddDialogEvent (UI_IDOK, Event_Select);
AddDialogEvent (UI_IDCANCEL, Event_Select);
}
else {
for (short i = 0; qd[i].id != -1 && qd[i].type != View_None; i++)
AddDialogEvent (qd[i].id, qd[i].type);
}
_lastEvent.id = -1;
}
#if defined(__MS_WINDOWS__)
UI_Dialog::UI_Dialog (UI_CompositeVObject* parent, const char* rsrc,
UI_DialogEventDescriptor* qd, UI_ViewID id)
: UI_CompositeVObject(parent, rsrc, id)
{
Set3DLook ();
_Init (qd);
}
#endif
UI_Dialog::~UI_Dialog()
{
_dialogEvents.DestroyContents();
}
#if defined(__MS_WINDOWS__)
struct DialogBoxHeader {
DWORD s; BYTE n; WORD x, y, cx, cy;
char mnu[1];
char cls[1];
char caption[1];
WORD pt;
char face[1];
};
#endif
#if defined(__MS_WINDOWS__)
struct SysFontStruct {
short width, height;
};
static SysFontStruct _SysFontSizes ()
{
HFONT hFont = GetStockObject (SYSTEM_FONT);
HDC dc = CreateDC ("DISPLAY", NULL, NULL, NULL);
HFONT old = SelectObject (dc, hFont);
TEXTMETRIC tm;
GetTextMetrics (dc, &tm);
SelectObject (dc, old);
DeleteObject (hFont);
DeleteDC (dc);
SysFontStruct st;
st.width = tm.tmAveCharWidth;
st.height = tm.tmHeight;
return st;
}
static SysFontStruct _SysFont = _SysFontSizes();
#endif
bool UI_Dialog::MakeVisualElement ()
{
#ifdef __MS_WINDOWS__
if (CreatedViaResource ())
return UI_CompositeVObject::MakeVisualElement ();
long x, y, w, h;
x = _shape.Origin().XCoord();
y = _shape.Origin().YCoord();
w = _shape.Width();
h = _shape.Height();
RECT rect;
rect.left = x;
rect.top = y;
rect.right = x + w;
rect.bottom = y + h;
AdjustWindowRect (&rect, _style, FALSE);
if (!_visible)
_style &= ~WS_VISIBLE;
HGLOBAL hMem = GlobalAlloc (GHND, sizeof (DialogBoxHeader) +
_title.Size() + 1);
DialogBoxHeader* hdr = (DialogBoxHeader*) GlobalLock (hMem);
if (hdr) {
hdr->n = 0;
short fontWidth = _SysFont.width;
if (fontWidth <= 0)
fontWidth = 4;
short fontHeight = _SysFont.height;
if (fontHeight <= 0)
fontHeight = 8;
hdr->x = rect.left * 4 / fontWidth;
hdr->y = rect.top * 8 / fontHeight;
hdr->cx = (rect.right - rect.left + 1) * 4 / fontWidth;
hdr->cy = (rect.bottom - rect.top + 1) * 8 / fontHeight;
hdr->cls[0] = '\0';
hdr->mnu[0] = '\0';
hdr->caption[0] = '\0';
hdr->pt = 0;
hdr->face[0] = '\0';
// For some reason, the dimensions set up in the hdr structure
// don't match up on all displays. So we make the dialog
// initially invisible, call SetWindowPos, and then let the
// controller make it visible.
hdr->s = _style & ~WS_VISIBLE;
_handle = CreateDialogIndirectParam
(_Application->ProcessId(), hdr,
_parent ? _parent->ViewHandle() : NULL,
(FARPROC) YACLDialogProc, 0L);
SetWindowPos (_handle, NULL, rect.left, rect.top,
rect.right - rect.left + 1,
rect.bottom - rect.top + 1, 0);
SendMessage (_handle, WM_SETTEXT, 0, (long)(const char*)_title);
GlobalFree (hMem);
Ctl3dSubclassDlgEx (_handle, CTL3D_ALL);
}
if (!_handle) {
CL_Error::Warning ("Window creation failed: id %ld class %s",
ViewID(), ClassName());
return FALSE;
}
// SetProp (_handle, _YACLWindowClassName, 1); // Needed to identify these
// // windows
return TRUE;
#elif defined(__X_MOTIF__)
return UI_CompositeVObject::MakeVisualElement ();
#elif defined (__OS2__)
return UI_CompositeVObject::MakeVisualElement ();
#endif
}
UI_DialogEventDescriptor UI_Dialog::ExecuteModal ()
{
_lastEvent.id = -1;
_modalState = TRUE;
// #ifdef __MS_WINDOWS__
// // Gray out the "Close" in the system menu
// HMENU h = GetSystemMenu (_handle, FALSE);
// if (h)
// EnableMenuItem (h, SC_CLOSE, FALSE);
// #endif
_Controller->DispatchPendingEvents (); // Flush the event queue
DialogBind filterBind (this, &UI_Dialog::EventFilter);
DialogBind finishBind (this, &UI_Dialog::RunFinished);
_Controller->EventLoop (&finishBind, &filterBind);
_modalState = FALSE;
return _lastEvent;
}
bool UI_Dialog::_DialogEventOccurred (CL_Object& obj, long)
{
UI_Event& e = (UI_Event&) obj;
DialogEvent t (e.Origin()->ViewID(), e.Type());
if (_dialogEvents.Includes (&t)) {
_lastEvent.id = e.Origin()->ViewID();
_lastEvent.type = e.Type();
}
return TRUE;
}
static bool IsAncestor (UI_VisualObject* a, UI_VisualObject* b)
{
// Check if a is an ancestor of b
if (!a || !b)
return FALSE;
while (b && b != a)
b = b->Parent();
return b == a;
}
// #include <iostream.h> // DEBUG
bool UI_Dialog::EventFilter (CL_Object& event, long)
{
UI_Event* e = &(UI_Event&) event;
UI_VisualObject* origin = e->Origin();
UI_VisualObject* dest = e->Destination();
bool b = (origin == this || dest == this || !origin || !dest
|| e->Type() == Event_MouseMove
|| e->Type() == Event_ViewEnter
|| e->Type() == Event_ViewLeave);
b |= IsAncestor (this, origin);
#if defined(__MS_WINDOWS__)
if (!b && e->Type() == Event_LButtonRelease)
_Controller->Beep();
#endif
// cout << "EventFilter: event " << e->Type() << " VObj " <<
// origin->ClassName() << " id " << origin->ViewID() << " label '" <<
// origin->Title() << "' returns " << b << endl;
if (origin == this && dest == this && e->Type() == Event_CloseDown) {
_closed = TRUE;
if (!_parent)
_Application->Destroy (this);
}
return b;
}
bool UI_Dialog::RunFinished (CL_Object&, long)
{
return _lastEvent.id != -1 || _closed;
}
bool UI_Dialog::AddDialogEvent (UI_ViewID id, UI_EventType type)
{
DialogBind bind (this, &UI_Dialog::_DialogEventOccurred);
AddEventDependent (type, bind, 0); // Last parameter unused
DialogEvent* d = new DialogEvent (id, type);
if (_dialogEvents.Add (d))
return TRUE;
delete d;
return FALSE;
}
bool UI_Dialog::RemoveDialogEvent (UI_ViewID id, UI_EventType type)
{
DialogBind bind (this, &UI_Dialog::_DialogEventOccurred);
RemoveEventDependent (type, bind);
DialogEvent d (id, type);
DialogEvent* p = (DialogEvent*) _dialogEvents.Remove (&d);
if (p) {
delete p;
return TRUE;
}
return FALSE;
}
void UI_Dialog::CloseDown ()
{
if (InModalState()) {
if (WantToQuit ())
_closed = TRUE;
}
else if (WantToQuit())
_Application->Destroy (this);
}