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