X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/20a1eea1fd93719fecec5fc44a408b0fc4e3cf33..92f1a59c288e0e181d2998a93220a73b89f675df:/src/common/wincmn.cpp diff --git a/src/common/wincmn.cpp b/src/common/wincmn.cpp index 8e3d5e4634..6cc620cf4f 100644 --- a/src/common/wincmn.cpp +++ b/src/common/wincmn.cpp @@ -6,7 +6,7 @@ // Created: 13/07/98 // RCS-ID: $Id$ // Copyright: (c) wxWindows team -// Licence: wxWindows license +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // ============================================================================ @@ -38,11 +38,13 @@ #include "wx/control.h" #include "wx/checkbox.h" #include "wx/radiobut.h" + #include "wx/statbox.h" #include "wx/textctrl.h" #include "wx/settings.h" #include "wx/dialog.h" #include "wx/msgdlg.h" #include "wx/statusbr.h" + #include "wx/dcclient.h" #endif //WX_PRECOMP #if wxUSE_CONSTRAINTS @@ -55,6 +57,10 @@ #include "wx/dnd.h" #endif // wxUSE_DRAG_AND_DROP +#if wxUSE_ACCESSIBILITY + #include "wx/access.h" +#endif + #if wxUSE_HELP #include "wx/cshelp.h" #endif // wxUSE_HELP @@ -71,7 +77,11 @@ // static data // ---------------------------------------------------------------------------- +#if defined(__WXPM__) +int wxWindowBase::ms_lastControlId = 2000; +#else int wxWindowBase::ms_lastControlId = -200; +#endif IMPLEMENT_ABSTRACT_CLASS(wxWindowBase, wxEvtHandler) @@ -104,7 +114,6 @@ void wxWindowBase::InitBase() // no window yet, no parent nor children m_parent = (wxWindow *)NULL; m_windowId = -1; - m_children.DeleteContents( FALSE ); // don't auto delete node data // no constraints on the minimal window size m_minWidth = @@ -139,15 +148,13 @@ void wxWindowBase::InitBase() m_hasBgCol = m_hasFgCol = m_hasFont = FALSE; + + m_isBeingDeleted = FALSE; // no style bits m_exStyle = m_windowStyle = 0; - // an optimization for the event processing: checking this flag is much - // faster than using IsKindOf(CLASSINFO(wxWindow)) - m_isWindow = TRUE; - #if wxUSE_CONSTRAINTS // no constraints whatsoever m_constraints = (wxLayoutConstraints *) NULL; @@ -174,6 +181,17 @@ void wxWindowBase::InitBase() m_hasCustomPalette = FALSE; #endif // wxUSE_PALETTE +#if wxUSE_ACCESSIBILITY + m_accessible = NULL; +#endif + + m_virtualSize = wxDefaultSize; + + m_minVirtualWidth = + m_minVirtualHeight = + m_maxVirtualWidth = + m_maxVirtualHeight = -1; + // Whether we're using the current theme for this window (wxGTK only for now) m_themeEnabled = FALSE; } @@ -187,13 +205,25 @@ bool wxWindowBase::CreateBase(wxWindowBase *parent, const wxValidator& validator, const wxString& name) { - // m_isWindow is set to TRUE in wxWindowBase::Init() as well as many other - // member variables - check that it has been called (will catch the case - // when a new ctor is added which doesn't call InitWindow) - wxASSERT_MSG( m_isWindow, wxT("Init() must have been called before!") ); +#if wxUSE_STATBOX + // wxGTK doesn't allow to create controls with static box as the parent so + // this will result in a crash when the program is ported to wxGTK so warn + // the user about it + + // if you get this assert, the correct solution is to create the controls + // as siblings of the static box + wxASSERT_MSG( !parent || !wxDynamicCast(parent, wxStaticBox), + _T("wxStaticBox can't be used as a window parent!") ); +#endif // wxUSE_STATBOX + + // ids are limited to 16 bits under MSW so if you care about portability, + // it's not a good idea to use ids out of this range (and negative ids are + // reserved for wxWindows own usage) + wxASSERT_MSG( id == wxID_ANY || (id >= 0 && id < 32767), + _T("invalid id value") ); // generate a new id if the user doesn't care about it - m_windowId = id == -1 ? NewControlId() : id; + m_windowId = id == wxID_ANY ? NewControlId() : id; SetName(name); SetWindowStyleFlag(style); @@ -208,7 +238,7 @@ bool wxWindowBase::CreateBase(wxWindowBase *parent, // dialog/frame and all children will inherit it by defult if ( parent && (parent->GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) ) { - SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY); + SetExtraStyle(GetExtraStyle() | wxWS_EX_VALIDATE_RECURSIVELY); } return TRUE; @@ -232,7 +262,7 @@ wxWindowBase::~wxWindowBase() // Just in case we've loaded a top-level window via LoadNativeDialog but // we weren't a dialog class - wxTopLevelWindows.DeleteObject(this); + wxTopLevelWindows.DeleteObject((wxWindow*)this); wxASSERT_MSG( GetChildren().GetCount() == 0, wxT("children not destroyed") ); @@ -263,7 +293,7 @@ wxWindowBase::~wxWindowBase() #endif // wxUSE_CONSTRAINTS if ( m_containingSizer ) - m_containingSizer->Remove((wxWindow*)this); + m_containingSizer->Detach( (wxWindow*)this ); if ( m_windowSizer ) delete m_windowSizer; @@ -278,6 +308,11 @@ wxWindowBase::~wxWindowBase() delete m_tooltip; #endif // wxUSE_TOOLTIPS +#if wxUSE_ACCESSIBILITY + if ( m_accessible ) + delete m_accessible; +#endif + // reset the dangling pointer our parent window may keep to us if ( m_parent && m_parent->GetDefaultItem() == this ) { @@ -308,7 +343,7 @@ bool wxWindowBase::Close(bool force) bool wxWindowBase::DestroyChildren() { - wxWindowList::Node *node; + wxWindowList::compatibility_iterator node; for ( ;; ) { // we iterate until the list becomes empty @@ -357,6 +392,20 @@ void wxWindowBase::Centre(int direction) } } + // there is no wxTopLevelWindow under wxMotif yet +#ifndef __WXMOTIF__ + // we shouldn't center the dialog on the iconized window: under + // Windows, for example, this places it completely off the screen + if ( parent ) + { + wxTopLevelWindow *winTop = wxDynamicCast(parent, wxTopLevelWindow); + if ( winTop && winTop->IsIconized() ) + { + parent = NULL; + } + } +#endif // __WXMOTIF__ + // did we find the parent? if ( !parent ) { @@ -440,28 +489,71 @@ void wxWindowBase::Fit() { if ( GetChildren().GetCount() > 0 ) { - wxSize size = DoGetBestSize(); - - // for compatibility with the old versions and because it really looks - // slightly more pretty like this, add a pad - size.x += 7; - size.y += 14; - - SetClientSize(size); + SetClientSize(DoGetBestSize()); } //else: do nothing if we have no children } +// fits virtual size (ie. scrolled area etc.) around children +void wxWindowBase::FitInside() +{ + if ( GetChildren().GetCount() > 0 ) + { + SetVirtualSize( GetBestVirtualSize() ); + } +} + // return the size best suited for the current window wxSize wxWindowBase::DoGetBestSize() const { - if ( GetChildren().GetCount() > 0 ) + if ( m_windowSizer ) + { + return m_windowSizer->GetMinSize(); + } +#if wxUSE_CONSTRAINTS + else if ( m_constraints ) + { + wxConstCast(this, wxWindowBase)->SatisfyConstraints(); + + // our minimal acceptable size is such that all our windows fit inside + int maxX = 0, + maxY = 0; + + for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); + node; + node = node->GetNext() ) + { + wxLayoutConstraints *c = node->GetData()->GetConstraints(); + if ( !c ) + { + // it's not normal that we have an unconstrained child, but + // what can we do about it? + continue; + } + + int x = c->right.GetValue(), + y = c->bottom.GetValue(); + + if ( x > maxX ) + maxX = x; + + if ( y > maxY ) + maxY = y; + + // TODO: we must calculate the overlaps somehow, otherwise we + // will never return a size bigger than the current one :-( + } + + return wxSize(maxX, maxY); + } +#endif // wxUSE_CONSTRAINTS + else if ( GetChildren().GetCount() > 0 ) { // our minimal acceptable size is such that all our windows fit inside int maxX = 0, maxY = 0; - for ( wxWindowList::Node *node = GetChildren().GetFirst(); + for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); node; node = node->GetNext() ) { @@ -495,6 +587,11 @@ wxSize wxWindowBase::DoGetBestSize() const maxY = wy + wh; } + // for compatibility with the old versions and because it really looks + // slightly more pretty like this, add a pad + maxX += 7; + maxY += 14; + return wxSize(maxX, maxY); } else @@ -516,12 +613,49 @@ void wxWindowBase::SetSizeHints(int minW, int minH, int maxW, int maxH, int WXUNUSED(incW), int WXUNUSED(incH)) { + // setting min width greater than max width leads to infinite loops under + // X11 and generally doesn't make any sense, so don't allow it + wxCHECK_RET( (minW == -1 || maxW == -1 || minW <= maxW) && + (minH == -1 || maxH == -1 || minH <= maxH), + _T("min width/height must be less than max width/height!") ); + m_minWidth = minW; m_maxWidth = maxW; m_minHeight = minH; m_maxHeight = maxH; } +void wxWindowBase::SetVirtualSizeHints( int minW, int minH, + int maxW, int maxH ) +{ + m_minVirtualWidth = minW; + m_maxVirtualWidth = maxW; + m_minVirtualHeight = minH; + m_maxVirtualHeight = maxH; +} + +void wxWindowBase::DoSetVirtualSize( int x, int y ) +{ + if ( m_minVirtualWidth != -1 && m_minVirtualWidth > x ) + x = m_minVirtualWidth; + if ( m_maxVirtualWidth != -1 && m_maxVirtualWidth < x ) + x = m_maxVirtualWidth; + if ( m_minVirtualHeight != -1 && m_minVirtualHeight > y ) + y = m_minVirtualHeight; + if ( m_maxVirtualHeight != -1 && m_maxVirtualHeight < y ) + y = m_maxVirtualHeight; + + m_virtualSize = wxSize(x, y); +} + +wxSize wxWindowBase::DoGetVirtualSize() const +{ + wxSize s( GetClientSize() ); + + return wxSize( wxMax( m_virtualSize.GetWidth(), s.GetWidth() ), + wxMax( m_virtualSize.GetHeight(), s.GetHeight() ) ); +} + // ---------------------------------------------------------------------------- // show/hide/enable/disable the window // ---------------------------------------------------------------------------- @@ -573,9 +707,9 @@ void wxWindowBase::AddChild(wxWindowBase *child) // this should never happen and it will lead to a crash later if it does // because RemoveChild() will remove only one node from the children list // and the other(s) one(s) will be left with dangling pointers in them - wxASSERT_MSG( !GetChildren().Find(child), _T("AddChild() called twice") ); + wxASSERT_MSG( !GetChildren().Find((wxWindow*)child), _T("AddChild() called twice") ); - GetChildren().Append(child); + GetChildren().Append((wxWindow*)child); child->SetParent(this); } @@ -583,8 +717,8 @@ void wxWindowBase::RemoveChild(wxWindowBase *child) { wxCHECK_RET( child, wxT("can't remove a NULL child") ); - GetChildren().DeleteObject(child); - child->SetParent((wxWindow *)NULL); + GetChildren().DeleteObject((wxWindow *)child); + child->SetParent(NULL); } bool wxWindowBase::Reparent(wxWindowBase *newParent) @@ -603,7 +737,7 @@ bool wxWindowBase::Reparent(wxWindowBase *newParent) } else { - wxTopLevelWindows.DeleteObject(this); + wxTopLevelWindows.DeleteObject((wxWindow *)this); } // add it to the new one @@ -613,7 +747,7 @@ bool wxWindowBase::Reparent(wxWindowBase *newParent) } else { - wxTopLevelWindows.Append(this); + wxTopLevelWindows.Append((wxWindow *)this); } return TRUE; @@ -625,7 +759,13 @@ bool wxWindowBase::Reparent(wxWindowBase *newParent) void wxWindowBase::PushEventHandler(wxEvtHandler *handler) { - handler->SetNextHandler(GetEventHandler()); + wxEvtHandler *handlerOld = GetEventHandler(); + + handler->SetNextHandler(handlerOld); + + if ( handlerOld ) + GetEventHandler()->SetPreviousHandler(handler); + SetEventHandler(handler); } @@ -636,7 +776,11 @@ wxEvtHandler *wxWindowBase::PopEventHandler(bool deleteHandler) { wxEvtHandler *handlerB = handlerA->GetNextHandler(); handlerA->SetNextHandler((wxEvtHandler *)NULL); + + if ( handlerB ) + handlerB->SetPreviousHandler((wxEvtHandler *)NULL); SetEventHandler(handlerB); + if ( deleteHandler ) { delete handlerA; @@ -668,6 +812,10 @@ bool wxWindowBase::RemoveEventHandler(wxEvtHandler *handler) SetEventHandler(handlerNext); } + if ( handlerNext ) + { + handlerNext->SetPreviousHandler ( handlerPrev ); + } handler->SetNextHandler(NULL); return TRUE; @@ -830,7 +978,7 @@ bool wxWindowBase::IsExposed(int x, int y, int w, int h) const } // ---------------------------------------------------------------------------- -// find window by id or name +// find child window by id or name // ---------------------------------------------------------------------------- wxWindow *wxWindowBase::FindWindow( long id ) @@ -839,7 +987,7 @@ wxWindow *wxWindowBase::FindWindow( long id ) return (wxWindow *)this; wxWindowBase *res = (wxWindow *)NULL; - wxWindowList::Node *node; + wxWindowList::compatibility_iterator node; for ( node = m_children.GetFirst(); node && !res; node = node->GetNext() ) { wxWindowBase *child = node->GetData(); @@ -855,7 +1003,7 @@ wxWindow *wxWindowBase::FindWindow( const wxString& name ) return (wxWindow *)this; wxWindowBase *res = (wxWindow *)NULL; - wxWindowList::Node *node; + wxWindowList::compatibility_iterator node; for ( node = m_children.GetFirst(); node && !res; node = node->GetNext() ) { wxWindow *child = node->GetData(); @@ -865,6 +1013,125 @@ wxWindow *wxWindowBase::FindWindow( const wxString& name ) return (wxWindow *)res; } + +// find any window by id or name or label: If parent is non-NULL, look through +// children for a label or title matching the specified string. If NULL, look +// through all top-level windows. +// +// to avoid duplicating code we reuse the same helper function but with +// different comparators + +typedef bool (*wxFindWindowCmp)(const wxWindow *win, + const wxString& label, long id); + +static +bool wxFindWindowCmpLabels(const wxWindow *win, const wxString& label, + long WXUNUSED(id)) +{ + return win->GetLabel() == label; +} + +static +bool wxFindWindowCmpNames(const wxWindow *win, const wxString& label, + long WXUNUSED(id)) +{ + return win->GetName() == label; +} + +static +bool wxFindWindowCmpIds(const wxWindow *win, const wxString& WXUNUSED(label), + long id) +{ + return win->GetId() == id; +} + +// recursive helper for the FindWindowByXXX() functions +static +wxWindow *wxFindWindowRecursively(const wxWindow *parent, + const wxString& label, + long id, + wxFindWindowCmp cmp) +{ + if ( parent ) + { + // see if this is the one we're looking for + if ( (*cmp)(parent, label, id) ) + return (wxWindow *)parent; + + // It wasn't, so check all its children + for ( wxWindowList::compatibility_iterator node = parent->GetChildren().GetFirst(); + node; + node = node->GetNext() ) + { + // recursively check each child + wxWindow *win = (wxWindow *)node->GetData(); + wxWindow *retwin = wxFindWindowRecursively(win, label, id, cmp); + if (retwin) + return retwin; + } + } + + // Not found + return NULL; +} + +// helper for FindWindowByXXX() +static +wxWindow *wxFindWindowHelper(const wxWindow *parent, + const wxString& label, + long id, + wxFindWindowCmp cmp) +{ + if ( parent ) + { + // just check parent and all its children + return wxFindWindowRecursively(parent, label, id, cmp); + } + + // start at very top of wx's windows + for ( wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetFirst(); + node; + node = node->GetNext() ) + { + // recursively check each window & its children + wxWindow *win = node->GetData(); + wxWindow *retwin = wxFindWindowRecursively(win, label, id, cmp); + if (retwin) + return retwin; + } + + return NULL; +} + +/* static */ +wxWindow * +wxWindowBase::FindWindowByLabel(const wxString& title, const wxWindow *parent) +{ + return wxFindWindowHelper(parent, title, 0, wxFindWindowCmpLabels); +} + +/* static */ +wxWindow * +wxWindowBase::FindWindowByName(const wxString& title, const wxWindow *parent) +{ + wxWindow *win = wxFindWindowHelper(parent, title, 0, wxFindWindowCmpNames); + + if ( !win ) + { + // fall back to the label + win = FindWindowByLabel(title, parent); + } + + return win; +} + +/* static */ +wxWindow * +wxWindowBase::FindWindowById( long id, const wxWindow* parent ) +{ + return wxFindWindowHelper(parent, _T(""), id, wxFindWindowCmpIds); +} + // ---------------------------------------------------------------------------- // dialog oriented functions // ---------------------------------------------------------------------------- @@ -874,7 +1141,7 @@ void wxWindowBase::MakeModal(bool modal) // Disable all other windows if ( IsTopLevel() ) { - wxWindowList::Node *node = wxTopLevelWindows.GetFirst(); + wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetFirst(); while (node) { wxWindow *win = node->GetData(); @@ -891,7 +1158,7 @@ bool wxWindowBase::Validate() #if wxUSE_VALIDATORS bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0; - wxWindowList::Node *node; + wxWindowList::compatibility_iterator node; for ( node = m_children.GetFirst(); node; node = node->GetNext() ) { wxWindowBase *child = node->GetData(); @@ -916,7 +1183,7 @@ bool wxWindowBase::TransferDataToWindow() #if wxUSE_VALIDATORS bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0; - wxWindowList::Node *node; + wxWindowList::compatibility_iterator node; for ( node = m_children.GetFirst(); node; node = node->GetNext() ) { wxWindowBase *child = node->GetData(); @@ -924,7 +1191,9 @@ bool wxWindowBase::TransferDataToWindow() if ( validator && !validator->TransferToWindow() ) { wxLogWarning(_("Could not transfer data to window")); +#if wxUSE_LOG wxLog::FlushActive(); +#endif // wxUSE_LOG return FALSE; } @@ -948,7 +1217,7 @@ bool wxWindowBase::TransferDataFromWindow() #if wxUSE_VALIDATORS bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0; - wxWindowList::Node *node; + wxWindowList::compatibility_iterator node; for ( node = m_children.GetFirst(); node; node = node->GetNext() ) { wxWindow *child = node->GetData(); @@ -1139,15 +1408,15 @@ void wxWindowBase::AddConstraintReference(wxWindowBase *otherWin) { if ( !m_constraintsInvolvedIn ) m_constraintsInvolvedIn = new wxWindowList; - if ( !m_constraintsInvolvedIn->Find(otherWin) ) - m_constraintsInvolvedIn->Append(otherWin); + if ( !m_constraintsInvolvedIn->Find((wxWindow *)otherWin) ) + m_constraintsInvolvedIn->Append((wxWindow *)otherWin); } // REMOVE back-pointer to other windows we're involved with. void wxWindowBase::RemoveConstraintReference(wxWindowBase *otherWin) { if ( m_constraintsInvolvedIn ) - m_constraintsInvolvedIn->DeleteObject(otherWin); + m_constraintsInvolvedIn->DeleteObject((wxWindow *)otherWin); } // Reset any constraints that mention this window @@ -1155,7 +1424,7 @@ void wxWindowBase::DeleteRelatedConstraints() { if ( m_constraintsInvolvedIn ) { - wxWindowList::Node *node = m_constraintsInvolvedIn->GetFirst(); + wxWindowList::compatibility_iterator node = m_constraintsInvolvedIn->GetFirst(); while (node) { wxWindow *win = node->GetData(); @@ -1174,8 +1443,8 @@ void wxWindowBase::DeleteRelatedConstraints() constr->centreY.ResetIfWin(this); } - wxWindowList::Node *next = node->GetNext(); - delete node; + wxWindowList::compatibility_iterator next = node->GetNext(); + m_constraintsInvolvedIn->Erase(node); node = next; } @@ -1183,47 +1452,65 @@ void wxWindowBase::DeleteRelatedConstraints() m_constraintsInvolvedIn = (wxWindowList *) NULL; } } -#endif -void wxWindowBase::SetSizer(wxSizer *sizer) +#endif // wxUSE_CONSTRAINTS + +void wxWindowBase::SetSizer(wxSizer *sizer, bool deleteOld) { - if (m_windowSizer) delete m_windowSizer; + if ( deleteOld ) + delete m_windowSizer; m_windowSizer = sizer; + + SetAutoLayout( sizer != NULL ); +} + +void wxWindowBase::SetSizerAndFit(wxSizer *sizer, bool deleteOld) +{ + SetSizer( sizer, deleteOld ); + sizer->SetSizeHints( (wxWindow*) this ); } +#if wxUSE_CONSTRAINTS + +void wxWindowBase::SatisfyConstraints() +{ + wxLayoutConstraints *constr = GetConstraints(); + bool wasOk = constr && constr->AreSatisfied(); + + ResetConstraints(); // Mark all constraints as unevaluated + + int noChanges = 1; + + // if we're a top level panel (i.e. our parent is frame/dialog), our + // own constraints will never be satisfied any more unless we do it + // here + if ( wasOk ) + { + while ( noChanges > 0 ) + { + LayoutPhase1(&noChanges); + } + } + + LayoutPhase2(&noChanges); +} + +#endif // wxUSE_CONSTRAINTS + bool wxWindowBase::Layout() { // If there is a sizer, use it instead of the constraints if ( GetSizer() ) { int w, h; - GetClientSize(&w, &h); - + GetVirtualSize(&w, &h); GetSizer()->SetDimension( 0, 0, w, h ); } #if wxUSE_CONSTRAINTS else { - wxLayoutConstraints *constr = GetConstraints(); - bool wasOk = constr && constr->AreSatisfied(); - - ResetConstraints(); // Mark all constraints as unevaluated - - // if we're a top level panel (i.e. our parent is frame/dialog), our - // own constraints will never be satisfied any more unless we do it - // here - if ( wasOk ) - { - int noChanges = 1; - while ( noChanges > 0 ) - { - constr->SatisfyConstraints(this, &noChanges); - } - } - - DoPhase(1); // Layout children - DoPhase(2); // Layout grand children + SatisfyConstraints(); // Find the right constraints values SetConstraintSizes(); // Recursively set the real window sizes } #endif @@ -1232,67 +1519,78 @@ bool wxWindowBase::Layout() } #if wxUSE_CONSTRAINTS -// Do a phase of evaluating constraints: the default behaviour. wxSizers may -// do a similar thing, but also impose their own 'constraints' and order the -// evaluation differently. + +// first phase of the constraints evaluation: set our own constraints bool wxWindowBase::LayoutPhase1(int *noChanges) { wxLayoutConstraints *constr = GetConstraints(); - if ( constr ) - { - return constr->SatisfyConstraints(this, noChanges); - } - else - return TRUE; + + return !constr || constr->SatisfyConstraints(this, noChanges); } +// second phase: set the constraints for our children bool wxWindowBase::LayoutPhase2(int *noChanges) { *noChanges = 0; // Layout children DoPhase(1); + + // Layout grand children DoPhase(2); + return TRUE; } // Do a phase of evaluating child constraints bool wxWindowBase::DoPhase(int phase) { - int noIterations = 0; - int maxIterations = 500; - int noChanges = 1; - int noFailures = 0; + // the list containing the children for which the constraints are already + // set correctly wxWindowList succeeded; - while ((noChanges > 0) && (noIterations < maxIterations)) + + // the max number of iterations we loop before concluding that we can't set + // the constraints + static const int maxIterations = 500; + + for ( int noIterations = 0; noIterations < maxIterations; noIterations++ ) { - noChanges = 0; - noFailures = 0; - wxWindowList::Node *node = GetChildren().GetFirst(); - while (node) + int noChanges = 0; + + // loop over all children setting their constraints + for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); + node; + node = node->GetNext() ) { wxWindow *child = node->GetData(); - if ( !child->IsTopLevel() ) + if ( child->IsTopLevel() ) { - wxLayoutConstraints *constr = child->GetConstraints(); - if ( constr ) - { - if ( !succeeded.Find(child) ) - { - int tempNoChanges = 0; - bool success = ( (phase == 1) ? child->LayoutPhase1(&tempNoChanges) : child->LayoutPhase2(&tempNoChanges) ) ; - noChanges += tempNoChanges; - if ( success ) - { - succeeded.Append(child); - } - } - } + // top level children are not inside our client area + continue; + } + + if ( !child->GetConstraints() || succeeded.Find(child) ) + { + // this one is either already ok or nothing we can do about it + continue; + } + + int tempNoChanges = 0; + bool success = phase == 1 ? child->LayoutPhase1(&tempNoChanges) + : child->LayoutPhase2(&tempNoChanges); + noChanges += tempNoChanges; + + if ( success ) + { + succeeded.Append(child); } - node = node->GetNext(); } - noIterations++; + if ( !noChanges ) + { + // constraints are set + break; + } } return TRUE; @@ -1313,7 +1611,7 @@ void wxWindowBase::ResetConstraints() constr->centreY.SetDone(FALSE); } - wxWindowList::Node *node = GetChildren().GetFirst(); + wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); while (node) { wxWindow *win = node->GetData(); @@ -1355,7 +1653,7 @@ void wxWindowBase::SetConstraintSizes(bool recurse) if ( recurse ) { - wxWindowList::Node *node = GetChildren().GetFirst(); + wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); while (node) { wxWindow *win = node->GetData(); @@ -1471,36 +1769,46 @@ void wxWindowBase::AdjustForParentClientOrigin(int& x, int& y, int sizeFlags) co // do Update UI processing for child controls // ---------------------------------------------------------------------------- -// TODO: should this be implemented for the child window rather -// than the parent? Then you can override it e.g. for wxCheckBox -// to do the Right Thing rather than having to assume a fixed number -// of control classes. -void wxWindowBase::UpdateWindowUI() +void wxWindowBase::UpdateWindowUI(long flags) { -#if wxUSE_CONTROLS wxUpdateUIEvent event(GetId()); event.m_eventObject = this; if ( GetEventHandler()->ProcessEvent(event) ) { - if ( event.GetSetEnabled() ) - Enable(event.GetEnabled()); + DoUpdateWindowUI(event); + } - if ( event.GetSetText() ) + if (flags & wxUPDATE_UI_RECURSE) + { + wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); + while (node) { - wxControl *control = wxDynamicCastThis(wxControl); - if ( control ) - { -#if wxUSE_TEXTCTRL - wxTextCtrl *text = wxDynamicCast(control, wxTextCtrl); - if ( text ) - text->SetValue(event.GetText()); - else -#endif // wxUSE_TEXTCTRL - control->SetLabel(event.GetText()); - } + wxWindow* child = (wxWindow*) node->GetData(); + child->UpdateWindowUI(flags); + node = node->GetNext(); } + } +} +// do the window-specific processing after processing the update event +// TODO: take specific knowledge out of this function and +// put in each control's base class. Unfortunately we don't +// yet have base implementation files for wxCheckBox and wxRadioButton. +void wxWindowBase::DoUpdateWindowUI(wxUpdateUIEvent& event) +{ + if ( event.GetSetEnabled() ) + Enable(event.GetEnabled()); + +#if wxUSE_CONTROLS + if ( event.GetSetText() ) + { + wxControl *control = wxDynamicCastThis(wxControl); + if ( control ) + { + if ( event.GetText() != control->GetLabel() ) + control->SetLabel(event.GetText()); + } #if wxUSE_CHECKBOX wxCheckBox *checkbox = wxDynamicCastThis(wxCheckBox); if ( checkbox ) @@ -1518,8 +1826,22 @@ void wxWindowBase::UpdateWindowUI() radiobtn->SetValue(event.GetChecked()); } #endif // wxUSE_RADIOBTN + } +#endif +} + +// call internal idle recursively +void wxWindowBase::ProcessInternalIdle() +{ + OnInternalIdle(); + + wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); + while (node) + { + wxWindow *child = node->GetData(); + child->ProcessInternalIdle(); + node = node->GetNext(); } -#endif // wxUSE_CONTROLS } // ---------------------------------------------------------------------------- @@ -1559,7 +1881,7 @@ wxPoint wxWindowBase::ConvertDialogToPixels(const wxPoint& pt) // propagate the colour change event to the subwindows void wxWindowBase::OnSysColourChanged(wxSysColourChangedEvent& event) { - wxWindowList::Node *node = GetChildren().GetFirst(); + wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); while ( node ) { // Only propagate to non-top-level windows @@ -1575,10 +1897,15 @@ void wxWindowBase::OnSysColourChanged(wxSysColourChangedEvent& event) } } -// the default action is to populate dialog with data when it's created +// the default action is to populate dialog with data when it's created, +// and nudge the UI into displaying itself correctly in case +// we've turned the wxUpdateUIEvents frequency down low. void wxWindowBase::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) ) { TransferDataToWindow(); + + // Update the UI at this point + UpdateWindowUI(wxUPDATE_UI_RECURSE); } // process Ctrl-Alt-mclick @@ -1596,27 +1923,27 @@ void wxWindowBase::OnMiddleClick( wxMouseEvent& event ) switch ( wxGetOsVersion() ) { - case wxMOTIF_X: port = _T("Motif"); break; + case wxMOTIF_X: port += _T("Motif"); break; case wxMAC: - case wxMAC_DARWIN: port = _T("Mac"); break; - case wxBEOS: port = _T("BeOS"); break; + case wxMAC_DARWIN: port += _T("Mac"); break; + case wxBEOS: port += _T("BeOS"); break; case wxGTK: case wxGTK_WIN32: case wxGTK_OS2: - case wxGTK_BEOS: port = _T("GTK"); break; + case wxGTK_BEOS: port += _T("GTK"); break; case wxWINDOWS: case wxPENWINDOWS: case wxWINDOWS_NT: case wxWIN32S: case wxWIN95: - case wxWIN386: port = _T("MS Windows"); break; + case wxWIN386: port += _T("MS Windows"); break; case wxMGL_UNIX: case wxMGL_X: case wxMGL_WIN32: - case wxMGL_OS2: port = _T("MGL"); break; + case wxMGL_OS2: port += _T("MGL"); break; case wxWINDOWS_OS2: - case wxOS2_PM: port = _T("OS/2"); break; - default: port = _T("unknown"); break; + case wxOS2_PM: port += _T("OS/2"); break; + default: port += _T("unknown"); break; } wxMessageBox(wxString::Format( @@ -1646,6 +1973,37 @@ void wxWindowBase::OnMiddleClick( wxMouseEvent& event ) } } +// ---------------------------------------------------------------------------- +// accessibility +// ---------------------------------------------------------------------------- + +#if wxUSE_ACCESSIBILITY +void wxWindowBase::SetAccessible(wxAccessible* accessible) +{ + if (m_accessible && (accessible != m_accessible)) + delete m_accessible; + m_accessible = accessible; + if (m_accessible) + m_accessible->SetWindow((wxWindow*) this); +} + +// Returns the accessible object, creating if necessary. +wxAccessible* wxWindowBase::GetOrCreateAccessible() +{ + if (!m_accessible) + m_accessible = CreateAccessible(); + return m_accessible; +} + +// Override to create a specific accessible object. +wxAccessible* wxWindowBase::CreateAccessible() +{ + return new wxWindowAccessible((wxWindow*) this); +} + +#endif + +#if !wxUSE_STL // ---------------------------------------------------------------------------- // list classes implementation // ---------------------------------------------------------------------------- @@ -1654,14 +2012,15 @@ void wxWindowListNode::DeleteData() { delete (wxWindow *)GetData(); } +#endif // ---------------------------------------------------------------------------- // borders // ---------------------------------------------------------------------------- -wxBorder wxWindowBase::GetBorder() const +wxBorder wxWindowBase::GetBorder(long flags) const { - wxBorder border = (wxBorder)(m_windowStyle & wxBORDER_MASK); + wxBorder border = (wxBorder)(flags & wxBORDER_MASK); if ( border == wxBORDER_DEFAULT ) { border = GetDefaultBorder(); @@ -1707,13 +2066,13 @@ struct WXDLLEXPORT wxWindowNext void wxWindowBase::CaptureMouse() { - wxLogTrace(_T("mousecapture"), _T("CaptureMouse(0x%08x)"), this); + wxLogTrace(_T("mousecapture"), _T("CaptureMouse(%p)"), this); wxWindow *winOld = GetCapture(); if ( winOld ) { ((wxWindowBase*) winOld)->DoReleaseMouse(); - + // save it on stack wxWindowNext *item = new wxWindowNext; item->win = winOld; @@ -1727,16 +2086,16 @@ void wxWindowBase::CaptureMouse() void wxWindowBase::ReleaseMouse() { - wxLogTrace(_T("mousecapture"), _T("ReleaseMouse(0x%08x)"), this); + wxLogTrace(_T("mousecapture"), _T("ReleaseMouse(%p)"), this); - wxASSERT_MSG( GetCapture() == this, wxT("attempt to release mouse, but this window hasn't captured it") ) + wxASSERT_MSG( GetCapture() == this, wxT("attempt to release mouse, but this window hasn't captured it") ); DoReleaseMouse(); if ( ms_winCaptureNext ) { ((wxWindowBase*)ms_winCaptureNext->win)->DoCaptureMouse(); - + wxWindowNext *item = ms_winCaptureNext; ms_winCaptureNext = item->next; delete item; @@ -1744,7 +2103,506 @@ void wxWindowBase::ReleaseMouse() //else: stack is empty, no previous capture wxLogTrace(_T("mousecapture"), - _T("After ReleaseMouse() mouse is captured by 0x%08x"), + _T("After ReleaseMouse() mouse is captured by %p"), GetCapture()); } +#if wxUSE_HOTKEY + +bool +wxWindowBase::RegisterHotKey(int WXUNUSED(hotkeyId), + int WXUNUSED(modifiers), + int WXUNUSED(keycode)) +{ + // not implemented + return false; +} + +bool wxWindowBase::UnregisterHotKey(int WXUNUSED(hotkeyId)) +{ + // not implemented + return false; +} + +#endif // wxUSE_HOTKEY + +void wxWindowBase::SendDestroyEvent() +{ + wxWindowDestroyEvent event; + event.SetEventObject(this); + event.SetId(GetId()); + GetEventHandler()->ProcessEvent(event); +} + +// ---------------------------------------------------------------------------- +// event processing +// ---------------------------------------------------------------------------- + +#if wxUSE_VALIDATORS + +bool wxWindowBase::TryValidator(wxEvent& event) +{ + // Can only use the validator of the window which + // is receiving the event + if ( event.GetEventObject() == this ) + { + wxValidator *validator = GetValidator(); + if ( validator && validator->ProcessEvent(event) ) + { + return TRUE; + } + } + + return FALSE; +} + +#endif // wxUSE_VALIDATORS + +bool wxWindowBase::TryParent(wxEvent& event) +{ + // Carry on up the parent-child hierarchy, but only if event is a command + // event: it wouldn't make sense for a parent to receive a child's size + // event, for example + if ( event.IsCommandEvent() ) + { + // honour the requests to stop propagation at this window: this is + // used by the dialogs, for example, to prevent processing the events + // from the dialog controls in the parent frame which rarely, if ever, + // makes sense + if ( !(GetExtraStyle() & wxWS_EX_BLOCK_EVENTS) ) + { + wxWindow *parent = GetParent(); + if ( parent && !parent->IsBeingDeleted() ) + return parent->GetEventHandler()->ProcessEvent(event); + } + } + + return wxEvtHandler::TryParent(event); +} + +// ---------------------------------------------------------------------------- +// global functions +// ---------------------------------------------------------------------------- + +wxWindow* wxGetTopLevelParent(wxWindow *win) +{ + while ( win && !win->IsTopLevel() ) + win = win->GetParent(); + + return win; +} + +#if wxUSE_ACCESSIBILITY +// ---------------------------------------------------------------------------- +// accessible object for windows +// ---------------------------------------------------------------------------- + +// Can return either a child object, or an integer +// representing the child element, starting from 1. +wxAccStatus wxWindowAccessible::HitTest(const wxPoint& pt, int* childId, wxAccessible** childObject) +{ + wxASSERT( GetWindow() != NULL ); + if (!GetWindow()) + return wxACC_FAIL; + + return wxACC_NOT_IMPLEMENTED; +} + +// Returns the rectangle for this object (id = 0) or a child element (id > 0). +wxAccStatus wxWindowAccessible::GetLocation(wxRect& rect, int elementId) +{ + wxASSERT( GetWindow() != NULL ); + if (!GetWindow()) + return wxACC_FAIL; + + wxWindow* win = NULL; + if (elementId == 0) + { + win = GetWindow(); + } + else + { + if (elementId <= (int) GetWindow()->GetChildren().GetCount()) + { + win = (wxWindow*) GetWindow()->GetChildren().Nth(elementId-1)->GetData(); + } + else + return wxACC_FAIL; + } + if (win) + { + rect = win->GetRect(); + if (win->GetParent() && !win->IsKindOf(CLASSINFO(wxTopLevelWindow))) + rect.SetPosition(win->GetParent()->ClientToScreen(rect.GetPosition())); + return wxACC_OK; + } + + return wxACC_NOT_IMPLEMENTED; +} + +// Navigates from fromId to toId/toObject. +wxAccStatus wxWindowAccessible::Navigate(wxNavDir navDir, int fromId, + int* toId, wxAccessible** toObject) +{ + wxASSERT( GetWindow() != NULL ); + if (!GetWindow()) + return wxACC_FAIL; + + switch (navDir) + { + case wxNAVDIR_FIRSTCHILD: + { + if (GetWindow()->GetChildren().GetCount() == 0) + return wxACC_FALSE; + wxWindow* childWindow = (wxWindow*) GetWindow()->GetChildren().GetFirst()->GetData(); + *toObject = childWindow->GetOrCreateAccessible(); + + return wxACC_OK; + } + case wxNAVDIR_LASTCHILD: + { + if (GetWindow()->GetChildren().GetCount() == 0) + return wxACC_FALSE; + wxWindow* childWindow = (wxWindow*) GetWindow()->GetChildren().GetLast()->GetData(); + *toObject = childWindow->GetOrCreateAccessible(); + + return wxACC_OK; + } + case wxNAVDIR_RIGHT: + case wxNAVDIR_DOWN: + case wxNAVDIR_NEXT: + { + wxWindowList::compatibility_iterator node = NULL; + if (fromId == 0) + { + // Can't navigate to sibling of this window + // if we're a top-level window. + if (!GetWindow()->GetParent()) + return wxACC_NOT_IMPLEMENTED; + + node = GetWindow()->GetParent()->GetChildren().Find(GetWindow()); + } + else + { + if (fromId <= (int) GetWindow()->GetChildren().GetCount()) + node = GetWindow()->GetChildren().Nth(fromId-1); + } + + if (node && node->GetNext()) + { + wxWindow* nextWindow = (wxWindow*) node->GetNext()->Data(); + *toObject = nextWindow->GetOrCreateAccessible(); + return wxACC_OK; + } + else + return wxACC_FALSE; + } + case wxNAVDIR_LEFT: + case wxNAVDIR_UP: + case wxNAVDIR_PREVIOUS: + { + wxWindowList::compatibility_iterator node = NULL; + if (fromId == 0) + { + // Can't navigate to sibling of this window + // if we're a top-level window. + if (!GetWindow()->GetParent()) + return wxACC_NOT_IMPLEMENTED; + + node = GetWindow()->GetParent()->GetChildren().Find(GetWindow()); + } + else + { + if (fromId <= (int) GetWindow()->GetChildren().GetCount()) + node = GetWindow()->GetChildren().Nth(fromId-1); + } + + if (node && node->GetPrevious()) + { + wxWindow* previousWindow = (wxWindow*) node->GetPrevious()->Data(); + *toObject = previousWindow->GetOrCreateAccessible(); + return wxACC_OK; + } + else + return wxACC_FALSE; + } + } + + return wxACC_NOT_IMPLEMENTED; +} + +// Gets the name of the specified object. +wxAccStatus wxWindowAccessible::GetName(int childId, wxString* name) +{ + wxASSERT( GetWindow() != NULL ); + if (!GetWindow()) + return wxACC_FAIL; + + wxString title; + + // If a child, leave wxWindows to call the function on the actual + // child object. + if (childId > 0) + return wxACC_NOT_IMPLEMENTED; + + // This will eventually be replaced by specialised + // accessible classes, one for each kind of wxWindows + // control or window. + if (GetWindow()->IsKindOf(CLASSINFO(wxButton))) + title = ((wxButton*) GetWindow())->GetLabel(); + else + title = GetWindow()->GetName(); + + if (!title.IsEmpty()) + { + *name = title; + return wxACC_OK; + } + else + return wxACC_NOT_IMPLEMENTED; +} + +// Gets the number of children. +wxAccStatus wxWindowAccessible::GetChildCount(int* childId) +{ + wxASSERT( GetWindow() != NULL ); + if (!GetWindow()) + return wxACC_FAIL; + + *childId = (int) GetWindow()->GetChildren().GetCount(); + return wxACC_OK; +} + +// Gets the specified child (starting from 1). +// If *child is NULL and return value is wxACC_OK, +// this means that the child is a simple element and +// not an accessible object. +wxAccStatus wxWindowAccessible::GetChild(int childId, wxAccessible** child) +{ + wxASSERT( GetWindow() != NULL ); + if (!GetWindow()) + return wxACC_FAIL; + + if (childId == 0) + { + *child = this; + return wxACC_OK; + } + + if (childId > (int) GetWindow()->GetChildren().GetCount()) + return wxACC_FAIL; + + wxWindow* childWindow = (wxWindow*) GetWindow()->GetChildren().Nth(childId-1)->GetData(); + *child = childWindow->GetOrCreateAccessible(); + if (*child) + return wxACC_OK; + else + return wxACC_FAIL; +} + +// Gets the parent, or NULL. +wxAccStatus wxWindowAccessible::GetParent(wxAccessible** parent) +{ + wxASSERT( GetWindow() != NULL ); + if (!GetWindow()) + return wxACC_FAIL; + + wxWindow* parentWindow = GetWindow()->GetParent(); + if (!parentWindow) + { + *parent = NULL; + return wxACC_OK; + } + else + { + *parent = parentWindow->GetOrCreateAccessible(); + if (*parent) + return wxACC_OK; + else + return wxACC_FAIL; + } +} + +// Performs the default action. childId is 0 (the action for this object) +// or > 0 (the action for a child). +// Return wxACC_NOT_SUPPORTED if there is no default action for this +// window (e.g. an edit control). +wxAccStatus wxWindowAccessible::DoDefaultAction(int childId) +{ + wxASSERT( GetWindow() != NULL ); + if (!GetWindow()) + return wxACC_FAIL; + + return wxACC_NOT_IMPLEMENTED; +} + +// Gets the default action for this object (0) or > 0 (the action for a child). +// Return wxACC_OK even if there is no action. actionName is the action, or the empty +// string if there is no action. +// The retrieved string describes the action that is performed on an object, +// not what the object does as a result. For example, a toolbar button that prints +// a document has a default action of "Press" rather than "Prints the current document." +wxAccStatus wxWindowAccessible::GetDefaultAction(int childId, wxString* actionName) +{ + wxASSERT( GetWindow() != NULL ); + if (!GetWindow()) + return wxACC_FAIL; + + return wxACC_NOT_IMPLEMENTED; +} + +// Returns the description for this object or a child. +wxAccStatus wxWindowAccessible::GetDescription(int childId, wxString* description) +{ + wxASSERT( GetWindow() != NULL ); + if (!GetWindow()) + return wxACC_FAIL; + + wxString ht(GetWindow()->GetHelpText()); + if (!ht.IsEmpty()) + { + *description = ht; + return wxACC_OK; + } + return wxACC_NOT_IMPLEMENTED; +} + +// Returns help text for this object or a child, similar to tooltip text. +wxAccStatus wxWindowAccessible::GetHelpText(int childId, wxString* helpText) +{ + wxASSERT( GetWindow() != NULL ); + if (!GetWindow()) + return wxACC_FAIL; + + wxString ht(GetWindow()->GetHelpText()); + if (!ht.IsEmpty()) + { + *helpText = ht; + return wxACC_OK; + } + return wxACC_NOT_IMPLEMENTED; +} + +// Returns the keyboard shortcut for this object or child. +// Return e.g. ALT+K +wxAccStatus wxWindowAccessible::GetKeyboardShortcut(int childId, wxString* shortcut) +{ + wxASSERT( GetWindow() != NULL ); + if (!GetWindow()) + return wxACC_FAIL; + + return wxACC_NOT_IMPLEMENTED; +} + +// Returns a role constant. +wxAccStatus wxWindowAccessible::GetRole(int childId, wxAccRole* role) +{ + wxASSERT( GetWindow() != NULL ); + if (!GetWindow()) + return wxACC_FAIL; + + // If a child, leave wxWindows to call the function on the actual + // child object. + if (childId > 0) + return wxACC_NOT_IMPLEMENTED; + + if (GetWindow()->IsKindOf(CLASSINFO(wxControl))) + return wxACC_NOT_IMPLEMENTED; +#if wxUSE_STATUSBAR + if (GetWindow()->IsKindOf(CLASSINFO(wxStatusBar))) + return wxACC_NOT_IMPLEMENTED; +#endif +#if wxUSE_TOOLBAR + if (GetWindow()->IsKindOf(CLASSINFO(wxToolBar))) + return wxACC_NOT_IMPLEMENTED; +#endif + + //*role = wxROLE_SYSTEM_CLIENT; + *role = wxROLE_SYSTEM_CLIENT; + return wxACC_OK; + + return wxACC_NOT_IMPLEMENTED; +} + +// Returns a state constant. +wxAccStatus wxWindowAccessible::GetState(int childId, long* state) +{ + wxASSERT( GetWindow() != NULL ); + if (!GetWindow()) + return wxACC_FAIL; + + // If a child, leave wxWindows to call the function on the actual + // child object. + if (childId > 0) + return wxACC_NOT_IMPLEMENTED; + + if (GetWindow()->IsKindOf(CLASSINFO(wxControl))) + return wxACC_NOT_IMPLEMENTED; + +#if wxUSE_STATUSBAR + if (GetWindow()->IsKindOf(CLASSINFO(wxStatusBar))) + return wxACC_NOT_IMPLEMENTED; +#endif +#if wxUSE_TOOLBAR + if (GetWindow()->IsKindOf(CLASSINFO(wxToolBar))) + return wxACC_NOT_IMPLEMENTED; +#endif + + *state = 0; + return wxACC_OK; + + return wxACC_NOT_IMPLEMENTED; +} + +// Returns a localized string representing the value for the object +// or child. +wxAccStatus wxWindowAccessible::GetValue(int childId, wxString* strValue) +{ + wxASSERT( GetWindow() != NULL ); + if (!GetWindow()) + return wxACC_FAIL; + + return wxACC_NOT_IMPLEMENTED; +} + +// Selects the object or child. +wxAccStatus wxWindowAccessible::Select(int childId, wxAccSelectionFlags selectFlags) +{ + wxASSERT( GetWindow() != NULL ); + if (!GetWindow()) + return wxACC_FAIL; + + return wxACC_NOT_IMPLEMENTED; +} + +// Gets the window with the keyboard focus. +// If childId is 0 and child is NULL, no object in +// this subhierarchy has the focus. +// If this object has the focus, child should be 'this'. +wxAccStatus wxWindowAccessible::GetFocus(int* childId, wxAccessible** child) +{ + wxASSERT( GetWindow() != NULL ); + if (!GetWindow()) + return wxACC_FAIL; + + return wxACC_NOT_IMPLEMENTED; +} + +// Gets a variant representing the selected children +// of this object. +// Acceptable values: +// - a null variant (IsNull() returns TRUE) +// - a list variant (GetType() == wxT("list") +// - an integer representing the selected child element, +// or 0 if this object is selected (GetType() == wxT("long") +// - a "void*" pointer to a wxAccessible child object +wxAccStatus wxWindowAccessible::GetSelections(wxVariant* selections) +{ + wxASSERT( GetWindow() != NULL ); + if (!GetWindow()) + return wxACC_FAIL; + + return wxACC_NOT_IMPLEMENTED; +} + +#endif // wxUSE_ACCESSIBILITY