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