]> git.saurik.com Git - wxWidgets.git/blob - src/motif/window.cpp
Motif files added.
[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 #include "wx/motif/private.h"
40
41 #include <string.h>
42
43 extern wxList wxPendingDelete;
44
45 #if !USE_SHARED_LIBRARY
46 IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxEvtHandler)
47
48 BEGIN_EVENT_TABLE(wxWindow, wxEvtHandler)
49 EVT_CHAR(wxWindow::OnChar)
50 EVT_ERASE_BACKGROUND(wxWindow::OnEraseBackground)
51 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged)
52 EVT_INIT_DIALOG(wxWindow::OnInitDialog)
53 EVT_IDLE(wxWindow::OnIdle)
54 END_EVENT_TABLE()
55
56 #endif
57
58
59 // Constructor
60 wxWindow::wxWindow()
61 {
62 // Generic
63 m_windowId = 0;
64 m_windowStyle = 0;
65 m_windowParent = NULL;
66 m_windowEventHandler = this;
67 m_windowName = "";
68 m_windowCursor = *wxSTANDARD_CURSOR;
69 m_children = new wxList;
70 m_constraints = NULL;
71 m_constraintsInvolvedIn = NULL;
72 m_windowSizer = NULL;
73 m_sizerParent = NULL;
74 m_autoLayout = FALSE;
75 m_windowValidator = NULL;
76 m_defaultItem = NULL;
77 m_returnCode = 0;
78 m_caretWidth = 0; m_caretHeight = 0;
79 m_caretEnabled = FALSE;
80 m_caretShown = FALSE;
81 m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW) ; ;
82 m_foregroundColour = *wxBLACK;
83 m_defaultForegroundColour = *wxBLACK ;
84 m_defaultBackgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE) ;
85
86 #if USE_DRAG_AND_DROP
87 m_pDropTarget = NULL;
88 #endif
89
90 /// MOTIF-specific
91 m_mainWidget = (WXWidget) 0;
92 m_button1Pressed = FALSE;
93 m_button2Pressed = FALSE;
94 m_button3Pressed = FALSE;
95 m_winCaptured = FALSE;
96 m_isShown = TRUE;
97 }
98
99 // Destructor
100 wxWindow::~wxWindow()
101 {
102 // Have to delete constraints/sizer FIRST otherwise
103 // sizers may try to look at deleted windows as they
104 // delete themselves.
105 #if USE_CONSTRAINTS
106 DeleteRelatedConstraints();
107 if (m_constraints)
108 {
109 // This removes any dangling pointers to this window
110 // in other windows' constraintsInvolvedIn lists.
111 UnsetConstraints(m_constraints);
112 delete m_constraints;
113 m_constraints = NULL;
114 }
115 if (m_windowSizer)
116 {
117 delete m_windowSizer;
118 m_windowSizer = NULL;
119 }
120 // If this is a child of a sizer, remove self from parent
121 if (m_sizerParent)
122 m_sizerParent->RemoveChild((wxWindow *)this);
123 #endif
124
125 if (m_windowParent)
126 m_windowParent->RemoveChild(this);
127
128 DestroyChildren();
129
130 // Destroy the window
131 if (GetMainWidget())
132 {
133 wxDeleteWindowFromTable((Widget) GetMainWidget());
134 XtDestroyWidget((Widget) GetMainWidget());
135 SetMainWidget((WXWidget) NULL);
136 }
137
138 delete m_children;
139 m_children = NULL;
140
141 // Just in case the window has been Closed, but
142 // we're then deleting immediately: don't leave
143 // dangling pointers.
144 wxPendingDelete.DeleteObject(this);
145
146 if ( m_windowValidator )
147 delete m_windowValidator;
148 }
149
150 // Destroy the window (delayed, if a managed window)
151 bool wxWindow::Destroy()
152 {
153 delete this;
154 return TRUE;
155 }
156
157 // Constructor
158 bool wxWindow::Create(wxWindow *parent, wxWindowID id,
159 const wxPoint& pos,
160 const wxSize& size,
161 long style,
162 const wxString& name)
163 {
164 // Generic
165 m_windowId = 0;
166 m_windowStyle = 0;
167 m_windowParent = NULL;
168 m_windowEventHandler = this;
169 m_windowName = "";
170 m_windowCursor = *wxSTANDARD_CURSOR;
171 m_constraints = NULL;
172 m_constraintsInvolvedIn = NULL;
173 m_windowSizer = NULL;
174 m_sizerParent = NULL;
175 m_autoLayout = FALSE;
176 m_windowValidator = NULL;
177
178 #if USE_DRAG_AND_DROP
179 m_pDropTarget = NULL;
180 #endif
181
182 m_caretWidth = 0; m_caretHeight = 0;
183 m_caretEnabled = FALSE;
184 m_caretShown = FALSE;
185 m_minSizeX = -1;
186 m_minSizeY = -1;
187 m_maxSizeX = -1;
188 m_maxSizeY = -1;
189 m_defaultItem = NULL;
190 m_windowParent = NULL;
191 if (!parent)
192 return FALSE;
193
194 if (parent) parent->AddChild(this);
195
196 m_returnCode = 0;
197
198 SetName(name);
199
200 if ( id == -1 )
201 m_windowId = (int)NewControlId();
202 else
203 m_windowId = id;
204
205 m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW) ; ;
206 m_foregroundColour = *wxBLACK;
207 m_defaultForegroundColour = *wxBLACK ;
208 m_defaultBackgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE) ;
209
210 m_windowStyle = style;
211
212 if ( id == -1 )
213 m_windowId = (int)NewControlId();
214 else
215 m_windowId = id;
216
217 // TODO: create the window
218
219 return TRUE;
220 }
221
222 void wxWindow::SetFocus()
223 {
224 XmProcessTraversal((Widget) GetMainWidget(), XmTRAVERSE_CURRENT);
225 XmProcessTraversal((Widget) GetMainWidget(), XmTRAVERSE_CURRENT);
226 }
227
228 void wxWindow::Enable(bool enable)
229 {
230 if (GetMainWidget())
231 {
232 XtSetSensitive((Widget) GetMainWidget(), enable);
233 XmUpdateDisplay((Widget) GetMainWidget());
234 }
235 }
236
237 void wxWindow::CaptureMouse()
238 {
239 if (m_winCaptured)
240 return;
241
242 if (GetMainWidget())
243 XtAddGrab((Widget) GetMainWidget(), TRUE, FALSE);
244
245 m_winCaptured = TRUE;
246 }
247
248 void wxWindow::ReleaseMouse()
249 {
250 if (!m_winCaptured)
251 return;
252
253 if (GetMainWidget())
254 XtRemoveGrab((Widget) GetMainWidget());
255 m_winCaptured = FALSE;
256 }
257
258 // Push/pop event handler (i.e. allow a chain of event handlers
259 // be searched)
260 void wxWindow::PushEventHandler(wxEvtHandler *handler)
261 {
262 handler->SetNextHandler(GetEventHandler());
263 SetEventHandler(handler);
264 }
265
266 wxEvtHandler *wxWindow::PopEventHandler(bool deleteHandler)
267 {
268 if ( GetEventHandler() )
269 {
270 wxEvtHandler *handlerA = GetEventHandler();
271 wxEvtHandler *handlerB = handlerA->GetNextHandler();
272 handlerA->SetNextHandler(NULL);
273 SetEventHandler(handlerB);
274 if ( deleteHandler )
275 {
276 delete handlerA;
277 return NULL;
278 }
279 else
280 return handlerA;
281 }
282 else
283 return NULL;
284 }
285
286 #if USE_DRAG_AND_DROP
287
288 void wxWindow::SetDropTarget(wxDropTarget *pDropTarget)
289 {
290 if ( m_pDropTarget != 0 ) {
291 delete m_pDropTarget;
292 }
293
294 m_pDropTarget = pDropTarget;
295 if ( m_pDropTarget != 0 )
296 {
297 // TODO
298 }
299 }
300
301 #endif
302
303 // Old style file-manager drag&drop
304 void wxWindow::DragAcceptFiles(bool accept)
305 {
306 // TODO
307 }
308
309 // Get total size
310 void wxWindow::GetSize(int *x, int *y) const
311 {
312 Widget widget = (Widget) GetMainWidget();
313 Dimension xx, yy;
314 XtVaGetValues(widget, XmNwidth, &xx, XmNheight, &yy, NULL);
315 *x = xx; *y = yy;
316 }
317
318 void wxWindow::GetPosition(int *x, int *y) const
319 {
320 Widget widget = (Widget) GetMainWidget();
321 Position xx, yy;
322 XtVaGetValues(widget, XmNx, &xx, XmNy, &yy, NULL);
323 *x = xx; *y = yy;
324 }
325
326 void wxWindow::ScreenToClient(int *x, int *y) const
327 {
328 // TODO
329 }
330
331 void wxWindow::ClientToScreen(int *x, int *y) const
332 {
333 Widget widget = (Widget) GetMainWidget();
334 Display *display = XtDisplay(widget);
335 Window rootWindow = RootWindowOfScreen(XtScreen(widget));
336 Window thisWindow;
337 if (this->IsKindOf(CLASSINFO(wxFrame)))
338 {
339 wxFrame *fr = (wxFrame *)this;
340 // TODO
341 // thisWindow = XtWindow(fr->m_clientArea);
342 }
343 else
344 thisWindow = XtWindow((Widget)widget);
345
346 Window childWindow;
347 int xx = *x;
348 int yy = *y;
349 XTranslateCoordinates(display, thisWindow, rootWindow, xx, yy, x, y, &childWindow);
350 }
351
352 void wxWindow::SetCursor(const wxCursor& cursor)
353 {
354 m_windowCursor = cursor;
355 if (m_windowCursor.Ok())
356 {
357 /* TODO when wxCursor implemented
358 WXDisplay *dpy = GetXDisplay();
359 Cursor x_cursor = cursor.GetXCursor(dpy);
360
361 Widget w = (Widget) GetMainWidget();
362 Window win = XtWindow(w);
363 XDefineCursor((Display*) dpy, win, x_cursor);
364 */
365 }
366 }
367
368
369 // Get size *available for subwindows* i.e. excluding menu bar etc.
370 void wxWindow::GetClientSize(int *x, int *y) const
371 {
372 Widget widget = (Widget) GetMainWidget();
373 Dimension xx, yy;
374 XtVaGetValues(widget, XmNwidth, &xx, XmNheight, &yy, NULL);
375 *x = xx; *y = yy;
376 }
377
378 void wxWindow::SetSize(int x, int y, int width, int height, int sizeFlags)
379 {
380 Widget widget = (Widget) GetMainWidget();
381
382 if (x > -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
383 XtVaSetValues(widget, XmNx, x, NULL);
384 if (y > -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
385 XtVaSetValues(widget, XmNy, y, NULL);
386 if (width > -1)
387 XtVaSetValues(widget, XmNwidth, width, NULL);
388 if (height > -1)
389 XtVaSetValues(widget, XmNheight, height, NULL);
390
391 wxSizeEvent sizeEvent(wxSize(width, height), GetId());
392 sizeEvent.SetEventObject(this);
393
394 GetEventHandler()->ProcessEvent(sizeEvent);
395 }
396
397 void wxWindow::SetClientSize(int width, int height)
398 {
399 Widget widget = (Widget) GetMainWidget();
400
401 if (width > -1)
402 XtVaSetValues(widget, XmNwidth, width, NULL);
403 if (height > -1)
404 XtVaSetValues(widget, XmNheight, height, NULL);
405
406 wxSizeEvent sizeEvent(wxSize(width, height), GetId());
407 sizeEvent.SetEventObject(this);
408
409 GetEventHandler()->ProcessEvent(sizeEvent);
410 }
411
412 // For implementation purposes - sometimes decorations make the client area
413 // smaller
414 wxPoint wxWindow::GetClientAreaOrigin() const
415 {
416 return wxPoint(0, 0);
417 }
418
419 // Makes an adjustment to the window position (for example, a frame that has
420 // a toolbar that it manages itself).
421 void wxWindow::AdjustForParentClientOrigin(int& x, int& y, int sizeFlags)
422 {
423 if (((sizeFlags & wxSIZE_NO_ADJUSTMENTS) == 0) && GetParent())
424 {
425 wxPoint pt(GetParent()->GetClientAreaOrigin());
426 x += pt.x; y += pt.y;
427 }
428 }
429
430 bool wxWindow::Show(bool show)
431 {
432 Window xwin = (Window) GetXWindow();
433 Display *xdisp = (Display*) GetXDisplay();
434 if (show)
435 XMapWindow(xdisp, xwin);
436 else
437 XUnmapWindow(xdisp, xwin);
438
439 m_isShown = show;
440
441 return TRUE;
442 }
443
444 bool wxWindow::IsShown() const
445 {
446 return m_isShown;
447 }
448
449 int wxWindow::GetCharHeight() const
450 {
451 // TODO
452 return 0;
453 }
454
455 int wxWindow::GetCharWidth() const
456 {
457 // TODO
458 return 0;
459 }
460
461 void wxWindow::GetTextExtent(const wxString& string, int *x, int *y,
462 int *descent, int *externalLeading, const wxFont *theFont, bool) const
463 {
464 wxFont *fontToUse = (wxFont *)theFont;
465 if (!fontToUse)
466 fontToUse = (wxFont *) & m_windowFont;
467
468 // TODO
469 }
470
471 void wxWindow::Refresh(bool eraseBack, const wxRectangle *rect)
472 {
473 Display *display = XtDisplay((Widget) GetMainWidget());
474 Window thisWindow = XtWindow((Widget) GetMainWidget());
475
476 XExposeEvent dummyEvent;
477 int width, height;
478 GetSize(&width, &height);
479
480 dummyEvent.type = Expose;
481 dummyEvent.display = display;
482 dummyEvent.send_event = True;
483 dummyEvent.window = thisWindow;
484 if (rect)
485 {
486 dummyEvent.x = rect->x;
487 dummyEvent.y = rect->y;
488 dummyEvent.width = rect->width;
489 dummyEvent.height = rect->height;
490 }
491 else
492 {
493 dummyEvent.x = 0;
494 dummyEvent.y = 0;
495 dummyEvent.width = width;
496 dummyEvent.height = height;
497 }
498 dummyEvent.count = 0;
499
500 if (eraseBack)
501 {
502 wxClientDC dc(this);
503 dc.Clear();
504 }
505
506 XSendEvent(display, thisWindow, False, ExposureMask, (XEvent *)&dummyEvent);
507 }
508
509 // Responds to colour changes: passes event on to children.
510 void wxWindow::OnSysColourChanged(wxSysColourChangedEvent& event)
511 {
512 wxNode *node = GetChildren()->First();
513 while ( node )
514 {
515 // Only propagate to non-top-level windows
516 wxWindow *win = (wxWindow *)node->Data();
517 if ( win->GetParent() )
518 {
519 wxSysColourChangedEvent event2;
520 event.m_eventObject = win;
521 win->GetEventHandler()->ProcessEvent(event2);
522 }
523
524 node = node->Next();
525 }
526 }
527
528 // This can be called by the app (or wxWindows) to do default processing for the current
529 // event. Save message/event info in wxWindow so they can be used in this function.
530 long wxWindow::Default()
531 {
532 // TODO
533 return 0;
534 }
535
536 void wxWindow::InitDialog()
537 {
538 wxInitDialogEvent event(GetId());
539 event.SetEventObject( this );
540 GetEventHandler()->ProcessEvent(event);
541 }
542
543 // Default init dialog behaviour is to transfer data to window
544 void wxWindow::OnInitDialog(wxInitDialogEvent& event)
545 {
546 TransferDataToWindow();
547 }
548
549 // Caret manipulation
550 void wxWindow::CreateCaret(int w, int h)
551 {
552 m_caretWidth = w;
553 m_caretHeight = h;
554 m_caretEnabled = TRUE;
555 }
556
557 void wxWindow::CreateCaret(const wxBitmap *WXUNUSED(bitmap))
558 {
559 // TODO
560 }
561
562 void wxWindow::ShowCaret(bool show)
563 {
564 // TODO
565 }
566
567 void wxWindow::DestroyCaret()
568 {
569 // TODO
570 m_caretEnabled = FALSE;
571 }
572
573 void wxWindow::SetCaretPos(int x, int y)
574 {
575 // TODO
576 }
577
578 void wxWindow::GetCaretPos(int *x, int *y) const
579 {
580 // TODO
581 }
582
583 wxWindow *wxGetActiveWindow()
584 {
585 // TODO
586 return NULL;
587 }
588
589 void wxWindow::SetSizeHints(int minW, int minH, int maxW, int maxH, int incW, int incH)
590 {
591 m_minSizeX = minW;
592 m_minSizeY = minH;
593 m_maxSizeX = maxW;
594 m_maxSizeY = maxH;
595
596 if (!this->IsKindOf(CLASSINFO(wxFrame)))
597 return;
598
599 wxFrame *frame = (wxFrame *)this;
600
601 /* Uncomment when wxFrame implemented
602 if (minW > -1)
603 XtVaSetValues((Widget) frame->m_frameShell, XmNminWidth, minW, NULL);
604 if (minH > -1)
605 XtVaSetValues((Widget) frame->m_frameShell, XmNminHeight, minH, NULL);
606 if (maxW > -1)
607 XtVaSetValues((Widget) frame->m_frameShell, XmNmaxWidth, maxW, NULL);
608 if (maxH > -1)
609 XtVaSetValues((Widget) frame->m_frameShell, XmNmaxHeight, maxH, NULL);
610 if (incW > -1)
611 XtVaSetValues((Widget) frame->m_frameShell, XmNwidthInc, incW, NULL);
612 if (incH > -1)
613 XtVaSetValues((Widget) frame->m_frameShell, XmNheightInc, incH, NULL);
614 */
615 }
616
617 void wxWindow::Centre(int direction)
618 {
619 int x, y, width, height, panel_width, panel_height, new_x, new_y;
620
621 wxWindow *father = (wxWindow *)GetParent();
622 if (!father)
623 return;
624
625 father->GetClientSize(&panel_width, &panel_height);
626 GetSize(&width, &height);
627 GetPosition(&x, &y);
628
629 new_x = -1;
630 new_y = -1;
631
632 if (direction & wxHORIZONTAL)
633 new_x = (int)((panel_width - width)/2);
634
635 if (direction & wxVERTICAL)
636 new_y = (int)((panel_height - height)/2);
637
638 SetSize(new_x, new_y, -1, -1);
639
640 }
641
642 // Coordinates relative to the window
643 void wxWindow::WarpPointer (int x_pos, int y_pos)
644 {
645 // TODO
646 }
647
648 void wxWindow::OnEraseBackground(wxEraseEvent& event)
649 {
650 // TODO
651 Default();
652 }
653
654 int wxWindow::GetScrollPos(int orient) const
655 {
656 // TODO
657 return 0;
658 }
659
660 // This now returns the whole range, not just the number
661 // of positions that we can scroll.
662 int wxWindow::GetScrollRange(int orient) const
663 {
664 // TODO
665 return 0;
666 }
667
668 int wxWindow::GetScrollThumb(int orient) const
669 {
670 // TODO
671 return 0;
672 }
673
674 void wxWindow::SetScrollPos(int orient, int pos, bool refresh)
675 {
676 // TODO
677 return;
678 }
679
680 // New function that will replace some of the above.
681 void wxWindow::SetScrollbar(int orient, int pos, int thumbVisible,
682 int range, bool refresh)
683 {
684 // TODO
685 }
686
687 // Does a physical scroll
688 void wxWindow::ScrollWindow(int dx, int dy, const wxRectangle *rect)
689 {
690 // TODO
691 return;
692 }
693
694 void wxWindow::SetFont(const wxFont& font)
695 {
696 m_windowFont = font;
697
698 if (!m_windowFont.Ok())
699 return;
700 // TODO
701 }
702
703 void wxWindow::OnChar(wxKeyEvent& event)
704 {
705 if ( event.KeyCode() == WXK_TAB ) {
706 // propagate the TABs to the parent - it's up to it to decide what
707 // to do with it
708 if ( GetParent() ) {
709 if ( GetParent()->ProcessEvent(event) )
710 return;
711 }
712 }
713 }
714
715 void wxWindow::OnPaint(wxPaintEvent& event)
716 {
717 Default();
718 }
719
720 bool wxWindow::IsEnabled() const
721 {
722 // TODO
723 return FALSE;
724 }
725
726 // Dialog support: override these and call
727 // base class members to add functionality
728 // that can't be done using validators.
729 // NOTE: these functions assume that controls
730 // are direct children of this window, not grandchildren
731 // or other levels of descendant.
732
733 // Transfer values to controls. If returns FALSE,
734 // it's an application error (pops up a dialog)
735 bool wxWindow::TransferDataToWindow()
736 {
737 wxNode *node = GetChildren()->First();
738 while ( node )
739 {
740 wxWindow *child = (wxWindow *)node->Data();
741 if ( child->GetValidator() &&
742 !child->GetValidator()->TransferToWindow() )
743 {
744 wxMessageBox("Application Error", "Could not transfer data to window", wxOK|wxICON_EXCLAMATION);
745 return FALSE;
746 }
747
748 node = node->Next();
749 }
750 return TRUE;
751 }
752
753 // Transfer values from controls. If returns FALSE,
754 // validation failed: don't quit
755 bool wxWindow::TransferDataFromWindow()
756 {
757 wxNode *node = GetChildren()->First();
758 while ( node )
759 {
760 wxWindow *child = (wxWindow *)node->Data();
761 if ( child->GetValidator() && !child->GetValidator()->TransferFromWindow() )
762 {
763 return FALSE;
764 }
765
766 node = node->Next();
767 }
768 return TRUE;
769 }
770
771 bool wxWindow::Validate()
772 {
773 wxNode *node = GetChildren()->First();
774 while ( node )
775 {
776 wxWindow *child = (wxWindow *)node->Data();
777 if ( child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->Validate(this) )
778 {
779 return FALSE;
780 }
781
782 node = node->Next();
783 }
784 return TRUE;
785 }
786
787 // Get the window with the focus
788 wxWindow *wxWindow::FindFocus()
789 {
790 // TODO
791 return NULL;
792 }
793
794 void wxWindow::AddChild(wxWindow *child)
795 {
796 GetChildren()->Append(child);
797 child->m_windowParent = this;
798 }
799
800 void wxWindow::RemoveChild(wxWindow *child)
801 {
802 if (GetChildren())
803 GetChildren()->DeleteObject(child);
804 child->m_windowParent = NULL;
805 }
806
807 void wxWindow::DestroyChildren()
808 {
809 if (GetChildren()) {
810 wxNode *node;
811 while ((node = GetChildren()->First()) != (wxNode *)NULL) {
812 wxWindow *child;
813 if ((child = (wxWindow *)node->Data()) != (wxWindow *)NULL) {
814 delete child;
815 if ( GetChildren()->Member(child) )
816 delete node;
817 }
818 } /* while */
819 }
820 }
821
822 void wxWindow::MakeModal(bool modal)
823 {
824 // Disable all other windows
825 if (this->IsKindOf(CLASSINFO(wxDialog)) || this->IsKindOf(CLASSINFO(wxFrame)))
826 {
827 wxNode *node = wxTopLevelWindows.First();
828 while (node)
829 {
830 wxWindow *win = (wxWindow *)node->Data();
831 if (win != this)
832 win->Enable(!modal);
833
834 node = node->Next();
835 }
836 }
837 }
838
839 void wxWindow::SetConstraints(wxLayoutConstraints *c)
840 {
841 if (m_constraints)
842 {
843 UnsetConstraints(m_constraints);
844 delete m_constraints;
845 }
846 m_constraints = c;
847 if (m_constraints)
848 {
849 // Make sure other windows know they're part of a 'meaningful relationship'
850 if (m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this))
851 m_constraints->left.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
852 if (m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this))
853 m_constraints->top.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
854 if (m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this))
855 m_constraints->right.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
856 if (m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this))
857 m_constraints->bottom.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
858 if (m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this))
859 m_constraints->width.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
860 if (m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this))
861 m_constraints->height.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
862 if (m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this))
863 m_constraints->centreX.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
864 if (m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this))
865 m_constraints->centreY.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
866 }
867 }
868
869 // This removes any dangling pointers to this window
870 // in other windows' constraintsInvolvedIn lists.
871 void wxWindow::UnsetConstraints(wxLayoutConstraints *c)
872 {
873 if (c)
874 {
875 if (c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this))
876 c->left.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
877 if (c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this))
878 c->top.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
879 if (c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this))
880 c->right.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
881 if (c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this))
882 c->bottom.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
883 if (c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this))
884 c->width.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
885 if (c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this))
886 c->height.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
887 if (c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this))
888 c->centreX.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
889 if (c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this))
890 c->centreY.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
891 }
892 }
893
894 // Back-pointer to other windows we're involved with, so if we delete
895 // this window, we must delete any constraints we're involved with.
896 void wxWindow::AddConstraintReference(wxWindow *otherWin)
897 {
898 if (!m_constraintsInvolvedIn)
899 m_constraintsInvolvedIn = new wxList;
900 if (!m_constraintsInvolvedIn->Member(otherWin))
901 m_constraintsInvolvedIn->Append(otherWin);
902 }
903
904 // REMOVE back-pointer to other windows we're involved with.
905 void wxWindow::RemoveConstraintReference(wxWindow *otherWin)
906 {
907 if (m_constraintsInvolvedIn)
908 m_constraintsInvolvedIn->DeleteObject(otherWin);
909 }
910
911 // Reset any constraints that mention this window
912 void wxWindow::DeleteRelatedConstraints()
913 {
914 if (m_constraintsInvolvedIn)
915 {
916 wxNode *node = m_constraintsInvolvedIn->First();
917 while (node)
918 {
919 wxWindow *win = (wxWindow *)node->Data();
920 wxNode *next = node->Next();
921 wxLayoutConstraints *constr = win->GetConstraints();
922
923 // Reset any constraints involving this window
924 if (constr)
925 {
926 constr->left.ResetIfWin((wxWindow *)this);
927 constr->top.ResetIfWin((wxWindow *)this);
928 constr->right.ResetIfWin((wxWindow *)this);
929 constr->bottom.ResetIfWin((wxWindow *)this);
930 constr->width.ResetIfWin((wxWindow *)this);
931 constr->height.ResetIfWin((wxWindow *)this);
932 constr->centreX.ResetIfWin((wxWindow *)this);
933 constr->centreY.ResetIfWin((wxWindow *)this);
934 }
935 delete node;
936 node = next;
937 }
938 delete m_constraintsInvolvedIn;
939 m_constraintsInvolvedIn = NULL;
940 }
941 }
942
943 void wxWindow::SetSizer(wxSizer *sizer)
944 {
945 m_windowSizer = sizer;
946 if (sizer)
947 sizer->SetSizerParent((wxWindow *)this);
948 }
949
950 /*
951 * New version
952 */
953
954 bool wxWindow::Layout()
955 {
956 if (GetConstraints())
957 {
958 int w, h;
959 GetClientSize(&w, &h);
960 GetConstraints()->width.SetValue(w);
961 GetConstraints()->height.SetValue(h);
962 }
963
964 // If top level (one sizer), evaluate the sizer's constraints.
965 if (GetSizer())
966 {
967 int noChanges;
968 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
969 GetSizer()->LayoutPhase1(&noChanges);
970 GetSizer()->LayoutPhase2(&noChanges);
971 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
972 return TRUE;
973 }
974 else
975 {
976 // Otherwise, evaluate child constraints
977 ResetConstraints(); // Mark all constraints as unevaluated
978 DoPhase(1); // Just one phase need if no sizers involved
979 DoPhase(2);
980 SetConstraintSizes(); // Recursively set the real window sizes
981 }
982 return TRUE;
983 }
984
985
986 // Do a phase of evaluating constraints:
987 // the default behaviour. wxSizers may do a similar
988 // thing, but also impose their own 'constraints'
989 // and order the evaluation differently.
990 bool wxWindow::LayoutPhase1(int *noChanges)
991 {
992 wxLayoutConstraints *constr = GetConstraints();
993 if (constr)
994 {
995 return constr->SatisfyConstraints((wxWindow *)this, noChanges);
996 }
997 else
998 return TRUE;
999 }
1000
1001 bool wxWindow::LayoutPhase2(int *noChanges)
1002 {
1003 *noChanges = 0;
1004
1005 // Layout children
1006 DoPhase(1);
1007 DoPhase(2);
1008 return TRUE;
1009 }
1010
1011 // Do a phase of evaluating child constraints
1012 bool wxWindow::DoPhase(int phase)
1013 {
1014 int noIterations = 0;
1015 int maxIterations = 500;
1016 int noChanges = 1;
1017 int noFailures = 0;
1018 wxList succeeded;
1019 while ((noChanges > 0) && (noIterations < maxIterations))
1020 {
1021 noChanges = 0;
1022 noFailures = 0;
1023 wxNode *node = GetChildren()->First();
1024 while (node)
1025 {
1026 wxWindow *child = (wxWindow *)node->Data();
1027 if (!child->IsKindOf(CLASSINFO(wxFrame)) && !child->IsKindOf(CLASSINFO(wxDialog)))
1028 {
1029 wxLayoutConstraints *constr = child->GetConstraints();
1030 if (constr)
1031 {
1032 if (succeeded.Member(child))
1033 {
1034 }
1035 else
1036 {
1037 int tempNoChanges = 0;
1038 bool success = ( (phase == 1) ? child->LayoutPhase1(&tempNoChanges) : child->LayoutPhase2(&tempNoChanges) ) ;
1039 noChanges += tempNoChanges;
1040 if (success)
1041 {
1042 succeeded.Append(child);
1043 }
1044 }
1045 }
1046 }
1047 node = node->Next();
1048 }
1049 noIterations ++;
1050 }
1051 return TRUE;
1052 }
1053
1054 void wxWindow::ResetConstraints()
1055 {
1056 wxLayoutConstraints *constr = GetConstraints();
1057 if (constr)
1058 {
1059 constr->left.SetDone(FALSE);
1060 constr->top.SetDone(FALSE);
1061 constr->right.SetDone(FALSE);
1062 constr->bottom.SetDone(FALSE);
1063 constr->width.SetDone(FALSE);
1064 constr->height.SetDone(FALSE);
1065 constr->centreX.SetDone(FALSE);
1066 constr->centreY.SetDone(FALSE);
1067 }
1068 wxNode *node = GetChildren()->First();
1069 while (node)
1070 {
1071 wxWindow *win = (wxWindow *)node->Data();
1072 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
1073 win->ResetConstraints();
1074 node = node->Next();
1075 }
1076 }
1077
1078 // Need to distinguish between setting the 'fake' size for
1079 // windows and sizers, and setting the real values.
1080 void wxWindow::SetConstraintSizes(bool recurse)
1081 {
1082 wxLayoutConstraints *constr = GetConstraints();
1083 if (constr && constr->left.GetDone() && constr->right.GetDone() &&
1084 constr->width.GetDone() && constr->height.GetDone())
1085 {
1086 int x = constr->left.GetValue();
1087 int y = constr->top.GetValue();
1088 int w = constr->width.GetValue();
1089 int h = constr->height.GetValue();
1090
1091 // If we don't want to resize this window, just move it...
1092 if ((constr->width.GetRelationship() != wxAsIs) ||
1093 (constr->height.GetRelationship() != wxAsIs))
1094 {
1095 // Calls Layout() recursively. AAAGH. How can we stop that.
1096 // Simply take Layout() out of non-top level OnSizes.
1097 SizerSetSize(x, y, w, h);
1098 }
1099 else
1100 {
1101 SizerMove(x, y);
1102 }
1103 }
1104 else if (constr)
1105 {
1106 char *windowClass = this->GetClassInfo()->GetClassName();
1107
1108 wxString winName;
1109 if (GetName() == "")
1110 winName = "unnamed";
1111 else
1112 winName = GetName();
1113 wxDebugMsg("Constraint(s) not satisfied for window of type %s, name %s:\n", (const char *)windowClass, (const char *)winName);
1114 if (!constr->left.GetDone())
1115 wxDebugMsg(" unsatisfied 'left' constraint.\n");
1116 if (!constr->right.GetDone())
1117 wxDebugMsg(" unsatisfied 'right' constraint.\n");
1118 if (!constr->width.GetDone())
1119 wxDebugMsg(" unsatisfied 'width' constraint.\n");
1120 if (!constr->height.GetDone())
1121 wxDebugMsg(" unsatisfied 'height' constraint.\n");
1122 wxDebugMsg("Please check constraints: try adding AsIs() constraints.\n");
1123 }
1124
1125 if (recurse)
1126 {
1127 wxNode *node = GetChildren()->First();
1128 while (node)
1129 {
1130 wxWindow *win = (wxWindow *)node->Data();
1131 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
1132 win->SetConstraintSizes();
1133 node = node->Next();
1134 }
1135 }
1136 }
1137
1138 // This assumes that all sizers are 'on' the same
1139 // window, i.e. the parent of this window.
1140 void wxWindow::TransformSizerToActual(int *x, int *y) const
1141 {
1142 if (!m_sizerParent || m_sizerParent->IsKindOf(CLASSINFO(wxDialog)) ||
1143 m_sizerParent->IsKindOf(CLASSINFO(wxFrame)) )
1144 return;
1145
1146 int xp, yp;
1147 m_sizerParent->GetPosition(&xp, &yp);
1148 m_sizerParent->TransformSizerToActual(&xp, &yp);
1149 *x += xp;
1150 *y += yp;
1151 }
1152
1153 void wxWindow::SizerSetSize(int x, int y, int w, int h)
1154 {
1155 int xx = x;
1156 int yy = y;
1157 TransformSizerToActual(&xx, &yy);
1158 SetSize(xx, yy, w, h);
1159 }
1160
1161 void wxWindow::SizerMove(int x, int y)
1162 {
1163 int xx = x;
1164 int yy = y;
1165 TransformSizerToActual(&xx, &yy);
1166 Move(xx, yy);
1167 }
1168
1169 // Only set the size/position of the constraint (if any)
1170 void wxWindow::SetSizeConstraint(int x, int y, int w, int h)
1171 {
1172 wxLayoutConstraints *constr = GetConstraints();
1173 if (constr)
1174 {
1175 if (x != -1)
1176 {
1177 constr->left.SetValue(x);
1178 constr->left.SetDone(TRUE);
1179 }
1180 if (y != -1)
1181 {
1182 constr->top.SetValue(y);
1183 constr->top.SetDone(TRUE);
1184 }
1185 if (w != -1)
1186 {
1187 constr->width.SetValue(w);
1188 constr->width.SetDone(TRUE);
1189 }
1190 if (h != -1)
1191 {
1192 constr->height.SetValue(h);
1193 constr->height.SetDone(TRUE);
1194 }
1195 }
1196 }
1197
1198 void wxWindow::MoveConstraint(int x, int y)
1199 {
1200 wxLayoutConstraints *constr = GetConstraints();
1201 if (constr)
1202 {
1203 if (x != -1)
1204 {
1205 constr->left.SetValue(x);
1206 constr->left.SetDone(TRUE);
1207 }
1208 if (y != -1)
1209 {
1210 constr->top.SetValue(y);
1211 constr->top.SetDone(TRUE);
1212 }
1213 }
1214 }
1215
1216 void wxWindow::GetSizeConstraint(int *w, int *h) const
1217 {
1218 wxLayoutConstraints *constr = GetConstraints();
1219 if (constr)
1220 {
1221 *w = constr->width.GetValue();
1222 *h = constr->height.GetValue();
1223 }
1224 else
1225 GetSize(w, h);
1226 }
1227
1228 void wxWindow::GetClientSizeConstraint(int *w, int *h) const
1229 {
1230 wxLayoutConstraints *constr = GetConstraints();
1231 if (constr)
1232 {
1233 *w = constr->width.GetValue();
1234 *h = constr->height.GetValue();
1235 }
1236 else
1237 GetClientSize(w, h);
1238 }
1239
1240 void wxWindow::GetPositionConstraint(int *x, int *y) const
1241 {
1242 wxLayoutConstraints *constr = GetConstraints();
1243 if (constr)
1244 {
1245 *x = constr->left.GetValue();
1246 *y = constr->top.GetValue();
1247 }
1248 else
1249 GetPosition(x, y);
1250 }
1251
1252 bool wxWindow::Close(bool force)
1253 {
1254 wxCloseEvent event(wxEVT_CLOSE_WINDOW, m_windowId);
1255 event.SetEventObject(this);
1256 event.SetForce(force);
1257
1258 return GetEventHandler()->ProcessEvent(event);
1259 }
1260
1261 wxObject* wxWindow::GetChild(int number) const
1262 {
1263 // Return a pointer to the Nth object in the window
1264 if (!GetChildren())
1265 return(NULL) ;
1266 wxNode *node = GetChildren()->First();
1267 int n = number;
1268 while (node && n--)
1269 node = node->Next() ;
1270 if (node)
1271 {
1272 wxObject *obj = (wxObject *)node->Data();
1273 return(obj) ;
1274 }
1275 else
1276 return NULL ;
1277 }
1278
1279 void wxWindow::OnDefaultAction(wxControl *initiatingItem)
1280 {
1281 // Obsolete function
1282 }
1283
1284 void wxWindow::Clear()
1285 {
1286 wxClientDC dc(this);
1287 wxBrush brush(GetBackgroundColour(), wxSOLID);
1288 dc.SetBackground(brush);
1289 dc.Clear();
1290 }
1291
1292 // Fits the panel around the items
1293 void wxWindow::Fit()
1294 {
1295 int maxX = 0;
1296 int maxY = 0;
1297 wxNode *node = GetChildren()->First();
1298 while ( node )
1299 {
1300 wxWindow *win = (wxWindow *)node->Data();
1301 int wx, wy, ww, wh;
1302 win->GetPosition(&wx, &wy);
1303 win->GetSize(&ww, &wh);
1304 if ( wx + ww > maxX )
1305 maxX = wx + ww;
1306 if ( wy + wh > maxY )
1307 maxY = wy + wh;
1308
1309 node = node->Next();
1310 }
1311 SetClientSize(maxX + 5, maxY + 5);
1312 }
1313
1314 void wxWindow::SetValidator(const wxValidator& validator)
1315 {
1316 if ( m_windowValidator )
1317 delete m_windowValidator;
1318 m_windowValidator = validator.Clone();
1319
1320 if ( m_windowValidator )
1321 m_windowValidator->SetWindow(this) ;
1322 }
1323
1324 // Find a window by id or name
1325 wxWindow *wxWindow::FindWindow(long id)
1326 {
1327 if ( GetId() == id)
1328 return this;
1329
1330 wxNode *node = GetChildren()->First();
1331 while ( node )
1332 {
1333 wxWindow *child = (wxWindow *)node->Data();
1334 wxWindow *found = child->FindWindow(id);
1335 if ( found )
1336 return found;
1337 node = node->Next();
1338 }
1339 return NULL;
1340 }
1341
1342 wxWindow *wxWindow::FindWindow(const wxString& name)
1343 {
1344 if ( GetName() == name)
1345 return this;
1346
1347 wxNode *node = GetChildren()->First();
1348 while ( node )
1349 {
1350 wxWindow *child = (wxWindow *)node->Data();
1351 wxWindow *found = child->FindWindow(name);
1352 if ( found )
1353 return found;
1354 node = node->Next();
1355 }
1356 return NULL;
1357 }
1358
1359 void wxWindow::OnIdle(wxIdleEvent& event)
1360 {
1361 /* TODO: you may need to do something like this
1362 * if your GUI doesn't generate enter/leave events
1363
1364 // Check if we need to send a LEAVE event
1365 if (m_mouseInWindow)
1366 {
1367 POINT pt;
1368 ::GetCursorPos(&pt);
1369 if (::WindowFromPoint(pt) != (HWND) GetHWND())
1370 {
1371 // Generate a LEAVE event
1372 m_mouseInWindow = FALSE;
1373 MSWOnMouseLeave(pt.x, pt.y, 0);
1374 }
1375 }
1376 */
1377
1378 // This calls the UI-update mechanism (querying windows for
1379 // menu/toolbar/control state information)
1380 UpdateWindowUI();
1381 }
1382
1383 // Raise the window to the top of the Z order
1384 void wxWindow::Raise()
1385 {
1386 Window window = XtWindow((Widget) GetMainWidget());
1387 XRaiseWindow(XtDisplay((Widget) GetMainWidget()), window);
1388 }
1389
1390 // Lower the window to the bottom of the Z order
1391 void wxWindow::Lower()
1392 {
1393 Window window = XtWindow((Widget) GetMainWidget());
1394 XLowerWindow(XtDisplay((Widget) GetMainWidget()), window);
1395 }
1396
1397 bool wxWindow::AcceptsFocus() const
1398 {
1399 return IsShown() && IsEnabled();
1400 }
1401
1402 // Update region access
1403 wxRegion wxWindow::GetUpdateRegion() const
1404 {
1405 return m_updateRegion;
1406 }
1407
1408 bool wxWindow::IsExposed(int x, int y, int w, int h) const
1409 {
1410 return (m_updateRegion.Contains(x, y, w, h) != wxOutRegion);
1411 }
1412
1413 bool wxWindow::IsExposed(const wxPoint& pt) const
1414 {
1415 return (m_updateRegion.Contains(pt) != wxOutRegion);
1416 }
1417
1418 bool wxWindow::IsExposed(const wxRect& rect) const
1419 {
1420 return (m_updateRegion.Contains(rect) != wxOutRegion);
1421 }
1422
1423 /*
1424 * Allocates control IDs
1425 */
1426
1427 int wxWindow::NewControlId()
1428 {
1429 static int s_controlId = 0;
1430 s_controlId ++;
1431 return s_controlId;
1432 }
1433
1434 void wxWindow::SetAcceleratorTable(const wxAcceleratorTable& accel)
1435 {
1436 m_acceleratorTable = accel;
1437 }
1438
1439 // All widgets should have this as their resize proc.
1440 // OnSize sent to wxWindow via client data.
1441 void wxWidgetResizeProc(Widget w, XConfigureEvent *event, String args[], int *num_args)
1442 {
1443 wxWindow *win = (wxWindow *)wxWidgetHashTable->Get((long)w);
1444 if (!win)
1445 return;
1446
1447 if (win->PreResize())
1448 {
1449 int width, height;
1450 win->GetSize(&width, &height);
1451 wxSizeEvent sizeEvent(wxSize(width, height), win->GetId());
1452 sizeEvent.SetEventObject(win);
1453 win->GetEventHandler()->ProcessEvent(sizeEvent);
1454 }
1455 }
1456
1457 bool wxAddWindowToTable(Widget w, wxWindow *win)
1458 {
1459 wxWindow *oldItem = NULL;
1460 #if DEBUG
1461 // printf("Adding widget %ld, name = %s\n", w, win->GetClassInfo()->GetClassName());
1462 #endif
1463 if ((oldItem = (wxWindow *)wxWidgetHashTable->Get ((long) w)))
1464 {
1465 char buf[300];
1466 sprintf(buf, "Widget table clash: new widget is %ld, %s", (long)w, win->GetClassInfo()->GetClassName());
1467 wxError (buf);
1468 fflush(stderr);
1469 sprintf(buf, "Old widget was %s", oldItem->GetClassInfo()->GetClassName());
1470 wxError (buf);
1471 return FALSE;
1472 }
1473
1474 wxWidgetHashTable->Put ((long) w, win);
1475 return TRUE;
1476 }
1477
1478 wxWindow *wxGetWindowFromTable(Widget w)
1479 {
1480 return (wxWindow *)wxWidgetHashTable->Get ((long) w);
1481 }
1482
1483 void wxDeleteWindowFromTable(Widget w)
1484 {
1485 #if DEBUG
1486 // printf("Deleting widget %ld\n", w);
1487 #endif
1488 // wxWindow *win = (wxWindow *)wxWidgetHashTable->Get ((long) w);
1489
1490 wxWidgetHashTable->Delete((long)w);
1491 }
1492
1493 // Get the underlying X window and display
1494 WXWindow wxWindow::GetXWindow() const
1495 {
1496 return (WXWindow) XtWindow((Widget) GetMainWidget());
1497 }
1498
1499 WXDisplay *wxWindow::GetXDisplay() const
1500 {
1501 return (WXDisplay*) XtDisplay((Widget) GetMainWidget());
1502 }
1503
1504 WXWidget wxWindow::GetMainWidget() const
1505 {
1506 return m_mainWidget;
1507 }
1508
1509