]> git.saurik.com Git - wxWidgets.git/blame - src/common/wincmn.cpp
return radio box own help text when origin is Origin_Unknown to make sure GetHelpText...
[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
0118b60b 75// For reporting compile- and runtime version of GTK+ in the ctrl+alt+mclick dialog.
c1da5058 76// The gtk includes don't pull any other headers in, at least not on my system - MR
0118b60b 77#ifdef __WXGTK__
6ef708cd
PC
78 #ifdef __WXGTK20__
79 #include <gtk/gtkversion.h>
80 #else
81 #include <gtk/gtkfeatures.h>
82 #endif
0118b60b
MR
83#endif
84
8bb6b2c0
VZ
85#include "wx/platinfo.h"
86
e7445ff8
PC
87// Windows List
88WXDLLIMPEXP_DATA_CORE(wxWindowList) wxTopLevelWindows;
89
eeb0bee1 90// globals
8bb08801 91#if wxUSE_MENUS
eeb0bee1 92wxMenu *wxCurrentPopupMenu = NULL;
8bb08801 93#endif // wxUSE_MENUS
eeb0bee1 94
f03fc89f
VZ
95// ----------------------------------------------------------------------------
96// static data
97// ----------------------------------------------------------------------------
98
f03fc89f
VZ
99
100IMPLEMENT_ABSTRACT_CLASS(wxWindowBase, wxEvtHandler)
101
102// ----------------------------------------------------------------------------
103// event table
104// ----------------------------------------------------------------------------
105
106BEGIN_EVENT_TABLE(wxWindowBase, wxEvtHandler)
107 EVT_SYS_COLOUR_CHANGED(wxWindowBase::OnSysColourChanged)
108 EVT_INIT_DIALOG(wxWindowBase::OnInitDialog)
a02dc3e3 109 EVT_MIDDLE_DOWN(wxWindowBase::OnMiddleClick)
bd83cb56
VZ
110
111#if wxUSE_HELP
e11f4636 112 EVT_HELP(wxID_ANY, wxWindowBase::OnHelp)
bd83cb56
VZ
113#endif // wxUSE_HELP
114
f03fc89f
VZ
115END_EVENT_TABLE()
116
117// ============================================================================
118// implementation of the common functionality of the wxWindow class
119// ============================================================================
120
121// ----------------------------------------------------------------------------
122// initialization
123// ----------------------------------------------------------------------------
124
125// the default initialization
72795335 126wxWindowBase::wxWindowBase()
f03fc89f
VZ
127{
128 // no window yet, no parent nor children
d3b9f782 129 m_parent = NULL;
e11f4636 130 m_windowId = wxID_ANY;
f03fc89f
VZ
131
132 // no constraints on the minimal window size
133 m_minWidth =
422d0ff0 134 m_maxWidth = wxDefaultCoord;
f03fc89f 135 m_minHeight =
422d0ff0 136 m_maxHeight = wxDefaultCoord;
f03fc89f 137
9f884528
RD
138 // invalidiated cache value
139 m_bestSizeCache = wxDefaultSize;
140
eefe6d4b
VZ
141 // window are created enabled and visible by default
142 m_isShown =
e11f4636 143 m_isEnabled = true;
f03fc89f 144
f03fc89f
VZ
145 // the default event handler is just this window
146 m_eventHandler = this;
147
88ac883a 148#if wxUSE_VALIDATORS
f03fc89f 149 // no validator
d3b9f782 150 m_windowValidator = NULL;
88ac883a 151#endif // wxUSE_VALIDATORS
f03fc89f 152
1b69c815
VZ
153 // the colours/fonts are default for now, so leave m_font,
154 // m_backgroundColour and m_foregroundColour uninitialized and set those
08df3e44
VZ
155 m_hasBgCol =
156 m_hasFgCol =
e11f4636 157 m_hasFont = false;
f8ff87ed
VS
158 m_inheritBgCol =
159 m_inheritFgCol =
160 m_inheritFont = false;
e11f4636 161
f03fc89f 162 // no style bits
d80cd92a 163 m_exStyle =
f03fc89f 164 m_windowStyle = 0;
cab1a605 165
50c53860 166 m_backgroundStyle = wxBG_STYLE_SYSTEM;
f03fc89f 167
f03fc89f
VZ
168#if wxUSE_CONSTRAINTS
169 // no constraints whatsoever
d3b9f782
VZ
170 m_constraints = NULL;
171 m_constraintsInvolvedIn = NULL;
461e93f9
JS
172#endif // wxUSE_CONSTRAINTS
173
d3b9f782
VZ
174 m_windowSizer = NULL;
175 m_containingSizer = NULL;
e11f4636 176 m_autoLayout = false;
f03fc89f
VZ
177
178#if wxUSE_DRAG_AND_DROP
d3b9f782 179 m_dropTarget = NULL;
f03fc89f
VZ
180#endif // wxUSE_DRAG_AND_DROP
181
182#if wxUSE_TOOLTIPS
d3b9f782 183 m_tooltip = NULL;
f03fc89f 184#endif // wxUSE_TOOLTIPS
789295bf
VZ
185
186#if wxUSE_CARET
d3b9f782 187 m_caret = NULL;
789295bf 188#endif // wxUSE_CARET
a2d93e73 189
574c939e 190#if wxUSE_PALETTE
e11f4636 191 m_hasCustomPalette = false;
574c939e
KB
192#endif // wxUSE_PALETTE
193
ed5317e5
JS
194#if wxUSE_ACCESSIBILITY
195 m_accessible = NULL;
196#endif
197
566d84a7 198 m_virtualSize = wxDefaultSize;
1b69c815 199
d3b9f782 200 m_scrollHelper = NULL;
f4fe2f20 201
1b69c815 202 m_windowVariant = wxWINDOW_VARIANT_NORMAL;
ff9f7a12
SC
203#if wxUSE_SYSTEM_OPTIONS
204 if ( wxSystemOptions::HasOption(wxWINDOW_DEFAULT_VARIANT) )
205 {
206 m_windowVariant = (wxWindowVariant) wxSystemOptions::GetOptionInt( wxWINDOW_DEFAULT_VARIANT ) ;
207 }
208#endif
69d90995 209
a2d93e73 210 // Whether we're using the current theme for this window (wxGTK only for now)
e11f4636 211 m_themeEnabled = false;
1b69c815 212
c6212a0c
VZ
213 // This is set to true by SendDestroyEvent() which should be called by the
214 // most derived class to ensure that the destruction event is sent as soon
215 // as possible to allow its handlers to still see the undestroyed window
1b69c815 216 m_isBeingDeleted = false;
17808a75
VZ
217
218 m_freezeCount = 0;
f03fc89f
VZ
219}
220
221// common part of window creation process
222bool wxWindowBase::CreateBase(wxWindowBase *parent,
223 wxWindowID id,
74e3313b 224 const wxPoint& WXUNUSED(pos),
400a9e41 225 const wxSize& WXUNUSED(size),
f03fc89f 226 long style,
ac8d0c11 227 const wxValidator& wxVALIDATOR_PARAM(validator),
f03fc89f
VZ
228 const wxString& name)
229{
106844da
VZ
230#if wxUSE_STATBOX
231 // wxGTK doesn't allow to create controls with static box as the parent so
232 // this will result in a crash when the program is ported to wxGTK so warn
233 // the user about it
234
235 // if you get this assert, the correct solution is to create the controls
236 // as siblings of the static box
237 wxASSERT_MSG( !parent || !wxDynamicCast(parent, wxStaticBox),
238 _T("wxStaticBox can't be used as a window parent!") );
239#endif // wxUSE_STATBOX
240
925f154d
VZ
241 // ids are limited to 16 bits under MSW so if you care about portability,
242 // it's not a good idea to use ids out of this range (and negative ids are
77ffb593 243 // reserved for wxWidgets own usage)
f35fdf7e
VZ
244 wxASSERT_MSG( id == wxID_ANY || (id >= 0 && id < 32767) ||
245 (id >= wxID_AUTO_LOWEST && id <= wxID_AUTO_HIGHEST),
925f154d
VZ
246 _T("invalid id value") );
247
f03fc89f 248 // generate a new id if the user doesn't care about it
f35fdf7e
VZ
249 if ( id == wxID_ANY )
250 {
251 m_windowId = NewControlId();
f35fdf7e
VZ
252 }
253 else // valid id specified
254 {
255 m_windowId = id;
256 }
f03fc89f 257
e96248c4
VZ
258 // don't use SetWindowStyleFlag() here, this function should only be called
259 // to change the flag after creation as it tries to reflect the changes in
260 // flags by updating the window dynamically and we don't need this here
261 m_windowStyle = style;
262
f03fc89f 263 SetName(name);
f03fc89f 264 SetParent(parent);
674ac8b9
VZ
265
266#if wxUSE_VALIDATORS
8d99be5f 267 SetValidator(validator);
674ac8b9 268#endif // wxUSE_VALIDATORS
f03fc89f 269
8ae6ce07
VZ
270 // if the parent window has wxWS_EX_VALIDATE_RECURSIVELY set, we want to
271 // have it too - like this it's possible to set it only in the top level
272 // dialog/frame and all children will inherit it by defult
273 if ( parent && (parent->GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) )
274 {
9cb98d89 275 SetExtraStyle(GetExtraStyle() | wxWS_EX_VALIDATE_RECURSIVELY);
8ae6ce07
VZ
276 }
277
e11f4636 278 return true;
f03fc89f
VZ
279}
280
d63312a9
VZ
281bool wxWindowBase::ToggleWindowStyle(int flag)
282{
283 wxASSERT_MSG( flag, _T("flags with 0 value can't be toggled") );
284
285 bool rc;
286 long style = GetWindowStyleFlag();
287 if ( style & flag )
288 {
289 style &= ~flag;
290 rc = false;
291 }
292 else // currently off
293 {
294 style |= flag;
295 rc = true;
296 }
297
298 SetWindowStyleFlag(style);
299
300 return rc;
301}
302
f03fc89f
VZ
303// ----------------------------------------------------------------------------
304// destruction
305// ----------------------------------------------------------------------------
306
307// common clean up
308wxWindowBase::~wxWindowBase()
309{
349d1942
VS
310 wxASSERT_MSG( GetCapture() != this, wxT("attempt to destroy window with mouse capture") );
311
f03fc89f
VZ
312 // FIXME if these 2 cases result from programming errors in the user code
313 // we should probably assert here instead of silently fixing them
314
315 // Just in case the window has been Closed, but we're then deleting
316 // immediately: don't leave dangling pointers.
317 wxPendingDelete.DeleteObject(this);
318
319 // Just in case we've loaded a top-level window via LoadNativeDialog but
320 // we weren't a dialog class
222ed1d6 321 wxTopLevelWindows.DeleteObject((wxWindow*)this);
a23fd0e1 322
3bc9aac0 323#if wxUSE_MENUS
eeb0bee1
VZ
324 // The associated popup menu can still be alive, disassociate from it in
325 // this case
326 if ( wxCurrentPopupMenu && wxCurrentPopupMenu->GetInvokingWindow() == this )
327 wxCurrentPopupMenu->SetInvokingWindow(NULL);
3bc9aac0 328#endif // wxUSE_MENUS
eeb0bee1 329
223d09f6 330 wxASSERT_MSG( GetChildren().GetCount() == 0, wxT("children not destroyed") );
f03fc89f 331
f8ab85ae 332 // notify the parent about this window destruction
f09df8b2 333 if ( m_parent )
8e35ab96 334 m_parent->RemoveChild(this);
8e35ab96 335
789295bf 336#if wxUSE_CARET
a2b436fb 337 delete m_caret;
789295bf
VZ
338#endif // wxUSE_CARET
339
88ac883a 340#if wxUSE_VALIDATORS
a2b436fb 341 delete m_windowValidator;
88ac883a 342#endif // wxUSE_VALIDATORS
f03fc89f 343
f03fc89f
VZ
344#if wxUSE_CONSTRAINTS
345 // Have to delete constraints/sizer FIRST otherwise sizers may try to look
346 // at deleted windows as they delete themselves.
347 DeleteRelatedConstraints();
348
349 if ( m_constraints )
350 {
351 // This removes any dangling pointers to this window in other windows'
352 // constraintsInvolvedIn lists.
353 UnsetConstraints(m_constraints);
354 delete m_constraints;
355 m_constraints = NULL;
356 }
461e93f9
JS
357#endif // wxUSE_CONSTRAINTS
358
be90c029 359 if ( m_containingSizer )
12a3f227 360 m_containingSizer->Detach( (wxWindow*)this );
be90c029 361
a2b436fb 362 delete m_windowSizer;
f03fc89f 363
f03fc89f 364#if wxUSE_DRAG_AND_DROP
a2b436fb 365 delete m_dropTarget;
f03fc89f
VZ
366#endif // wxUSE_DRAG_AND_DROP
367
368#if wxUSE_TOOLTIPS
a2b436fb 369 delete m_tooltip;
f03fc89f 370#endif // wxUSE_TOOLTIPS
b0ee47ff 371
ed5317e5 372#if wxUSE_ACCESSIBILITY
a2b436fb 373 delete m_accessible;
ed5317e5 374#endif
d18d8bda
VS
375
376#if wxUSE_HELP
377 // NB: this has to be called unconditionally, because we don't know
378 // whether this window has associated help text or not
379 wxHelpProvider *helpProvider = wxHelpProvider::Get();
380 if ( helpProvider )
381 helpProvider->RemoveHelp(this);
382#endif
f03fc89f
VZ
383}
384
a3ac93e3
VZ
385bool wxWindowBase::IsBeingDeleted() const
386{
387 return m_isBeingDeleted ||
388 (!IsTopLevel() && m_parent && m_parent->IsBeingDeleted());
389}
390
602a2e02
VZ
391void wxWindowBase::SendDestroyEvent()
392{
c6212a0c
VZ
393 if ( m_isBeingDeleted )
394 {
395 // we could have been already called from a more derived class dtor,
396 // e.g. ~wxTLW calls us and so does ~wxWindow and the latter call
397 // should be simply ignored
398 return;
399 }
400
401 m_isBeingDeleted = true;
402
602a2e02
VZ
403 wxWindowDestroyEvent event;
404 event.SetEventObject(this);
405 event.SetId(GetId());
406 GetEventHandler()->ProcessEvent(event);
407}
408
f03fc89f
VZ
409bool wxWindowBase::Destroy()
410{
a79a6671
VZ
411 SendDestroyEvent();
412
f03fc89f
VZ
413 delete this;
414
e11f4636 415 return true;
f03fc89f
VZ
416}
417
418bool wxWindowBase::Close(bool force)
419{
420 wxCloseEvent event(wxEVT_CLOSE_WINDOW, m_windowId);
421 event.SetEventObject(this);
f03fc89f
VZ
422 event.SetCanVeto(!force);
423
e11f4636 424 // return false if window wasn't closed because the application vetoed the
f03fc89f 425 // close event
a50c5fcc 426 return HandleWindowEvent(event) && !event.GetVeto();
f03fc89f
VZ
427}
428
429bool wxWindowBase::DestroyChildren()
430{
222ed1d6 431 wxWindowList::compatibility_iterator node;
a23fd0e1 432 for ( ;; )
f03fc89f 433 {
a23fd0e1
VZ
434 // we iterate until the list becomes empty
435 node = GetChildren().GetFirst();
436 if ( !node )
437 break;
438
f03fc89f 439 wxWindow *child = node->GetData();
a23fd0e1 440
a79a6671
VZ
441 // note that we really want to delete it immediately so don't call the
442 // possible overridden Destroy() version which might not delete the
443 // child immediately resulting in problems with our (top level) child
444 // outliving its parent
445 child->wxWindowBase::Destroy();
a23fd0e1
VZ
446
447 wxASSERT_MSG( !GetChildren().Find(child),
223d09f6 448 wxT("child didn't remove itself using RemoveChild()") );
f03fc89f
VZ
449 }
450
e11f4636 451 return true;
f03fc89f
VZ
452}
453
454// ----------------------------------------------------------------------------
f68586e5 455// size/position related methods
f03fc89f
VZ
456// ----------------------------------------------------------------------------
457
458// centre the window with respect to its parent in either (or both) directions
1f464296 459void wxWindowBase::DoCentre(int dir)
f03fc89f 460{
1f464296
VZ
461 wxCHECK_RET( !(dir & wxCENTRE_ON_SCREEN) && GetParent(),
462 _T("this method only implements centering child windows") );
ef397583 463
1f464296 464 SetSize(GetRect().CentreIn(GetParent()->GetClientSize(), dir));
7631a292
RD
465}
466
f03fc89f
VZ
467// fits the window around the children
468void wxWindowBase::Fit()
469{
74205969 470 if ( !GetChildren().empty() )
f68586e5 471 {
1736f021 472 SetSize(GetBestSize());
f68586e5
VZ
473 }
474 //else: do nothing if we have no children
475}
f03fc89f 476
2b5f62a0
VZ
477// fits virtual size (ie. scrolled area etc.) around children
478void wxWindowBase::FitInside()
479{
480 if ( GetChildren().GetCount() > 0 )
481 {
482 SetVirtualSize( GetBestVirtualSize() );
483 }
484}
485
7d59475e
JS
486// On Mac, scrollbars are explicitly children.
487#ifdef __WXMAC__
488static bool wxHasRealChildren(const wxWindowBase* win)
489{
490 int realChildCount = 0;
cab1a605 491
7d59475e
JS
492 for ( wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst();
493 node;
494 node = node->GetNext() )
495 {
496 wxWindow *win = node->GetData();
497 if ( !win->IsTopLevel() && win->IsShown() && !win->IsKindOf(CLASSINFO(wxScrollBar)))
498 realChildCount ++;
499 }
500 return (realChildCount > 0);
501}
502#endif
ba889513 503
992b2ec4
VS
504void wxWindowBase::InvalidateBestSize()
505{
506 m_bestSizeCache = wxDefaultSize;
507
508 // parent's best size calculation may depend on its children's
5b7df27e
WS
509 // as long as child window we are in is not top level window itself
510 // (because the TLW size is never resized automatically)
511 // so let's invalidate it as well to be safe:
5ff84587 512 if (m_parent && !IsTopLevel())
992b2ec4
VS
513 m_parent->InvalidateBestSize();
514}
7d59475e 515
f68586e5
VZ
516// return the size best suited for the current window
517wxSize wxWindowBase::DoGetBestSize() const
518{
08a19f64 519 wxSize best;
2997ca30 520
ec5bb70d
VZ
521 if ( m_windowSizer )
522 {
7e0f7539 523 best = m_windowSizer->GetMinSize();
ec5bb70d
VZ
524 }
525#if wxUSE_CONSTRAINTS
526 else if ( m_constraints )
527 {
528 wxConstCast(this, wxWindowBase)->SatisfyConstraints();
529
530 // our minimal acceptable size is such that all our windows fit inside
531 int maxX = 0,
532 maxY = 0;
533
222ed1d6 534 for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
ec5bb70d
VZ
535 node;
536 node = node->GetNext() )
537 {
538 wxLayoutConstraints *c = node->GetData()->GetConstraints();
539 if ( !c )
540 {
541 // it's not normal that we have an unconstrained child, but
542 // what can we do about it?
543 continue;
544 }
545
546 int x = c->right.GetValue(),
547 y = c->bottom.GetValue();
548
549 if ( x > maxX )
550 maxX = x;
551
552 if ( y > maxY )
553 maxY = y;
554
555 // TODO: we must calculate the overlaps somehow, otherwise we
556 // will never return a size bigger than the current one :-(
557 }
558
08a19f64 559 best = wxSize(maxX, maxY);
ec5bb70d
VZ
560 }
561#endif // wxUSE_CONSTRAINTS
7d59475e
JS
562 else if ( !GetChildren().empty()
563#ifdef __WXMAC__
564 && wxHasRealChildren(this)
565#endif
566 )
f03fc89f 567 {
54af2461
VZ
568 // our minimal acceptable size is such that all our visible child
569 // windows fit inside
f68586e5
VZ
570 int maxX = 0,
571 maxY = 0;
572
222ed1d6 573 for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
f68586e5
VZ
574 node;
575 node = node->GetNext() )
42e69d6b 576 {
f68586e5 577 wxWindow *win = node->GetData();
54af2461
VZ
578 if ( win->IsTopLevel()
579 || !win->IsShown()
1e6feb95 580#if wxUSE_STATUSBAR
54af2461 581 || wxDynamicCast(win, wxStatusBar)
1e6feb95
VZ
582#endif // wxUSE_STATUSBAR
583 )
f68586e5
VZ
584 {
585 // dialogs and frames lie in different top level windows -
7d9fd004
VZ
586 // don't deal with them here; as for the status bars, they
587 // don't lie in the client area at all
f68586e5
VZ
588 continue;
589 }
590
591 int wx, wy, ww, wh;
592 win->GetPosition(&wx, &wy);
3f5513f5
VZ
593
594 // if the window hadn't been positioned yet, assume that it is in
595 // the origin
422d0ff0 596 if ( wx == wxDefaultCoord )
3f5513f5 597 wx = 0;
422d0ff0 598 if ( wy == wxDefaultCoord )
3f5513f5
VZ
599 wy = 0;
600
f68586e5
VZ
601 win->GetSize(&ww, &wh);
602 if ( wx + ww > maxX )
603 maxX = wx + ww;
604 if ( wy + wh > maxY )
605 maxY = wy + wh;
42e69d6b
VZ
606 }
607
08a19f64 608 best = wxSize(maxX, maxY);
f68586e5 609 }
997c7280 610 else // ! has children
f68586e5 611 {
c0bb586f
VZ
612 // for a generic window there is no natural best size so, if the
613 // minimal size is not set, use the current size but take care to
614 // remember it as minimal size for the next time because our best size
615 // should be constant: otherwise we could get into a situation when the
616 // window is initially at some size, then expanded to a larger size and
617 // then, when the containing window is shrunk back (because our initial
618 // best size had been used for computing the parent min size), we can't
619 // be shrunk back any more because our best size is now bigger
9240613a
VZ
620 wxSize size = GetMinSize();
621 if ( !size.IsFullySpecified() )
622 {
623 size.SetDefaults(GetSize());
624 wxConstCast(this, wxWindowBase)->SetMinSize(size);
625 }
c0bb586f
VZ
626
627 // return as-is, unadjusted by the client size difference.
9240613a 628 return size;
f03fc89f 629 }
08a19f64
RD
630
631 // Add any difference between size and client size
632 wxSize diff = GetSize() - GetClientSize();
633 best.x += wxMax(0, diff.x);
634 best.y += wxMax(0, diff.y);
635
636 return best;
f03fc89f
VZ
637}
638
333d7052
VZ
639// helper of GetWindowBorderSize(): as many ports don't implement support for
640// wxSYS_BORDER/EDGE_X/Y metrics in their wxSystemSettings, use hard coded
641// fallbacks in this case
d45a01e0 642static int wxGetMetricOrDefault(wxSystemMetric what, const wxWindowBase* win)
333d7052 643{
d45a01e0
PC
644 int rc = wxSystemSettings::GetMetric(
645 what, static_cast<wxWindow*>(const_cast<wxWindowBase*>(win)));
333d7052
VZ
646 if ( rc == -1 )
647 {
648 switch ( what )
649 {
650 case wxSYS_BORDER_X:
651 case wxSYS_BORDER_Y:
652 // 2D border is by default 1 pixel wide
653 rc = 1;
654 break;
655
656 case wxSYS_EDGE_X:
657 case wxSYS_EDGE_Y:
658 // 3D borders are by default 2 pixels
659 rc = 2;
660 break;
661
662 default:
663 wxFAIL_MSG( _T("unexpected wxGetMetricOrDefault() argument") );
664 rc = 0;
665 }
666 }
667
668 return rc;
669}
670
671wxSize wxWindowBase::GetWindowBorderSize() const
672{
673 wxSize size;
674
675 switch ( GetBorder() )
676 {
677 case wxBORDER_NONE:
678 // nothing to do, size is already (0, 0)
679 break;
680
681 case wxBORDER_SIMPLE:
682 case wxBORDER_STATIC:
d45a01e0
PC
683 size.x = wxGetMetricOrDefault(wxSYS_BORDER_X, this);
684 size.y = wxGetMetricOrDefault(wxSYS_BORDER_Y, this);
333d7052
VZ
685 break;
686
687 case wxBORDER_SUNKEN:
688 case wxBORDER_RAISED:
d45a01e0
PC
689 size.x = wxMax(wxGetMetricOrDefault(wxSYS_EDGE_X, this),
690 wxGetMetricOrDefault(wxSYS_BORDER_X, this));
691 size.y = wxMax(wxGetMetricOrDefault(wxSYS_EDGE_Y, this),
692 wxGetMetricOrDefault(wxSYS_BORDER_Y, this));
333d7052
VZ
693 break;
694
695 case wxBORDER_DOUBLE:
d45a01e0
PC
696 size.x = wxGetMetricOrDefault(wxSYS_EDGE_X, this) +
697 wxGetMetricOrDefault(wxSYS_BORDER_X, this);
698 size.y = wxGetMetricOrDefault(wxSYS_EDGE_Y, this) +
699 wxGetMetricOrDefault(wxSYS_BORDER_Y, this);
333d7052
VZ
700 break;
701
702 default:
703 wxFAIL_MSG(_T("Unknown border style."));
704 break;
705 }
706
707 // we have borders on both sides
708 return size*2;
709}
9f884528 710
170acdc9 711wxSize wxWindowBase::GetEffectiveMinSize() const
400a9e41 712{
9f884528
RD
713 // merge the best size with the min size, giving priority to the min size
714 wxSize min = GetMinSize();
1b942d5f 715
9f884528 716 if (min.x == wxDefaultCoord || min.y == wxDefaultCoord)
400a9e41 717 {
9f884528
RD
718 wxSize best = GetBestSize();
719 if (min.x == wxDefaultCoord) min.x = best.x;
720 if (min.y == wxDefaultCoord) min.y = best.y;
17c48da8 721 }
1b942d5f 722
9f884528
RD
723 return min;
724}
17c48da8 725
26f7724c
RR
726wxSize wxWindowBase::GetBestSize() const
727{
728 if ((!m_windowSizer) && (m_bestSizeCache.IsFullySpecified()))
729 return m_bestSizeCache;
1b942d5f 730
26f7724c
RR
731 return DoGetBestSize();
732}
42cfa184 733
e81c7155 734void wxWindowBase::SetMinSize(const wxSize& minSize)
1b942d5f
FM
735{
736 m_minWidth = minSize.x;
737 m_minHeight = minSize.y;
e81c7155
RR
738}
739
740void wxWindowBase::SetMaxSize(const wxSize& maxSize)
1b942d5f
FM
741{
742 m_maxWidth = maxSize.x;
e81c7155
RR
743 m_maxHeight = maxSize.y;
744}
745
170acdc9 746void wxWindowBase::SetInitialSize(const wxSize& size)
9f884528
RD
747{
748 // Set the min size to the size passed in. This will usually either be
749 // wxDefaultSize or the size passed to this window's ctor/Create function.
750 SetMinSize(size);
751
752 // Merge the size with the best size if needed
170acdc9 753 wxSize best = GetEffectiveMinSize();
cab1a605 754
9f884528
RD
755 // If the current size doesn't match then change it
756 if (GetSize() != best)
757 SetSize(best);
400a9e41
VZ
758}
759
9f884528 760
1e6feb95
VZ
761// by default the origin is not shifted
762wxPoint wxWindowBase::GetClientAreaOrigin() const
763{
c47addef 764 return wxPoint(0,0);
1e6feb95
VZ
765}
766
301d7a0d
VS
767wxSize wxWindowBase::ClientToWindowSize(const wxSize& size) const
768{
769 const wxSize diff(GetSize() - GetClientSize());
770
771 return wxSize(size.x == -1 ? -1 : size.x + diff.x,
772 size.y == -1 ? -1 : size.y + diff.y);
773}
774
775wxSize wxWindowBase::WindowToClientSize(const wxSize& size) const
776{
777 const wxSize diff(GetSize() - GetClientSize());
778
779 return wxSize(size.x == -1 ? -1 : size.x - diff.x,
780 size.y == -1 ? -1 : size.y - diff.y);
781}
782
69d90995
SC
783void wxWindowBase::SetWindowVariant( wxWindowVariant variant )
784{
1b69c815
VZ
785 if ( m_windowVariant != variant )
786 {
787 m_windowVariant = variant;
69d90995 788
1b69c815
VZ
789 DoSetWindowVariant(variant);
790 }
69d90995
SC
791}
792
793void wxWindowBase::DoSetWindowVariant( wxWindowVariant variant )
794{
1b69c815
VZ
795 // adjust the font height to correspond to our new variant (notice that
796 // we're only called if something really changed)
797 wxFont font = GetFont();
798 int size = font.GetPointSize();
69d90995
SC
799 switch ( variant )
800 {
1b69c815
VZ
801 case wxWINDOW_VARIANT_NORMAL:
802 break;
803
804 case wxWINDOW_VARIANT_SMALL:
805 size *= 3;
806 size /= 4;
807 break;
808
809 case wxWINDOW_VARIANT_MINI:
810 size *= 2;
811 size /= 3;
812 break;
813
814 case wxWINDOW_VARIANT_LARGE:
815 size *= 5;
816 size /= 4;
817 break;
818
69d90995
SC
819 default:
820 wxFAIL_MSG(_T("unexpected window variant"));
1b69c815 821 break;
69d90995 822 }
1b69c815
VZ
823
824 font.SetPointSize(size);
825 SetFont(font);
69d90995
SC
826}
827
b21f4960
RR
828void wxWindowBase::DoSetSizeHints( int minW, int minH,
829 int maxW, int maxH,
f36978ba 830 int WXUNUSED(incW), int WXUNUSED(incH) )
b21f4960
RR
831{
832 wxCHECK_RET( (minW == wxDefaultCoord || maxW == wxDefaultCoord || minW <= maxW) &&
833 (minH == wxDefaultCoord || maxH == wxDefaultCoord || minH <= maxH),
834 _T("min width/height must be less than max width/height!") );
835
836 m_minWidth = minW;
837 m_maxWidth = maxW;
838 m_minHeight = minH;
839 m_maxHeight = maxH;
840}
841
842
f944aec0
VS
843#if WXWIN_COMPATIBILITY_2_8
844void wxWindowBase::SetVirtualSizeHints(int WXUNUSED(minW), int WXUNUSED(minH),
845 int WXUNUSED(maxW), int WXUNUSED(maxH))
566d84a7 846{
566d84a7
RL
847}
848
f944aec0
VS
849void wxWindowBase::SetVirtualSizeHints(const wxSize& WXUNUSED(minsize),
850 const wxSize& WXUNUSED(maxsize))
566d84a7 851{
f944aec0
VS
852}
853#endif // WXWIN_COMPATIBILITY_2_8
1e2a653b 854
f944aec0
VS
855void wxWindowBase::DoSetVirtualSize( int x, int y )
856{
1e2a653b 857 m_virtualSize = wxSize(x, y);
566d84a7
RL
858}
859
860wxSize wxWindowBase::DoGetVirtualSize() const
861{
143e2719
VZ
862 // we should use the entire client area so if it is greater than our
863 // virtual size, expand it to fit (otherwise if the window is big enough we
864 // wouldn't be using parts of it)
c20ab85b 865 wxSize size = GetClientSize();
143e2719 866 if ( m_virtualSize.x > size.x )
c20ab85b
VZ
867 size.x = m_virtualSize.x;
868
143e2719 869 if ( m_virtualSize.y >= size.y )
c20ab85b
VZ
870 size.y = m_virtualSize.y;
871
872 return size;
566d84a7
RL
873}
874
3c81c9aa
VZ
875void wxWindowBase::DoGetScreenPosition(int *x, int *y) const
876{
877 // screen position is the same as (0, 0) in client coords for non TLWs (and
878 // TLWs override this method)
879 if ( x )
880 *x = 0;
881 if ( y )
882 *y = 0;
883
aa738eb8 884 ClientToScreen(x, y);
3c81c9aa
VZ
885}
886
ecdc1183 887void wxWindowBase::SendSizeEvent(int flags)
0dba08dd
VZ
888{
889 wxSizeEvent event(GetSize(), GetId());
890 event.SetEventObject(this);
ecdc1183
VZ
891 if ( flags & wxSEND_EVENT_POST )
892 wxPostEvent(this, event);
893 else
894 HandleWindowEvent(event);
0dba08dd
VZ
895}
896
ecdc1183 897void wxWindowBase::SendSizeEventToParent(int flags)
0dba08dd
VZ
898{
899 wxWindow * const parent = GetParent();
900 if ( parent && !parent->IsBeingDeleted() )
ecdc1183 901 parent->SendSizeEvent(flags);
0dba08dd
VZ
902}
903
f03fc89f
VZ
904// ----------------------------------------------------------------------------
905// show/hide/enable/disable the window
906// ----------------------------------------------------------------------------
907
908bool wxWindowBase::Show(bool show)
909{
910 if ( show != m_isShown )
911 {
912 m_isShown = show;
913
e11f4636 914 return true;
f03fc89f
VZ
915 }
916 else
917 {
e11f4636 918 return false;
f03fc89f
VZ
919 }
920}
921
47a8a4d5 922bool wxWindowBase::IsEnabled() const
f03fc89f 923{
47a8a4d5
VZ
924 return IsThisEnabled() && (IsTopLevel() || !GetParent() || GetParent()->IsEnabled());
925}
f03fc89f 926
47a8a4d5
VZ
927void wxWindowBase::NotifyWindowOnEnableChange(bool enabled)
928{
929#ifndef wxHAS_NATIVE_ENABLED_MANAGEMENT
930 DoEnable(enabled);
931#endif // !defined(wxHAS_NATIVE_ENABLED_MANAGEMENT)
932
933 OnEnabled(enabled);
934
935 // If we are top-level then the logic doesn't apply - otherwise
936 // showing a modal dialog would result in total greying out (and ungreying
937 // out later) of everything which would be really ugly
938 if ( IsTopLevel() )
939 return;
940
941 for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
942 node;
943 node = node->GetNext() )
f03fc89f 944 {
47a8a4d5
VZ
945 wxWindowBase * const child = node->GetData();
946 if ( !child->IsTopLevel() && child->IsThisEnabled() )
947 child->NotifyWindowOnEnableChange(enabled);
948 }
949}
950
951bool wxWindowBase::Enable(bool enable)
952{
953 if ( enable == IsThisEnabled() )
e11f4636 954 return false;
47a8a4d5
VZ
955
956 m_isEnabled = enable;
957
958#ifdef wxHAS_NATIVE_ENABLED_MANAGEMENT
959 DoEnable(enable);
960#else // !defined(wxHAS_NATIVE_ENABLED_MANAGEMENT)
961 wxWindowBase * const parent = GetParent();
962 if( !IsTopLevel() && parent && !parent->IsEnabled() )
963 {
964 return true;
f03fc89f 965 }
47a8a4d5
VZ
966#endif // !defined(wxHAS_NATIVE_ENABLED_MANAGEMENT)
967
968 NotifyWindowOnEnableChange(enable);
969
970 return true;
f03fc89f 971}
9c72cf76 972
865a74c7 973bool wxWindowBase::IsShownOnScreen() const
9c72cf76 974{
8a6a997f
VS
975 // A window is shown on screen if it itself is shown and so are all its
976 // parents. But if a window is toplevel one, then its always visible on
977 // screen if IsShown() returns true, even if it has a hidden parent.
865a74c7 978 return IsShown() &&
8a6a997f 979 (IsTopLevel() || GetParent() == NULL || GetParent()->IsShownOnScreen());
9c72cf76
VS
980}
981
34636400
VZ
982// ----------------------------------------------------------------------------
983// RTTI
984// ----------------------------------------------------------------------------
985
986bool wxWindowBase::IsTopLevel() const
987{
e11f4636 988 return false;
34636400 989}
f03fc89f 990
1c8e5c51
VS
991// ----------------------------------------------------------------------------
992// Freeze/Thaw
993// ----------------------------------------------------------------------------
994
995void wxWindowBase::Freeze()
996{
997 if ( !m_freezeCount++ )
998 {
999 // physically freeze this window:
1000 DoFreeze();
1001
1002 // and recursively freeze all children:
1003 for ( wxWindowList::iterator i = GetChildren().begin();
1004 i != GetChildren().end(); ++i )
1005 {
1006 wxWindow *child = *i;
1007 if ( child->IsTopLevel() )
1008 continue;
1009
1010 child->Freeze();
1011 }
1012 }
1013}
1014
1015void wxWindowBase::Thaw()
1016{
1017 wxASSERT_MSG( m_freezeCount, "Thaw() without matching Freeze()" );
1018
1019 if ( !--m_freezeCount )
1020 {
1021 // recursively thaw all children:
1022 for ( wxWindowList::iterator i = GetChildren().begin();
1023 i != GetChildren().end(); ++i )
1024 {
1025 wxWindow *child = *i;
1026 if ( child->IsTopLevel() )
1027 continue;
1028
1029 child->Thaw();
1030 }
1031
1032 // physically thaw this window:
1033 DoThaw();
1034 }
1035}
1036
f03fc89f
VZ
1037// ----------------------------------------------------------------------------
1038// reparenting the window
1039// ----------------------------------------------------------------------------
1040
1041void wxWindowBase::AddChild(wxWindowBase *child)
1042{
223d09f6 1043 wxCHECK_RET( child, wxT("can't add a NULL child") );
f03fc89f 1044
f6bcfd97
BP
1045 // this should never happen and it will lead to a crash later if it does
1046 // because RemoveChild() will remove only one node from the children list
1047 // and the other(s) one(s) will be left with dangling pointers in them
222ed1d6 1048 wxASSERT_MSG( !GetChildren().Find((wxWindow*)child), _T("AddChild() called twice") );
f6bcfd97 1049
222ed1d6 1050 GetChildren().Append((wxWindow*)child);
f03fc89f 1051 child->SetParent(this);
1c8e5c51 1052
76be36e4 1053 // adding a child while frozen will assert when thawed, so freeze it as if
1c8e5c51
VS
1054 // it had been already present when we were frozen
1055 if ( IsFrozen() && !child->IsTopLevel() )
1056 child->Freeze();
f03fc89f
VZ
1057}
1058
1059void wxWindowBase::RemoveChild(wxWindowBase *child)
1060{
223d09f6 1061 wxCHECK_RET( child, wxT("can't remove a NULL child") );
f03fc89f 1062
1c8e5c51
VS
1063 // removing a child while frozen may result in permanently frozen window
1064 // if used e.g. from Reparent(), so thaw it
76be36e4
VZ
1065 //
1066 // NB: IsTopLevel() doesn't return true any more when a TLW child is being
1067 // removed from its ~wxWindowBase, so check for IsBeingDeleted() too
1068 if ( IsFrozen() && !child->IsBeingDeleted() && !child->IsTopLevel() )
1c8e5c51
VS
1069 child->Thaw();
1070
222ed1d6
MB
1071 GetChildren().DeleteObject((wxWindow *)child);
1072 child->SetParent(NULL);
f03fc89f 1073}
439b3bf1 1074
f03fc89f
VZ
1075bool wxWindowBase::Reparent(wxWindowBase *newParent)
1076{
1077 wxWindow *oldParent = GetParent();
1078 if ( newParent == oldParent )
1079 {
1080 // nothing done
e11f4636 1081 return false;
f03fc89f
VZ
1082 }
1083
47a8a4d5
VZ
1084 const bool oldEnabledState = IsEnabled();
1085
f03fc89f
VZ
1086 // unlink this window from the existing parent.
1087 if ( oldParent )
1088 {
1089 oldParent->RemoveChild(this);
1090 }
1091 else
1092 {
222ed1d6 1093 wxTopLevelWindows.DeleteObject((wxWindow *)this);
f03fc89f
VZ
1094 }
1095
1096 // add it to the new one
1097 if ( newParent )
1098 {
1099 newParent->AddChild(this);
1100 }
1101 else
1102 {
222ed1d6 1103 wxTopLevelWindows.Append((wxWindow *)this);
f03fc89f
VZ
1104 }
1105
47a8a4d5
VZ
1106 // We need to notify window (and its subwindows) if by changing the parent
1107 // we also change our enabled/disabled status.
1108 const bool newEnabledState = IsEnabled();
1109 if ( newEnabledState != oldEnabledState )
1110 {
1111 NotifyWindowOnEnableChange(newEnabledState);
1112 }
1113
e11f4636 1114 return true;
f03fc89f
VZ
1115}
1116
1117// ----------------------------------------------------------------------------
1118// event handler stuff
1119// ----------------------------------------------------------------------------
1120
7f853dd0 1121void wxWindowBase::SetEventHandler(wxEvtHandler *handler)
f03fc89f 1122{
7f853dd0
FM
1123 wxCHECK_RET(handler != NULL, "SetEventHandler(NULL) called");
1124
1125 m_eventHandler = handler;
1126}
1127
1128void wxWindowBase::SetNextHandler(wxEvtHandler *WXUNUSED(handler))
1129{
1130 // disable wxEvtHandler chain mechanism for wxWindows:
1131 // wxWindow uses its own stack mechanism which doesn't mix well with wxEvtHandler's one
1132
1133 wxFAIL_MSG("wxWindow cannot be part of a wxEvtHandler chain");
1134}
1135void wxWindowBase::SetPreviousHandler(wxEvtHandler *WXUNUSED(handler))
1136{
1137 // we can't simply wxFAIL here as in SetNextHandler: in fact the last
1138 // handler of our stack when is destroyed will be Unlink()ed and thus
1139 // will call this function to update the pointer of this window...
1140
1141 //wxFAIL_MSG("wxWindow cannot be part of a wxEvtHandler chain");
1142}
1143
1144void wxWindowBase::PushEventHandler(wxEvtHandler *handlerToPush)
1145{
1146 wxCHECK_RET( handlerToPush != NULL, "PushEventHandler(NULL) called" );
1147
1148 // the new handler is going to be part of the wxWindow stack of event handlers:
1149 // it can't be part also of an event handler double-linked chain:
1150 wxASSERT_MSG(handlerToPush->IsUnlinked(),
1151 "The handler being pushed in the wxWindow stack shouldn't be part of "
1152 "a wxEvtHandler chain; call Unlink() on it first");
1153
3a074ba8 1154 wxEvtHandler *handlerOld = GetEventHandler();
7f853dd0
FM
1155 wxCHECK_RET( handlerOld, "an old event handler is NULL?" );
1156
1157 // now use wxEvtHandler double-linked list to implement a stack:
1158 handlerToPush->SetNextHandler(handlerOld);
3a074ba8 1159
7f853dd0
FM
1160 if (handlerOld != this)
1161 handlerOld->SetPreviousHandler(handlerToPush);
3a074ba8 1162
7f853dd0 1163 SetEventHandler(handlerToPush);
3a074ba8 1164
7f853dd0
FM
1165#ifdef __WXDEBUG__
1166 // final checks of the operations done above:
1167 wxASSERT_MSG( handlerToPush->GetPreviousHandler() == NULL,
1168 "the first handler of the wxWindow stack should have no previous handlers set" );
1169 wxASSERT_MSG( handlerToPush->GetNextHandler() != NULL,
1170 "the first handler of the wxWindow stack should have non-NULL next handler" );
1171
1172 wxEvtHandler* pLast = handlerToPush;
1173 while (pLast && pLast != this)
1174 pLast = pLast->GetNextHandler();
1175 wxASSERT_MSG( pLast->GetNextHandler() == NULL,
1176 "the last handler of the wxWindow stack should have this window as next handler" );
1177#endif
f03fc89f
VZ
1178}
1179
1180wxEvtHandler *wxWindowBase::PopEventHandler(bool deleteHandler)
1181{
7f853dd0 1182 // we need to pop the wxWindow stack, i.e. we need to remove the first handler
3a074ba8 1183
7f853dd0
FM
1184 wxEvtHandler *firstHandler = GetEventHandler();
1185 wxCHECK_MSG( firstHandler != NULL, NULL, "wxWindow cannot have a NULL event handler" );
1186 wxCHECK_MSG( firstHandler != this, NULL, "cannot pop the wxWindow itself" );
1187 wxCHECK_MSG( firstHandler->GetPreviousHandler() == NULL, NULL,
1188 "the first handler of the wxWindow stack should have no previous handlers set" );
3a074ba8 1189
7f853dd0
FM
1190 wxEvtHandler *secondHandler = firstHandler->GetNextHandler();
1191 wxCHECK_MSG( secondHandler != NULL, NULL,
1192 "the first handler of the wxWindow stack should have non-NULL next handler" );
1193
1194 firstHandler->SetNextHandler(NULL);
1195 secondHandler->SetPreviousHandler(NULL);
1196
1197 // now firstHandler is completely unlinked; set secondHandler as the new window event handler
1198 SetEventHandler(secondHandler);
1199
1200 if ( deleteHandler )
1201 {
1202 delete firstHandler;
1203 firstHandler = NULL;
f03fc89f
VZ
1204 }
1205
7f853dd0 1206 return firstHandler;
f03fc89f
VZ
1207}
1208
7f853dd0 1209bool wxWindowBase::RemoveEventHandler(wxEvtHandler *handlerToRemove)
2e36d5cf 1210{
7f853dd0
FM
1211 wxCHECK_MSG( handlerToRemove != NULL, false, "RemoveEventHandler(NULL) called" );
1212 wxCHECK_MSG( handlerToRemove != this, false, "Cannot remove the window itself" );
1213
1214 if (handlerToRemove == GetEventHandler())
1215 {
1216 // removing the first event handler is equivalent to "popping" the stack
1217 PopEventHandler(false);
1218 return true;
1219 }
2e36d5cf 1220
7f853dd0
FM
1221 // NOTE: the wxWindow event handler list is always terminated with "this" handler
1222 wxEvtHandler *handlerCur = GetEventHandler()->GetNextHandler();
1223 while ( handlerCur != this )
2e36d5cf
VZ
1224 {
1225 wxEvtHandler *handlerNext = handlerCur->GetNextHandler();
1226
7f853dd0 1227 if ( handlerCur == handlerToRemove )
2e36d5cf 1228 {
7f853dd0 1229 handlerCur->Unlink();
2e36d5cf 1230
7f853dd0
FM
1231 wxASSERT_MSG( handlerCur != GetEventHandler(),
1232 "the case Remove == Pop should was already handled" );
e11f4636 1233 return true;
2e36d5cf
VZ
1234 }
1235
2e36d5cf
VZ
1236 handlerCur = handlerNext;
1237 }
1238
1239 wxFAIL_MSG( _T("where has the event handler gone?") );
1240
e11f4636 1241 return false;
2e36d5cf
VZ
1242}
1243
937013e0
VS
1244bool wxWindowBase::HandleWindowEvent(wxEvent& event) const
1245{
7f853dd0 1246 // SafelyProcessEvent() will handle exceptions nicely
937013e0
VS
1247 return GetEventHandler()->SafelyProcessEvent(event);
1248}
1249
f03fc89f 1250// ----------------------------------------------------------------------------
1b69c815 1251// colours, fonts &c
f03fc89f
VZ
1252// ----------------------------------------------------------------------------
1253
b8e7b673
VZ
1254void wxWindowBase::InheritAttributes()
1255{
8afef133 1256 const wxWindowBase * const parent = GetParent();
b8e7b673
VZ
1257 if ( !parent )
1258 return;
1259
1260 // we only inherit attributes which had been explicitly set for the parent
1261 // which ensures that this only happens if the user really wants it and
1262 // not by default which wouldn't make any sense in modern GUIs where the
1263 // controls don't all use the same fonts (nor colours)
f8ff87ed 1264 if ( parent->m_inheritFont && !m_hasFont )
b8e7b673
VZ
1265 SetFont(parent->GetFont());
1266
1267 // in addition, there is a possibility to explicitly forbid inheriting
1268 // colours at each class level by overriding ShouldInheritColours()
1269 if ( ShouldInheritColours() )
1270 {
f8ff87ed 1271 if ( parent->m_inheritFgCol && !m_hasFgCol )
b8e7b673
VZ
1272 SetForegroundColour(parent->GetForegroundColour());
1273
eb96212b
VZ
1274 // inheriting (solid) background colour is wrong as it totally breaks
1275 // any kind of themed backgrounds
1276 //
1277 // instead, the controls should use the same background as their parent
1278 // (ideally by not drawing it at all)
1279#if 0
f8ff87ed 1280 if ( parent->m_inheritBgCol && !m_hasBgCol )
b8e7b673 1281 SetBackgroundColour(parent->GetBackgroundColour());
eb96212b 1282#endif // 0
b8e7b673
VZ
1283 }
1284}
1285
1b69c815
VZ
1286/* static */ wxVisualAttributes
1287wxWindowBase::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
1288{
1289 // it is important to return valid values for all attributes from here,
1290 // GetXXX() below rely on this
1291 wxVisualAttributes attrs;
1292 attrs.font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
1293 attrs.colFg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
1b69c815 1294
0477a857
JS
1295 // On Smartphone/PocketPC, wxSYS_COLOUR_WINDOW is a better reflection of
1296 // the usual background colour than wxSYS_COLOUR_BTNFACE.
1297 // It's a pity that wxSYS_COLOUR_WINDOW isn't always a suitable background
1298 // colour on other platforms.
1299
1300#if defined(__WXWINCE__) && (defined(__SMARTPHONE__) || defined(__POCKETPC__))
1301 attrs.colBg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
1302#else
1303 attrs.colBg = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE);
1304#endif
1b69c815
VZ
1305 return attrs;
1306}
1307
1308wxColour wxWindowBase::GetBackgroundColour() const
1309{
1117d56f 1310 if ( !m_backgroundColour.IsOk() )
1b69c815
VZ
1311 {
1312 wxASSERT_MSG( !m_hasBgCol, _T("we have invalid explicit bg colour?") );
1313
1314 // get our default background colour
1315 wxColour colBg = GetDefaultAttributes().colBg;
1316
1317 // we must return some valid colour to avoid redoing this every time
1318 // and also to avoid surprizing the applications written for older
77ffb593 1319 // wxWidgets versions where GetBackgroundColour() always returned
1b69c815
VZ
1320 // something -- so give them something even if it doesn't make sense
1321 // for this window (e.g. it has a themed background)
1322 if ( !colBg.Ok() )
1323 colBg = GetClassDefaultAttributes().colBg;
1324
f604c658 1325 return colBg;
1b69c815 1326 }
f604c658
VS
1327 else
1328 return m_backgroundColour;
1b69c815
VZ
1329}
1330
1331wxColour wxWindowBase::GetForegroundColour() const
1332{
1333 // logic is the same as above
1334 if ( !m_hasFgCol && !m_foregroundColour.Ok() )
1335 {
1b69c815
VZ
1336 wxColour colFg = GetDefaultAttributes().colFg;
1337
1117d56f 1338 if ( !colFg.IsOk() )
1b69c815
VZ
1339 colFg = GetClassDefaultAttributes().colFg;
1340
f604c658 1341 return colFg;
1b69c815 1342 }
f604c658
VS
1343 else
1344 return m_foregroundColour;
1b69c815
VZ
1345}
1346
f03fc89f
VZ
1347bool wxWindowBase::SetBackgroundColour( const wxColour &colour )
1348{
cab1a605 1349 if ( colour == m_backgroundColour )
e11f4636 1350 return false;
f03fc89f 1351
1117d56f 1352 m_hasBgCol = colour.IsOk();
17bcd9a6
VZ
1353 if ( m_backgroundStyle != wxBG_STYLE_CUSTOM )
1354 m_backgroundStyle = m_hasBgCol ? wxBG_STYLE_COLOUR : wxBG_STYLE_SYSTEM;
1355
f8ff87ed 1356 m_inheritBgCol = m_hasBgCol;
f03fc89f 1357 m_backgroundColour = colour;
44dfb5ce 1358 SetThemeEnabled( !m_hasBgCol && !m_foregroundColour.Ok() );
e11f4636 1359 return true;
f03fc89f
VZ
1360}
1361
1362bool wxWindowBase::SetForegroundColour( const wxColour &colour )
1363{
44dfb5ce 1364 if (colour == m_foregroundColour )
e11f4636 1365 return false;
f03fc89f 1366
1117d56f 1367 m_hasFgCol = colour.IsOk();
f8ff87ed 1368 m_inheritFgCol = m_hasFgCol;
f03fc89f 1369 m_foregroundColour = colour;
44dfb5ce 1370 SetThemeEnabled( !m_hasFgCol && !m_backgroundColour.Ok() );
e11f4636 1371 return true;
f03fc89f
VZ
1372}
1373
1374bool wxWindowBase::SetCursor(const wxCursor& cursor)
1375{
8a9c2246
VZ
1376 // setting an invalid cursor is ok, it means that we don't have any special
1377 // cursor
a3ab1c18 1378 if ( m_cursor.IsSameAs(cursor) )
f03fc89f
VZ
1379 {
1380 // no change
e11f4636 1381 return false;
f03fc89f
VZ
1382 }
1383
8a9c2246 1384 m_cursor = cursor;
f03fc89f 1385
e11f4636 1386 return true;
f03fc89f
VZ
1387}
1388
f604c658 1389wxFont wxWindowBase::GetFont() const
1b69c815
VZ
1390{
1391 // logic is the same as in GetBackgroundColour()
1117d56f 1392 if ( !m_font.IsOk() )
1b69c815
VZ
1393 {
1394 wxASSERT_MSG( !m_hasFont, _T("we have invalid explicit font?") );
1395
1396 wxFont font = GetDefaultAttributes().font;
1117d56f 1397 if ( !font.IsOk() )
1b69c815
VZ
1398 font = GetClassDefaultAttributes().font;
1399
f604c658 1400 return font;
1b69c815 1401 }
f604c658
VS
1402 else
1403 return m_font;
1b69c815
VZ
1404}
1405
f03fc89f
VZ
1406bool wxWindowBase::SetFont(const wxFont& font)
1407{
1b69c815 1408 if ( font == m_font )
f03fc89f
VZ
1409 {
1410 // no change
e11f4636 1411 return false;
f03fc89f
VZ
1412 }
1413
1b69c815 1414 m_font = font;
1117d56f 1415 m_hasFont = font.IsOk();
f8ff87ed 1416 m_inheritFont = m_hasFont;
23895080 1417
583d7e55
VS
1418 InvalidateBestSize();
1419
e11f4636 1420 return true;
f03fc89f
VZ
1421}
1422
b95edd47
VZ
1423#if wxUSE_PALETTE
1424
1425void wxWindowBase::SetPalette(const wxPalette& pal)
1426{
e11f4636 1427 m_hasCustomPalette = true;
b95edd47
VZ
1428 m_palette = pal;
1429
1430 // VZ: can anyone explain me what do we do here?
1431 wxWindowDC d((wxWindow *) this);
1432 d.SetPalette(pal);
1433}
1434
1435wxWindow *wxWindowBase::GetAncestorWithCustomPalette() const
1436{
1437 wxWindow *win = (wxWindow *)this;
1438 while ( win && !win->HasCustomPalette() )
1439 {
1440 win = win->GetParent();
1441 }
1442
1443 return win;
1444}
1445
1446#endif // wxUSE_PALETTE
1447
789295bf
VZ
1448#if wxUSE_CARET
1449void wxWindowBase::SetCaret(wxCaret *caret)
1450{
1451 if ( m_caret )
1452 {
1453 delete m_caret;
1454 }
1455
1456 m_caret = caret;
1457
1458 if ( m_caret )
1459 {
1460 wxASSERT_MSG( m_caret->GetWindow() == this,
223d09f6 1461 wxT("caret should be created associated to this window") );
789295bf
VZ
1462 }
1463}
1464#endif // wxUSE_CARET
1465
88ac883a 1466#if wxUSE_VALIDATORS
f03fc89f
VZ
1467// ----------------------------------------------------------------------------
1468// validators
1469// ----------------------------------------------------------------------------
1470
1471void wxWindowBase::SetValidator(const wxValidator& validator)
1472{
1473 if ( m_windowValidator )
1474 delete m_windowValidator;
1475
1476 m_windowValidator = (wxValidator *)validator.Clone();
1477
1478 if ( m_windowValidator )
1b69c815 1479 m_windowValidator->SetWindow(this);
f03fc89f 1480}
88ac883a 1481#endif // wxUSE_VALIDATORS
f03fc89f
VZ
1482
1483// ----------------------------------------------------------------------------
1e6feb95 1484// update region stuff
f03fc89f
VZ
1485// ----------------------------------------------------------------------------
1486
1e6feb95
VZ
1487wxRect wxWindowBase::GetUpdateClientRect() const
1488{
1489 wxRegion rgnUpdate = GetUpdateRegion();
1490 rgnUpdate.Intersect(GetClientRect());
1491 wxRect rectUpdate = rgnUpdate.GetBox();
1492 wxPoint ptOrigin = GetClientAreaOrigin();
1493 rectUpdate.x -= ptOrigin.x;
1494 rectUpdate.y -= ptOrigin.y;
1495
1496 return rectUpdate;
1497}
1498
657b4fd4 1499bool wxWindowBase::DoIsExposed(int x, int y) const
f03fc89f
VZ
1500{
1501 return m_updateRegion.Contains(x, y) != wxOutRegion;
1502}
1503
657b4fd4 1504bool wxWindowBase::DoIsExposed(int x, int y, int w, int h) const
f03fc89f
VZ
1505{
1506 return m_updateRegion.Contains(x, y, w, h) != wxOutRegion;
1507}
1508
5da0803c
VZ
1509void wxWindowBase::ClearBackground()
1510{
1511 // wxGTK uses its own version, no need to add never used code
1512#ifndef __WXGTK__
1513 wxClientDC dc((wxWindow *)this);
cb129171 1514 wxBrush brush(GetBackgroundColour(), wxBRUSHSTYLE_SOLID);
5da0803c
VZ
1515 dc.SetBackground(brush);
1516 dc.Clear();
1517#endif // __WXGTK__
1518}
1519
f03fc89f 1520// ----------------------------------------------------------------------------
146ba0fe 1521// find child window by id or name
f03fc89f
VZ
1522// ----------------------------------------------------------------------------
1523
6b73af79 1524wxWindow *wxWindowBase::FindWindow(long id) const
f03fc89f
VZ
1525{
1526 if ( id == m_windowId )
1527 return (wxWindow *)this;
1528
d3b9f782 1529 wxWindowBase *res = NULL;
222ed1d6 1530 wxWindowList::compatibility_iterator node;
f03fc89f
VZ
1531 for ( node = m_children.GetFirst(); node && !res; node = node->GetNext() )
1532 {
1533 wxWindowBase *child = node->GetData();
1534 res = child->FindWindow( id );
1535 }
1536
1537 return (wxWindow *)res;
1538}
1539
6b73af79 1540wxWindow *wxWindowBase::FindWindow(const wxString& name) const
f03fc89f
VZ
1541{
1542 if ( name == m_windowName )
1543 return (wxWindow *)this;
1544
d3b9f782 1545 wxWindowBase *res = NULL;
222ed1d6 1546 wxWindowList::compatibility_iterator node;
f03fc89f
VZ
1547 for ( node = m_children.GetFirst(); node && !res; node = node->GetNext() )
1548 {
1549 wxWindow *child = node->GetData();
1550 res = child->FindWindow(name);
1551 }
1552
1553 return (wxWindow *)res;
1554}
1555
146ba0fe
VZ
1556
1557// find any window by id or name or label: If parent is non-NULL, look through
1558// children for a label or title matching the specified string. If NULL, look
1559// through all top-level windows.
1560//
1561// to avoid duplicating code we reuse the same helper function but with
1562// different comparators
1563
1564typedef bool (*wxFindWindowCmp)(const wxWindow *win,
1565 const wxString& label, long id);
1566
1567static
1568bool wxFindWindowCmpLabels(const wxWindow *win, const wxString& label,
1569 long WXUNUSED(id))
1570{
1571 return win->GetLabel() == label;
1572}
1573
1574static
1575bool wxFindWindowCmpNames(const wxWindow *win, const wxString& label,
1576 long WXUNUSED(id))
1577{
1578 return win->GetName() == label;
1579}
1580
1581static
1582bool wxFindWindowCmpIds(const wxWindow *win, const wxString& WXUNUSED(label),
1583 long id)
1584{
1585 return win->GetId() == id;
1586}
1587
1588// recursive helper for the FindWindowByXXX() functions
1589static
1590wxWindow *wxFindWindowRecursively(const wxWindow *parent,
1591 const wxString& label,
1592 long id,
1593 wxFindWindowCmp cmp)
1594{
1595 if ( parent )
1596 {
1597 // see if this is the one we're looking for
1598 if ( (*cmp)(parent, label, id) )
1599 return (wxWindow *)parent;
1600
1601 // It wasn't, so check all its children
222ed1d6 1602 for ( wxWindowList::compatibility_iterator node = parent->GetChildren().GetFirst();
146ba0fe
VZ
1603 node;
1604 node = node->GetNext() )
1605 {
1606 // recursively check each child
1607 wxWindow *win = (wxWindow *)node->GetData();
1608 wxWindow *retwin = wxFindWindowRecursively(win, label, id, cmp);
1609 if (retwin)
1610 return retwin;
1611 }
1612 }
1613
1614 // Not found
1615 return NULL;
1616}
1617
1618// helper for FindWindowByXXX()
1619static
1620wxWindow *wxFindWindowHelper(const wxWindow *parent,
1621 const wxString& label,
1622 long id,
1623 wxFindWindowCmp cmp)
1624{
1625 if ( parent )
1626 {
1627 // just check parent and all its children
1628 return wxFindWindowRecursively(parent, label, id, cmp);
1629 }
1630
1631 // start at very top of wx's windows
222ed1d6 1632 for ( wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetFirst();
146ba0fe
VZ
1633 node;
1634 node = node->GetNext() )
1635 {
1636 // recursively check each window & its children
1637 wxWindow *win = node->GetData();
1638 wxWindow *retwin = wxFindWindowRecursively(win, label, id, cmp);
1639 if (retwin)
1640 return retwin;
1641 }
1642
1643 return NULL;
1644}
1645
1646/* static */
1647wxWindow *
1648wxWindowBase::FindWindowByLabel(const wxString& title, const wxWindow *parent)
1649{
1650 return wxFindWindowHelper(parent, title, 0, wxFindWindowCmpLabels);
1651}
1652
1653/* static */
1654wxWindow *
1655wxWindowBase::FindWindowByName(const wxString& title, const wxWindow *parent)
1656{
1657 wxWindow *win = wxFindWindowHelper(parent, title, 0, wxFindWindowCmpNames);
1658
1659 if ( !win )
1660 {
1661 // fall back to the label
1662 win = FindWindowByLabel(title, parent);
1663 }
1664
1665 return win;
1666}
1667
1668/* static */
1669wxWindow *
1670wxWindowBase::FindWindowById( long id, const wxWindow* parent )
1671{
525d8583 1672 return wxFindWindowHelper(parent, wxEmptyString, id, wxFindWindowCmpIds);
146ba0fe
VZ
1673}
1674
f03fc89f
VZ
1675// ----------------------------------------------------------------------------
1676// dialog oriented functions
1677// ----------------------------------------------------------------------------
1678
34636400 1679void wxWindowBase::MakeModal(bool modal)
f03fc89f 1680{
34636400
VZ
1681 // Disable all other windows
1682 if ( IsTopLevel() )
1683 {
222ed1d6 1684 wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetFirst();
34636400
VZ
1685 while (node)
1686 {
1687 wxWindow *win = node->GetData();
1688 if (win != this)
1689 win->Enable(!modal);
1690
1691 node = node->GetNext();
1692 }
1693 }
f03fc89f
VZ
1694}
1695
1696bool wxWindowBase::Validate()
1697{
88ac883a 1698#if wxUSE_VALIDATORS
d80cd92a
VZ
1699 bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
1700
222ed1d6 1701 wxWindowList::compatibility_iterator node;
f03fc89f
VZ
1702 for ( node = m_children.GetFirst(); node; node = node->GetNext() )
1703 {
1704 wxWindowBase *child = node->GetData();
1705 wxValidator *validator = child->GetValidator();
dcd6b914 1706 if ( validator && !validator->Validate((wxWindow *)this) )
f03fc89f 1707 {
e11f4636 1708 return false;
f03fc89f 1709 }
d80cd92a
VZ
1710
1711 if ( recurse && !child->Validate() )
1712 {
e11f4636 1713 return false;
d80cd92a 1714 }
f03fc89f 1715 }
88ac883a 1716#endif // wxUSE_VALIDATORS
f03fc89f 1717
e11f4636 1718 return true;
f03fc89f
VZ
1719}
1720
1721bool wxWindowBase::TransferDataToWindow()
1722{
88ac883a 1723#if wxUSE_VALIDATORS
d80cd92a
VZ
1724 bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
1725
222ed1d6 1726 wxWindowList::compatibility_iterator node;
f03fc89f
VZ
1727 for ( node = m_children.GetFirst(); node; node = node->GetNext() )
1728 {
1729 wxWindowBase *child = node->GetData();
1730 wxValidator *validator = child->GetValidator();
1731 if ( validator && !validator->TransferToWindow() )
1732 {
d80cd92a 1733 wxLogWarning(_("Could not transfer data to window"));
e30285ab 1734#if wxUSE_LOG
d80cd92a 1735 wxLog::FlushActive();
e30285ab 1736#endif // wxUSE_LOG
f03fc89f 1737
e11f4636 1738 return false;
f03fc89f 1739 }
d80cd92a
VZ
1740
1741 if ( recurse )
1742 {
a58a12e9 1743 if ( !child->TransferDataToWindow() )
d80cd92a
VZ
1744 {
1745 // warning already given
e11f4636 1746 return false;
d80cd92a
VZ
1747 }
1748 }
f03fc89f 1749 }
88ac883a 1750#endif // wxUSE_VALIDATORS
f03fc89f 1751
e11f4636 1752 return true;
f03fc89f
VZ
1753}
1754
1755bool wxWindowBase::TransferDataFromWindow()
1756{
88ac883a 1757#if wxUSE_VALIDATORS
d80cd92a
VZ
1758 bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
1759
222ed1d6 1760 wxWindowList::compatibility_iterator node;
f03fc89f
VZ
1761 for ( node = m_children.GetFirst(); node; node = node->GetNext() )
1762 {
1763 wxWindow *child = node->GetData();
d80cd92a
VZ
1764 wxValidator *validator = child->GetValidator();
1765 if ( validator && !validator->TransferFromWindow() )
f03fc89f 1766 {
d80cd92a
VZ
1767 // nop warning here because the application is supposed to give
1768 // one itself - we don't know here what might have gone wrongly
1769
e11f4636 1770 return false;
f03fc89f 1771 }
d80cd92a
VZ
1772
1773 if ( recurse )
1774 {
a58a12e9 1775 if ( !child->TransferDataFromWindow() )
d80cd92a
VZ
1776 {
1777 // warning already given
e11f4636 1778 return false;
d80cd92a
VZ
1779 }
1780 }
f03fc89f 1781 }
88ac883a 1782#endif // wxUSE_VALIDATORS
f03fc89f 1783
e11f4636 1784 return true;
f03fc89f
VZ
1785}
1786
1787void wxWindowBase::InitDialog()
1788{
1789 wxInitDialogEvent event(GetId());
1790 event.SetEventObject( this );
1791 GetEventHandler()->ProcessEvent(event);
1792}
1793
1794// ----------------------------------------------------------------------------
bd83cb56
VZ
1795// context-sensitive help support
1796// ----------------------------------------------------------------------------
1797
1798#if wxUSE_HELP
1799
1800// associate this help text with this window
1801void wxWindowBase::SetHelpText(const wxString& text)
1802{
1803 wxHelpProvider *helpProvider = wxHelpProvider::Get();
1804 if ( helpProvider )
1805 {
1806 helpProvider->AddHelp(this, text);
1807 }
1808}
1809
520746ac 1810#if WXWIN_COMPATIBILITY_2_8
bd83cb56
VZ
1811// associate this help text with all windows with the same id as this
1812// one
1813void wxWindowBase::SetHelpTextForId(const wxString& text)
1814{
1815 wxHelpProvider *helpProvider = wxHelpProvider::Get();
1816 if ( helpProvider )
1817 {
1818 helpProvider->AddHelp(GetId(), text);
1819 }
1820}
520746ac 1821#endif // WXWIN_COMPATIBILITY_2_8
bd83cb56
VZ
1822
1823// get the help string associated with this window (may be empty)
dc6588e7
VZ
1824// default implementation forwards calls to the help provider
1825wxString
1826wxWindowBase::GetHelpTextAtPoint(const wxPoint & WXUNUSED(pt),
1827 wxHelpEvent::Origin WXUNUSED(origin)) const
bd83cb56
VZ
1828{
1829 wxString text;
1830 wxHelpProvider *helpProvider = wxHelpProvider::Get();
1831 if ( helpProvider )
1832 {
1833 text = helpProvider->GetHelp(this);
1834 }
1835
1836 return text;
1837}
1838
1839// show help for this window
1840void wxWindowBase::OnHelp(wxHelpEvent& event)
1841{
1842 wxHelpProvider *helpProvider = wxHelpProvider::Get();
1843 if ( helpProvider )
1844 {
95d3881f
VZ
1845 wxPoint pos = event.GetPosition();
1846 const wxHelpEvent::Origin origin = event.GetOrigin();
1847 if ( origin == wxHelpEvent::Origin_Keyboard )
1848 {
1849 // if the help event was generated from keyboard it shouldn't
1850 // appear at the mouse position (which is still the only position
1851 // associated with help event) if the mouse is far away, although
1852 // we still do use the mouse position if it's over the window
1853 // because we suppose the user looks approximately at the mouse
1854 // already and so it would be more convenient than showing tooltip
1855 // at some arbitrary position which can be quite far from it
1856 const wxRect rectClient = GetClientRect();
1857 if ( !rectClient.Contains(ScreenToClient(pos)) )
1858 {
1859 // position help slightly under and to the right of this window
1860 pos = ClientToScreen(wxPoint(
1861 2*GetCharWidth(),
1862 rectClient.height + GetCharHeight()
1863 ));
1864 }
1865 }
1866
1867 if ( helpProvider->ShowHelpAtPoint(this, pos, origin) )
bd83cb56
VZ
1868 {
1869 // skip the event.Skip() below
1870 return;
1871 }
1872 }
1873
1874 event.Skip();
1875}
1876
1877#endif // wxUSE_HELP
1878
1879// ----------------------------------------------------------------------------
602a2e02 1880// tooltips
f03fc89f
VZ
1881// ----------------------------------------------------------------------------
1882
1883#if wxUSE_TOOLTIPS
1884
1885void wxWindowBase::SetToolTip( const wxString &tip )
1886{
1887 // don't create the new tooltip if we already have one
1888 if ( m_tooltip )
1889 {
1890 m_tooltip->SetTip( tip );
1891 }
1892 else
1893 {
1894 SetToolTip( new wxToolTip( tip ) );
1895 }
1896
1897 // setting empty tooltip text does not remove the tooltip any more - use
d3b9f782 1898 // SetToolTip(NULL) for this
f03fc89f
VZ
1899}
1900
1901void wxWindowBase::DoSetToolTip(wxToolTip *tooltip)
1902{
0cb57187
VZ
1903 if ( m_tooltip != tooltip )
1904 {
1905 if ( m_tooltip )
1906 delete m_tooltip;
f03fc89f 1907
0cb57187
VZ
1908 m_tooltip = tooltip;
1909 }
f03fc89f
VZ
1910}
1911
1912#endif // wxUSE_TOOLTIPS
1913
1914// ----------------------------------------------------------------------------
1915// constraints and sizers
1916// ----------------------------------------------------------------------------
1917
1918#if wxUSE_CONSTRAINTS
1919
1920void wxWindowBase::SetConstraints( wxLayoutConstraints *constraints )
1921{
1922 if ( m_constraints )
1923 {
1924 UnsetConstraints(m_constraints);
1925 delete m_constraints;
1926 }
1927 m_constraints = constraints;
1928 if ( m_constraints )
1929 {
1930 // Make sure other windows know they're part of a 'meaningful relationship'
1931 if ( m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this) )
1932 m_constraints->left.GetOtherWindow()->AddConstraintReference(this);
1933 if ( m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this) )
1934 m_constraints->top.GetOtherWindow()->AddConstraintReference(this);
1935 if ( m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this) )
1936 m_constraints->right.GetOtherWindow()->AddConstraintReference(this);
1937 if ( m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this) )
1938 m_constraints->bottom.GetOtherWindow()->AddConstraintReference(this);
1939 if ( m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this) )
1940 m_constraints->width.GetOtherWindow()->AddConstraintReference(this);
1941 if ( m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this) )
1942 m_constraints->height.GetOtherWindow()->AddConstraintReference(this);
1943 if ( m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this) )
1944 m_constraints->centreX.GetOtherWindow()->AddConstraintReference(this);
1945 if ( m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this) )
1946 m_constraints->centreY.GetOtherWindow()->AddConstraintReference(this);
1947 }
1948}
1949
1950// This removes any dangling pointers to this window in other windows'
1951// constraintsInvolvedIn lists.
1952void wxWindowBase::UnsetConstraints(wxLayoutConstraints *c)
1953{
1954 if ( c )
1955 {
1956 if ( c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this) )
1957 c->left.GetOtherWindow()->RemoveConstraintReference(this);
1958 if ( c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this) )
1959 c->top.GetOtherWindow()->RemoveConstraintReference(this);
1960 if ( c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this) )
1961 c->right.GetOtherWindow()->RemoveConstraintReference(this);
1962 if ( c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this) )
1963 c->bottom.GetOtherWindow()->RemoveConstraintReference(this);
1964 if ( c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this) )
1965 c->width.GetOtherWindow()->RemoveConstraintReference(this);
1966 if ( c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this) )
1967 c->height.GetOtherWindow()->RemoveConstraintReference(this);
1968 if ( c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this) )
1969 c->centreX.GetOtherWindow()->RemoveConstraintReference(this);
1970 if ( c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this) )
1971 c->centreY.GetOtherWindow()->RemoveConstraintReference(this);
1972 }
1973}
1974
1975// Back-pointer to other windows we're involved with, so if we delete this
1976// window, we must delete any constraints we're involved with.
1977void wxWindowBase::AddConstraintReference(wxWindowBase *otherWin)
1978{
1979 if ( !m_constraintsInvolvedIn )
1980 m_constraintsInvolvedIn = new wxWindowList;
222ed1d6
MB
1981 if ( !m_constraintsInvolvedIn->Find((wxWindow *)otherWin) )
1982 m_constraintsInvolvedIn->Append((wxWindow *)otherWin);
f03fc89f
VZ
1983}
1984
1985// REMOVE back-pointer to other windows we're involved with.
1986void wxWindowBase::RemoveConstraintReference(wxWindowBase *otherWin)
1987{
1988 if ( m_constraintsInvolvedIn )
222ed1d6 1989 m_constraintsInvolvedIn->DeleteObject((wxWindow *)otherWin);
f03fc89f
VZ
1990}
1991
1992// Reset any constraints that mention this window
1993void wxWindowBase::DeleteRelatedConstraints()
1994{
1995 if ( m_constraintsInvolvedIn )
1996 {
222ed1d6 1997 wxWindowList::compatibility_iterator node = m_constraintsInvolvedIn->GetFirst();
f03fc89f
VZ
1998 while (node)
1999 {
2000 wxWindow *win = node->GetData();
2001 wxLayoutConstraints *constr = win->GetConstraints();
2002
2003 // Reset any constraints involving this window
2004 if ( constr )
2005 {
2006 constr->left.ResetIfWin(this);
2007 constr->top.ResetIfWin(this);
2008 constr->right.ResetIfWin(this);
2009 constr->bottom.ResetIfWin(this);
2010 constr->width.ResetIfWin(this);
2011 constr->height.ResetIfWin(this);
2012 constr->centreX.ResetIfWin(this);
2013 constr->centreY.ResetIfWin(this);
2014 }
2015
222ed1d6
MB
2016 wxWindowList::compatibility_iterator next = node->GetNext();
2017 m_constraintsInvolvedIn->Erase(node);
f03fc89f
VZ
2018 node = next;
2019 }
2020
2021 delete m_constraintsInvolvedIn;
d3b9f782 2022 m_constraintsInvolvedIn = NULL;
f03fc89f
VZ
2023 }
2024}
ec5bb70d
VZ
2025
2026#endif // wxUSE_CONSTRAINTS
f03fc89f 2027
3aa5d532 2028void wxWindowBase::SetSizer(wxSizer *sizer, bool deleteOld)
f03fc89f 2029{
fb89cfc5
RD
2030 if ( sizer == m_windowSizer)
2031 return;
1b69c815 2032
e8cfff87
VZ
2033 if ( m_windowSizer )
2034 {
2035 m_windowSizer->SetContainingWindow(NULL);
2036
2037 if ( deleteOld )
2038 delete m_windowSizer;
2039 }
3417c2cd 2040
f03fc89f 2041 m_windowSizer = sizer;
e8cfff87
VZ
2042 if ( m_windowSizer )
2043 {
2044 m_windowSizer->SetContainingWindow((wxWindow *)this);
2045 }
566d84a7 2046
e8cfff87 2047 SetAutoLayout(m_windowSizer != NULL);
566d84a7
RL
2048}
2049
2050void wxWindowBase::SetSizerAndFit(wxSizer *sizer, bool deleteOld)
2051{
2052 SetSizer( sizer, deleteOld );
2053 sizer->SetSizeHints( (wxWindow*) this );
f03fc89f
VZ
2054}
2055
400a9e41 2056
1ebfafde
RD
2057void wxWindowBase::SetContainingSizer(wxSizer* sizer)
2058{
2059 // adding a window to a sizer twice is going to result in fatal and
2060 // hard to debug problems later because when deleting the second
2061 // associated wxSizerItem we're going to dereference a dangling
2062 // pointer; so try to detect this as early as possible
2063 wxASSERT_MSG( !sizer || m_containingSizer != sizer,
2064 _T("Adding a window to the same sizer twice?") );
1ebfafde 2065
400a9e41 2066 m_containingSizer = sizer;
1ebfafde 2067}
400a9e41 2068
ec5bb70d
VZ
2069#if wxUSE_CONSTRAINTS
2070
2071void wxWindowBase::SatisfyConstraints()
2072{
2073 wxLayoutConstraints *constr = GetConstraints();
2074 bool wasOk = constr && constr->AreSatisfied();
2075
2076 ResetConstraints(); // Mark all constraints as unevaluated
2077
2078 int noChanges = 1;
2079
2080 // if we're a top level panel (i.e. our parent is frame/dialog), our
2081 // own constraints will never be satisfied any more unless we do it
2082 // here
2083 if ( wasOk )
2084 {
2085 while ( noChanges > 0 )
2086 {
2087 LayoutPhase1(&noChanges);
2088 }
2089 }
2090
2091 LayoutPhase2(&noChanges);
2092}
2093
2094#endif // wxUSE_CONSTRAINTS
2095
f03fc89f
VZ
2096bool wxWindowBase::Layout()
2097{
3417c2cd 2098 // If there is a sizer, use it instead of the constraints
f03fc89f
VZ
2099 if ( GetSizer() )
2100 {
8d7eaf91 2101 int w = 0, h = 0;
566d84a7 2102 GetVirtualSize(&w, &h);
3417c2cd 2103 GetSizer()->SetDimension( 0, 0, w, h );
f03fc89f 2104 }
461e93f9 2105#if wxUSE_CONSTRAINTS
f1df0927 2106 else
f03fc89f 2107 {
ec5bb70d 2108 SatisfyConstraints(); // Find the right constraints values
f1df0927 2109 SetConstraintSizes(); // Recursively set the real window sizes
f03fc89f 2110 }
461e93f9 2111#endif
5d4b632b 2112
e11f4636 2113 return true;
f03fc89f
VZ
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
ac8d0c11 2874bool wxWindowBase::TryValidator(wxEvent& wxVALIDATOR_PARAM(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
6eabf58c 2889 return false;
4caf847c
VZ
2890}
2891
4caf847c
VZ
2892bool wxWindowBase::TryParent(wxEvent& event)
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
2914 return wxEvtHandler::TryParent(event);
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