]> git.saurik.com Git - wxWidgets.git/blame - src/common/wincmn.cpp
compilation fix after wxBitmap image changes
[wxWidgets.git] / src / common / wincmn.cpp
CommitLineData
7ec1983b 1/////////////////////////////////////////////////////////////////////////////
7ec69821 2// Name: src/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$
77ffb593 8// Copyright: (c) wxWidgets team
65571936 9// Licence: wxWindows licence
7ec1983b
VZ
10/////////////////////////////////////////////////////////////////////////////
11
f03fc89f
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
f701d7ab 19
341287bf
JS
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
f701d7ab 23#ifdef __BORLANDC__
f03fc89f 24 #pragma hdrstop
f701d7ab
JS
25#endif
26
f03fc89f
VZ
27#ifndef WX_PRECOMP
28 #include "wx/string.h"
29 #include "wx/log.h"
30 #include "wx/intl.h"
31 #include "wx/frame.h"
f03fc89f 32 #include "wx/window.h"
1e6feb95 33 #include "wx/control.h"
f03fc89f
VZ
34 #include "wx/checkbox.h"
35 #include "wx/radiobut.h"
106844da 36 #include "wx/statbox.h"
26bf1ce0 37 #include "wx/textctrl.h"
f03fc89f
VZ
38 #include "wx/settings.h"
39 #include "wx/dialog.h"
a02dc3e3 40 #include "wx/msgdlg.h"
1b942d5f 41 #include "wx/msgout.h"
a37a5a73 42 #include "wx/statusbr.h"
e0cf3745 43 #include "wx/toolbar.h"
ed39ff57 44 #include "wx/dcclient.h"
7d59475e 45 #include "wx/scrolbar.h"
f03fc89f 46 #include "wx/layout.h"
ed2fbeb8 47 #include "wx/sizer.h"
8515098c 48 #include "wx/menu.h"
ed2fbeb8 49#endif //WX_PRECOMP
461e93f9 50
f03fc89f
VZ
51#if wxUSE_DRAG_AND_DROP
52 #include "wx/dnd.h"
53#endif // wxUSE_DRAG_AND_DROP
54
ed5317e5 55#if wxUSE_ACCESSIBILITY
7de59551 56 #include "wx/access.h"
ed5317e5
JS
57#endif
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
ff9f7a12 71#if wxUSE_SYSTEM_OPTIONS
cab1a605 72 #include "wx/sysopt.h"
ff9f7a12
SC
73#endif
74
8bb6b2c0
VZ
75#include "wx/platinfo.h"
76
e7445ff8
PC
77// Windows List
78WXDLLIMPEXP_DATA_CORE(wxWindowList) wxTopLevelWindows;
79
eeb0bee1 80// globals
8bb08801 81#if wxUSE_MENUS
eeb0bee1 82wxMenu *wxCurrentPopupMenu = NULL;
8bb08801 83#endif // wxUSE_MENUS
eeb0bee1 84
f03fc89f
VZ
85// ----------------------------------------------------------------------------
86// static data
87// ----------------------------------------------------------------------------
88
f03fc89f
VZ
89
90IMPLEMENT_ABSTRACT_CLASS(wxWindowBase, wxEvtHandler)
91
92// ----------------------------------------------------------------------------
93// event table
94// ----------------------------------------------------------------------------
95
96BEGIN_EVENT_TABLE(wxWindowBase, wxEvtHandler)
97 EVT_SYS_COLOUR_CHANGED(wxWindowBase::OnSysColourChanged)
98 EVT_INIT_DIALOG(wxWindowBase::OnInitDialog)
a02dc3e3 99 EVT_MIDDLE_DOWN(wxWindowBase::OnMiddleClick)
bd83cb56
VZ
100
101#if wxUSE_HELP
e11f4636 102 EVT_HELP(wxID_ANY, wxWindowBase::OnHelp)
bd83cb56
VZ
103#endif // wxUSE_HELP
104
6528a7f1 105 EVT_SIZE(wxWindowBase::InternalOnSize)
f03fc89f
VZ
106END_EVENT_TABLE()
107
108// ============================================================================
109// implementation of the common functionality of the wxWindow class
110// ============================================================================
111
112// ----------------------------------------------------------------------------
113// initialization
114// ----------------------------------------------------------------------------
115
116// the default initialization
72795335 117wxWindowBase::wxWindowBase()
f03fc89f
VZ
118{
119 // no window yet, no parent nor children
d3b9f782 120 m_parent = NULL;
e11f4636 121 m_windowId = wxID_ANY;
f03fc89f
VZ
122
123 // no constraints on the minimal window size
124 m_minWidth =
422d0ff0 125 m_maxWidth = wxDefaultCoord;
f03fc89f 126 m_minHeight =
422d0ff0 127 m_maxHeight = wxDefaultCoord;
f03fc89f 128
9f884528
RD
129 // invalidiated cache value
130 m_bestSizeCache = wxDefaultSize;
131
eefe6d4b
VZ
132 // window are created enabled and visible by default
133 m_isShown =
e11f4636 134 m_isEnabled = true;
f03fc89f 135
f03fc89f
VZ
136 // the default event handler is just this window
137 m_eventHandler = this;
138
88ac883a 139#if wxUSE_VALIDATORS
f03fc89f 140 // no validator
d3b9f782 141 m_windowValidator = NULL;
88ac883a 142#endif // wxUSE_VALIDATORS
f03fc89f 143
1b69c815
VZ
144 // the colours/fonts are default for now, so leave m_font,
145 // m_backgroundColour and m_foregroundColour uninitialized and set those
08df3e44
VZ
146 m_hasBgCol =
147 m_hasFgCol =
e11f4636 148 m_hasFont = false;
f8ff87ed
VS
149 m_inheritBgCol =
150 m_inheritFgCol =
151 m_inheritFont = false;
e11f4636 152
f03fc89f 153 // no style bits
d80cd92a 154 m_exStyle =
f03fc89f 155 m_windowStyle = 0;
cab1a605 156
9c61c5b0 157 m_backgroundStyle = wxBG_STYLE_ERASE;
f03fc89f 158
f03fc89f
VZ
159#if wxUSE_CONSTRAINTS
160 // no constraints whatsoever
d3b9f782
VZ
161 m_constraints = NULL;
162 m_constraintsInvolvedIn = NULL;
461e93f9
JS
163#endif // wxUSE_CONSTRAINTS
164
d3b9f782
VZ
165 m_windowSizer = NULL;
166 m_containingSizer = NULL;
e11f4636 167 m_autoLayout = false;
f03fc89f
VZ
168
169#if wxUSE_DRAG_AND_DROP
d3b9f782 170 m_dropTarget = NULL;
f03fc89f
VZ
171#endif // wxUSE_DRAG_AND_DROP
172
173#if wxUSE_TOOLTIPS
d3b9f782 174 m_tooltip = NULL;
f03fc89f 175#endif // wxUSE_TOOLTIPS
789295bf
VZ
176
177#if wxUSE_CARET
d3b9f782 178 m_caret = NULL;
789295bf 179#endif // wxUSE_CARET
a2d93e73 180
574c939e 181#if wxUSE_PALETTE
e11f4636 182 m_hasCustomPalette = false;
574c939e
KB
183#endif // wxUSE_PALETTE
184
ed5317e5
JS
185#if wxUSE_ACCESSIBILITY
186 m_accessible = NULL;
187#endif
188
566d84a7 189 m_virtualSize = wxDefaultSize;
1b69c815 190
d3b9f782 191 m_scrollHelper = NULL;
f4fe2f20 192
1b69c815 193 m_windowVariant = wxWINDOW_VARIANT_NORMAL;
ff9f7a12
SC
194#if wxUSE_SYSTEM_OPTIONS
195 if ( wxSystemOptions::HasOption(wxWINDOW_DEFAULT_VARIANT) )
196 {
197 m_windowVariant = (wxWindowVariant) wxSystemOptions::GetOptionInt( wxWINDOW_DEFAULT_VARIANT ) ;
198 }
199#endif
69d90995 200
a2d93e73 201 // Whether we're using the current theme for this window (wxGTK only for now)
e11f4636 202 m_themeEnabled = false;
1b69c815 203
c6212a0c
VZ
204 // This is set to true by SendDestroyEvent() which should be called by the
205 // most derived class to ensure that the destruction event is sent as soon
206 // as possible to allow its handlers to still see the undestroyed window
1b69c815 207 m_isBeingDeleted = false;
17808a75
VZ
208
209 m_freezeCount = 0;
f03fc89f
VZ
210}
211
212// common part of window creation process
213bool wxWindowBase::CreateBase(wxWindowBase *parent,
214 wxWindowID id,
74e3313b 215 const wxPoint& WXUNUSED(pos),
400a9e41 216 const wxSize& WXUNUSED(size),
f03fc89f 217 long style,
ac8d0c11 218 const wxValidator& wxVALIDATOR_PARAM(validator),
f03fc89f
VZ
219 const wxString& name)
220{
925f154d
VZ
221 // ids are limited to 16 bits under MSW so if you care about portability,
222 // it's not a good idea to use ids out of this range (and negative ids are
77ffb593 223 // reserved for wxWidgets own usage)
f35fdf7e
VZ
224 wxASSERT_MSG( id == wxID_ANY || (id >= 0 && id < 32767) ||
225 (id >= wxID_AUTO_LOWEST && id <= wxID_AUTO_HIGHEST),
925f154d
VZ
226 _T("invalid id value") );
227
f03fc89f 228 // generate a new id if the user doesn't care about it
f35fdf7e
VZ
229 if ( id == wxID_ANY )
230 {
231 m_windowId = NewControlId();
f35fdf7e
VZ
232 }
233 else // valid id specified
234 {
235 m_windowId = id;
236 }
f03fc89f 237
e96248c4
VZ
238 // don't use SetWindowStyleFlag() here, this function should only be called
239 // to change the flag after creation as it tries to reflect the changes in
240 // flags by updating the window dynamically and we don't need this here
241 m_windowStyle = style;
242
f03fc89f 243 SetName(name);
f03fc89f 244 SetParent(parent);
674ac8b9
VZ
245
246#if wxUSE_VALIDATORS
8d99be5f 247 SetValidator(validator);
674ac8b9 248#endif // wxUSE_VALIDATORS
f03fc89f 249
8ae6ce07
VZ
250 // if the parent window has wxWS_EX_VALIDATE_RECURSIVELY set, we want to
251 // have it too - like this it's possible to set it only in the top level
252 // dialog/frame and all children will inherit it by defult
253 if ( parent && (parent->GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) )
254 {
9cb98d89 255 SetExtraStyle(GetExtraStyle() | wxWS_EX_VALIDATE_RECURSIVELY);
8ae6ce07
VZ
256 }
257
e11f4636 258 return true;
f03fc89f
VZ
259}
260
d63312a9
VZ
261bool wxWindowBase::ToggleWindowStyle(int flag)
262{
263 wxASSERT_MSG( flag, _T("flags with 0 value can't be toggled") );
264
265 bool rc;
266 long style = GetWindowStyleFlag();
267 if ( style & flag )
268 {
269 style &= ~flag;
270 rc = false;
271 }
272 else // currently off
273 {
274 style |= flag;
275 rc = true;
276 }
277
278 SetWindowStyleFlag(style);
279
280 return rc;
281}
282
f03fc89f
VZ
283// ----------------------------------------------------------------------------
284// destruction
285// ----------------------------------------------------------------------------
286
287// common clean up
288wxWindowBase::~wxWindowBase()
289{
349d1942
VS
290 wxASSERT_MSG( GetCapture() != this, wxT("attempt to destroy window with mouse capture") );
291
f03fc89f
VZ
292 // FIXME if these 2 cases result from programming errors in the user code
293 // we should probably assert here instead of silently fixing them
294
295 // Just in case the window has been Closed, but we're then deleting
296 // immediately: don't leave dangling pointers.
297 wxPendingDelete.DeleteObject(this);
298
299 // Just in case we've loaded a top-level window via LoadNativeDialog but
300 // we weren't a dialog class
222ed1d6 301 wxTopLevelWindows.DeleteObject((wxWindow*)this);
a23fd0e1 302
3bc9aac0 303#if wxUSE_MENUS
eeb0bee1
VZ
304 // The associated popup menu can still be alive, disassociate from it in
305 // this case
306 if ( wxCurrentPopupMenu && wxCurrentPopupMenu->GetInvokingWindow() == this )
307 wxCurrentPopupMenu->SetInvokingWindow(NULL);
3bc9aac0 308#endif // wxUSE_MENUS
eeb0bee1 309
223d09f6 310 wxASSERT_MSG( GetChildren().GetCount() == 0, wxT("children not destroyed") );
f03fc89f 311
f8ab85ae 312 // notify the parent about this window destruction
f09df8b2 313 if ( m_parent )
8e35ab96 314 m_parent->RemoveChild(this);
8e35ab96 315
789295bf 316#if wxUSE_CARET
a2b436fb 317 delete m_caret;
789295bf
VZ
318#endif // wxUSE_CARET
319
88ac883a 320#if wxUSE_VALIDATORS
a2b436fb 321 delete m_windowValidator;
88ac883a 322#endif // wxUSE_VALIDATORS
f03fc89f 323
f03fc89f
VZ
324#if wxUSE_CONSTRAINTS
325 // Have to delete constraints/sizer FIRST otherwise sizers may try to look
326 // at deleted windows as they delete themselves.
327 DeleteRelatedConstraints();
328
329 if ( m_constraints )
330 {
331 // This removes any dangling pointers to this window in other windows'
332 // constraintsInvolvedIn lists.
333 UnsetConstraints(m_constraints);
334 delete m_constraints;
335 m_constraints = NULL;
336 }
461e93f9
JS
337#endif // wxUSE_CONSTRAINTS
338
be90c029 339 if ( m_containingSizer )
12a3f227 340 m_containingSizer->Detach( (wxWindow*)this );
be90c029 341
a2b436fb 342 delete m_windowSizer;
f03fc89f 343
f03fc89f 344#if wxUSE_DRAG_AND_DROP
a2b436fb 345 delete m_dropTarget;
f03fc89f
VZ
346#endif // wxUSE_DRAG_AND_DROP
347
348#if wxUSE_TOOLTIPS
a2b436fb 349 delete m_tooltip;
f03fc89f 350#endif // wxUSE_TOOLTIPS
b0ee47ff 351
ed5317e5 352#if wxUSE_ACCESSIBILITY
a2b436fb 353 delete m_accessible;
ed5317e5 354#endif
d18d8bda
VS
355
356#if wxUSE_HELP
357 // NB: this has to be called unconditionally, because we don't know
358 // whether this window has associated help text or not
359 wxHelpProvider *helpProvider = wxHelpProvider::Get();
360 if ( helpProvider )
361 helpProvider->RemoveHelp(this);
362#endif
f03fc89f
VZ
363}
364
a3ac93e3
VZ
365bool wxWindowBase::IsBeingDeleted() const
366{
367 return m_isBeingDeleted ||
368 (!IsTopLevel() && m_parent && m_parent->IsBeingDeleted());
369}
370
602a2e02
VZ
371void wxWindowBase::SendDestroyEvent()
372{
c6212a0c
VZ
373 if ( m_isBeingDeleted )
374 {
375 // we could have been already called from a more derived class dtor,
376 // e.g. ~wxTLW calls us and so does ~wxWindow and the latter call
377 // should be simply ignored
378 return;
379 }
380
381 m_isBeingDeleted = true;
382
602a2e02
VZ
383 wxWindowDestroyEvent event;
384 event.SetEventObject(this);
385 event.SetId(GetId());
386 GetEventHandler()->ProcessEvent(event);
387}
388
f03fc89f
VZ
389bool wxWindowBase::Destroy()
390{
a79a6671
VZ
391 SendDestroyEvent();
392
f03fc89f
VZ
393 delete this;
394
e11f4636 395 return true;
f03fc89f
VZ
396}
397
398bool wxWindowBase::Close(bool force)
399{
400 wxCloseEvent event(wxEVT_CLOSE_WINDOW, m_windowId);
401 event.SetEventObject(this);
f03fc89f
VZ
402 event.SetCanVeto(!force);
403
e11f4636 404 // return false if window wasn't closed because the application vetoed the
f03fc89f 405 // close event
a50c5fcc 406 return HandleWindowEvent(event) && !event.GetVeto();
f03fc89f
VZ
407}
408
409bool wxWindowBase::DestroyChildren()
410{
222ed1d6 411 wxWindowList::compatibility_iterator node;
a23fd0e1 412 for ( ;; )
f03fc89f 413 {
a23fd0e1
VZ
414 // we iterate until the list becomes empty
415 node = GetChildren().GetFirst();
416 if ( !node )
417 break;
418
f03fc89f 419 wxWindow *child = node->GetData();
a23fd0e1 420
a79a6671
VZ
421 // note that we really want to delete it immediately so don't call the
422 // possible overridden Destroy() version which might not delete the
423 // child immediately resulting in problems with our (top level) child
424 // outliving its parent
425 child->wxWindowBase::Destroy();
a23fd0e1
VZ
426
427 wxASSERT_MSG( !GetChildren().Find(child),
223d09f6 428 wxT("child didn't remove itself using RemoveChild()") );
f03fc89f
VZ
429 }
430
e11f4636 431 return true;
f03fc89f
VZ
432}
433
434// ----------------------------------------------------------------------------
f68586e5 435// size/position related methods
f03fc89f
VZ
436// ----------------------------------------------------------------------------
437
438// centre the window with respect to its parent in either (or both) directions
1f464296 439void wxWindowBase::DoCentre(int dir)
f03fc89f 440{
1f464296
VZ
441 wxCHECK_RET( !(dir & wxCENTRE_ON_SCREEN) && GetParent(),
442 _T("this method only implements centering child windows") );
ef397583 443
1f464296 444 SetSize(GetRect().CentreIn(GetParent()->GetClientSize(), dir));
7631a292
RD
445}
446
f03fc89f
VZ
447// fits the window around the children
448void wxWindowBase::Fit()
449{
74205969 450 if ( !GetChildren().empty() )
f68586e5 451 {
1736f021 452 SetSize(GetBestSize());
f68586e5
VZ
453 }
454 //else: do nothing if we have no children
455}
f03fc89f 456
2b5f62a0
VZ
457// fits virtual size (ie. scrolled area etc.) around children
458void wxWindowBase::FitInside()
459{
460 if ( GetChildren().GetCount() > 0 )
461 {
462 SetVirtualSize( GetBestVirtualSize() );
463 }
464}
465
7d59475e 466// On Mac, scrollbars are explicitly children.
d7928233 467#if defined( __WXMAC__ ) && !defined(__WXUNIVERSAL__)
7d59475e
JS
468static bool wxHasRealChildren(const wxWindowBase* win)
469{
470 int realChildCount = 0;
cab1a605 471
7d59475e
JS
472 for ( wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst();
473 node;
474 node = node->GetNext() )
475 {
476 wxWindow *win = node->GetData();
477 if ( !win->IsTopLevel() && win->IsShown() && !win->IsKindOf(CLASSINFO(wxScrollBar)))
478 realChildCount ++;
479 }
480 return (realChildCount > 0);
481}
482#endif
ba889513 483
992b2ec4
VS
484void wxWindowBase::InvalidateBestSize()
485{
486 m_bestSizeCache = wxDefaultSize;
487
488 // parent's best size calculation may depend on its children's
5b7df27e
WS
489 // as long as child window we are in is not top level window itself
490 // (because the TLW size is never resized automatically)
491 // so let's invalidate it as well to be safe:
5ff84587 492 if (m_parent && !IsTopLevel())
992b2ec4
VS
493 m_parent->InvalidateBestSize();
494}
7d59475e 495
f68586e5
VZ
496// return the size best suited for the current window
497wxSize wxWindowBase::DoGetBestSize() const
498{
08a19f64 499 wxSize best;
2997ca30 500
ec5bb70d
VZ
501 if ( m_windowSizer )
502 {
7e0f7539 503 best = m_windowSizer->GetMinSize();
ec5bb70d
VZ
504 }
505#if wxUSE_CONSTRAINTS
506 else if ( m_constraints )
507 {
508 wxConstCast(this, wxWindowBase)->SatisfyConstraints();
509
510 // our minimal acceptable size is such that all our windows fit inside
511 int maxX = 0,
512 maxY = 0;
513
222ed1d6 514 for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
ec5bb70d
VZ
515 node;
516 node = node->GetNext() )
517 {
518 wxLayoutConstraints *c = node->GetData()->GetConstraints();
519 if ( !c )
520 {
521 // it's not normal that we have an unconstrained child, but
522 // what can we do about it?
523 continue;
524 }
525
526 int x = c->right.GetValue(),
527 y = c->bottom.GetValue();
528
529 if ( x > maxX )
530 maxX = x;
531
532 if ( y > maxY )
533 maxY = y;
534
535 // TODO: we must calculate the overlaps somehow, otherwise we
536 // will never return a size bigger than the current one :-(
537 }
538
08a19f64 539 best = wxSize(maxX, maxY);
ec5bb70d
VZ
540 }
541#endif // wxUSE_CONSTRAINTS
7d59475e 542 else if ( !GetChildren().empty()
d7928233 543#if defined( __WXMAC__ ) && !defined(__WXUNIVERSAL__)
7d59475e
JS
544 && wxHasRealChildren(this)
545#endif
546 )
f03fc89f 547 {
54af2461
VZ
548 // our minimal acceptable size is such that all our visible child
549 // windows fit inside
f68586e5
VZ
550 int maxX = 0,
551 maxY = 0;
552
222ed1d6 553 for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
f68586e5
VZ
554 node;
555 node = node->GetNext() )
42e69d6b 556 {
f68586e5 557 wxWindow *win = node->GetData();
54af2461
VZ
558 if ( win->IsTopLevel()
559 || !win->IsShown()
1e6feb95 560#if wxUSE_STATUSBAR
54af2461 561 || wxDynamicCast(win, wxStatusBar)
1e6feb95
VZ
562#endif // wxUSE_STATUSBAR
563 )
f68586e5
VZ
564 {
565 // dialogs and frames lie in different top level windows -
7d9fd004
VZ
566 // don't deal with them here; as for the status bars, they
567 // don't lie in the client area at all
f68586e5
VZ
568 continue;
569 }
570
571 int wx, wy, ww, wh;
572 win->GetPosition(&wx, &wy);
3f5513f5
VZ
573
574 // if the window hadn't been positioned yet, assume that it is in
575 // the origin
422d0ff0 576 if ( wx == wxDefaultCoord )
3f5513f5 577 wx = 0;
422d0ff0 578 if ( wy == wxDefaultCoord )
3f5513f5
VZ
579 wy = 0;
580
f68586e5
VZ
581 win->GetSize(&ww, &wh);
582 if ( wx + ww > maxX )
583 maxX = wx + ww;
584 if ( wy + wh > maxY )
585 maxY = wy + wh;
42e69d6b
VZ
586 }
587
08a19f64 588 best = wxSize(maxX, maxY);
f68586e5 589 }
997c7280 590 else // ! has children
f68586e5 591 {
c0bb586f
VZ
592 // for a generic window there is no natural best size so, if the
593 // minimal size is not set, use the current size but take care to
594 // remember it as minimal size for the next time because our best size
595 // should be constant: otherwise we could get into a situation when the
596 // window is initially at some size, then expanded to a larger size and
597 // then, when the containing window is shrunk back (because our initial
598 // best size had been used for computing the parent min size), we can't
599 // be shrunk back any more because our best size is now bigger
9240613a
VZ
600 wxSize size = GetMinSize();
601 if ( !size.IsFullySpecified() )
602 {
603 size.SetDefaults(GetSize());
604 wxConstCast(this, wxWindowBase)->SetMinSize(size);
605 }
c0bb586f
VZ
606
607 // return as-is, unadjusted by the client size difference.
9240613a 608 return size;
f03fc89f 609 }
08a19f64
RD
610
611 // Add any difference between size and client size
612 wxSize diff = GetSize() - GetClientSize();
613 best.x += wxMax(0, diff.x);
614 best.y += wxMax(0, diff.y);
615
616 return best;
f03fc89f
VZ
617}
618
333d7052
VZ
619// helper of GetWindowBorderSize(): as many ports don't implement support for
620// wxSYS_BORDER/EDGE_X/Y metrics in their wxSystemSettings, use hard coded
621// fallbacks in this case
d45a01e0 622static int wxGetMetricOrDefault(wxSystemMetric what, const wxWindowBase* win)
333d7052 623{
d45a01e0
PC
624 int rc = wxSystemSettings::GetMetric(
625 what, static_cast<wxWindow*>(const_cast<wxWindowBase*>(win)));
333d7052
VZ
626 if ( rc == -1 )
627 {
628 switch ( what )
629 {
630 case wxSYS_BORDER_X:
631 case wxSYS_BORDER_Y:
632 // 2D border is by default 1 pixel wide
633 rc = 1;
634 break;
635
636 case wxSYS_EDGE_X:
637 case wxSYS_EDGE_Y:
638 // 3D borders are by default 2 pixels
639 rc = 2;
640 break;
641
642 default:
643 wxFAIL_MSG( _T("unexpected wxGetMetricOrDefault() argument") );
644 rc = 0;
645 }
646 }
647
648 return rc;
649}
650
651wxSize wxWindowBase::GetWindowBorderSize() const
652{
653 wxSize size;
654
655 switch ( GetBorder() )
656 {
657 case wxBORDER_NONE:
658 // nothing to do, size is already (0, 0)
659 break;
660
661 case wxBORDER_SIMPLE:
662 case wxBORDER_STATIC:
d45a01e0
PC
663 size.x = wxGetMetricOrDefault(wxSYS_BORDER_X, this);
664 size.y = wxGetMetricOrDefault(wxSYS_BORDER_Y, this);
333d7052
VZ
665 break;
666
667 case wxBORDER_SUNKEN:
668 case wxBORDER_RAISED:
d45a01e0
PC
669 size.x = wxMax(wxGetMetricOrDefault(wxSYS_EDGE_X, this),
670 wxGetMetricOrDefault(wxSYS_BORDER_X, this));
671 size.y = wxMax(wxGetMetricOrDefault(wxSYS_EDGE_Y, this),
672 wxGetMetricOrDefault(wxSYS_BORDER_Y, this));
333d7052
VZ
673 break;
674
675 case wxBORDER_DOUBLE:
d45a01e0
PC
676 size.x = wxGetMetricOrDefault(wxSYS_EDGE_X, this) +
677 wxGetMetricOrDefault(wxSYS_BORDER_X, this);
678 size.y = wxGetMetricOrDefault(wxSYS_EDGE_Y, this) +
679 wxGetMetricOrDefault(wxSYS_BORDER_Y, this);
333d7052
VZ
680 break;
681
682 default:
683 wxFAIL_MSG(_T("Unknown border style."));
684 break;
685 }
686
687 // we have borders on both sides
688 return size*2;
689}
9f884528 690
170acdc9 691wxSize wxWindowBase::GetEffectiveMinSize() const
400a9e41 692{
9f884528
RD
693 // merge the best size with the min size, giving priority to the min size
694 wxSize min = GetMinSize();
1b942d5f 695
9f884528 696 if (min.x == wxDefaultCoord || min.y == wxDefaultCoord)
400a9e41 697 {
9f884528
RD
698 wxSize best = GetBestSize();
699 if (min.x == wxDefaultCoord) min.x = best.x;
700 if (min.y == wxDefaultCoord) min.y = best.y;
17c48da8 701 }
1b942d5f 702
9f884528
RD
703 return min;
704}
17c48da8 705
26f7724c
RR
706wxSize wxWindowBase::GetBestSize() const
707{
743b4266 708 if ( !m_windowSizer && m_bestSizeCache.IsFullySpecified() )
26f7724c 709 return m_bestSizeCache;
1b942d5f 710
743b4266
VZ
711 // call DoGetBestClientSize() first, if a derived class overrides it wants
712 // it to be used
713 wxSize size = DoGetBestClientSize();
714 if ( size != wxDefaultSize )
715 {
716 size += DoGetBorderSize();
717
718 CacheBestSize(size);
719 return size;
720 }
721
26f7724c
RR
722 return DoGetBestSize();
723}
42cfa184 724
e81c7155 725void wxWindowBase::SetMinSize(const wxSize& minSize)
1b942d5f
FM
726{
727 m_minWidth = minSize.x;
728 m_minHeight = minSize.y;
e81c7155
RR
729}
730
731void wxWindowBase::SetMaxSize(const wxSize& maxSize)
1b942d5f
FM
732{
733 m_maxWidth = maxSize.x;
e81c7155
RR
734 m_maxHeight = maxSize.y;
735}
736
170acdc9 737void wxWindowBase::SetInitialSize(const wxSize& size)
9f884528
RD
738{
739 // Set the min size to the size passed in. This will usually either be
740 // wxDefaultSize or the size passed to this window's ctor/Create function.
741 SetMinSize(size);
742
743 // Merge the size with the best size if needed
170acdc9 744 wxSize best = GetEffectiveMinSize();
cab1a605 745
9f884528
RD
746 // If the current size doesn't match then change it
747 if (GetSize() != best)
748 SetSize(best);
400a9e41
VZ
749}
750
9f884528 751
1e6feb95
VZ
752// by default the origin is not shifted
753wxPoint wxWindowBase::GetClientAreaOrigin() const
754{
c47addef 755 return wxPoint(0,0);
1e6feb95
VZ
756}
757
301d7a0d
VS
758wxSize wxWindowBase::ClientToWindowSize(const wxSize& size) const
759{
760 const wxSize diff(GetSize() - GetClientSize());
761
762 return wxSize(size.x == -1 ? -1 : size.x + diff.x,
763 size.y == -1 ? -1 : size.y + diff.y);
764}
765
766wxSize wxWindowBase::WindowToClientSize(const wxSize& size) const
767{
768 const wxSize diff(GetSize() - GetClientSize());
769
770 return wxSize(size.x == -1 ? -1 : size.x - diff.x,
771 size.y == -1 ? -1 : size.y - diff.y);
772}
773
69d90995
SC
774void wxWindowBase::SetWindowVariant( wxWindowVariant variant )
775{
1b69c815
VZ
776 if ( m_windowVariant != variant )
777 {
778 m_windowVariant = variant;
69d90995 779
1b69c815
VZ
780 DoSetWindowVariant(variant);
781 }
69d90995
SC
782}
783
784void wxWindowBase::DoSetWindowVariant( wxWindowVariant variant )
785{
1b69c815
VZ
786 // adjust the font height to correspond to our new variant (notice that
787 // we're only called if something really changed)
788 wxFont font = GetFont();
789 int size = font.GetPointSize();
69d90995
SC
790 switch ( variant )
791 {
1b69c815
VZ
792 case wxWINDOW_VARIANT_NORMAL:
793 break;
794
795 case wxWINDOW_VARIANT_SMALL:
796 size *= 3;
797 size /= 4;
798 break;
799
800 case wxWINDOW_VARIANT_MINI:
801 size *= 2;
802 size /= 3;
803 break;
804
805 case wxWINDOW_VARIANT_LARGE:
806 size *= 5;
807 size /= 4;
808 break;
809
69d90995
SC
810 default:
811 wxFAIL_MSG(_T("unexpected window variant"));
1b69c815 812 break;
69d90995 813 }
1b69c815
VZ
814
815 font.SetPointSize(size);
816 SetFont(font);
69d90995
SC
817}
818
b21f4960
RR
819void wxWindowBase::DoSetSizeHints( int minW, int minH,
820 int maxW, int maxH,
f36978ba 821 int WXUNUSED(incW), int WXUNUSED(incH) )
b21f4960
RR
822{
823 wxCHECK_RET( (minW == wxDefaultCoord || maxW == wxDefaultCoord || minW <= maxW) &&
824 (minH == wxDefaultCoord || maxH == wxDefaultCoord || minH <= maxH),
825 _T("min width/height must be less than max width/height!") );
826
827 m_minWidth = minW;
828 m_maxWidth = maxW;
829 m_minHeight = minH;
830 m_maxHeight = maxH;
831}
832
833
f944aec0
VS
834#if WXWIN_COMPATIBILITY_2_8
835void wxWindowBase::SetVirtualSizeHints(int WXUNUSED(minW), int WXUNUSED(minH),
836 int WXUNUSED(maxW), int WXUNUSED(maxH))
566d84a7 837{
566d84a7
RL
838}
839
f944aec0
VS
840void wxWindowBase::SetVirtualSizeHints(const wxSize& WXUNUSED(minsize),
841 const wxSize& WXUNUSED(maxsize))
566d84a7 842{
f944aec0
VS
843}
844#endif // WXWIN_COMPATIBILITY_2_8
1e2a653b 845
f944aec0
VS
846void wxWindowBase::DoSetVirtualSize( int x, int y )
847{
1e2a653b 848 m_virtualSize = wxSize(x, y);
566d84a7
RL
849}
850
851wxSize wxWindowBase::DoGetVirtualSize() const
852{
143e2719
VZ
853 // we should use the entire client area so if it is greater than our
854 // virtual size, expand it to fit (otherwise if the window is big enough we
855 // wouldn't be using parts of it)
c20ab85b 856 wxSize size = GetClientSize();
143e2719 857 if ( m_virtualSize.x > size.x )
c20ab85b
VZ
858 size.x = m_virtualSize.x;
859
143e2719 860 if ( m_virtualSize.y >= size.y )
c20ab85b
VZ
861 size.y = m_virtualSize.y;
862
863 return size;
566d84a7
RL
864}
865
3c81c9aa
VZ
866void wxWindowBase::DoGetScreenPosition(int *x, int *y) const
867{
868 // screen position is the same as (0, 0) in client coords for non TLWs (and
869 // TLWs override this method)
870 if ( x )
871 *x = 0;
872 if ( y )
873 *y = 0;
874
aa738eb8 875 ClientToScreen(x, y);
3c81c9aa
VZ
876}
877
ecdc1183 878void wxWindowBase::SendSizeEvent(int flags)
0dba08dd
VZ
879{
880 wxSizeEvent event(GetSize(), GetId());
881 event.SetEventObject(this);
ecdc1183
VZ
882 if ( flags & wxSEND_EVENT_POST )
883 wxPostEvent(this, event);
884 else
885 HandleWindowEvent(event);
0dba08dd
VZ
886}
887
ecdc1183 888void wxWindowBase::SendSizeEventToParent(int flags)
0dba08dd
VZ
889{
890 wxWindow * const parent = GetParent();
891 if ( parent && !parent->IsBeingDeleted() )
ecdc1183 892 parent->SendSizeEvent(flags);
0dba08dd
VZ
893}
894
f03fc89f
VZ
895// ----------------------------------------------------------------------------
896// show/hide/enable/disable the window
897// ----------------------------------------------------------------------------
898
899bool wxWindowBase::Show(bool show)
900{
901 if ( show != m_isShown )
902 {
903 m_isShown = show;
904
e11f4636 905 return true;
f03fc89f
VZ
906 }
907 else
908 {
e11f4636 909 return false;
f03fc89f
VZ
910 }
911}
912
47a8a4d5 913bool wxWindowBase::IsEnabled() const
f03fc89f 914{
47a8a4d5
VZ
915 return IsThisEnabled() && (IsTopLevel() || !GetParent() || GetParent()->IsEnabled());
916}
f03fc89f 917
47a8a4d5
VZ
918void wxWindowBase::NotifyWindowOnEnableChange(bool enabled)
919{
920#ifndef wxHAS_NATIVE_ENABLED_MANAGEMENT
921 DoEnable(enabled);
922#endif // !defined(wxHAS_NATIVE_ENABLED_MANAGEMENT)
923
924 OnEnabled(enabled);
925
926 // If we are top-level then the logic doesn't apply - otherwise
927 // showing a modal dialog would result in total greying out (and ungreying
928 // out later) of everything which would be really ugly
929 if ( IsTopLevel() )
930 return;
931
932 for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
933 node;
934 node = node->GetNext() )
f03fc89f 935 {
47a8a4d5
VZ
936 wxWindowBase * const child = node->GetData();
937 if ( !child->IsTopLevel() && child->IsThisEnabled() )
938 child->NotifyWindowOnEnableChange(enabled);
939 }
940}
941
942bool wxWindowBase::Enable(bool enable)
943{
944 if ( enable == IsThisEnabled() )
e11f4636 945 return false;
47a8a4d5
VZ
946
947 m_isEnabled = enable;
948
949#ifdef wxHAS_NATIVE_ENABLED_MANAGEMENT
950 DoEnable(enable);
951#else // !defined(wxHAS_NATIVE_ENABLED_MANAGEMENT)
952 wxWindowBase * const parent = GetParent();
953 if( !IsTopLevel() && parent && !parent->IsEnabled() )
954 {
955 return true;
f03fc89f 956 }
47a8a4d5
VZ
957#endif // !defined(wxHAS_NATIVE_ENABLED_MANAGEMENT)
958
959 NotifyWindowOnEnableChange(enable);
960
961 return true;
f03fc89f 962}
9c72cf76 963
865a74c7 964bool wxWindowBase::IsShownOnScreen() const
9c72cf76 965{
8a6a997f
VS
966 // A window is shown on screen if it itself is shown and so are all its
967 // parents. But if a window is toplevel one, then its always visible on
968 // screen if IsShown() returns true, even if it has a hidden parent.
865a74c7 969 return IsShown() &&
8a6a997f 970 (IsTopLevel() || GetParent() == NULL || GetParent()->IsShownOnScreen());
9c72cf76
VS
971}
972
34636400
VZ
973// ----------------------------------------------------------------------------
974// RTTI
975// ----------------------------------------------------------------------------
976
977bool wxWindowBase::IsTopLevel() const
978{
e11f4636 979 return false;
34636400 980}
f03fc89f 981
1c8e5c51
VS
982// ----------------------------------------------------------------------------
983// Freeze/Thaw
984// ----------------------------------------------------------------------------
985
986void wxWindowBase::Freeze()
987{
988 if ( !m_freezeCount++ )
989 {
990 // physically freeze this window:
991 DoFreeze();
992
993 // and recursively freeze all children:
994 for ( wxWindowList::iterator i = GetChildren().begin();
995 i != GetChildren().end(); ++i )
996 {
997 wxWindow *child = *i;
998 if ( child->IsTopLevel() )
999 continue;
1000
1001 child->Freeze();
1002 }
1003 }
1004}
1005
1006void wxWindowBase::Thaw()
1007{
1008 wxASSERT_MSG( m_freezeCount, "Thaw() without matching Freeze()" );
1009
1010 if ( !--m_freezeCount )
1011 {
1012 // recursively thaw all children:
1013 for ( wxWindowList::iterator i = GetChildren().begin();
1014 i != GetChildren().end(); ++i )
1015 {
1016 wxWindow *child = *i;
1017 if ( child->IsTopLevel() )
1018 continue;
1019
1020 child->Thaw();
1021 }
1022
1023 // physically thaw this window:
1024 DoThaw();
1025 }
1026}
1027
f03fc89f
VZ
1028// ----------------------------------------------------------------------------
1029// reparenting the window
1030// ----------------------------------------------------------------------------
1031
1032void wxWindowBase::AddChild(wxWindowBase *child)
1033{
223d09f6 1034 wxCHECK_RET( child, wxT("can't add a NULL child") );
f03fc89f 1035
f6bcfd97
BP
1036 // this should never happen and it will lead to a crash later if it does
1037 // because RemoveChild() will remove only one node from the children list
1038 // and the other(s) one(s) will be left with dangling pointers in them
222ed1d6 1039 wxASSERT_MSG( !GetChildren().Find((wxWindow*)child), _T("AddChild() called twice") );
f6bcfd97 1040
222ed1d6 1041 GetChildren().Append((wxWindow*)child);
f03fc89f 1042 child->SetParent(this);
1c8e5c51 1043
76be36e4 1044 // adding a child while frozen will assert when thawed, so freeze it as if
1c8e5c51
VS
1045 // it had been already present when we were frozen
1046 if ( IsFrozen() && !child->IsTopLevel() )
1047 child->Freeze();
f03fc89f
VZ
1048}
1049
1050void wxWindowBase::RemoveChild(wxWindowBase *child)
1051{
223d09f6 1052 wxCHECK_RET( child, wxT("can't remove a NULL child") );
f03fc89f 1053
1c8e5c51
VS
1054 // removing a child while frozen may result in permanently frozen window
1055 // if used e.g. from Reparent(), so thaw it
76be36e4
VZ
1056 //
1057 // NB: IsTopLevel() doesn't return true any more when a TLW child is being
1058 // removed from its ~wxWindowBase, so check for IsBeingDeleted() too
1059 if ( IsFrozen() && !child->IsBeingDeleted() && !child->IsTopLevel() )
1c8e5c51
VS
1060 child->Thaw();
1061
222ed1d6
MB
1062 GetChildren().DeleteObject((wxWindow *)child);
1063 child->SetParent(NULL);
f03fc89f 1064}
439b3bf1 1065
f03fc89f
VZ
1066bool wxWindowBase::Reparent(wxWindowBase *newParent)
1067{
1068 wxWindow *oldParent = GetParent();
1069 if ( newParent == oldParent )
1070 {
1071 // nothing done
e11f4636 1072 return false;
f03fc89f
VZ
1073 }
1074
47a8a4d5
VZ
1075 const bool oldEnabledState = IsEnabled();
1076
f03fc89f
VZ
1077 // unlink this window from the existing parent.
1078 if ( oldParent )
1079 {
1080 oldParent->RemoveChild(this);
1081 }
1082 else
1083 {
222ed1d6 1084 wxTopLevelWindows.DeleteObject((wxWindow *)this);
f03fc89f
VZ
1085 }
1086
1087 // add it to the new one
1088 if ( newParent )
1089 {
1090 newParent->AddChild(this);
1091 }
1092 else
1093 {
222ed1d6 1094 wxTopLevelWindows.Append((wxWindow *)this);
f03fc89f
VZ
1095 }
1096
47a8a4d5
VZ
1097 // We need to notify window (and its subwindows) if by changing the parent
1098 // we also change our enabled/disabled status.
1099 const bool newEnabledState = IsEnabled();
1100 if ( newEnabledState != oldEnabledState )
1101 {
1102 NotifyWindowOnEnableChange(newEnabledState);
1103 }
1104
e11f4636 1105 return true;
f03fc89f
VZ
1106}
1107
1108// ----------------------------------------------------------------------------
1109// event handler stuff
1110// ----------------------------------------------------------------------------
1111
7f853dd0 1112void wxWindowBase::SetEventHandler(wxEvtHandler *handler)
f03fc89f 1113{
7f853dd0
FM
1114 wxCHECK_RET(handler != NULL, "SetEventHandler(NULL) called");
1115
1116 m_eventHandler = handler;
1117}
1118
1119void wxWindowBase::SetNextHandler(wxEvtHandler *WXUNUSED(handler))
1120{
1121 // disable wxEvtHandler chain mechanism for wxWindows:
1122 // wxWindow uses its own stack mechanism which doesn't mix well with wxEvtHandler's one
1123
1124 wxFAIL_MSG("wxWindow cannot be part of a wxEvtHandler chain");
1125}
1126void wxWindowBase::SetPreviousHandler(wxEvtHandler *WXUNUSED(handler))
1127{
1128 // we can't simply wxFAIL here as in SetNextHandler: in fact the last
1129 // handler of our stack when is destroyed will be Unlink()ed and thus
1130 // will call this function to update the pointer of this window...
1131
1132 //wxFAIL_MSG("wxWindow cannot be part of a wxEvtHandler chain");
1133}
1134
1135void wxWindowBase::PushEventHandler(wxEvtHandler *handlerToPush)
1136{
1137 wxCHECK_RET( handlerToPush != NULL, "PushEventHandler(NULL) called" );
1138
1139 // the new handler is going to be part of the wxWindow stack of event handlers:
1140 // it can't be part also of an event handler double-linked chain:
1141 wxASSERT_MSG(handlerToPush->IsUnlinked(),
1142 "The handler being pushed in the wxWindow stack shouldn't be part of "
1143 "a wxEvtHandler chain; call Unlink() on it first");
1144
3a074ba8 1145 wxEvtHandler *handlerOld = GetEventHandler();
7f853dd0
FM
1146 wxCHECK_RET( handlerOld, "an old event handler is NULL?" );
1147
1148 // now use wxEvtHandler double-linked list to implement a stack:
1149 handlerToPush->SetNextHandler(handlerOld);
3a074ba8 1150
7f853dd0
FM
1151 if (handlerOld != this)
1152 handlerOld->SetPreviousHandler(handlerToPush);
3a074ba8 1153
7f853dd0 1154 SetEventHandler(handlerToPush);
3a074ba8 1155
4b6a582b 1156#if wxDEBUG_LEVEL
7f853dd0
FM
1157 // final checks of the operations done above:
1158 wxASSERT_MSG( handlerToPush->GetPreviousHandler() == NULL,
4b6a582b
VZ
1159 "the first handler of the wxWindow stack should "
1160 "have no previous handlers set" );
7f853dd0 1161 wxASSERT_MSG( handlerToPush->GetNextHandler() != NULL,
4b6a582b
VZ
1162 "the first handler of the wxWindow stack should "
1163 "have non-NULL next handler" );
7f853dd0
FM
1164
1165 wxEvtHandler* pLast = handlerToPush;
4b6a582b 1166 while ( pLast && pLast != this )
7f853dd0
FM
1167 pLast = pLast->GetNextHandler();
1168 wxASSERT_MSG( pLast->GetNextHandler() == NULL,
4b6a582b
VZ
1169 "the last handler of the wxWindow stack should "
1170 "have this window as next handler" );
1171#endif // wxDEBUG_LEVEL
f03fc89f
VZ
1172}
1173
1174wxEvtHandler *wxWindowBase::PopEventHandler(bool deleteHandler)
1175{
7f853dd0 1176 // we need to pop the wxWindow stack, i.e. we need to remove the first handler
3a074ba8 1177
7f853dd0
FM
1178 wxEvtHandler *firstHandler = GetEventHandler();
1179 wxCHECK_MSG( firstHandler != NULL, NULL, "wxWindow cannot have a NULL event handler" );
1180 wxCHECK_MSG( firstHandler != this, NULL, "cannot pop the wxWindow itself" );
1181 wxCHECK_MSG( firstHandler->GetPreviousHandler() == NULL, NULL,
1182 "the first handler of the wxWindow stack should have no previous handlers set" );
3a074ba8 1183
7f853dd0
FM
1184 wxEvtHandler *secondHandler = firstHandler->GetNextHandler();
1185 wxCHECK_MSG( secondHandler != NULL, NULL,
1186 "the first handler of the wxWindow stack should have non-NULL next handler" );
1187
1188 firstHandler->SetNextHandler(NULL);
1189 secondHandler->SetPreviousHandler(NULL);
1190
1191 // now firstHandler is completely unlinked; set secondHandler as the new window event handler
1192 SetEventHandler(secondHandler);
1193
1194 if ( deleteHandler )
1195 {
1196 delete firstHandler;
1197 firstHandler = NULL;
f03fc89f
VZ
1198 }
1199
7f853dd0 1200 return firstHandler;
f03fc89f
VZ
1201}
1202
7f853dd0 1203bool wxWindowBase::RemoveEventHandler(wxEvtHandler *handlerToRemove)
2e36d5cf 1204{
7f853dd0
FM
1205 wxCHECK_MSG( handlerToRemove != NULL, false, "RemoveEventHandler(NULL) called" );
1206 wxCHECK_MSG( handlerToRemove != this, false, "Cannot remove the window itself" );
1207
1208 if (handlerToRemove == GetEventHandler())
1209 {
1210 // removing the first event handler is equivalent to "popping" the stack
1211 PopEventHandler(false);
1212 return true;
1213 }
2e36d5cf 1214
7f853dd0
FM
1215 // NOTE: the wxWindow event handler list is always terminated with "this" handler
1216 wxEvtHandler *handlerCur = GetEventHandler()->GetNextHandler();
1217 while ( handlerCur != this )
2e36d5cf
VZ
1218 {
1219 wxEvtHandler *handlerNext = handlerCur->GetNextHandler();
1220
7f853dd0 1221 if ( handlerCur == handlerToRemove )
2e36d5cf 1222 {
7f853dd0 1223 handlerCur->Unlink();
2e36d5cf 1224
7f853dd0
FM
1225 wxASSERT_MSG( handlerCur != GetEventHandler(),
1226 "the case Remove == Pop should was already handled" );
e11f4636 1227 return true;
2e36d5cf
VZ
1228 }
1229
2e36d5cf
VZ
1230 handlerCur = handlerNext;
1231 }
1232
1233 wxFAIL_MSG( _T("where has the event handler gone?") );
1234
e11f4636 1235 return false;
2e36d5cf
VZ
1236}
1237
937013e0
VS
1238bool wxWindowBase::HandleWindowEvent(wxEvent& event) const
1239{
7f853dd0 1240 // SafelyProcessEvent() will handle exceptions nicely
937013e0
VS
1241 return GetEventHandler()->SafelyProcessEvent(event);
1242}
1243
f03fc89f 1244// ----------------------------------------------------------------------------
1b69c815 1245// colours, fonts &c
f03fc89f
VZ
1246// ----------------------------------------------------------------------------
1247
b8e7b673
VZ
1248void wxWindowBase::InheritAttributes()
1249{
8afef133 1250 const wxWindowBase * const parent = GetParent();
b8e7b673
VZ
1251 if ( !parent )
1252 return;
1253
1254 // we only inherit attributes which had been explicitly set for the parent
1255 // which ensures that this only happens if the user really wants it and
1256 // not by default which wouldn't make any sense in modern GUIs where the
1257 // controls don't all use the same fonts (nor colours)
f8ff87ed 1258 if ( parent->m_inheritFont && !m_hasFont )
b8e7b673
VZ
1259 SetFont(parent->GetFont());
1260
1261 // in addition, there is a possibility to explicitly forbid inheriting
1262 // colours at each class level by overriding ShouldInheritColours()
1263 if ( ShouldInheritColours() )
1264 {
f8ff87ed 1265 if ( parent->m_inheritFgCol && !m_hasFgCol )
b8e7b673
VZ
1266 SetForegroundColour(parent->GetForegroundColour());
1267
eb96212b
VZ
1268 // inheriting (solid) background colour is wrong as it totally breaks
1269 // any kind of themed backgrounds
1270 //
1271 // instead, the controls should use the same background as their parent
1272 // (ideally by not drawing it at all)
1273#if 0
f8ff87ed 1274 if ( parent->m_inheritBgCol && !m_hasBgCol )
b8e7b673 1275 SetBackgroundColour(parent->GetBackgroundColour());
eb96212b 1276#endif // 0
b8e7b673
VZ
1277 }
1278}
1279
1b69c815
VZ
1280/* static */ wxVisualAttributes
1281wxWindowBase::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
1282{
1283 // it is important to return valid values for all attributes from here,
1284 // GetXXX() below rely on this
1285 wxVisualAttributes attrs;
1286 attrs.font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
1287 attrs.colFg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
1b69c815 1288
0477a857
JS
1289 // On Smartphone/PocketPC, wxSYS_COLOUR_WINDOW is a better reflection of
1290 // the usual background colour than wxSYS_COLOUR_BTNFACE.
1291 // It's a pity that wxSYS_COLOUR_WINDOW isn't always a suitable background
1292 // colour on other platforms.
1293
1294#if defined(__WXWINCE__) && (defined(__SMARTPHONE__) || defined(__POCKETPC__))
1295 attrs.colBg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
1296#else
1297 attrs.colBg = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE);
1298#endif
1b69c815
VZ
1299 return attrs;
1300}
1301
1302wxColour wxWindowBase::GetBackgroundColour() const
1303{
1117d56f 1304 if ( !m_backgroundColour.IsOk() )
1b69c815
VZ
1305 {
1306 wxASSERT_MSG( !m_hasBgCol, _T("we have invalid explicit bg colour?") );
1307
1308 // get our default background colour
1309 wxColour colBg = GetDefaultAttributes().colBg;
1310
1311 // we must return some valid colour to avoid redoing this every time
1312 // and also to avoid surprizing the applications written for older
77ffb593 1313 // wxWidgets versions where GetBackgroundColour() always returned
1b69c815
VZ
1314 // something -- so give them something even if it doesn't make sense
1315 // for this window (e.g. it has a themed background)
1316 if ( !colBg.Ok() )
1317 colBg = GetClassDefaultAttributes().colBg;
1318
f604c658 1319 return colBg;
1b69c815 1320 }
f604c658
VS
1321 else
1322 return m_backgroundColour;
1b69c815
VZ
1323}
1324
1325wxColour wxWindowBase::GetForegroundColour() const
1326{
1327 // logic is the same as above
1328 if ( !m_hasFgCol && !m_foregroundColour.Ok() )
1329 {
1b69c815
VZ
1330 wxColour colFg = GetDefaultAttributes().colFg;
1331
1117d56f 1332 if ( !colFg.IsOk() )
1b69c815
VZ
1333 colFg = GetClassDefaultAttributes().colFg;
1334
f604c658 1335 return colFg;
1b69c815 1336 }
f604c658
VS
1337 else
1338 return m_foregroundColour;
1b69c815
VZ
1339}
1340
f03fc89f
VZ
1341bool wxWindowBase::SetBackgroundColour( const wxColour &colour )
1342{
cab1a605 1343 if ( colour == m_backgroundColour )
e11f4636 1344 return false;
f03fc89f 1345
1117d56f 1346 m_hasBgCol = colour.IsOk();
17bcd9a6 1347
f8ff87ed 1348 m_inheritBgCol = m_hasBgCol;
f03fc89f 1349 m_backgroundColour = colour;
44dfb5ce 1350 SetThemeEnabled( !m_hasBgCol && !m_foregroundColour.Ok() );
e11f4636 1351 return true;
f03fc89f
VZ
1352}
1353
1354bool wxWindowBase::SetForegroundColour( const wxColour &colour )
1355{
44dfb5ce 1356 if (colour == m_foregroundColour )
e11f4636 1357 return false;
f03fc89f 1358
1117d56f 1359 m_hasFgCol = colour.IsOk();
f8ff87ed 1360 m_inheritFgCol = m_hasFgCol;
f03fc89f 1361 m_foregroundColour = colour;
44dfb5ce 1362 SetThemeEnabled( !m_hasFgCol && !m_backgroundColour.Ok() );
e11f4636 1363 return true;
f03fc89f
VZ
1364}
1365
1366bool wxWindowBase::SetCursor(const wxCursor& cursor)
1367{
8a9c2246
VZ
1368 // setting an invalid cursor is ok, it means that we don't have any special
1369 // cursor
a3ab1c18 1370 if ( m_cursor.IsSameAs(cursor) )
f03fc89f
VZ
1371 {
1372 // no change
e11f4636 1373 return false;
f03fc89f
VZ
1374 }
1375
8a9c2246 1376 m_cursor = cursor;
f03fc89f 1377
e11f4636 1378 return true;
f03fc89f
VZ
1379}
1380
f604c658 1381wxFont wxWindowBase::GetFont() const
1b69c815
VZ
1382{
1383 // logic is the same as in GetBackgroundColour()
1117d56f 1384 if ( !m_font.IsOk() )
1b69c815
VZ
1385 {
1386 wxASSERT_MSG( !m_hasFont, _T("we have invalid explicit font?") );
1387
1388 wxFont font = GetDefaultAttributes().font;
1117d56f 1389 if ( !font.IsOk() )
1b69c815
VZ
1390 font = GetClassDefaultAttributes().font;
1391
f604c658 1392 return font;
1b69c815 1393 }
f604c658
VS
1394 else
1395 return m_font;
1b69c815
VZ
1396}
1397
f03fc89f
VZ
1398bool wxWindowBase::SetFont(const wxFont& font)
1399{
1b69c815 1400 if ( font == m_font )
f03fc89f
VZ
1401 {
1402 // no change
e11f4636 1403 return false;
f03fc89f
VZ
1404 }
1405
1b69c815 1406 m_font = font;
1117d56f 1407 m_hasFont = font.IsOk();
f8ff87ed 1408 m_inheritFont = m_hasFont;
23895080 1409
583d7e55
VS
1410 InvalidateBestSize();
1411
e11f4636 1412 return true;
f03fc89f
VZ
1413}
1414
b95edd47
VZ
1415#if wxUSE_PALETTE
1416
1417void wxWindowBase::SetPalette(const wxPalette& pal)
1418{
e11f4636 1419 m_hasCustomPalette = true;
b95edd47
VZ
1420 m_palette = pal;
1421
1422 // VZ: can anyone explain me what do we do here?
1423 wxWindowDC d((wxWindow *) this);
1424 d.SetPalette(pal);
1425}
1426
1427wxWindow *wxWindowBase::GetAncestorWithCustomPalette() const
1428{
1429 wxWindow *win = (wxWindow *)this;
1430 while ( win && !win->HasCustomPalette() )
1431 {
1432 win = win->GetParent();
1433 }
1434
1435 return win;
1436}
1437
1438#endif // wxUSE_PALETTE
1439
789295bf
VZ
1440#if wxUSE_CARET
1441void wxWindowBase::SetCaret(wxCaret *caret)
1442{
1443 if ( m_caret )
1444 {
1445 delete m_caret;
1446 }
1447
1448 m_caret = caret;
1449
1450 if ( m_caret )
1451 {
1452 wxASSERT_MSG( m_caret->GetWindow() == this,
223d09f6 1453 wxT("caret should be created associated to this window") );
789295bf
VZ
1454 }
1455}
1456#endif // wxUSE_CARET
1457
88ac883a 1458#if wxUSE_VALIDATORS
f03fc89f
VZ
1459// ----------------------------------------------------------------------------
1460// validators
1461// ----------------------------------------------------------------------------
1462
1463void wxWindowBase::SetValidator(const wxValidator& validator)
1464{
1465 if ( m_windowValidator )
1466 delete m_windowValidator;
1467
1468 m_windowValidator = (wxValidator *)validator.Clone();
1469
1470 if ( m_windowValidator )
1b69c815 1471 m_windowValidator->SetWindow(this);
f03fc89f 1472}
88ac883a 1473#endif // wxUSE_VALIDATORS
f03fc89f
VZ
1474
1475// ----------------------------------------------------------------------------
1e6feb95 1476// update region stuff
f03fc89f
VZ
1477// ----------------------------------------------------------------------------
1478
1e6feb95
VZ
1479wxRect wxWindowBase::GetUpdateClientRect() const
1480{
1481 wxRegion rgnUpdate = GetUpdateRegion();
1482 rgnUpdate.Intersect(GetClientRect());
1483 wxRect rectUpdate = rgnUpdate.GetBox();
1484 wxPoint ptOrigin = GetClientAreaOrigin();
1485 rectUpdate.x -= ptOrigin.x;
1486 rectUpdate.y -= ptOrigin.y;
1487
1488 return rectUpdate;
1489}
1490
657b4fd4 1491bool wxWindowBase::DoIsExposed(int x, int y) const
f03fc89f
VZ
1492{
1493 return m_updateRegion.Contains(x, y) != wxOutRegion;
1494}
1495
657b4fd4 1496bool wxWindowBase::DoIsExposed(int x, int y, int w, int h) const
f03fc89f
VZ
1497{
1498 return m_updateRegion.Contains(x, y, w, h) != wxOutRegion;
1499}
1500
5da0803c
VZ
1501void wxWindowBase::ClearBackground()
1502{
1503 // wxGTK uses its own version, no need to add never used code
1504#ifndef __WXGTK__
1505 wxClientDC dc((wxWindow *)this);
cb129171 1506 wxBrush brush(GetBackgroundColour(), wxBRUSHSTYLE_SOLID);
5da0803c
VZ
1507 dc.SetBackground(brush);
1508 dc.Clear();
1509#endif // __WXGTK__
1510}
1511
f03fc89f 1512// ----------------------------------------------------------------------------
146ba0fe 1513// find child window by id or name
f03fc89f
VZ
1514// ----------------------------------------------------------------------------
1515
6b73af79 1516wxWindow *wxWindowBase::FindWindow(long id) const
f03fc89f
VZ
1517{
1518 if ( id == m_windowId )
1519 return (wxWindow *)this;
1520
d3b9f782 1521 wxWindowBase *res = NULL;
222ed1d6 1522 wxWindowList::compatibility_iterator node;
f03fc89f
VZ
1523 for ( node = m_children.GetFirst(); node && !res; node = node->GetNext() )
1524 {
1525 wxWindowBase *child = node->GetData();
1526 res = child->FindWindow( id );
1527 }
1528
1529 return (wxWindow *)res;
1530}
1531
6b73af79 1532wxWindow *wxWindowBase::FindWindow(const wxString& name) const
f03fc89f
VZ
1533{
1534 if ( name == m_windowName )
1535 return (wxWindow *)this;
1536
d3b9f782 1537 wxWindowBase *res = NULL;
222ed1d6 1538 wxWindowList::compatibility_iterator node;
f03fc89f
VZ
1539 for ( node = m_children.GetFirst(); node && !res; node = node->GetNext() )
1540 {
1541 wxWindow *child = node->GetData();
1542 res = child->FindWindow(name);
1543 }
1544
1545 return (wxWindow *)res;
1546}
1547
146ba0fe
VZ
1548
1549// find any window by id or name or label: If parent is non-NULL, look through
1550// children for a label or title matching the specified string. If NULL, look
1551// through all top-level windows.
1552//
1553// to avoid duplicating code we reuse the same helper function but with
1554// different comparators
1555
1556typedef bool (*wxFindWindowCmp)(const wxWindow *win,
1557 const wxString& label, long id);
1558
1559static
1560bool wxFindWindowCmpLabels(const wxWindow *win, const wxString& label,
1561 long WXUNUSED(id))
1562{
1563 return win->GetLabel() == label;
1564}
1565
1566static
1567bool wxFindWindowCmpNames(const wxWindow *win, const wxString& label,
1568 long WXUNUSED(id))
1569{
1570 return win->GetName() == label;
1571}
1572
1573static
1574bool wxFindWindowCmpIds(const wxWindow *win, const wxString& WXUNUSED(label),
1575 long id)
1576{
1577 return win->GetId() == id;
1578}
1579
1580// recursive helper for the FindWindowByXXX() functions
1581static
1582wxWindow *wxFindWindowRecursively(const wxWindow *parent,
1583 const wxString& label,
1584 long id,
1585 wxFindWindowCmp cmp)
1586{
1587 if ( parent )
1588 {
1589 // see if this is the one we're looking for
1590 if ( (*cmp)(parent, label, id) )
1591 return (wxWindow *)parent;
1592
1593 // It wasn't, so check all its children
222ed1d6 1594 for ( wxWindowList::compatibility_iterator node = parent->GetChildren().GetFirst();
146ba0fe
VZ
1595 node;
1596 node = node->GetNext() )
1597 {
1598 // recursively check each child
1599 wxWindow *win = (wxWindow *)node->GetData();
1600 wxWindow *retwin = wxFindWindowRecursively(win, label, id, cmp);
1601 if (retwin)
1602 return retwin;
1603 }
1604 }
1605
1606 // Not found
1607 return NULL;
1608}
1609
1610// helper for FindWindowByXXX()
1611static
1612wxWindow *wxFindWindowHelper(const wxWindow *parent,
1613 const wxString& label,
1614 long id,
1615 wxFindWindowCmp cmp)
1616{
1617 if ( parent )
1618 {
1619 // just check parent and all its children
1620 return wxFindWindowRecursively(parent, label, id, cmp);
1621 }
1622
1623 // start at very top of wx's windows
222ed1d6 1624 for ( wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetFirst();
146ba0fe
VZ
1625 node;
1626 node = node->GetNext() )
1627 {
1628 // recursively check each window & its children
1629 wxWindow *win = node->GetData();
1630 wxWindow *retwin = wxFindWindowRecursively(win, label, id, cmp);
1631 if (retwin)
1632 return retwin;
1633 }
1634
1635 return NULL;
1636}
1637
1638/* static */
1639wxWindow *
1640wxWindowBase::FindWindowByLabel(const wxString& title, const wxWindow *parent)
1641{
1642 return wxFindWindowHelper(parent, title, 0, wxFindWindowCmpLabels);
1643}
1644
1645/* static */
1646wxWindow *
1647wxWindowBase::FindWindowByName(const wxString& title, const wxWindow *parent)
1648{
1649 wxWindow *win = wxFindWindowHelper(parent, title, 0, wxFindWindowCmpNames);
1650
1651 if ( !win )
1652 {
1653 // fall back to the label
1654 win = FindWindowByLabel(title, parent);
1655 }
1656
1657 return win;
1658}
1659
1660/* static */
1661wxWindow *
1662wxWindowBase::FindWindowById( long id, const wxWindow* parent )
1663{
525d8583 1664 return wxFindWindowHelper(parent, wxEmptyString, id, wxFindWindowCmpIds);
146ba0fe
VZ
1665}
1666
f03fc89f
VZ
1667// ----------------------------------------------------------------------------
1668// dialog oriented functions
1669// ----------------------------------------------------------------------------
1670
34636400 1671void wxWindowBase::MakeModal(bool modal)
f03fc89f 1672{
34636400
VZ
1673 // Disable all other windows
1674 if ( IsTopLevel() )
1675 {
222ed1d6 1676 wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetFirst();
34636400
VZ
1677 while (node)
1678 {
1679 wxWindow *win = node->GetData();
1680 if (win != this)
1681 win->Enable(!modal);
1682
1683 node = node->GetNext();
1684 }
1685 }
f03fc89f
VZ
1686}
1687
1688bool wxWindowBase::Validate()
1689{
88ac883a 1690#if wxUSE_VALIDATORS
d80cd92a
VZ
1691 bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
1692
222ed1d6 1693 wxWindowList::compatibility_iterator node;
f03fc89f
VZ
1694 for ( node = m_children.GetFirst(); node; node = node->GetNext() )
1695 {
1696 wxWindowBase *child = node->GetData();
1697 wxValidator *validator = child->GetValidator();
dcd6b914 1698 if ( validator && !validator->Validate((wxWindow *)this) )
f03fc89f 1699 {
e11f4636 1700 return false;
f03fc89f 1701 }
d80cd92a
VZ
1702
1703 if ( recurse && !child->Validate() )
1704 {
e11f4636 1705 return false;
d80cd92a 1706 }
f03fc89f 1707 }
88ac883a 1708#endif // wxUSE_VALIDATORS
f03fc89f 1709
e11f4636 1710 return true;
f03fc89f
VZ
1711}
1712
1713bool wxWindowBase::TransferDataToWindow()
1714{
88ac883a 1715#if wxUSE_VALIDATORS
d80cd92a
VZ
1716 bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
1717
222ed1d6 1718 wxWindowList::compatibility_iterator node;
f03fc89f
VZ
1719 for ( node = m_children.GetFirst(); node; node = node->GetNext() )
1720 {
1721 wxWindowBase *child = node->GetData();
1722 wxValidator *validator = child->GetValidator();
1723 if ( validator && !validator->TransferToWindow() )
1724 {
d80cd92a 1725 wxLogWarning(_("Could not transfer data to window"));
e30285ab 1726#if wxUSE_LOG
d80cd92a 1727 wxLog::FlushActive();
e30285ab 1728#endif // wxUSE_LOG
f03fc89f 1729
e11f4636 1730 return false;
f03fc89f 1731 }
d80cd92a
VZ
1732
1733 if ( recurse )
1734 {
a58a12e9 1735 if ( !child->TransferDataToWindow() )
d80cd92a
VZ
1736 {
1737 // warning already given
e11f4636 1738 return false;
d80cd92a
VZ
1739 }
1740 }
f03fc89f 1741 }
88ac883a 1742#endif // wxUSE_VALIDATORS
f03fc89f 1743
e11f4636 1744 return true;
f03fc89f
VZ
1745}
1746
1747bool wxWindowBase::TransferDataFromWindow()
1748{
88ac883a 1749#if wxUSE_VALIDATORS
d80cd92a
VZ
1750 bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
1751
222ed1d6 1752 wxWindowList::compatibility_iterator node;
f03fc89f
VZ
1753 for ( node = m_children.GetFirst(); node; node = node->GetNext() )
1754 {
1755 wxWindow *child = node->GetData();
d80cd92a
VZ
1756 wxValidator *validator = child->GetValidator();
1757 if ( validator && !validator->TransferFromWindow() )
f03fc89f 1758 {
d80cd92a
VZ
1759 // nop warning here because the application is supposed to give
1760 // one itself - we don't know here what might have gone wrongly
1761
e11f4636 1762 return false;
f03fc89f 1763 }
d80cd92a
VZ
1764
1765 if ( recurse )
1766 {
a58a12e9 1767 if ( !child->TransferDataFromWindow() )
d80cd92a
VZ
1768 {
1769 // warning already given
e11f4636 1770 return false;
d80cd92a
VZ
1771 }
1772 }
f03fc89f 1773 }
88ac883a 1774#endif // wxUSE_VALIDATORS
f03fc89f 1775
e11f4636 1776 return true;
f03fc89f
VZ
1777}
1778
1779void wxWindowBase::InitDialog()
1780{
1781 wxInitDialogEvent event(GetId());
1782 event.SetEventObject( this );
1783 GetEventHandler()->ProcessEvent(event);
1784}
1785
1786// ----------------------------------------------------------------------------
bd83cb56
VZ
1787// context-sensitive help support
1788// ----------------------------------------------------------------------------
1789
1790#if wxUSE_HELP
1791
1792// associate this help text with this window
1793void wxWindowBase::SetHelpText(const wxString& text)
1794{
1795 wxHelpProvider *helpProvider = wxHelpProvider::Get();
1796 if ( helpProvider )
1797 {
1798 helpProvider->AddHelp(this, text);
1799 }
1800}
1801
520746ac 1802#if WXWIN_COMPATIBILITY_2_8
bd83cb56
VZ
1803// associate this help text with all windows with the same id as this
1804// one
1805void wxWindowBase::SetHelpTextForId(const wxString& text)
1806{
1807 wxHelpProvider *helpProvider = wxHelpProvider::Get();
1808 if ( helpProvider )
1809 {
1810 helpProvider->AddHelp(GetId(), text);
1811 }
1812}
520746ac 1813#endif // WXWIN_COMPATIBILITY_2_8
bd83cb56
VZ
1814
1815// get the help string associated with this window (may be empty)
dc6588e7
VZ
1816// default implementation forwards calls to the help provider
1817wxString
1818wxWindowBase::GetHelpTextAtPoint(const wxPoint & WXUNUSED(pt),
1819 wxHelpEvent::Origin WXUNUSED(origin)) const
bd83cb56
VZ
1820{
1821 wxString text;
1822 wxHelpProvider *helpProvider = wxHelpProvider::Get();
1823 if ( helpProvider )
1824 {
1825 text = helpProvider->GetHelp(this);
1826 }
1827
1828 return text;
1829}
1830
1831// show help for this window
1832void wxWindowBase::OnHelp(wxHelpEvent& event)
1833{
1834 wxHelpProvider *helpProvider = wxHelpProvider::Get();
1835 if ( helpProvider )
1836 {
95d3881f
VZ
1837 wxPoint pos = event.GetPosition();
1838 const wxHelpEvent::Origin origin = event.GetOrigin();
1839 if ( origin == wxHelpEvent::Origin_Keyboard )
1840 {
1841 // if the help event was generated from keyboard it shouldn't
1842 // appear at the mouse position (which is still the only position
1843 // associated with help event) if the mouse is far away, although
1844 // we still do use the mouse position if it's over the window
1845 // because we suppose the user looks approximately at the mouse
1846 // already and so it would be more convenient than showing tooltip
1847 // at some arbitrary position which can be quite far from it
1848 const wxRect rectClient = GetClientRect();
1849 if ( !rectClient.Contains(ScreenToClient(pos)) )
1850 {
1851 // position help slightly under and to the right of this window
1852 pos = ClientToScreen(wxPoint(
1853 2*GetCharWidth(),
1854 rectClient.height + GetCharHeight()
1855 ));
1856 }
1857 }
1858
1859 if ( helpProvider->ShowHelpAtPoint(this, pos, origin) )
bd83cb56
VZ
1860 {
1861 // skip the event.Skip() below
1862 return;
1863 }
1864 }
1865
1866 event.Skip();
1867}
1868
1869#endif // wxUSE_HELP
1870
1871// ----------------------------------------------------------------------------
602a2e02 1872// tooltips
f03fc89f
VZ
1873// ----------------------------------------------------------------------------
1874
1875#if wxUSE_TOOLTIPS
1876
1877void wxWindowBase::SetToolTip( const wxString &tip )
1878{
1879 // don't create the new tooltip if we already have one
1880 if ( m_tooltip )
1881 {
1882 m_tooltip->SetTip( tip );
1883 }
1884 else
1885 {
1886 SetToolTip( new wxToolTip( tip ) );
1887 }
1888
1889 // setting empty tooltip text does not remove the tooltip any more - use
d3b9f782 1890 // SetToolTip(NULL) for this
f03fc89f
VZ
1891}
1892
1893void wxWindowBase::DoSetToolTip(wxToolTip *tooltip)
1894{
0cb57187
VZ
1895 if ( m_tooltip != tooltip )
1896 {
1897 if ( m_tooltip )
1898 delete m_tooltip;
f03fc89f 1899
0cb57187
VZ
1900 m_tooltip = tooltip;
1901 }
f03fc89f
VZ
1902}
1903
1904#endif // wxUSE_TOOLTIPS
1905
1906// ----------------------------------------------------------------------------
1907// constraints and sizers
1908// ----------------------------------------------------------------------------
1909
1910#if wxUSE_CONSTRAINTS
1911
1912void wxWindowBase::SetConstraints( wxLayoutConstraints *constraints )
1913{
1914 if ( m_constraints )
1915 {
1916 UnsetConstraints(m_constraints);
1917 delete m_constraints;
1918 }
1919 m_constraints = constraints;
1920 if ( m_constraints )
1921 {
1922 // Make sure other windows know they're part of a 'meaningful relationship'
1923 if ( m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this) )
1924 m_constraints->left.GetOtherWindow()->AddConstraintReference(this);
1925 if ( m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this) )
1926 m_constraints->top.GetOtherWindow()->AddConstraintReference(this);
1927 if ( m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this) )
1928 m_constraints->right.GetOtherWindow()->AddConstraintReference(this);
1929 if ( m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this) )
1930 m_constraints->bottom.GetOtherWindow()->AddConstraintReference(this);
1931 if ( m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this) )
1932 m_constraints->width.GetOtherWindow()->AddConstraintReference(this);
1933 if ( m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this) )
1934 m_constraints->height.GetOtherWindow()->AddConstraintReference(this);
1935 if ( m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this) )
1936 m_constraints->centreX.GetOtherWindow()->AddConstraintReference(this);
1937 if ( m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this) )
1938 m_constraints->centreY.GetOtherWindow()->AddConstraintReference(this);
1939 }
1940}
1941
1942// This removes any dangling pointers to this window in other windows'
1943// constraintsInvolvedIn lists.
1944void wxWindowBase::UnsetConstraints(wxLayoutConstraints *c)
1945{
1946 if ( c )
1947 {
1948 if ( c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this) )
1949 c->left.GetOtherWindow()->RemoveConstraintReference(this);
1950 if ( c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this) )
1951 c->top.GetOtherWindow()->RemoveConstraintReference(this);
1952 if ( c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this) )
1953 c->right.GetOtherWindow()->RemoveConstraintReference(this);
1954 if ( c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this) )
1955 c->bottom.GetOtherWindow()->RemoveConstraintReference(this);
1956 if ( c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this) )
1957 c->width.GetOtherWindow()->RemoveConstraintReference(this);
1958 if ( c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this) )
1959 c->height.GetOtherWindow()->RemoveConstraintReference(this);
1960 if ( c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this) )
1961 c->centreX.GetOtherWindow()->RemoveConstraintReference(this);
1962 if ( c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this) )
1963 c->centreY.GetOtherWindow()->RemoveConstraintReference(this);
1964 }
1965}
1966
1967// Back-pointer to other windows we're involved with, so if we delete this
1968// window, we must delete any constraints we're involved with.
1969void wxWindowBase::AddConstraintReference(wxWindowBase *otherWin)
1970{
1971 if ( !m_constraintsInvolvedIn )
1972 m_constraintsInvolvedIn = new wxWindowList;
222ed1d6
MB
1973 if ( !m_constraintsInvolvedIn->Find((wxWindow *)otherWin) )
1974 m_constraintsInvolvedIn->Append((wxWindow *)otherWin);
f03fc89f
VZ
1975}
1976
1977// REMOVE back-pointer to other windows we're involved with.
1978void wxWindowBase::RemoveConstraintReference(wxWindowBase *otherWin)
1979{
1980 if ( m_constraintsInvolvedIn )
222ed1d6 1981 m_constraintsInvolvedIn->DeleteObject((wxWindow *)otherWin);
f03fc89f
VZ
1982}
1983
1984// Reset any constraints that mention this window
1985void wxWindowBase::DeleteRelatedConstraints()
1986{
1987 if ( m_constraintsInvolvedIn )
1988 {
222ed1d6 1989 wxWindowList::compatibility_iterator node = m_constraintsInvolvedIn->GetFirst();
f03fc89f
VZ
1990 while (node)
1991 {
1992 wxWindow *win = node->GetData();
1993 wxLayoutConstraints *constr = win->GetConstraints();
1994
1995 // Reset any constraints involving this window
1996 if ( constr )
1997 {
1998 constr->left.ResetIfWin(this);
1999 constr->top.ResetIfWin(this);
2000 constr->right.ResetIfWin(this);
2001 constr->bottom.ResetIfWin(this);
2002 constr->width.ResetIfWin(this);
2003 constr->height.ResetIfWin(this);
2004 constr->centreX.ResetIfWin(this);
2005 constr->centreY.ResetIfWin(this);
2006 }
2007
222ed1d6
MB
2008 wxWindowList::compatibility_iterator next = node->GetNext();
2009 m_constraintsInvolvedIn->Erase(node);
f03fc89f
VZ
2010 node = next;
2011 }
2012
2013 delete m_constraintsInvolvedIn;
d3b9f782 2014 m_constraintsInvolvedIn = NULL;
f03fc89f
VZ
2015 }
2016}
ec5bb70d
VZ
2017
2018#endif // wxUSE_CONSTRAINTS
f03fc89f 2019
3aa5d532 2020void wxWindowBase::SetSizer(wxSizer *sizer, bool deleteOld)
f03fc89f 2021{
fb89cfc5
RD
2022 if ( sizer == m_windowSizer)
2023 return;
1b69c815 2024
e8cfff87
VZ
2025 if ( m_windowSizer )
2026 {
2027 m_windowSizer->SetContainingWindow(NULL);
2028
2029 if ( deleteOld )
2030 delete m_windowSizer;
2031 }
3417c2cd 2032
f03fc89f 2033 m_windowSizer = sizer;
e8cfff87
VZ
2034 if ( m_windowSizer )
2035 {
2036 m_windowSizer->SetContainingWindow((wxWindow *)this);
2037 }
566d84a7 2038
e8cfff87 2039 SetAutoLayout(m_windowSizer != NULL);
566d84a7
RL
2040}
2041
2042void wxWindowBase::SetSizerAndFit(wxSizer *sizer, bool deleteOld)
2043{
2044 SetSizer( sizer, deleteOld );
2045 sizer->SetSizeHints( (wxWindow*) this );
f03fc89f
VZ
2046}
2047
400a9e41 2048
1ebfafde
RD
2049void wxWindowBase::SetContainingSizer(wxSizer* sizer)
2050{
2051 // adding a window to a sizer twice is going to result in fatal and
2052 // hard to debug problems later because when deleting the second
2053 // associated wxSizerItem we're going to dereference a dangling
2054 // pointer; so try to detect this as early as possible
2055 wxASSERT_MSG( !sizer || m_containingSizer != sizer,
2056 _T("Adding a window to the same sizer twice?") );
1ebfafde 2057
400a9e41 2058 m_containingSizer = sizer;
1ebfafde 2059}
400a9e41 2060
ec5bb70d
VZ
2061#if wxUSE_CONSTRAINTS
2062
2063void wxWindowBase::SatisfyConstraints()
2064{
2065 wxLayoutConstraints *constr = GetConstraints();
2066 bool wasOk = constr && constr->AreSatisfied();
2067
2068 ResetConstraints(); // Mark all constraints as unevaluated
2069
2070 int noChanges = 1;
2071
2072 // if we're a top level panel (i.e. our parent is frame/dialog), our
2073 // own constraints will never be satisfied any more unless we do it
2074 // here
2075 if ( wasOk )
2076 {
2077 while ( noChanges > 0 )
2078 {
2079 LayoutPhase1(&noChanges);
2080 }
2081 }
2082
2083 LayoutPhase2(&noChanges);
2084}
2085
2086#endif // wxUSE_CONSTRAINTS
2087
f03fc89f
VZ
2088bool wxWindowBase::Layout()
2089{
3417c2cd 2090 // If there is a sizer, use it instead of the constraints
f03fc89f
VZ
2091 if ( GetSizer() )
2092 {
8d7eaf91 2093 int w = 0, h = 0;
566d84a7 2094 GetVirtualSize(&w, &h);
3417c2cd 2095 GetSizer()->SetDimension( 0, 0, w, h );
f03fc89f 2096 }
461e93f9 2097#if wxUSE_CONSTRAINTS
f1df0927 2098 else
f03fc89f 2099 {
ec5bb70d 2100 SatisfyConstraints(); // Find the right constraints values
f1df0927 2101 SetConstraintSizes(); // Recursively set the real window sizes
f03fc89f 2102 }
461e93f9 2103#endif
5d4b632b 2104
e11f4636 2105 return true;
f03fc89f
VZ
2106}
2107
6528a7f1
VZ
2108void wxWindowBase::InternalOnSize(wxSizeEvent& event)
2109{
2110 if ( GetAutoLayout() )
2111 Layout();
2112
2113 event.Skip();
2114}
2115
461e93f9 2116#if wxUSE_CONSTRAINTS
ec5bb70d
VZ
2117
2118// first phase of the constraints evaluation: set our own constraints
f03fc89f
VZ
2119bool wxWindowBase::LayoutPhase1(int *noChanges)
2120{
2121 wxLayoutConstraints *constr = GetConstraints();
ec5bb70d
VZ
2122
2123 return !constr || constr->SatisfyConstraints(this, noChanges);
f03fc89f
VZ
2124}
2125
ec5bb70d 2126// second phase: set the constraints for our children
f03fc89f
VZ
2127bool wxWindowBase::LayoutPhase2(int *noChanges)
2128{
2129 *noChanges = 0;
2130
2131 // Layout children
2132 DoPhase(1);
ec5bb70d
VZ
2133
2134 // Layout grand children
f03fc89f 2135 DoPhase(2);
ec5bb70d 2136
e11f4636 2137 return true;
f03fc89f
VZ
2138}
2139
2140// Do a phase of evaluating child constraints
2141bool wxWindowBase::DoPhase(int phase)
2142{
ec5bb70d
VZ
2143 // the list containing the children for which the constraints are already
2144 // set correctly
f03fc89f 2145 wxWindowList succeeded;
ec5bb70d
VZ
2146
2147 // the max number of iterations we loop before concluding that we can't set
2148 // the constraints
2149 static const int maxIterations = 500;
2150
2151 for ( int noIterations = 0; noIterations < maxIterations; noIterations++ )
f03fc89f 2152 {
ec5bb70d
VZ
2153 int noChanges = 0;
2154
2155 // loop over all children setting their constraints
222ed1d6 2156 for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
ec5bb70d
VZ
2157 node;
2158 node = node->GetNext() )
f03fc89f
VZ
2159 {
2160 wxWindow *child = node->GetData();
ec5bb70d 2161 if ( child->IsTopLevel() )
f03fc89f 2162 {
ec5bb70d
VZ
2163 // top level children are not inside our client area
2164 continue;
2165 }
2166
2167 if ( !child->GetConstraints() || succeeded.Find(child) )
2168 {
2169 // this one is either already ok or nothing we can do about it
2170 continue;
2171 }
2172
2173 int tempNoChanges = 0;
2174 bool success = phase == 1 ? child->LayoutPhase1(&tempNoChanges)
2175 : child->LayoutPhase2(&tempNoChanges);
2176 noChanges += tempNoChanges;
2177
2178 if ( success )
2179 {
2180 succeeded.Append(child);
f03fc89f 2181 }
f03fc89f
VZ
2182 }
2183
ec5bb70d
VZ
2184 if ( !noChanges )
2185 {
2186 // constraints are set
2187 break;
2188 }
f03fc89f
VZ
2189 }
2190
e11f4636 2191 return true;
f03fc89f
VZ
2192}
2193
2194void wxWindowBase::ResetConstraints()
2195{
2196 wxLayoutConstraints *constr = GetConstraints();
2197 if ( constr )
2198 {
e11f4636
DS
2199 constr->left.SetDone(false);
2200 constr->top.SetDone(false);
2201 constr->right.SetDone(false);
2202 constr->bottom.SetDone(false);
2203 constr->width.SetDone(false);
2204 constr->height.SetDone(false);
2205 constr->centreX.SetDone(false);
2206 constr->centreY.SetDone(false);
f03fc89f 2207 }
f1df0927 2208
222ed1d6 2209 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
f03fc89f
VZ
2210 while (node)
2211 {
2212 wxWindow *win = node->GetData();
34636400 2213 if ( !win->IsTopLevel() )
f03fc89f
VZ
2214 win->ResetConstraints();
2215 node = node->GetNext();
2216 }
2217}
2218
2219// Need to distinguish between setting the 'fake' size for windows and sizers,
2220// and setting the real values.
2221void wxWindowBase::SetConstraintSizes(bool recurse)
2222{
2223 wxLayoutConstraints *constr = GetConstraints();
4b7f2165 2224 if ( constr && constr->AreSatisfied() )
f03fc89f
VZ
2225 {
2226 int x = constr->left.GetValue();
2227 int y = constr->top.GetValue();
2228 int w = constr->width.GetValue();
2229 int h = constr->height.GetValue();
2230
f03fc89f 2231 if ( (constr->width.GetRelationship() != wxAsIs ) ||
3417c2cd 2232 (constr->height.GetRelationship() != wxAsIs) )
f03fc89f 2233 {
3417c2cd 2234 SetSize(x, y, w, h);
f03fc89f
VZ
2235 }
2236 else
2237 {
3417c2cd
RR
2238 // If we don't want to resize this window, just move it...
2239 Move(x, y);
f03fc89f
VZ
2240 }
2241 }
2242 else if ( constr )
2243 {
4b7f2165 2244 wxLogDebug(wxT("Constraints not satisfied for %s named '%s'."),
f1df0927 2245 GetClassInfo()->GetClassName(),
4b7f2165 2246 GetName().c_str());
f03fc89f
VZ
2247 }
2248
2249 if ( recurse )
2250 {
222ed1d6 2251 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
f03fc89f
VZ
2252 while (node)
2253 {
2254 wxWindow *win = node->GetData();
e2f9212c 2255 if ( !win->IsTopLevel() && win->GetConstraints() )
f03fc89f
VZ
2256 win->SetConstraintSizes();
2257 node = node->GetNext();
2258 }
2259 }
2260}
2261
f03fc89f
VZ
2262// Only set the size/position of the constraint (if any)
2263void wxWindowBase::SetSizeConstraint(int x, int y, int w, int h)
2264{
2265 wxLayoutConstraints *constr = GetConstraints();
2266 if ( constr )
2267 {
422d0ff0 2268 if ( x != wxDefaultCoord )
f03fc89f
VZ
2269 {
2270 constr->left.SetValue(x);
e11f4636 2271 constr->left.SetDone(true);
f03fc89f 2272 }
422d0ff0 2273 if ( y != wxDefaultCoord )
f03fc89f
VZ
2274 {
2275 constr->top.SetValue(y);
e11f4636 2276 constr->top.SetDone(true);
f03fc89f 2277 }
422d0ff0 2278 if ( w != wxDefaultCoord )
f03fc89f
VZ
2279 {
2280 constr->width.SetValue(w);
e11f4636 2281 constr->width.SetDone(true);
f03fc89f 2282 }
422d0ff0 2283 if ( h != wxDefaultCoord )
f03fc89f
VZ
2284 {
2285 constr->height.SetValue(h);
e11f4636 2286 constr->height.SetDone(true);
f03fc89f
VZ
2287 }
2288 }
2289}
2290
2291void wxWindowBase::MoveConstraint(int x, int y)
2292{
2293 wxLayoutConstraints *constr = GetConstraints();
2294 if ( constr )
2295 {
422d0ff0 2296 if ( x != wxDefaultCoord )
f03fc89f
VZ
2297 {
2298 constr->left.SetValue(x);
e11f4636 2299 constr->left.SetDone(true);
f03fc89f 2300 }
422d0ff0 2301 if ( y != wxDefaultCoord )
f03fc89f
VZ
2302 {
2303 constr->top.SetValue(y);
e11f4636 2304 constr->top.SetDone(true);
f03fc89f
VZ
2305 }
2306 }
2307}
2308
2309void wxWindowBase::GetSizeConstraint(int *w, int *h) const
2310{
2311 wxLayoutConstraints *constr = GetConstraints();
2312 if ( constr )
2313 {
2314 *w = constr->width.GetValue();
2315 *h = constr->height.GetValue();
2316 }
2317 else
2318 GetSize(w, h);
2319}
2320
2321void wxWindowBase::GetClientSizeConstraint(int *w, int *h) const
2322{
2323 wxLayoutConstraints *constr = GetConstraints();
2324 if ( constr )
2325 {
2326 *w = constr->width.GetValue();
2327 *h = constr->height.GetValue();
2328 }
2329 else
2330 GetClientSize(w, h);
2331}
2332
461e93f9
JS
2333void wxWindowBase::GetPositionConstraint(int *x, int *y) const
2334{
2335 wxLayoutConstraints *constr = GetConstraints();
2336 if ( constr )
2337 {
2338 *x = constr->left.GetValue();
2339 *y = constr->top.GetValue();
2340 }
2341 else
2342 GetPosition(x, y);
2343}
2344
2345#endif // wxUSE_CONSTRAINTS
2346
20a1eea1 2347void wxWindowBase::AdjustForParentClientOrigin(int& x, int& y, int sizeFlags) const
a200c35e
VS
2348{
2349 // don't do it for the dialogs/frames - they float independently of their
2350 // parent
2351 if ( !IsTopLevel() )
2352 {
2353 wxWindow *parent = GetParent();
2354 if ( !(sizeFlags & wxSIZE_NO_ADJUSTMENTS) && parent )
2355 {
2356 wxPoint pt(parent->GetClientAreaOrigin());
2357 x += pt.x;
2358 y += pt.y;
2359 }
2360 }
2361}
2362
f03fc89f 2363// ----------------------------------------------------------------------------
602a2e02 2364// Update UI processing
f03fc89f 2365// ----------------------------------------------------------------------------
7ec1983b 2366
e39af974 2367void wxWindowBase::UpdateWindowUI(long flags)
7ec1983b 2368{
26bf1ce0 2369 wxUpdateUIEvent event(GetId());
687706f5 2370 event.SetEventObject(this);
26bf1ce0
VZ
2371
2372 if ( GetEventHandler()->ProcessEvent(event) )
7ec1983b 2373 {
e39af974
JS
2374 DoUpdateWindowUI(event);
2375 }
7ec1983b 2376
e39af974
JS
2377 if (flags & wxUPDATE_UI_RECURSE)
2378 {
222ed1d6 2379 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
e39af974 2380 while (node)
f03fc89f 2381 {
e39af974
JS
2382 wxWindow* child = (wxWindow*) node->GetData();
2383 child->UpdateWindowUI(flags);
2384 node = node->GetNext();
26bf1ce0 2385 }
e39af974
JS
2386 }
2387}
f03fc89f 2388
e39af974 2389// do the window-specific processing after processing the update event
e39af974
JS
2390void wxWindowBase::DoUpdateWindowUI(wxUpdateUIEvent& event)
2391{
2392 if ( event.GetSetEnabled() )
2393 Enable(event.GetEnabled());
e11f4636 2394
a3a4105d
VZ
2395 if ( event.GetSetShown() )
2396 Show(event.GetShown());
e39af974
JS
2397}
2398
f03fc89f
VZ
2399// ----------------------------------------------------------------------------
2400// dialog units translations
2401// ----------------------------------------------------------------------------
2402
2403wxPoint wxWindowBase::ConvertPixelsToDialog(const wxPoint& pt)
fd71308f
JS
2404{
2405 int charWidth = GetCharWidth();
2406 int charHeight = GetCharHeight();
cab1a605
WS
2407 wxPoint pt2 = wxDefaultPosition;
2408 if (pt.x != wxDefaultCoord)
1b69c815 2409 pt2.x = (int) ((pt.x * 4) / charWidth);
cab1a605 2410 if (pt.y != wxDefaultCoord)
1b69c815 2411 pt2.y = (int) ((pt.y * 8) / charHeight);
fd71308f
JS
2412
2413 return pt2;
2414}
2415
f03fc89f 2416wxPoint wxWindowBase::ConvertDialogToPixels(const wxPoint& pt)
fd71308f
JS
2417{
2418 int charWidth = GetCharWidth();
2419 int charHeight = GetCharHeight();
cab1a605
WS
2420 wxPoint pt2 = wxDefaultPosition;
2421 if (pt.x != wxDefaultCoord)
1b69c815 2422 pt2.x = (int) ((pt.x * charWidth) / 4);
cab1a605 2423 if (pt.y != wxDefaultCoord)
1b69c815 2424 pt2.y = (int) ((pt.y * charHeight) / 8);
fd71308f
JS
2425
2426 return pt2;
2427}
2428
f03fc89f
VZ
2429// ----------------------------------------------------------------------------
2430// event handlers
2431// ----------------------------------------------------------------------------
2432
2433// propagate the colour change event to the subwindows
2434void wxWindowBase::OnSysColourChanged(wxSysColourChangedEvent& event)
2435{
222ed1d6 2436 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
f03fc89f
VZ
2437 while ( node )
2438 {
2439 // Only propagate to non-top-level windows
2440 wxWindow *win = node->GetData();
2441 if ( !win->IsTopLevel() )
2442 {
2443 wxSysColourChangedEvent event2;
687706f5 2444 event.SetEventObject(win);
f03fc89f
VZ
2445 win->GetEventHandler()->ProcessEvent(event2);
2446 }
2447
2448 node = node->GetNext();
2449 }
9a8477e1
VS
2450
2451 Refresh();
f03fc89f
VZ
2452}
2453
e39af974
JS
2454// the default action is to populate dialog with data when it's created,
2455// and nudge the UI into displaying itself correctly in case
2456// we've turned the wxUpdateUIEvents frequency down low.
f03fc89f
VZ
2457void wxWindowBase::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) )
2458{
2459 TransferDataToWindow();
e11f4636 2460
e39af974
JS
2461 // Update the UI at this point
2462 UpdateWindowUI(wxUPDATE_UI_RECURSE);
f03fc89f
VZ
2463}
2464
00a77b7c
VZ
2465// ----------------------------------------------------------------------------
2466// menu-related functions
2467// ----------------------------------------------------------------------------
2468
2469#if wxUSE_MENUS
2470
eeb0bee1
VZ
2471bool wxWindowBase::PopupMenu(wxMenu *menu, int x, int y)
2472{
2473 wxCHECK_MSG( menu, false, "can't popup NULL menu" );
2474
2475 wxCurrentPopupMenu = menu;
2476 const bool rc = DoPopupMenu(menu, x, y);
2477 wxCurrentPopupMenu = NULL;
2478
2479 return rc;
2480}
2481
00a77b7c
VZ
2482// this is used to pass the id of the selected item from the menu event handler
2483// to the main function itself
2484//
2485// it's ok to use a global here as there can be at most one popup menu shown at
2486// any time
2487static int gs_popupMenuSelection = wxID_NONE;
2488
2489void wxWindowBase::InternalOnPopupMenu(wxCommandEvent& event)
2490{
2491 // store the id in a global variable where we'll retrieve it from later
2492 gs_popupMenuSelection = event.GetId();
2493}
2494
565382de
VZ
2495void wxWindowBase::InternalOnPopupMenuUpdate(wxUpdateUIEvent& WXUNUSED(event))
2496{
2497 // nothing to do but do not skip it
2498}
2499
00a77b7c
VZ
2500int
2501wxWindowBase::DoGetPopupMenuSelectionFromUser(wxMenu& menu, int x, int y)
2502{
2503 gs_popupMenuSelection = wxID_NONE;
2504
2505 Connect(wxEVT_COMMAND_MENU_SELECTED,
2506 wxCommandEventHandler(wxWindowBase::InternalOnPopupMenu),
2507 NULL,
2508 this);
2509
565382de
VZ
2510 // it is common to construct the menu passed to this function dynamically
2511 // using some fixed range of ids which could clash with the ids used
2512 // elsewhere in the program, which could result in some menu items being
2513 // unintentionally disabled or otherwise modified by update UI handlers
2514 // elsewhere in the program code and this is difficult to avoid in the
2515 // program itself, so instead we just temporarily suspend UI updating while
2516 // this menu is shown
2517 Connect(wxEVT_UPDATE_UI,
2518 wxUpdateUIEventHandler(wxWindowBase::InternalOnPopupMenuUpdate),
2519 NULL,
2520 this);
2521
00a77b7c
VZ
2522 PopupMenu(&menu, x, y);
2523
565382de
VZ
2524 Disconnect(wxEVT_UPDATE_UI,
2525 wxUpdateUIEventHandler(wxWindowBase::InternalOnPopupMenuUpdate),
2526 NULL,
2527 this);
00a77b7c
VZ
2528 Disconnect(wxEVT_COMMAND_MENU_SELECTED,
2529 wxCommandEventHandler(wxWindowBase::InternalOnPopupMenu),
2530 NULL,
2531 this);
2532
2533 return gs_popupMenuSelection;
2534}
2535
2536#endif // wxUSE_MENUS
2537
dddd1f21
VZ
2538// methods for drawing the sizers in a visible way
2539#ifdef __WXDEBUG__
2540
2541static void DrawSizers(wxWindowBase *win);
2542
a721fd82 2543static void DrawBorder(wxWindowBase *win, const wxRect& rect, bool fill, const wxPen* pen)
dddd1f21
VZ
2544{
2545 wxClientDC dc((wxWindow *)win);
a721fd82 2546 dc.SetPen(*pen);
1b942d5f 2547 dc.SetBrush(fill ? wxBrush(pen->GetColour(), wxBRUSHSTYLE_CROSSDIAG_HATCH) :
a721fd82 2548 *wxTRANSPARENT_BRUSH);
dddd1f21
VZ
2549 dc.DrawRectangle(rect.Deflate(1, 1));
2550}
2551
2552static void DrawSizer(wxWindowBase *win, wxSizer *sizer)
2553{
2554 const wxSizerItemList& items = sizer->GetChildren();
2555 for ( wxSizerItemList::const_iterator i = items.begin(),
2556 end = items.end();
2557 i != end;
2558 ++i )
2559 {
2560 wxSizerItem *item = *i;
2561 if ( item->IsSizer() )
2562 {
a721fd82 2563 DrawBorder(win, item->GetRect().Deflate(2), false, wxRED_PEN);
dddd1f21
VZ
2564 DrawSizer(win, item->GetSizer());
2565 }
2566 else if ( item->IsSpacer() )
2567 {
a721fd82 2568 DrawBorder(win, item->GetRect().Deflate(2), true, wxBLUE_PEN);
dddd1f21
VZ
2569 }
2570 else if ( item->IsWindow() )
2571 {
2572 DrawSizers(item->GetWindow());
2573 }
1b942d5f
FM
2574 else
2575 wxFAIL_MSG("inconsistent wxSizerItem status!");
dddd1f21
VZ
2576 }
2577}
2578
2579static void DrawSizers(wxWindowBase *win)
2580{
a721fd82
FM
2581 DrawBorder(win, win->GetClientSize(), false, wxGREEN_PEN);
2582
dddd1f21
VZ
2583 wxSizer *sizer = win->GetSizer();
2584 if ( sizer )
2585 {
dddd1f21
VZ
2586 DrawSizer(win, sizer);
2587 }
2588 else // no sizer, still recurse into the children
2589 {
2590 const wxWindowList& children = win->GetChildren();
2591 for ( wxWindowList::const_iterator i = children.begin(),
2592 end = children.end();
2593 i != end;
2594 ++i )
2595 {
2596 DrawSizers(*i);
2597 }
1b942d5f
FM
2598
2599 // show all kind of sizes of this window; see the "window sizing" topic
2600 // overview for more info about the various differences:
2601 wxSize fullSz = win->GetSize();
2602 wxSize clientSz = win->GetClientSize();
2603 wxSize bestSz = win->GetBestSize();
2604 wxSize minSz = win->GetMinSize();
2605 wxSize maxSz = win->GetMaxSize();
2606 wxSize virtualSz = win->GetVirtualSize();
2607
2608 wxMessageOutputDebug dbgout;
2609 dbgout.Printf(
2610 "%-10s => fullsz=%4d;%-4d clientsz=%4d;%-4d bestsz=%4d;%-4d minsz=%4d;%-4d maxsz=%4d;%-4d virtualsz=%4d;%-4d\n",
79cb759d 2611 win->GetName(),
1b942d5f
FM
2612 fullSz.x, fullSz.y,
2613 clientSz.x, clientSz.y,
2614 bestSz.x, bestSz.y,
2615 minSz.x, minSz.y,
2616 maxSz.x, maxSz.y,
2617 virtualSz.x, virtualSz.y);
dddd1f21
VZ
2618 }
2619}
2620
2621#endif // __WXDEBUG__
2622
2623// process special middle clicks
a02dc3e3
VZ
2624void wxWindowBase::OnMiddleClick( wxMouseEvent& event )
2625{
2626 if ( event.ControlDown() && event.AltDown() )
2627 {
dddd1f21
VZ
2628#ifdef __WXDEBUG__
2629 // Ctrl-Alt-Shift-mclick makes the sizers visible in debug builds
2630 if ( event.ShiftDown() )
2631 {
2632 DrawSizers(this);
2633 return;
2634 }
2635#endif // __WXDEBUG__
8cf304f8 2636 ::wxInfoMessageBox((wxWindow*)this);
a02dc3e3
VZ
2637 }
2638 else
2639 {
2640 event.Skip();
2641 }
2642}
2643
ed5317e5
JS
2644// ----------------------------------------------------------------------------
2645// accessibility
2646// ----------------------------------------------------------------------------
2647
2648#if wxUSE_ACCESSIBILITY
2649void wxWindowBase::SetAccessible(wxAccessible* accessible)
2650{
2aefc528 2651 if (m_accessible && (accessible != m_accessible))
ed5317e5
JS
2652 delete m_accessible;
2653 m_accessible = accessible;
2654 if (m_accessible)
2655 m_accessible->SetWindow((wxWindow*) this);
2656}
2657
2658// Returns the accessible object, creating if necessary.
2659wxAccessible* wxWindowBase::GetOrCreateAccessible()
2660{
2661 if (!m_accessible)
2662 m_accessible = CreateAccessible();
2663 return m_accessible;
2664}
2665
2666// Override to create a specific accessible object.
2667wxAccessible* wxWindowBase::CreateAccessible()
2668{
2669 return new wxWindowAccessible((wxWindow*) this);
2670}
2671
2672#endif
2673
f03fc89f
VZ
2674// ----------------------------------------------------------------------------
2675// list classes implementation
2676// ----------------------------------------------------------------------------
2677
ed1288c1
VZ
2678#if wxUSE_STL
2679
7ec69821 2680#include "wx/listimpl.cpp"
412e0d47 2681WX_DEFINE_LIST(wxWindowList)
ed1288c1 2682
602a2e02 2683#else // !wxUSE_STL
ed1288c1 2684
f03fc89f
VZ
2685void wxWindowListNode::DeleteData()
2686{
2687 delete (wxWindow *)GetData();
2688}
ed1288c1 2689
602a2e02 2690#endif // wxUSE_STL/!wxUSE_STL
f03fc89f 2691
1e6feb95
VZ
2692// ----------------------------------------------------------------------------
2693// borders
2694// ----------------------------------------------------------------------------
2695
aede4ebb 2696wxBorder wxWindowBase::GetBorder(long flags) const
1e6feb95 2697{
aede4ebb 2698 wxBorder border = (wxBorder)(flags & wxBORDER_MASK);
1e6feb95
VZ
2699 if ( border == wxBORDER_DEFAULT )
2700 {
2701 border = GetDefaultBorder();
2702 }
78cd9c69
JS
2703 else if ( border == wxBORDER_THEME )
2704 {
2705 border = GetDefaultBorderForControl();
2706 }
1e6feb95
VZ
2707
2708 return border;
2709}
2710
2711wxBorder wxWindowBase::GetDefaultBorder() const
2712{
2713 return wxBORDER_NONE;
2714}
2715
2716// ----------------------------------------------------------------------------
2717// hit testing
2718// ----------------------------------------------------------------------------
2719
2720wxHitTest wxWindowBase::DoHitTest(wxCoord x, wxCoord y) const
2721{
2722 // here we just check if the point is inside the window or not
2723
2724 // check the top and left border first
2725 bool outside = x < 0 || y < 0;
2726 if ( !outside )
2727 {
2728 // check the right and bottom borders too
2729 wxSize size = GetSize();
2730 outside = x >= size.x || y >= size.y;
2731 }
2732
2733 return outside ? wxHT_WINDOW_OUTSIDE : wxHT_WINDOW_INSIDE;
2734}
2735
94633ad9
VZ
2736// ----------------------------------------------------------------------------
2737// mouse capture
2738// ----------------------------------------------------------------------------
2739
2740struct WXDLLEXPORT wxWindowNext
2741{
2742 wxWindow *win;
2743 wxWindowNext *next;
786646f3 2744} *wxWindowBase::ms_winCaptureNext = NULL;
63e819f2
VS
2745wxWindow *wxWindowBase::ms_winCaptureCurrent = NULL;
2746bool wxWindowBase::ms_winCaptureChanging = false;
94633ad9 2747
a83e1475 2748void wxWindowBase::CaptureMouse()
94633ad9 2749{
5c33522f 2750 wxLogTrace(_T("mousecapture"), _T("CaptureMouse(%p)"), static_cast<void*>(this));
45e0dc94 2751
63e819f2
VS
2752 wxASSERT_MSG( !ms_winCaptureChanging, _T("recursive CaptureMouse call?") );
2753
2754 ms_winCaptureChanging = true;
2755
94633ad9
VZ
2756 wxWindow *winOld = GetCapture();
2757 if ( winOld )
2758 {
df2f507b 2759 ((wxWindowBase*) winOld)->DoReleaseMouse();
edd802c6 2760
94633ad9
VZ
2761 // save it on stack
2762 wxWindowNext *item = new wxWindowNext;
2763 item->win = winOld;
2764 item->next = ms_winCaptureNext;
2765 ms_winCaptureNext = item;
2766 }
2767 //else: no mouse capture to save
2768
2769 DoCaptureMouse();
63e819f2
VS
2770 ms_winCaptureCurrent = (wxWindow*)this;
2771
2772 ms_winCaptureChanging = false;
94633ad9
VZ
2773}
2774
a83e1475 2775void wxWindowBase::ReleaseMouse()
94633ad9 2776{
5c33522f 2777 wxLogTrace(_T("mousecapture"), _T("ReleaseMouse(%p)"), static_cast<void*>(this));
349d1942 2778
63e819f2
VS
2779 wxASSERT_MSG( !ms_winCaptureChanging, _T("recursive ReleaseMouse call?") );
2780
31b9d29f
VS
2781 wxASSERT_MSG( GetCapture() == this,
2782 "attempt to release mouse, but this window hasn't captured it" );
2783 wxASSERT_MSG( ms_winCaptureCurrent == this,
2784 "attempt to release mouse, but this window hasn't captured it" );
a7b09001 2785
63e819f2
VS
2786 ms_winCaptureChanging = true;
2787
94633ad9 2788 DoReleaseMouse();
63e819f2 2789 ms_winCaptureCurrent = NULL;
94633ad9
VZ
2790
2791 if ( ms_winCaptureNext )
2792 {
44f8caa7 2793 ((wxWindowBase*)ms_winCaptureNext->win)->DoCaptureMouse();
63e819f2 2794 ms_winCaptureCurrent = ms_winCaptureNext->win;
edd802c6 2795
94633ad9
VZ
2796 wxWindowNext *item = ms_winCaptureNext;
2797 ms_winCaptureNext = item->next;
2798 delete item;
2799 }
2800 //else: stack is empty, no previous capture
2801
63e819f2
VS
2802 ms_winCaptureChanging = false;
2803
94633ad9 2804 wxLogTrace(_T("mousecapture"),
e11f4636 2805 (const wxChar *) _T("After ReleaseMouse() mouse is captured by %p"),
5c33522f 2806 static_cast<void*>(GetCapture()));
94633ad9
VZ
2807}
2808
63e819f2
VS
2809static void DoNotifyWindowAboutCaptureLost(wxWindow *win)
2810{
2811 wxMouseCaptureLostEvent event(win->GetId());
2812 event.SetEventObject(win);
40bdc5d6
VZ
2813 if ( !win->GetEventHandler()->ProcessEvent(event) )
2814 {
44038f9a
VS
2815 // windows must handle this event, otherwise the app wouldn't behave
2816 // correctly if it loses capture unexpectedly; see the discussion here:
2817 // http://sourceforge.net/tracker/index.php?func=detail&aid=1153662&group_id=9863&atid=109863
2818 // http://article.gmane.org/gmane.comp.lib.wxwidgets.devel/82376
40bdc5d6
VZ
2819 wxFAIL_MSG( _T("window that captured the mouse didn't process wxEVT_MOUSE_CAPTURE_LOST") );
2820 }
63e819f2
VS
2821}
2822
2823/* static */
72f8c792 2824void wxWindowBase::NotifyCaptureLost()
63e819f2
VS
2825{
2826 // don't do anything if capture lost was expected, i.e. resulted from
2827 // a wx call to ReleaseMouse or CaptureMouse:
2828 if ( ms_winCaptureChanging )
2829 return;
2830
2831 // if the capture was lost unexpectedly, notify every window that has
2832 // capture (on stack or current) about it and clear the stack:
2833
2834 if ( ms_winCaptureCurrent )
2835 {
2836 DoNotifyWindowAboutCaptureLost(ms_winCaptureCurrent);
2837 ms_winCaptureCurrent = NULL;
2838 }
2839
2840 while ( ms_winCaptureNext )
2841 {
2842 wxWindowNext *item = ms_winCaptureNext;
2843 ms_winCaptureNext = item->next;
2844
2845 DoNotifyWindowAboutCaptureLost(item->win);
2846
2847 delete item;
2848 }
2849}
2850
5048c832 2851#if wxUSE_HOTKEY
540b6b09
VZ
2852
2853bool
2854wxWindowBase::RegisterHotKey(int WXUNUSED(hotkeyId),
2855 int WXUNUSED(modifiers),
2856 int WXUNUSED(keycode))
5048c832
JS
2857{
2858 // not implemented
2859 return false;
2860}
2861
540b6b09 2862bool wxWindowBase::UnregisterHotKey(int WXUNUSED(hotkeyId))
5048c832
JS
2863{
2864 // not implemented
2865 return false;
2866}
540b6b09
VZ
2867
2868#endif // wxUSE_HOTKEY
7de59551 2869
4caf847c
VZ
2870// ----------------------------------------------------------------------------
2871// event processing
2872// ----------------------------------------------------------------------------
2873
8cc208e3 2874bool wxWindowBase::TryBefore(wxEvent& event)
4caf847c 2875{
6eabf58c 2876#if wxUSE_VALIDATORS
4caf847c
VZ
2877 // Can only use the validator of the window which
2878 // is receiving the event
2879 if ( event.GetEventObject() == this )
2880 {
92089d00
VZ
2881 wxValidator * const validator = GetValidator();
2882 if ( validator && validator->ProcessEventHere(event) )
4caf847c 2883 {
6eabf58c 2884 return true;
4caf847c
VZ
2885 }
2886 }
6eabf58c 2887#endif // wxUSE_VALIDATORS
4caf847c 2888
8cc208e3 2889 return wxEvtHandler::TryBefore(event);
4caf847c
VZ
2890}
2891
8cc208e3 2892bool wxWindowBase::TryAfter(wxEvent& event)
4caf847c 2893{
90e572f1 2894 // carry on up the parent-child hierarchy if the propagation count hasn't
040e234d
VZ
2895 // reached zero yet
2896 if ( event.ShouldPropagate() )
4caf847c
VZ
2897 {
2898 // honour the requests to stop propagation at this window: this is
2899 // used by the dialogs, for example, to prevent processing the events
2900 // from the dialog controls in the parent frame which rarely, if ever,
2901 // makes sense
2902 if ( !(GetExtraStyle() & wxWS_EX_BLOCK_EVENTS) )
2903 {
2904 wxWindow *parent = GetParent();
2905 if ( parent && !parent->IsBeingDeleted() )
040e234d
VZ
2906 {
2907 wxPropagateOnce propagateOnce(event);
2908
4caf847c 2909 return parent->GetEventHandler()->ProcessEvent(event);
040e234d 2910 }
4caf847c
VZ
2911 }
2912 }
2913
8cc208e3 2914 return wxEvtHandler::TryAfter(event);
4caf847c
VZ
2915}
2916
c944775f
VZ
2917// ----------------------------------------------------------------------------
2918// window relationships
2919// ----------------------------------------------------------------------------
2920
2921wxWindow *wxWindowBase::DoGetSibling(WindowOrder order) const
2922{
2923 wxCHECK_MSG( GetParent(), NULL,
2924 _T("GetPrev/NextSibling() don't work for TLWs!") );
2925
2926 wxWindowList& siblings = GetParent()->GetChildren();
c52b9635 2927 wxWindowList::compatibility_iterator i = siblings.Find((wxWindow *)this);
c944775f
VZ
2928 wxCHECK_MSG( i, NULL, _T("window not a child of its parent?") );
2929
2930 if ( order == OrderBefore )
2931 i = i->GetPrevious();
2932 else // OrderAfter
2933 i = i->GetNext();
2934
2935 return i ? i->GetData() : NULL;
2936}
2937
5f6cfda7 2938// ----------------------------------------------------------------------------
a24de76b 2939// keyboard navigation
5f6cfda7
JS
2940// ----------------------------------------------------------------------------
2941
5644933f 2942// Navigates in the specified direction inside this window
553d2d7d 2943bool wxWindowBase::DoNavigateIn(int flags)
5f6cfda7 2944{
5644933f
VZ
2945#ifdef wxHAS_NATIVE_TAB_TRAVERSAL
2946 // native code doesn't process our wxNavigationKeyEvents anyhow
553d2d7d 2947 wxUnusedVar(flags);
5644933f
VZ
2948 return false;
2949#else // !wxHAS_NATIVE_TAB_TRAVERSAL
5f6cfda7 2950 wxNavigationKeyEvent eventNav;
f029f1d1
VS
2951 wxWindow *focused = FindFocus();
2952 eventNav.SetCurrentFocus(focused);
2953 eventNav.SetEventObject(focused);
eedc82f4 2954 eventNav.SetFlags(flags);
5644933f
VZ
2955 return GetEventHandler()->ProcessEvent(eventNav);
2956#endif // wxHAS_NATIVE_TAB_TRAVERSAL/!wxHAS_NATIVE_TAB_TRAVERSAL
5f6cfda7
JS
2957}
2958
f029f1d1
VS
2959bool wxWindowBase::HandleAsNavigationKey(const wxKeyEvent& event)
2960{
2961 if ( event.GetKeyCode() != WXK_TAB )
2962 return false;
2963
2964 int flags = wxNavigationKeyEvent::FromTab;
2965
2966 if ( event.ShiftDown() )
2967 flags |= wxNavigationKeyEvent::IsBackward;
2968 else
2969 flags |= wxNavigationKeyEvent::IsForward;
2970
2971 if ( event.ControlDown() )
2972 flags |= wxNavigationKeyEvent::WinChange;
2973
2974 Navigate(flags);
2975 return true;
2976}
2977
c944775f 2978void wxWindowBase::DoMoveInTabOrder(wxWindow *win, WindowOrder move)
a24de76b
VZ
2979{
2980 // check that we're not a top level window
2981 wxCHECK_RET( GetParent(),
2982 _T("MoveBefore/AfterInTabOrder() don't work for TLWs!") );
2983
ef6816ef
VZ
2984 // detect the special case when we have nothing to do anyhow and when the
2985 // code below wouldn't work
2986 if ( win == this )
2987 return;
2988
a24de76b
VZ
2989 // find the target window in the siblings list
2990 wxWindowList& siblings = GetParent()->GetChildren();
2991 wxWindowList::compatibility_iterator i = siblings.Find(win);
2992 wxCHECK_RET( i, _T("MoveBefore/AfterInTabOrder(): win is not a sibling") );
2993
2994 // unfortunately, when wxUSE_STL == 1 DetachNode() is not implemented so we
2995 // can't just move the node around
feef1ecf
VZ
2996 wxWindow *self = (wxWindow *)this;
2997 siblings.DeleteObject(self);
c944775f 2998 if ( move == OrderAfter )
9e9300c4
VZ
2999 {
3000 i = i->GetNext();
3001 }
3002
3003 if ( i )
a24de76b 3004 {
feef1ecf 3005 siblings.Insert(i, self);
a24de76b 3006 }
c944775f 3007 else // OrderAfter and win was the last sibling
a24de76b 3008 {
feef1ecf 3009 siblings.Append(self);
a24de76b
VZ
3010 }
3011}
3012
0fe02759
VS
3013// ----------------------------------------------------------------------------
3014// focus handling
3015// ----------------------------------------------------------------------------
3016
3017/*static*/ wxWindow* wxWindowBase::FindFocus()
3018{
9c52a429 3019 wxWindowBase *win = DoFindFocus();
0fe02759
VS
3020 return win ? win->GetMainWindowOfCompositeControl() : NULL;
3021}
3022
3358af0f
VS
3023bool wxWindowBase::HasFocus() const
3024{
3025 wxWindowBase *win = DoFindFocus();
3026 return win == this ||
3027 win == wxConstCast(this, wxWindowBase)->GetMainWindowOfCompositeControl();
3028}
3029
4f24cbbd
VS
3030// ----------------------------------------------------------------------------
3031// drag and drop
3032// ----------------------------------------------------------------------------
3033
3034#if wxUSE_DRAG_AND_DROP && !defined(__WXMSW__)
3035
3036namespace
3037{
3038
3039class DragAcceptFilesTarget : public wxFileDropTarget
3040{
3041public:
3042 DragAcceptFilesTarget(wxWindowBase *win) : m_win(win) {}
3043
3044 virtual bool OnDropFiles(wxCoord x, wxCoord y,
3045 const wxArrayString& filenames)
3046 {
3047 wxDropFilesEvent event(wxEVT_DROP_FILES,
3048 filenames.size(),
3049 wxCArrayString(filenames).Release());
3050 event.SetEventObject(m_win);
3051 event.m_pos.x = x;
3052 event.m_pos.y = y;
3053
3054 return m_win->HandleWindowEvent(event);
3055 }
3056
3057private:
3058 wxWindowBase * const m_win;
3059
c0c133e1 3060 wxDECLARE_NO_COPY_CLASS(DragAcceptFilesTarget);
4f24cbbd
VS
3061};
3062
3063
3064} // anonymous namespace
3065
3066// Generic version of DragAcceptFiles(). It works by installing a simple
3067// wxFileDropTarget-to-EVT_DROP_FILES adaptor and therefore cannot be used
3068// together with explicit SetDropTarget() calls.
3069void wxWindowBase::DragAcceptFiles(bool accept)
3070{
3071 if ( accept )
3072 {
3073 wxASSERT_MSG( !GetDropTarget(),
3074 "cannot use DragAcceptFiles() and SetDropTarget() together" );
3075 SetDropTarget(new DragAcceptFilesTarget(this));
3076 }
3077 else
3078 {
3079 SetDropTarget(NULL);
3080 }
3081}
3082
3083#endif // wxUSE_DRAG_AND_DROP && !defined(__WXMSW__)
3084
33b494d6
VZ
3085// ----------------------------------------------------------------------------
3086// global functions
3087// ----------------------------------------------------------------------------
3088
3089wxWindow* wxGetTopLevelParent(wxWindow *win)
3090{
3091 while ( win && !win->IsTopLevel() )
3092 win = win->GetParent();
3093
3094 return win;
3095}
3096
ed5317e5
JS
3097#if wxUSE_ACCESSIBILITY
3098// ----------------------------------------------------------------------------
3099// accessible object for windows
3100// ----------------------------------------------------------------------------
3101
3102// Can return either a child object, or an integer
3103// representing the child element, starting from 1.
66b9ec3d 3104wxAccStatus wxWindowAccessible::HitTest(const wxPoint& WXUNUSED(pt), int* WXUNUSED(childId), wxAccessible** WXUNUSED(childObject))
ed5317e5
JS
3105{
3106 wxASSERT( GetWindow() != NULL );
3107 if (!GetWindow())
3108 return wxACC_FAIL;
3109
3110 return wxACC_NOT_IMPLEMENTED;
3111}
3112
3113// Returns the rectangle for this object (id = 0) or a child element (id > 0).
3114wxAccStatus wxWindowAccessible::GetLocation(wxRect& rect, int elementId)
3115{
3116 wxASSERT( GetWindow() != NULL );
3117 if (!GetWindow())
3118 return wxACC_FAIL;
3119
c6e2af45
JS
3120 wxWindow* win = NULL;
3121 if (elementId == 0)
3122 {
3123 win = GetWindow();
3124 }
3125 else
3126 {
3127 if (elementId <= (int) GetWindow()->GetChildren().GetCount())
3128 {
ee6eb8d8 3129 win = GetWindow()->GetChildren().Item(elementId-1)->GetData();
c6e2af45
JS
3130 }
3131 else
3132 return wxACC_FAIL;
3133 }
3134 if (win)
3135 {
3136 rect = win->GetRect();
3137 if (win->GetParent() && !win->IsKindOf(CLASSINFO(wxTopLevelWindow)))
3138 rect.SetPosition(win->GetParent()->ClientToScreen(rect.GetPosition()));
3139 return wxACC_OK;
3140 }
3141
ed5317e5
JS
3142 return wxACC_NOT_IMPLEMENTED;
3143}
3144
3145// Navigates from fromId to toId/toObject.
3146wxAccStatus wxWindowAccessible::Navigate(wxNavDir navDir, int fromId,
66b9ec3d 3147 int* WXUNUSED(toId), wxAccessible** toObject)
ed5317e5
JS
3148{
3149 wxASSERT( GetWindow() != NULL );
3150 if (!GetWindow())
3151 return wxACC_FAIL;
3152
c6e2af45
JS
3153 switch (navDir)
3154 {
3155 case wxNAVDIR_FIRSTCHILD:
3156 {
3157 if (GetWindow()->GetChildren().GetCount() == 0)
3158 return wxACC_FALSE;
3159 wxWindow* childWindow = (wxWindow*) GetWindow()->GetChildren().GetFirst()->GetData();
3160 *toObject = childWindow->GetOrCreateAccessible();
3161
3162 return wxACC_OK;
3163 }
3164 case wxNAVDIR_LASTCHILD:
3165 {
3166 if (GetWindow()->GetChildren().GetCount() == 0)
3167 return wxACC_FALSE;
3168 wxWindow* childWindow = (wxWindow*) GetWindow()->GetChildren().GetLast()->GetData();
3169 *toObject = childWindow->GetOrCreateAccessible();
3170
3171 return wxACC_OK;
3172 }
3173 case wxNAVDIR_RIGHT:
3174 case wxNAVDIR_DOWN:
3175 case wxNAVDIR_NEXT:
3176 {
ee6eb8d8
MB
3177 wxWindowList::compatibility_iterator node =
3178 wxWindowList::compatibility_iterator();
c6e2af45
JS
3179 if (fromId == 0)
3180 {
3181 // Can't navigate to sibling of this window
3182 // if we're a top-level window.
3183 if (!GetWindow()->GetParent())
3184 return wxACC_NOT_IMPLEMENTED;
3185
3186 node = GetWindow()->GetParent()->GetChildren().Find(GetWindow());
3187 }
3188 else
3189 {
3190 if (fromId <= (int) GetWindow()->GetChildren().GetCount())
33b3f7c3 3191 node = GetWindow()->GetChildren().Item(fromId-1);
c6e2af45
JS
3192 }
3193
3194 if (node && node->GetNext())
3195 {
ee6eb8d8 3196 wxWindow* nextWindow = node->GetNext()->GetData();
c6e2af45
JS
3197 *toObject = nextWindow->GetOrCreateAccessible();
3198 return wxACC_OK;
3199 }
3200 else
3201 return wxACC_FALSE;
3202 }
3203 case wxNAVDIR_LEFT:
3204 case wxNAVDIR_UP:
3205 case wxNAVDIR_PREVIOUS:
3206 {
ee6eb8d8
MB
3207 wxWindowList::compatibility_iterator node =
3208 wxWindowList::compatibility_iterator();
c6e2af45
JS
3209 if (fromId == 0)
3210 {
3211 // Can't navigate to sibling of this window
3212 // if we're a top-level window.
3213 if (!GetWindow()->GetParent())
3214 return wxACC_NOT_IMPLEMENTED;
3215
3216 node = GetWindow()->GetParent()->GetChildren().Find(GetWindow());
3217 }
3218 else
3219 {
3220 if (fromId <= (int) GetWindow()->GetChildren().GetCount())
33b3f7c3 3221 node = GetWindow()->GetChildren().Item(fromId-1);
c6e2af45
JS
3222 }
3223
3224 if (node && node->GetPrevious())
3225 {
ee6eb8d8 3226 wxWindow* previousWindow = node->GetPrevious()->GetData();
c6e2af45
JS
3227 *toObject = previousWindow->GetOrCreateAccessible();
3228 return wxACC_OK;
3229 }
3230 else
3231 return wxACC_FALSE;
3232 }
3233 }
3234
ed5317e5
JS
3235 return wxACC_NOT_IMPLEMENTED;
3236}
3237
3238// Gets the name of the specified object.
3239wxAccStatus wxWindowAccessible::GetName(int childId, wxString* name)
3240{
3241 wxASSERT( GetWindow() != NULL );
3242 if (!GetWindow())
3243 return wxACC_FAIL;
3244
2aefc528
JS
3245 wxString title;
3246
77ffb593 3247 // If a child, leave wxWidgets to call the function on the actual
2aefc528
JS
3248 // child object.
3249 if (childId > 0)
3250 return wxACC_NOT_IMPLEMENTED;
3251
3252 // This will eventually be replaced by specialised
77ffb593 3253 // accessible classes, one for each kind of wxWidgets
2aefc528 3254 // control or window.
0b4f47a3 3255#if wxUSE_BUTTON
2aefc528
JS
3256 if (GetWindow()->IsKindOf(CLASSINFO(wxButton)))
3257 title = ((wxButton*) GetWindow())->GetLabel();
3258 else
0b4f47a3 3259#endif
2aefc528 3260 title = GetWindow()->GetName();
e11f4636 3261
ba889513 3262 if (!title.empty())
ed5317e5
JS
3263 {
3264 *name = title;
3265 return wxACC_OK;
3266 }
3267 else
3268 return wxACC_NOT_IMPLEMENTED;
3269}
3270
3271// Gets the number of children.
3272wxAccStatus wxWindowAccessible::GetChildCount(int* childId)
3273{
3274 wxASSERT( GetWindow() != NULL );
3275 if (!GetWindow())
3276 return wxACC_FAIL;
3277
3278 *childId = (int) GetWindow()->GetChildren().GetCount();
3279 return wxACC_OK;
3280}
3281
3282// Gets the specified child (starting from 1).
3283// If *child is NULL and return value is wxACC_OK,
3284// this means that the child is a simple element and
3285// not an accessible object.
3286wxAccStatus wxWindowAccessible::GetChild(int childId, wxAccessible** child)
3287{
3288 wxASSERT( GetWindow() != NULL );
3289 if (!GetWindow())
3290 return wxACC_FAIL;
3291
3292 if (childId == 0)
3293 {
3294 *child = this;
3295 return wxACC_OK;
3296 }
3297
3298 if (childId > (int) GetWindow()->GetChildren().GetCount())
3299 return wxACC_FAIL;
3300
ee6eb8d8 3301 wxWindow* childWindow = GetWindow()->GetChildren().Item(childId-1)->GetData();
ed5317e5
JS
3302 *child = childWindow->GetOrCreateAccessible();
3303 if (*child)
3304 return wxACC_OK;
3305 else
3306 return wxACC_FAIL;
3307}
3308
3309// Gets the parent, or NULL.
3310wxAccStatus wxWindowAccessible::GetParent(wxAccessible** parent)
3311{
3312 wxASSERT( GetWindow() != NULL );
3313 if (!GetWindow())
3314 return wxACC_FAIL;
3315
3316 wxWindow* parentWindow = GetWindow()->GetParent();
c6e2af45 3317 if (!parentWindow)
ed5317e5
JS
3318 {
3319 *parent = NULL;
3320 return wxACC_OK;
3321 }
3322 else
3323 {
3324 *parent = parentWindow->GetOrCreateAccessible();
3325 if (*parent)
3326 return wxACC_OK;
3327 else
3328 return wxACC_FAIL;
3329 }
3330}
3331
3332// Performs the default action. childId is 0 (the action for this object)
3333// or > 0 (the action for a child).
3334// Return wxACC_NOT_SUPPORTED if there is no default action for this
3335// window (e.g. an edit control).
66b9ec3d 3336wxAccStatus wxWindowAccessible::DoDefaultAction(int WXUNUSED(childId))
ed5317e5
JS
3337{
3338 wxASSERT( GetWindow() != NULL );
3339 if (!GetWindow())
3340 return wxACC_FAIL;
3341
3342 return wxACC_NOT_IMPLEMENTED;
3343}
3344
3345// Gets the default action for this object (0) or > 0 (the action for a child).
3346// Return wxACC_OK even if there is no action. actionName is the action, or the empty
3347// string if there is no action.
3348// The retrieved string describes the action that is performed on an object,
3349// not what the object does as a result. For example, a toolbar button that prints
3350// a document has a default action of "Press" rather than "Prints the current document."
66b9ec3d 3351wxAccStatus wxWindowAccessible::GetDefaultAction(int WXUNUSED(childId), wxString* WXUNUSED(actionName))
ed5317e5
JS
3352{
3353 wxASSERT( GetWindow() != NULL );
3354 if (!GetWindow())
3355 return wxACC_FAIL;
3356
3357 return wxACC_NOT_IMPLEMENTED;
3358}
3359
3360// Returns the description for this object or a child.
66b9ec3d 3361wxAccStatus wxWindowAccessible::GetDescription(int WXUNUSED(childId), wxString* description)
ed5317e5
JS
3362{
3363 wxASSERT( GetWindow() != NULL );
3364 if (!GetWindow())
3365 return wxACC_FAIL;
3366
dc6588e7 3367 wxString ht(GetWindow()->GetHelpTextAtPoint(wxDefaultPosition, wxHelpEvent::Origin_Keyboard));
ba889513 3368 if (!ht.empty())
2aefc528
JS
3369 {
3370 *description = ht;
3371 return wxACC_OK;
3372 }
ed5317e5
JS
3373 return wxACC_NOT_IMPLEMENTED;
3374}
3375
3376// Returns help text for this object or a child, similar to tooltip text.
66b9ec3d 3377wxAccStatus wxWindowAccessible::GetHelpText(int WXUNUSED(childId), wxString* helpText)
ed5317e5
JS
3378{
3379 wxASSERT( GetWindow() != NULL );
3380 if (!GetWindow())
3381 return wxACC_FAIL;
3382
dc6588e7 3383 wxString ht(GetWindow()->GetHelpTextAtPoint(wxDefaultPosition, wxHelpEvent::Origin_Keyboard));
ba889513 3384 if (!ht.empty())
ed5317e5
JS
3385 {
3386 *helpText = ht;
3387 return wxACC_OK;
3388 }
3389 return wxACC_NOT_IMPLEMENTED;
3390}
3391
3392// Returns the keyboard shortcut for this object or child.
3393// Return e.g. ALT+K
66b9ec3d 3394wxAccStatus wxWindowAccessible::GetKeyboardShortcut(int WXUNUSED(childId), wxString* WXUNUSED(shortcut))
ed5317e5
JS
3395{
3396 wxASSERT( GetWindow() != NULL );
3397 if (!GetWindow())
3398 return wxACC_FAIL;
3399
3400 return wxACC_NOT_IMPLEMENTED;
3401}
3402
3403// Returns a role constant.
3404wxAccStatus wxWindowAccessible::GetRole(int childId, wxAccRole* role)
3405{
3406 wxASSERT( GetWindow() != NULL );
3407 if (!GetWindow())
3408 return wxACC_FAIL;
3409
77ffb593 3410 // If a child, leave wxWidgets to call the function on the actual
2aefc528
JS
3411 // child object.
3412 if (childId > 0)
3413 return wxACC_NOT_IMPLEMENTED;
3414
3415 if (GetWindow()->IsKindOf(CLASSINFO(wxControl)))
3416 return wxACC_NOT_IMPLEMENTED;
3417#if wxUSE_STATUSBAR
3418 if (GetWindow()->IsKindOf(CLASSINFO(wxStatusBar)))
3419 return wxACC_NOT_IMPLEMENTED;
3420#endif
3421#if wxUSE_TOOLBAR
3422 if (GetWindow()->IsKindOf(CLASSINFO(wxToolBar)))
3423 return wxACC_NOT_IMPLEMENTED;
3424#endif
3425
3426 //*role = wxROLE_SYSTEM_CLIENT;
3427 *role = wxROLE_SYSTEM_CLIENT;
3428 return wxACC_OK;
3429
66b9ec3d 3430 #if 0
ed5317e5 3431 return wxACC_NOT_IMPLEMENTED;
66b9ec3d 3432 #endif
ed5317e5
JS
3433}
3434
3435// Returns a state constant.
3436wxAccStatus wxWindowAccessible::GetState(int childId, long* state)
3437{
3438 wxASSERT( GetWindow() != NULL );
3439 if (!GetWindow())
3440 return wxACC_FAIL;
3441
77ffb593 3442 // If a child, leave wxWidgets to call the function on the actual
2aefc528
JS
3443 // child object.
3444 if (childId > 0)
3445 return wxACC_NOT_IMPLEMENTED;
3446
3447 if (GetWindow()->IsKindOf(CLASSINFO(wxControl)))
3448 return wxACC_NOT_IMPLEMENTED;
3449
3450#if wxUSE_STATUSBAR
3451 if (GetWindow()->IsKindOf(CLASSINFO(wxStatusBar)))
3452 return wxACC_NOT_IMPLEMENTED;
3453#endif
3454#if wxUSE_TOOLBAR
3455 if (GetWindow()->IsKindOf(CLASSINFO(wxToolBar)))
3456 return wxACC_NOT_IMPLEMENTED;
3457#endif
3458
3459 *state = 0;
3460 return wxACC_OK;
3461
66b9ec3d 3462 #if 0
ed5317e5 3463 return wxACC_NOT_IMPLEMENTED;
66b9ec3d 3464 #endif
ed5317e5
JS
3465}
3466
3467// Returns a localized string representing the value for the object
3468// or child.
66b9ec3d 3469wxAccStatus wxWindowAccessible::GetValue(int WXUNUSED(childId), wxString* WXUNUSED(strValue))
ed5317e5
JS
3470{
3471 wxASSERT( GetWindow() != NULL );
3472 if (!GetWindow())
3473 return wxACC_FAIL;
3474
3475 return wxACC_NOT_IMPLEMENTED;
3476}
3477
3478// Selects the object or child.
66b9ec3d 3479wxAccStatus wxWindowAccessible::Select(int WXUNUSED(childId), wxAccSelectionFlags WXUNUSED(selectFlags))
ed5317e5
JS
3480{
3481 wxASSERT( GetWindow() != NULL );
3482 if (!GetWindow())
3483 return wxACC_FAIL;
3484
3485 return wxACC_NOT_IMPLEMENTED;
3486}
3487
3488// Gets the window with the keyboard focus.
3489// If childId is 0 and child is NULL, no object in
3490// this subhierarchy has the focus.
3491// If this object has the focus, child should be 'this'.
66b9ec3d 3492wxAccStatus wxWindowAccessible::GetFocus(int* WXUNUSED(childId), wxAccessible** WXUNUSED(child))
ed5317e5
JS
3493{
3494 wxASSERT( GetWindow() != NULL );
3495 if (!GetWindow())
3496 return wxACC_FAIL;
3497
3498 return wxACC_NOT_IMPLEMENTED;
3499}
3500
ca5c6ac3 3501#if wxUSE_VARIANT
ed5317e5
JS
3502// Gets a variant representing the selected children
3503// of this object.
3504// Acceptable values:
cab1a605 3505// - a null variant (IsNull() returns true)
ed5317e5
JS
3506// - a list variant (GetType() == wxT("list")
3507// - an integer representing the selected child element,
3508// or 0 if this object is selected (GetType() == wxT("long")
3509// - a "void*" pointer to a wxAccessible child object
66b9ec3d 3510wxAccStatus wxWindowAccessible::GetSelections(wxVariant* WXUNUSED(selections))
ed5317e5
JS
3511{
3512 wxASSERT( GetWindow() != NULL );
3513 if (!GetWindow())
3514 return wxACC_FAIL;
3515
3516 return wxACC_NOT_IMPLEMENTED;
3517}
ca5c6ac3 3518#endif // wxUSE_VARIANT
ed5317e5
JS
3519
3520#endif // wxUSE_ACCESSIBILITY
978af864
VZ
3521
3522// ----------------------------------------------------------------------------
3523// RTL support
3524// ----------------------------------------------------------------------------
3525
3526wxCoord
3527wxWindowBase::AdjustForLayoutDirection(wxCoord x,
3528 wxCoord width,
3529 wxCoord widthTotal) const
3530{
3531 if ( GetLayoutDirection() == wxLayout_RightToLeft )
3532 {
3533 x = widthTotal - x - width;
3534 }
3535
3536 return x;
3537}
3538
f35fdf7e 3539