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