]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/treebkg.cpp
Fix crash on wxDataViewCtrl creation after r73565.
[wxWidgets.git] / src / generic / treebkg.cpp
index a5d5c88358f526fbc64da7265563c7aeb0e48cbb..140829ad6a26e650cf9e0ccda4b3052c40e1efcd 100644 (file)
 #if wxUSE_TREEBOOK
 
 #include "wx/treebook.h"
+
+#ifndef WX_PRECOMP
+    #include "wx/settings.h"
+#endif
+
 #include "wx/imaglist.h"
-#include "wx/settings.h"
 
 // ----------------------------------------------------------------------------
 // various wxWidgets macros
 // ----------------------------------------------------------------------------
 
 IMPLEMENT_DYNAMIC_CLASS(wxTreebook, wxBookCtrlBase)
-IMPLEMENT_DYNAMIC_CLASS(wxTreebookEvent, wxNotifyEvent)
 
-const wxEventType wxEVT_COMMAND_TREEBOOK_PAGE_CHANGING = wxNewEventType();
-const wxEventType wxEVT_COMMAND_TREEBOOK_PAGE_CHANGED = wxNewEventType();
-const wxEventType wxEVT_COMMAND_TREEBOOK_NODE_COLLAPSED = wxNewEventType();
-const wxEventType wxEVT_COMMAND_TREEBOOK_NODE_EXPANDED = wxNewEventType();
-const int wxID_TREEBOOKTREEVIEW = wxNewId();
+wxDEFINE_EVENT( wxEVT_COMMAND_TREEBOOK_PAGE_CHANGING,  wxBookCtrlEvent );
+wxDEFINE_EVENT( wxEVT_COMMAND_TREEBOOK_PAGE_CHANGED,   wxBookCtrlEvent );
+wxDEFINE_EVENT( wxEVT_COMMAND_TREEBOOK_NODE_COLLAPSED, wxBookCtrlEvent );
+wxDEFINE_EVENT( wxEVT_COMMAND_TREEBOOK_NODE_EXPANDED,  wxBookCtrlEvent );
 
 BEGIN_EVENT_TABLE(wxTreebook, wxBookCtrlBase)
-    EVT_TREE_SEL_CHANGED   (wxID_TREEBOOKTREEVIEW, wxTreebook::OnTreeSelectionChange)
-    EVT_TREE_ITEM_EXPANDED (wxID_TREEBOOKTREEVIEW, wxTreebook::OnTreeNodeExpandedCollapsed)
-    EVT_TREE_ITEM_COLLAPSED(wxID_TREEBOOKTREEVIEW, wxTreebook::OnTreeNodeExpandedCollapsed)
+    EVT_TREE_SEL_CHANGED   (wxID_ANY, wxTreebook::OnTreeSelectionChange)
+    EVT_TREE_ITEM_EXPANDED (wxID_ANY, wxTreebook::OnTreeNodeExpandedCollapsed)
+    EVT_TREE_ITEM_COLLAPSED(wxID_ANY, wxTreebook::OnTreeNodeExpandedCollapsed)
 END_EVENT_TABLE()
 
 // ============================================================================
@@ -83,6 +85,7 @@ wxTreebook::Create(wxWindow *parent,
     {
         style |= wxBK_LEFT;
     }
+    style |= wxTAB_TRAVERSAL;
 
     // no border for this control, it doesn't look nice together with the tree
     style &= ~wxBORDER_MASK;
@@ -95,14 +98,15 @@ wxTreebook::Create(wxWindow *parent,
     m_bookctrl = new wxTreeCtrl
                  (
                     this,
-                    wxID_TREEBOOKTREEVIEW,
+                    wxID_ANY,
                     wxDefaultPosition,
                     wxDefaultSize,
-                    wxBORDER_SIMPLE |
+                    wxBORDER_THEME |
                     wxTR_DEFAULT_STYLE |
                     wxTR_HIDE_ROOT |
                     wxTR_SINGLE
                  );
+    GetTreeCtrl()->SetQuickBestSize(false); // do full size calculation
     GetTreeCtrl()->AddRoot(wxEmptyString); // label doesn't matter, it's hidden
 
 #ifdef __WXMSW__
@@ -201,8 +205,6 @@ bool wxTreebook::DoInsertPage(size_t pagePos,
 
     DoUpdateSelection(bSelect, pagePos);
 
-    m_bookctrl->InvalidateBestSize();
-
     return true;
 }
 
@@ -215,7 +217,7 @@ bool wxTreebook::DoAddSubPage(wxWindow *page, const wxString& text, bool bSelect
     wxTreeItemId lastNodeId = tree->GetLastChild(rootId);
 
     wxCHECK_MSG( lastNodeId.IsOk(), false,
-                        _T("Can't insert sub page when there are no pages") );
+                        wxT("Can't insert sub page when there are no pages") );
 
     // now calculate its position (should we save/update it too?)
     size_t newPos = tree->GetCount() -
@@ -256,8 +258,6 @@ bool wxTreebook::DoInsertSubPage(size_t pagePos,
 
     DoUpdateSelection(bSelect, newPos);
 
-    m_bookctrl->InvalidateBestSize();
-
     return true;
 }
 
@@ -306,7 +306,6 @@ wxTreebookPage *wxTreebook::DoRemovePage(size_t pagePos)
 
     tree->DeleteChildren( pageId );
     tree->Delete( pageId );
-    tree->InvalidateBestSize();
 
     return oldPage;
 }
@@ -419,7 +418,9 @@ void wxTreebook::DoInternalRemovePageRange(size_t pagePos, size_t subCount)
             // actually shown page (the first (sub)child with page != NULL) is
             // already deleted
             m_actualSelection = m_selection;
-            DoSetSelection(m_selection);
+
+            // send event as documented
+            DoSetSelection(m_selection, SetSelection_SendEvent);
         }
         //else: nothing to do -- selection is before the deleted node
     }
@@ -555,49 +556,32 @@ bool wxTreebook::SetPageImage(size_t n, int imageId)
     return true;
 }
 
-wxSize wxTreebook::CalcSizeFromPage(const wxSize& sizePage) const
-{
-    const wxSize sizeTree = GetControllerSize();
-
-    wxSize size = sizePage;
-    size.x += sizeTree.x;
-
-    return size;
-}
-
-int wxTreebook::GetSelection() const
-{
-   return m_selection;
-}
-
-int wxTreebook::SetSelection(size_t pagePos)
-{
-   if ( (size_t)m_selection != pagePos )
-       return DoSetSelection(pagePos);
-
-   return m_selection;
-}
-
-int wxTreebook::DoSetSelection(size_t pagePos)
+int wxTreebook::DoSetSelection(size_t pagePos, int flags)
 {
     wxCHECK_MSG( IS_VALID_PAGE(pagePos), wxNOT_FOUND,
-                 wxT("invalid page index in wxListbook::SetSelection()") );
+                 wxT("invalid page index in wxListbook::DoSetSelection()") );
     wxASSERT_MSG( GetPageCount() == DoInternalGetPageCount(),
                   wxT("wxTreebook logic error: m_treeIds and m_pages not in sync!"));
 
+    wxBookCtrlEvent event(wxEVT_COMMAND_TREEBOOK_PAGE_CHANGING, m_windowId);
     const int oldSel = m_selection;
     wxTreeCtrl *tree = GetTreeCtrl();
+    bool allowed = false;
 
-    wxTreebookEvent event(wxEVT_COMMAND_TREEBOOK_PAGE_CHANGING, m_windowId);
-    event.SetEventObject(this);
-    event.SetSelection(pagePos);
-    event.SetOldSelection(m_selection);
+    if (flags & SetSelection_SendEvent)
+    {
+        event.SetEventObject(this);
+        event.SetSelection(pagePos);
+        event.SetOldSelection(m_selection);
+
+        // don't send the event if the old and new pages are the same; do send it
+        // otherwise and be prepared for it to be vetoed
+        allowed = (int)pagePos == m_selection ||
+                  !GetEventHandler()->ProcessEvent(event) ||
+                  event.IsAllowed();
+    }
 
-    // don't send the event if the old and new pages are the same; do send it
-    // otherwise and be prepared for it to be vetoed
-    if ( (int)pagePos == m_selection ||
-            !GetEventHandler()->ProcessEvent(event) ||
-                event.IsAllowed() )
+    if ( !(flags & SetSelection_SendEvent) || allowed )
     {
         // hide the previously shown page
         wxTreebookPage * const oldPage = DoGetCurrentPage();
@@ -612,41 +596,56 @@ int wxTreebook::DoSetSelection(size_t pagePos)
             // find the next page suitable to be shown: the first (grand)child
             // of this one with a non-NULL associated page
             wxTreeItemId childId = m_treeIds[pagePos];
-            m_actualSelection = pagePos;
+            int actualPagePos = pagePos;
             while ( !page && childId.IsOk() )
             {
                 wxTreeItemIdValue cookie;
                 childId = tree->GetFirstChild( childId, cookie );
                 if ( childId.IsOk() )
                 {
-                    page = wxBookCtrlBase::GetPage(++m_actualSelection);
+                    page = wxBookCtrlBase::GetPage(++actualPagePos);
                 }
             }
 
-            wxASSERT_MSG( page, wxT("no page to show found!") );
+            m_actualSelection = page ? actualPagePos : m_selection;
         }
 
         if ( page )
-        {
-            page->SetSize(GetPageRect());
             page->Show();
-        }
 
         tree->SelectItem(DoInternalGetPage(pagePos));
 
-        // notify about the (now completed) page change
-        event.SetEventType(wxEVT_COMMAND_TREEBOOK_PAGE_CHANGED);
-        (void)GetEventHandler()->ProcessEvent(event);
+        if (flags & SetSelection_SendEvent)
+        {
+            // notify about the (now completed) page change
+            event.SetEventType(wxEVT_COMMAND_TREEBOOK_PAGE_CHANGED);
+            (void)GetEventHandler()->ProcessEvent(event);
+        }
     }
-    else // page change vetoed
+    else if ( (flags & SetSelection_SendEvent) && !allowed) // page change vetoed
     {
         // tree selection might have already had changed
-        tree->SelectItem(DoInternalGetPage(oldSel));
+        if ( oldSel != wxNOT_FOUND )
+            tree->SelectItem(DoInternalGetPage(oldSel));
     }
 
     return oldSel;
 }
 
+wxTreebookPage *wxTreebook::DoGetCurrentPage() const
+{
+    if ( m_selection == wxNOT_FOUND )
+        return NULL;
+
+    wxTreebookPage *page = wxBookCtrlBase::GetPage(m_selection);
+    if ( !page && m_actualSelection != wxNOT_FOUND )
+    {
+        page = wxBookCtrlBase::GetPage(m_actualSelection);
+    }
+
+    return page;
+}
+
 void wxTreebook::SetImageList(wxImageList *imageList)
 {
     wxBookCtrlBase::SetImageList(imageList);
@@ -665,6 +664,12 @@ void wxTreebook::AssignImageList(wxImageList *imageList)
 
 void wxTreebook::OnTreeSelectionChange(wxTreeEvent& event)
 {
+    if ( event.GetEventObject() != m_bookctrl )
+    {
+        event.Skip();
+        return;
+    }
+
     wxTreeItemId newId = event.GetItem();
 
     if ( (m_selection == wxNOT_FOUND &&
@@ -684,13 +689,19 @@ void wxTreebook::OnTreeSelectionChange(wxTreeEvent& event)
 
 void wxTreebook::OnTreeNodeExpandedCollapsed(wxTreeEvent & event)
 {
+    if ( event.GetEventObject() != m_bookctrl )
+    {
+        event.Skip();
+        return;
+    }
+
     wxTreeItemId nodeId = event.GetItem();
     if ( !nodeId.IsOk() || nodeId == GetTreeCtrl()->GetRootItem() )
         return;
     int pagePos = DoInternalFindPageById(nodeId);
     wxCHECK_RET( pagePos != wxNOT_FOUND, wxT("Internal problem in wxTreebook!..") );
 
-    wxTreebookEvent ev(GetTreeCtrl()->IsExpanded(nodeId)
+    wxBookCtrlEvent ev(GetTreeCtrl()->IsExpanded(nodeId)
             ? wxEVT_COMMAND_TREEBOOK_NODE_EXPANDED
             : wxEVT_COMMAND_TREEBOOK_NODE_COLLAPSED,
         m_windowId);
@@ -706,18 +717,49 @@ void wxTreebook::OnTreeNodeExpandedCollapsed(wxTreeEvent & event)
 // wxTreebook geometry management
 // ----------------------------------------------------------------------------
 
-wxTreebookPage * wxTreebook::DoGetCurrentPage() const
+int wxTreebook::HitTest(wxPoint const & pt, long * flags) const
 {
-    if ( m_selection == wxNOT_FOUND )
-        return NULL;
+    int pagePos = wxNOT_FOUND;
 
-    wxTreebookPage *page = wxBookCtrlBase::GetPage(m_selection);
-    if ( !page && m_actualSelection != wxNOT_FOUND )
+    if ( flags )
+        *flags = wxBK_HITTEST_NOWHERE;
+
+    // convert from wxTreebook coorindates to wxTreeCtrl ones
+    const wxTreeCtrl * const tree = GetTreeCtrl();
+    const wxPoint treePt = tree->ScreenToClient(ClientToScreen(pt));
+
+    // is it over the tree?
+    if ( wxRect(tree->GetSize()).Contains(treePt) )
     {
-        page = wxBookCtrlBase::GetPage(m_actualSelection);
+        int flagsTree;
+        wxTreeItemId id = tree->HitTest(treePt, flagsTree);
+
+        if ( id.IsOk() && (flagsTree & wxTREE_HITTEST_ONITEM) )
+        {
+            pagePos = DoInternalFindPageById(id);
+        }
+
+        if ( flags )
+        {
+            if ( pagePos != wxNOT_FOUND )
+                *flags = 0;
+
+            if ( flagsTree & (wxTREE_HITTEST_ONITEMBUTTON |
+                              wxTREE_HITTEST_ONITEMICON |
+                              wxTREE_HITTEST_ONITEMSTATEICON) )
+                *flags |= wxBK_HITTEST_ONICON;
+
+            if ( flagsTree & wxTREE_HITTEST_ONITEMLABEL )
+                *flags |= wxBK_HITTEST_ONLABEL;
+        }
+    }
+    else // not over the tree
+    {
+        if ( flags && GetPageRect().Contains( pt ) )
+            *flags |= wxBK_HITTEST_ONPAGE;
     }
 
-    return page;
+    return pagePos;
 }
 
 #endif // wxUSE_TREEBOOK