]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/wincmn.cpp
Compilation fix.
[wxWidgets.git] / src / common / wincmn.cpp
index aa805541dab4eed34953bd7f7e5afa5a6d20c4d7..810d518d9dc2a58a9aef38026738970ef7c2a9ca 100644 (file)
@@ -6,7 +6,7 @@
 // Created:     13/07/98
 // RCS-ID:      $Id$
 // Copyright:   (c) wxWindows team
-// Licence:     wxWindows license
+// Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
 // ============================================================================
@@ -44,6 +44,7 @@
     #include "wx/dialog.h"
     #include "wx/msgdlg.h"
     #include "wx/statusbr.h"
+    #include "wx/dcclient.h"
 #endif //WX_PRECOMP
 
 #if wxUSE_CONSTRAINTS
     #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
@@ -144,15 +149,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;
@@ -179,6 +182,10 @@ void wxWindowBase::InitBase()
     m_hasCustomPalette = FALSE;
 #endif // wxUSE_PALETTE
 
+#if wxUSE_ACCESSIBILITY
+    m_accessible = NULL;
+#endif
+
     m_virtualSize = wxDefaultSize;
 
     m_minVirtualWidth =
@@ -199,11 +206,6 @@ 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
@@ -215,8 +217,14 @@ bool wxWindowBase::CreateBase(wxWindowBase *parent,
                   _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);
@@ -231,7 +239,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;
@@ -301,6 +309,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 )
     {
@@ -601,6 +614,12 @@ 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;
@@ -634,12 +653,8 @@ wxSize wxWindowBase::DoGetVirtualSize() const
 {
     wxSize  s( GetClientSize() );
 
-    if( m_virtualSize.GetWidth() != -1 )
-        s.SetWidth( m_virtualSize.GetWidth() );
-    if( m_virtualSize.GetHeight() != -1 )
-        s.SetHeight( m_virtualSize.GetHeight() );
-
-    return s;
+    return wxSize( wxMax( m_virtualSize.GetWidth(), s.GetWidth() ),
+                   wxMax( m_virtualSize.GetHeight(), s.GetHeight() ) );
 }
 
 // ----------------------------------------------------------------------------
@@ -1936,6 +1951,36 @@ 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
+
 // ----------------------------------------------------------------------------
 // list classes implementation
 // ----------------------------------------------------------------------------
@@ -1949,9 +1994,9 @@ void wxWindowListNode::DeleteData()
 // 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();
@@ -2038,6 +2083,61 @@ void wxWindowBase::ReleaseMouse()
                GetCapture());
 }
 
+
+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
 // ----------------------------------------------------------------------------
@@ -2050,4 +2150,417 @@ wxWindow* wxGetTopLevelParent(wxWindow *win)
     return win;
 }
 
-// vi:sts=4:sw=4:et
+#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::Node *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 = (wxWindowList::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::Node *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 = (wxWindowList::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