]> git.saurik.com Git - wxWidgets.git/blame - src/motif/window.cpp
Motif bug fixes; dialog OnPaint works now; wxColourDialog tweaking
[wxWidgets.git] / src / motif / window.cpp
CommitLineData
4bb6408c
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: windows.cpp
3// Purpose: wxWindow
4// Author: Julian Smart
5// Modified by:
6// Created: 17/09/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "window.h"
14#endif
15
16#include "wx/setup.h"
17#include "wx/menu.h"
18#include "wx/dc.h"
19#include "wx/dcclient.h"
20#include "wx/utils.h"
21#include "wx/app.h"
22#include "wx/panel.h"
23#include "wx/layout.h"
24#include "wx/dialog.h"
25#include "wx/listbox.h"
26#include "wx/button.h"
27#include "wx/settings.h"
28#include "wx/msgdlg.h"
29#include "wx/frame.h"
30
31#include "wx/menuitem.h"
32#include "wx/log.h"
33
47d67540 34#if wxUSE_DRAG_AND_DROP
4bb6408c
JS
35#include "wx/dnd.h"
36#endif
37
38#include <Xm/Xm.h>
50414e24
JS
39
40#include <Xm/DrawingA.h>
41#include <Xm/ScrolledW.h>
42#include <Xm/ScrollBar.h>
43#include <Xm/Frame.h>
44#include <Xm/Label.h>
45
4bb6408c
JS
46#include "wx/motif/private.h"
47
48#include <string.h>
49
50414e24
JS
50#define SCROLL_MARGIN 4
51void wxCanvasRepaintProc (Widget, XtPointer, XmDrawingAreaCallbackStruct * cbs);
52void wxCanvasInputEvent (Widget drawingArea, XtPointer data, XmDrawingAreaCallbackStruct * cbs);
53void wxCanvasMotionEvent (Widget, XButtonEvent * event);
54void wxCanvasEnterLeave (Widget drawingArea, XtPointer clientData, XCrossingEvent * event);
47bc1060
JS
55void wxScrollBarCallback(Widget widget, XtPointer clientData,
56 XmScaleCallbackStruct *cbs);
02e8b2f9
JS
57void wxPanelItemEventHandler (Widget wid,
58 XtPointer client_data,
59 XEvent* event,
60 Boolean *continueToDispatch);
50414e24
JS
61
62#define event_left_is_down(x) ((x)->xbutton.state & Button1Mask)
63#define event_middle_is_down(x) ((x)->xbutton.state & Button2Mask)
64#define event_right_is_down(x) ((x)->xbutton.state & Button3Mask)
65
4bb6408c
JS
66extern wxList wxPendingDelete;
67
68#if !USE_SHARED_LIBRARY
69IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxEvtHandler)
70
71BEGIN_EVENT_TABLE(wxWindow, wxEvtHandler)
72 EVT_CHAR(wxWindow::OnChar)
73 EVT_ERASE_BACKGROUND(wxWindow::OnEraseBackground)
74 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged)
75 EVT_INIT_DIALOG(wxWindow::OnInitDialog)
76 EVT_IDLE(wxWindow::OnIdle)
77END_EVENT_TABLE()
78
79#endif
80
81
82// Constructor
83wxWindow::wxWindow()
84{
85 // Generic
86 m_windowId = 0;
87 m_windowStyle = 0;
88 m_windowParent = NULL;
89 m_windowEventHandler = this;
90 m_windowName = "";
91 m_windowCursor = *wxSTANDARD_CURSOR;
92 m_children = new wxList;
93 m_constraints = NULL;
94 m_constraintsInvolvedIn = NULL;
95 m_windowSizer = NULL;
96 m_sizerParent = NULL;
97 m_autoLayout = FALSE;
98 m_windowValidator = NULL;
99 m_defaultItem = NULL;
100 m_returnCode = 0;
101 m_caretWidth = 0; m_caretHeight = 0;
102 m_caretEnabled = FALSE;
103 m_caretShown = FALSE;
fd71308f
JS
104 // m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW) ; ;
105 m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE) ;
4bb6408c 106 m_foregroundColour = *wxBLACK;
4bb6408c 107
47d67540 108#if wxUSE_DRAG_AND_DROP
4bb6408c
JS
109 m_pDropTarget = NULL;
110#endif
3dd4e4e0
JS
111 m_clientObject = (wxClientData*) NULL;
112 m_clientData = NULL;
4bb6408c 113
50414e24 114 /// Motif-specific
4bb6408c
JS
115 m_mainWidget = (WXWidget) 0;
116 m_button1Pressed = FALSE;
117 m_button2Pressed = FALSE;
118 m_button3Pressed = FALSE;
119 m_winCaptured = FALSE;
120 m_isShown = TRUE;
50414e24
JS
121 m_hScrollBar = (WXWidget) 0;
122 m_vScrollBar = (WXWidget) 0;
123 m_borderWidget = (WXWidget) 0;
124 m_scrolledWindow = (WXWidget) 0;
125 m_drawingArea = (WXWidget) 0;
126 m_hScroll = FALSE;
127 m_vScroll = FALSE;
50414e24
JS
128 m_backingPixmap = (WXPixmap) 0;
129 m_pixmapWidth = 0;
130 m_pixmapHeight = 0;
131 m_pixmapOffsetX = 0;
132 m_pixmapOffsetY = 0;
133 m_lastTS = 0;
134 m_lastButton = 0;
02e8b2f9 135 m_canAddEventHandler = FALSE;
47bc1060
JS
136 m_scrollPosX = 0;
137 m_scrollPosY = 0;
4bb6408c
JS
138}
139
140// Destructor
141wxWindow::~wxWindow()
142{
f97c9854 143 //// Motif-specific
50414e24 144
f97c9854
JS
145 if (GetMainWidget())
146 DetachWidget(GetMainWidget()); // Removes event handlers
02e8b2f9 147
f97c9854
JS
148 // If m_drawingArea, we're a fully-fledged window with drawing area, scrollbars etc. (what wxCanvas used to be)
149 if (m_drawingArea)
150 {
151 // Destroy children before destroying self
152 DestroyChildren();
50414e24 153
f97c9854
JS
154 if (m_backingPixmap)
155 XFreePixmap (XtDisplay ((Widget) GetMainWidget()), (Pixmap) m_backingPixmap);
50414e24 156
f97c9854
JS
157 Widget w = (Widget) m_drawingArea;
158 wxDeleteWindowFromTable(w);
50414e24 159
f97c9854
JS
160 if (w)
161 XtDestroyWidget(w);
162 m_mainWidget = (WXWidget) 0;
50414e24 163
f97c9854
JS
164 // Only if we're _really_ a canvas (not a dialog box/panel)
165 if (m_scrolledWindow)
166 {
167 wxDeleteWindowFromTable((Widget) m_scrolledWindow);
168 }
50414e24 169
f97c9854
JS
170 if (m_hScrollBar)
171 {
172 XtUnmanageChild ((Widget) m_hScrollBar);
173 XtDestroyWidget ((Widget) m_hScrollBar);
174 }
175 if (m_vScrollBar)
176 {
177 XtUnmanageChild ((Widget) m_vScrollBar);
178 XtDestroyWidget ((Widget) m_vScrollBar);
179 }
180 if (m_scrolledWindow)
181 {
182 XtUnmanageChild ((Widget) m_scrolledWindow);
183 XtDestroyWidget ((Widget) m_scrolledWindow);
184 }
50414e24 185
f97c9854
JS
186 if (m_borderWidget)
187 {
188 XtDestroyWidget ((Widget) m_borderWidget);
189 m_borderWidget = (WXWidget) 0;
190 }
50414e24 191 }
50414e24 192
f97c9854 193 //// Generic stuff
50414e24 194
4bb6408c
JS
195 // Have to delete constraints/sizer FIRST otherwise
196 // sizers may try to look at deleted windows as they
197 // delete themselves.
47d67540 198#if wxUSE_CONSTRAINTS
4bb6408c
JS
199 DeleteRelatedConstraints();
200 if (m_constraints)
201 {
202 // This removes any dangling pointers to this window
203 // in other windows' constraintsInvolvedIn lists.
204 UnsetConstraints(m_constraints);
205 delete m_constraints;
206 m_constraints = NULL;
207 }
208 if (m_windowSizer)
209 {
210 delete m_windowSizer;
211 m_windowSizer = NULL;
212 }
213 // If this is a child of a sizer, remove self from parent
214 if (m_sizerParent)
215 m_sizerParent->RemoveChild((wxWindow *)this);
216#endif
217
218 if (m_windowParent)
219 m_windowParent->RemoveChild(this);
220
221 DestroyChildren();
222
223 // Destroy the window
224 if (GetMainWidget())
225 {
226 wxDeleteWindowFromTable((Widget) GetMainWidget());
227 XtDestroyWidget((Widget) GetMainWidget());
228 SetMainWidget((WXWidget) NULL);
229 }
230
231 delete m_children;
232 m_children = NULL;
233
234 // Just in case the window has been Closed, but
235 // we're then deleting immediately: don't leave
236 // dangling pointers.
237 wxPendingDelete.DeleteObject(this);
238
3dd4e4e0
JS
239 if ( m_windowValidator ) delete m_windowValidator;
240 if (m_clientObject) delete m_clientObject;
55acd85e
JS
241
242 ClearUpdateRects();
4bb6408c
JS
243}
244
245// Destroy the window (delayed, if a managed window)
246bool wxWindow::Destroy()
247{
248 delete this;
249 return TRUE;
250}
251
252// Constructor
253bool wxWindow::Create(wxWindow *parent, wxWindowID id,
254 const wxPoint& pos,
255 const wxSize& size,
256 long style,
257 const wxString& name)
258{
259 // Generic
260 m_windowId = 0;
261 m_windowStyle = 0;
262 m_windowParent = NULL;
263 m_windowEventHandler = this;
264 m_windowName = "";
265 m_windowCursor = *wxSTANDARD_CURSOR;
266 m_constraints = NULL;
267 m_constraintsInvolvedIn = NULL;
268 m_windowSizer = NULL;
269 m_sizerParent = NULL;
270 m_autoLayout = FALSE;
271 m_windowValidator = NULL;
47d67540 272#if wxUSE_DRAG_AND_DROP
4bb6408c
JS
273 m_pDropTarget = NULL;
274#endif
4bb6408c
JS
275 m_caretWidth = 0; m_caretHeight = 0;
276 m_caretEnabled = FALSE;
277 m_caretShown = FALSE;
278 m_minSizeX = -1;
279 m_minSizeY = -1;
280 m_maxSizeX = -1;
281 m_maxSizeY = -1;
282 m_defaultItem = NULL;
283 m_windowParent = NULL;
3dd4e4e0
JS
284 m_clientObject = (wxClientData*) NULL;
285 m_clientData = NULL;
50414e24
JS
286
287 // Motif-specific
02e8b2f9 288 m_canAddEventHandler = FALSE;
50414e24
JS
289 m_mainWidget = (WXWidget) 0;
290 m_button1Pressed = FALSE;
291 m_button2Pressed = FALSE;
292 m_button3Pressed = FALSE;
293 m_winCaptured = FALSE;
294 m_isShown = TRUE;
295 m_hScrollBar = (WXWidget) 0;
296 m_vScrollBar = (WXWidget) 0;
297 m_borderWidget = (WXWidget) 0;
298 m_scrolledWindow = (WXWidget) 0;
299 m_drawingArea = (WXWidget) 0;
300 m_hScroll = FALSE;
301 m_vScroll = FALSE;
50414e24
JS
302 m_backingPixmap = (WXPixmap) 0;
303 m_pixmapWidth = 0;
304 m_pixmapHeight = 0;
305 m_pixmapOffsetX = 0;
306 m_pixmapOffsetY = 0;
47bc1060
JS
307 m_scrollPosX = 0;
308 m_scrollPosY = 0;
50414e24 309
4bb6408c
JS
310 if (!parent)
311 return FALSE;
312
313 if (parent) parent->AddChild(this);
314
315 m_returnCode = 0;
316
317 SetName(name);
318
319 if ( id == -1 )
320 m_windowId = (int)NewControlId();
321 else
322 m_windowId = id;
323
fd71308f
JS
324 // m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW) ; ;
325 m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE) ;
4bb6408c 326 m_foregroundColour = *wxBLACK;
4bb6408c
JS
327
328 m_windowStyle = style;
329
330 if ( id == -1 )
331 m_windowId = (int)NewControlId();
332 else
333 m_windowId = id;
334
50414e24
JS
335 //// TODO: we should probably optimize by only creating a
336 //// a drawing area if we have one or more scrollbars (wxVSCROLL/wxHSCROLL).
337 //// But for now, let's simplify things by always creating the
338 //// drawing area, since otherwise the translations are different.
339
340 // New translations for getting mouse motion feedback
341 String translations =
342 "<Btn1Motion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
343 <Btn2Motion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
344 <Btn3Motion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
345 <BtnMotion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
346 <Btn1Down>: DrawingAreaInput() ManagerGadgetArm()\n\
347 <Btn2Down>: DrawingAreaInput() ManagerGadgetArm()\n\
348 <Btn3Down>: DrawingAreaInput() ManagerGadgetArm()\n\
349 <Btn1Up>: DrawingAreaInput() ManagerGadgetActivate()\n\
350 <Btn2Up>: DrawingAreaInput() ManagerGadgetActivate()\n\
351 <Btn3Up>: DrawingAreaInput() ManagerGadgetActivate()\n\
352 <Motion>: wxCanvasMotionEvent() DrawingAreaInput()\n\
353 <EnterWindow>: wxCanvasMotionEvent() DrawingAreaInput()\n\
354 <LeaveWindow>: wxCanvasMotionEvent() DrawingAreaInput()\n\
355 <Key>: DrawingAreaInput()";
356
357 XtActionsRec actions[1];
358 actions[0].string = "wxCanvasMotionEvent";
359 actions[0].proc = (XtActionProc) wxCanvasMotionEvent;
360 XtAppAddActions ((XtAppContext) wxTheApp->GetAppContext(), actions, 1);
361
362 Widget parentWidget = (Widget) parent->GetClientWidget();
363 if (style & wxBORDER)
364 m_borderWidget = (WXWidget) XtVaCreateManagedWidget ("canvasBorder",
365 xmFrameWidgetClass, parentWidget,
366 XmNshadowType, XmSHADOW_IN,
367 NULL);
368
369 m_scrolledWindow = (WXWidget) XtVaCreateManagedWidget ("scrolledWindow",
370 xmScrolledWindowWidgetClass, m_borderWidget ? (Widget) m_borderWidget : parentWidget,
371 XmNspacing, 0,
372 XmNscrollingPolicy, XmAPPLICATION_DEFINED,
373 NULL);
374
375 XtTranslations ptr;
376 m_drawingArea = (WXWidget) XtVaCreateWidget ((char*) (const char*) name,
377 xmDrawingAreaWidgetClass, (Widget) m_scrolledWindow,
378 XmNunitType, XmPIXELS,
379// XmNresizePolicy, XmRESIZE_ANY,
380 XmNresizePolicy, XmRESIZE_NONE,
381 XmNmarginHeight, 0,
382 XmNmarginWidth, 0,
383 XmNtranslations, ptr = XtParseTranslationTable (translations),
384 NULL);
385 /*
386 if (GetWindowStyleFlag() & wxOVERRIDE_KEY_TRANSLATIONS)
387 {
388 XtFree ((char *) ptr);
389 ptr = XtParseTranslationTable ("<Key>: DrawingAreaInput()");
390 XtOverrideTranslations ((Widget) m_drawingArea, ptr);
391 XtFree ((char *) ptr);
392 }
393 */
394
395 wxAddWindowToTable((Widget) m_drawingArea, this);
396 wxAddWindowToTable((Widget) m_scrolledWindow, this);
397
398 /*
399 * This order is very important in Motif 1.2.1
400 *
401 */
402
403 XtRealizeWidget ((Widget) m_scrolledWindow);
404 XtRealizeWidget ((Widget) m_drawingArea);
405 XtManageChild ((Widget) m_drawingArea);
406
407 XtOverrideTranslations ((Widget) m_drawingArea,
408 ptr = XtParseTranslationTable ("<Configure>: resize()"));
409 XtFree ((char *) ptr);
410
411 XtAddCallback ((Widget) m_drawingArea, XmNexposeCallback, (XtCallbackProc) wxCanvasRepaintProc, (XtPointer) this);
412 XtAddCallback ((Widget) m_drawingArea, XmNinputCallback, (XtCallbackProc) wxCanvasInputEvent, (XtPointer) this);
413
414 /* TODO?
415 display = XtDisplay (scrolledWindow);
416 xwindow = XtWindow (drawingArea);
417 */
418
419 XtAddEventHandler ((Widget) m_drawingArea, PointerMotionHintMask | EnterWindowMask | LeaveWindowMask | FocusChangeMask,
420 False, (XtEventHandler) wxCanvasEnterLeave, (XtPointer) this);
4bb6408c 421
47bc1060
JS
422 // Add scrollbars if required
423 if (m_windowStyle & wxHSCROLL)
424 {
425 Widget hScrollBar = XtVaCreateManagedWidget ("hsb",
426 xmScrollBarWidgetClass, (Widget) m_scrolledWindow,
427 XmNorientation, XmHORIZONTAL,
428 NULL);
429 // XtAddCallback (hScrollBar, XmNvalueChangedCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
430 XtAddCallback (hScrollBar, XmNdragCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
431 XtAddCallback (hScrollBar, XmNincrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
432 XtAddCallback (hScrollBar, XmNdecrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
433 XtAddCallback (hScrollBar, XmNpageIncrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
434 XtAddCallback (hScrollBar, XmNpageDecrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
435 XtAddCallback (hScrollBar, XmNtoTopCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
436 XtAddCallback (hScrollBar, XmNtoBottomCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
437
438 XtVaSetValues (hScrollBar,
439 XmNincrement, 1,
440 XmNvalue, 0,
441 NULL);
442
443 m_hScrollBar = (WXWidget) hScrollBar;
444 m_hScroll = TRUE;
445 }
446 if (m_windowStyle & wxVSCROLL)
447 {
448 Widget vScrollBar = XtVaCreateManagedWidget ("vsb",
449 xmScrollBarWidgetClass, (Widget) m_scrolledWindow,
450 XmNorientation, XmVERTICAL,
451 NULL);
452 // XtAddCallback (vScrollBar, XmNvalueChangedCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
453 XtAddCallback (vScrollBar, XmNdragCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
454 XtAddCallback (vScrollBar, XmNincrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
455 XtAddCallback (vScrollBar, XmNdecrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
456 XtAddCallback (vScrollBar, XmNpageIncrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
457 XtAddCallback (vScrollBar, XmNpageDecrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
458 XtAddCallback (vScrollBar, XmNtoTopCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
459 XtAddCallback (vScrollBar, XmNtoBottomCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
460
461 XtVaSetValues (vScrollBar,
462 XmNincrement, 1,
463 XmNvalue, 0,
464 NULL);
465
466 m_vScrollBar = (WXWidget) vScrollBar;
467 m_vScroll = TRUE;
468 }
469
470 if (m_hScrollBar || m_vScrollBar)
471 XmScrolledWindowSetAreas ((Widget) m_scrolledWindow, (Widget) m_hScrollBar, (Widget) m_vScrollBar, (Widget) m_drawingArea);
472
473 if (m_hScrollBar)
474 XtRealizeWidget ((Widget) m_hScrollBar);
475 if (m_vScrollBar)
476 XtRealizeWidget ((Widget) m_vScrollBar);
477
a4294b78
JS
478 // Without this, the cursor may not be restored properly
479 // (e.g. in splitter sample).
480 SetCursor(*wxSTANDARD_CURSOR);
e97f20a0
JS
481 SetSize(pos.x, pos.y, size.x, size.y);
482
483 return TRUE;
4bb6408c
JS
484}
485
486void wxWindow::SetFocus()
487{
488 XmProcessTraversal((Widget) GetMainWidget(), XmTRAVERSE_CURRENT);
489 XmProcessTraversal((Widget) GetMainWidget(), XmTRAVERSE_CURRENT);
490}
491
492void wxWindow::Enable(bool enable)
493{
494 if (GetMainWidget())
495 {
496 XtSetSensitive((Widget) GetMainWidget(), enable);
497 XmUpdateDisplay((Widget) GetMainWidget());
498 }
499}
500
501void wxWindow::CaptureMouse()
502{
503 if (m_winCaptured)
504 return;
505
506 if (GetMainWidget())
507 XtAddGrab((Widget) GetMainWidget(), TRUE, FALSE);
508
509 m_winCaptured = TRUE;
510}
511
512void wxWindow::ReleaseMouse()
513{
514 if (!m_winCaptured)
515 return;
516
517 if (GetMainWidget())
518 XtRemoveGrab((Widget) GetMainWidget());
519 m_winCaptured = FALSE;
520}
521
522// Push/pop event handler (i.e. allow a chain of event handlers
523// be searched)
524void wxWindow::PushEventHandler(wxEvtHandler *handler)
525{
526 handler->SetNextHandler(GetEventHandler());
527 SetEventHandler(handler);
528}
529
530wxEvtHandler *wxWindow::PopEventHandler(bool deleteHandler)
531{
532 if ( GetEventHandler() )
533 {
534 wxEvtHandler *handlerA = GetEventHandler();
535 wxEvtHandler *handlerB = handlerA->GetNextHandler();
536 handlerA->SetNextHandler(NULL);
537 SetEventHandler(handlerB);
538 if ( deleteHandler )
539 {
540 delete handlerA;
541 return NULL;
542 }
543 else
544 return handlerA;
545 }
546 else
547 return NULL;
548}
549
47d67540 550#if wxUSE_DRAG_AND_DROP
4bb6408c
JS
551
552void wxWindow::SetDropTarget(wxDropTarget *pDropTarget)
553{
554 if ( m_pDropTarget != 0 ) {
555 delete m_pDropTarget;
556 }
557
558 m_pDropTarget = pDropTarget;
559 if ( m_pDropTarget != 0 )
560 {
561 // TODO
562 }
563}
564
565#endif
566
567// Old style file-manager drag&drop
568void wxWindow::DragAcceptFiles(bool accept)
569{
570 // TODO
571}
572
573// Get total size
574void wxWindow::GetSize(int *x, int *y) const
575{
50414e24
JS
576 if (m_drawingArea)
577 {
578 CanvasGetSize(x, y);
579 return;
580 }
581
02e8b2f9 582 Widget widget = (Widget) GetTopWidget();
4bb6408c
JS
583 Dimension xx, yy;
584 XtVaGetValues(widget, XmNwidth, &xx, XmNheight, &yy, NULL);
585 *x = xx; *y = yy;
586}
587
588void wxWindow::GetPosition(int *x, int *y) const
589{
a4294b78
JS
590 if (m_drawingArea)
591 {
592 CanvasGetPosition(x, y);
593 return;
594 }
595 Widget widget = (Widget) GetTopWidget();
596 Position xx, yy;
597 XtVaGetValues(widget, XmNx, &xx, XmNy, &yy, NULL);
598
599 // We may be faking the client origin.
600 // So a window that's really at (0, 30) may appear
601 // (to wxWin apps) to be at (0, 0).
602 if (GetParent())
603 {
604 wxPoint pt(GetParent()->GetClientAreaOrigin());
605 xx -= pt.x;
606 yy -= pt.y;
607 }
608
609 *x = xx; *y = yy;
4bb6408c
JS
610}
611
612void wxWindow::ScreenToClient(int *x, int *y) const
613{
47bc1060
JS
614 Widget widget = (Widget) GetClientWidget();
615 Display *display = XtDisplay((Widget) GetMainWidget());
616 Window rootWindow = RootWindowOfScreen(XtScreen(widget));
617 Window thisWindow = XtWindow(widget);
618
619 Window childWindow;
620 int xx = *x;
621 int yy = *y;
622 XTranslateCoordinates(display, rootWindow, thisWindow, xx, yy, x, y, &childWindow);
4bb6408c
JS
623}
624
625void wxWindow::ClientToScreen(int *x, int *y) const
626{
02e8b2f9 627 Widget widget = (Widget) GetClientWidget();
4bb6408c
JS
628 Display *display = XtDisplay(widget);
629 Window rootWindow = RootWindowOfScreen(XtScreen(widget));
47bc1060 630 Window thisWindow = XtWindow(widget);
4bb6408c
JS
631
632 Window childWindow;
633 int xx = *x;
634 int yy = *y;
635 XTranslateCoordinates(display, thisWindow, rootWindow, xx, yy, x, y, &childWindow);
636}
637
638void wxWindow::SetCursor(const wxCursor& cursor)
639{
640 m_windowCursor = cursor;
641 if (m_windowCursor.Ok())
642 {
4bb6408c 643 WXDisplay *dpy = GetXDisplay();
47bc1060 644 WXCursor x_cursor = ((wxCursor&)cursor).GetXCursor(dpy);
4bb6408c
JS
645
646 Widget w = (Widget) GetMainWidget();
647 Window win = XtWindow(w);
47bc1060 648 XDefineCursor((Display*) dpy, win, (Cursor) x_cursor);
4bb6408c
JS
649 }
650}
651
652
653// Get size *available for subwindows* i.e. excluding menu bar etc.
654void wxWindow::GetClientSize(int *x, int *y) const
655{
47bc1060 656 Widget widget = (Widget) GetClientWidget();
4bb6408c
JS
657 Dimension xx, yy;
658 XtVaGetValues(widget, XmNwidth, &xx, XmNheight, &yy, NULL);
659 *x = xx; *y = yy;
660}
661
662void wxWindow::SetSize(int x, int y, int width, int height, int sizeFlags)
663{
50414e24
JS
664 if (m_drawingArea)
665 {
666 CanvasSetSize(x, y, width, height, sizeFlags);
667 return;
668 }
02e8b2f9
JS
669 Widget widget = (Widget) GetTopWidget();
670 if (!widget)
671 return;
672
673 bool managed = XtIsManaged( widget );
674 if (managed)
675 XtUnmanageChild(widget);
4bb6408c 676
a4294b78
JS
677 int xx = x; int yy = y;
678 AdjustForParentClientOrigin(xx, yy, sizeFlags);
679
4bb6408c 680 if (x > -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
a4294b78 681 XtVaSetValues(widget, XmNx, xx, NULL);
4bb6408c 682 if (y > -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
a4294b78 683 XtVaSetValues(widget, XmNy, yy, NULL);
4bb6408c
JS
684 if (width > -1)
685 XtVaSetValues(widget, XmNwidth, width, NULL);
686 if (height > -1)
687 XtVaSetValues(widget, XmNheight, height, NULL);
688
02e8b2f9
JS
689 if (managed)
690 XtManageChild(widget);
691
4bb6408c
JS
692 wxSizeEvent sizeEvent(wxSize(width, height), GetId());
693 sizeEvent.SetEventObject(this);
694
695 GetEventHandler()->ProcessEvent(sizeEvent);
696}
697
698void wxWindow::SetClientSize(int width, int height)
699{
50414e24
JS
700 if (m_drawingArea)
701 {
702 CanvasSetClientSize(width, height);
703 return;
704 }
705
02e8b2f9 706 Widget widget = (Widget) GetTopWidget();
4bb6408c
JS
707
708 if (width > -1)
709 XtVaSetValues(widget, XmNwidth, width, NULL);
710 if (height > -1)
711 XtVaSetValues(widget, XmNheight, height, NULL);
712
713 wxSizeEvent sizeEvent(wxSize(width, height), GetId());
714 sizeEvent.SetEventObject(this);
715
716 GetEventHandler()->ProcessEvent(sizeEvent);
717}
718
719// For implementation purposes - sometimes decorations make the client area
720// smaller
721wxPoint wxWindow::GetClientAreaOrigin() const
722{
723 return wxPoint(0, 0);
724}
725
726// Makes an adjustment to the window position (for example, a frame that has
727// a toolbar that it manages itself).
728void wxWindow::AdjustForParentClientOrigin(int& x, int& y, int sizeFlags)
729{
730 if (((sizeFlags & wxSIZE_NO_ADJUSTMENTS) == 0) && GetParent())
731 {
732 wxPoint pt(GetParent()->GetClientAreaOrigin());
733 x += pt.x; y += pt.y;
734 }
735}
736
737bool wxWindow::Show(bool show)
738{
50414e24
JS
739 if (show)
740 {
741 if (m_borderWidget || m_scrolledWindow)
742 {
02800301
JS
743 if (m_drawingArea)
744 XtMapWidget((Widget) m_drawingArea);
50414e24
JS
745 XtMapWidget(m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow);
746 }
747 else
748 {
02e8b2f9 749 XtMapWidget((Widget) GetTopWidget());
50414e24
JS
750 }
751 }
752 else
753 {
754 if (m_borderWidget || m_scrolledWindow)
755 {
02800301
JS
756 if (m_drawingArea)
757 XtUnmapWidget((Widget) m_drawingArea);
50414e24
JS
758 XtUnmapWidget(m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow);
759 }
760 else
761 {
02e8b2f9 762 XtUnmapWidget((Widget) GetTopWidget());
50414e24
JS
763 }
764 }
765
766 /*
4bb6408c
JS
767 Window xwin = (Window) GetXWindow();
768 Display *xdisp = (Display*) GetXDisplay();
769 if (show)
770 XMapWindow(xdisp, xwin);
771 else
772 XUnmapWindow(xdisp, xwin);
50414e24 773 */
4bb6408c
JS
774
775 m_isShown = show;
776
777 return TRUE;
778}
779
780bool wxWindow::IsShown() const
781{
782 return m_isShown;
783}
784
785int wxWindow::GetCharHeight() const
786{
47bc1060 787 if (!m_windowFont.Ok())
4bb6408c 788 return 0;
47bc1060
JS
789
790 WXFontStructPtr pFontStruct = m_windowFont.GetFontStruct(1.0, GetXDisplay());
791
792 int direction, ascent, descent;
793 XCharStruct overall;
794 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
795 &descent, &overall);
796// return (overall.ascent + overall.descent);
797 return (ascent + descent);
4bb6408c
JS
798}
799
800int wxWindow::GetCharWidth() const
801{
47bc1060 802 if (!m_windowFont.Ok())
4bb6408c 803 return 0;
47bc1060
JS
804
805 WXFontStructPtr pFontStruct = m_windowFont.GetFontStruct(1.0, GetXDisplay());
806
807 int direction, ascent, descent;
808 XCharStruct overall;
809 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
810 &descent, &overall);
811 return overall.width;
812}
813
814/* Helper function for 16-bit fonts */
815static int str16len(const char *s)
816{
817 int count = 0;
818
819 while (s[0] && s[1]) {
820 count++;
821 s += 2;
822 }
823
824 return count;
4bb6408c
JS
825}
826
827void wxWindow::GetTextExtent(const wxString& string, int *x, int *y,
47bc1060 828 int *descent, int *externalLeading, const wxFont *theFont, bool use16) const
4bb6408c
JS
829{
830 wxFont *fontToUse = (wxFont *)theFont;
831 if (!fontToUse)
832 fontToUse = (wxFont *) & m_windowFont;
833
47bc1060
JS
834 if (!fontToUse->Ok())
835 return;
836
837 WXFontStructPtr pFontStruct = theFont->GetFontStruct(1.0, GetXDisplay());
838
839 int direction, ascent, descent2;
840 XCharStruct overall;
841 int slen;
842
843 if (use16) slen = str16len(string); else slen = strlen(string);
844
845 if (use16)
846 XTextExtents16((XFontStruct*) pFontStruct, (XChar2b *) (char*) (const char*) string, slen, &direction,
847 &ascent, &descent2, &overall);
848 else
849 XTextExtents((XFontStruct*) pFontStruct, (char*) (const char*) string, slen, &direction,
850 &ascent, &descent2, &overall);
851
852 *x = (overall.width);
853 *y = (ascent + descent2);
854 if (descent)
855 *descent = descent2;
856 if (externalLeading)
857 *externalLeading = 0;
4bb6408c
JS
858}
859
860void wxWindow::Refresh(bool eraseBack, const wxRectangle *rect)
861{
862 Display *display = XtDisplay((Widget) GetMainWidget());
863 Window thisWindow = XtWindow((Widget) GetMainWidget());
864
865 XExposeEvent dummyEvent;
866 int width, height;
867 GetSize(&width, &height);
868
869 dummyEvent.type = Expose;
870 dummyEvent.display = display;
871 dummyEvent.send_event = True;
872 dummyEvent.window = thisWindow;
873 if (rect)
874 {
875 dummyEvent.x = rect->x;
876 dummyEvent.y = rect->y;
877 dummyEvent.width = rect->width;
878 dummyEvent.height = rect->height;
879 }
880 else
881 {
882 dummyEvent.x = 0;
883 dummyEvent.y = 0;
884 dummyEvent.width = width;
885 dummyEvent.height = height;
886 }
887 dummyEvent.count = 0;
888
889 if (eraseBack)
890 {
891 wxClientDC dc(this);
e97f20a0
JS
892 wxBrush backgroundBrush(GetBackgroundColour(), wxSOLID);
893 dc.SetBackground(backgroundBrush);
4bb6408c
JS
894 dc.Clear();
895 }
896
897 XSendEvent(display, thisWindow, False, ExposureMask, (XEvent *)&dummyEvent);
898}
899
900// Responds to colour changes: passes event on to children.
901void wxWindow::OnSysColourChanged(wxSysColourChangedEvent& event)
902{
903 wxNode *node = GetChildren()->First();
904 while ( node )
905 {
906 // Only propagate to non-top-level windows
907 wxWindow *win = (wxWindow *)node->Data();
908 if ( win->GetParent() )
909 {
910 wxSysColourChangedEvent event2;
911 event.m_eventObject = win;
912 win->GetEventHandler()->ProcessEvent(event2);
913 }
914
915 node = node->Next();
916 }
917}
918
919// This can be called by the app (or wxWindows) to do default processing for the current
920// event. Save message/event info in wxWindow so they can be used in this function.
921long wxWindow::Default()
922{
923 // TODO
924 return 0;
925}
926
927void wxWindow::InitDialog()
928{
929 wxInitDialogEvent event(GetId());
930 event.SetEventObject( this );
931 GetEventHandler()->ProcessEvent(event);
932}
933
934// Default init dialog behaviour is to transfer data to window
935void wxWindow::OnInitDialog(wxInitDialogEvent& event)
936{
937 TransferDataToWindow();
938}
939
940// Caret manipulation
941void wxWindow::CreateCaret(int w, int h)
942{
943 m_caretWidth = w;
944 m_caretHeight = h;
945 m_caretEnabled = TRUE;
946}
947
948void wxWindow::CreateCaret(const wxBitmap *WXUNUSED(bitmap))
949{
950 // TODO
951}
952
953void wxWindow::ShowCaret(bool show)
954{
955 // TODO
956}
957
958void wxWindow::DestroyCaret()
959{
960 // TODO
961 m_caretEnabled = FALSE;
962}
963
964void wxWindow::SetCaretPos(int x, int y)
965{
966 // TODO
967}
968
969void wxWindow::GetCaretPos(int *x, int *y) const
970{
971 // TODO
972}
973
974wxWindow *wxGetActiveWindow()
975{
976 // TODO
977 return NULL;
978}
979
980void wxWindow::SetSizeHints(int minW, int minH, int maxW, int maxH, int incW, int incH)
981{
982 m_minSizeX = minW;
983 m_minSizeY = minH;
984 m_maxSizeX = maxW;
985 m_maxSizeY = maxH;
986
987 if (!this->IsKindOf(CLASSINFO(wxFrame)))
988 return;
989
990 wxFrame *frame = (wxFrame *)this;
47bc1060 991 Widget widget = (Widget) frame->GetShellWidget();
4bb6408c 992
4bb6408c 993 if (minW > -1)
47bc1060 994 XtVaSetValues(widget, XmNminWidth, minW, NULL);
4bb6408c 995 if (minH > -1)
47bc1060 996 XtVaSetValues(widget, XmNminHeight, minH, NULL);
4bb6408c 997 if (maxW > -1)
47bc1060 998 XtVaSetValues(widget, XmNmaxWidth, maxW, NULL);
4bb6408c 999 if (maxH > -1)
47bc1060 1000 XtVaSetValues(widget, XmNmaxHeight, maxH, NULL);
4bb6408c 1001 if (incW > -1)
47bc1060 1002 XtVaSetValues(widget, XmNwidthInc, incW, NULL);
4bb6408c 1003 if (incH > -1)
47bc1060 1004 XtVaSetValues(widget, XmNheightInc, incH, NULL);
4bb6408c
JS
1005}
1006
1007void wxWindow::Centre(int direction)
1008{
1009 int x, y, width, height, panel_width, panel_height, new_x, new_y;
1010
1011 wxWindow *father = (wxWindow *)GetParent();
1012 if (!father)
1013 return;
1014
1015 father->GetClientSize(&panel_width, &panel_height);
1016 GetSize(&width, &height);
1017 GetPosition(&x, &y);
1018
1019 new_x = -1;
1020 new_y = -1;
1021
1022 if (direction & wxHORIZONTAL)
1023 new_x = (int)((panel_width - width)/2);
1024
1025 if (direction & wxVERTICAL)
1026 new_y = (int)((panel_height - height)/2);
1027
1028 SetSize(new_x, new_y, -1, -1);
1029
1030}
1031
1032// Coordinates relative to the window
50414e24 1033void wxWindow::WarpPointer (int x, int y)
4bb6408c 1034{
50414e24 1035 XWarpPointer (XtDisplay((Widget) GetClientWidget()), None, XtWindow((Widget) GetClientWidget()), 0, 0, 0, 0, x, y);
4bb6408c
JS
1036}
1037
1038void wxWindow::OnEraseBackground(wxEraseEvent& event)
1039{
1040 // TODO
1041 Default();
1042}
1043
1044int wxWindow::GetScrollPos(int orient) const
1045{
47bc1060
JS
1046 if (orient == wxHORIZONTAL)
1047 return m_scrollPosX;
1048 else
1049 return m_scrollPosY;
1050/*
1051 Widget scrollBar = (Widget) ((orient == wxHORIZONTAL) ? m_hScrollBar : m_vScrollBar);
1052 if (scrollBar)
1053 {
1054 int pos;
1055 XtVaGetValues(scrollBar,
1056 XmNvalue, &pos, NULL);
1057 return pos;
1058 }
1059 else
1060 return 0;
1061*/
4bb6408c
JS
1062}
1063
1064// This now returns the whole range, not just the number
1065// of positions that we can scroll.
1066int wxWindow::GetScrollRange(int orient) const
1067{
47bc1060
JS
1068 Widget scrollBar = (Widget) ((orient == wxHORIZONTAL) ? m_hScrollBar : m_vScrollBar);
1069 if (scrollBar)
1070 {
1071 int range;
1072 XtVaGetValues(scrollBar,
1073 XmNmaximum, &range, NULL);
1074 return range;
1075 }
1076 else
1077 return 0;
4bb6408c
JS
1078}
1079
1080int wxWindow::GetScrollThumb(int orient) const
1081{
47bc1060
JS
1082 Widget scrollBar = (Widget) ((orient == wxHORIZONTAL) ? m_hScrollBar : m_vScrollBar);
1083 if (scrollBar)
1084 {
1085 int thumb;
1086 XtVaGetValues(scrollBar,
1087 XmNsliderSize, &thumb, NULL);
1088 return thumb;
1089 }
1090 else
1091 return 0;
4bb6408c
JS
1092}
1093
47bc1060 1094void wxWindow::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh))
4bb6408c 1095{
47bc1060
JS
1096 Widget scrollBar = (Widget) ((orient == wxHORIZONTAL) ? m_hScrollBar : m_vScrollBar);
1097 if (scrollBar)
1098 {
1099 XtVaSetValues (scrollBar,
1100 XmNvalue, pos,
1101 NULL);
1102 }
1103 if (orient == wxHORIZONTAL)
1104 m_scrollPosX = pos;
1105 else
1106 m_scrollPosY = pos;
1107
4bb6408c
JS
1108}
1109
1110// New function that will replace some of the above.
1111void wxWindow::SetScrollbar(int orient, int pos, int thumbVisible,
47bc1060 1112 int range, bool WXUNUSED(refresh))
4bb6408c 1113{
47bc1060
JS
1114 Widget scrollBar = (Widget) ((orient == wxHORIZONTAL) ? m_hScrollBar : m_vScrollBar );
1115 if (!scrollBar)
1116 return;
1117
1118 if (range == 0)
1119 range = 1;
1120 if (thumbVisible == 0)
1121 thumbVisible = 1;
1122
1123 XtVaSetValues(scrollBar,
1124 XmNvalue, pos,
1125 XmNminimum, 0,
1126 XmNmaximum, range,
1127 XmNsliderSize, thumbVisible,
1128 NULL);
1129
1130 if (orient == wxHORIZONTAL)
1131 m_scrollPosX = pos;
1132 else
1133 m_scrollPosY = pos;
4bb6408c
JS
1134}
1135
1136// Does a physical scroll
1137void wxWindow::ScrollWindow(int dx, int dy, const wxRectangle *rect)
1138{
47bc1060
JS
1139// cerr << "Scrolling. delta = " << dx << ", " << dy << endl;
1140 int x, y, w, h;
1141 if (rect)
1142 {
1143 // Use specified rectangle
1144 x = rect->x; y = rect->y; w = rect->width; h = rect->height;
1145 }
1146 else
1147 {
1148 // Use whole client area
1149 x = 0; y = 0;
1150 GetClientSize(& w, & h);
1151 }
1152
1153 int x1 = (dx >= 0) ? x : x - dx ;
1154 int y1 = (dy >= 0) ? y : y - dy;
1155 int w1 = w - abs(dx);
1156 int h1 = h - abs(dy);
1157 int x2 = (dx >= 0) ? x + dx : x;
1158 int y2 = (dy >= 0) ? y + dy : y;
1159
1160 wxClientDC dc(this);
1161
1162 dc.SetLogicalFunction (wxCOPY);
1163
1164 Widget widget = (Widget) GetMainWidget();
1165 Window window = XtWindow(widget);
1166 Display* display = XtDisplay(widget);
1167
1168 XCopyArea(display, window,
1169 window, (GC) dc.GetGC(),
1170 x1, y1,
1171 w1, h1,
1172 x2, y2);
1173
1174 dc.SetAutoSetting(TRUE);
1175 wxBrush brush(GetBackgroundColour(), wxSOLID);
1176 dc.SetBrush(brush); // ??
1177
1178 // We'll add rectangles to the list of update rectangles
1179 // according to which bits we've exposed.
1180 wxList updateRects;
1181
1182 if (dx > 0)
1183 {
1184 wxRect *rect = new wxRect;
1185 rect->x = x;
1186 rect->y = y;
1187 rect->width = dx;
1188 rect->height = h;
1189
1190 XFillRectangle(display, window,
1191 (GC) dc.GetGC(), rect->x, rect->y, rect->width, rect->height);
1192
1193 rect->x = rect->x;
1194 rect->y = rect->y;
1195 rect->width = rect->width;
1196 rect->height = rect->height;
1197
1198 updateRects.Append((wxObject*) rect);
1199 }
1200 else if (dx < 0)
1201 {
1202 wxRect *rect = new wxRect;
1203
1204 rect->x = x + w + dx;
1205 rect->y = y;
1206 rect->width = -dx;
1207 rect->height = h;
1208
1209 XFillRectangle(display, window,
1210 (GC) dc.GetGC(), rect->x, rect->y, rect->width,
1211 rect->height);
1212
1213 rect->x = rect->x;
1214 rect->y = rect->y;
1215 rect->width = rect->width;
1216 rect->height = rect->height;
1217
1218 updateRects.Append((wxObject*) rect);
1219 }
1220 if (dy > 0)
1221 {
1222 wxRect *rect = new wxRect;
1223
1224 rect->x = x;
1225 rect->y = y;
1226 rect->width = w;
1227 rect->height = dy;
1228
1229 XFillRectangle(display, window,
1230 (GC) dc.GetGC(), rect->x, rect->y, rect->width, rect->height);
1231
1232 rect->x = rect->x;
1233 rect->y = rect->y;
1234 rect->width = rect->width;
1235 rect->height = rect->height;
1236
1237 updateRects.Append((wxObject*) rect);
1238 }
1239 else if (dy < 0)
1240 {
1241 wxRect *rect = new wxRect;
1242
1243 rect->x = x;
1244 rect->y = y + h + dy;
1245 rect->width = w;
1246 rect->height = -dy;
1247
1248 XFillRectangle(display, window,
1249 (GC) dc.GetGC(), rect->x, rect->y, rect->width, rect->height);
1250
1251 rect->x = rect->x;
1252 rect->y = rect->y;
1253 rect->width = rect->width;
1254 rect->height = rect->height;
1255
1256 updateRects.Append((wxObject*) rect);
1257 }
1258 dc.SetBrush(wxNullBrush);
1259
1260 // Now send expose events
1261
1262 wxNode* node = updateRects.First();
1263 while (node)
1264 {
1265 wxRect* rect = (wxRect*) node->Data();
1266 XExposeEvent event;
1267
1268 event.type = Expose;
1269 event.display = display;
1270 event.send_event = True;
1271 event.window = window;
1272
1273 event.x = rect->x;
1274 event.y = rect->y;
1275 event.width = rect->width;
1276 event.height = rect->height;
1277
1278 event.count = 0;
1279
1280 XSendEvent(display, window, False, ExposureMask, (XEvent *)&event);
1281
1282 node = node->Next();
1283
1284 }
4bb6408c
JS
1285}
1286
4bb6408c
JS
1287void wxWindow::OnChar(wxKeyEvent& event)
1288{
1289 if ( event.KeyCode() == WXK_TAB ) {
1290 // propagate the TABs to the parent - it's up to it to decide what
1291 // to do with it
1292 if ( GetParent() ) {
1293 if ( GetParent()->ProcessEvent(event) )
1294 return;
1295 }
1296 }
1297}
1298
1299void wxWindow::OnPaint(wxPaintEvent& event)
1300{
1301 Default();
1302}
1303
1304bool wxWindow::IsEnabled() const
1305{
47bc1060
JS
1306 // TODO. Is this right?
1307 // return XtGetSensitive((Widget) GetMainWidget());
4bb6408c
JS
1308 return FALSE;
1309}
1310
1311// Dialog support: override these and call
1312// base class members to add functionality
1313// that can't be done using validators.
1314// NOTE: these functions assume that controls
1315// are direct children of this window, not grandchildren
1316// or other levels of descendant.
1317
1318// Transfer values to controls. If returns FALSE,
1319// it's an application error (pops up a dialog)
1320bool wxWindow::TransferDataToWindow()
1321{
1322 wxNode *node = GetChildren()->First();
1323 while ( node )
1324 {
1325 wxWindow *child = (wxWindow *)node->Data();
1326 if ( child->GetValidator() &&
1327 !child->GetValidator()->TransferToWindow() )
1328 {
1329 wxMessageBox("Application Error", "Could not transfer data to window", wxOK|wxICON_EXCLAMATION);
1330 return FALSE;
1331 }
1332
1333 node = node->Next();
1334 }
1335 return TRUE;
1336}
1337
1338// Transfer values from controls. If returns FALSE,
1339// validation failed: don't quit
1340bool wxWindow::TransferDataFromWindow()
1341{
1342 wxNode *node = GetChildren()->First();
1343 while ( node )
1344 {
1345 wxWindow *child = (wxWindow *)node->Data();
1346 if ( child->GetValidator() && !child->GetValidator()->TransferFromWindow() )
1347 {
1348 return FALSE;
1349 }
1350
1351 node = node->Next();
1352 }
1353 return TRUE;
1354}
1355
1356bool wxWindow::Validate()
1357{
1358 wxNode *node = GetChildren()->First();
1359 while ( node )
1360 {
1361 wxWindow *child = (wxWindow *)node->Data();
1362 if ( child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->Validate(this) )
1363 {
1364 return FALSE;
1365 }
1366
1367 node = node->Next();
1368 }
1369 return TRUE;
1370}
1371
1372// Get the window with the focus
1373wxWindow *wxWindow::FindFocus()
1374{
1375 // TODO
1376 return NULL;
1377}
1378
1379void wxWindow::AddChild(wxWindow *child)
1380{
1381 GetChildren()->Append(child);
1382 child->m_windowParent = this;
1383}
1384
1385void wxWindow::RemoveChild(wxWindow *child)
1386{
1387 if (GetChildren())
1388 GetChildren()->DeleteObject(child);
1389 child->m_windowParent = NULL;
1390}
1391
1392void wxWindow::DestroyChildren()
1393{
02800301
JS
1394 if (GetChildren())
1395 {
1396 wxNode *node = GetChildren()->First();
1397 while (node)
1398 {
1399 wxNode* next = node->Next();
1400 wxWindow* child = (wxWindow*) node->Data();
1401 delete child;
1402 node = next;
1403 }
1404 GetChildren()->Clear();
1405#if 0
4bb6408c
JS
1406 wxNode *node;
1407 while ((node = GetChildren()->First()) != (wxNode *)NULL) {
1408 wxWindow *child;
1409 if ((child = (wxWindow *)node->Data()) != (wxWindow *)NULL) {
1410 delete child;
1411 if ( GetChildren()->Member(child) )
1412 delete node;
1413 }
1414 } /* while */
02800301 1415#endif
4bb6408c
JS
1416 }
1417}
1418
1419void wxWindow::MakeModal(bool modal)
1420{
1421 // Disable all other windows
1422 if (this->IsKindOf(CLASSINFO(wxDialog)) || this->IsKindOf(CLASSINFO(wxFrame)))
1423 {
1424 wxNode *node = wxTopLevelWindows.First();
1425 while (node)
1426 {
1427 wxWindow *win = (wxWindow *)node->Data();
1428 if (win != this)
1429 win->Enable(!modal);
1430
1431 node = node->Next();
1432 }
1433 }
1434}
1435
02e8b2f9
JS
1436// If nothing defined for this, try the parent.
1437// E.g. we may be a button loaded from a resource, with no callback function
1438// defined.
1439void wxWindow::OnCommand(wxWindow& win, wxCommandEvent& event)
1440{
1441 if (GetEventHandler()->ProcessEvent(event) )
1442 return;
1443 if (m_windowParent)
1444 m_windowParent->GetEventHandler()->OnCommand(win, event);
1445}
1446
4bb6408c
JS
1447void wxWindow::SetConstraints(wxLayoutConstraints *c)
1448{
1449 if (m_constraints)
1450 {
1451 UnsetConstraints(m_constraints);
1452 delete m_constraints;
1453 }
1454 m_constraints = c;
1455 if (m_constraints)
1456 {
1457 // Make sure other windows know they're part of a 'meaningful relationship'
1458 if (m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this))
1459 m_constraints->left.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
1460 if (m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this))
1461 m_constraints->top.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
1462 if (m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this))
1463 m_constraints->right.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
1464 if (m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this))
1465 m_constraints->bottom.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
1466 if (m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this))
1467 m_constraints->width.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
1468 if (m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this))
1469 m_constraints->height.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
1470 if (m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this))
1471 m_constraints->centreX.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
1472 if (m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this))
1473 m_constraints->centreY.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
1474 }
1475}
1476
1477// This removes any dangling pointers to this window
1478// in other windows' constraintsInvolvedIn lists.
1479void wxWindow::UnsetConstraints(wxLayoutConstraints *c)
1480{
1481 if (c)
1482 {
1483 if (c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this))
1484 c->left.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
1485 if (c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this))
1486 c->top.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
1487 if (c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this))
1488 c->right.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
1489 if (c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this))
1490 c->bottom.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
1491 if (c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this))
1492 c->width.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
1493 if (c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this))
1494 c->height.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
1495 if (c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this))
1496 c->centreX.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
1497 if (c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this))
1498 c->centreY.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
1499 }
1500}
1501
1502// Back-pointer to other windows we're involved with, so if we delete
1503// this window, we must delete any constraints we're involved with.
1504void wxWindow::AddConstraintReference(wxWindow *otherWin)
1505{
1506 if (!m_constraintsInvolvedIn)
1507 m_constraintsInvolvedIn = new wxList;
1508 if (!m_constraintsInvolvedIn->Member(otherWin))
1509 m_constraintsInvolvedIn->Append(otherWin);
1510}
1511
1512// REMOVE back-pointer to other windows we're involved with.
1513void wxWindow::RemoveConstraintReference(wxWindow *otherWin)
1514{
1515 if (m_constraintsInvolvedIn)
1516 m_constraintsInvolvedIn->DeleteObject(otherWin);
1517}
1518
1519// Reset any constraints that mention this window
1520void wxWindow::DeleteRelatedConstraints()
1521{
1522 if (m_constraintsInvolvedIn)
1523 {
1524 wxNode *node = m_constraintsInvolvedIn->First();
1525 while (node)
1526 {
1527 wxWindow *win = (wxWindow *)node->Data();
1528 wxNode *next = node->Next();
1529 wxLayoutConstraints *constr = win->GetConstraints();
1530
1531 // Reset any constraints involving this window
1532 if (constr)
1533 {
1534 constr->left.ResetIfWin((wxWindow *)this);
1535 constr->top.ResetIfWin((wxWindow *)this);
1536 constr->right.ResetIfWin((wxWindow *)this);
1537 constr->bottom.ResetIfWin((wxWindow *)this);
1538 constr->width.ResetIfWin((wxWindow *)this);
1539 constr->height.ResetIfWin((wxWindow *)this);
1540 constr->centreX.ResetIfWin((wxWindow *)this);
1541 constr->centreY.ResetIfWin((wxWindow *)this);
1542 }
1543 delete node;
1544 node = next;
1545 }
1546 delete m_constraintsInvolvedIn;
1547 m_constraintsInvolvedIn = NULL;
1548 }
1549}
1550
1551void wxWindow::SetSizer(wxSizer *sizer)
1552{
1553 m_windowSizer = sizer;
1554 if (sizer)
1555 sizer->SetSizerParent((wxWindow *)this);
1556}
1557
1558/*
1559 * New version
1560 */
1561
1562bool wxWindow::Layout()
1563{
1564 if (GetConstraints())
1565 {
1566 int w, h;
1567 GetClientSize(&w, &h);
1568 GetConstraints()->width.SetValue(w);
1569 GetConstraints()->height.SetValue(h);
1570 }
1571
1572 // If top level (one sizer), evaluate the sizer's constraints.
1573 if (GetSizer())
1574 {
1575 int noChanges;
1576 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
1577 GetSizer()->LayoutPhase1(&noChanges);
1578 GetSizer()->LayoutPhase2(&noChanges);
1579 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
1580 return TRUE;
1581 }
1582 else
1583 {
1584 // Otherwise, evaluate child constraints
1585 ResetConstraints(); // Mark all constraints as unevaluated
1586 DoPhase(1); // Just one phase need if no sizers involved
1587 DoPhase(2);
1588 SetConstraintSizes(); // Recursively set the real window sizes
1589 }
1590 return TRUE;
1591}
1592
1593
1594// Do a phase of evaluating constraints:
1595// the default behaviour. wxSizers may do a similar
1596// thing, but also impose their own 'constraints'
1597// and order the evaluation differently.
1598bool wxWindow::LayoutPhase1(int *noChanges)
1599{
1600 wxLayoutConstraints *constr = GetConstraints();
1601 if (constr)
1602 {
1603 return constr->SatisfyConstraints((wxWindow *)this, noChanges);
1604 }
1605 else
1606 return TRUE;
1607}
1608
1609bool wxWindow::LayoutPhase2(int *noChanges)
1610{
1611 *noChanges = 0;
1612
1613 // Layout children
1614 DoPhase(1);
1615 DoPhase(2);
1616 return TRUE;
1617}
1618
1619// Do a phase of evaluating child constraints
1620bool wxWindow::DoPhase(int phase)
1621{
1622 int noIterations = 0;
1623 int maxIterations = 500;
1624 int noChanges = 1;
1625 int noFailures = 0;
1626 wxList succeeded;
1627 while ((noChanges > 0) && (noIterations < maxIterations))
1628 {
1629 noChanges = 0;
1630 noFailures = 0;
1631 wxNode *node = GetChildren()->First();
1632 while (node)
1633 {
1634 wxWindow *child = (wxWindow *)node->Data();
1635 if (!child->IsKindOf(CLASSINFO(wxFrame)) && !child->IsKindOf(CLASSINFO(wxDialog)))
1636 {
1637 wxLayoutConstraints *constr = child->GetConstraints();
1638 if (constr)
1639 {
1640 if (succeeded.Member(child))
1641 {
1642 }
1643 else
1644 {
1645 int tempNoChanges = 0;
1646 bool success = ( (phase == 1) ? child->LayoutPhase1(&tempNoChanges) : child->LayoutPhase2(&tempNoChanges) ) ;
1647 noChanges += tempNoChanges;
1648 if (success)
1649 {
1650 succeeded.Append(child);
1651 }
1652 }
1653 }
1654 }
1655 node = node->Next();
1656 }
1657 noIterations ++;
1658 }
1659 return TRUE;
1660}
1661
1662void wxWindow::ResetConstraints()
1663{
1664 wxLayoutConstraints *constr = GetConstraints();
1665 if (constr)
1666 {
1667 constr->left.SetDone(FALSE);
1668 constr->top.SetDone(FALSE);
1669 constr->right.SetDone(FALSE);
1670 constr->bottom.SetDone(FALSE);
1671 constr->width.SetDone(FALSE);
1672 constr->height.SetDone(FALSE);
1673 constr->centreX.SetDone(FALSE);
1674 constr->centreY.SetDone(FALSE);
1675 }
1676 wxNode *node = GetChildren()->First();
1677 while (node)
1678 {
1679 wxWindow *win = (wxWindow *)node->Data();
1680 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
1681 win->ResetConstraints();
1682 node = node->Next();
1683 }
1684}
1685
1686// Need to distinguish between setting the 'fake' size for
1687// windows and sizers, and setting the real values.
1688void wxWindow::SetConstraintSizes(bool recurse)
1689{
1690 wxLayoutConstraints *constr = GetConstraints();
1691 if (constr && constr->left.GetDone() && constr->right.GetDone() &&
1692 constr->width.GetDone() && constr->height.GetDone())
1693 {
1694 int x = constr->left.GetValue();
1695 int y = constr->top.GetValue();
1696 int w = constr->width.GetValue();
1697 int h = constr->height.GetValue();
1698
1699 // If we don't want to resize this window, just move it...
1700 if ((constr->width.GetRelationship() != wxAsIs) ||
1701 (constr->height.GetRelationship() != wxAsIs))
1702 {
1703 // Calls Layout() recursively. AAAGH. How can we stop that.
1704 // Simply take Layout() out of non-top level OnSizes.
1705 SizerSetSize(x, y, w, h);
1706 }
1707 else
1708 {
1709 SizerMove(x, y);
1710 }
1711 }
1712 else if (constr)
1713 {
1714 char *windowClass = this->GetClassInfo()->GetClassName();
1715
1716 wxString winName;
1717 if (GetName() == "")
1718 winName = "unnamed";
1719 else
1720 winName = GetName();
1721 wxDebugMsg("Constraint(s) not satisfied for window of type %s, name %s:\n", (const char *)windowClass, (const char *)winName);
1722 if (!constr->left.GetDone())
1723 wxDebugMsg(" unsatisfied 'left' constraint.\n");
1724 if (!constr->right.GetDone())
1725 wxDebugMsg(" unsatisfied 'right' constraint.\n");
1726 if (!constr->width.GetDone())
1727 wxDebugMsg(" unsatisfied 'width' constraint.\n");
1728 if (!constr->height.GetDone())
1729 wxDebugMsg(" unsatisfied 'height' constraint.\n");
1730 wxDebugMsg("Please check constraints: try adding AsIs() constraints.\n");
1731 }
1732
1733 if (recurse)
1734 {
1735 wxNode *node = GetChildren()->First();
1736 while (node)
1737 {
1738 wxWindow *win = (wxWindow *)node->Data();
1739 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
1740 win->SetConstraintSizes();
1741 node = node->Next();
1742 }
1743 }
1744}
1745
1746// This assumes that all sizers are 'on' the same
1747// window, i.e. the parent of this window.
1748void wxWindow::TransformSizerToActual(int *x, int *y) const
1749{
1750 if (!m_sizerParent || m_sizerParent->IsKindOf(CLASSINFO(wxDialog)) ||
1751 m_sizerParent->IsKindOf(CLASSINFO(wxFrame)) )
1752 return;
1753
1754 int xp, yp;
1755 m_sizerParent->GetPosition(&xp, &yp);
1756 m_sizerParent->TransformSizerToActual(&xp, &yp);
1757 *x += xp;
1758 *y += yp;
1759}
1760
1761void wxWindow::SizerSetSize(int x, int y, int w, int h)
1762{
1763 int xx = x;
1764 int yy = y;
1765 TransformSizerToActual(&xx, &yy);
1766 SetSize(xx, yy, w, h);
1767}
1768
1769void wxWindow::SizerMove(int x, int y)
1770{
1771 int xx = x;
1772 int yy = y;
1773 TransformSizerToActual(&xx, &yy);
1774 Move(xx, yy);
1775}
1776
1777// Only set the size/position of the constraint (if any)
1778void wxWindow::SetSizeConstraint(int x, int y, int w, int h)
1779{
1780 wxLayoutConstraints *constr = GetConstraints();
1781 if (constr)
1782 {
1783 if (x != -1)
1784 {
1785 constr->left.SetValue(x);
1786 constr->left.SetDone(TRUE);
1787 }
1788 if (y != -1)
1789 {
1790 constr->top.SetValue(y);
1791 constr->top.SetDone(TRUE);
1792 }
1793 if (w != -1)
1794 {
1795 constr->width.SetValue(w);
1796 constr->width.SetDone(TRUE);
1797 }
1798 if (h != -1)
1799 {
1800 constr->height.SetValue(h);
1801 constr->height.SetDone(TRUE);
1802 }
1803 }
1804}
1805
1806void wxWindow::MoveConstraint(int x, int y)
1807{
1808 wxLayoutConstraints *constr = GetConstraints();
1809 if (constr)
1810 {
1811 if (x != -1)
1812 {
1813 constr->left.SetValue(x);
1814 constr->left.SetDone(TRUE);
1815 }
1816 if (y != -1)
1817 {
1818 constr->top.SetValue(y);
1819 constr->top.SetDone(TRUE);
1820 }
1821 }
1822}
1823
1824void wxWindow::GetSizeConstraint(int *w, int *h) const
1825{
1826 wxLayoutConstraints *constr = GetConstraints();
1827 if (constr)
1828 {
1829 *w = constr->width.GetValue();
1830 *h = constr->height.GetValue();
1831 }
1832 else
1833 GetSize(w, h);
1834}
1835
1836void wxWindow::GetClientSizeConstraint(int *w, int *h) const
1837{
1838 wxLayoutConstraints *constr = GetConstraints();
1839 if (constr)
1840 {
1841 *w = constr->width.GetValue();
1842 *h = constr->height.GetValue();
1843 }
1844 else
1845 GetClientSize(w, h);
1846}
1847
1848void wxWindow::GetPositionConstraint(int *x, int *y) const
1849{
1850 wxLayoutConstraints *constr = GetConstraints();
1851 if (constr)
1852 {
1853 *x = constr->left.GetValue();
1854 *y = constr->top.GetValue();
1855 }
1856 else
1857 GetPosition(x, y);
1858}
1859
1860bool wxWindow::Close(bool force)
1861{
1862 wxCloseEvent event(wxEVT_CLOSE_WINDOW, m_windowId);
1863 event.SetEventObject(this);
1864 event.SetForce(force);
1865
1866 return GetEventHandler()->ProcessEvent(event);
1867}
1868
1869wxObject* wxWindow::GetChild(int number) const
1870{
1871 // Return a pointer to the Nth object in the window
1872 if (!GetChildren())
1873 return(NULL) ;
1874 wxNode *node = GetChildren()->First();
1875 int n = number;
1876 while (node && n--)
1877 node = node->Next() ;
1878 if (node)
1879 {
1880 wxObject *obj = (wxObject *)node->Data();
1881 return(obj) ;
1882 }
1883 else
1884 return NULL ;
1885}
1886
1887void wxWindow::OnDefaultAction(wxControl *initiatingItem)
1888{
1889 // Obsolete function
1890}
1891
1892void wxWindow::Clear()
1893{
e97f20a0 1894 wxClientDC dc(this);
4bb6408c
JS
1895 wxBrush brush(GetBackgroundColour(), wxSOLID);
1896 dc.SetBackground(brush);
1897 dc.Clear();
1898}
1899
1900// Fits the panel around the items
1901void wxWindow::Fit()
1902{
1903 int maxX = 0;
1904 int maxY = 0;
1905 wxNode *node = GetChildren()->First();
1906 while ( node )
1907 {
1908 wxWindow *win = (wxWindow *)node->Data();
1909 int wx, wy, ww, wh;
1910 win->GetPosition(&wx, &wy);
1911 win->GetSize(&ww, &wh);
1912 if ( wx + ww > maxX )
1913 maxX = wx + ww;
1914 if ( wy + wh > maxY )
1915 maxY = wy + wh;
1916
1917 node = node->Next();
1918 }
1919 SetClientSize(maxX + 5, maxY + 5);
1920}
1921
1922void wxWindow::SetValidator(const wxValidator& validator)
1923{
1924 if ( m_windowValidator )
1925 delete m_windowValidator;
1926 m_windowValidator = validator.Clone();
1927
1928 if ( m_windowValidator )
1929 m_windowValidator->SetWindow(this) ;
3dd4e4e0
JS
1930}
1931
1932void wxWindow::SetClientObject( wxClientData *data )
1933{
1934 if (m_clientObject) delete m_clientObject;
1935 m_clientObject = data;
1936}
1937
1938wxClientData *wxWindow::GetClientObject()
1939{
1940 return m_clientObject;
1941}
1942
1943void wxWindow::SetClientData( void *data )
1944{
1945 m_clientData = data;
1946}
1947
1948void *wxWindow::GetClientData()
1949{
1950 return m_clientData;
4bb6408c
JS
1951}
1952
1953// Find a window by id or name
1954wxWindow *wxWindow::FindWindow(long id)
1955{
1956 if ( GetId() == id)
1957 return this;
1958
1959 wxNode *node = GetChildren()->First();
1960 while ( node )
1961 {
1962 wxWindow *child = (wxWindow *)node->Data();
1963 wxWindow *found = child->FindWindow(id);
1964 if ( found )
1965 return found;
1966 node = node->Next();
1967 }
1968 return NULL;
1969}
1970
1971wxWindow *wxWindow::FindWindow(const wxString& name)
1972{
1973 if ( GetName() == name)
1974 return this;
1975
1976 wxNode *node = GetChildren()->First();
1977 while ( node )
1978 {
1979 wxWindow *child = (wxWindow *)node->Data();
1980 wxWindow *found = child->FindWindow(name);
1981 if ( found )
1982 return found;
1983 node = node->Next();
1984 }
1985 return NULL;
1986}
1987
1988void wxWindow::OnIdle(wxIdleEvent& event)
1989{
4bb6408c
JS
1990 // This calls the UI-update mechanism (querying windows for
1991 // menu/toolbar/control state information)
0d57be45 1992 UpdateWindowUI();
4bb6408c
JS
1993}
1994
1995// Raise the window to the top of the Z order
1996void wxWindow::Raise()
1997{
02e8b2f9
JS
1998 Window window = XtWindow((Widget) GetTopWidget());
1999 XRaiseWindow(XtDisplay((Widget) GetTopWidget()), window);
4bb6408c
JS
2000}
2001
2002// Lower the window to the bottom of the Z order
2003void wxWindow::Lower()
2004{
02e8b2f9
JS
2005 Window window = XtWindow((Widget) GetTopWidget());
2006 XLowerWindow(XtDisplay((Widget) GetTopWidget()), window);
4bb6408c
JS
2007}
2008
2009bool wxWindow::AcceptsFocus() const
2010{
2011 return IsShown() && IsEnabled();
2012}
2013
2014// Update region access
55acd85e 2015wxRegion& wxWindow::GetUpdateRegion() const
4bb6408c 2016{
55acd85e 2017 return (wxRegion&) m_updateRegion;
4bb6408c
JS
2018}
2019
2020bool wxWindow::IsExposed(int x, int y, int w, int h) const
2021{
2022 return (m_updateRegion.Contains(x, y, w, h) != wxOutRegion);
2023}
2024
2025bool wxWindow::IsExposed(const wxPoint& pt) const
2026{
2027 return (m_updateRegion.Contains(pt) != wxOutRegion);
2028}
2029
2030bool wxWindow::IsExposed(const wxRect& rect) const
2031{
2032 return (m_updateRegion.Contains(rect) != wxOutRegion);
2033}
2034
2035/*
2036 * Allocates control IDs
2037 */
2038
2039int wxWindow::NewControlId()
2040{
2041 static int s_controlId = 0;
2042 s_controlId ++;
2043 return s_controlId;
2044}
2045
2046void wxWindow::SetAcceleratorTable(const wxAcceleratorTable& accel)
2047{
2048 m_acceleratorTable = accel;
2049}
2050
2051// All widgets should have this as their resize proc.
2052// OnSize sent to wxWindow via client data.
2053void wxWidgetResizeProc(Widget w, XConfigureEvent *event, String args[], int *num_args)
2054{
2055 wxWindow *win = (wxWindow *)wxWidgetHashTable->Get((long)w);
2056 if (!win)
2057 return;
2058
2059 if (win->PreResize())
2060 {
2061 int width, height;
2062 win->GetSize(&width, &height);
2063 wxSizeEvent sizeEvent(wxSize(width, height), win->GetId());
2064 sizeEvent.SetEventObject(win);
2065 win->GetEventHandler()->ProcessEvent(sizeEvent);
2066 }
2067}
2068
2069bool wxAddWindowToTable(Widget w, wxWindow *win)
2070{
2071 wxWindow *oldItem = NULL;
4bb6408c 2072// printf("Adding widget %ld, name = %s\n", w, win->GetClassInfo()->GetClassName());
4bb6408c
JS
2073 if ((oldItem = (wxWindow *)wxWidgetHashTable->Get ((long) w)))
2074 {
2075 char buf[300];
2076 sprintf(buf, "Widget table clash: new widget is %ld, %s", (long)w, win->GetClassInfo()->GetClassName());
2077 wxError (buf);
2078 fflush(stderr);
2079 sprintf(buf, "Old widget was %s", oldItem->GetClassInfo()->GetClassName());
2080 wxError (buf);
2081 return FALSE;
2082 }
2083
2084 wxWidgetHashTable->Put ((long) w, win);
2085 return TRUE;
2086}
2087
2088wxWindow *wxGetWindowFromTable(Widget w)
2089{
2090 return (wxWindow *)wxWidgetHashTable->Get ((long) w);
2091}
2092
2093void wxDeleteWindowFromTable(Widget w)
2094{
4bb6408c
JS
2095 wxWidgetHashTable->Delete((long)w);
2096}
2097
2098// Get the underlying X window and display
2099WXWindow wxWindow::GetXWindow() const
2100{
50414e24 2101 return (WXWindow) XtWindow((Widget) GetMainWidget());
4bb6408c
JS
2102}
2103
2104WXDisplay *wxWindow::GetXDisplay() const
2105{
50414e24 2106 return (WXDisplay*) XtDisplay((Widget) GetMainWidget());
4bb6408c
JS
2107}
2108
2109WXWidget wxWindow::GetMainWidget() const
2110{
50414e24
JS
2111 if (m_drawingArea)
2112 return m_drawingArea;
2113 else
2114 return m_mainWidget;
2115}
2116
2117WXWidget wxWindow::GetClientWidget() const
2118{
2119 if (m_drawingArea != (WXWidget) 0)
2120 return m_drawingArea;
2121 else
02e8b2f9
JS
2122 return GetMainWidget();
2123}
2124
2125WXWidget wxWindow::GetTopWidget() const
2126{
2127 return GetMainWidget();
4bb6408c
JS
2128}
2129
50414e24
JS
2130void wxCanvasRepaintProc (Widget drawingArea, XtPointer clientData,
2131 XmDrawingAreaCallbackStruct * cbs)
2132{
2133 if (!wxWidgetHashTable->Get ((long) (Widget) drawingArea))
55acd85e 2134 return;
50414e24
JS
2135
2136 XEvent * event = cbs->event;
55acd85e
JS
2137 wxWindow * win = (wxWindow *) clientData;
2138 Display * display = (Display *) win->GetXDisplay();
50414e24
JS
2139
2140 switch (event->type)
2141 {
55acd85e
JS
2142 case Expose:
2143 {
2144 wxRect* rect = new wxRect(event->xexpose.x, event->xexpose.y,
2145 event->xexpose.width, event->xexpose.height);
2146 /*
2147 cout << "Expose proc. wxRect: " << rect->x << ", " << rect->y << ", ";
2148 cout << rect->width << ", " << rect->height << "\n\n";
2149 */
50414e24 2150
55acd85e 2151 win->m_updateRects.Append((wxObject*) rect);
50414e24 2152
55acd85e
JS
2153 if (event -> xexpose.count == 0)
2154 {
2155 wxPaintEvent event(win->GetId());
2156 event.SetEventObject(win);
2157 win->GetEventHandler()->ProcessEvent(event);
50414e24 2158
55acd85e
JS
2159 win->ClearUpdateRects();
2160 }
2161 break;
2162 }
2163 default:
2164 {
2165 cout << "\n\nNew Event ! is = " << event -> type << "\n";
2166 break;
2167 }
50414e24 2168 }
50414e24
JS
2169}
2170
2171// Unable to deal with Enter/Leave without a separate EventHandler (Motif 1.1.4)
2172void
2173wxCanvasEnterLeave (Widget drawingArea, XtPointer clientData, XCrossingEvent * event)
2174{
2175 XmDrawingAreaCallbackStruct cbs;
2176 XEvent ev;
2177
2178 //if (event->mode!=NotifyNormal)
2179 // return ;
2180
2181// ev = *((XEvent *) event); // Causes Purify error (copying too many bytes)
2182 ((XCrossingEvent &) ev) = *event;
2183
2184 cbs.reason = XmCR_INPUT;
2185 cbs.event = &ev;
2186
2187 wxCanvasInputEvent (drawingArea, (XtPointer) NULL, &cbs);
2188}
2189
2190// Fix to make it work under Motif 1.0 (!)
2191void wxCanvasMotionEvent (Widget drawingArea, XButtonEvent * event)
2192{
2193#if XmVersion<=1000
4bb6408c 2194
50414e24
JS
2195 XmDrawingAreaCallbackStruct cbs;
2196 XEvent ev;
2197
2198 //ev.xbutton = *event;
2199 ev = *((XEvent *) event);
2200 cbs.reason = XmCR_INPUT;
2201 cbs.event = &ev;
2202
2203 wxCanvasInputEvent (drawingArea, (XtPointer) NULL, &cbs);
2204#endif
2205}
2206
2207void wxCanvasInputEvent (Widget drawingArea, XtPointer data, XmDrawingAreaCallbackStruct * cbs)
2208{
2209 wxWindow *canvas = (wxWindow *) wxWidgetHashTable->Get ((long) (Widget) drawingArea);
2210 XEvent local_event;
2211
2212 if (canvas==NULL)
2213 return ;
2214
2215 if (cbs->reason != XmCR_INPUT)
2216 return;
2217
2218 local_event = *(cbs->event); // We must keep a copy!
2219
2220 switch (local_event.xany.type)
2221 {
2222 case EnterNotify:
2223 case LeaveNotify:
2224 case ButtonPress:
2225 case ButtonRelease:
2226 case MotionNotify:
2227 {
2228 wxEventType eventType = wxEVT_NULL;
2229
2230 if (local_event.xany.type == EnterNotify)
2231 {
2232 //if (local_event.xcrossing.mode!=NotifyNormal)
2233 // return ; // Ignore grab events
2234 eventType = wxEVT_ENTER_WINDOW;
2235// canvas->GetEventHandler()->OnSetFocus();
2236 }
2237 else if (local_event.xany.type == LeaveNotify)
2238 {
2239 //if (local_event.xcrossing.mode!=NotifyNormal)
2240 // return ; // Ignore grab events
2241 eventType = wxEVT_LEAVE_WINDOW;
2242// canvas->GetEventHandler()->OnKillFocus();
2243 }
2244 else if (local_event.xany.type == MotionNotify)
2245 {
2246 eventType = wxEVT_MOTION;
2247 if (local_event.xmotion.is_hint == NotifyHint)
2248 {
2249 Window root, child;
2250 Display *dpy = XtDisplay (drawingArea);
2251
2252 XQueryPointer (dpy, XtWindow (drawingArea),
2253 &root, &child,
2254 &local_event.xmotion.x_root,
2255 &local_event.xmotion.y_root,
2256 &local_event.xmotion.x,
2257 &local_event.xmotion.y,
2258 &local_event.xmotion.state);
2259 }
2260 else
2261 {
2262 }
2263 }
2264
2265 else if (local_event.xany.type == ButtonPress)
2266 {
2267 if (local_event.xbutton.button == Button1)
2268 {
2269 eventType = wxEVT_LEFT_DOWN;
2270 canvas->m_button1Pressed = TRUE;
2271 }
2272 else if (local_event.xbutton.button == Button2)
2273 {
2274 eventType = wxEVT_MIDDLE_DOWN;
2275 canvas->m_button2Pressed = TRUE;
2276 }
2277 else if (local_event.xbutton.button == Button3)
2278 {
2279 eventType = wxEVT_RIGHT_DOWN;
2280 canvas->m_button3Pressed = TRUE;
2281 }
2282 }
2283 else if (local_event.xany.type == ButtonRelease)
2284 {
2285 if (local_event.xbutton.button == Button1)
2286 {
2287 eventType = wxEVT_LEFT_UP;
2288 canvas->m_button1Pressed = FALSE;
2289 }
2290 else if (local_event.xbutton.button == Button2)
2291 {
2292 eventType = wxEVT_MIDDLE_UP;
2293 canvas->m_button2Pressed = FALSE;
2294 }
2295 else if (local_event.xbutton.button == Button3)
2296 {
2297 eventType = wxEVT_RIGHT_UP;
2298 canvas->m_button3Pressed = FALSE;
2299 }
2300 }
2301
2302 wxMouseEvent wxevent (eventType);
2303 wxevent.m_eventHandle = (char *) &local_event;
2304
2305 wxevent.m_leftDown = ((eventType == wxEVT_LEFT_DOWN)
2306 || (event_left_is_down (&local_event)
2307 && (eventType != wxEVT_LEFT_UP)));
2308 wxevent.m_middleDown = ((eventType == wxEVT_MIDDLE_DOWN)
2309 || (event_middle_is_down (&local_event)
2310 && (eventType != wxEVT_MIDDLE_UP)));
2311 wxevent.m_rightDown = ((eventType == wxEVT_RIGHT_DOWN)
2312 || (event_right_is_down (&local_event)
2313 && (eventType != wxEVT_RIGHT_UP)));
2314
2315 wxevent.m_shiftDown = local_event.xbutton.state & ShiftMask;
2316 wxevent.m_controlDown = local_event.xbutton.state & ControlMask;
2317 wxevent.m_altDown = local_event.xbutton.state & Mod3Mask;
2318 wxevent.m_metaDown = local_event.xbutton.state & Mod1Mask;
2319 wxevent.SetTimestamp(local_event.xbutton.time);
2320
2321 // Now check if we need to translate this event into a double click
2322 if (TRUE) // canvas->doubleClickAllowed)
2323 {
2324 if (wxevent.ButtonDown())
2325 {
2326 long dclickTime = XtGetMultiClickTime((Display*) wxGetDisplay()) ;
2327
2328 // get button and time-stamp
2329 int button = 0;
2330 if (wxevent.LeftDown()) button = 1;
2331 else if (wxevent.MiddleDown()) button = 2;
2332 else if (wxevent.RightDown()) button = 3;
2333 long ts = wxevent.GetTimestamp();
2334 // check, if single or double click
2335 if (canvas->m_lastButton && canvas->m_lastButton==button && (ts - canvas->m_lastTS) < dclickTime)
2336 {
2337 // I have a dclick
2338 canvas->m_lastButton = 0;
2339 switch ( eventType )
2340 {
2341 case wxEVT_LEFT_DOWN:
2342 wxevent.SetEventType(wxEVT_LEFT_DCLICK);
2343 break;
2344 case wxEVT_MIDDLE_DOWN:
2345 wxevent.SetEventType(wxEVT_MIDDLE_DCLICK);
2346 break;
2347 case wxEVT_RIGHT_DOWN:
2348 wxevent.SetEventType(wxEVT_RIGHT_DCLICK);
2349 break;
2350
2351 default :
2352 break;
2353 }
2354
2355 }
2356 else
2357 {
2358 // not fast enough or different button
2359 canvas->m_lastTS = ts;
2360 canvas->m_lastButton = button;
2361 }
2362 }
2363 }
2364
2365 wxevent.SetId(canvas->GetId());
2366 wxevent.SetEventObject(canvas);
a4294b78
JS
2367 wxevent.m_x = local_event.xbutton.x;
2368 wxevent.m_y = local_event.xbutton.y;
50414e24
JS
2369 canvas->GetEventHandler()->ProcessEvent (wxevent);
2370 /*
2371 if (eventType == wxEVT_ENTER_WINDOW ||
2372 eventType == wxEVT_LEAVE_WINDOW ||
2373 eventType == wxEVT_MOTION
2374 )
2375 return;
2376 */
2377 break;
2378 }
2379 case KeyPress:
2380 {
2381 KeySym keySym;
2382// XComposeStatus compose;
2383// (void) XLookupString ((XKeyEvent *) & local_event, wxBuffer, 20, &keySym, &compose);
2384 (void) XLookupString ((XKeyEvent *) & local_event, wxBuffer, 20, &keySym, NULL);
2385 int id = wxCharCodeXToWX (keySym);
2386
2387 wxKeyEvent event (wxEVT_CHAR);
2388
2389 if (local_event.xkey.state & ShiftMask)
2390 event.m_shiftDown = TRUE;
2391 if (local_event.xkey.state & ControlMask)
2392 event.m_controlDown = TRUE;
2393 if (local_event.xkey.state & Mod3Mask)
2394 event.m_altDown = TRUE;
2395 if (local_event.xkey.state & Mod1Mask)
2396 event.m_metaDown = TRUE;
2397 event.SetEventObject(canvas);
2398 event.m_keyCode = id;
2399 event.SetTimestamp(local_event.xkey.time);
2400
2401 if (id > -1)
2402 {
2403 // Implement wxFrame::OnCharHook by checking ancestor.
2404 wxWindow *parent = canvas->GetParent();
2405 while (parent && !parent->IsKindOf(CLASSINFO(wxFrame)))
2406 parent = parent->GetParent();
2407
2408 if (parent)
2409 {
2410 event.SetEventType(wxEVT_CHAR_HOOK);
2411 if (parent->GetEventHandler()->ProcessEvent(event))
2412 return;
2413 event.SetEventType(wxEVT_CHAR);
2414 }
2415
2416 canvas->GetEventHandler()->ProcessEvent (event);
2417 }
2418 break;
2419 }
2420 case FocusIn:
2421 {
2422 if (local_event.xfocus.detail != NotifyPointer)
2423 {
2424 wxFocusEvent event(wxEVT_SET_FOCUS, canvas->GetId());
2425 event.SetEventObject(canvas);
2426 canvas->GetEventHandler()->ProcessEvent(event);
2427 }
2428 break;
2429 }
2430 case FocusOut:
2431 {
2432 if (local_event.xfocus.detail != NotifyPointer)
2433 {
2434 wxFocusEvent event(wxEVT_KILL_FOCUS, canvas->GetId());
2435 event.SetEventObject(canvas);
2436 canvas->GetEventHandler()->ProcessEvent(event);
2437 }
2438 break;
2439 }
2440 default:
2441 break;
2442 }
2443}
2444
2445void wxWindow::DoPaint()
2446{
2447 //TODO : make a temporary gc so we can do the XCopyArea below
2448 if (0) // m_backingPixmap)
2449 {
2450 /*
2451 Widget drawingArea = (Widget) m_drawingArea;
2452 // int orig = GetDC()->GetLogicalFunction();
2453 // GetDC()->SetLogicalFunction (wxCOPY);
2454
2455 // TODO: it may not be necessary to store m_pixmapOffsetX/Y; we
2456 // should be able to calculate them.
2457 XCopyArea (XtDisplay (drawingArea), m_backingPixmap, XtWindow (drawingArea), GetDC ()->gc,
2458 m_pixmapOffsetX, m_pixmapOffsetY,
2459 m_pixmapWidth, m_pixmapHeight,
2460 0, 0);
2461
2462 // GetDC()->SetLogicalFunction (orig);
2463 */
2464 }
2465 else
2466 {
2467 wxPaintEvent event(GetId());
2468 event.SetEventObject(this);
2469 GetEventHandler()->ProcessEvent(event);
2470 }
2471}
2472
2473// SetSize, but as per old wxCanvas (with drawing widget etc.)
2474void wxWindow::CanvasSetSize (int x, int y, int w, int h, int sizeFlags)
2475{
2476 Widget drawingArea = (Widget) m_drawingArea;
2477 bool managed = XtIsManaged(m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow);
2478
2479 if (managed)
2480 XtUnmanageChild (m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow);
2481 XtVaSetValues((Widget) m_drawingArea, XmNresizePolicy, XmRESIZE_ANY, NULL);
2482
a4294b78
JS
2483 int xx = x; int yy = y;
2484 AdjustForParentClientOrigin(xx, yy, sizeFlags);
2485
50414e24
JS
2486 if (x > -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
2487 {
2488 XtVaSetValues (m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow,
a4294b78 2489 XmNx, xx, NULL);
50414e24
JS
2490 }
2491
2492 if (y > -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
2493 {
2494 XtVaSetValues (m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow,
a4294b78 2495 XmNy, yy, NULL);
50414e24
JS
2496 }
2497
2498 if (w > -1)
2499 {
2500 if (m_borderWidget)
2501 {
2502 XtVaSetValues ((Widget) m_borderWidget, XmNwidth, w, NULL);
2503 short thick, margin;
2504 XtVaGetValues ((Widget) m_borderWidget,
2505 XmNshadowThickness, &thick,
2506 XmNmarginWidth, &margin,
2507 NULL);
2508 w -= 2 * (thick + margin);
2509 }
2510
2511 XtVaSetValues ((Widget) m_scrolledWindow, XmNwidth, w, NULL);
2512
2513 Dimension spacing;
2514 Widget sbar;
2515 XtVaGetValues ((Widget) m_scrolledWindow,
2516 XmNspacing, &spacing,
2517 XmNverticalScrollBar, &sbar,
2518 NULL);
2519 Dimension wsbar;
2520 if (sbar)
2521 XtVaGetValues (sbar, XmNwidth, &wsbar, NULL);
2522 else
2523 wsbar = 0;
2524
2525 w -= (spacing + wsbar);
2526
2527 XtVaSetValues ((Widget) m_drawingArea, XmNwidth, w, NULL);
2528 }
2529 if (h > -1)
2530 {
2531 if (m_borderWidget)
2532 {
2533 XtVaSetValues ((Widget) m_borderWidget, XmNheight, h, NULL);
2534 short thick, margin;
2535 XtVaGetValues ((Widget) m_borderWidget,
2536 XmNshadowThickness, &thick,
2537 XmNmarginHeight, &margin,
2538 NULL);
2539 h -= 2 * (thick + margin);
2540 }
2541
2542 XtVaSetValues ((Widget) m_scrolledWindow, XmNheight, h, NULL);
2543
2544 Dimension spacing;
2545 Widget sbar;
2546 XtVaGetValues ((Widget) m_scrolledWindow,
2547 XmNspacing, &spacing,
2548 XmNhorizontalScrollBar, &sbar,
2549 NULL);
2550 Dimension wsbar;
2551 if (sbar)
2552 XtVaGetValues (sbar, XmNheight, &wsbar, NULL);
2553 else
2554 wsbar = 0;
2555
2556 h -= (spacing + wsbar);
2557
2558 XtVaSetValues ((Widget) m_drawingArea, XmNheight, h, NULL);
2559 }
2560 if (managed)
2561 XtManageChild (m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow);
2562 XtVaSetValues((Widget) m_drawingArea, XmNresizePolicy, XmRESIZE_NONE, NULL);
2563
2564 int ww, hh;
2565 GetClientSize (&ww, &hh);
2566 wxSizeEvent sizeEvent(wxSize(ww, hh), GetId());
2567 sizeEvent.SetEventObject(this);
2568
2569 GetEventHandler()->ProcessEvent(sizeEvent);
2570}
2571
2572void wxWindow::CanvasSetClientSize (int w, int h)
2573{
2574 Widget drawingArea = (Widget) m_drawingArea;
2575
2576 XtVaSetValues((Widget) m_drawingArea, XmNresizePolicy, XmRESIZE_ANY, NULL);
2577
2578 if (w > -1)
2579 XtVaSetValues ((Widget) m_drawingArea, XmNwidth, w, NULL);
2580 if (h > -1)
2581 XtVaSetValues ((Widget) m_drawingArea, XmNheight, h, NULL);
2582 /* TODO: is this necessary?
2583 allowRepainting = FALSE;
2584
2585 XSync (XtDisplay (drawingArea), FALSE);
2586 XEvent event;
2587 while (XtAppPending (wxTheApp->appContext))
2588 {
2589 XFlush (XtDisplay (drawingArea));
2590 XtAppNextEvent (wxTheApp->appContext, &event);
2591 XtDispatchEvent (&event);
2592 }
2593 */
2594
2595 XtVaSetValues((Widget) m_drawingArea, XmNresizePolicy, XmRESIZE_NONE, NULL);
2596
2597 /* TODO
2598 allowRepainting = TRUE;
2599 DoRefresh ();
2600 */
2601
2602 wxSizeEvent sizeEvent(wxSize(w, h), GetId());
2603 sizeEvent.SetEventObject(this);
2604
2605 GetEventHandler()->ProcessEvent(sizeEvent);
2606}
2607
2608void wxWindow::CanvasGetClientSize (int *w, int *h) const
2609{
2610 // Must return the same thing that was set via SetClientSize
2611 Dimension xx, yy;
2612 XtVaGetValues ((Widget) m_drawingArea, XmNwidth, &xx, XmNheight, &yy, NULL);
2613 *w = xx;
2614 *h = yy;
2615}
2616
2617void wxWindow::CanvasGetSize (int *w, int *h) const
2618{
2619 Dimension xx, yy;
2620 if ((Widget) m_borderWidget)
2621 XtVaGetValues ((Widget) m_borderWidget, XmNwidth, &xx, XmNheight, &yy, NULL);
2622 else if ((Widget) m_scrolledWindow)
2623 XtVaGetValues ((Widget) m_scrolledWindow, XmNwidth, &xx, XmNheight, &yy, NULL);
2624 else
2625 XtVaGetValues ((Widget) m_drawingArea, XmNwidth, &xx, XmNheight, &yy, NULL);
2626
2627 *w = xx;
2628 *h = yy;
2629}
2630
2631void wxWindow::CanvasGetPosition (int *x, int *y) const
2632{
a4294b78
JS
2633 Position xx, yy;
2634 XtVaGetValues (m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow, XmNx, &xx, XmNy, &yy, NULL);
2635
2636 // We may be faking the client origin.
2637 // So a window that's really at (0, 30) may appear
2638 // (to wxWin apps) to be at (0, 0).
2639 if (GetParent())
2640 {
2641 wxPoint pt(GetParent()->GetClientAreaOrigin());
2642 xx -= pt.x;
2643 yy -= pt.y;
2644 }
2645
2646 *x = xx;
2647 *y = yy;
50414e24 2648}
02e8b2f9
JS
2649
2650// Add to hash table, add event handler
2651bool wxWindow::AttachWidget (wxWindow* parent, WXWidget mainWidget,
2652 WXWidget formWidget, int x, int y, int width, int height)
2653{
2654 wxAddWindowToTable((Widget) mainWidget, this);
2655 if (CanAddEventHandler())
2656 {
2657 XtAddEventHandler((Widget) mainWidget,
2658 ButtonPressMask | ButtonReleaseMask | PointerMotionMask, // | KeyPressMask,
2659 False,
2660 wxPanelItemEventHandler,
2661 (XtPointer) this);
2662 }
2663
2664 if (!formWidget)
2665 {
2666 XtTranslations ptr;
2667 XtOverrideTranslations ((Widget) mainWidget,
2668 ptr = XtParseTranslationTable ("<Configure>: resize()"));
2669 XtFree ((char *) ptr);
2670 }
2671
2672 // Some widgets have a parent form widget, e.g. wxRadioBox
2673 if (formWidget)
2674 {
2675 if (!wxAddWindowToTable((Widget) formWidget, this))
2676 return FALSE;
2677
2678 XtTranslations ptr;
2679 XtOverrideTranslations ((Widget) formWidget,
2680 ptr = XtParseTranslationTable ("<Configure>: resize()"));
2681 XtFree ((char *) ptr);
2682 }
2683
2684 if (x == -1)
2685 x = 0;
2686 if (y == -1)
2687 y = 0;
2688 SetSize (x, y, width, height);
2689
2690 return TRUE;
2691}
2692
2693// Remove event handler, remove from hash table
2694bool wxWindow::DetachWidget(WXWidget widget)
2695{
2696 if (CanAddEventHandler())
2697 {
2698 XtRemoveEventHandler((Widget) widget,
2699 ButtonPressMask | ButtonReleaseMask | PointerMotionMask, // | KeyPressMask,
2700 False,
2701 wxPanelItemEventHandler,
2702 (XtPointer)this);
2703 }
2704
2705 wxDeleteWindowFromTable((Widget) widget);
2706 return TRUE;
2707}
2708
2709void wxPanelItemEventHandler (Widget wid,
2710 XtPointer client_data,
2711 XEvent* event,
2712 Boolean *continueToDispatch)
2713{
2714 // Widget can be a label or the actual widget.
2715
2716 wxWindow *window = (wxWindow *)wxWidgetHashTable->Get((long)wid);
2717 if (window)
2718 {
2719 wxMouseEvent wxevent(0);
2720 if (wxTranslateMouseEvent(wxevent, window, wid, event))
2721 {
2722 window->GetEventHandler()->ProcessEvent(wxevent);
2723 }
2724 }
2725 // TODO: probably the key to allowing default behaviour
2726 // to happen.
2727 // Say we set a m_doDefault flag to FALSE at the start of this
2728 // function. Then in e.g. wxWindow::OnMouseEvent we can
2729 // call Default() which sets this flag to TRUE, indicating
2730 // that default processing can happen. Thus, behaviour can appear
2731 // to be overridden just by adding an event handler and not calling
2732 // wxWindow::OnWhatever.
2733 // ALSO, maybe we can use this instead of the current way of handling
2734 // drawing area events, to simplify things.
2735 *continueToDispatch = True;
2736}
2737
47bc1060
JS
2738void wxScrollBarCallback(Widget scrollbar, XtPointer clientData,
2739 XmScaleCallbackStruct *cbs)
2740{
2741 Widget scrolledWindow = XtParent (scrollbar);
2742 wxWindow *win = (wxWindow *) wxWidgetHashTable->Get ((long) scrolledWindow);
2743 int orientation = (int) clientData;
2744
2745 wxEventType eventType = wxEVT_NULL;
2746 switch (cbs->reason)
2747 {
2748 case XmCR_INCREMENT:
2749 {
2750 eventType = wxEVT_SCROLL_LINEDOWN;
2751 break;
2752 }
2753 case XmCR_DECREMENT:
2754 {
2755 eventType = wxEVT_SCROLL_LINEUP;
2756 break;
2757 }
2758 case XmCR_DRAG:
2759 {
2760 eventType = wxEVT_SCROLL_THUMBTRACK;
2761 break;
2762 }
2763 case XmCR_VALUE_CHANGED:
2764 {
2765 // TODO: Should this be intercepted too, or will it cause
2766 // duplicate events?
2767 eventType = wxEVT_SCROLL_THUMBTRACK;
2768 break;
2769 }
2770 case XmCR_PAGE_INCREMENT:
2771 {
2772 eventType = wxEVT_SCROLL_PAGEDOWN;
2773 break;
2774 }
2775 case XmCR_PAGE_DECREMENT:
2776 {
2777 eventType = wxEVT_SCROLL_PAGEUP;
2778 break;
2779 }
2780 case XmCR_TO_TOP:
2781 {
2782 eventType = wxEVT_SCROLL_TOP;
2783 break;
2784 }
2785 case XmCR_TO_BOTTOM:
2786 {
2787 eventType = wxEVT_SCROLL_BOTTOM;
2788 break;
2789 }
2790 default:
2791 {
2792 // Should never get here
2793 wxFAIL_MSG("Unknown scroll event.");
2794 break;
2795 }
2796 }
2797
2798 wxScrollEvent event(eventType, win->GetId());
2799 event.SetEventObject(win);
2800 event.SetPosition(cbs->value);
2801 event.SetOrientation( (orientation == XmHORIZONTAL) ? wxHORIZONTAL : wxVERTICAL );
2802
2803 win->GetEventHandler()->ProcessEvent(event);
2804}
2805
02e8b2f9
JS
2806bool wxTranslateMouseEvent(wxMouseEvent& wxevent, wxWindow *win, Widget widget, XEvent *xevent)
2807{
2808 switch (xevent->xany.type)
2809 {
2810 case EnterNotify:
2811 case LeaveNotify:
2812 case ButtonPress:
2813 case ButtonRelease:
2814 case MotionNotify:
2815 {
2816 wxEventType eventType = wxEVT_NULL;
2817
2818 if (xevent->xany.type == LeaveNotify)
2819 {
2820 win->m_button1Pressed = FALSE;
2821 win->m_button2Pressed = FALSE;
2822 win->m_button3Pressed = FALSE;
2823 return FALSE;
2824 }
2825 else if (xevent->xany.type == MotionNotify)
2826 {
2827 eventType = wxEVT_MOTION;
2828 }
2829 else if (xevent->xany.type == ButtonPress)
2830 {
2831 if (xevent->xbutton.button == Button1)
2832 {
2833 eventType = wxEVT_LEFT_DOWN;
2834 win->m_button1Pressed = TRUE;
2835 }
2836 else if (xevent->xbutton.button == Button2)
2837 {
2838 eventType = wxEVT_MIDDLE_DOWN;
2839 win->m_button2Pressed = TRUE;
2840 }
2841 else if (xevent->xbutton.button == Button3)
2842 {
2843 eventType = wxEVT_RIGHT_DOWN;
2844 win->m_button3Pressed = TRUE;
2845 }
2846 }
2847 else if (xevent->xany.type == ButtonRelease)
2848 {
2849 if (xevent->xbutton.button == Button1)
2850 {
2851 eventType = wxEVT_LEFT_UP;
2852 win->m_button1Pressed = FALSE;
2853 }
2854 else if (xevent->xbutton.button == Button2)
2855 {
2856 eventType = wxEVT_MIDDLE_UP;
2857 win->m_button2Pressed = FALSE;
2858 }
2859 else if (xevent->xbutton.button == Button3)
2860 {
2861 eventType = wxEVT_RIGHT_UP;
2862 win->m_button3Pressed = FALSE;
2863 }
2864 else return FALSE;
2865 }
2866 else return FALSE;
2867
2868 wxevent.m_eventHandle = (char *)xevent;
2869 wxevent.SetEventType(eventType);
2870
2871 Position x1, y1;
2872 XtVaGetValues(widget, XmNx, &x1, XmNy, &y1, NULL);
2873
2874 int x2, y2;
2875 win->GetPosition(&x2, &y2);
2876
2877 // The button x/y must be translated to wxWindows
2878 // window space - the widget might be a label or button,
2879 // within a form.
2880 int dx = 0;
2881 int dy = 0;
2882 if (widget != (Widget)win->GetMainWidget())
2883 {
2884 dx = x1;
2885 dy = y1;
2886 }
2887
2888 wxevent.m_x = xevent->xbutton.x + dx;
2889 wxevent.m_y = xevent->xbutton.y + dy;
2890
2891 wxevent.m_leftDown = ((eventType == wxEVT_LEFT_DOWN)
2892 || (event_left_is_down (xevent)
2893 && (eventType != wxEVT_LEFT_UP)));
2894 wxevent.m_middleDown = ((eventType == wxEVT_MIDDLE_DOWN)
2895 || (event_middle_is_down (xevent)
2896 && (eventType != wxEVT_MIDDLE_UP)));
2897 wxevent.m_rightDown = ((eventType == wxEVT_RIGHT_DOWN)
2898 || (event_right_is_down (xevent)
2899 && (eventType != wxEVT_RIGHT_UP)));
2900
2901 wxevent.m_shiftDown = xevent->xbutton.state & ShiftMask;
2902 wxevent.m_controlDown = xevent->xbutton.state & ControlMask;
2903 return TRUE;
2904 }
2905 }
2906 return FALSE;
2907}
2908
2909bool wxTranslateKeyEvent(wxKeyEvent& wxevent, wxWindow *win, Widget widget, XEvent *xevent)
2910{
2911 switch (xevent->xany.type)
2912 {
2913 case KeyPress:
2914 {
2915 char buf[20];
2916
2917 KeySym keySym;
2918// XComposeStatus compose;
2919// (void) XLookupString ((XKeyEvent *) xevent, buf, 20, &keySym, &compose);
2920 (void) XLookupString ((XKeyEvent *) xevent, buf, 20, &keySym, NULL);
2921 int id = wxCharCodeXToWX (keySym);
2922
2923 if (xevent->xkey.state & ShiftMask)
2924 wxevent.m_shiftDown = TRUE;
2925 if (xevent->xkey.state & ControlMask)
2926 wxevent.m_controlDown = TRUE;
2927 if (xevent->xkey.state & Mod3Mask)
2928 wxevent.m_altDown = TRUE;
2929 if (xevent->xkey.state & Mod1Mask)
2930 wxevent.m_metaDown = TRUE;
2931 wxevent.SetEventObject(win);
2932 wxevent.m_keyCode = id;
2933 wxevent.SetTimestamp(xevent->xkey.time);
2934
2935 wxevent.m_x = xevent->xbutton.x;
2936 wxevent.m_y = xevent->xbutton.y;
2937
2938 if (id > -1)
2939 return TRUE;
2940 else
2941 return FALSE;
2942 break;
2943 }
2944 default:
2945 break;
2946 }
2947 return FALSE;
2948}
2949
02e8b2f9 2950#define YAllocColor XAllocColor
0d57be45
JS
2951XColor g_itemColors[5];
2952int wxComputeColours (Display *display, wxColour * back, wxColour * fore)
02e8b2f9
JS
2953{
2954 int result;
2955 static XmColorProc colorProc;
2956
2957 result = wxNO_COLORS;
2958
2959 if (back)
2960 {
0d57be45
JS
2961 g_itemColors[0].red = (((long) back->Red ()) << 8);
2962 g_itemColors[0].green = (((long) back->Green ()) << 8);
2963 g_itemColors[0].blue = (((long) back->Blue ()) << 8);
2964 g_itemColors[0].flags = DoRed | DoGreen | DoBlue;
02e8b2f9
JS
2965 if (colorProc == (XmColorProc) NULL)
2966 {
2967 // Get a ptr to the actual function
2968 colorProc = XmSetColorCalculation ((XmColorProc) NULL);
2969 // And set it back to motif.
2970 XmSetColorCalculation (colorProc);
2971 }
0d57be45
JS
2972 (*colorProc) (&g_itemColors[wxBACK_INDEX],
2973 &g_itemColors[wxFORE_INDEX],
2974 &g_itemColors[wxSELE_INDEX],
2975 &g_itemColors[wxTOPS_INDEX],
2976 &g_itemColors[wxBOTS_INDEX]);
02e8b2f9
JS
2977 result = wxBACK_COLORS;
2978 }
2979 if (fore)
2980 {
0d57be45
JS
2981 g_itemColors[wxFORE_INDEX].red = (((long) fore->Red ()) << 8);
2982 g_itemColors[wxFORE_INDEX].green = (((long) fore->Green ()) << 8);
2983 g_itemColors[wxFORE_INDEX].blue = (((long) fore->Blue ()) << 8);
2984 g_itemColors[wxFORE_INDEX].flags = DoRed | DoGreen | DoBlue;
02e8b2f9
JS
2985 if (result == wxNO_COLORS)
2986 result = wxFORE_COLORS;
2987 }
2988
2989 Display *dpy = display;
2990 Colormap cmap = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) dpy);
2991
2992 if (back)
2993 {
2994 /* 5 Colours to allocate */
2995 for (int i = 0; i < 5; i++)
0d57be45 2996 if (!YAllocColor (dpy, cmap, &g_itemColors[i]))
02e8b2f9
JS
2997 result = wxNO_COLORS;
2998 }
2999 else if (fore)
3000 {
3001 /* Only 1 colour to allocate */
0d57be45 3002 if (!YAllocColor (dpy, cmap, &g_itemColors[wxFORE_INDEX]))
02e8b2f9
JS
3003 result = wxNO_COLORS;
3004 }
3005
3006 return (result);
3007
3008}
3009
0d57be45
JS
3010// Changes the foreground and background colours to be derived
3011// from the current background colour.
3012// To change the foreground colour, you must call SetForegroundColour
3013// explicitly.
3014void wxWindow::ChangeBackgroundColour()
02e8b2f9 3015{
0d57be45
JS
3016 if (GetMainWidget())
3017 DoChangeBackgroundColour(GetMainWidget(), m_backgroundColour);
3018}
02e8b2f9 3019
0d57be45
JS
3020void wxWindow::ChangeForegroundColour()
3021{
3022 if (GetMainWidget())
3023 DoChangeForegroundColour(GetMainWidget(), m_foregroundColour);
3024}
02e8b2f9 3025
0d57be45
JS
3026// Change a widget's foreground and background colours.
3027
0d57be45
JS
3028void wxWindow::DoChangeForegroundColour(WXWidget widget, wxColour& foregroundColour)
3029{
3030 // When should we specify the foreground, if it's calculated
3031 // by wxComputeColours?
3032 // Solution: say we start with the default (computed) foreground colour.
3033 // If we call SetForegroundColour explicitly for a control or window,
3034 // then the foreground is changed.
3035 // Therefore SetBackgroundColour computes the foreground colour, and
3036 // SetForegroundColour changes the foreground colour. The ordering is
3037 // important.
02e8b2f9 3038
0d57be45
JS
3039 XtVaSetValues ((Widget) widget,
3040 XmNforeground, foregroundColour.AllocColour(XtDisplay((Widget) widget)),
02e8b2f9 3041 NULL);
0d57be45
JS
3042}
3043
3044void wxWindow::DoChangeBackgroundColour(WXWidget widget, wxColour& backgroundColour, bool changeArmColour)
3045{
3046 wxComputeColours (XtDisplay((Widget) widget), & backgroundColour,
3047 (wxColour*) NULL);
3048
3049 XtVaSetValues ((Widget) widget,
3050 XmNbackground, g_itemColors[wxBACK_INDEX].pixel,
3051 XmNtopShadowColor, g_itemColors[wxTOPS_INDEX].pixel,
3052 XmNbottomShadowColor, g_itemColors[wxBOTS_INDEX].pixel,
3053 XmNforeground, g_itemColors[wxFORE_INDEX].pixel,
02e8b2f9 3054 NULL);
0d57be45
JS
3055
3056 if (changeArmColour)
3057 XtVaSetValues ((Widget) widget,
3058 XmNarmColor, g_itemColors[wxSELE_INDEX].pixel,
3059 NULL);
02e8b2f9
JS
3060}
3061
0d57be45 3062void wxWindow::SetBackgroundColour(const wxColour& col)
02e8b2f9 3063{
0d57be45
JS
3064 m_backgroundColour = col;
3065 ChangeBackgroundColour();
3066}
3067
3068void wxWindow::SetForegroundColour(const wxColour& col)
3069{
3070 m_foregroundColour = col;
3071 ChangeForegroundColour();
3072}
3073
4b5f3fe6 3074void wxWindow::ChangeFont(bool keepOriginalSize)
0d57be45
JS
3075{
3076 // Note that this causes the widget to be resized back
3077 // to its original size! We therefore have to set the size
3078 // back again. TODO: a better way in Motif?
0d57be45
JS
3079 Widget w = (Widget) GetLabelWidget(); // Usually the main widget
3080 if (w && m_windowFont.Ok())
3081 {
3082 int width, height, width1, height1;
3083 GetSize(& width, & height);
3084
3085 XtVaSetValues (w,
3086 XmNfontList, (XmFontList) m_windowFont.GetFontList(1.0, XtDisplay(w)),
02e8b2f9 3087 NULL);
0d57be45
JS
3088
3089 GetSize(& width1, & height1);
4b5f3fe6 3090 if (keepOriginalSize && (width != width1 || height != height1))
0d57be45
JS
3091 {
3092 SetSize(-1, -1, width, height);
3093 }
3094 }
02e8b2f9 3095}
0d57be45
JS
3096
3097void wxWindow::SetFont(const wxFont& font)
3098{
3099 m_windowFont = font;
3100 ChangeFont();
3101}
3102
55acd85e
JS
3103void wxWindow::ClearUpdateRects()
3104{
3105 wxNode* node = m_updateRects.First();
3106 while (node)
3107 {
3108 wxRect* rect = (wxRect*) node->Data();
3109 delete rect;
3110 node = node->Next();
3111 }
3112 m_updateRects.Clear();
3113}