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