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