]> git.saurik.com Git - wxWidgets.git/blob - src/common/wincmn.cpp
partially fix bug [ wxwindows-Bugs-1145813 ] Centre() Doesn't Work With Dual Monitors...
[wxWidgets.git] / src / common / wincmn.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: common/window.cpp
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$
8 // Copyright: (c) wxWidgets team
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation "windowbase.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #ifndef WX_PRECOMP
32 #include "wx/string.h"
33 #include "wx/log.h"
34 #include "wx/intl.h"
35 #include "wx/frame.h"
36 #include "wx/defs.h"
37 #include "wx/window.h"
38 #include "wx/control.h"
39 #include "wx/checkbox.h"
40 #include "wx/radiobut.h"
41 #include "wx/statbox.h"
42 #include "wx/textctrl.h"
43 #include "wx/settings.h"
44 #include "wx/dialog.h"
45 #include "wx/msgdlg.h"
46 #include "wx/statusbr.h"
47 #include "wx/dcclient.h"
48 #endif //WX_PRECOMP
49
50 #if defined(__WXMAC__) && wxUSE_SCROLLBAR
51 #include "wx/scrolbar.h"
52 #endif
53
54 #if wxUSE_CONSTRAINTS
55 #include "wx/layout.h"
56 #endif // wxUSE_CONSTRAINTS
57
58 #include "wx/sizer.h"
59
60 #if wxUSE_DRAG_AND_DROP
61 #include "wx/dnd.h"
62 #endif // wxUSE_DRAG_AND_DROP
63
64 #if wxUSE_ACCESSIBILITY
65 #include "wx/access.h"
66 #endif
67
68 #if wxUSE_HELP
69 #include "wx/cshelp.h"
70 #endif // wxUSE_HELP
71
72 #if wxUSE_TOOLTIPS
73 #include "wx/tooltip.h"
74 #endif // wxUSE_TOOLTIPS
75
76 #if wxUSE_CARET
77 #include "wx/caret.h"
78 #endif // wxUSE_CARET
79
80 #if wxUSE_DISPLAY
81 #include "wx/display.h"
82 #endif
83
84 #if wxUSE_SYSTEM_OPTIONS
85 #include "wx/sysopt.h"
86 #endif
87
88 // ----------------------------------------------------------------------------
89 // static data
90 // ----------------------------------------------------------------------------
91
92 #if defined(__WXPALMOS__)
93 int wxWindowBase::ms_lastControlId = 32767;
94 #elif defined(__WXPM__)
95 int wxWindowBase::ms_lastControlId = 2000;
96 #else
97 int wxWindowBase::ms_lastControlId = -200;
98 #endif
99
100 IMPLEMENT_ABSTRACT_CLASS(wxWindowBase, wxEvtHandler)
101
102 // ----------------------------------------------------------------------------
103 // event table
104 // ----------------------------------------------------------------------------
105
106 BEGIN_EVENT_TABLE(wxWindowBase, wxEvtHandler)
107 EVT_SYS_COLOUR_CHANGED(wxWindowBase::OnSysColourChanged)
108 EVT_INIT_DIALOG(wxWindowBase::OnInitDialog)
109 EVT_MIDDLE_DOWN(wxWindowBase::OnMiddleClick)
110
111 #if wxUSE_HELP
112 EVT_HELP(wxID_ANY, wxWindowBase::OnHelp)
113 #endif // wxUSE_HELP
114
115 END_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
126 wxWindowBase::wxWindowBase()
127 {
128 // no window yet, no parent nor children
129 m_parent = (wxWindow *)NULL;
130 m_windowId = wxID_ANY;
131
132 // no constraints on the minimal window size
133 m_minWidth =
134 m_maxWidth = wxDefaultCoord;
135 m_minHeight =
136 m_maxHeight = wxDefaultCoord;
137
138 // invalidiated cache value
139 m_bestSizeCache = wxDefaultSize;
140
141 // window are created enabled and visible by default
142 m_isShown =
143 m_isEnabled = true;
144
145 // the default event handler is just this window
146 m_eventHandler = this;
147
148 #if wxUSE_VALIDATORS
149 // no validator
150 m_windowValidator = (wxValidator *) NULL;
151 #endif // wxUSE_VALIDATORS
152
153 // the colours/fonts are default for now, so leave m_font,
154 // m_backgroundColour and m_foregroundColour uninitialized and set those
155 m_hasBgCol =
156 m_hasFgCol =
157 m_hasFont = false;
158 m_inheritBgCol =
159 m_inheritFgCol =
160 m_inheritFont = false;
161
162 // no style bits
163 m_exStyle =
164 m_windowStyle = 0;
165
166 m_backgroundStyle = wxBG_STYLE_SYSTEM;
167
168 #if wxUSE_CONSTRAINTS
169 // no constraints whatsoever
170 m_constraints = (wxLayoutConstraints *) NULL;
171 m_constraintsInvolvedIn = (wxWindowList *) NULL;
172 #endif // wxUSE_CONSTRAINTS
173
174 m_windowSizer = (wxSizer *) NULL;
175 m_containingSizer = (wxSizer *) NULL;
176 m_autoLayout = false;
177
178 #if wxUSE_DRAG_AND_DROP
179 m_dropTarget = (wxDropTarget *)NULL;
180 #endif // wxUSE_DRAG_AND_DROP
181
182 #if wxUSE_TOOLTIPS
183 m_tooltip = (wxToolTip *)NULL;
184 #endif // wxUSE_TOOLTIPS
185
186 #if wxUSE_CARET
187 m_caret = (wxCaret *)NULL;
188 #endif // wxUSE_CARET
189
190 #if wxUSE_PALETTE
191 m_hasCustomPalette = false;
192 #endif // wxUSE_PALETTE
193
194 #if wxUSE_ACCESSIBILITY
195 m_accessible = NULL;
196 #endif
197
198 m_virtualSize = wxDefaultSize;
199
200 m_minVirtualWidth =
201 m_maxVirtualWidth = wxDefaultCoord;
202 m_minVirtualHeight =
203 m_maxVirtualHeight = wxDefaultCoord;
204
205 m_windowVariant = wxWINDOW_VARIANT_NORMAL;
206 #if wxUSE_SYSTEM_OPTIONS
207 if ( wxSystemOptions::HasOption(wxWINDOW_DEFAULT_VARIANT) )
208 {
209 m_windowVariant = (wxWindowVariant) wxSystemOptions::GetOptionInt( wxWINDOW_DEFAULT_VARIANT ) ;
210 }
211 #endif
212
213 // Whether we're using the current theme for this window (wxGTK only for now)
214 m_themeEnabled = false;
215
216 // VZ: this one shouldn't exist...
217 m_isBeingDeleted = false;
218 }
219
220 // common part of window creation process
221 bool wxWindowBase::CreateBase(wxWindowBase *parent,
222 wxWindowID id,
223 const wxPoint& WXUNUSED(pos),
224 const wxSize& WXUNUSED(size),
225 long style,
226 const wxValidator& wxVALIDATOR_PARAM(validator),
227 const wxString& name)
228 {
229 #if wxUSE_STATBOX
230 // wxGTK doesn't allow to create controls with static box as the parent so
231 // this will result in a crash when the program is ported to wxGTK so warn
232 // the user about it
233
234 // if you get this assert, the correct solution is to create the controls
235 // as siblings of the static box
236 wxASSERT_MSG( !parent || !wxDynamicCast(parent, wxStaticBox),
237 _T("wxStaticBox can't be used as a window parent!") );
238 #endif // wxUSE_STATBOX
239
240 // ids are limited to 16 bits under MSW so if you care about portability,
241 // it's not a good idea to use ids out of this range (and negative ids are
242 // reserved for wxWidgets own usage)
243 wxASSERT_MSG( id == wxID_ANY || (id >= 0 && id < 32767),
244 _T("invalid id value") );
245
246 // generate a new id if the user doesn't care about it
247 m_windowId = id == wxID_ANY ? NewControlId() : id;
248
249 SetName(name);
250 SetWindowStyleFlag(style);
251 SetParent(parent);
252
253 #if wxUSE_VALIDATORS
254 SetValidator(validator);
255 #endif // wxUSE_VALIDATORS
256
257 // if the parent window has wxWS_EX_VALIDATE_RECURSIVELY set, we want to
258 // have it too - like this it's possible to set it only in the top level
259 // dialog/frame and all children will inherit it by defult
260 if ( parent && (parent->GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) )
261 {
262 SetExtraStyle(GetExtraStyle() | wxWS_EX_VALIDATE_RECURSIVELY);
263 }
264
265 return true;
266 }
267
268 // ----------------------------------------------------------------------------
269 // destruction
270 // ----------------------------------------------------------------------------
271
272 // common clean up
273 wxWindowBase::~wxWindowBase()
274 {
275 wxASSERT_MSG( GetCapture() != this, wxT("attempt to destroy window with mouse capture") );
276
277 // FIXME if these 2 cases result from programming errors in the user code
278 // we should probably assert here instead of silently fixing them
279
280 // Just in case the window has been Closed, but we're then deleting
281 // immediately: don't leave dangling pointers.
282 wxPendingDelete.DeleteObject(this);
283
284 // Just in case we've loaded a top-level window via LoadNativeDialog but
285 // we weren't a dialog class
286 wxTopLevelWindows.DeleteObject((wxWindow*)this);
287
288 wxASSERT_MSG( GetChildren().GetCount() == 0, wxT("children not destroyed") );
289
290 // reset the dangling pointer our parent window may keep to us
291 if ( m_parent )
292 {
293 if ( m_parent->GetDefaultItem() == this )
294 {
295 m_parent->SetDefaultItem(NULL);
296 }
297
298 m_parent->RemoveChild(this);
299 }
300
301 #if wxUSE_CARET
302 delete m_caret;
303 #endif // wxUSE_CARET
304
305 #if wxUSE_VALIDATORS
306 delete m_windowValidator;
307 #endif // wxUSE_VALIDATORS
308
309 #if wxUSE_CONSTRAINTS
310 // Have to delete constraints/sizer FIRST otherwise sizers may try to look
311 // at deleted windows as they delete themselves.
312 DeleteRelatedConstraints();
313
314 if ( m_constraints )
315 {
316 // This removes any dangling pointers to this window in other windows'
317 // constraintsInvolvedIn lists.
318 UnsetConstraints(m_constraints);
319 delete m_constraints;
320 m_constraints = NULL;
321 }
322 #endif // wxUSE_CONSTRAINTS
323
324 if ( m_containingSizer )
325 m_containingSizer->Detach( (wxWindow*)this );
326
327 delete m_windowSizer;
328
329 #if wxUSE_DRAG_AND_DROP
330 delete m_dropTarget;
331 #endif // wxUSE_DRAG_AND_DROP
332
333 #if wxUSE_TOOLTIPS
334 delete m_tooltip;
335 #endif // wxUSE_TOOLTIPS
336
337 #if wxUSE_ACCESSIBILITY
338 delete m_accessible;
339 #endif
340 }
341
342 bool wxWindowBase::Destroy()
343 {
344 delete this;
345
346 return true;
347 }
348
349 bool wxWindowBase::Close(bool force)
350 {
351 wxCloseEvent event(wxEVT_CLOSE_WINDOW, m_windowId);
352 event.SetEventObject(this);
353 event.SetCanVeto(!force);
354
355 // return false if window wasn't closed because the application vetoed the
356 // close event
357 return GetEventHandler()->ProcessEvent(event) && !event.GetVeto();
358 }
359
360 bool wxWindowBase::DestroyChildren()
361 {
362 wxWindowList::compatibility_iterator node;
363 for ( ;; )
364 {
365 // we iterate until the list becomes empty
366 node = GetChildren().GetFirst();
367 if ( !node )
368 break;
369
370 wxWindow *child = node->GetData();
371
372 // note that we really want to call delete and not ->Destroy() here
373 // because we want to delete the child immediately, before we are
374 // deleted, and delayed deletion would result in problems as our (top
375 // level) child could outlive its parent
376 delete child;
377
378 wxASSERT_MSG( !GetChildren().Find(child),
379 wxT("child didn't remove itself using RemoveChild()") );
380 }
381
382 return true;
383 }
384
385 // ----------------------------------------------------------------------------
386 // size/position related methods
387 // ----------------------------------------------------------------------------
388
389 // centre the window with respect to its parent in either (or both) directions
390 void wxWindowBase::Centre(int direction)
391 {
392 // the position/size of the parent window or of the entire screen
393 wxPoint posParent;
394 int widthParent, heightParent;
395
396 wxWindow *parent = NULL;
397 wxTopLevelWindow *winTop = NULL;
398
399 if ( !(direction & wxCENTRE_ON_SCREEN) )
400 {
401 // find the parent to centre this window on: it should be the
402 // immediate parent for the controls but the top level parent for the
403 // top level windows (like dialogs)
404 parent = GetParent();
405 if ( IsTopLevel() )
406 {
407 while ( parent && !parent->IsTopLevel() )
408 {
409 parent = parent->GetParent();
410 }
411 }
412
413 // there is no wxTopLevelWindow under wxMotif yet
414 #ifndef __WXMOTIF__
415 // we shouldn't center the dialog on the iconized window: under
416 // Windows, for example, this places it completely off the screen
417 if ( parent )
418 {
419 winTop = wxDynamicCast(parent, wxTopLevelWindow);
420 if ( winTop && winTop->IsIconized() )
421 {
422 winTop = NULL;
423 parent = NULL;
424 }
425 }
426 #endif // __WXMOTIF__
427
428 // did we find the parent?
429 if ( !parent )
430 {
431 // no other choice
432 direction |= wxCENTRE_ON_SCREEN;
433 }
434 }
435
436 if ( direction & wxCENTRE_ON_SCREEN )
437 {
438 //RN: If we are using wxDisplay we get
439 //the dimensions of the monitor the window is on,
440 //otherwise we get the dimensions of the primary monitor
441 #if wxUSE_DISPLAY
442 int nDisplay = wxDisplay::GetFromWindow((wxWindow*)this);
443 if(nDisplay != wxNOT_FOUND)
444 {
445 wxDisplay windowDisplay(nDisplay);
446 wxRect displayRect = windowDisplay.GetGeometry();
447 widthParent = displayRect.width;
448 heightParent = displayRect.height;
449 }
450 else
451 #endif
452 // centre with respect to the whole screen
453 wxDisplaySize(&widthParent, &heightParent);
454 }
455 else
456 {
457 if ( IsTopLevel() )
458 {
459 if(winTop)
460 winTop->GetRectForTopLevelChildren(&posParent.x, &posParent.y, &widthParent, &heightParent);
461 else
462 {
463 // centre on the parent
464 parent->GetSize(&widthParent, &heightParent);
465
466 // adjust to the parents position
467 posParent = parent->GetPosition();
468 }
469 }
470 else
471 {
472 // centre inside the parents client rectangle
473 parent->GetClientSize(&widthParent, &heightParent);
474 }
475 }
476
477 int width, height;
478 GetSize(&width, &height);
479
480 int xNew = wxDefaultCoord,
481 yNew = wxDefaultCoord;
482
483 if ( direction & wxHORIZONTAL )
484 xNew = (widthParent - width)/2;
485
486 if ( direction & wxVERTICAL )
487 yNew = (heightParent - height)/2;
488
489 xNew += posParent.x;
490 yNew += posParent.y;
491
492 // FIXME: This needs to get the client display rect of the display
493 // the window is (via wxDisplay::GetFromWindow).
494
495 // Base size of the visible dimensions of the display
496 // to take into account the taskbar. And the Mac menu bar at top.
497 wxRect clientrect = wxGetClientDisplayRect();
498
499 // NB: in wxMSW, negative position may not neccessary mean "out of screen",
500 // but it may mean that the window is placed on other than the main
501 // display. Therefore we only make sure centered window is on the main display
502 // if the parent is at least partially present here.
503 if (posParent.x + widthParent >= 0) // if parent is (partially) on the main display
504 {
505 if (xNew < clientrect.GetLeft())
506 xNew = clientrect.GetLeft();
507 else if (xNew + width > clientrect.GetRight())
508 xNew = clientrect.GetRight() - width;
509 }
510 if (posParent.y + heightParent >= 0) // if parent is (partially) on the main display
511 {
512 if (yNew + height > clientrect.GetBottom())
513 yNew = clientrect.GetBottom() - height;
514
515 // Make certain that the title bar is initially visible
516 // always, even if this would push the bottom of the
517 // dialog off the visible area of the display
518 if (yNew < clientrect.GetTop())
519 yNew = clientrect.GetTop();
520 }
521
522 // move the window to this position (keeping the old size but using
523 // SetSize() and not Move() to allow xNew and/or yNew to be wxDefaultCoord)
524 SetSize(xNew, yNew, width, height, wxSIZE_ALLOW_MINUS_ONE);
525 }
526
527 // fits the window around the children
528 void wxWindowBase::Fit()
529 {
530 if ( GetChildren().GetCount() > 0 )
531 {
532 SetSize(GetBestSize());
533 }
534 //else: do nothing if we have no children
535 }
536
537 // fits virtual size (ie. scrolled area etc.) around children
538 void wxWindowBase::FitInside()
539 {
540 if ( GetChildren().GetCount() > 0 )
541 {
542 SetVirtualSize( GetBestVirtualSize() );
543 }
544 }
545
546 // On Mac, scrollbars are explicitly children.
547 #ifdef __WXMAC__
548 static bool wxHasRealChildren(const wxWindowBase* win)
549 {
550 int realChildCount = 0;
551
552 for ( wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst();
553 node;
554 node = node->GetNext() )
555 {
556 wxWindow *win = node->GetData();
557 if ( !win->IsTopLevel() && win->IsShown() && !win->IsKindOf(CLASSINFO(wxScrollBar)))
558 realChildCount ++;
559 }
560 return (realChildCount > 0);
561 }
562 #endif
563
564 void wxWindowBase::InvalidateBestSize()
565 {
566 m_bestSizeCache = wxDefaultSize;
567
568 // parent's best size calculation may depend on its children's
569 // best sizes, so let's invalidate it as well to be safe:
570 if (m_parent)
571 m_parent->InvalidateBestSize();
572 }
573
574 // return the size best suited for the current window
575 wxSize wxWindowBase::DoGetBestSize() const
576 {
577 wxSize best;
578
579 if ( m_windowSizer )
580 {
581 best = m_windowSizer->GetMinSize();
582 }
583 #if wxUSE_CONSTRAINTS
584 else if ( m_constraints )
585 {
586 wxConstCast(this, wxWindowBase)->SatisfyConstraints();
587
588 // our minimal acceptable size is such that all our windows fit inside
589 int maxX = 0,
590 maxY = 0;
591
592 for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
593 node;
594 node = node->GetNext() )
595 {
596 wxLayoutConstraints *c = node->GetData()->GetConstraints();
597 if ( !c )
598 {
599 // it's not normal that we have an unconstrained child, but
600 // what can we do about it?
601 continue;
602 }
603
604 int x = c->right.GetValue(),
605 y = c->bottom.GetValue();
606
607 if ( x > maxX )
608 maxX = x;
609
610 if ( y > maxY )
611 maxY = y;
612
613 // TODO: we must calculate the overlaps somehow, otherwise we
614 // will never return a size bigger than the current one :-(
615 }
616
617 best = wxSize(maxX, maxY);
618 }
619 #endif // wxUSE_CONSTRAINTS
620 else if ( !GetChildren().empty()
621 #ifdef __WXMAC__
622 && wxHasRealChildren(this)
623 #endif
624 )
625 {
626 // our minimal acceptable size is such that all our visible child windows fit inside
627 int maxX = 0,
628 maxY = 0;
629
630 for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
631 node;
632 node = node->GetNext() )
633 {
634 wxWindow *win = node->GetData();
635 if ( win->IsTopLevel() || ( ! win->IsShown() )
636 #if wxUSE_STATUSBAR
637 || wxDynamicCast(win, wxStatusBar)
638 #endif // wxUSE_STATUSBAR
639 )
640 {
641 // dialogs and frames lie in different top level windows -
642 // don't deal with them here; as for the status bars, they
643 // don't lie in the client area at all
644 continue;
645 }
646
647 int wx, wy, ww, wh;
648 win->GetPosition(&wx, &wy);
649
650 // if the window hadn't been positioned yet, assume that it is in
651 // the origin
652 if ( wx == wxDefaultCoord )
653 wx = 0;
654 if ( wy == wxDefaultCoord )
655 wy = 0;
656
657 win->GetSize(&ww, &wh);
658 if ( wx + ww > maxX )
659 maxX = wx + ww;
660 if ( wy + wh > maxY )
661 maxY = wy + wh;
662 }
663
664 // for compatibility with the old versions and because it really looks
665 // slightly more pretty like this, add a pad
666 maxX += 7;
667 maxY += 14;
668
669 best = wxSize(maxX, maxY);
670 }
671 else // ! has children
672 {
673 // For a generic window there is no natural best size - just use
674 // either the minimum size if there is one, or the current size.
675 // These are returned as-is, unadjusted by the client size difference.
676 if ( GetMinSize().IsFullySpecified() )
677 return GetMinSize();
678 else
679 return GetSize();
680 }
681
682 // Add any difference between size and client size
683 wxSize diff = GetSize() - GetClientSize();
684 best.x += wxMax(0, diff.x);
685 best.y += wxMax(0, diff.y);
686
687 return best;
688 }
689
690
691 wxSize wxWindowBase::GetBestFittingSize() const
692 {
693 // merge the best size with the min size, giving priority to the min size
694 wxSize min = GetMinSize();
695 if (min.x == wxDefaultCoord || min.y == wxDefaultCoord)
696 {
697 wxSize best = GetBestSize();
698 if (min.x == wxDefaultCoord) min.x = best.x;
699 if (min.y == wxDefaultCoord) min.y = best.y;
700 }
701 return min;
702 }
703
704
705 void wxWindowBase::SetBestFittingSize(const wxSize& size)
706 {
707 // Set the min size to the size passed in. This will usually either be
708 // wxDefaultSize or the size passed to this window's ctor/Create function.
709 SetMinSize(size);
710
711 // Merge the size with the best size if needed
712 wxSize best = GetBestFittingSize();
713
714 // If the current size doesn't match then change it
715 if (GetSize() != best)
716 SetSize(best);
717 }
718
719
720 // by default the origin is not shifted
721 wxPoint wxWindowBase::GetClientAreaOrigin() const
722 {
723 return wxPoint(0,0);
724 }
725
726 // set the min/max size of the window
727 void wxWindowBase::DoSetSizeHints(int minW, int minH,
728 int maxW, int maxH,
729 int WXUNUSED(incW), int WXUNUSED(incH))
730 {
731 // setting min width greater than max width leads to infinite loops under
732 // X11 and generally doesn't make any sense, so don't allow it
733 wxCHECK_RET( (minW == wxDefaultCoord || maxW == wxDefaultCoord || minW <= maxW) &&
734 (minH == wxDefaultCoord || maxH == wxDefaultCoord || minH <= maxH),
735 _T("min width/height must be less than max width/height!") );
736
737 m_minWidth = minW;
738 m_maxWidth = maxW;
739 m_minHeight = minH;
740 m_maxHeight = maxH;
741 }
742
743 void wxWindowBase::SetWindowVariant( wxWindowVariant variant )
744 {
745 if ( m_windowVariant != variant )
746 {
747 m_windowVariant = variant;
748
749 DoSetWindowVariant(variant);
750 }
751 }
752
753 void wxWindowBase::DoSetWindowVariant( wxWindowVariant variant )
754 {
755 // adjust the font height to correspond to our new variant (notice that
756 // we're only called if something really changed)
757 wxFont font = GetFont();
758 int size = font.GetPointSize();
759 switch ( variant )
760 {
761 case wxWINDOW_VARIANT_NORMAL:
762 break;
763
764 case wxWINDOW_VARIANT_SMALL:
765 size *= 3;
766 size /= 4;
767 break;
768
769 case wxWINDOW_VARIANT_MINI:
770 size *= 2;
771 size /= 3;
772 break;
773
774 case wxWINDOW_VARIANT_LARGE:
775 size *= 5;
776 size /= 4;
777 break;
778
779 default:
780 wxFAIL_MSG(_T("unexpected window variant"));
781 break;
782 }
783
784 font.SetPointSize(size);
785 SetFont(font);
786 }
787
788 void wxWindowBase::SetVirtualSizeHints( int minW, int minH,
789 int maxW, int maxH )
790 {
791 m_minVirtualWidth = minW;
792 m_maxVirtualWidth = maxW;
793 m_minVirtualHeight = minH;
794 m_maxVirtualHeight = maxH;
795 }
796
797 void wxWindowBase::DoSetVirtualSize( int x, int y )
798 {
799 if ( m_minVirtualWidth != wxDefaultCoord && m_minVirtualWidth > x )
800 x = m_minVirtualWidth;
801 if ( m_maxVirtualWidth != wxDefaultCoord && m_maxVirtualWidth < x )
802 x = m_maxVirtualWidth;
803 if ( m_minVirtualHeight != wxDefaultCoord && m_minVirtualHeight > y )
804 y = m_minVirtualHeight;
805 if ( m_maxVirtualHeight != wxDefaultCoord && m_maxVirtualHeight < y )
806 y = m_maxVirtualHeight;
807
808 m_virtualSize = wxSize(x, y);
809 }
810
811 wxSize wxWindowBase::DoGetVirtualSize() const
812 {
813 if (m_virtualSize == wxDefaultSize)
814 return GetClientSize();
815
816 return m_virtualSize;
817 }
818
819 // ----------------------------------------------------------------------------
820 // show/hide/enable/disable the window
821 // ----------------------------------------------------------------------------
822
823 bool wxWindowBase::Show(bool show)
824 {
825 if ( show != m_isShown )
826 {
827 m_isShown = show;
828
829 return true;
830 }
831 else
832 {
833 return false;
834 }
835 }
836
837 bool wxWindowBase::Enable(bool enable)
838 {
839 if ( enable != m_isEnabled )
840 {
841 m_isEnabled = enable;
842
843 return true;
844 }
845 else
846 {
847 return false;
848 }
849 }
850 // ----------------------------------------------------------------------------
851 // RTTI
852 // ----------------------------------------------------------------------------
853
854 bool wxWindowBase::IsTopLevel() const
855 {
856 return false;
857 }
858
859 // ----------------------------------------------------------------------------
860 // reparenting the window
861 // ----------------------------------------------------------------------------
862
863 void wxWindowBase::AddChild(wxWindowBase *child)
864 {
865 wxCHECK_RET( child, wxT("can't add a NULL child") );
866
867 // this should never happen and it will lead to a crash later if it does
868 // because RemoveChild() will remove only one node from the children list
869 // and the other(s) one(s) will be left with dangling pointers in them
870 wxASSERT_MSG( !GetChildren().Find((wxWindow*)child), _T("AddChild() called twice") );
871
872 GetChildren().Append((wxWindow*)child);
873 child->SetParent(this);
874 }
875
876 void wxWindowBase::RemoveChild(wxWindowBase *child)
877 {
878 wxCHECK_RET( child, wxT("can't remove a NULL child") );
879
880 GetChildren().DeleteObject((wxWindow *)child);
881 child->SetParent(NULL);
882 }
883
884 bool wxWindowBase::Reparent(wxWindowBase *newParent)
885 {
886 wxWindow *oldParent = GetParent();
887 if ( newParent == oldParent )
888 {
889 // nothing done
890 return false;
891 }
892
893 // unlink this window from the existing parent.
894 if ( oldParent )
895 {
896 oldParent->RemoveChild(this);
897 }
898 else
899 {
900 wxTopLevelWindows.DeleteObject((wxWindow *)this);
901 }
902
903 // add it to the new one
904 if ( newParent )
905 {
906 newParent->AddChild(this);
907 }
908 else
909 {
910 wxTopLevelWindows.Append((wxWindow *)this);
911 }
912
913 return true;
914 }
915
916 // ----------------------------------------------------------------------------
917 // event handler stuff
918 // ----------------------------------------------------------------------------
919
920 void wxWindowBase::PushEventHandler(wxEvtHandler *handler)
921 {
922 wxEvtHandler *handlerOld = GetEventHandler();
923
924 handler->SetNextHandler(handlerOld);
925
926 if ( handlerOld )
927 GetEventHandler()->SetPreviousHandler(handler);
928
929 SetEventHandler(handler);
930 }
931
932 wxEvtHandler *wxWindowBase::PopEventHandler(bool deleteHandler)
933 {
934 wxEvtHandler *handlerA = GetEventHandler();
935 if ( handlerA )
936 {
937 wxEvtHandler *handlerB = handlerA->GetNextHandler();
938 handlerA->SetNextHandler((wxEvtHandler *)NULL);
939
940 if ( handlerB )
941 handlerB->SetPreviousHandler((wxEvtHandler *)NULL);
942 SetEventHandler(handlerB);
943
944 if ( deleteHandler )
945 {
946 delete handlerA;
947 handlerA = (wxEvtHandler *)NULL;
948 }
949 }
950
951 return handlerA;
952 }
953
954 bool wxWindowBase::RemoveEventHandler(wxEvtHandler *handler)
955 {
956 wxCHECK_MSG( handler, false, _T("RemoveEventHandler(NULL) called") );
957
958 wxEvtHandler *handlerPrev = NULL,
959 *handlerCur = GetEventHandler();
960 while ( handlerCur )
961 {
962 wxEvtHandler *handlerNext = handlerCur->GetNextHandler();
963
964 if ( handlerCur == handler )
965 {
966 if ( handlerPrev )
967 {
968 handlerPrev->SetNextHandler(handlerNext);
969 }
970 else
971 {
972 SetEventHandler(handlerNext);
973 }
974
975 if ( handlerNext )
976 {
977 handlerNext->SetPreviousHandler ( handlerPrev );
978 }
979
980 handler->SetNextHandler(NULL);
981 handler->SetPreviousHandler(NULL);
982
983 return true;
984 }
985
986 handlerPrev = handlerCur;
987 handlerCur = handlerNext;
988 }
989
990 wxFAIL_MSG( _T("where has the event handler gone?") );
991
992 return false;
993 }
994
995 // ----------------------------------------------------------------------------
996 // colours, fonts &c
997 // ----------------------------------------------------------------------------
998
999 void wxWindowBase::InheritAttributes()
1000 {
1001 const wxWindowBase * const parent = GetParent();
1002 if ( !parent )
1003 return;
1004
1005 // we only inherit attributes which had been explicitly set for the parent
1006 // which ensures that this only happens if the user really wants it and
1007 // not by default which wouldn't make any sense in modern GUIs where the
1008 // controls don't all use the same fonts (nor colours)
1009 if ( parent->m_inheritFont && !m_hasFont )
1010 SetFont(parent->GetFont());
1011
1012 // in addition, there is a possibility to explicitly forbid inheriting
1013 // colours at each class level by overriding ShouldInheritColours()
1014 if ( ShouldInheritColours() )
1015 {
1016 if ( parent->m_inheritFgCol && !m_hasFgCol )
1017 SetForegroundColour(parent->GetForegroundColour());
1018
1019 // inheriting (solid) background colour is wrong as it totally breaks
1020 // any kind of themed backgrounds
1021 //
1022 // instead, the controls should use the same background as their parent
1023 // (ideally by not drawing it at all)
1024 #if 0
1025 if ( parent->m_inheritBgCol && !m_hasBgCol )
1026 SetBackgroundColour(parent->GetBackgroundColour());
1027 #endif // 0
1028 }
1029 }
1030
1031 /* static */ wxVisualAttributes
1032 wxWindowBase::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
1033 {
1034 // it is important to return valid values for all attributes from here,
1035 // GetXXX() below rely on this
1036 wxVisualAttributes attrs;
1037 attrs.font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
1038 attrs.colFg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
1039 attrs.colBg = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE);
1040
1041 return attrs;
1042 }
1043
1044 wxColour wxWindowBase::GetBackgroundColour() const
1045 {
1046 if ( !m_backgroundColour.Ok() )
1047 {
1048 wxASSERT_MSG( !m_hasBgCol, _T("we have invalid explicit bg colour?") );
1049
1050 // get our default background colour
1051 wxColour colBg = GetDefaultAttributes().colBg;
1052
1053 // we must return some valid colour to avoid redoing this every time
1054 // and also to avoid surprizing the applications written for older
1055 // wxWidgets versions where GetBackgroundColour() always returned
1056 // something -- so give them something even if it doesn't make sense
1057 // for this window (e.g. it has a themed background)
1058 if ( !colBg.Ok() )
1059 colBg = GetClassDefaultAttributes().colBg;
1060
1061 return colBg;
1062 }
1063 else
1064 return m_backgroundColour;
1065 }
1066
1067 wxColour wxWindowBase::GetForegroundColour() const
1068 {
1069 // logic is the same as above
1070 if ( !m_hasFgCol && !m_foregroundColour.Ok() )
1071 {
1072 wxASSERT_MSG( !m_hasFgCol, _T("we have invalid explicit fg colour?") );
1073
1074 wxColour colFg = GetDefaultAttributes().colFg;
1075
1076 if ( !colFg.Ok() )
1077 colFg = GetClassDefaultAttributes().colFg;
1078
1079 return colFg;
1080 }
1081 else
1082 return m_foregroundColour;
1083 }
1084
1085 bool wxWindowBase::SetBackgroundColour( const wxColour &colour )
1086 {
1087 if ( colour == m_backgroundColour )
1088 return false;
1089
1090 m_hasBgCol = colour.Ok();
1091 if ( m_backgroundStyle != wxBG_STYLE_CUSTOM )
1092 m_backgroundStyle = m_hasBgCol ? wxBG_STYLE_COLOUR : wxBG_STYLE_SYSTEM;
1093
1094 m_inheritBgCol = m_hasBgCol;
1095 m_backgroundColour = colour;
1096 SetThemeEnabled( !m_hasBgCol && !m_foregroundColour.Ok() );
1097 return true;
1098 }
1099
1100 bool wxWindowBase::SetForegroundColour( const wxColour &colour )
1101 {
1102 if (colour == m_foregroundColour )
1103 return false;
1104
1105 m_hasFgCol = colour.Ok();
1106 m_inheritFgCol = m_hasFgCol;
1107 m_foregroundColour = colour;
1108 SetThemeEnabled( !m_hasFgCol && !m_backgroundColour.Ok() );
1109 return true;
1110 }
1111
1112 bool wxWindowBase::SetCursor(const wxCursor& cursor)
1113 {
1114 // setting an invalid cursor is ok, it means that we don't have any special
1115 // cursor
1116 if ( m_cursor == cursor )
1117 {
1118 // no change
1119 return false;
1120 }
1121
1122 m_cursor = cursor;
1123
1124 return true;
1125 }
1126
1127 wxFont wxWindowBase::GetFont() const
1128 {
1129 // logic is the same as in GetBackgroundColour()
1130 if ( !m_font.Ok() )
1131 {
1132 wxASSERT_MSG( !m_hasFont, _T("we have invalid explicit font?") );
1133
1134 wxFont font = GetDefaultAttributes().font;
1135 if ( !font.Ok() )
1136 font = GetClassDefaultAttributes().font;
1137
1138 return font;
1139 }
1140 else
1141 return m_font;
1142 }
1143
1144 bool wxWindowBase::SetFont(const wxFont& font)
1145 {
1146 if ( font == m_font )
1147 {
1148 // no change
1149 return false;
1150 }
1151
1152 m_font = font;
1153 m_hasFont = font.Ok();
1154 m_inheritFont = m_hasFont;
1155
1156 InvalidateBestSize();
1157
1158 return true;
1159 }
1160
1161 #if wxUSE_PALETTE
1162
1163 void wxWindowBase::SetPalette(const wxPalette& pal)
1164 {
1165 m_hasCustomPalette = true;
1166 m_palette = pal;
1167
1168 // VZ: can anyone explain me what do we do here?
1169 wxWindowDC d((wxWindow *) this);
1170 d.SetPalette(pal);
1171 }
1172
1173 wxWindow *wxWindowBase::GetAncestorWithCustomPalette() const
1174 {
1175 wxWindow *win = (wxWindow *)this;
1176 while ( win && !win->HasCustomPalette() )
1177 {
1178 win = win->GetParent();
1179 }
1180
1181 return win;
1182 }
1183
1184 #endif // wxUSE_PALETTE
1185
1186 #if wxUSE_CARET
1187 void wxWindowBase::SetCaret(wxCaret *caret)
1188 {
1189 if ( m_caret )
1190 {
1191 delete m_caret;
1192 }
1193
1194 m_caret = caret;
1195
1196 if ( m_caret )
1197 {
1198 wxASSERT_MSG( m_caret->GetWindow() == this,
1199 wxT("caret should be created associated to this window") );
1200 }
1201 }
1202 #endif // wxUSE_CARET
1203
1204 #if wxUSE_VALIDATORS
1205 // ----------------------------------------------------------------------------
1206 // validators
1207 // ----------------------------------------------------------------------------
1208
1209 void wxWindowBase::SetValidator(const wxValidator& validator)
1210 {
1211 if ( m_windowValidator )
1212 delete m_windowValidator;
1213
1214 m_windowValidator = (wxValidator *)validator.Clone();
1215
1216 if ( m_windowValidator )
1217 m_windowValidator->SetWindow(this);
1218 }
1219 #endif // wxUSE_VALIDATORS
1220
1221 // ----------------------------------------------------------------------------
1222 // update region stuff
1223 // ----------------------------------------------------------------------------
1224
1225 wxRect wxWindowBase::GetUpdateClientRect() const
1226 {
1227 wxRegion rgnUpdate = GetUpdateRegion();
1228 rgnUpdate.Intersect(GetClientRect());
1229 wxRect rectUpdate = rgnUpdate.GetBox();
1230 wxPoint ptOrigin = GetClientAreaOrigin();
1231 rectUpdate.x -= ptOrigin.x;
1232 rectUpdate.y -= ptOrigin.y;
1233
1234 return rectUpdate;
1235 }
1236
1237 bool wxWindowBase::IsExposed(int x, int y) const
1238 {
1239 return m_updateRegion.Contains(x, y) != wxOutRegion;
1240 }
1241
1242 bool wxWindowBase::IsExposed(int x, int y, int w, int h) const
1243 {
1244 return m_updateRegion.Contains(x, y, w, h) != wxOutRegion;
1245 }
1246
1247 void wxWindowBase::ClearBackground()
1248 {
1249 // wxGTK uses its own version, no need to add never used code
1250 #ifndef __WXGTK__
1251 wxClientDC dc((wxWindow *)this);
1252 wxBrush brush(GetBackgroundColour(), wxSOLID);
1253 dc.SetBackground(brush);
1254 dc.Clear();
1255 #endif // __WXGTK__
1256 }
1257
1258 // ----------------------------------------------------------------------------
1259 // find child window by id or name
1260 // ----------------------------------------------------------------------------
1261
1262 wxWindow *wxWindowBase::FindWindow(long id) const
1263 {
1264 if ( id == m_windowId )
1265 return (wxWindow *)this;
1266
1267 wxWindowBase *res = (wxWindow *)NULL;
1268 wxWindowList::compatibility_iterator node;
1269 for ( node = m_children.GetFirst(); node && !res; node = node->GetNext() )
1270 {
1271 wxWindowBase *child = node->GetData();
1272 res = child->FindWindow( id );
1273 }
1274
1275 return (wxWindow *)res;
1276 }
1277
1278 wxWindow *wxWindowBase::FindWindow(const wxString& name) const
1279 {
1280 if ( name == m_windowName )
1281 return (wxWindow *)this;
1282
1283 wxWindowBase *res = (wxWindow *)NULL;
1284 wxWindowList::compatibility_iterator node;
1285 for ( node = m_children.GetFirst(); node && !res; node = node->GetNext() )
1286 {
1287 wxWindow *child = node->GetData();
1288 res = child->FindWindow(name);
1289 }
1290
1291 return (wxWindow *)res;
1292 }
1293
1294
1295 // find any window by id or name or label: If parent is non-NULL, look through
1296 // children for a label or title matching the specified string. If NULL, look
1297 // through all top-level windows.
1298 //
1299 // to avoid duplicating code we reuse the same helper function but with
1300 // different comparators
1301
1302 typedef bool (*wxFindWindowCmp)(const wxWindow *win,
1303 const wxString& label, long id);
1304
1305 static
1306 bool wxFindWindowCmpLabels(const wxWindow *win, const wxString& label,
1307 long WXUNUSED(id))
1308 {
1309 return win->GetLabel() == label;
1310 }
1311
1312 static
1313 bool wxFindWindowCmpNames(const wxWindow *win, const wxString& label,
1314 long WXUNUSED(id))
1315 {
1316 return win->GetName() == label;
1317 }
1318
1319 static
1320 bool wxFindWindowCmpIds(const wxWindow *win, const wxString& WXUNUSED(label),
1321 long id)
1322 {
1323 return win->GetId() == id;
1324 }
1325
1326 // recursive helper for the FindWindowByXXX() functions
1327 static
1328 wxWindow *wxFindWindowRecursively(const wxWindow *parent,
1329 const wxString& label,
1330 long id,
1331 wxFindWindowCmp cmp)
1332 {
1333 if ( parent )
1334 {
1335 // see if this is the one we're looking for
1336 if ( (*cmp)(parent, label, id) )
1337 return (wxWindow *)parent;
1338
1339 // It wasn't, so check all its children
1340 for ( wxWindowList::compatibility_iterator node = parent->GetChildren().GetFirst();
1341 node;
1342 node = node->GetNext() )
1343 {
1344 // recursively check each child
1345 wxWindow *win = (wxWindow *)node->GetData();
1346 wxWindow *retwin = wxFindWindowRecursively(win, label, id, cmp);
1347 if (retwin)
1348 return retwin;
1349 }
1350 }
1351
1352 // Not found
1353 return NULL;
1354 }
1355
1356 // helper for FindWindowByXXX()
1357 static
1358 wxWindow *wxFindWindowHelper(const wxWindow *parent,
1359 const wxString& label,
1360 long id,
1361 wxFindWindowCmp cmp)
1362 {
1363 if ( parent )
1364 {
1365 // just check parent and all its children
1366 return wxFindWindowRecursively(parent, label, id, cmp);
1367 }
1368
1369 // start at very top of wx's windows
1370 for ( wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetFirst();
1371 node;
1372 node = node->GetNext() )
1373 {
1374 // recursively check each window & its children
1375 wxWindow *win = node->GetData();
1376 wxWindow *retwin = wxFindWindowRecursively(win, label, id, cmp);
1377 if (retwin)
1378 return retwin;
1379 }
1380
1381 return NULL;
1382 }
1383
1384 /* static */
1385 wxWindow *
1386 wxWindowBase::FindWindowByLabel(const wxString& title, const wxWindow *parent)
1387 {
1388 return wxFindWindowHelper(parent, title, 0, wxFindWindowCmpLabels);
1389 }
1390
1391 /* static */
1392 wxWindow *
1393 wxWindowBase::FindWindowByName(const wxString& title, const wxWindow *parent)
1394 {
1395 wxWindow *win = wxFindWindowHelper(parent, title, 0, wxFindWindowCmpNames);
1396
1397 if ( !win )
1398 {
1399 // fall back to the label
1400 win = FindWindowByLabel(title, parent);
1401 }
1402
1403 return win;
1404 }
1405
1406 /* static */
1407 wxWindow *
1408 wxWindowBase::FindWindowById( long id, const wxWindow* parent )
1409 {
1410 return wxFindWindowHelper(parent, wxEmptyString, id, wxFindWindowCmpIds);
1411 }
1412
1413 // ----------------------------------------------------------------------------
1414 // dialog oriented functions
1415 // ----------------------------------------------------------------------------
1416
1417 void wxWindowBase::MakeModal(bool modal)
1418 {
1419 // Disable all other windows
1420 if ( IsTopLevel() )
1421 {
1422 wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetFirst();
1423 while (node)
1424 {
1425 wxWindow *win = node->GetData();
1426 if (win != this)
1427 win->Enable(!modal);
1428
1429 node = node->GetNext();
1430 }
1431 }
1432 }
1433
1434 bool wxWindowBase::Validate()
1435 {
1436 #if wxUSE_VALIDATORS
1437 bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
1438
1439 wxWindowList::compatibility_iterator node;
1440 for ( node = m_children.GetFirst(); node; node = node->GetNext() )
1441 {
1442 wxWindowBase *child = node->GetData();
1443 wxValidator *validator = child->GetValidator();
1444 if ( validator && !validator->Validate((wxWindow *)this) )
1445 {
1446 return false;
1447 }
1448
1449 if ( recurse && !child->Validate() )
1450 {
1451 return false;
1452 }
1453 }
1454 #endif // wxUSE_VALIDATORS
1455
1456 return true;
1457 }
1458
1459 bool wxWindowBase::TransferDataToWindow()
1460 {
1461 #if wxUSE_VALIDATORS
1462 bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
1463
1464 wxWindowList::compatibility_iterator node;
1465 for ( node = m_children.GetFirst(); node; node = node->GetNext() )
1466 {
1467 wxWindowBase *child = node->GetData();
1468 wxValidator *validator = child->GetValidator();
1469 if ( validator && !validator->TransferToWindow() )
1470 {
1471 wxLogWarning(_("Could not transfer data to window"));
1472 #if wxUSE_LOG
1473 wxLog::FlushActive();
1474 #endif // wxUSE_LOG
1475
1476 return false;
1477 }
1478
1479 if ( recurse )
1480 {
1481 if ( !child->TransferDataToWindow() )
1482 {
1483 // warning already given
1484 return false;
1485 }
1486 }
1487 }
1488 #endif // wxUSE_VALIDATORS
1489
1490 return true;
1491 }
1492
1493 bool wxWindowBase::TransferDataFromWindow()
1494 {
1495 #if wxUSE_VALIDATORS
1496 bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
1497
1498 wxWindowList::compatibility_iterator node;
1499 for ( node = m_children.GetFirst(); node; node = node->GetNext() )
1500 {
1501 wxWindow *child = node->GetData();
1502 wxValidator *validator = child->GetValidator();
1503 if ( validator && !validator->TransferFromWindow() )
1504 {
1505 // nop warning here because the application is supposed to give
1506 // one itself - we don't know here what might have gone wrongly
1507
1508 return false;
1509 }
1510
1511 if ( recurse )
1512 {
1513 if ( !child->TransferDataFromWindow() )
1514 {
1515 // warning already given
1516 return false;
1517 }
1518 }
1519 }
1520 #endif // wxUSE_VALIDATORS
1521
1522 return true;
1523 }
1524
1525 void wxWindowBase::InitDialog()
1526 {
1527 wxInitDialogEvent event(GetId());
1528 event.SetEventObject( this );
1529 GetEventHandler()->ProcessEvent(event);
1530 }
1531
1532 // ----------------------------------------------------------------------------
1533 // context-sensitive help support
1534 // ----------------------------------------------------------------------------
1535
1536 #if wxUSE_HELP
1537
1538 // associate this help text with this window
1539 void wxWindowBase::SetHelpText(const wxString& text)
1540 {
1541 wxHelpProvider *helpProvider = wxHelpProvider::Get();
1542 if ( helpProvider )
1543 {
1544 helpProvider->AddHelp(this, text);
1545 }
1546 }
1547
1548 // associate this help text with all windows with the same id as this
1549 // one
1550 void wxWindowBase::SetHelpTextForId(const wxString& text)
1551 {
1552 wxHelpProvider *helpProvider = wxHelpProvider::Get();
1553 if ( helpProvider )
1554 {
1555 helpProvider->AddHelp(GetId(), text);
1556 }
1557 }
1558
1559 // get the help string associated with this window (may be empty)
1560 wxString wxWindowBase::GetHelpText() const
1561 {
1562 wxString text;
1563 wxHelpProvider *helpProvider = wxHelpProvider::Get();
1564 if ( helpProvider )
1565 {
1566 text = helpProvider->GetHelp(this);
1567 }
1568
1569 return text;
1570 }
1571
1572 // show help for this window
1573 void wxWindowBase::OnHelp(wxHelpEvent& event)
1574 {
1575 wxHelpProvider *helpProvider = wxHelpProvider::Get();
1576 if ( helpProvider )
1577 {
1578 if ( helpProvider->ShowHelp(this) )
1579 {
1580 // skip the event.Skip() below
1581 return;
1582 }
1583 }
1584
1585 event.Skip();
1586 }
1587
1588 #endif // wxUSE_HELP
1589
1590 // ----------------------------------------------------------------------------
1591 // tooltipsroot.Replace("\\", "/");
1592 // ----------------------------------------------------------------------------
1593
1594 #if wxUSE_TOOLTIPS
1595
1596 void wxWindowBase::SetToolTip( const wxString &tip )
1597 {
1598 // don't create the new tooltip if we already have one
1599 if ( m_tooltip )
1600 {
1601 m_tooltip->SetTip( tip );
1602 }
1603 else
1604 {
1605 SetToolTip( new wxToolTip( tip ) );
1606 }
1607
1608 // setting empty tooltip text does not remove the tooltip any more - use
1609 // SetToolTip((wxToolTip *)NULL) for this
1610 }
1611
1612 void wxWindowBase::DoSetToolTip(wxToolTip *tooltip)
1613 {
1614 if ( m_tooltip )
1615 delete m_tooltip;
1616
1617 m_tooltip = tooltip;
1618 }
1619
1620 #endif // wxUSE_TOOLTIPS
1621
1622 // ----------------------------------------------------------------------------
1623 // constraints and sizers
1624 // ----------------------------------------------------------------------------
1625
1626 #if wxUSE_CONSTRAINTS
1627
1628 void wxWindowBase::SetConstraints( wxLayoutConstraints *constraints )
1629 {
1630 if ( m_constraints )
1631 {
1632 UnsetConstraints(m_constraints);
1633 delete m_constraints;
1634 }
1635 m_constraints = constraints;
1636 if ( m_constraints )
1637 {
1638 // Make sure other windows know they're part of a 'meaningful relationship'
1639 if ( m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this) )
1640 m_constraints->left.GetOtherWindow()->AddConstraintReference(this);
1641 if ( m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this) )
1642 m_constraints->top.GetOtherWindow()->AddConstraintReference(this);
1643 if ( m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this) )
1644 m_constraints->right.GetOtherWindow()->AddConstraintReference(this);
1645 if ( m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this) )
1646 m_constraints->bottom.GetOtherWindow()->AddConstraintReference(this);
1647 if ( m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this) )
1648 m_constraints->width.GetOtherWindow()->AddConstraintReference(this);
1649 if ( m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this) )
1650 m_constraints->height.GetOtherWindow()->AddConstraintReference(this);
1651 if ( m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this) )
1652 m_constraints->centreX.GetOtherWindow()->AddConstraintReference(this);
1653 if ( m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this) )
1654 m_constraints->centreY.GetOtherWindow()->AddConstraintReference(this);
1655 }
1656 }
1657
1658 // This removes any dangling pointers to this window in other windows'
1659 // constraintsInvolvedIn lists.
1660 void wxWindowBase::UnsetConstraints(wxLayoutConstraints *c)
1661 {
1662 if ( c )
1663 {
1664 if ( c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this) )
1665 c->left.GetOtherWindow()->RemoveConstraintReference(this);
1666 if ( c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this) )
1667 c->top.GetOtherWindow()->RemoveConstraintReference(this);
1668 if ( c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this) )
1669 c->right.GetOtherWindow()->RemoveConstraintReference(this);
1670 if ( c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this) )
1671 c->bottom.GetOtherWindow()->RemoveConstraintReference(this);
1672 if ( c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this) )
1673 c->width.GetOtherWindow()->RemoveConstraintReference(this);
1674 if ( c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this) )
1675 c->height.GetOtherWindow()->RemoveConstraintReference(this);
1676 if ( c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this) )
1677 c->centreX.GetOtherWindow()->RemoveConstraintReference(this);
1678 if ( c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this) )
1679 c->centreY.GetOtherWindow()->RemoveConstraintReference(this);
1680 }
1681 }
1682
1683 // Back-pointer to other windows we're involved with, so if we delete this
1684 // window, we must delete any constraints we're involved with.
1685 void wxWindowBase::AddConstraintReference(wxWindowBase *otherWin)
1686 {
1687 if ( !m_constraintsInvolvedIn )
1688 m_constraintsInvolvedIn = new wxWindowList;
1689 if ( !m_constraintsInvolvedIn->Find((wxWindow *)otherWin) )
1690 m_constraintsInvolvedIn->Append((wxWindow *)otherWin);
1691 }
1692
1693 // REMOVE back-pointer to other windows we're involved with.
1694 void wxWindowBase::RemoveConstraintReference(wxWindowBase *otherWin)
1695 {
1696 if ( m_constraintsInvolvedIn )
1697 m_constraintsInvolvedIn->DeleteObject((wxWindow *)otherWin);
1698 }
1699
1700 // Reset any constraints that mention this window
1701 void wxWindowBase::DeleteRelatedConstraints()
1702 {
1703 if ( m_constraintsInvolvedIn )
1704 {
1705 wxWindowList::compatibility_iterator node = m_constraintsInvolvedIn->GetFirst();
1706 while (node)
1707 {
1708 wxWindow *win = node->GetData();
1709 wxLayoutConstraints *constr = win->GetConstraints();
1710
1711 // Reset any constraints involving this window
1712 if ( constr )
1713 {
1714 constr->left.ResetIfWin(this);
1715 constr->top.ResetIfWin(this);
1716 constr->right.ResetIfWin(this);
1717 constr->bottom.ResetIfWin(this);
1718 constr->width.ResetIfWin(this);
1719 constr->height.ResetIfWin(this);
1720 constr->centreX.ResetIfWin(this);
1721 constr->centreY.ResetIfWin(this);
1722 }
1723
1724 wxWindowList::compatibility_iterator next = node->GetNext();
1725 m_constraintsInvolvedIn->Erase(node);
1726 node = next;
1727 }
1728
1729 delete m_constraintsInvolvedIn;
1730 m_constraintsInvolvedIn = (wxWindowList *) NULL;
1731 }
1732 }
1733
1734 #endif // wxUSE_CONSTRAINTS
1735
1736 void wxWindowBase::SetSizer(wxSizer *sizer, bool deleteOld)
1737 {
1738 if ( sizer == m_windowSizer)
1739 return;
1740
1741 if ( deleteOld )
1742 delete m_windowSizer;
1743
1744 m_windowSizer = sizer;
1745
1746 SetAutoLayout( sizer != NULL );
1747 }
1748
1749 void wxWindowBase::SetSizerAndFit(wxSizer *sizer, bool deleteOld)
1750 {
1751 SetSizer( sizer, deleteOld );
1752 sizer->SetSizeHints( (wxWindow*) this );
1753 }
1754
1755
1756 void wxWindowBase::SetContainingSizer(wxSizer* sizer)
1757 {
1758 // adding a window to a sizer twice is going to result in fatal and
1759 // hard to debug problems later because when deleting the second
1760 // associated wxSizerItem we're going to dereference a dangling
1761 // pointer; so try to detect this as early as possible
1762 wxASSERT_MSG( !sizer || m_containingSizer != sizer,
1763 _T("Adding a window to the same sizer twice?") );
1764
1765 m_containingSizer = sizer;
1766 }
1767
1768 #if wxUSE_CONSTRAINTS
1769
1770 void wxWindowBase::SatisfyConstraints()
1771 {
1772 wxLayoutConstraints *constr = GetConstraints();
1773 bool wasOk = constr && constr->AreSatisfied();
1774
1775 ResetConstraints(); // Mark all constraints as unevaluated
1776
1777 int noChanges = 1;
1778
1779 // if we're a top level panel (i.e. our parent is frame/dialog), our
1780 // own constraints will never be satisfied any more unless we do it
1781 // here
1782 if ( wasOk )
1783 {
1784 while ( noChanges > 0 )
1785 {
1786 LayoutPhase1(&noChanges);
1787 }
1788 }
1789
1790 LayoutPhase2(&noChanges);
1791 }
1792
1793 #endif // wxUSE_CONSTRAINTS
1794
1795 bool wxWindowBase::Layout()
1796 {
1797 // If there is a sizer, use it instead of the constraints
1798 if ( GetSizer() )
1799 {
1800 int w, h;
1801 GetVirtualSize(&w, &h);
1802 GetSizer()->SetDimension( 0, 0, w, h );
1803 }
1804 #if wxUSE_CONSTRAINTS
1805 else
1806 {
1807 SatisfyConstraints(); // Find the right constraints values
1808 SetConstraintSizes(); // Recursively set the real window sizes
1809 }
1810 #endif
1811
1812 return true;
1813 }
1814
1815 #if wxUSE_CONSTRAINTS
1816
1817 // first phase of the constraints evaluation: set our own constraints
1818 bool wxWindowBase::LayoutPhase1(int *noChanges)
1819 {
1820 wxLayoutConstraints *constr = GetConstraints();
1821
1822 return !constr || constr->SatisfyConstraints(this, noChanges);
1823 }
1824
1825 // second phase: set the constraints for our children
1826 bool wxWindowBase::LayoutPhase2(int *noChanges)
1827 {
1828 *noChanges = 0;
1829
1830 // Layout children
1831 DoPhase(1);
1832
1833 // Layout grand children
1834 DoPhase(2);
1835
1836 return true;
1837 }
1838
1839 // Do a phase of evaluating child constraints
1840 bool wxWindowBase::DoPhase(int phase)
1841 {
1842 // the list containing the children for which the constraints are already
1843 // set correctly
1844 wxWindowList succeeded;
1845
1846 // the max number of iterations we loop before concluding that we can't set
1847 // the constraints
1848 static const int maxIterations = 500;
1849
1850 for ( int noIterations = 0; noIterations < maxIterations; noIterations++ )
1851 {
1852 int noChanges = 0;
1853
1854 // loop over all children setting their constraints
1855 for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
1856 node;
1857 node = node->GetNext() )
1858 {
1859 wxWindow *child = node->GetData();
1860 if ( child->IsTopLevel() )
1861 {
1862 // top level children are not inside our client area
1863 continue;
1864 }
1865
1866 if ( !child->GetConstraints() || succeeded.Find(child) )
1867 {
1868 // this one is either already ok or nothing we can do about it
1869 continue;
1870 }
1871
1872 int tempNoChanges = 0;
1873 bool success = phase == 1 ? child->LayoutPhase1(&tempNoChanges)
1874 : child->LayoutPhase2(&tempNoChanges);
1875 noChanges += tempNoChanges;
1876
1877 if ( success )
1878 {
1879 succeeded.Append(child);
1880 }
1881 }
1882
1883 if ( !noChanges )
1884 {
1885 // constraints are set
1886 break;
1887 }
1888 }
1889
1890 return true;
1891 }
1892
1893 void wxWindowBase::ResetConstraints()
1894 {
1895 wxLayoutConstraints *constr = GetConstraints();
1896 if ( constr )
1897 {
1898 constr->left.SetDone(false);
1899 constr->top.SetDone(false);
1900 constr->right.SetDone(false);
1901 constr->bottom.SetDone(false);
1902 constr->width.SetDone(false);
1903 constr->height.SetDone(false);
1904 constr->centreX.SetDone(false);
1905 constr->centreY.SetDone(false);
1906 }
1907
1908 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
1909 while (node)
1910 {
1911 wxWindow *win = node->GetData();
1912 if ( !win->IsTopLevel() )
1913 win->ResetConstraints();
1914 node = node->GetNext();
1915 }
1916 }
1917
1918 // Need to distinguish between setting the 'fake' size for windows and sizers,
1919 // and setting the real values.
1920 void wxWindowBase::SetConstraintSizes(bool recurse)
1921 {
1922 wxLayoutConstraints *constr = GetConstraints();
1923 if ( constr && constr->AreSatisfied() )
1924 {
1925 int x = constr->left.GetValue();
1926 int y = constr->top.GetValue();
1927 int w = constr->width.GetValue();
1928 int h = constr->height.GetValue();
1929
1930 if ( (constr->width.GetRelationship() != wxAsIs ) ||
1931 (constr->height.GetRelationship() != wxAsIs) )
1932 {
1933 SetSize(x, y, w, h);
1934 }
1935 else
1936 {
1937 // If we don't want to resize this window, just move it...
1938 Move(x, y);
1939 }
1940 }
1941 else if ( constr )
1942 {
1943 wxLogDebug(wxT("Constraints not satisfied for %s named '%s'."),
1944 GetClassInfo()->GetClassName(),
1945 GetName().c_str());
1946 }
1947
1948 if ( recurse )
1949 {
1950 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
1951 while (node)
1952 {
1953 wxWindow *win = node->GetData();
1954 if ( !win->IsTopLevel() && win->GetConstraints() )
1955 win->SetConstraintSizes();
1956 node = node->GetNext();
1957 }
1958 }
1959 }
1960
1961 // Only set the size/position of the constraint (if any)
1962 void wxWindowBase::SetSizeConstraint(int x, int y, int w, int h)
1963 {
1964 wxLayoutConstraints *constr = GetConstraints();
1965 if ( constr )
1966 {
1967 if ( x != wxDefaultCoord )
1968 {
1969 constr->left.SetValue(x);
1970 constr->left.SetDone(true);
1971 }
1972 if ( y != wxDefaultCoord )
1973 {
1974 constr->top.SetValue(y);
1975 constr->top.SetDone(true);
1976 }
1977 if ( w != wxDefaultCoord )
1978 {
1979 constr->width.SetValue(w);
1980 constr->width.SetDone(true);
1981 }
1982 if ( h != wxDefaultCoord )
1983 {
1984 constr->height.SetValue(h);
1985 constr->height.SetDone(true);
1986 }
1987 }
1988 }
1989
1990 void wxWindowBase::MoveConstraint(int x, int y)
1991 {
1992 wxLayoutConstraints *constr = GetConstraints();
1993 if ( constr )
1994 {
1995 if ( x != wxDefaultCoord )
1996 {
1997 constr->left.SetValue(x);
1998 constr->left.SetDone(true);
1999 }
2000 if ( y != wxDefaultCoord )
2001 {
2002 constr->top.SetValue(y);
2003 constr->top.SetDone(true);
2004 }
2005 }
2006 }
2007
2008 void wxWindowBase::GetSizeConstraint(int *w, int *h) const
2009 {
2010 wxLayoutConstraints *constr = GetConstraints();
2011 if ( constr )
2012 {
2013 *w = constr->width.GetValue();
2014 *h = constr->height.GetValue();
2015 }
2016 else
2017 GetSize(w, h);
2018 }
2019
2020 void wxWindowBase::GetClientSizeConstraint(int *w, int *h) const
2021 {
2022 wxLayoutConstraints *constr = GetConstraints();
2023 if ( constr )
2024 {
2025 *w = constr->width.GetValue();
2026 *h = constr->height.GetValue();
2027 }
2028 else
2029 GetClientSize(w, h);
2030 }
2031
2032 void wxWindowBase::GetPositionConstraint(int *x, int *y) const
2033 {
2034 wxLayoutConstraints *constr = GetConstraints();
2035 if ( constr )
2036 {
2037 *x = constr->left.GetValue();
2038 *y = constr->top.GetValue();
2039 }
2040 else
2041 GetPosition(x, y);
2042 }
2043
2044 #endif // wxUSE_CONSTRAINTS
2045
2046 void wxWindowBase::AdjustForParentClientOrigin(int& x, int& y, int sizeFlags) const
2047 {
2048 // don't do it for the dialogs/frames - they float independently of their
2049 // parent
2050 if ( !IsTopLevel() )
2051 {
2052 wxWindow *parent = GetParent();
2053 if ( !(sizeFlags & wxSIZE_NO_ADJUSTMENTS) && parent )
2054 {
2055 wxPoint pt(parent->GetClientAreaOrigin());
2056 x += pt.x;
2057 y += pt.y;
2058 }
2059 }
2060 }
2061
2062 // ----------------------------------------------------------------------------
2063 // do Update UI processing for child controls
2064 // ----------------------------------------------------------------------------
2065
2066 void wxWindowBase::UpdateWindowUI(long flags)
2067 {
2068 wxUpdateUIEvent event(GetId());
2069 event.SetEventObject(this);
2070
2071 if ( GetEventHandler()->ProcessEvent(event) )
2072 {
2073 DoUpdateWindowUI(event);
2074 }
2075
2076 if (flags & wxUPDATE_UI_RECURSE)
2077 {
2078 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
2079 while (node)
2080 {
2081 wxWindow* child = (wxWindow*) node->GetData();
2082 child->UpdateWindowUI(flags);
2083 node = node->GetNext();
2084 }
2085 }
2086 }
2087
2088 // do the window-specific processing after processing the update event
2089 // TODO: take specific knowledge out of this function and
2090 // put in each control's base class. Unfortunately we don't
2091 // yet have base implementation files for wxCheckBox and wxRadioButton.
2092 void wxWindowBase::DoUpdateWindowUI(wxUpdateUIEvent& event)
2093 {
2094 if ( event.GetSetEnabled() )
2095 Enable(event.GetEnabled());
2096
2097 #if wxUSE_CONTROLS
2098 if ( event.GetSetText() )
2099 {
2100 wxControl *control = wxDynamicCastThis(wxControl);
2101 if ( control )
2102 {
2103 if ( event.GetText() != control->GetLabel() )
2104 control->SetLabel(event.GetText());
2105 }
2106 }
2107 #endif // wxUSE_CONTROLS
2108
2109 if ( event.GetSetChecked() )
2110 {
2111 #if wxUSE_CHECKBOX
2112 wxCheckBox *checkbox = wxDynamicCastThis(wxCheckBox);
2113 if ( checkbox )
2114 {
2115 checkbox->SetValue(event.GetChecked());
2116 }
2117 #endif // wxUSE_CHECKBOX
2118
2119 #if wxUSE_RADIOBTN
2120 wxRadioButton *radiobtn = wxDynamicCastThis(wxRadioButton);
2121 if ( radiobtn )
2122 {
2123 radiobtn->SetValue(event.GetChecked());
2124 }
2125 #endif // wxUSE_RADIOBTN
2126 }
2127 }
2128
2129 #if 0
2130 // call internal idle recursively
2131 // may be obsolete (wait until OnIdle scheme stabilises)
2132 void wxWindowBase::ProcessInternalIdle()
2133 {
2134 OnInternalIdle();
2135
2136 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
2137 while (node)
2138 {
2139 wxWindow *child = node->GetData();
2140 child->ProcessInternalIdle();
2141 node = node->GetNext();
2142 }
2143 }
2144 #endif
2145
2146 // ----------------------------------------------------------------------------
2147 // dialog units translations
2148 // ----------------------------------------------------------------------------
2149
2150 wxPoint wxWindowBase::ConvertPixelsToDialog(const wxPoint& pt)
2151 {
2152 int charWidth = GetCharWidth();
2153 int charHeight = GetCharHeight();
2154 wxPoint pt2 = wxDefaultPosition;
2155 if (pt.x != wxDefaultCoord)
2156 pt2.x = (int) ((pt.x * 4) / charWidth);
2157 if (pt.y != wxDefaultCoord)
2158 pt2.y = (int) ((pt.y * 8) / charHeight);
2159
2160 return pt2;
2161 }
2162
2163 wxPoint wxWindowBase::ConvertDialogToPixels(const wxPoint& pt)
2164 {
2165 int charWidth = GetCharWidth();
2166 int charHeight = GetCharHeight();
2167 wxPoint pt2 = wxDefaultPosition;
2168 if (pt.x != wxDefaultCoord)
2169 pt2.x = (int) ((pt.x * charWidth) / 4);
2170 if (pt.y != wxDefaultCoord)
2171 pt2.y = (int) ((pt.y * charHeight) / 8);
2172
2173 return pt2;
2174 }
2175
2176 // ----------------------------------------------------------------------------
2177 // event handlers
2178 // ----------------------------------------------------------------------------
2179
2180 // propagate the colour change event to the subwindows
2181 void wxWindowBase::OnSysColourChanged(wxSysColourChangedEvent& event)
2182 {
2183 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
2184 while ( node )
2185 {
2186 // Only propagate to non-top-level windows
2187 wxWindow *win = node->GetData();
2188 if ( !win->IsTopLevel() )
2189 {
2190 wxSysColourChangedEvent event2;
2191 event.SetEventObject(win);
2192 win->GetEventHandler()->ProcessEvent(event2);
2193 }
2194
2195 node = node->GetNext();
2196 }
2197
2198 Refresh();
2199 }
2200
2201 // the default action is to populate dialog with data when it's created,
2202 // and nudge the UI into displaying itself correctly in case
2203 // we've turned the wxUpdateUIEvents frequency down low.
2204 void wxWindowBase::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) )
2205 {
2206 TransferDataToWindow();
2207
2208 // Update the UI at this point
2209 UpdateWindowUI(wxUPDATE_UI_RECURSE);
2210 }
2211
2212 // process Ctrl-Alt-mclick
2213 void wxWindowBase::OnMiddleClick( wxMouseEvent& event )
2214 {
2215 #if wxUSE_MSGDLG
2216 if ( event.ControlDown() && event.AltDown() )
2217 {
2218 // don't translate these strings
2219 wxString port;
2220
2221 #ifdef __WXUNIVERSAL__
2222 port = _T("Univ/");
2223 #endif // __WXUNIVERSAL__
2224
2225 switch ( wxGetOsVersion() )
2226 {
2227 case wxMOTIF_X: port += _T("Motif"); break;
2228 case wxMAC:
2229 case wxMAC_DARWIN: port += _T("Mac"); break;
2230 case wxBEOS: port += _T("BeOS"); break;
2231 case wxGTK:
2232 case wxGTK_WIN32:
2233 case wxGTK_OS2:
2234 case wxGTK_BEOS: port += _T("GTK"); break;
2235 case wxWINDOWS:
2236 case wxPENWINDOWS:
2237 case wxWINDOWS_NT:
2238 case wxWIN32S:
2239 case wxWIN95:
2240 case wxWIN386: port += _T("MS Windows"); break;
2241 case wxMGL_UNIX:
2242 case wxMGL_X:
2243 case wxMGL_WIN32:
2244 case wxMGL_OS2: port += _T("MGL"); break;
2245 case wxWINDOWS_OS2:
2246 case wxOS2_PM: port += _T("OS/2"); break;
2247 default: port += _T("unknown"); break;
2248 }
2249
2250 wxMessageBox(wxString::Format(
2251 _T(
2252 " wxWidgets Library (%s port)\nVersion %u.%u.%u%s%s, compiled at %s %s\n Copyright (c) 1995-2005 wxWidgets team"
2253 ),
2254 port.c_str(),
2255 wxMAJOR_VERSION,
2256 wxMINOR_VERSION,
2257 wxRELEASE_NUMBER,
2258 #if wxUSE_UNICODE
2259 L" (Unicode)",
2260 #else
2261 "",
2262 #endif
2263 #ifdef __WXDEBUG__
2264 _T(" Debug build"),
2265 #else
2266 wxEmptyString,
2267 #endif
2268 __TDATE__,
2269 __TTIME__
2270 ),
2271 _T("wxWidgets information"),
2272 wxICON_INFORMATION | wxOK,
2273 (wxWindow *)this);
2274 }
2275 else
2276 #endif // wxUSE_MSGDLG
2277 {
2278 event.Skip();
2279 }
2280 }
2281
2282 // ----------------------------------------------------------------------------
2283 // accessibility
2284 // ----------------------------------------------------------------------------
2285
2286 #if wxUSE_ACCESSIBILITY
2287 void wxWindowBase::SetAccessible(wxAccessible* accessible)
2288 {
2289 if (m_accessible && (accessible != m_accessible))
2290 delete m_accessible;
2291 m_accessible = accessible;
2292 if (m_accessible)
2293 m_accessible->SetWindow((wxWindow*) this);
2294 }
2295
2296 // Returns the accessible object, creating if necessary.
2297 wxAccessible* wxWindowBase::GetOrCreateAccessible()
2298 {
2299 if (!m_accessible)
2300 m_accessible = CreateAccessible();
2301 return m_accessible;
2302 }
2303
2304 // Override to create a specific accessible object.
2305 wxAccessible* wxWindowBase::CreateAccessible()
2306 {
2307 return new wxWindowAccessible((wxWindow*) this);
2308 }
2309
2310 #endif
2311
2312 // ----------------------------------------------------------------------------
2313 // list classes implementation
2314 // ----------------------------------------------------------------------------
2315
2316 #if wxUSE_STL
2317
2318 #include <wx/listimpl.cpp>
2319 WX_DEFINE_LIST(wxWindowList);
2320
2321 #else
2322
2323 void wxWindowListNode::DeleteData()
2324 {
2325 delete (wxWindow *)GetData();
2326 }
2327
2328 #endif
2329
2330 // ----------------------------------------------------------------------------
2331 // borders
2332 // ----------------------------------------------------------------------------
2333
2334 wxBorder wxWindowBase::GetBorder(long flags) const
2335 {
2336 wxBorder border = (wxBorder)(flags & wxBORDER_MASK);
2337 if ( border == wxBORDER_DEFAULT )
2338 {
2339 border = GetDefaultBorder();
2340 }
2341
2342 return border;
2343 }
2344
2345 wxBorder wxWindowBase::GetDefaultBorder() const
2346 {
2347 return wxBORDER_NONE;
2348 }
2349
2350 // ----------------------------------------------------------------------------
2351 // hit testing
2352 // ----------------------------------------------------------------------------
2353
2354 wxHitTest wxWindowBase::DoHitTest(wxCoord x, wxCoord y) const
2355 {
2356 // here we just check if the point is inside the window or not
2357
2358 // check the top and left border first
2359 bool outside = x < 0 || y < 0;
2360 if ( !outside )
2361 {
2362 // check the right and bottom borders too
2363 wxSize size = GetSize();
2364 outside = x >= size.x || y >= size.y;
2365 }
2366
2367 return outside ? wxHT_WINDOW_OUTSIDE : wxHT_WINDOW_INSIDE;
2368 }
2369
2370 // ----------------------------------------------------------------------------
2371 // mouse capture
2372 // ----------------------------------------------------------------------------
2373
2374 struct WXDLLEXPORT wxWindowNext
2375 {
2376 wxWindow *win;
2377 wxWindowNext *next;
2378 } *wxWindowBase::ms_winCaptureNext = NULL;
2379
2380 void wxWindowBase::CaptureMouse()
2381 {
2382 wxLogTrace(_T("mousecapture"), _T("CaptureMouse(%p)"), this);
2383
2384 wxWindow *winOld = GetCapture();
2385 if ( winOld )
2386 {
2387 ((wxWindowBase*) winOld)->DoReleaseMouse();
2388
2389 // save it on stack
2390 wxWindowNext *item = new wxWindowNext;
2391 item->win = winOld;
2392 item->next = ms_winCaptureNext;
2393 ms_winCaptureNext = item;
2394 }
2395 //else: no mouse capture to save
2396
2397 DoCaptureMouse();
2398 }
2399
2400 void wxWindowBase::ReleaseMouse()
2401 {
2402 wxLogTrace(_T("mousecapture"), _T("ReleaseMouse(%p)"), this);
2403
2404 wxASSERT_MSG( GetCapture() == this, wxT("attempt to release mouse, but this window hasn't captured it") );
2405
2406 DoReleaseMouse();
2407
2408 if ( ms_winCaptureNext )
2409 {
2410 ((wxWindowBase*)ms_winCaptureNext->win)->DoCaptureMouse();
2411
2412 wxWindowNext *item = ms_winCaptureNext;
2413 ms_winCaptureNext = item->next;
2414 delete item;
2415 }
2416 //else: stack is empty, no previous capture
2417
2418 wxLogTrace(_T("mousecapture"),
2419 (const wxChar *) _T("After ReleaseMouse() mouse is captured by %p"),
2420 GetCapture());
2421 }
2422
2423 #if wxUSE_HOTKEY
2424
2425 bool
2426 wxWindowBase::RegisterHotKey(int WXUNUSED(hotkeyId),
2427 int WXUNUSED(modifiers),
2428 int WXUNUSED(keycode))
2429 {
2430 // not implemented
2431 return false;
2432 }
2433
2434 bool wxWindowBase::UnregisterHotKey(int WXUNUSED(hotkeyId))
2435 {
2436 // not implemented
2437 return false;
2438 }
2439
2440 #endif // wxUSE_HOTKEY
2441
2442 void wxWindowBase::SendDestroyEvent()
2443 {
2444 wxWindowDestroyEvent event;
2445 event.SetEventObject(this);
2446 event.SetId(GetId());
2447 GetEventHandler()->ProcessEvent(event);
2448 }
2449
2450 // ----------------------------------------------------------------------------
2451 // event processing
2452 // ----------------------------------------------------------------------------
2453
2454 bool wxWindowBase::TryValidator(wxEvent& wxVALIDATOR_PARAM(event))
2455 {
2456 #if wxUSE_VALIDATORS
2457 // Can only use the validator of the window which
2458 // is receiving the event
2459 if ( event.GetEventObject() == this )
2460 {
2461 wxValidator *validator = GetValidator();
2462 if ( validator && validator->ProcessEvent(event) )
2463 {
2464 return true;
2465 }
2466 }
2467 #endif // wxUSE_VALIDATORS
2468
2469 return false;
2470 }
2471
2472 bool wxWindowBase::TryParent(wxEvent& event)
2473 {
2474 // carry on up the parent-child hierarchy if the propgation count hasn't
2475 // reached zero yet
2476 if ( event.ShouldPropagate() )
2477 {
2478 // honour the requests to stop propagation at this window: this is
2479 // used by the dialogs, for example, to prevent processing the events
2480 // from the dialog controls in the parent frame which rarely, if ever,
2481 // makes sense
2482 if ( !(GetExtraStyle() & wxWS_EX_BLOCK_EVENTS) )
2483 {
2484 wxWindow *parent = GetParent();
2485 if ( parent && !parent->IsBeingDeleted() )
2486 {
2487 wxPropagateOnce propagateOnce(event);
2488
2489 return parent->GetEventHandler()->ProcessEvent(event);
2490 }
2491 }
2492 }
2493
2494 return wxEvtHandler::TryParent(event);
2495 }
2496
2497 // ----------------------------------------------------------------------------
2498 // keyboard navigation
2499 // ----------------------------------------------------------------------------
2500
2501 // Navigates in the specified direction.
2502 bool wxWindowBase::Navigate(int flags)
2503 {
2504 wxNavigationKeyEvent eventNav;
2505 eventNav.SetFlags(flags);
2506 eventNav.SetEventObject(this);
2507 if ( GetParent()->GetEventHandler()->ProcessEvent(eventNav) )
2508 {
2509 return true;
2510 }
2511 return false;
2512 }
2513
2514 void wxWindowBase::DoMoveInTabOrder(wxWindow *win, MoveKind move)
2515 {
2516 // check that we're not a top level window
2517 wxCHECK_RET( GetParent(),
2518 _T("MoveBefore/AfterInTabOrder() don't work for TLWs!") );
2519
2520 // detect the special case when we have nothing to do anyhow and when the
2521 // code below wouldn't work
2522 if ( win == this )
2523 return;
2524
2525 // find the target window in the siblings list
2526 wxWindowList& siblings = GetParent()->GetChildren();
2527 wxWindowList::compatibility_iterator i = siblings.Find(win);
2528 wxCHECK_RET( i, _T("MoveBefore/AfterInTabOrder(): win is not a sibling") );
2529
2530 // unfortunately, when wxUSE_STL == 1 DetachNode() is not implemented so we
2531 // can't just move the node around
2532 wxWindow *self = (wxWindow *)this;
2533 siblings.DeleteObject(self);
2534 if ( move == MoveAfter )
2535 {
2536 i = i->GetNext();
2537 }
2538
2539 if ( i )
2540 {
2541 siblings.Insert(i, self);
2542 }
2543 else // MoveAfter and win was the last sibling
2544 {
2545 siblings.Append(self);
2546 }
2547 }
2548
2549 // ----------------------------------------------------------------------------
2550 // focus handling
2551 // ----------------------------------------------------------------------------
2552
2553 /*static*/ wxWindow* wxWindowBase::FindFocus()
2554 {
2555 wxWindowBase *win = DoFindFocus();
2556 return win ? win->GetMainWindowOfCompositeControl() : NULL;
2557 }
2558
2559 // ----------------------------------------------------------------------------
2560 // global functions
2561 // ----------------------------------------------------------------------------
2562
2563 wxWindow* wxGetTopLevelParent(wxWindow *win)
2564 {
2565 while ( win && !win->IsTopLevel() )
2566 win = win->GetParent();
2567
2568 return win;
2569 }
2570
2571 #if wxUSE_ACCESSIBILITY
2572 // ----------------------------------------------------------------------------
2573 // accessible object for windows
2574 // ----------------------------------------------------------------------------
2575
2576 // Can return either a child object, or an integer
2577 // representing the child element, starting from 1.
2578 wxAccStatus wxWindowAccessible::HitTest(const wxPoint& WXUNUSED(pt), int* WXUNUSED(childId), wxAccessible** WXUNUSED(childObject))
2579 {
2580 wxASSERT( GetWindow() != NULL );
2581 if (!GetWindow())
2582 return wxACC_FAIL;
2583
2584 return wxACC_NOT_IMPLEMENTED;
2585 }
2586
2587 // Returns the rectangle for this object (id = 0) or a child element (id > 0).
2588 wxAccStatus wxWindowAccessible::GetLocation(wxRect& rect, int elementId)
2589 {
2590 wxASSERT( GetWindow() != NULL );
2591 if (!GetWindow())
2592 return wxACC_FAIL;
2593
2594 wxWindow* win = NULL;
2595 if (elementId == 0)
2596 {
2597 win = GetWindow();
2598 }
2599 else
2600 {
2601 if (elementId <= (int) GetWindow()->GetChildren().GetCount())
2602 {
2603 win = GetWindow()->GetChildren().Item(elementId-1)->GetData();
2604 }
2605 else
2606 return wxACC_FAIL;
2607 }
2608 if (win)
2609 {
2610 rect = win->GetRect();
2611 if (win->GetParent() && !win->IsKindOf(CLASSINFO(wxTopLevelWindow)))
2612 rect.SetPosition(win->GetParent()->ClientToScreen(rect.GetPosition()));
2613 return wxACC_OK;
2614 }
2615
2616 return wxACC_NOT_IMPLEMENTED;
2617 }
2618
2619 // Navigates from fromId to toId/toObject.
2620 wxAccStatus wxWindowAccessible::Navigate(wxNavDir navDir, int fromId,
2621 int* WXUNUSED(toId), wxAccessible** toObject)
2622 {
2623 wxASSERT( GetWindow() != NULL );
2624 if (!GetWindow())
2625 return wxACC_FAIL;
2626
2627 switch (navDir)
2628 {
2629 case wxNAVDIR_FIRSTCHILD:
2630 {
2631 if (GetWindow()->GetChildren().GetCount() == 0)
2632 return wxACC_FALSE;
2633 wxWindow* childWindow = (wxWindow*) GetWindow()->GetChildren().GetFirst()->GetData();
2634 *toObject = childWindow->GetOrCreateAccessible();
2635
2636 return wxACC_OK;
2637 }
2638 case wxNAVDIR_LASTCHILD:
2639 {
2640 if (GetWindow()->GetChildren().GetCount() == 0)
2641 return wxACC_FALSE;
2642 wxWindow* childWindow = (wxWindow*) GetWindow()->GetChildren().GetLast()->GetData();
2643 *toObject = childWindow->GetOrCreateAccessible();
2644
2645 return wxACC_OK;
2646 }
2647 case wxNAVDIR_RIGHT:
2648 case wxNAVDIR_DOWN:
2649 case wxNAVDIR_NEXT:
2650 {
2651 wxWindowList::compatibility_iterator node =
2652 wxWindowList::compatibility_iterator();
2653 if (fromId == 0)
2654 {
2655 // Can't navigate to sibling of this window
2656 // if we're a top-level window.
2657 if (!GetWindow()->GetParent())
2658 return wxACC_NOT_IMPLEMENTED;
2659
2660 node = GetWindow()->GetParent()->GetChildren().Find(GetWindow());
2661 }
2662 else
2663 {
2664 if (fromId <= (int) GetWindow()->GetChildren().GetCount())
2665 node = GetWindow()->GetChildren().Item(fromId-1);
2666 }
2667
2668 if (node && node->GetNext())
2669 {
2670 wxWindow* nextWindow = node->GetNext()->GetData();
2671 *toObject = nextWindow->GetOrCreateAccessible();
2672 return wxACC_OK;
2673 }
2674 else
2675 return wxACC_FALSE;
2676 }
2677 case wxNAVDIR_LEFT:
2678 case wxNAVDIR_UP:
2679 case wxNAVDIR_PREVIOUS:
2680 {
2681 wxWindowList::compatibility_iterator node =
2682 wxWindowList::compatibility_iterator();
2683 if (fromId == 0)
2684 {
2685 // Can't navigate to sibling of this window
2686 // if we're a top-level window.
2687 if (!GetWindow()->GetParent())
2688 return wxACC_NOT_IMPLEMENTED;
2689
2690 node = GetWindow()->GetParent()->GetChildren().Find(GetWindow());
2691 }
2692 else
2693 {
2694 if (fromId <= (int) GetWindow()->GetChildren().GetCount())
2695 node = GetWindow()->GetChildren().Item(fromId-1);
2696 }
2697
2698 if (node && node->GetPrevious())
2699 {
2700 wxWindow* previousWindow = node->GetPrevious()->GetData();
2701 *toObject = previousWindow->GetOrCreateAccessible();
2702 return wxACC_OK;
2703 }
2704 else
2705 return wxACC_FALSE;
2706 }
2707 }
2708
2709 return wxACC_NOT_IMPLEMENTED;
2710 }
2711
2712 // Gets the name of the specified object.
2713 wxAccStatus wxWindowAccessible::GetName(int childId, wxString* name)
2714 {
2715 wxASSERT( GetWindow() != NULL );
2716 if (!GetWindow())
2717 return wxACC_FAIL;
2718
2719 wxString title;
2720
2721 // If a child, leave wxWidgets to call the function on the actual
2722 // child object.
2723 if (childId > 0)
2724 return wxACC_NOT_IMPLEMENTED;
2725
2726 // This will eventually be replaced by specialised
2727 // accessible classes, one for each kind of wxWidgets
2728 // control or window.
2729 #if wxUSE_BUTTON
2730 if (GetWindow()->IsKindOf(CLASSINFO(wxButton)))
2731 title = ((wxButton*) GetWindow())->GetLabel();
2732 else
2733 #endif
2734 title = GetWindow()->GetName();
2735
2736 if (!title.empty())
2737 {
2738 *name = title;
2739 return wxACC_OK;
2740 }
2741 else
2742 return wxACC_NOT_IMPLEMENTED;
2743 }
2744
2745 // Gets the number of children.
2746 wxAccStatus wxWindowAccessible::GetChildCount(int* childId)
2747 {
2748 wxASSERT( GetWindow() != NULL );
2749 if (!GetWindow())
2750 return wxACC_FAIL;
2751
2752 *childId = (int) GetWindow()->GetChildren().GetCount();
2753 return wxACC_OK;
2754 }
2755
2756 // Gets the specified child (starting from 1).
2757 // If *child is NULL and return value is wxACC_OK,
2758 // this means that the child is a simple element and
2759 // not an accessible object.
2760 wxAccStatus wxWindowAccessible::GetChild(int childId, wxAccessible** child)
2761 {
2762 wxASSERT( GetWindow() != NULL );
2763 if (!GetWindow())
2764 return wxACC_FAIL;
2765
2766 if (childId == 0)
2767 {
2768 *child = this;
2769 return wxACC_OK;
2770 }
2771
2772 if (childId > (int) GetWindow()->GetChildren().GetCount())
2773 return wxACC_FAIL;
2774
2775 wxWindow* childWindow = GetWindow()->GetChildren().Item(childId-1)->GetData();
2776 *child = childWindow->GetOrCreateAccessible();
2777 if (*child)
2778 return wxACC_OK;
2779 else
2780 return wxACC_FAIL;
2781 }
2782
2783 // Gets the parent, or NULL.
2784 wxAccStatus wxWindowAccessible::GetParent(wxAccessible** parent)
2785 {
2786 wxASSERT( GetWindow() != NULL );
2787 if (!GetWindow())
2788 return wxACC_FAIL;
2789
2790 wxWindow* parentWindow = GetWindow()->GetParent();
2791 if (!parentWindow)
2792 {
2793 *parent = NULL;
2794 return wxACC_OK;
2795 }
2796 else
2797 {
2798 *parent = parentWindow->GetOrCreateAccessible();
2799 if (*parent)
2800 return wxACC_OK;
2801 else
2802 return wxACC_FAIL;
2803 }
2804 }
2805
2806 // Performs the default action. childId is 0 (the action for this object)
2807 // or > 0 (the action for a child).
2808 // Return wxACC_NOT_SUPPORTED if there is no default action for this
2809 // window (e.g. an edit control).
2810 wxAccStatus wxWindowAccessible::DoDefaultAction(int WXUNUSED(childId))
2811 {
2812 wxASSERT( GetWindow() != NULL );
2813 if (!GetWindow())
2814 return wxACC_FAIL;
2815
2816 return wxACC_NOT_IMPLEMENTED;
2817 }
2818
2819 // Gets the default action for this object (0) or > 0 (the action for a child).
2820 // Return wxACC_OK even if there is no action. actionName is the action, or the empty
2821 // string if there is no action.
2822 // The retrieved string describes the action that is performed on an object,
2823 // not what the object does as a result. For example, a toolbar button that prints
2824 // a document has a default action of "Press" rather than "Prints the current document."
2825 wxAccStatus wxWindowAccessible::GetDefaultAction(int WXUNUSED(childId), wxString* WXUNUSED(actionName))
2826 {
2827 wxASSERT( GetWindow() != NULL );
2828 if (!GetWindow())
2829 return wxACC_FAIL;
2830
2831 return wxACC_NOT_IMPLEMENTED;
2832 }
2833
2834 // Returns the description for this object or a child.
2835 wxAccStatus wxWindowAccessible::GetDescription(int WXUNUSED(childId), wxString* description)
2836 {
2837 wxASSERT( GetWindow() != NULL );
2838 if (!GetWindow())
2839 return wxACC_FAIL;
2840
2841 wxString ht(GetWindow()->GetHelpText());
2842 if (!ht.empty())
2843 {
2844 *description = ht;
2845 return wxACC_OK;
2846 }
2847 return wxACC_NOT_IMPLEMENTED;
2848 }
2849
2850 // Returns help text for this object or a child, similar to tooltip text.
2851 wxAccStatus wxWindowAccessible::GetHelpText(int WXUNUSED(childId), wxString* helpText)
2852 {
2853 wxASSERT( GetWindow() != NULL );
2854 if (!GetWindow())
2855 return wxACC_FAIL;
2856
2857 wxString ht(GetWindow()->GetHelpText());
2858 if (!ht.empty())
2859 {
2860 *helpText = ht;
2861 return wxACC_OK;
2862 }
2863 return wxACC_NOT_IMPLEMENTED;
2864 }
2865
2866 // Returns the keyboard shortcut for this object or child.
2867 // Return e.g. ALT+K
2868 wxAccStatus wxWindowAccessible::GetKeyboardShortcut(int WXUNUSED(childId), wxString* WXUNUSED(shortcut))
2869 {
2870 wxASSERT( GetWindow() != NULL );
2871 if (!GetWindow())
2872 return wxACC_FAIL;
2873
2874 return wxACC_NOT_IMPLEMENTED;
2875 }
2876
2877 // Returns a role constant.
2878 wxAccStatus wxWindowAccessible::GetRole(int childId, wxAccRole* role)
2879 {
2880 wxASSERT( GetWindow() != NULL );
2881 if (!GetWindow())
2882 return wxACC_FAIL;
2883
2884 // If a child, leave wxWidgets to call the function on the actual
2885 // child object.
2886 if (childId > 0)
2887 return wxACC_NOT_IMPLEMENTED;
2888
2889 if (GetWindow()->IsKindOf(CLASSINFO(wxControl)))
2890 return wxACC_NOT_IMPLEMENTED;
2891 #if wxUSE_STATUSBAR
2892 if (GetWindow()->IsKindOf(CLASSINFO(wxStatusBar)))
2893 return wxACC_NOT_IMPLEMENTED;
2894 #endif
2895 #if wxUSE_TOOLBAR
2896 if (GetWindow()->IsKindOf(CLASSINFO(wxToolBar)))
2897 return wxACC_NOT_IMPLEMENTED;
2898 #endif
2899
2900 //*role = wxROLE_SYSTEM_CLIENT;
2901 *role = wxROLE_SYSTEM_CLIENT;
2902 return wxACC_OK;
2903
2904 #if 0
2905 return wxACC_NOT_IMPLEMENTED;
2906 #endif
2907 }
2908
2909 // Returns a state constant.
2910 wxAccStatus wxWindowAccessible::GetState(int childId, long* state)
2911 {
2912 wxASSERT( GetWindow() != NULL );
2913 if (!GetWindow())
2914 return wxACC_FAIL;
2915
2916 // If a child, leave wxWidgets to call the function on the actual
2917 // child object.
2918 if (childId > 0)
2919 return wxACC_NOT_IMPLEMENTED;
2920
2921 if (GetWindow()->IsKindOf(CLASSINFO(wxControl)))
2922 return wxACC_NOT_IMPLEMENTED;
2923
2924 #if wxUSE_STATUSBAR
2925 if (GetWindow()->IsKindOf(CLASSINFO(wxStatusBar)))
2926 return wxACC_NOT_IMPLEMENTED;
2927 #endif
2928 #if wxUSE_TOOLBAR
2929 if (GetWindow()->IsKindOf(CLASSINFO(wxToolBar)))
2930 return wxACC_NOT_IMPLEMENTED;
2931 #endif
2932
2933 *state = 0;
2934 return wxACC_OK;
2935
2936 #if 0
2937 return wxACC_NOT_IMPLEMENTED;
2938 #endif
2939 }
2940
2941 // Returns a localized string representing the value for the object
2942 // or child.
2943 wxAccStatus wxWindowAccessible::GetValue(int WXUNUSED(childId), wxString* WXUNUSED(strValue))
2944 {
2945 wxASSERT( GetWindow() != NULL );
2946 if (!GetWindow())
2947 return wxACC_FAIL;
2948
2949 return wxACC_NOT_IMPLEMENTED;
2950 }
2951
2952 // Selects the object or child.
2953 wxAccStatus wxWindowAccessible::Select(int WXUNUSED(childId), wxAccSelectionFlags WXUNUSED(selectFlags))
2954 {
2955 wxASSERT( GetWindow() != NULL );
2956 if (!GetWindow())
2957 return wxACC_FAIL;
2958
2959 return wxACC_NOT_IMPLEMENTED;
2960 }
2961
2962 // Gets the window with the keyboard focus.
2963 // If childId is 0 and child is NULL, no object in
2964 // this subhierarchy has the focus.
2965 // If this object has the focus, child should be 'this'.
2966 wxAccStatus wxWindowAccessible::GetFocus(int* WXUNUSED(childId), wxAccessible** WXUNUSED(child))
2967 {
2968 wxASSERT( GetWindow() != NULL );
2969 if (!GetWindow())
2970 return wxACC_FAIL;
2971
2972 return wxACC_NOT_IMPLEMENTED;
2973 }
2974
2975 // Gets a variant representing the selected children
2976 // of this object.
2977 // Acceptable values:
2978 // - a null variant (IsNull() returns true)
2979 // - a list variant (GetType() == wxT("list")
2980 // - an integer representing the selected child element,
2981 // or 0 if this object is selected (GetType() == wxT("long")
2982 // - a "void*" pointer to a wxAccessible child object
2983 wxAccStatus wxWindowAccessible::GetSelections(wxVariant* WXUNUSED(selections))
2984 {
2985 wxASSERT( GetWindow() != NULL );
2986 if (!GetWindow())
2987 return wxACC_FAIL;
2988
2989 return wxACC_NOT_IMPLEMENTED;
2990 }
2991
2992 #endif // wxUSE_ACCESSIBILITY