treebook.cpp

Go to the documentation of this file.
00001 // $Id: treebook.cpp 1089 2006-05-16 17:57:54Z alex $
00002 /* @@tag:xara-cn-tp@@ THIRD PARTY COPYRIGHT */
00003 // The following line makes normalize.pl skip type fixing
00004 /* SKIPFIXTYPES: START */
00005 
00007 // Name:        src/generic/treebkg.cpp
00008 // Purpose:     generic implementation of wxTreebook
00009 // Author:      Evgeniy Tarassov, Vadim Zeitlin
00010 // Modified by:
00011 // Created:     2005-09-15
00012 // RCS-ID:      $Id: treebkg.cpp,v 1.7 2006/05/03 00:42:33 VZ Exp $
00013 // Copyright:   (c) 2005 Vadim Zeitlin <vadim@wxwidgets.org>
00014 // Licence:     wxWindows licence
00016 
00017 // ============================================================================
00018 // declarations
00019 // ============================================================================
00020 
00021 // ----------------------------------------------------------------------------
00022 // headers
00023 // ----------------------------------------------------------------------------
00024 
00025 #include "treebook.h"
00026 #if wxXTRA_TREEBOOK
00027 
00028 #include <wx/imaglist.h>
00029 #include <wx/settings.h>
00030 
00031 // This overrides the dumb implementation in wx2.6
00032 class wxCamTreeCtrl : public wxTreeCtrl
00033 {
00034 public:
00035     wxCamTreeCtrl(wxWindow *parent, wxWindowID id = wxID_ANY,
00036                const wxPoint& pos = wxDefaultPosition,
00037                const wxSize& size = wxDefaultSize,
00038                long style = wxTR_DEFAULT_STYLE,
00039                const wxValidator &validator = wxDefaultValidator,
00040                const wxString& name = wxTreeCtrlNameStr) :
00041                 wxTreeCtrl(parent, id, pos, size, style, validator, name), m_fixedBestSize(160,380) {}
00042 
00043     virtual wxSize DoGetBestSize() const
00044     {
00045         return m_fixedBestSize;
00046     }
00047 
00048     virtual void SetFixedBestSize(wxSize s)
00049     {
00050         m_fixedBestSize=s;
00051     }
00052 
00053     wxSize m_fixedBestSize;
00054 };
00055 
00056 // ----------------------------------------------------------------------------
00057 // various wxWidgets macros
00058 // ----------------------------------------------------------------------------
00059 
00060 // check that the page index is valid
00061 #define IS_VALID_PAGE(nPage) ((nPage) < DoInternalGetPageCount())
00062 
00063 // ----------------------------------------------------------------------------
00064 // event table
00065 // ----------------------------------------------------------------------------
00066 
00067 IMPLEMENT_DYNAMIC_CLASS(wxTreebook, wxBookCtrlBase)
00068 IMPLEMENT_DYNAMIC_CLASS(wxTreebookEvent, wxNotifyEvent)
00069 
00070 #if !WXWIN_COMPATIBILITY_EVENT_TYPES
00071 const wxEventType wxEVT_COMMAND_TREEBOOK_PAGE_CHANGING = wxNewEventType();
00072 const wxEventType wxEVT_COMMAND_TREEBOOK_PAGE_CHANGED = wxNewEventType();
00073 const wxEventType wxEVT_COMMAND_TREEBOOK_NODE_COLLAPSED = wxNewEventType();
00074 const wxEventType wxEVT_COMMAND_TREEBOOK_NODE_EXPANDED = wxNewEventType();
00075 #endif
00076 const int wxID_TREEBOOKTREEVIEW = wxNewId();
00077 
00078 BEGIN_EVENT_TABLE(wxTreebook, wxBookCtrlBase)
00079     EVT_TREE_SEL_CHANGED   (wxID_TREEBOOKTREEVIEW, wxTreebook::OnTreeSelectionChange)
00080     EVT_TREE_ITEM_EXPANDED (wxID_TREEBOOKTREEVIEW, wxTreebook::OnTreeNodeExpandedCollapsed)
00081     EVT_TREE_ITEM_COLLAPSED(wxID_TREEBOOKTREEVIEW, wxTreebook::OnTreeNodeExpandedCollapsed)
00082     EVT_SIZE(wxTreebook::OnSize)
00083 END_EVENT_TABLE()
00084 
00085 // ============================================================================
00086 // wxTreebook implementation
00087 // ============================================================================
00088 
00089 // ----------------------------------------------------------------------------
00090 // wxTreebook creation
00091 // ----------------------------------------------------------------------------
00092 
00093 void wxTreebook::Init()
00094 {
00095     m_bookctrl = NULL;
00096     m_selection =
00097     m_actualSelection = wxNOT_FOUND;
00098 #if defined(__WXWINCE__)
00099     m_internalBorder = 1;
00100 #else
00101     m_internalBorder = 5;
00102 #endif
00103 
00104 }
00105 
00106 bool
00107 wxTreebook::Create(wxWindow *parent,
00108                    wxWindowID id,
00109                    const wxPoint& pos,
00110                    const wxSize& size,
00111                    long style,
00112                    const wxString& name)
00113 {
00114     // Check the style flag to have either wxTBK_RIGHT or wxTBK_LEFT
00115     if ( (style & wxBK_ALIGN_MASK ) == wxBK_DEFAULT )
00116     {
00117         style |= wxBK_LEFT;
00118     }
00119 
00120     // no border for this control, it doesn't look nice together with the tree
00121     style &= ~wxBORDER_MASK;
00122     style |= wxBORDER_NONE;
00123 
00124     if ( !wxControl::Create(parent, id, pos, size,
00125                             style, wxDefaultValidator, name) )
00126         return false;
00127 
00128     m_bookctrl = new wxCamTreeCtrl
00129                  (
00130                     this,
00131                     wxID_TREEBOOKTREEVIEW,
00132                     wxDefaultPosition,
00133                     wxSize(160,380),
00134                     wxBORDER_SIMPLE |
00135                     wxTR_DEFAULT_STYLE |
00136                     wxTR_HIDE_ROOT |
00137                     wxTR_SINGLE
00138                  );
00139     GetTreeCtrl()->AddRoot(wxEmptyString); // label doesn't matter, it's hidden
00140 
00141 #ifdef __WXMSW__
00142     // We need to add dummy size event to force possible scrollbar hiding
00143     wxSizeEvent evt;
00144     GetEventHandler()->AddPendingEvent(evt);
00145 #endif
00146 
00147     return true;
00148 }
00149 
00150 
00151 // insert a new page just before the pagePos
00152 bool wxTreebook::InsertPage(size_t pagePos,
00153                             wxWindow *page,
00154                             const wxString& text,
00155                             bool bSelect,
00156                             int imageId)
00157 {
00158     return DoInsertPage(pagePos, page, text, bSelect, imageId);
00159 }
00160 
00161 bool wxTreebook::InsertSubPage(size_t pagePos,
00162                                wxWindow *page,
00163                                const wxString& text,
00164                                bool bSelect,
00165                                int imageId)
00166 {
00167     return DoInsertSubPage(pagePos, page, text, bSelect, imageId);
00168 }
00169 
00170 bool wxTreebook::AddPage(wxWindow *page, const wxString& text, bool bSelect,
00171                          int imageId)
00172 {
00173     return DoInsertPage(m_treeIds.GetCount(), page, text, bSelect, imageId);
00174 }
00175 
00176 // insertion time is linear to the number of top-pages
00177 bool wxTreebook::AddSubPage(wxWindow *page, const wxString& text, bool bSelect, int imageId)
00178 {
00179     return DoAddSubPage(page, text, bSelect, imageId);
00180 }
00181 
00182 
00183 bool wxTreebook::DoInsertPage(size_t pagePos,
00184                               wxWindow *page,
00185                               const wxString& text,
00186                               bool bSelect,
00187                               int imageId)
00188 {
00189     wxCHECK_MSG( pagePos <= DoInternalGetPageCount(), false,
00190                         wxT("Invalid treebook page position") );
00191 
00192     if ( !wxBookCtrlBase::InsertPage(pagePos, page, text, bSelect, imageId) )
00193         return false;
00194 
00195     wxTreeCtrl *tree = GetTreeCtrl();
00196     wxTreeItemId newId;
00197     if ( pagePos == DoInternalGetPageCount() )
00198     {
00199         // append the page to the end
00200         wxTreeItemId rootId = tree->GetRootItem();
00201 
00202         newId = tree->AppendItem(rootId, text, imageId);
00203     }
00204     else // insert the new page before the given one
00205     {
00206         wxTreeItemId nodeId = m_treeIds[pagePos];
00207 
00208         wxTreeItemId previousId = tree->GetPrevSibling(nodeId);
00209         wxTreeItemId parentId = tree->GetItemParent(nodeId);
00210 
00211         if ( previousId.IsOk() )
00212         {
00213             // insert before the sibling - previousId
00214             newId = tree->InsertItem(parentId, previousId, text, imageId);
00215         }
00216         else // no prev siblings -- insert as a first child
00217         {
00218             wxASSERT_MSG( parentId.IsOk(), wxT( "Tree has no root node?" ) );
00219 
00220             newId = tree->PrependItem(parentId, text, imageId);
00221         }
00222     }
00223 
00224     if ( !newId.IsOk() )
00225     {
00226         //something wrong -> cleaning and returning with false
00227         (void)wxBookCtrlBase::DoRemovePage(pagePos);
00228 
00229         wxFAIL_MSG( wxT("Failed to insert treebook page") );
00230         return false;
00231     }
00232 
00233     DoInternalAddPage(pagePos, page, newId);
00234 
00235     DoUpdateSelection(bSelect, pagePos);
00236 
00237     return true;
00238 }
00239 
00240 bool wxTreebook::DoAddSubPage(wxWindow *page, const wxString& text, bool bSelect, int imageId)
00241 {
00242     wxTreeCtrl *tree = GetTreeCtrl();
00243 
00244     wxTreeItemId rootId = tree->GetRootItem();
00245 
00246     wxTreeItemId lastNodeId = tree->GetLastChild(rootId);
00247 
00248     wxCHECK_MSG( lastNodeId.IsOk(), false,
00249                         _T("Can't insert sub page when there are no pages") );
00250 
00251     // now calculate its position (should we save/update it too?)
00252     size_t newPos = tree->GetCount() -
00253                         (tree->GetChildrenCount(lastNodeId, true) + 1);
00254 
00255     return DoInsertSubPage(newPos, page, text, bSelect, imageId);
00256 }
00257 
00258 bool wxTreebook::DoInsertSubPage(size_t pagePos,
00259                                  wxTreebookPage *page,
00260                                  const wxString& text,
00261                                  bool bSelect,
00262                                  int imageId)
00263 {
00264     wxTreeItemId parentId = DoInternalGetPage(pagePos);
00265     wxCHECK_MSG( parentId.IsOk(), false, wxT("invalid tree item") );
00266 
00267     wxTreeCtrl *tree = GetTreeCtrl();
00268 
00269     size_t newPos = pagePos + tree->GetChildrenCount(parentId, true) + 1;
00270     wxASSERT_MSG( newPos <= DoInternalGetPageCount(),
00271                     wxT("Internal error in tree insert point calculation") );
00272 
00273     if ( !wxBookCtrlBase::InsertPage(newPos, page, text, bSelect, imageId) )
00274         return false;
00275 
00276     wxTreeItemId newId = tree->AppendItem(parentId, text, imageId);
00277 
00278     if ( !newId.IsOk() )
00279     {
00280         (void)wxBookCtrlBase::DoRemovePage(newPos);
00281 
00282         wxFAIL_MSG( wxT("Failed to insert treebook page") );
00283         return false;
00284     }
00285 
00286     DoInternalAddPage(newPos, page, newId);
00287 
00288     DoUpdateSelection(bSelect, newPos);
00289 
00290     return true;
00291 }
00292 
00293 bool wxTreebook::DeletePage(size_t pagePos)
00294 {
00295     wxCHECK_MSG( IS_VALID_PAGE(pagePos), false, wxT("Invalid tree index") );
00296 
00297     wxTreebookPage *oldPage = DoRemovePage(pagePos);
00298     if ( !oldPage )
00299         return false;
00300 
00301     delete oldPage;
00302 
00303     return true;
00304 }
00305 
00306 wxTreebookPage *wxTreebook::DoRemovePage(size_t pagePos)
00307 {
00308     wxTreeItemId pageId = DoInternalGetPage(pagePos);
00309     wxCHECK_MSG( pageId.IsOk(), NULL, wxT("Invalid tree index") );
00310 
00311     wxTreebookPage * oldPage = GetPage(pagePos);
00312     wxTreeCtrl *tree = GetTreeCtrl();
00313 
00314     size_t subCount = tree->GetChildrenCount(pageId, true);
00315     wxASSERT_MSG ( IS_VALID_PAGE(pagePos + subCount),
00316                         wxT("Internal error in wxTreebook::DoRemovePage") );
00317 
00318     // here we are going to delete ALL the pages in the range
00319     // [pagePos, pagePos + subCount] -- the page and its children
00320 
00321     // deleting all the pages from the base class
00322     for ( size_t i = 0; i <= subCount; ++i )
00323     {
00324         wxTreebookPage *page = wxBookCtrlBase::DoRemovePage(pagePos);
00325 
00326         // don't delete the page itself though -- it will be deleted in
00327         // DeletePage() when we return
00328         if ( i )
00329         {
00330             delete page;
00331         }
00332     }
00333 
00334     DoInternalRemovePageRange(pagePos, subCount);
00335 
00336     tree->DeleteChildren( pageId );
00337     tree->Delete( pageId );
00338 
00339     return oldPage;
00340 }
00341 
00342 bool wxTreebook::DeleteAllPages()
00343 {
00344     wxBookCtrlBase::DeleteAllPages();
00345     m_treeIds.Clear();
00346     m_selection =
00347     m_actualSelection = wxNOT_FOUND;
00348 
00349     wxTreeCtrl *tree = GetTreeCtrl();
00350     tree->DeleteChildren(tree->GetRootItem());
00351 
00352     return true;
00353 }
00354 
00355 void wxTreebook::DoInternalAddPage(size_t newPos,
00356                                    wxTreebookPage *page,
00357                                    wxTreeItemId pageId)
00358 {
00359     wxASSERT_MSG( newPos <= m_treeIds.GetCount(), wxT("Ivalid index passed to wxTreebook::DoInternalAddPage") );
00360 
00361     // hide newly inserted page initially (it will be shown when selected)
00362     if ( page )
00363         page->Hide();
00364 
00365     if ( newPos == m_treeIds.GetCount() )
00366     {
00367         // append
00368         m_treeIds.Add(pageId);
00369     }
00370     else // insert
00371     {
00372         m_treeIds.Insert(pageId.m_pItem, newPos);
00373 
00374         if ( m_selection != wxNOT_FOUND && newPos <= (size_t)m_selection )
00375         {
00376             // selection has been moved one unit toward the end
00377             ++m_selection;
00378             if ( m_actualSelection != wxNOT_FOUND )
00379                 ++m_actualSelection;
00380         }
00381         else if ( m_actualSelection != wxNOT_FOUND &&
00382                     newPos <= (size_t)m_actualSelection )
00383         {
00384             DoSetSelection(m_selection);
00385         }
00386     }
00387 }
00388 
00389 void wxTreebook::DoInternalRemovePageRange(size_t pagePos, size_t subCount)
00390 {
00391     // Attention: this function is only for a situation when we delete a node
00392     // with all its children so pagePos is the node's index and subCount is the
00393     // node children count
00394     wxASSERT_MSG( pagePos + subCount < m_treeIds.GetCount(),
00395                     wxT("Ivalid page index") );
00396 
00397     wxTreeItemId pageId = m_treeIds[pagePos];
00398 
00399     m_treeIds.RemoveAt(pagePos, subCount + 1);
00400 
00401     if ( m_selection != wxNOT_FOUND )
00402     {
00403         if ( (size_t)m_selection > pagePos + subCount)
00404         {
00405             // selection is far after the deleted page, so just update the index and move on
00406             m_selection -= 1 + subCount;
00407             if ( m_actualSelection != wxNOT_FOUND)
00408             {
00409                 m_actualSelection -= subCount + 1;
00410             }
00411         }
00412         else if ( (size_t)m_selection >= pagePos )
00413         {
00414             wxTreeCtrl *tree = GetTreeCtrl();
00415 
00416             // as selected page is going to be deleted, try to select the next
00417             // sibling if exists, if not then the parent
00418             wxTreeItemId nodeId = tree->GetNextSibling(pageId);
00419 
00420             m_selection = wxNOT_FOUND;
00421             m_actualSelection = wxNOT_FOUND;
00422 
00423             if ( nodeId.IsOk() )
00424             {
00425                 // selecting next siblings
00426                 tree->SelectItem(nodeId);
00427             }
00428             else // no next sibling, select the parent
00429             {
00430                 wxTreeItemId parentId = tree->GetItemParent(pageId);
00431 
00432                 if ( parentId.IsOk() && parentId != tree->GetRootItem() )
00433                 {
00434                     tree->SelectItem(parentId);
00435                 }
00436                 else // parent is root
00437                 {
00438                     // we can't select it as it's hidden
00439                     DoUpdateSelection(false, wxNOT_FOUND);
00440                 }
00441             }
00442         }
00443         else if ( m_actualSelection != wxNOT_FOUND &&
00444                     (size_t)m_actualSelection >= pagePos )
00445         {
00446             // nothing to do -- selection is before the deleted node, but
00447             // actually shown page (the first (sub)child with page != NULL) is
00448             // already deleted
00449             m_actualSelection = m_selection;
00450             DoSetSelection(m_selection);
00451         }
00452         //else: nothing to do -- selection is before the deleted node
00453     }
00454     else
00455     {
00456         DoUpdateSelection(false, wxNOT_FOUND);
00457     }
00458 }
00459 
00460 
00461 void wxTreebook::DoUpdateSelection(bool bSelect, int newPos)
00462 {
00463     int newSelPos;
00464     if ( bSelect )
00465     {
00466         newSelPos = newPos;
00467     }
00468     else if ( m_selection == wxNOT_FOUND && DoInternalGetPageCount() > 0 )
00469     {
00470         newSelPos = 0;
00471     }
00472     else
00473     {
00474         newSelPos = wxNOT_FOUND;
00475     }
00476 
00477     if ( newSelPos != wxNOT_FOUND )
00478     {
00479         SetSelection((size_t)newSelPos);
00480     }
00481 }
00482 
00483 wxTreeItemId wxTreebook::DoInternalGetPage(size_t pagePos) const
00484 {
00485     if ( pagePos >= m_treeIds.GetCount() )
00486     {
00487         // invalid position but ok here, in this internal function, don't assert
00488         // (the caller will do it)
00489         return wxTreeItemId();
00490     }
00491 
00492     return m_treeIds[pagePos];
00493 }
00494 
00495 int wxTreebook::DoInternalFindPageById(wxTreeItemId pageId) const
00496 {
00497     const size_t count = m_treeIds.GetCount();
00498     for ( size_t i = 0; i < count; ++i )
00499     {
00500         if ( m_treeIds[i] == pageId )
00501             return i;
00502     }
00503 
00504     return wxNOT_FOUND;
00505 }
00506 
00507 bool wxTreebook::IsNodeExpanded(size_t pagePos) const
00508 {
00509     wxTreeItemId pageId = DoInternalGetPage(pagePos);
00510 
00511     wxCHECK_MSG( pageId.IsOk(), false, wxT("invalid tree item") );
00512 
00513     return GetTreeCtrl()->IsExpanded(pageId);
00514 }
00515 
00516 bool wxTreebook::ExpandNode(size_t pagePos, bool expand)
00517 {
00518     wxTreeItemId pageId = DoInternalGetPage(pagePos);
00519 
00520     wxCHECK_MSG( pageId.IsOk(), false, wxT("invalid tree item") );
00521 
00522     if ( expand )
00523     {
00524         GetTreeCtrl()->Expand( pageId );
00525     }
00526     else // collapse
00527     {
00528         GetTreeCtrl()->Collapse( pageId );
00529 
00530         // rely on the events generated by wxTreeCtrl to update selection
00531     }
00532 
00533     return true;
00534 }
00535 
00536 int wxTreebook::GetPageParent(size_t pagePos) const
00537 {
00538     wxTreeItemId nodeId = DoInternalGetPage( pagePos );
00539     wxCHECK_MSG( nodeId.IsOk(), wxNOT_FOUND, wxT("Invalid page index spacified!") );
00540 
00541     const wxTreeItemId parent = GetTreeCtrl()->GetItemParent( nodeId );
00542 
00543     return parent.IsOk() ? DoInternalFindPageById(parent) : wxNOT_FOUND;
00544 }
00545 
00546 bool wxTreebook::SetPageText(size_t n, const wxString& strText)
00547 {
00548     wxTreeItemId pageId = DoInternalGetPage(n);
00549 
00550     wxCHECK_MSG( pageId.IsOk(), false, wxT("invalid tree item") );
00551 
00552     GetTreeCtrl()->SetItemText(pageId, strText);
00553 
00554     return true;
00555 }
00556 
00557 wxString wxTreebook::GetPageText(size_t n) const
00558 {
00559     wxTreeItemId pageId = DoInternalGetPage(n);
00560 
00561     wxCHECK_MSG( pageId.IsOk(), wxString(), wxT("invalid tree item") );
00562 
00563     return GetTreeCtrl()->GetItemText(pageId);
00564 }
00565 
00566 int wxTreebook::GetPageImage(size_t n) const
00567 {
00568     wxTreeItemId pageId = DoInternalGetPage(n);
00569 
00570     wxCHECK_MSG( pageId.IsOk(), wxNOT_FOUND, wxT("invalid tree item") );
00571 
00572     return GetTreeCtrl()->GetItemImage(pageId);
00573 }
00574 
00575 bool wxTreebook::SetPageImage(size_t n, int imageId)
00576 {
00577     wxTreeItemId pageId = DoInternalGetPage(n);
00578 
00579     wxCHECK_MSG( pageId.IsOk(), false, wxT("invalid tree item") );
00580 
00581     GetTreeCtrl()->SetItemImage(pageId, imageId);
00582 
00583     return true;
00584 }
00585 
00586 wxSize wxTreebook::CalcSizeFromPage(const wxSize& sizePage) const
00587 {
00588     const wxSize sizeTree = GetControllerSize();
00589 
00590     wxSize size = sizePage;
00591     size.x += sizeTree.x;
00592 
00593     return size;
00594 }
00595 
00596 int wxTreebook::GetSelection() const
00597 {
00598    return m_selection;
00599 }
00600 
00601 int wxTreebook::SetSelection(size_t pagePos)
00602 {
00603    if ( (size_t)m_selection != pagePos )
00604        return DoSetSelection(pagePos);
00605 
00606    return m_selection;
00607 }
00608 
00609 int wxTreebook::DoSetSelection(size_t pagePos)
00610 {
00611     wxCHECK_MSG( IS_VALID_PAGE(pagePos), wxNOT_FOUND,
00612                  wxT("invalid page index in wxListbook::SetSelection()") );
00613     wxASSERT_MSG( GetPageCount() == DoInternalGetPageCount(),
00614                   wxT("wxTreebook logic error: m_treeIds and m_pages not in sync!"));
00615 
00616     const int oldSel = m_selection;
00617     wxTreeCtrl *tree = GetTreeCtrl();
00618 
00619     wxTreebookEvent event(wxEVT_COMMAND_TREEBOOK_PAGE_CHANGING, m_windowId);
00620     event.SetEventObject(this);
00621     event.SetSelection(pagePos);
00622     event.SetOldSelection(m_selection);
00623 
00624     // don't send the event if the old and new pages are the same; do send it
00625     // otherwise and be prepared for it to be vetoed
00626     if ( (int)pagePos == m_selection ||
00627             !GetEventHandler()->ProcessEvent(event) ||
00628                 event.IsAllowed() )
00629     {
00630         // hide the previously shown page
00631         wxTreebookPage * const oldPage = DoGetCurrentPage();
00632         if ( oldPage )
00633             oldPage->Hide();
00634 
00635         // then show the new one
00636         m_selection = pagePos;
00637         wxTreebookPage *page = wxBookCtrlBase::GetPage(m_selection);
00638         if ( !page )
00639         {
00640             // find the next page suitable to be shown: the first (grand)child
00641             // of this one with a non-NULL associated page
00642             wxTreeItemId childId = m_treeIds[pagePos];
00643             int actualPagePos = pagePos;
00644             while ( !page && childId.IsOk() )
00645             {
00646                 wxTreeItemIdValue cookie;
00647                 childId = tree->GetFirstChild( childId, cookie );
00648                 if ( childId.IsOk() )
00649                 {
00650                     page = wxBookCtrlBase::GetPage(++actualPagePos);
00651                 }
00652             }
00653 
00654             m_actualSelection = page ? actualPagePos : m_selection;
00655         }
00656 
00657         if ( page )
00658             page->Show();
00659 
00660         tree->SelectItem(DoInternalGetPage(pagePos));
00661 
00662         // notify about the (now completed) page change
00663         event.SetEventType(wxEVT_COMMAND_TREEBOOK_PAGE_CHANGED);
00664         (void)GetEventHandler()->ProcessEvent(event);
00665     }
00666     else // page change vetoed
00667     {
00668         // tree selection might have already had changed
00669         tree->SelectItem(DoInternalGetPage(oldSel));
00670     }
00671 
00672     return oldSel;
00673 }
00674 
00675 void wxTreebook::SetImageList(wxImageList *imageList)
00676 {
00677     wxBookCtrlBase::SetImageList(imageList);
00678     GetTreeCtrl()->SetImageList(imageList);
00679 }
00680 
00681 void wxTreebook::AssignImageList(wxImageList *imageList)
00682 {
00683     wxBookCtrlBase::AssignImageList(imageList);
00684     GetTreeCtrl()->SetImageList(imageList);
00685 }
00686 
00687 // ----------------------------------------------------------------------------
00688 // event handlers
00689 // ----------------------------------------------------------------------------
00690 
00691 void wxTreebook::OnTreeSelectionChange(wxTreeEvent& event)
00692 {
00693     wxTreeItemId newId = event.GetItem();
00694 
00695     if ( (m_selection == wxNOT_FOUND &&
00696                 (!newId.IsOk() || newId == GetTreeCtrl()->GetRootItem())) ||
00697             (m_selection != wxNOT_FOUND && newId == m_treeIds[m_selection]) )
00698     {
00699         // this event can only come when we modify the tree selection ourselves
00700         // so we should simply ignore it
00701         return;
00702     }
00703 
00704     int newPos = DoInternalFindPageById(newId);
00705 
00706     if ( newPos != wxNOT_FOUND )
00707         SetSelection( newPos );
00708 }
00709 
00710 void wxTreebook::OnTreeNodeExpandedCollapsed(wxTreeEvent & event)
00711 {
00712     wxTreeItemId nodeId = event.GetItem();
00713     if ( !nodeId.IsOk() || nodeId == GetTreeCtrl()->GetRootItem() )
00714         return;
00715     int pagePos = DoInternalFindPageById(nodeId);
00716     wxCHECK_RET( pagePos != wxNOT_FOUND, wxT("Internal problem in wxTreebook!..") );
00717 
00718     wxTreebookEvent ev(GetTreeCtrl()->IsExpanded(nodeId)
00719             ? wxEVT_COMMAND_TREEBOOK_NODE_EXPANDED
00720             : wxEVT_COMMAND_TREEBOOK_NODE_COLLAPSED,
00721         m_windowId);
00722 
00723     ev.SetSelection(pagePos);
00724     ev.SetOldSelection(pagePos);
00725     ev.SetEventObject(this);
00726 
00727     GetEventHandler()->ProcessEvent(ev);
00728 }
00729 
00730 // ----------------------------------------------------------------------------
00731 // wxTreebook geometry management
00732 // ----------------------------------------------------------------------------
00733 
00734 wxTreebookPage * wxTreebook::DoGetCurrentPage()
00735 {
00736     if ( m_selection == wxNOT_FOUND )
00737         return NULL;
00738 
00739     wxTreebookPage *page = wxBookCtrlBase::GetPage(m_selection);
00740     if ( !page && m_actualSelection != wxNOT_FOUND )
00741     {
00742         page = wxBookCtrlBase::GetPage(m_actualSelection);
00743     }
00744 
00745     return page;
00746 }
00747 
00748 // Some routines from the base class
00749 
00750 
00751 // Lay out controls
00752 void wxTreebook::DoSize()
00753 {
00754     if ( !m_bookctrl )
00755     {
00756         // we're not fully created yet or OnSize() should be hidden by derived class
00757         return;
00758     }
00759 
00760     if (GetSizer())
00761         Layout();
00762     else
00763     {
00764         // resize controller and the page area to fit inside our new size
00765         const wxSize sizeClient( GetClientSize() ),
00766                     sizeBorder( m_bookctrl->GetSize() - m_bookctrl->GetClientSize() ),
00767                     sizeCtrl( GetControllerSize() );
00768 
00769         m_bookctrl->SetClientSize( sizeCtrl.x - sizeBorder.x, sizeCtrl.y - sizeBorder.y );
00770 
00771         const wxSize sizeNew = m_bookctrl->GetSize();
00772         wxPoint posCtrl;
00773         switch ( GetWindowStyle() & wxBK_ALIGN_MASK )
00774         {
00775             default:
00776                 wxFAIL_MSG( _T("unexpected alignment") );
00777                 // fall through
00778 
00779             case wxBK_TOP:
00780             case wxBK_LEFT:
00781                 // posCtrl is already ok
00782                 break;
00783 
00784             case wxBK_BOTTOM:
00785                 posCtrl.y = sizeClient.y - sizeNew.y;
00786                 break;
00787 
00788             case wxBK_RIGHT:
00789                 posCtrl.x = sizeClient.x - sizeNew.x;
00790                 break;
00791         }
00792 
00793         if ( m_bookctrl->GetPosition() != posCtrl )
00794             m_bookctrl->Move(posCtrl);
00795     }
00796 
00797     // resize all pages to fit the new control size
00798     const wxRect pageRect = GetPageRect();
00799     const unsigned pagesCount = m_pages.Count();
00800     for ( unsigned int i = 0; i < pagesCount; ++i )
00801     {
00802         wxWindow * const page = m_pages[i];
00803         if ( !page )
00804         {
00805             wxASSERT_MSG( AllowNullPage(),
00806                 _T("Null page in a control that does not allow null pages?") );
00807             continue;
00808         }
00809 
00810         page->SetSize(pageRect);
00811     }
00812 }
00813 
00814 void wxTreebook::OnSize(wxSizeEvent& event)
00815 {
00816     m_bookctrl->InvalidateBestSize();
00817     m_bookctrl->SetSize(m_bookctrl->GetBestSize());
00818 
00819     event.Skip();
00820 
00821     DoSize();
00822 }
00823 
00824 wxSize wxTreebook::GetControllerSize() const
00825 {
00826     if(!m_bookctrl)
00827         return wxSize(0,0);
00828 
00829     wxSize cbestsize = m_bookctrl->GetBestSize();
00830 
00831     wxSize sizeClient = GetClientSize(),
00832                  sizeBorder = m_bookctrl->GetSize() - m_bookctrl->GetClientSize(),
00833                  sizeCtrl =  cbestsize + sizeBorder;
00834 
00835     wxSize size;
00836 
00837     if ( HasFlag(wxBK_BOTTOM | wxBK_TOP) )
00838     {
00839         size.x = sizeClient.x;
00840         size.y = sizeCtrl.y;
00841     }
00842     else // left/right aligned
00843     {
00844         size.x = sizeCtrl.x;
00845         size.y = sizeClient.y;
00846     }
00847 
00848     return size;
00849 }
00850 
00851 wxRect wxTreebook::GetPageRect() const
00852 {
00853     const wxSize size = GetControllerSize();
00854 
00855     wxPoint pt;
00856     wxRect rectPage(pt, GetClientSize());
00857     switch ( GetWindowStyle() & wxBK_ALIGN_MASK )
00858     {
00859         default:
00860             wxFAIL_MSG( _T("unexpected alignment") );
00861             // fall through
00862 
00863         case wxBK_TOP:
00864             rectPage.y = size.y + GetInternalBorder();
00865             // fall through
00866 
00867         case wxBK_BOTTOM:
00868             rectPage.height -= size.y + GetInternalBorder();
00869             break;
00870 
00871         case wxBK_LEFT:
00872             rectPage.x = size.x + GetInternalBorder();
00873             // fall through
00874 
00875         case wxBK_RIGHT:
00876             rectPage.width -= size.x + GetInternalBorder();
00877             break;
00878     }
00879 
00880     return rectPage;
00881 }
00882 
00883 
00884 #endif // wxXTRA_TREEBOOK

Generated on Sat Nov 10 03:49:02 2007 for Camelot by  doxygen 1.4.4