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