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