]> git.saurik.com Git - wxWidgets.git/blame - src/motif/window.cpp
DnD
[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
111
50414e24 112 /// Motif-specific
4bb6408c
JS
113 m_mainWidget = (WXWidget) 0;
114 m_button1Pressed = FALSE;
115 m_button2Pressed = FALSE;
116 m_button3Pressed = FALSE;
117 m_winCaptured = FALSE;
118 m_isShown = TRUE;
50414e24
JS
119 m_hScrollBar = (WXWidget) 0;
120 m_vScrollBar = (WXWidget) 0;
121 m_borderWidget = (WXWidget) 0;
122 m_scrolledWindow = (WXWidget) 0;
123 m_drawingArea = (WXWidget) 0;
124 m_hScroll = FALSE;
125 m_vScroll = FALSE;
50414e24
JS
126 m_backingPixmap = (WXPixmap) 0;
127 m_pixmapWidth = 0;
128 m_pixmapHeight = 0;
129 m_pixmapOffsetX = 0;
130 m_pixmapOffsetY = 0;
131 m_lastTS = 0;
132 m_lastButton = 0;
02e8b2f9 133 m_canAddEventHandler = FALSE;
47bc1060
JS
134 m_scrollPosX = 0;
135 m_scrollPosY = 0;
16c1f7f3 136 m_paintRegion = (WXRegion) 0;
4bb6408c
JS
137}
138
139// Destructor
140wxWindow::~wxWindow()
141{
f97c9854 142 //// Motif-specific
50414e24 143
f97c9854
JS
144 if (m_paintRegion)
145 XDestroyRegion ((Region) m_paintRegion);
146 m_paintRegion = (WXRegion) 0;
16c1f7f3 147
f97c9854
JS
148 if (GetMainWidget())
149 DetachWidget(GetMainWidget()); // Removes event handlers
02e8b2f9 150
f97c9854
JS
151 // If m_drawingArea, we're a fully-fledged window with drawing area, scrollbars etc. (what wxCanvas used to be)
152 if (m_drawingArea)
153 {
154 // Destroy children before destroying self
155 DestroyChildren();
50414e24 156
f97c9854
JS
157 if (m_backingPixmap)
158 XFreePixmap (XtDisplay ((Widget) GetMainWidget()), (Pixmap) m_backingPixmap);
50414e24 159
f97c9854
JS
160 Widget w = (Widget) m_drawingArea;
161 wxDeleteWindowFromTable(w);
50414e24 162
f97c9854
JS
163 if (w)
164 XtDestroyWidget(w);
165 m_mainWidget = (WXWidget) 0;
50414e24 166
f97c9854
JS
167 // Only if we're _really_ a canvas (not a dialog box/panel)
168 if (m_scrolledWindow)
169 {
170 wxDeleteWindowFromTable((Widget) m_scrolledWindow);
171 }
50414e24 172
f97c9854
JS
173 if (m_hScrollBar)
174 {
175 XtUnmanageChild ((Widget) m_hScrollBar);
176 XtDestroyWidget ((Widget) m_hScrollBar);
177 }
178 if (m_vScrollBar)
179 {
180 XtUnmanageChild ((Widget) m_vScrollBar);
181 XtDestroyWidget ((Widget) m_vScrollBar);
182 }
183 if (m_scrolledWindow)
184 {
185 XtUnmanageChild ((Widget) m_scrolledWindow);
186 XtDestroyWidget ((Widget) m_scrolledWindow);
187 }
50414e24 188
f97c9854
JS
189 if (m_borderWidget)
190 {
191 XtDestroyWidget ((Widget) m_borderWidget);
192 m_borderWidget = (WXWidget) 0;
193 }
50414e24 194 }
50414e24 195
f97c9854 196 //// Generic stuff
50414e24 197
4bb6408c
JS
198 // Have to delete constraints/sizer FIRST otherwise
199 // sizers may try to look at deleted windows as they
200 // delete themselves.
47d67540 201#if wxUSE_CONSTRAINTS
4bb6408c
JS
202 DeleteRelatedConstraints();
203 if (m_constraints)
204 {
205 // This removes any dangling pointers to this window
206 // in other windows' constraintsInvolvedIn lists.
207 UnsetConstraints(m_constraints);
208 delete m_constraints;
209 m_constraints = NULL;
210 }
211 if (m_windowSizer)
212 {
213 delete m_windowSizer;
214 m_windowSizer = NULL;
215 }
216 // If this is a child of a sizer, remove self from parent
217 if (m_sizerParent)
218 m_sizerParent->RemoveChild((wxWindow *)this);
219#endif
220
221 if (m_windowParent)
222 m_windowParent->RemoveChild(this);
223
224 DestroyChildren();
225
226 // Destroy the window
227 if (GetMainWidget())
228 {
229 wxDeleteWindowFromTable((Widget) GetMainWidget());
230 XtDestroyWidget((Widget) GetMainWidget());
231 SetMainWidget((WXWidget) NULL);
232 }
233
234 delete m_children;
235 m_children = NULL;
236
237 // Just in case the window has been Closed, but
238 // we're then deleting immediately: don't leave
239 // dangling pointers.
240 wxPendingDelete.DeleteObject(this);
241
242 if ( m_windowValidator )
243 delete m_windowValidator;
244}
245
246// Destroy the window (delayed, if a managed window)
247bool wxWindow::Destroy()
248{
249 delete this;
250 return TRUE;
251}
252
253// Constructor
254bool wxWindow::Create(wxWindow *parent, wxWindowID id,
255 const wxPoint& pos,
256 const wxSize& size,
257 long style,
258 const wxString& name)
259{
260 // Generic
261 m_windowId = 0;
262 m_windowStyle = 0;
263 m_windowParent = NULL;
264 m_windowEventHandler = this;
265 m_windowName = "";
266 m_windowCursor = *wxSTANDARD_CURSOR;
267 m_constraints = NULL;
268 m_constraintsInvolvedIn = NULL;
269 m_windowSizer = NULL;
270 m_sizerParent = NULL;
271 m_autoLayout = FALSE;
272 m_windowValidator = NULL;
47d67540 273#if wxUSE_DRAG_AND_DROP
4bb6408c
JS
274 m_pDropTarget = NULL;
275#endif
4bb6408c
JS
276 m_caretWidth = 0; m_caretHeight = 0;
277 m_caretEnabled = FALSE;
278 m_caretShown = FALSE;
279 m_minSizeX = -1;
280 m_minSizeY = -1;
281 m_maxSizeX = -1;
282 m_maxSizeY = -1;
283 m_defaultItem = NULL;
284 m_windowParent = NULL;
50414e24
JS
285
286 // Motif-specific
02e8b2f9 287 m_canAddEventHandler = FALSE;
50414e24
JS
288 m_mainWidget = (WXWidget) 0;
289 m_button1Pressed = FALSE;
290 m_button2Pressed = FALSE;
291 m_button3Pressed = FALSE;
292 m_winCaptured = FALSE;
293 m_isShown = TRUE;
294 m_hScrollBar = (WXWidget) 0;
295 m_vScrollBar = (WXWidget) 0;
296 m_borderWidget = (WXWidget) 0;
297 m_scrolledWindow = (WXWidget) 0;
298 m_drawingArea = (WXWidget) 0;
299 m_hScroll = FALSE;
300 m_vScroll = FALSE;
50414e24
JS
301 m_backingPixmap = (WXPixmap) 0;
302 m_pixmapWidth = 0;
303 m_pixmapHeight = 0;
304 m_pixmapOffsetX = 0;
305 m_pixmapOffsetY = 0;
47bc1060
JS
306 m_scrollPosX = 0;
307 m_scrollPosY = 0;
16c1f7f3 308 m_paintRegion = (WXRegion) 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) ;
1930}
1931
1932// Find a window by id or name
1933wxWindow *wxWindow::FindWindow(long id)
1934{
1935 if ( GetId() == id)
1936 return this;
1937
1938 wxNode *node = GetChildren()->First();
1939 while ( node )
1940 {
1941 wxWindow *child = (wxWindow *)node->Data();
1942 wxWindow *found = child->FindWindow(id);
1943 if ( found )
1944 return found;
1945 node = node->Next();
1946 }
1947 return NULL;
1948}
1949
1950wxWindow *wxWindow::FindWindow(const wxString& name)
1951{
1952 if ( GetName() == name)
1953 return this;
1954
1955 wxNode *node = GetChildren()->First();
1956 while ( node )
1957 {
1958 wxWindow *child = (wxWindow *)node->Data();
1959 wxWindow *found = child->FindWindow(name);
1960 if ( found )
1961 return found;
1962 node = node->Next();
1963 }
1964 return NULL;
1965}
1966
1967void wxWindow::OnIdle(wxIdleEvent& event)
1968{
4bb6408c
JS
1969 // This calls the UI-update mechanism (querying windows for
1970 // menu/toolbar/control state information)
0d57be45 1971 UpdateWindowUI();
4bb6408c
JS
1972}
1973
1974// Raise the window to the top of the Z order
1975void wxWindow::Raise()
1976{
02e8b2f9
JS
1977 Window window = XtWindow((Widget) GetTopWidget());
1978 XRaiseWindow(XtDisplay((Widget) GetTopWidget()), window);
4bb6408c
JS
1979}
1980
1981// Lower the window to the bottom of the Z order
1982void wxWindow::Lower()
1983{
02e8b2f9
JS
1984 Window window = XtWindow((Widget) GetTopWidget());
1985 XLowerWindow(XtDisplay((Widget) GetTopWidget()), window);
4bb6408c
JS
1986}
1987
1988bool wxWindow::AcceptsFocus() const
1989{
1990 return IsShown() && IsEnabled();
1991}
1992
1993// Update region access
1994wxRegion wxWindow::GetUpdateRegion() const
1995{
1996 return m_updateRegion;
1997}
1998
1999bool wxWindow::IsExposed(int x, int y, int w, int h) const
2000{
2001 return (m_updateRegion.Contains(x, y, w, h) != wxOutRegion);
2002}
2003
2004bool wxWindow::IsExposed(const wxPoint& pt) const
2005{
2006 return (m_updateRegion.Contains(pt) != wxOutRegion);
2007}
2008
2009bool wxWindow::IsExposed(const wxRect& rect) const
2010{
2011 return (m_updateRegion.Contains(rect) != wxOutRegion);
2012}
2013
2014/*
2015 * Allocates control IDs
2016 */
2017
2018int wxWindow::NewControlId()
2019{
2020 static int s_controlId = 0;
2021 s_controlId ++;
2022 return s_controlId;
2023}
2024
2025void wxWindow::SetAcceleratorTable(const wxAcceleratorTable& accel)
2026{
2027 m_acceleratorTable = accel;
2028}
2029
2030// All widgets should have this as their resize proc.
2031// OnSize sent to wxWindow via client data.
2032void wxWidgetResizeProc(Widget w, XConfigureEvent *event, String args[], int *num_args)
2033{
2034 wxWindow *win = (wxWindow *)wxWidgetHashTable->Get((long)w);
2035 if (!win)
2036 return;
2037
2038 if (win->PreResize())
2039 {
2040 int width, height;
2041 win->GetSize(&width, &height);
2042 wxSizeEvent sizeEvent(wxSize(width, height), win->GetId());
2043 sizeEvent.SetEventObject(win);
2044 win->GetEventHandler()->ProcessEvent(sizeEvent);
2045 }
2046}
2047
2048bool wxAddWindowToTable(Widget w, wxWindow *win)
2049{
2050 wxWindow *oldItem = NULL;
2051#if DEBUG
2052// printf("Adding widget %ld, name = %s\n", w, win->GetClassInfo()->GetClassName());
2053#endif
2054 if ((oldItem = (wxWindow *)wxWidgetHashTable->Get ((long) w)))
2055 {
2056 char buf[300];
2057 sprintf(buf, "Widget table clash: new widget is %ld, %s", (long)w, win->GetClassInfo()->GetClassName());
2058 wxError (buf);
2059 fflush(stderr);
2060 sprintf(buf, "Old widget was %s", oldItem->GetClassInfo()->GetClassName());
2061 wxError (buf);
2062 return FALSE;
2063 }
2064
2065 wxWidgetHashTable->Put ((long) w, win);
2066 return TRUE;
2067}
2068
2069wxWindow *wxGetWindowFromTable(Widget w)
2070{
2071 return (wxWindow *)wxWidgetHashTable->Get ((long) w);
2072}
2073
2074void wxDeleteWindowFromTable(Widget w)
2075{
4bb6408c
JS
2076 wxWidgetHashTable->Delete((long)w);
2077}
2078
2079// Get the underlying X window and display
2080WXWindow wxWindow::GetXWindow() const
2081{
50414e24 2082 return (WXWindow) XtWindow((Widget) GetMainWidget());
4bb6408c
JS
2083}
2084
2085WXDisplay *wxWindow::GetXDisplay() const
2086{
50414e24 2087 return (WXDisplay*) XtDisplay((Widget) GetMainWidget());
4bb6408c
JS
2088}
2089
2090WXWidget wxWindow::GetMainWidget() const
2091{
50414e24
JS
2092 if (m_drawingArea)
2093 return m_drawingArea;
2094 else
2095 return m_mainWidget;
2096}
2097
2098WXWidget wxWindow::GetClientWidget() const
2099{
2100 if (m_drawingArea != (WXWidget) 0)
2101 return m_drawingArea;
2102 else
02e8b2f9
JS
2103 return GetMainWidget();
2104}
2105
2106WXWidget wxWindow::GetTopWidget() const
2107{
2108 return GetMainWidget();
4bb6408c
JS
2109}
2110
50414e24
JS
2111void wxCanvasRepaintProc (Widget drawingArea, XtPointer clientData,
2112 XmDrawingAreaCallbackStruct * cbs)
2113{
2114 if (!wxWidgetHashTable->Get ((long) (Widget) drawingArea))
2115 return;
2116
2117 XEvent * event = cbs->event;
2118 wxWindow * canvas = (wxWindow *) clientData;
2119 Display * display = (Display *) canvas->GetXDisplay();
2120 // GC gc = (GC) canvas->GetDC()->gc;
2121
2122 switch (event->type)
2123 {
2124 case Expose:
2125 {
2126 /* TODO
2127 wxCanvasDC* canvasDC = canvas->GetDC();
2128 if (canvasDC)
2129 {
2130 if (canvasDC->onpaint_reg)
2131 XDestroyRegion(canvasDC->onpaint_reg);
2132 canvasDC->onpaint_reg = XCreateRegion();
2133
2134 }
2135 */
2136
2137 int n = canvas->m_updateRects.Number();
2138 XRectangle* xrects = new XRectangle[n];
2139 int i;
2140 for (i = 0; i < canvas->m_updateRects.Number(); i++)
2141 {
2142 wxRect* rect = (wxRect*) canvas->m_updateRects.Nth(i)->Data();
2143 xrects[i].x = rect->x;
2144 xrects[i].y = rect->y;
2145 xrects[i].width = rect->width;
2146 xrects[i].height = rect->height;
2147 /* TODO (?) Actually ignore it I think.
2148 if (canvasDC)
2149 XUnionRectWithRegion(&(xrects[i]), canvasDC->onpaint_reg,
2150 canvasDC->onpaint_reg);
2151 */
2152 }
2153 /* TODO must clip the area being repainted. So we need a gc.
2154 * Alternatively, wxPaintDC must do the clipping
2155 * when it's created.
2156 XSetClipRectangles(display, gc, 0, 0, xrects, n, Unsorted);
2157 */
2158
2159 canvas->DoPaint() ; // xrects, n);
2160 delete[] xrects;
2161
2162 canvas->m_updateRects.Clear();
2163
2164 /*
2165 if (canvasDC)
2166 {
2167 XDestroyRegion(canvasDC->onpaint_reg);
2168 canvasDC->onpaint_reg = NULL;
2169 }
2170
2171 XGCValues gc_val;
2172 gc_val.clip_mask = None;
2173 XChangeGC(display, gc, GCClipMask, &gc_val);
2174 */
2175
2176 break;
2177 }
2178 default:
2179 {
2180 cout << "\n\nNew Event ! is = " << event -> type << "\n";
2181 break;
2182 }
2183 }
2184}
2185
2186// Unable to deal with Enter/Leave without a separate EventHandler (Motif 1.1.4)
2187void
2188wxCanvasEnterLeave (Widget drawingArea, XtPointer clientData, XCrossingEvent * event)
2189{
2190 XmDrawingAreaCallbackStruct cbs;
2191 XEvent ev;
2192
2193 //if (event->mode!=NotifyNormal)
2194 // return ;
2195
2196// ev = *((XEvent *) event); // Causes Purify error (copying too many bytes)
2197 ((XCrossingEvent &) ev) = *event;
2198
2199 cbs.reason = XmCR_INPUT;
2200 cbs.event = &ev;
2201
2202 wxCanvasInputEvent (drawingArea, (XtPointer) NULL, &cbs);
2203}
2204
2205// Fix to make it work under Motif 1.0 (!)
2206void wxCanvasMotionEvent (Widget drawingArea, XButtonEvent * event)
2207{
2208#if XmVersion<=1000
4bb6408c 2209
50414e24
JS
2210 XmDrawingAreaCallbackStruct cbs;
2211 XEvent ev;
2212
2213 //ev.xbutton = *event;
2214 ev = *((XEvent *) event);
2215 cbs.reason = XmCR_INPUT;
2216 cbs.event = &ev;
2217
2218 wxCanvasInputEvent (drawingArea, (XtPointer) NULL, &cbs);
2219#endif
2220}
2221
2222void wxCanvasInputEvent (Widget drawingArea, XtPointer data, XmDrawingAreaCallbackStruct * cbs)
2223{
2224 wxWindow *canvas = (wxWindow *) wxWidgetHashTable->Get ((long) (Widget) drawingArea);
2225 XEvent local_event;
2226
2227 if (canvas==NULL)
2228 return ;
2229
2230 if (cbs->reason != XmCR_INPUT)
2231 return;
2232
2233 local_event = *(cbs->event); // We must keep a copy!
2234
2235 switch (local_event.xany.type)
2236 {
2237 case EnterNotify:
2238 case LeaveNotify:
2239 case ButtonPress:
2240 case ButtonRelease:
2241 case MotionNotify:
2242 {
2243 wxEventType eventType = wxEVT_NULL;
2244
2245 if (local_event.xany.type == EnterNotify)
2246 {
2247 //if (local_event.xcrossing.mode!=NotifyNormal)
2248 // return ; // Ignore grab events
2249 eventType = wxEVT_ENTER_WINDOW;
2250// canvas->GetEventHandler()->OnSetFocus();
2251 }
2252 else if (local_event.xany.type == LeaveNotify)
2253 {
2254 //if (local_event.xcrossing.mode!=NotifyNormal)
2255 // return ; // Ignore grab events
2256 eventType = wxEVT_LEAVE_WINDOW;
2257// canvas->GetEventHandler()->OnKillFocus();
2258 }
2259 else if (local_event.xany.type == MotionNotify)
2260 {
2261 eventType = wxEVT_MOTION;
2262 if (local_event.xmotion.is_hint == NotifyHint)
2263 {
2264 Window root, child;
2265 Display *dpy = XtDisplay (drawingArea);
2266
2267 XQueryPointer (dpy, XtWindow (drawingArea),
2268 &root, &child,
2269 &local_event.xmotion.x_root,
2270 &local_event.xmotion.y_root,
2271 &local_event.xmotion.x,
2272 &local_event.xmotion.y,
2273 &local_event.xmotion.state);
2274 }
2275 else
2276 {
2277 }
2278 }
2279
2280 else if (local_event.xany.type == ButtonPress)
2281 {
2282 if (local_event.xbutton.button == Button1)
2283 {
2284 eventType = wxEVT_LEFT_DOWN;
2285 canvas->m_button1Pressed = TRUE;
2286 }
2287 else if (local_event.xbutton.button == Button2)
2288 {
2289 eventType = wxEVT_MIDDLE_DOWN;
2290 canvas->m_button2Pressed = TRUE;
2291 }
2292 else if (local_event.xbutton.button == Button3)
2293 {
2294 eventType = wxEVT_RIGHT_DOWN;
2295 canvas->m_button3Pressed = TRUE;
2296 }
2297 }
2298 else if (local_event.xany.type == ButtonRelease)
2299 {
2300 if (local_event.xbutton.button == Button1)
2301 {
2302 eventType = wxEVT_LEFT_UP;
2303 canvas->m_button1Pressed = FALSE;
2304 }
2305 else if (local_event.xbutton.button == Button2)
2306 {
2307 eventType = wxEVT_MIDDLE_UP;
2308 canvas->m_button2Pressed = FALSE;
2309 }
2310 else if (local_event.xbutton.button == Button3)
2311 {
2312 eventType = wxEVT_RIGHT_UP;
2313 canvas->m_button3Pressed = FALSE;
2314 }
2315 }
2316
2317 wxMouseEvent wxevent (eventType);
2318 wxevent.m_eventHandle = (char *) &local_event;
2319
2320 wxevent.m_leftDown = ((eventType == wxEVT_LEFT_DOWN)
2321 || (event_left_is_down (&local_event)
2322 && (eventType != wxEVT_LEFT_UP)));
2323 wxevent.m_middleDown = ((eventType == wxEVT_MIDDLE_DOWN)
2324 || (event_middle_is_down (&local_event)
2325 && (eventType != wxEVT_MIDDLE_UP)));
2326 wxevent.m_rightDown = ((eventType == wxEVT_RIGHT_DOWN)
2327 || (event_right_is_down (&local_event)
2328 && (eventType != wxEVT_RIGHT_UP)));
2329
2330 wxevent.m_shiftDown = local_event.xbutton.state & ShiftMask;
2331 wxevent.m_controlDown = local_event.xbutton.state & ControlMask;
2332 wxevent.m_altDown = local_event.xbutton.state & Mod3Mask;
2333 wxevent.m_metaDown = local_event.xbutton.state & Mod1Mask;
2334 wxevent.SetTimestamp(local_event.xbutton.time);
2335
2336 // Now check if we need to translate this event into a double click
2337 if (TRUE) // canvas->doubleClickAllowed)
2338 {
2339 if (wxevent.ButtonDown())
2340 {
2341 long dclickTime = XtGetMultiClickTime((Display*) wxGetDisplay()) ;
2342
2343 // get button and time-stamp
2344 int button = 0;
2345 if (wxevent.LeftDown()) button = 1;
2346 else if (wxevent.MiddleDown()) button = 2;
2347 else if (wxevent.RightDown()) button = 3;
2348 long ts = wxevent.GetTimestamp();
2349 // check, if single or double click
2350 if (canvas->m_lastButton && canvas->m_lastButton==button && (ts - canvas->m_lastTS) < dclickTime)
2351 {
2352 // I have a dclick
2353 canvas->m_lastButton = 0;
2354 switch ( eventType )
2355 {
2356 case wxEVT_LEFT_DOWN:
2357 wxevent.SetEventType(wxEVT_LEFT_DCLICK);
2358 break;
2359 case wxEVT_MIDDLE_DOWN:
2360 wxevent.SetEventType(wxEVT_MIDDLE_DCLICK);
2361 break;
2362 case wxEVT_RIGHT_DOWN:
2363 wxevent.SetEventType(wxEVT_RIGHT_DCLICK);
2364 break;
2365
2366 default :
2367 break;
2368 }
2369
2370 }
2371 else
2372 {
2373 // not fast enough or different button
2374 canvas->m_lastTS = ts;
2375 canvas->m_lastButton = button;
2376 }
2377 }
2378 }
2379
2380 wxevent.SetId(canvas->GetId());
2381 wxevent.SetEventObject(canvas);
a4294b78
JS
2382 wxevent.m_x = local_event.xbutton.x;
2383 wxevent.m_y = local_event.xbutton.y;
50414e24
JS
2384 canvas->GetEventHandler()->ProcessEvent (wxevent);
2385 /*
2386 if (eventType == wxEVT_ENTER_WINDOW ||
2387 eventType == wxEVT_LEAVE_WINDOW ||
2388 eventType == wxEVT_MOTION
2389 )
2390 return;
2391 */
2392 break;
2393 }
2394 case KeyPress:
2395 {
2396 KeySym keySym;
2397// XComposeStatus compose;
2398// (void) XLookupString ((XKeyEvent *) & local_event, wxBuffer, 20, &keySym, &compose);
2399 (void) XLookupString ((XKeyEvent *) & local_event, wxBuffer, 20, &keySym, NULL);
2400 int id = wxCharCodeXToWX (keySym);
2401
2402 wxKeyEvent event (wxEVT_CHAR);
2403
2404 if (local_event.xkey.state & ShiftMask)
2405 event.m_shiftDown = TRUE;
2406 if (local_event.xkey.state & ControlMask)
2407 event.m_controlDown = TRUE;
2408 if (local_event.xkey.state & Mod3Mask)
2409 event.m_altDown = TRUE;
2410 if (local_event.xkey.state & Mod1Mask)
2411 event.m_metaDown = TRUE;
2412 event.SetEventObject(canvas);
2413 event.m_keyCode = id;
2414 event.SetTimestamp(local_event.xkey.time);
2415
2416 if (id > -1)
2417 {
2418 // Implement wxFrame::OnCharHook by checking ancestor.
2419 wxWindow *parent = canvas->GetParent();
2420 while (parent && !parent->IsKindOf(CLASSINFO(wxFrame)))
2421 parent = parent->GetParent();
2422
2423 if (parent)
2424 {
2425 event.SetEventType(wxEVT_CHAR_HOOK);
2426 if (parent->GetEventHandler()->ProcessEvent(event))
2427 return;
2428 event.SetEventType(wxEVT_CHAR);
2429 }
2430
2431 canvas->GetEventHandler()->ProcessEvent (event);
2432 }
2433 break;
2434 }
2435 case FocusIn:
2436 {
2437 if (local_event.xfocus.detail != NotifyPointer)
2438 {
2439 wxFocusEvent event(wxEVT_SET_FOCUS, canvas->GetId());
2440 event.SetEventObject(canvas);
2441 canvas->GetEventHandler()->ProcessEvent(event);
2442 }
2443 break;
2444 }
2445 case FocusOut:
2446 {
2447 if (local_event.xfocus.detail != NotifyPointer)
2448 {
2449 wxFocusEvent event(wxEVT_KILL_FOCUS, canvas->GetId());
2450 event.SetEventObject(canvas);
2451 canvas->GetEventHandler()->ProcessEvent(event);
2452 }
2453 break;
2454 }
2455 default:
2456 break;
2457 }
2458}
2459
2460void wxWindow::DoPaint()
2461{
2462 //TODO : make a temporary gc so we can do the XCopyArea below
2463 if (0) // m_backingPixmap)
2464 {
2465 /*
2466 Widget drawingArea = (Widget) m_drawingArea;
2467 // int orig = GetDC()->GetLogicalFunction();
2468 // GetDC()->SetLogicalFunction (wxCOPY);
2469
2470 // TODO: it may not be necessary to store m_pixmapOffsetX/Y; we
2471 // should be able to calculate them.
2472 XCopyArea (XtDisplay (drawingArea), m_backingPixmap, XtWindow (drawingArea), GetDC ()->gc,
2473 m_pixmapOffsetX, m_pixmapOffsetY,
2474 m_pixmapWidth, m_pixmapHeight,
2475 0, 0);
2476
2477 // GetDC()->SetLogicalFunction (orig);
2478 */
2479 }
2480 else
2481 {
2482 wxPaintEvent event(GetId());
2483 event.SetEventObject(this);
2484 GetEventHandler()->ProcessEvent(event);
2485 }
2486}
2487
2488// SetSize, but as per old wxCanvas (with drawing widget etc.)
2489void wxWindow::CanvasSetSize (int x, int y, int w, int h, int sizeFlags)
2490{
2491 Widget drawingArea = (Widget) m_drawingArea;
2492 bool managed = XtIsManaged(m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow);
2493
2494 if (managed)
2495 XtUnmanageChild (m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow);
2496 XtVaSetValues((Widget) m_drawingArea, XmNresizePolicy, XmRESIZE_ANY, NULL);
2497
a4294b78
JS
2498 int xx = x; int yy = y;
2499 AdjustForParentClientOrigin(xx, yy, sizeFlags);
2500
50414e24
JS
2501 if (x > -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
2502 {
2503 XtVaSetValues (m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow,
a4294b78 2504 XmNx, xx, NULL);
50414e24
JS
2505 }
2506
2507 if (y > -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
2508 {
2509 XtVaSetValues (m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow,
a4294b78 2510 XmNy, yy, NULL);
50414e24
JS
2511 }
2512
2513 if (w > -1)
2514 {
2515 if (m_borderWidget)
2516 {
2517 XtVaSetValues ((Widget) m_borderWidget, XmNwidth, w, NULL);
2518 short thick, margin;
2519 XtVaGetValues ((Widget) m_borderWidget,
2520 XmNshadowThickness, &thick,
2521 XmNmarginWidth, &margin,
2522 NULL);
2523 w -= 2 * (thick + margin);
2524 }
2525
2526 XtVaSetValues ((Widget) m_scrolledWindow, XmNwidth, w, NULL);
2527
2528 Dimension spacing;
2529 Widget sbar;
2530 XtVaGetValues ((Widget) m_scrolledWindow,
2531 XmNspacing, &spacing,
2532 XmNverticalScrollBar, &sbar,
2533 NULL);
2534 Dimension wsbar;
2535 if (sbar)
2536 XtVaGetValues (sbar, XmNwidth, &wsbar, NULL);
2537 else
2538 wsbar = 0;
2539
2540 w -= (spacing + wsbar);
2541
2542 XtVaSetValues ((Widget) m_drawingArea, XmNwidth, w, NULL);
2543 }
2544 if (h > -1)
2545 {
2546 if (m_borderWidget)
2547 {
2548 XtVaSetValues ((Widget) m_borderWidget, XmNheight, h, NULL);
2549 short thick, margin;
2550 XtVaGetValues ((Widget) m_borderWidget,
2551 XmNshadowThickness, &thick,
2552 XmNmarginHeight, &margin,
2553 NULL);
2554 h -= 2 * (thick + margin);
2555 }
2556
2557 XtVaSetValues ((Widget) m_scrolledWindow, XmNheight, h, NULL);
2558
2559 Dimension spacing;
2560 Widget sbar;
2561 XtVaGetValues ((Widget) m_scrolledWindow,
2562 XmNspacing, &spacing,
2563 XmNhorizontalScrollBar, &sbar,
2564 NULL);
2565 Dimension wsbar;
2566 if (sbar)
2567 XtVaGetValues (sbar, XmNheight, &wsbar, NULL);
2568 else
2569 wsbar = 0;
2570
2571 h -= (spacing + wsbar);
2572
2573 XtVaSetValues ((Widget) m_drawingArea, XmNheight, h, NULL);
2574 }
2575 if (managed)
2576 XtManageChild (m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow);
2577 XtVaSetValues((Widget) m_drawingArea, XmNresizePolicy, XmRESIZE_NONE, NULL);
2578
2579 int ww, hh;
2580 GetClientSize (&ww, &hh);
2581 wxSizeEvent sizeEvent(wxSize(ww, hh), GetId());
2582 sizeEvent.SetEventObject(this);
2583
2584 GetEventHandler()->ProcessEvent(sizeEvent);
2585}
2586
2587void wxWindow::CanvasSetClientSize (int w, int h)
2588{
2589 Widget drawingArea = (Widget) m_drawingArea;
2590
2591 XtVaSetValues((Widget) m_drawingArea, XmNresizePolicy, XmRESIZE_ANY, NULL);
2592
2593 if (w > -1)
2594 XtVaSetValues ((Widget) m_drawingArea, XmNwidth, w, NULL);
2595 if (h > -1)
2596 XtVaSetValues ((Widget) m_drawingArea, XmNheight, h, NULL);
2597 /* TODO: is this necessary?
2598 allowRepainting = FALSE;
2599
2600 XSync (XtDisplay (drawingArea), FALSE);
2601 XEvent event;
2602 while (XtAppPending (wxTheApp->appContext))
2603 {
2604 XFlush (XtDisplay (drawingArea));
2605 XtAppNextEvent (wxTheApp->appContext, &event);
2606 XtDispatchEvent (&event);
2607 }
2608 */
2609
2610 XtVaSetValues((Widget) m_drawingArea, XmNresizePolicy, XmRESIZE_NONE, NULL);
2611
2612 /* TODO
2613 allowRepainting = TRUE;
2614 DoRefresh ();
2615 */
2616
2617 wxSizeEvent sizeEvent(wxSize(w, h), GetId());
2618 sizeEvent.SetEventObject(this);
2619
2620 GetEventHandler()->ProcessEvent(sizeEvent);
2621}
2622
2623void wxWindow::CanvasGetClientSize (int *w, int *h) const
2624{
2625 // Must return the same thing that was set via SetClientSize
2626 Dimension xx, yy;
2627 XtVaGetValues ((Widget) m_drawingArea, XmNwidth, &xx, XmNheight, &yy, NULL);
2628 *w = xx;
2629 *h = yy;
2630}
2631
2632void wxWindow::CanvasGetSize (int *w, int *h) const
2633{
2634 Dimension xx, yy;
2635 if ((Widget) m_borderWidget)
2636 XtVaGetValues ((Widget) m_borderWidget, XmNwidth, &xx, XmNheight, &yy, NULL);
2637 else if ((Widget) m_scrolledWindow)
2638 XtVaGetValues ((Widget) m_scrolledWindow, XmNwidth, &xx, XmNheight, &yy, NULL);
2639 else
2640 XtVaGetValues ((Widget) m_drawingArea, XmNwidth, &xx, XmNheight, &yy, NULL);
2641
2642 *w = xx;
2643 *h = yy;
2644}
2645
2646void wxWindow::CanvasGetPosition (int *x, int *y) const
2647{
a4294b78
JS
2648 Position xx, yy;
2649 XtVaGetValues (m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow, XmNx, &xx, XmNy, &yy, NULL);
2650
2651 // We may be faking the client origin.
2652 // So a window that's really at (0, 30) may appear
2653 // (to wxWin apps) to be at (0, 0).
2654 if (GetParent())
2655 {
2656 wxPoint pt(GetParent()->GetClientAreaOrigin());
2657 xx -= pt.x;
2658 yy -= pt.y;
2659 }
2660
2661 *x = xx;
2662 *y = yy;
50414e24 2663}
02e8b2f9
JS
2664
2665// Add to hash table, add event handler
2666bool wxWindow::AttachWidget (wxWindow* parent, WXWidget mainWidget,
2667 WXWidget formWidget, int x, int y, int width, int height)
2668{
2669 wxAddWindowToTable((Widget) mainWidget, this);
2670 if (CanAddEventHandler())
2671 {
2672 XtAddEventHandler((Widget) mainWidget,
2673 ButtonPressMask | ButtonReleaseMask | PointerMotionMask, // | KeyPressMask,
2674 False,
2675 wxPanelItemEventHandler,
2676 (XtPointer) this);
2677 }
2678
2679 if (!formWidget)
2680 {
2681 XtTranslations ptr;
2682 XtOverrideTranslations ((Widget) mainWidget,
2683 ptr = XtParseTranslationTable ("<Configure>: resize()"));
2684 XtFree ((char *) ptr);
2685 }
2686
2687 // Some widgets have a parent form widget, e.g. wxRadioBox
2688 if (formWidget)
2689 {
2690 if (!wxAddWindowToTable((Widget) formWidget, this))
2691 return FALSE;
2692
2693 XtTranslations ptr;
2694 XtOverrideTranslations ((Widget) formWidget,
2695 ptr = XtParseTranslationTable ("<Configure>: resize()"));
2696 XtFree ((char *) ptr);
2697 }
2698
2699 if (x == -1)
2700 x = 0;
2701 if (y == -1)
2702 y = 0;
2703 SetSize (x, y, width, height);
2704
2705 return TRUE;
2706}
2707
2708// Remove event handler, remove from hash table
2709bool wxWindow::DetachWidget(WXWidget widget)
2710{
2711 if (CanAddEventHandler())
2712 {
2713 XtRemoveEventHandler((Widget) widget,
2714 ButtonPressMask | ButtonReleaseMask | PointerMotionMask, // | KeyPressMask,
2715 False,
2716 wxPanelItemEventHandler,
2717 (XtPointer)this);
2718 }
2719
2720 wxDeleteWindowFromTable((Widget) widget);
2721 return TRUE;
2722}
2723
2724void wxPanelItemEventHandler (Widget wid,
2725 XtPointer client_data,
2726 XEvent* event,
2727 Boolean *continueToDispatch)
2728{
2729 // Widget can be a label or the actual widget.
2730
2731 wxWindow *window = (wxWindow *)wxWidgetHashTable->Get((long)wid);
2732 if (window)
2733 {
2734 wxMouseEvent wxevent(0);
2735 if (wxTranslateMouseEvent(wxevent, window, wid, event))
2736 {
2737 window->GetEventHandler()->ProcessEvent(wxevent);
2738 }
2739 }
2740 // TODO: probably the key to allowing default behaviour
2741 // to happen.
2742 // Say we set a m_doDefault flag to FALSE at the start of this
2743 // function. Then in e.g. wxWindow::OnMouseEvent we can
2744 // call Default() which sets this flag to TRUE, indicating
2745 // that default processing can happen. Thus, behaviour can appear
2746 // to be overridden just by adding an event handler and not calling
2747 // wxWindow::OnWhatever.
2748 // ALSO, maybe we can use this instead of the current way of handling
2749 // drawing area events, to simplify things.
2750 *continueToDispatch = True;
2751}
2752
47bc1060
JS
2753void wxScrollBarCallback(Widget scrollbar, XtPointer clientData,
2754 XmScaleCallbackStruct *cbs)
2755{
2756 Widget scrolledWindow = XtParent (scrollbar);
2757 wxWindow *win = (wxWindow *) wxWidgetHashTable->Get ((long) scrolledWindow);
2758 int orientation = (int) clientData;
2759
2760 wxEventType eventType = wxEVT_NULL;
2761 switch (cbs->reason)
2762 {
2763 case XmCR_INCREMENT:
2764 {
2765 eventType = wxEVT_SCROLL_LINEDOWN;
2766 break;
2767 }
2768 case XmCR_DECREMENT:
2769 {
2770 eventType = wxEVT_SCROLL_LINEUP;
2771 break;
2772 }
2773 case XmCR_DRAG:
2774 {
2775 eventType = wxEVT_SCROLL_THUMBTRACK;
2776 break;
2777 }
2778 case XmCR_VALUE_CHANGED:
2779 {
2780 // TODO: Should this be intercepted too, or will it cause
2781 // duplicate events?
2782 eventType = wxEVT_SCROLL_THUMBTRACK;
2783 break;
2784 }
2785 case XmCR_PAGE_INCREMENT:
2786 {
2787 eventType = wxEVT_SCROLL_PAGEDOWN;
2788 break;
2789 }
2790 case XmCR_PAGE_DECREMENT:
2791 {
2792 eventType = wxEVT_SCROLL_PAGEUP;
2793 break;
2794 }
2795 case XmCR_TO_TOP:
2796 {
2797 eventType = wxEVT_SCROLL_TOP;
2798 break;
2799 }
2800 case XmCR_TO_BOTTOM:
2801 {
2802 eventType = wxEVT_SCROLL_BOTTOM;
2803 break;
2804 }
2805 default:
2806 {
2807 // Should never get here
2808 wxFAIL_MSG("Unknown scroll event.");
2809 break;
2810 }
2811 }
2812
2813 wxScrollEvent event(eventType, win->GetId());
2814 event.SetEventObject(win);
2815 event.SetPosition(cbs->value);
2816 event.SetOrientation( (orientation == XmHORIZONTAL) ? wxHORIZONTAL : wxVERTICAL );
2817
2818 win->GetEventHandler()->ProcessEvent(event);
2819}
2820
02e8b2f9
JS
2821bool wxTranslateMouseEvent(wxMouseEvent& wxevent, wxWindow *win, Widget widget, XEvent *xevent)
2822{
2823 switch (xevent->xany.type)
2824 {
2825 case EnterNotify:
2826 case LeaveNotify:
2827 case ButtonPress:
2828 case ButtonRelease:
2829 case MotionNotify:
2830 {
2831 wxEventType eventType = wxEVT_NULL;
2832
2833 if (xevent->xany.type == LeaveNotify)
2834 {
2835 win->m_button1Pressed = FALSE;
2836 win->m_button2Pressed = FALSE;
2837 win->m_button3Pressed = FALSE;
2838 return FALSE;
2839 }
2840 else if (xevent->xany.type == MotionNotify)
2841 {
2842 eventType = wxEVT_MOTION;
2843 }
2844 else if (xevent->xany.type == ButtonPress)
2845 {
2846 if (xevent->xbutton.button == Button1)
2847 {
2848 eventType = wxEVT_LEFT_DOWN;
2849 win->m_button1Pressed = TRUE;
2850 }
2851 else if (xevent->xbutton.button == Button2)
2852 {
2853 eventType = wxEVT_MIDDLE_DOWN;
2854 win->m_button2Pressed = TRUE;
2855 }
2856 else if (xevent->xbutton.button == Button3)
2857 {
2858 eventType = wxEVT_RIGHT_DOWN;
2859 win->m_button3Pressed = TRUE;
2860 }
2861 }
2862 else if (xevent->xany.type == ButtonRelease)
2863 {
2864 if (xevent->xbutton.button == Button1)
2865 {
2866 eventType = wxEVT_LEFT_UP;
2867 win->m_button1Pressed = FALSE;
2868 }
2869 else if (xevent->xbutton.button == Button2)
2870 {
2871 eventType = wxEVT_MIDDLE_UP;
2872 win->m_button2Pressed = FALSE;
2873 }
2874 else if (xevent->xbutton.button == Button3)
2875 {
2876 eventType = wxEVT_RIGHT_UP;
2877 win->m_button3Pressed = FALSE;
2878 }
2879 else return FALSE;
2880 }
2881 else return FALSE;
2882
2883 wxevent.m_eventHandle = (char *)xevent;
2884 wxevent.SetEventType(eventType);
2885
2886 Position x1, y1;
2887 XtVaGetValues(widget, XmNx, &x1, XmNy, &y1, NULL);
2888
2889 int x2, y2;
2890 win->GetPosition(&x2, &y2);
2891
2892 // The button x/y must be translated to wxWindows
2893 // window space - the widget might be a label or button,
2894 // within a form.
2895 int dx = 0;
2896 int dy = 0;
2897 if (widget != (Widget)win->GetMainWidget())
2898 {
2899 dx = x1;
2900 dy = y1;
2901 }
2902
2903 wxevent.m_x = xevent->xbutton.x + dx;
2904 wxevent.m_y = xevent->xbutton.y + dy;
2905
2906 wxevent.m_leftDown = ((eventType == wxEVT_LEFT_DOWN)
2907 || (event_left_is_down (xevent)
2908 && (eventType != wxEVT_LEFT_UP)));
2909 wxevent.m_middleDown = ((eventType == wxEVT_MIDDLE_DOWN)
2910 || (event_middle_is_down (xevent)
2911 && (eventType != wxEVT_MIDDLE_UP)));
2912 wxevent.m_rightDown = ((eventType == wxEVT_RIGHT_DOWN)
2913 || (event_right_is_down (xevent)
2914 && (eventType != wxEVT_RIGHT_UP)));
2915
2916 wxevent.m_shiftDown = xevent->xbutton.state & ShiftMask;
2917 wxevent.m_controlDown = xevent->xbutton.state & ControlMask;
2918 return TRUE;
2919 }
2920 }
2921 return FALSE;
2922}
2923
2924bool wxTranslateKeyEvent(wxKeyEvent& wxevent, wxWindow *win, Widget widget, XEvent *xevent)
2925{
2926 switch (xevent->xany.type)
2927 {
2928 case KeyPress:
2929 {
2930 char buf[20];
2931
2932 KeySym keySym;
2933// XComposeStatus compose;
2934// (void) XLookupString ((XKeyEvent *) xevent, buf, 20, &keySym, &compose);
2935 (void) XLookupString ((XKeyEvent *) xevent, buf, 20, &keySym, NULL);
2936 int id = wxCharCodeXToWX (keySym);
2937
2938 if (xevent->xkey.state & ShiftMask)
2939 wxevent.m_shiftDown = TRUE;
2940 if (xevent->xkey.state & ControlMask)
2941 wxevent.m_controlDown = TRUE;
2942 if (xevent->xkey.state & Mod3Mask)
2943 wxevent.m_altDown = TRUE;
2944 if (xevent->xkey.state & Mod1Mask)
2945 wxevent.m_metaDown = TRUE;
2946 wxevent.SetEventObject(win);
2947 wxevent.m_keyCode = id;
2948 wxevent.SetTimestamp(xevent->xkey.time);
2949
2950 wxevent.m_x = xevent->xbutton.x;
2951 wxevent.m_y = xevent->xbutton.y;
2952
2953 if (id > -1)
2954 return TRUE;
2955 else
2956 return FALSE;
2957 break;
2958 }
2959 default:
2960 break;
2961 }
2962 return FALSE;
2963}
2964
02e8b2f9 2965#define YAllocColor XAllocColor
0d57be45
JS
2966XColor g_itemColors[5];
2967int wxComputeColours (Display *display, wxColour * back, wxColour * fore)
02e8b2f9
JS
2968{
2969 int result;
2970 static XmColorProc colorProc;
2971
2972 result = wxNO_COLORS;
2973
2974 if (back)
2975 {
0d57be45
JS
2976 g_itemColors[0].red = (((long) back->Red ()) << 8);
2977 g_itemColors[0].green = (((long) back->Green ()) << 8);
2978 g_itemColors[0].blue = (((long) back->Blue ()) << 8);
2979 g_itemColors[0].flags = DoRed | DoGreen | DoBlue;
02e8b2f9
JS
2980 if (colorProc == (XmColorProc) NULL)
2981 {
2982 // Get a ptr to the actual function
2983 colorProc = XmSetColorCalculation ((XmColorProc) NULL);
2984 // And set it back to motif.
2985 XmSetColorCalculation (colorProc);
2986 }
0d57be45
JS
2987 (*colorProc) (&g_itemColors[wxBACK_INDEX],
2988 &g_itemColors[wxFORE_INDEX],
2989 &g_itemColors[wxSELE_INDEX],
2990 &g_itemColors[wxTOPS_INDEX],
2991 &g_itemColors[wxBOTS_INDEX]);
02e8b2f9
JS
2992 result = wxBACK_COLORS;
2993 }
2994 if (fore)
2995 {
0d57be45
JS
2996 g_itemColors[wxFORE_INDEX].red = (((long) fore->Red ()) << 8);
2997 g_itemColors[wxFORE_INDEX].green = (((long) fore->Green ()) << 8);
2998 g_itemColors[wxFORE_INDEX].blue = (((long) fore->Blue ()) << 8);
2999 g_itemColors[wxFORE_INDEX].flags = DoRed | DoGreen | DoBlue;
02e8b2f9
JS
3000 if (result == wxNO_COLORS)
3001 result = wxFORE_COLORS;
3002 }
3003
3004 Display *dpy = display;
3005 Colormap cmap = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) dpy);
3006
3007 if (back)
3008 {
3009 /* 5 Colours to allocate */
3010 for (int i = 0; i < 5; i++)
0d57be45 3011 if (!YAllocColor (dpy, cmap, &g_itemColors[i]))
02e8b2f9
JS
3012 result = wxNO_COLORS;
3013 }
3014 else if (fore)
3015 {
3016 /* Only 1 colour to allocate */
0d57be45 3017 if (!YAllocColor (dpy, cmap, &g_itemColors[wxFORE_INDEX]))
02e8b2f9
JS
3018 result = wxNO_COLORS;
3019 }
3020
3021 return (result);
3022
3023}
3024
0d57be45
JS
3025// Changes the foreground and background colours to be derived
3026// from the current background colour.
3027// To change the foreground colour, you must call SetForegroundColour
3028// explicitly.
3029void wxWindow::ChangeBackgroundColour()
02e8b2f9 3030{
0d57be45
JS
3031 if (GetMainWidget())
3032 DoChangeBackgroundColour(GetMainWidget(), m_backgroundColour);
3033}
02e8b2f9 3034
0d57be45
JS
3035void wxWindow::ChangeForegroundColour()
3036{
3037 if (GetMainWidget())
3038 DoChangeForegroundColour(GetMainWidget(), m_foregroundColour);
3039}
02e8b2f9 3040
0d57be45
JS
3041// Change a widget's foreground and background colours.
3042
0d57be45
JS
3043void wxWindow::DoChangeForegroundColour(WXWidget widget, wxColour& foregroundColour)
3044{
3045 // When should we specify the foreground, if it's calculated
3046 // by wxComputeColours?
3047 // Solution: say we start with the default (computed) foreground colour.
3048 // If we call SetForegroundColour explicitly for a control or window,
3049 // then the foreground is changed.
3050 // Therefore SetBackgroundColour computes the foreground colour, and
3051 // SetForegroundColour changes the foreground colour. The ordering is
3052 // important.
02e8b2f9 3053
0d57be45
JS
3054 XtVaSetValues ((Widget) widget,
3055 XmNforeground, foregroundColour.AllocColour(XtDisplay((Widget) widget)),
02e8b2f9 3056 NULL);
0d57be45
JS
3057}
3058
3059void wxWindow::DoChangeBackgroundColour(WXWidget widget, wxColour& backgroundColour, bool changeArmColour)
3060{
3061 wxComputeColours (XtDisplay((Widget) widget), & backgroundColour,
3062 (wxColour*) NULL);
3063
3064 XtVaSetValues ((Widget) widget,
3065 XmNbackground, g_itemColors[wxBACK_INDEX].pixel,
3066 XmNtopShadowColor, g_itemColors[wxTOPS_INDEX].pixel,
3067 XmNbottomShadowColor, g_itemColors[wxBOTS_INDEX].pixel,
3068 XmNforeground, g_itemColors[wxFORE_INDEX].pixel,
02e8b2f9 3069 NULL);
0d57be45
JS
3070
3071 if (changeArmColour)
3072 XtVaSetValues ((Widget) widget,
3073 XmNarmColor, g_itemColors[wxSELE_INDEX].pixel,
3074 NULL);
02e8b2f9
JS
3075}
3076
0d57be45 3077void wxWindow::SetBackgroundColour(const wxColour& col)
02e8b2f9 3078{
0d57be45
JS
3079 m_backgroundColour = col;
3080 ChangeBackgroundColour();
3081}
3082
3083void wxWindow::SetForegroundColour(const wxColour& col)
3084{
3085 m_foregroundColour = col;
3086 ChangeForegroundColour();
3087}
3088
4b5f3fe6 3089void wxWindow::ChangeFont(bool keepOriginalSize)
0d57be45
JS
3090{
3091 // Note that this causes the widget to be resized back
3092 // to its original size! We therefore have to set the size
3093 // back again. TODO: a better way in Motif?
0d57be45
JS
3094 Widget w = (Widget) GetLabelWidget(); // Usually the main widget
3095 if (w && m_windowFont.Ok())
3096 {
3097 int width, height, width1, height1;
3098 GetSize(& width, & height);
3099
3100 XtVaSetValues (w,
3101 XmNfontList, (XmFontList) m_windowFont.GetFontList(1.0, XtDisplay(w)),
02e8b2f9 3102 NULL);
0d57be45
JS
3103
3104 GetSize(& width1, & height1);
4b5f3fe6 3105 if (keepOriginalSize && (width != width1 || height != height1))
0d57be45
JS
3106 {
3107 SetSize(-1, -1, width, height);
3108 }
3109 }
02e8b2f9 3110}
0d57be45
JS
3111
3112void wxWindow::SetFont(const wxFont& font)
3113{
3114 m_windowFont = font;
3115 ChangeFont();
3116}
3117
3118