]> git.saurik.com Git - wxWidgets.git/blob - src/common/wincmn.cpp
Added X11 readme & install docs, updates to Motif ones
[wxWidgets.git] / src / common / wincmn.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: common/window.cpp
3 // Purpose: common (to all ports) wxWindow functions
4 // Author: Julian Smart, Vadim Zeitlin
5 // Modified by:
6 // Created: 13/07/98
7 // RCS-ID: $Id$
8 // Copyright: (c) wxWindows team
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation "windowbase.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #ifndef WX_PRECOMP
32 #include "wx/string.h"
33 #include "wx/log.h"
34 #include "wx/intl.h"
35 #include "wx/frame.h"
36 #include "wx/defs.h"
37 #include "wx/window.h"
38 #include "wx/control.h"
39 #include "wx/checkbox.h"
40 #include "wx/radiobut.h"
41 #include "wx/textctrl.h"
42 #include "wx/settings.h"
43 #include "wx/dialog.h"
44 #include "wx/msgdlg.h"
45 #include "wx/statusbr.h"
46 #endif //WX_PRECOMP
47
48 #if wxUSE_CONSTRAINTS
49 #include "wx/layout.h"
50 #include "wx/sizer.h"
51 #endif // wxUSE_CONSTRAINTS
52
53 #if wxUSE_DRAG_AND_DROP
54 #include "wx/dnd.h"
55 #endif // wxUSE_DRAG_AND_DROP
56
57 #if wxUSE_HELP
58 #include "wx/cshelp.h"
59 #endif // wxUSE_HELP
60
61 #if wxUSE_TOOLTIPS
62 #include "wx/tooltip.h"
63 #endif // wxUSE_TOOLTIPS
64
65 #if wxUSE_CARET
66 #include "wx/caret.h"
67 #endif // wxUSE_CARET
68
69 // ----------------------------------------------------------------------------
70 // static data
71 // ----------------------------------------------------------------------------
72
73 int wxWindowBase::ms_lastControlId = -200;
74
75 IMPLEMENT_ABSTRACT_CLASS(wxWindowBase, wxEvtHandler)
76
77 // ----------------------------------------------------------------------------
78 // event table
79 // ----------------------------------------------------------------------------
80
81 BEGIN_EVENT_TABLE(wxWindowBase, wxEvtHandler)
82 EVT_SYS_COLOUR_CHANGED(wxWindowBase::OnSysColourChanged)
83 EVT_INIT_DIALOG(wxWindowBase::OnInitDialog)
84 EVT_MIDDLE_DOWN(wxWindowBase::OnMiddleClick)
85
86 #if wxUSE_HELP
87 EVT_HELP(-1, wxWindowBase::OnHelp)
88 #endif // wxUSE_HELP
89
90 END_EVENT_TABLE()
91
92 // ============================================================================
93 // implementation of the common functionality of the wxWindow class
94 // ============================================================================
95
96 // ----------------------------------------------------------------------------
97 // initialization
98 // ----------------------------------------------------------------------------
99
100 // the default initialization
101 void wxWindowBase::InitBase()
102 {
103 // no window yet, no parent nor children
104 m_parent = (wxWindow *)NULL;
105 m_windowId = -1;
106 m_children.DeleteContents( FALSE ); // don't auto delete node data
107
108 // no constraints on the minimal window size
109 m_minWidth =
110 m_minHeight =
111 m_maxWidth =
112 m_maxHeight = -1;
113
114 // window is created enabled but it's not visible yet
115 m_isShown = FALSE;
116 m_isEnabled = TRUE;
117
118 // the default event handler is just this window
119 m_eventHandler = this;
120
121 #if wxUSE_VALIDATORS
122 // no validator
123 m_windowValidator = (wxValidator *) NULL;
124 #endif // wxUSE_VALIDATORS
125
126 // use the system default colours
127 m_backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE);
128 m_foregroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
129
130 // don't set the font here for wxMSW as we don't call WM_SETFONT here and
131 // so the font is *not* really set - but calls to SetFont() later won't do
132 // anything because m_font appears to be already set!
133 #ifndef __WXMSW__
134 m_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
135 #endif // __WXMSW__
136
137 // the colours/fonts are default for now
138 m_hasBgCol =
139 m_hasFgCol =
140 m_hasFont = FALSE;
141
142 // no style bits
143 m_exStyle =
144 m_windowStyle = 0;
145
146 // an optimization for the event processing: checking this flag is much
147 // faster than using IsKindOf(CLASSINFO(wxWindow))
148 m_isWindow = TRUE;
149
150 #if wxUSE_CONSTRAINTS
151 // no constraints whatsoever
152 m_constraints = (wxLayoutConstraints *) NULL;
153 m_constraintsInvolvedIn = (wxWindowList *) NULL;
154 m_windowSizer = (wxSizer *) NULL;
155 m_autoLayout = FALSE;
156 #endif // wxUSE_CONSTRAINTS
157
158 #if wxUSE_DRAG_AND_DROP
159 m_dropTarget = (wxDropTarget *)NULL;
160 #endif // wxUSE_DRAG_AND_DROP
161
162 #if wxUSE_TOOLTIPS
163 m_tooltip = (wxToolTip *)NULL;
164 #endif // wxUSE_TOOLTIPS
165
166 #if wxUSE_CARET
167 m_caret = (wxCaret *)NULL;
168 #endif // wxUSE_CARET
169
170 #if wxUSE_PALETTE
171 m_hasCustomPalette = FALSE;
172 #endif // wxUSE_PALETTE
173
174 // Whether we're using the current theme for this window (wxGTK only for now)
175 m_themeEnabled = FALSE;
176 }
177
178 // common part of window creation process
179 bool wxWindowBase::CreateBase(wxWindowBase *parent,
180 wxWindowID id,
181 const wxPoint& WXUNUSED(pos),
182 const wxSize& WXUNUSED(size),
183 long style,
184 const wxValidator& validator,
185 const wxString& name)
186 {
187 // m_isWindow is set to TRUE in wxWindowBase::Init() as well as many other
188 // member variables - check that it has been called (will catch the case
189 // when a new ctor is added which doesn't call InitWindow)
190 wxASSERT_MSG( m_isWindow, wxT("Init() must have been called before!") );
191
192 // generate a new id if the user doesn't care about it
193 m_windowId = id == -1 ? NewControlId() : id;
194
195 SetName(name);
196 SetWindowStyleFlag(style);
197 SetParent(parent);
198
199 #if wxUSE_VALIDATORS
200 SetValidator(validator);
201 #endif // wxUSE_VALIDATORS
202
203 // if the parent window has wxWS_EX_VALIDATE_RECURSIVELY set, we want to
204 // have it too - like this it's possible to set it only in the top level
205 // dialog/frame and all children will inherit it by defult
206 if ( parent && (parent->GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) )
207 {
208 SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY);
209 }
210
211 return TRUE;
212 }
213
214 // ----------------------------------------------------------------------------
215 // destruction
216 // ----------------------------------------------------------------------------
217
218 // common clean up
219 wxWindowBase::~wxWindowBase()
220 {
221 wxASSERT_MSG( GetCapture() != this, wxT("attempt to destroy window with mouse capture") );
222
223 // FIXME if these 2 cases result from programming errors in the user code
224 // we should probably assert here instead of silently fixing them
225
226 // Just in case the window has been Closed, but we're then deleting
227 // immediately: don't leave dangling pointers.
228 wxPendingDelete.DeleteObject(this);
229
230 // Just in case we've loaded a top-level window via LoadNativeDialog but
231 // we weren't a dialog class
232 wxTopLevelWindows.DeleteObject(this);
233
234 wxASSERT_MSG( GetChildren().GetCount() == 0, wxT("children not destroyed") );
235
236 #if wxUSE_CARET
237 if ( m_caret )
238 delete m_caret;
239 #endif // wxUSE_CARET
240
241 #if wxUSE_VALIDATORS
242 if ( m_windowValidator )
243 delete m_windowValidator;
244 #endif // wxUSE_VALIDATORS
245
246 #if wxUSE_CONSTRAINTS
247 // Have to delete constraints/sizer FIRST otherwise sizers may try to look
248 // at deleted windows as they delete themselves.
249 DeleteRelatedConstraints();
250
251 if ( m_constraints )
252 {
253 // This removes any dangling pointers to this window in other windows'
254 // constraintsInvolvedIn lists.
255 UnsetConstraints(m_constraints);
256 delete m_constraints;
257 m_constraints = NULL;
258 }
259
260 if ( m_windowSizer )
261 delete m_windowSizer;
262
263 #endif // wxUSE_CONSTRAINTS
264
265 #if wxUSE_DRAG_AND_DROP
266 if ( m_dropTarget )
267 delete m_dropTarget;
268 #endif // wxUSE_DRAG_AND_DROP
269
270 #if wxUSE_TOOLTIPS
271 if ( m_tooltip )
272 delete m_tooltip;
273 #endif // wxUSE_TOOLTIPS
274
275 // reset the dangling pointer our parent window may keep to us
276 if ( m_parent && m_parent->GetDefaultItem() == this )
277 {
278 m_parent->SetDefaultItem(NULL);
279 }
280 }
281
282 bool wxWindowBase::Destroy()
283 {
284 delete this;
285
286 return TRUE;
287 }
288
289 bool wxWindowBase::Close(bool force)
290 {
291 wxCloseEvent event(wxEVT_CLOSE_WINDOW, m_windowId);
292 event.SetEventObject(this);
293 #if WXWIN_COMPATIBILITY
294 event.SetForce(force);
295 #endif // WXWIN_COMPATIBILITY
296 event.SetCanVeto(!force);
297
298 // return FALSE if window wasn't closed because the application vetoed the
299 // close event
300 return GetEventHandler()->ProcessEvent(event) && !event.GetVeto();
301 }
302
303 bool wxWindowBase::DestroyChildren()
304 {
305 wxWindowList::Node *node;
306 for ( ;; )
307 {
308 // we iterate until the list becomes empty
309 node = GetChildren().GetFirst();
310 if ( !node )
311 break;
312
313 wxWindow *child = node->GetData();
314
315 wxASSERT_MSG( child, wxT("children list contains empty nodes") );
316
317 child->Show(FALSE);
318 delete child;
319
320 wxASSERT_MSG( !GetChildren().Find(child),
321 wxT("child didn't remove itself using RemoveChild()") );
322 }
323
324 return TRUE;
325 }
326
327 // ----------------------------------------------------------------------------
328 // size/position related methods
329 // ----------------------------------------------------------------------------
330
331 // centre the window with respect to its parent in either (or both) directions
332 void wxWindowBase::Centre(int direction)
333 {
334 // the position/size of the parent window or of the entire screen
335 wxPoint posParent;
336 int widthParent, heightParent;
337
338 wxWindow *parent = NULL;
339
340 if ( !(direction & wxCENTRE_ON_SCREEN) )
341 {
342 // find the parent to centre this window on: it should be the
343 // immediate parent for the controls but the top level parent for the
344 // top level windows (like dialogs)
345 parent = GetParent();
346 if ( IsTopLevel() )
347 {
348 while ( parent && !parent->IsTopLevel() )
349 {
350 parent = parent->GetParent();
351 }
352 }
353
354 // did we find the parent?
355 if ( !parent )
356 {
357 // no other choice
358 direction |= wxCENTRE_ON_SCREEN;
359 }
360 }
361
362 if ( direction & wxCENTRE_ON_SCREEN )
363 {
364 // centre with respect to the whole screen
365 wxDisplaySize(&widthParent, &heightParent);
366 }
367 else
368 {
369 if ( IsTopLevel() )
370 {
371 // centre on the parent
372 parent->GetSize(&widthParent, &heightParent);
373
374 // adjust to the parents position
375 posParent = parent->GetPosition();
376 }
377 else
378 {
379 // centre inside the parents client rectangle
380 parent->GetClientSize(&widthParent, &heightParent);
381 }
382 }
383
384 int width, height;
385 GetSize(&width, &height);
386
387 int xNew = -1,
388 yNew = -1;
389
390 if ( direction & wxHORIZONTAL )
391 xNew = (widthParent - width)/2;
392
393 if ( direction & wxVERTICAL )
394 yNew = (heightParent - height)/2;
395
396 xNew += posParent.x;
397 yNew += posParent.y;
398
399 // Base size of the visible dimensions of the display
400 // to take into account the taskbar
401 wxRect rect = wxGetClientDisplayRect();
402 wxSize size (rect.width,rect.height);
403
404 if (posParent.x >= 0) // if parent is on the main display
405 {
406 if (xNew < 0)
407 xNew = 0;
408 else if (xNew+width > size.x)
409 xNew = size.x-width-1;
410 }
411 if (posParent.y >= 0) // if parent is on the main display
412 {
413 if (yNew+height > size.y)
414 yNew = size.y-height-1;
415
416 // Make certain that the title bar is initially visible
417 // always, even if this would push the bottom of the
418 // dialog of the visible area of the display
419 if (yNew < 0)
420 yNew = 0;
421 }
422
423 // move the window to this position (keeping the old size but using
424 // SetSize() and not Move() to allow xNew and/or yNew to be -1)
425 SetSize(xNew, yNew, width, height, wxSIZE_ALLOW_MINUS_ONE);
426 }
427
428 // fits the window around the children
429 void wxWindowBase::Fit()
430 {
431 if ( GetChildren().GetCount() > 0 )
432 {
433 wxSize size = DoGetBestSize();
434
435 // for compatibility with the old versions and because it really looks
436 // slightly more pretty like this, add a pad
437 size.x += 7;
438 size.y += 14;
439
440 SetClientSize(size);
441 }
442 //else: do nothing if we have no children
443 }
444
445 // return the size best suited for the current window
446 wxSize wxWindowBase::DoGetBestSize() const
447 {
448 if ( GetChildren().GetCount() > 0 )
449 {
450 // our minimal acceptable size is such that all our windows fit inside
451 int maxX = 0,
452 maxY = 0;
453
454 for ( wxWindowList::Node *node = GetChildren().GetFirst();
455 node;
456 node = node->GetNext() )
457 {
458 wxWindow *win = node->GetData();
459 if ( win->IsTopLevel()
460 #if wxUSE_STATUSBAR
461 || wxDynamicCast(win, wxStatusBar)
462 #endif // wxUSE_STATUSBAR
463 )
464 {
465 // dialogs and frames lie in different top level windows -
466 // don't deal with them here; as for the status bars, they
467 // don't lie in the client area at all
468 continue;
469 }
470
471 int wx, wy, ww, wh;
472 win->GetPosition(&wx, &wy);
473
474 // if the window hadn't been positioned yet, assume that it is in
475 // the origin
476 if ( wx == -1 )
477 wx = 0;
478 if ( wy == -1 )
479 wy = 0;
480
481 win->GetSize(&ww, &wh);
482 if ( wx + ww > maxX )
483 maxX = wx + ww;
484 if ( wy + wh > maxY )
485 maxY = wy + wh;
486 }
487
488 return wxSize(maxX, maxY);
489 }
490 else
491 {
492 // for a generic window there is no natural best size - just use the
493 // current one
494 return GetSize();
495 }
496 }
497
498 // by default the origin is not shifted
499 wxPoint wxWindowBase::GetClientAreaOrigin() const
500 {
501 return wxPoint(0, 0);
502 }
503
504 // set the min/max size of the window
505 void wxWindowBase::SetSizeHints(int minW, int minH,
506 int maxW, int maxH,
507 int WXUNUSED(incW), int WXUNUSED(incH))
508 {
509 m_minWidth = minW;
510 m_maxWidth = maxW;
511 m_minHeight = minH;
512 m_maxHeight = maxH;
513 }
514
515 // ----------------------------------------------------------------------------
516 // show/hide/enable/disable the window
517 // ----------------------------------------------------------------------------
518
519 bool wxWindowBase::Show(bool show)
520 {
521 if ( show != m_isShown )
522 {
523 m_isShown = show;
524
525 return TRUE;
526 }
527 else
528 {
529 return FALSE;
530 }
531 }
532
533 bool wxWindowBase::Enable(bool enable)
534 {
535 if ( enable != m_isEnabled )
536 {
537 m_isEnabled = enable;
538
539 return TRUE;
540 }
541 else
542 {
543 return FALSE;
544 }
545 }
546 // ----------------------------------------------------------------------------
547 // RTTI
548 // ----------------------------------------------------------------------------
549
550 bool wxWindowBase::IsTopLevel() const
551 {
552 return FALSE;
553 }
554
555 // ----------------------------------------------------------------------------
556 // reparenting the window
557 // ----------------------------------------------------------------------------
558
559 void wxWindowBase::AddChild(wxWindowBase *child)
560 {
561 wxCHECK_RET( child, wxT("can't add a NULL child") );
562
563 // this should never happen and it will lead to a crash later if it does
564 // because RemoveChild() will remove only one node from the children list
565 // and the other(s) one(s) will be left with dangling pointers in them
566 wxASSERT_MSG( !GetChildren().Find(child), _T("AddChild() called twice") );
567
568 GetChildren().Append(child);
569 child->SetParent(this);
570 }
571
572 void wxWindowBase::RemoveChild(wxWindowBase *child)
573 {
574 wxCHECK_RET( child, wxT("can't remove a NULL child") );
575
576 GetChildren().DeleteObject(child);
577 child->SetParent((wxWindow *)NULL);
578 }
579
580 bool wxWindowBase::Reparent(wxWindowBase *newParent)
581 {
582 wxWindow *oldParent = GetParent();
583 if ( newParent == oldParent )
584 {
585 // nothing done
586 return FALSE;
587 }
588
589 // unlink this window from the existing parent.
590 if ( oldParent )
591 {
592 oldParent->RemoveChild(this);
593 }
594 else
595 {
596 wxTopLevelWindows.DeleteObject(this);
597 }
598
599 // add it to the new one
600 if ( newParent )
601 {
602 newParent->AddChild(this);
603 }
604 else
605 {
606 wxTopLevelWindows.Append(this);
607 }
608
609 return TRUE;
610 }
611
612 // ----------------------------------------------------------------------------
613 // event handler stuff
614 // ----------------------------------------------------------------------------
615
616 void wxWindowBase::PushEventHandler(wxEvtHandler *handler)
617 {
618 handler->SetNextHandler(GetEventHandler());
619 SetEventHandler(handler);
620 }
621
622 wxEvtHandler *wxWindowBase::PopEventHandler(bool deleteHandler)
623 {
624 wxEvtHandler *handlerA = GetEventHandler();
625 if ( handlerA )
626 {
627 wxEvtHandler *handlerB = handlerA->GetNextHandler();
628 handlerA->SetNextHandler((wxEvtHandler *)NULL);
629 SetEventHandler(handlerB);
630 if ( deleteHandler )
631 {
632 delete handlerA;
633 handlerA = (wxEvtHandler *)NULL;
634 }
635 }
636
637 return handlerA;
638 }
639
640 bool wxWindowBase::RemoveEventHandler(wxEvtHandler *handler)
641 {
642 wxCHECK_MSG( handler, FALSE, _T("RemoveEventHandler(NULL) called") );
643
644 wxEvtHandler *handlerPrev = NULL,
645 *handlerCur = GetEventHandler();
646 while ( handlerCur )
647 {
648 wxEvtHandler *handlerNext = handlerCur->GetNextHandler();
649
650 if ( handlerCur == handler )
651 {
652 if ( handlerPrev )
653 {
654 handlerPrev->SetNextHandler(handlerNext);
655 }
656 else
657 {
658 SetEventHandler(handlerNext);
659 }
660
661 handler->SetNextHandler(NULL);
662
663 return TRUE;
664 }
665
666 handlerPrev = handlerCur;
667 handlerCur = handlerNext;
668 }
669
670 wxFAIL_MSG( _T("where has the event handler gone?") );
671
672 return FALSE;
673 }
674
675 // ----------------------------------------------------------------------------
676 // cursors, fonts &c
677 // ----------------------------------------------------------------------------
678
679 bool wxWindowBase::SetBackgroundColour( const wxColour &colour )
680 {
681 if ( !colour.Ok() || (colour == m_backgroundColour) )
682 return FALSE;
683
684 m_backgroundColour = colour;
685
686 m_hasBgCol = TRUE;
687
688 return TRUE;
689 }
690
691 bool wxWindowBase::SetForegroundColour( const wxColour &colour )
692 {
693 if ( !colour.Ok() || (colour == m_foregroundColour) )
694 return FALSE;
695
696 m_foregroundColour = colour;
697
698 m_hasFgCol = TRUE;
699
700 return TRUE;
701 }
702
703 bool wxWindowBase::SetCursor(const wxCursor& cursor)
704 {
705 // setting an invalid cursor is ok, it means that we don't have any special
706 // cursor
707 if ( m_cursor == cursor )
708 {
709 // no change
710 return FALSE;
711 }
712
713 m_cursor = cursor;
714
715 return TRUE;
716 }
717
718 bool wxWindowBase::SetFont(const wxFont& font)
719 {
720 // don't try to set invalid font, always fall back to the default
721 const wxFont& fontOk = font.Ok() ? font : *wxSWISS_FONT;
722
723 if ( fontOk == m_font )
724 {
725 // no change
726 return FALSE;
727 }
728
729 m_font = fontOk;
730
731 m_hasFont = TRUE;
732
733 return TRUE;
734 }
735
736 #if wxUSE_PALETTE
737
738 void wxWindowBase::SetPalette(const wxPalette& pal)
739 {
740 m_hasCustomPalette = TRUE;
741 m_palette = pal;
742
743 // VZ: can anyone explain me what do we do here?
744 wxWindowDC d((wxWindow *) this);
745 d.SetPalette(pal);
746 }
747
748 wxWindow *wxWindowBase::GetAncestorWithCustomPalette() const
749 {
750 wxWindow *win = (wxWindow *)this;
751 while ( win && !win->HasCustomPalette() )
752 {
753 win = win->GetParent();
754 }
755
756 return win;
757 }
758
759 #endif // wxUSE_PALETTE
760
761 #if wxUSE_CARET
762 void wxWindowBase::SetCaret(wxCaret *caret)
763 {
764 if ( m_caret )
765 {
766 delete m_caret;
767 }
768
769 m_caret = caret;
770
771 if ( m_caret )
772 {
773 wxASSERT_MSG( m_caret->GetWindow() == this,
774 wxT("caret should be created associated to this window") );
775 }
776 }
777 #endif // wxUSE_CARET
778
779 #if wxUSE_VALIDATORS
780 // ----------------------------------------------------------------------------
781 // validators
782 // ----------------------------------------------------------------------------
783
784 void wxWindowBase::SetValidator(const wxValidator& validator)
785 {
786 if ( m_windowValidator )
787 delete m_windowValidator;
788
789 m_windowValidator = (wxValidator *)validator.Clone();
790
791 if ( m_windowValidator )
792 m_windowValidator->SetWindow(this) ;
793 }
794 #endif // wxUSE_VALIDATORS
795
796 // ----------------------------------------------------------------------------
797 // update region stuff
798 // ----------------------------------------------------------------------------
799
800 wxRect wxWindowBase::GetUpdateClientRect() const
801 {
802 wxRegion rgnUpdate = GetUpdateRegion();
803 rgnUpdate.Intersect(GetClientRect());
804 wxRect rectUpdate = rgnUpdate.GetBox();
805 wxPoint ptOrigin = GetClientAreaOrigin();
806 rectUpdate.x -= ptOrigin.x;
807 rectUpdate.y -= ptOrigin.y;
808
809 return rectUpdate;
810 }
811
812 bool wxWindowBase::IsExposed(int x, int y) const
813 {
814 return m_updateRegion.Contains(x, y) != wxOutRegion;
815 }
816
817 bool wxWindowBase::IsExposed(int x, int y, int w, int h) const
818 {
819 return m_updateRegion.Contains(x, y, w, h) != wxOutRegion;
820 }
821
822 // ----------------------------------------------------------------------------
823 // find window by id or name
824 // ----------------------------------------------------------------------------
825
826 wxWindow *wxWindowBase::FindWindow( long id )
827 {
828 if ( id == m_windowId )
829 return (wxWindow *)this;
830
831 wxWindowBase *res = (wxWindow *)NULL;
832 wxWindowList::Node *node;
833 for ( node = m_children.GetFirst(); node && !res; node = node->GetNext() )
834 {
835 wxWindowBase *child = node->GetData();
836 res = child->FindWindow( id );
837 }
838
839 return (wxWindow *)res;
840 }
841
842 wxWindow *wxWindowBase::FindWindow( const wxString& name )
843 {
844 if ( name == m_windowName )
845 return (wxWindow *)this;
846
847 wxWindowBase *res = (wxWindow *)NULL;
848 wxWindowList::Node *node;
849 for ( node = m_children.GetFirst(); node && !res; node = node->GetNext() )
850 {
851 wxWindow *child = node->GetData();
852 res = child->FindWindow(name);
853 }
854
855 return (wxWindow *)res;
856 }
857
858 // ----------------------------------------------------------------------------
859 // dialog oriented functions
860 // ----------------------------------------------------------------------------
861
862 void wxWindowBase::MakeModal(bool modal)
863 {
864 // Disable all other windows
865 if ( IsTopLevel() )
866 {
867 wxWindowList::Node *node = wxTopLevelWindows.GetFirst();
868 while (node)
869 {
870 wxWindow *win = node->GetData();
871 if (win != this)
872 win->Enable(!modal);
873
874 node = node->GetNext();
875 }
876 }
877 }
878
879 bool wxWindowBase::Validate()
880 {
881 #if wxUSE_VALIDATORS
882 bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
883
884 wxWindowList::Node *node;
885 for ( node = m_children.GetFirst(); node; node = node->GetNext() )
886 {
887 wxWindowBase *child = node->GetData();
888 wxValidator *validator = child->GetValidator();
889 if ( validator && !validator->Validate((wxWindow *)this) )
890 {
891 return FALSE;
892 }
893
894 if ( recurse && !child->Validate() )
895 {
896 return FALSE;
897 }
898 }
899 #endif // wxUSE_VALIDATORS
900
901 return TRUE;
902 }
903
904 bool wxWindowBase::TransferDataToWindow()
905 {
906 #if wxUSE_VALIDATORS
907 bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
908
909 wxWindowList::Node *node;
910 for ( node = m_children.GetFirst(); node; node = node->GetNext() )
911 {
912 wxWindowBase *child = node->GetData();
913 wxValidator *validator = child->GetValidator();
914 if ( validator && !validator->TransferToWindow() )
915 {
916 wxLogWarning(_("Could not transfer data to window"));
917 wxLog::FlushActive();
918
919 return FALSE;
920 }
921
922 if ( recurse )
923 {
924 if ( !child->TransferDataToWindow() )
925 {
926 // warning already given
927 return FALSE;
928 }
929 }
930 }
931 #endif // wxUSE_VALIDATORS
932
933 return TRUE;
934 }
935
936 bool wxWindowBase::TransferDataFromWindow()
937 {
938 #if wxUSE_VALIDATORS
939 bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
940
941 wxWindowList::Node *node;
942 for ( node = m_children.GetFirst(); node; node = node->GetNext() )
943 {
944 wxWindow *child = node->GetData();
945 wxValidator *validator = child->GetValidator();
946 if ( validator && !validator->TransferFromWindow() )
947 {
948 // nop warning here because the application is supposed to give
949 // one itself - we don't know here what might have gone wrongly
950
951 return FALSE;
952 }
953
954 if ( recurse )
955 {
956 if ( !child->TransferDataFromWindow() )
957 {
958 // warning already given
959 return FALSE;
960 }
961 }
962 }
963 #endif // wxUSE_VALIDATORS
964
965 return TRUE;
966 }
967
968 void wxWindowBase::InitDialog()
969 {
970 wxInitDialogEvent event(GetId());
971 event.SetEventObject( this );
972 GetEventHandler()->ProcessEvent(event);
973 }
974
975 // ----------------------------------------------------------------------------
976 // context-sensitive help support
977 // ----------------------------------------------------------------------------
978
979 #if wxUSE_HELP
980
981 // associate this help text with this window
982 void wxWindowBase::SetHelpText(const wxString& text)
983 {
984 wxHelpProvider *helpProvider = wxHelpProvider::Get();
985 if ( helpProvider )
986 {
987 helpProvider->AddHelp(this, text);
988 }
989 }
990
991 // associate this help text with all windows with the same id as this
992 // one
993 void wxWindowBase::SetHelpTextForId(const wxString& text)
994 {
995 wxHelpProvider *helpProvider = wxHelpProvider::Get();
996 if ( helpProvider )
997 {
998 helpProvider->AddHelp(GetId(), text);
999 }
1000 }
1001
1002 // get the help string associated with this window (may be empty)
1003 wxString wxWindowBase::GetHelpText() const
1004 {
1005 wxString text;
1006 wxHelpProvider *helpProvider = wxHelpProvider::Get();
1007 if ( helpProvider )
1008 {
1009 text = helpProvider->GetHelp(this);
1010 }
1011
1012 return text;
1013 }
1014
1015 // show help for this window
1016 void wxWindowBase::OnHelp(wxHelpEvent& event)
1017 {
1018 wxHelpProvider *helpProvider = wxHelpProvider::Get();
1019 if ( helpProvider )
1020 {
1021 if ( helpProvider->ShowHelp(this) )
1022 {
1023 // skip the event.Skip() below
1024 return;
1025 }
1026 }
1027
1028 event.Skip();
1029 }
1030
1031 #endif // wxUSE_HELP
1032
1033 // ----------------------------------------------------------------------------
1034 // tooltipsroot.Replace("\\", "/");
1035 // ----------------------------------------------------------------------------
1036
1037 #if wxUSE_TOOLTIPS
1038
1039 void wxWindowBase::SetToolTip( const wxString &tip )
1040 {
1041 // don't create the new tooltip if we already have one
1042 if ( m_tooltip )
1043 {
1044 m_tooltip->SetTip( tip );
1045 }
1046 else
1047 {
1048 SetToolTip( new wxToolTip( tip ) );
1049 }
1050
1051 // setting empty tooltip text does not remove the tooltip any more - use
1052 // SetToolTip((wxToolTip *)NULL) for this
1053 }
1054
1055 void wxWindowBase::DoSetToolTip(wxToolTip *tooltip)
1056 {
1057 if ( m_tooltip )
1058 delete m_tooltip;
1059
1060 m_tooltip = tooltip;
1061 }
1062
1063 #endif // wxUSE_TOOLTIPS
1064
1065 // ----------------------------------------------------------------------------
1066 // constraints and sizers
1067 // ----------------------------------------------------------------------------
1068
1069 #if wxUSE_CONSTRAINTS
1070
1071 void wxWindowBase::SetConstraints( wxLayoutConstraints *constraints )
1072 {
1073 if ( m_constraints )
1074 {
1075 UnsetConstraints(m_constraints);
1076 delete m_constraints;
1077 }
1078 m_constraints = constraints;
1079 if ( m_constraints )
1080 {
1081 // Make sure other windows know they're part of a 'meaningful relationship'
1082 if ( m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this) )
1083 m_constraints->left.GetOtherWindow()->AddConstraintReference(this);
1084 if ( m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this) )
1085 m_constraints->top.GetOtherWindow()->AddConstraintReference(this);
1086 if ( m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this) )
1087 m_constraints->right.GetOtherWindow()->AddConstraintReference(this);
1088 if ( m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this) )
1089 m_constraints->bottom.GetOtherWindow()->AddConstraintReference(this);
1090 if ( m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this) )
1091 m_constraints->width.GetOtherWindow()->AddConstraintReference(this);
1092 if ( m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this) )
1093 m_constraints->height.GetOtherWindow()->AddConstraintReference(this);
1094 if ( m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this) )
1095 m_constraints->centreX.GetOtherWindow()->AddConstraintReference(this);
1096 if ( m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this) )
1097 m_constraints->centreY.GetOtherWindow()->AddConstraintReference(this);
1098 }
1099 }
1100
1101 // This removes any dangling pointers to this window in other windows'
1102 // constraintsInvolvedIn lists.
1103 void wxWindowBase::UnsetConstraints(wxLayoutConstraints *c)
1104 {
1105 if ( c )
1106 {
1107 if ( c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this) )
1108 c->left.GetOtherWindow()->RemoveConstraintReference(this);
1109 if ( c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this) )
1110 c->top.GetOtherWindow()->RemoveConstraintReference(this);
1111 if ( c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this) )
1112 c->right.GetOtherWindow()->RemoveConstraintReference(this);
1113 if ( c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this) )
1114 c->bottom.GetOtherWindow()->RemoveConstraintReference(this);
1115 if ( c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this) )
1116 c->width.GetOtherWindow()->RemoveConstraintReference(this);
1117 if ( c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this) )
1118 c->height.GetOtherWindow()->RemoveConstraintReference(this);
1119 if ( c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this) )
1120 c->centreX.GetOtherWindow()->RemoveConstraintReference(this);
1121 if ( c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this) )
1122 c->centreY.GetOtherWindow()->RemoveConstraintReference(this);
1123 }
1124 }
1125
1126 // Back-pointer to other windows we're involved with, so if we delete this
1127 // window, we must delete any constraints we're involved with.
1128 void wxWindowBase::AddConstraintReference(wxWindowBase *otherWin)
1129 {
1130 if ( !m_constraintsInvolvedIn )
1131 m_constraintsInvolvedIn = new wxWindowList;
1132 if ( !m_constraintsInvolvedIn->Find(otherWin) )
1133 m_constraintsInvolvedIn->Append(otherWin);
1134 }
1135
1136 // REMOVE back-pointer to other windows we're involved with.
1137 void wxWindowBase::RemoveConstraintReference(wxWindowBase *otherWin)
1138 {
1139 if ( m_constraintsInvolvedIn )
1140 m_constraintsInvolvedIn->DeleteObject(otherWin);
1141 }
1142
1143 // Reset any constraints that mention this window
1144 void wxWindowBase::DeleteRelatedConstraints()
1145 {
1146 if ( m_constraintsInvolvedIn )
1147 {
1148 wxWindowList::Node *node = m_constraintsInvolvedIn->GetFirst();
1149 while (node)
1150 {
1151 wxWindow *win = node->GetData();
1152 wxLayoutConstraints *constr = win->GetConstraints();
1153
1154 // Reset any constraints involving this window
1155 if ( constr )
1156 {
1157 constr->left.ResetIfWin(this);
1158 constr->top.ResetIfWin(this);
1159 constr->right.ResetIfWin(this);
1160 constr->bottom.ResetIfWin(this);
1161 constr->width.ResetIfWin(this);
1162 constr->height.ResetIfWin(this);
1163 constr->centreX.ResetIfWin(this);
1164 constr->centreY.ResetIfWin(this);
1165 }
1166
1167 wxWindowList::Node *next = node->GetNext();
1168 delete node;
1169 node = next;
1170 }
1171
1172 delete m_constraintsInvolvedIn;
1173 m_constraintsInvolvedIn = (wxWindowList *) NULL;
1174 }
1175 }
1176
1177 void wxWindowBase::SetSizer(wxSizer *sizer)
1178 {
1179 if (m_windowSizer) delete m_windowSizer;
1180
1181 m_windowSizer = sizer;
1182 }
1183
1184 bool wxWindowBase::Layout()
1185 {
1186 // If there is a sizer, use it instead of the constraints
1187 if ( GetSizer() )
1188 {
1189 int w, h;
1190 GetClientSize(&w, &h);
1191
1192 GetSizer()->SetDimension( 0, 0, w, h );
1193 #if defined __WXPM__
1194 OS2Layout(w, h);
1195 #endif
1196 }
1197 else
1198 {
1199 wxLayoutConstraints *constr = GetConstraints();
1200 bool wasOk = constr && constr->AreSatisfied();
1201
1202 ResetConstraints(); // Mark all constraints as unevaluated
1203
1204 // if we're a top level panel (i.e. our parent is frame/dialog), our
1205 // own constraints will never be satisfied any more unless we do it
1206 // here
1207 if ( wasOk )
1208 {
1209 int noChanges = 1;
1210 while ( noChanges > 0 )
1211 {
1212 constr->SatisfyConstraints(this, &noChanges);
1213 }
1214 }
1215
1216 DoPhase(1); // Layout children
1217 DoPhase(2); // Layout grand children
1218 SetConstraintSizes(); // Recursively set the real window sizes
1219 }
1220
1221 return TRUE;
1222 }
1223
1224
1225 // Do a phase of evaluating constraints: the default behaviour. wxSizers may
1226 // do a similar thing, but also impose their own 'constraints' and order the
1227 // evaluation differently.
1228 bool wxWindowBase::LayoutPhase1(int *noChanges)
1229 {
1230 wxLayoutConstraints *constr = GetConstraints();
1231 if ( constr )
1232 {
1233 return constr->SatisfyConstraints(this, noChanges);
1234 }
1235 else
1236 return TRUE;
1237 }
1238
1239 bool wxWindowBase::LayoutPhase2(int *noChanges)
1240 {
1241 *noChanges = 0;
1242
1243 // Layout children
1244 DoPhase(1);
1245 DoPhase(2);
1246 return TRUE;
1247 }
1248
1249 // Do a phase of evaluating child constraints
1250 bool wxWindowBase::DoPhase(int phase)
1251 {
1252 int noIterations = 0;
1253 int maxIterations = 500;
1254 int noChanges = 1;
1255 int noFailures = 0;
1256 wxWindowList succeeded;
1257 while ((noChanges > 0) && (noIterations < maxIterations))
1258 {
1259 noChanges = 0;
1260 noFailures = 0;
1261 wxWindowList::Node *node = GetChildren().GetFirst();
1262 while (node)
1263 {
1264 wxWindow *child = node->GetData();
1265 if ( !child->IsTopLevel() )
1266 {
1267 wxLayoutConstraints *constr = child->GetConstraints();
1268 if ( constr )
1269 {
1270 if ( !succeeded.Find(child) )
1271 {
1272 int tempNoChanges = 0;
1273 bool success = ( (phase == 1) ? child->LayoutPhase1(&tempNoChanges) : child->LayoutPhase2(&tempNoChanges) ) ;
1274 noChanges += tempNoChanges;
1275 if ( success )
1276 {
1277 succeeded.Append(child);
1278 }
1279 }
1280 }
1281 }
1282 node = node->GetNext();
1283 }
1284
1285 noIterations++;
1286 }
1287
1288 return TRUE;
1289 }
1290
1291 void wxWindowBase::ResetConstraints()
1292 {
1293 wxLayoutConstraints *constr = GetConstraints();
1294 if ( constr )
1295 {
1296 constr->left.SetDone(FALSE);
1297 constr->top.SetDone(FALSE);
1298 constr->right.SetDone(FALSE);
1299 constr->bottom.SetDone(FALSE);
1300 constr->width.SetDone(FALSE);
1301 constr->height.SetDone(FALSE);
1302 constr->centreX.SetDone(FALSE);
1303 constr->centreY.SetDone(FALSE);
1304 }
1305
1306 wxWindowList::Node *node = GetChildren().GetFirst();
1307 while (node)
1308 {
1309 wxWindow *win = node->GetData();
1310 if ( !win->IsTopLevel() )
1311 win->ResetConstraints();
1312 node = node->GetNext();
1313 }
1314 }
1315
1316 // Need to distinguish between setting the 'fake' size for windows and sizers,
1317 // and setting the real values.
1318 void wxWindowBase::SetConstraintSizes(bool recurse)
1319 {
1320 wxLayoutConstraints *constr = GetConstraints();
1321 if ( constr && constr->AreSatisfied() )
1322 {
1323 int x = constr->left.GetValue();
1324 int y = constr->top.GetValue();
1325 int w = constr->width.GetValue();
1326 int h = constr->height.GetValue();
1327
1328 if ( (constr->width.GetRelationship() != wxAsIs ) ||
1329 (constr->height.GetRelationship() != wxAsIs) )
1330 {
1331 SetSize(x, y, w, h);
1332 }
1333 else
1334 {
1335 // If we don't want to resize this window, just move it...
1336 Move(x, y);
1337 }
1338 }
1339 else if ( constr )
1340 {
1341 wxLogDebug(wxT("Constraints not satisfied for %s named '%s'."),
1342 GetClassInfo()->GetClassName(),
1343 GetName().c_str());
1344 }
1345
1346 if ( recurse )
1347 {
1348 wxWindowList::Node *node = GetChildren().GetFirst();
1349 while (node)
1350 {
1351 wxWindow *win = node->GetData();
1352 if ( !win->IsTopLevel() && win->GetConstraints() )
1353 win->SetConstraintSizes();
1354 node = node->GetNext();
1355 }
1356 }
1357 }
1358
1359 // Only set the size/position of the constraint (if any)
1360 void wxWindowBase::SetSizeConstraint(int x, int y, int w, int h)
1361 {
1362 wxLayoutConstraints *constr = GetConstraints();
1363 if ( constr )
1364 {
1365 if ( x != -1 )
1366 {
1367 constr->left.SetValue(x);
1368 constr->left.SetDone(TRUE);
1369 }
1370 if ( y != -1 )
1371 {
1372 constr->top.SetValue(y);
1373 constr->top.SetDone(TRUE);
1374 }
1375 if ( w != -1 )
1376 {
1377 constr->width.SetValue(w);
1378 constr->width.SetDone(TRUE);
1379 }
1380 if ( h != -1 )
1381 {
1382 constr->height.SetValue(h);
1383 constr->height.SetDone(TRUE);
1384 }
1385 }
1386 }
1387
1388 void wxWindowBase::MoveConstraint(int x, int y)
1389 {
1390 wxLayoutConstraints *constr = GetConstraints();
1391 if ( constr )
1392 {
1393 if ( x != -1 )
1394 {
1395 constr->left.SetValue(x);
1396 constr->left.SetDone(TRUE);
1397 }
1398 if ( y != -1 )
1399 {
1400 constr->top.SetValue(y);
1401 constr->top.SetDone(TRUE);
1402 }
1403 }
1404 }
1405
1406 void wxWindowBase::GetSizeConstraint(int *w, int *h) const
1407 {
1408 wxLayoutConstraints *constr = GetConstraints();
1409 if ( constr )
1410 {
1411 *w = constr->width.GetValue();
1412 *h = constr->height.GetValue();
1413 }
1414 else
1415 GetSize(w, h);
1416 }
1417
1418 void wxWindowBase::GetClientSizeConstraint(int *w, int *h) const
1419 {
1420 wxLayoutConstraints *constr = GetConstraints();
1421 if ( constr )
1422 {
1423 *w = constr->width.GetValue();
1424 *h = constr->height.GetValue();
1425 }
1426 else
1427 GetClientSize(w, h);
1428 }
1429
1430 void wxWindowBase::AdjustForParentClientOrigin(int& x, int& y, int sizeFlags)
1431 {
1432 // don't do it for the dialogs/frames - they float independently of their
1433 // parent
1434 if ( !IsTopLevel() )
1435 {
1436 wxWindow *parent = GetParent();
1437 if ( !(sizeFlags & wxSIZE_NO_ADJUSTMENTS) && parent )
1438 {
1439 wxPoint pt(parent->GetClientAreaOrigin());
1440 x += pt.x;
1441 y += pt.y;
1442 }
1443 }
1444 }
1445
1446
1447 void wxWindowBase::GetPositionConstraint(int *x, int *y) const
1448 {
1449 wxLayoutConstraints *constr = GetConstraints();
1450 if ( constr )
1451 {
1452 *x = constr->left.GetValue();
1453 *y = constr->top.GetValue();
1454 }
1455 else
1456 GetPosition(x, y);
1457 }
1458
1459 #endif // wxUSE_CONSTRAINTS
1460
1461 // ----------------------------------------------------------------------------
1462 // do Update UI processing for child controls
1463 // ----------------------------------------------------------------------------
1464
1465 // TODO: should this be implemented for the child window rather
1466 // than the parent? Then you can override it e.g. for wxCheckBox
1467 // to do the Right Thing rather than having to assume a fixed number
1468 // of control classes.
1469 void wxWindowBase::UpdateWindowUI()
1470 {
1471 #if wxUSE_CONTROLS
1472 wxUpdateUIEvent event(GetId());
1473 event.m_eventObject = this;
1474
1475 if ( GetEventHandler()->ProcessEvent(event) )
1476 {
1477 if ( event.GetSetEnabled() )
1478 Enable(event.GetEnabled());
1479
1480 if ( event.GetSetText() )
1481 {
1482 wxControl *control = wxDynamicCastThis(wxControl);
1483 if ( control )
1484 {
1485 #if wxUSE_TEXTCTRL
1486 wxTextCtrl *text = wxDynamicCast(control, wxTextCtrl);
1487 if ( text )
1488 text->SetValue(event.GetText());
1489 else
1490 #endif // wxUSE_TEXTCTRL
1491 control->SetLabel(event.GetText());
1492 }
1493 }
1494
1495 #if wxUSE_CHECKBOX
1496 wxCheckBox *checkbox = wxDynamicCastThis(wxCheckBox);
1497 if ( checkbox )
1498 {
1499 if ( event.GetSetChecked() )
1500 checkbox->SetValue(event.GetChecked());
1501 }
1502 #endif // wxUSE_CHECKBOX
1503
1504 #if wxUSE_RADIOBTN
1505 wxRadioButton *radiobtn = wxDynamicCastThis(wxRadioButton);
1506 if ( radiobtn )
1507 {
1508 if ( event.GetSetChecked() )
1509 radiobtn->SetValue(event.GetChecked());
1510 }
1511 #endif // wxUSE_RADIOBTN
1512 }
1513 #endif // wxUSE_CONTROLS
1514 }
1515
1516 // ----------------------------------------------------------------------------
1517 // dialog units translations
1518 // ----------------------------------------------------------------------------
1519
1520 wxPoint wxWindowBase::ConvertPixelsToDialog(const wxPoint& pt)
1521 {
1522 int charWidth = GetCharWidth();
1523 int charHeight = GetCharHeight();
1524 wxPoint pt2(-1, -1);
1525 if (pt.x != -1)
1526 pt2.x = (int) ((pt.x * 4) / charWidth) ;
1527 if (pt.y != -1)
1528 pt2.y = (int) ((pt.y * 8) / charHeight) ;
1529
1530 return pt2;
1531 }
1532
1533 wxPoint wxWindowBase::ConvertDialogToPixels(const wxPoint& pt)
1534 {
1535 int charWidth = GetCharWidth();
1536 int charHeight = GetCharHeight();
1537 wxPoint pt2(-1, -1);
1538 if (pt.x != -1)
1539 pt2.x = (int) ((pt.x * charWidth) / 4) ;
1540 if (pt.y != -1)
1541 pt2.y = (int) ((pt.y * charHeight) / 8) ;
1542
1543 return pt2;
1544 }
1545
1546 // ----------------------------------------------------------------------------
1547 // event handlers
1548 // ----------------------------------------------------------------------------
1549
1550 // propagate the colour change event to the subwindows
1551 void wxWindowBase::OnSysColourChanged(wxSysColourChangedEvent& event)
1552 {
1553 wxWindowList::Node *node = GetChildren().GetFirst();
1554 while ( node )
1555 {
1556 // Only propagate to non-top-level windows
1557 wxWindow *win = node->GetData();
1558 if ( !win->IsTopLevel() )
1559 {
1560 wxSysColourChangedEvent event2;
1561 event.m_eventObject = win;
1562 win->GetEventHandler()->ProcessEvent(event2);
1563 }
1564
1565 node = node->GetNext();
1566 }
1567 }
1568
1569 // the default action is to populate dialog with data when it's created
1570 void wxWindowBase::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) )
1571 {
1572 TransferDataToWindow();
1573 }
1574
1575 // process Ctrl-Alt-mclick
1576 void wxWindowBase::OnMiddleClick( wxMouseEvent& event )
1577 {
1578 #if wxUSE_MSGDLG
1579 if ( event.ControlDown() && event.AltDown() )
1580 {
1581 // don't translate these strings
1582 wxString port;
1583
1584 #ifdef __WXUNIVERSAL__
1585 port = _T("Univ/");
1586 #endif // __WXUNIVERSAL__
1587
1588 switch ( wxGetOsVersion() )
1589 {
1590 case wxMOTIF_X: port = _T("Motif"); break;
1591 case wxMAC:
1592 case wxMAC_DARWIN: port = _T("Mac"); break;
1593 case wxBEOS: port = _T("BeOS"); break;
1594 case wxGTK:
1595 case wxGTK_WIN32:
1596 case wxGTK_OS2:
1597 case wxGTK_BEOS: port = _T("GTK"); break;
1598 case wxWINDOWS:
1599 case wxPENWINDOWS:
1600 case wxWINDOWS_NT:
1601 case wxWIN32S:
1602 case wxWIN95:
1603 case wxWIN386: port = _T("MS Windows"); break;
1604 case wxMGL_UNIX:
1605 case wxMGL_X:
1606 case wxMGL_WIN32:
1607 case wxMGL_OS2: port = _T("MGL"); break;
1608 case wxWINDOWS_OS2:
1609 case wxOS2_PM: port = _T("OS/2"); break;
1610 default: port = _T("unknown"); break;
1611 }
1612
1613 wxMessageBox(wxString::Format(
1614 _T(
1615 " wxWindows Library (%s port)\nVersion %u.%u.%u%s, compiled at %s %s\n Copyright (c) 1995-2002 wxWindows team"
1616 ),
1617 port.c_str(),
1618 wxMAJOR_VERSION,
1619 wxMINOR_VERSION,
1620 wxRELEASE_NUMBER,
1621 #if wxUSE_UNICODE
1622 L" (Unicode)",
1623 #else
1624 "",
1625 #endif
1626 __TDATE__,
1627 __TTIME__
1628 ),
1629 _T("wxWindows information"),
1630 wxICON_INFORMATION | wxOK,
1631 (wxWindow *)this);
1632 }
1633 else
1634 #endif // wxUSE_MSGDLG
1635 {
1636 event.Skip();
1637 }
1638 }
1639
1640 // ----------------------------------------------------------------------------
1641 // list classes implementation
1642 // ----------------------------------------------------------------------------
1643
1644 void wxWindowListNode::DeleteData()
1645 {
1646 delete (wxWindow *)GetData();
1647 }
1648
1649 // ----------------------------------------------------------------------------
1650 // borders
1651 // ----------------------------------------------------------------------------
1652
1653 wxBorder wxWindowBase::GetBorder() const
1654 {
1655 wxBorder border = (wxBorder)(m_windowStyle & wxBORDER_MASK);
1656 if ( border == wxBORDER_DEFAULT )
1657 {
1658 border = GetDefaultBorder();
1659 }
1660
1661 return border;
1662 }
1663
1664 wxBorder wxWindowBase::GetDefaultBorder() const
1665 {
1666 return wxBORDER_NONE;
1667 }
1668
1669 // ----------------------------------------------------------------------------
1670 // hit testing
1671 // ----------------------------------------------------------------------------
1672
1673 wxHitTest wxWindowBase::DoHitTest(wxCoord x, wxCoord y) const
1674 {
1675 // here we just check if the point is inside the window or not
1676
1677 // check the top and left border first
1678 bool outside = x < 0 || y < 0;
1679 if ( !outside )
1680 {
1681 // check the right and bottom borders too
1682 wxSize size = GetSize();
1683 outside = x >= size.x || y >= size.y;
1684 }
1685
1686 return outside ? wxHT_WINDOW_OUTSIDE : wxHT_WINDOW_INSIDE;
1687 }
1688
1689 // ----------------------------------------------------------------------------
1690 // mouse capture
1691 // ----------------------------------------------------------------------------
1692
1693 struct WXDLLEXPORT wxWindowNext
1694 {
1695 wxWindow *win;
1696 wxWindowNext *next;
1697 } *wxWindowBase::ms_winCaptureNext = NULL;
1698
1699 void wxWindowBase::CaptureMouse()
1700 {
1701 wxLogTrace(_T("mousecapture"), _T("CaptureMouse(0x%08x)"), this);
1702
1703 wxWindow *winOld = GetCapture();
1704 if ( winOld )
1705 {
1706 // save it on stack
1707 wxWindowNext *item = new wxWindowNext;
1708 item->win = winOld;
1709 item->next = ms_winCaptureNext;
1710 ms_winCaptureNext = item;
1711 }
1712 //else: no mouse capture to save
1713
1714 DoCaptureMouse();
1715 }
1716
1717 void wxWindowBase::ReleaseMouse()
1718 {
1719 wxLogTrace(_T("mousecapture"), _T("ReleaseMouse(0x%08x)"), this);
1720
1721 wxASSERT_MSG( GetCapture() == this, wxT("attempt to release mouse, but this window hasn't captured it") )
1722
1723 DoReleaseMouse();
1724
1725 if ( ms_winCaptureNext )
1726 {
1727 ms_winCaptureNext->win->CaptureMouse();
1728
1729 wxWindowNext *item = ms_winCaptureNext;
1730 ms_winCaptureNext = item->next;
1731 delete item;
1732 }
1733 //else: stack is empty, no previous capture
1734
1735 wxLogTrace(_T("mousecapture"),
1736 _T("After ReleaseMouse() mouse is captured by 0x%08x"),
1737 GetCapture());
1738 }
1739