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