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