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