]> git.saurik.com Git - wxWidgets.git/blob - src/generic/treebkg.cpp
Include wx/timer.h according to precompiled headers of wx/wx.h (with other minor...
[wxWidgets.git] / src / generic / treebkg.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/generic/treebkg.cpp
3 // Purpose: generic implementation of wxTreebook
4 // Author: Evgeniy Tarassov, Vadim Zeitlin
5 // Modified by:
6 // Created: 2005-09-15
7 // RCS-ID: $Id$
8 // Copyright: (c) 2005 Vadim Zeitlin <vadim@wxwidgets.org>
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #if wxUSE_TREEBOOK
28
29 #include "wx/treebook.h"
30 #include "wx/imaglist.h"
31 #include "wx/settings.h"
32
33 // ----------------------------------------------------------------------------
34 // various wxWidgets macros
35 // ----------------------------------------------------------------------------
36
37 // check that the page index is valid
38 #define IS_VALID_PAGE(nPage) ((nPage) < DoInternalGetPageCount())
39
40 // ----------------------------------------------------------------------------
41 // event table
42 // ----------------------------------------------------------------------------
43
44 IMPLEMENT_DYNAMIC_CLASS(wxTreebook, wxBookCtrlBase)
45 IMPLEMENT_DYNAMIC_CLASS(wxTreebookEvent, wxNotifyEvent)
46
47 #if !WXWIN_COMPATIBILITY_EVENT_TYPES
48 const wxEventType wxEVT_COMMAND_TREEBOOK_PAGE_CHANGING = wxNewEventType();
49 const wxEventType wxEVT_COMMAND_TREEBOOK_PAGE_CHANGED = wxNewEventType();
50 const wxEventType wxEVT_COMMAND_TREEBOOK_NODE_COLLAPSED = wxNewEventType();
51 const wxEventType wxEVT_COMMAND_TREEBOOK_NODE_EXPANDED = wxNewEventType();
52 #endif
53 const int wxID_TREEBOOKTREEVIEW = wxNewId();
54
55 BEGIN_EVENT_TABLE(wxTreebook, wxBookCtrlBase)
56 EVT_TREE_SEL_CHANGED (wxID_TREEBOOKTREEVIEW, wxTreebook::OnTreeSelectionChange)
57 EVT_TREE_ITEM_EXPANDED (wxID_TREEBOOKTREEVIEW, wxTreebook::OnTreeNodeExpandedCollapsed)
58 EVT_TREE_ITEM_COLLAPSED(wxID_TREEBOOKTREEVIEW, wxTreebook::OnTreeNodeExpandedCollapsed)
59 END_EVENT_TABLE()
60
61 // ============================================================================
62 // wxTreebook implementation
63 // ============================================================================
64
65 // ----------------------------------------------------------------------------
66 // wxTreebook creation
67 // ----------------------------------------------------------------------------
68
69 void wxTreebook::Init()
70 {
71 m_selection =
72 m_actualSelection = wxNOT_FOUND;
73 }
74
75 bool
76 wxTreebook::Create(wxWindow *parent,
77 wxWindowID id,
78 const wxPoint& pos,
79 const wxSize& size,
80 long style,
81 const wxString& name)
82 {
83 // Check the style flag to have either wxTBK_RIGHT or wxTBK_LEFT
84 if ( (style & wxBK_ALIGN_MASK) == wxBK_DEFAULT )
85 {
86 style |= wxBK_LEFT;
87 }
88
89 // no border for this control, it doesn't look nice together with the tree
90 style &= ~wxBORDER_MASK;
91 style |= wxBORDER_NONE;
92
93 if ( !wxControl::Create(parent, id, pos, size,
94 style, wxDefaultValidator, name) )
95 return false;
96
97 m_bookctrl = new wxTreeCtrl
98 (
99 this,
100 wxID_TREEBOOKTREEVIEW,
101 wxDefaultPosition,
102 wxDefaultSize,
103 #ifndef __WXMSW__
104 wxBORDER_SIMPLE | // On wxMSW this produces a black border which is wrong
105 #endif
106 wxTR_DEFAULT_STYLE |
107 wxTR_HIDE_ROOT |
108 wxTR_SINGLE
109 );
110 GetTreeCtrl()->SetQuickBestSize(false); // do full size calculation
111 GetTreeCtrl()->AddRoot(wxEmptyString); // label doesn't matter, it's hidden
112
113 #ifdef __WXMSW__
114 // We need to add dummy size event to force possible scrollbar hiding
115 wxSizeEvent evt;
116 GetEventHandler()->AddPendingEvent(evt);
117 #endif
118
119 return true;
120 }
121
122
123 // insert a new page just before the pagePos
124 bool wxTreebook::InsertPage(size_t pagePos,
125 wxWindow *page,
126 const wxString& text,
127 bool bSelect,
128 int imageId)
129 {
130 return DoInsertPage(pagePos, page, text, bSelect, imageId);
131 }
132
133 bool wxTreebook::InsertSubPage(size_t pagePos,
134 wxWindow *page,
135 const wxString& text,
136 bool bSelect,
137 int imageId)
138 {
139 return DoInsertSubPage(pagePos, page, text, bSelect, imageId);
140 }
141
142 bool wxTreebook::AddPage(wxWindow *page, const wxString& text, bool bSelect,
143 int imageId)
144 {
145 return DoInsertPage(m_treeIds.GetCount(), page, text, bSelect, imageId);
146 }
147
148 // insertion time is linear to the number of top-pages
149 bool wxTreebook::AddSubPage(wxWindow *page, const wxString& text, bool bSelect, int imageId)
150 {
151 return DoAddSubPage(page, text, bSelect, imageId);
152 }
153
154
155 bool wxTreebook::DoInsertPage(size_t pagePos,
156 wxWindow *page,
157 const wxString& text,
158 bool bSelect,
159 int imageId)
160 {
161 wxCHECK_MSG( pagePos <= DoInternalGetPageCount(), false,
162 wxT("Invalid treebook page position") );
163
164 if ( !wxBookCtrlBase::InsertPage(pagePos, page, text, bSelect, imageId) )
165 return false;
166
167 wxTreeCtrl *tree = GetTreeCtrl();
168 wxTreeItemId newId;
169 if ( pagePos == DoInternalGetPageCount() )
170 {
171 // append the page to the end
172 wxTreeItemId rootId = tree->GetRootItem();
173
174 newId = tree->AppendItem(rootId, text, imageId);
175 }
176 else // insert the new page before the given one
177 {
178 wxTreeItemId nodeId = m_treeIds[pagePos];
179
180 wxTreeItemId previousId = tree->GetPrevSibling(nodeId);
181 wxTreeItemId parentId = tree->GetItemParent(nodeId);
182
183 if ( previousId.IsOk() )
184 {
185 // insert before the sibling - previousId
186 newId = tree->InsertItem(parentId, previousId, text, imageId);
187 }
188 else // no prev siblings -- insert as a first child
189 {
190 wxASSERT_MSG( parentId.IsOk(), wxT( "Tree has no root node?" ) );
191
192 newId = tree->PrependItem(parentId, text, imageId);
193 }
194 }
195
196 if ( !newId.IsOk() )
197 {
198 //something wrong -> cleaning and returning with false
199 (void)wxBookCtrlBase::DoRemovePage(pagePos);
200
201 wxFAIL_MSG( wxT("Failed to insert treebook page") );
202 return false;
203 }
204
205 DoInternalAddPage(pagePos, page, newId);
206
207 DoUpdateSelection(bSelect, pagePos);
208
209 return true;
210 }
211
212 bool wxTreebook::DoAddSubPage(wxWindow *page, const wxString& text, bool bSelect, int imageId)
213 {
214 wxTreeCtrl *tree = GetTreeCtrl();
215
216 wxTreeItemId rootId = tree->GetRootItem();
217
218 wxTreeItemId lastNodeId = tree->GetLastChild(rootId);
219
220 wxCHECK_MSG( lastNodeId.IsOk(), false,
221 _T("Can't insert sub page when there are no pages") );
222
223 // now calculate its position (should we save/update it too?)
224 size_t newPos = tree->GetCount() -
225 (tree->GetChildrenCount(lastNodeId, true) + 1);
226
227 return DoInsertSubPage(newPos, page, text, bSelect, imageId);
228 }
229
230 bool wxTreebook::DoInsertSubPage(size_t pagePos,
231 wxTreebookPage *page,
232 const wxString& text,
233 bool bSelect,
234 int imageId)
235 {
236 wxTreeItemId parentId = DoInternalGetPage(pagePos);
237 wxCHECK_MSG( parentId.IsOk(), false, wxT("invalid tree item") );
238
239 wxTreeCtrl *tree = GetTreeCtrl();
240
241 size_t newPos = pagePos + tree->GetChildrenCount(parentId, true) + 1;
242 wxASSERT_MSG( newPos <= DoInternalGetPageCount(),
243 wxT("Internal error in tree insert point calculation") );
244
245 if ( !wxBookCtrlBase::InsertPage(newPos, page, text, bSelect, imageId) )
246 return false;
247
248 wxTreeItemId newId = tree->AppendItem(parentId, text, imageId);
249
250 tree->InvalidateBestSize();
251
252 if ( !newId.IsOk() )
253 {
254 (void)wxBookCtrlBase::DoRemovePage(newPos);
255
256 wxFAIL_MSG( wxT("Failed to insert treebook page") );
257 return false;
258 }
259
260 DoInternalAddPage(newPos, page, newId);
261
262 DoUpdateSelection(bSelect, newPos);
263
264 return true;
265 }
266
267 bool wxTreebook::DeletePage(size_t pagePos)
268 {
269 wxCHECK_MSG( IS_VALID_PAGE(pagePos), false, wxT("Invalid tree index") );
270
271 wxTreebookPage *oldPage = DoRemovePage(pagePos);
272 if ( !oldPage )
273 return false;
274
275 delete oldPage;
276
277 return true;
278 }
279
280 wxTreebookPage *wxTreebook::DoRemovePage(size_t pagePos)
281 {
282 wxTreeItemId pageId = DoInternalGetPage(pagePos);
283 wxCHECK_MSG( pageId.IsOk(), NULL, wxT("Invalid tree index") );
284
285 wxTreebookPage * oldPage = GetPage(pagePos);
286 wxTreeCtrl *tree = GetTreeCtrl();
287
288 size_t subCount = tree->GetChildrenCount(pageId, true);
289 wxASSERT_MSG ( IS_VALID_PAGE(pagePos + subCount),
290 wxT("Internal error in wxTreebook::DoRemovePage") );
291
292 // here we are going to delete ALL the pages in the range
293 // [pagePos, pagePos + subCount] -- the page and its children
294
295 // deleting all the pages from the base class
296 for ( size_t i = 0; i <= subCount; ++i )
297 {
298 wxTreebookPage *page = wxBookCtrlBase::DoRemovePage(pagePos);
299
300 // don't delete the page itself though -- it will be deleted in
301 // DeletePage() when we return
302 if ( i )
303 {
304 delete page;
305 }
306 }
307
308 DoInternalRemovePageRange(pagePos, subCount);
309
310 tree->DeleteChildren( pageId );
311 tree->Delete( pageId );
312
313 return oldPage;
314 }
315
316 bool wxTreebook::DeleteAllPages()
317 {
318 wxBookCtrlBase::DeleteAllPages();
319 m_treeIds.Clear();
320 m_selection =
321 m_actualSelection = wxNOT_FOUND;
322
323 wxTreeCtrl *tree = GetTreeCtrl();
324 tree->DeleteChildren(tree->GetRootItem());
325
326 return true;
327 }
328
329 void wxTreebook::DoInternalAddPage(size_t newPos,
330 wxTreebookPage *page,
331 wxTreeItemId pageId)
332 {
333 wxASSERT_MSG( newPos <= m_treeIds.GetCount(), wxT("Ivalid index passed to wxTreebook::DoInternalAddPage") );
334
335 // hide newly inserted page initially (it will be shown when selected)
336 if ( page )
337 page->Hide();
338
339 if ( newPos == m_treeIds.GetCount() )
340 {
341 // append
342 m_treeIds.Add(pageId);
343 }
344 else // insert
345 {
346 m_treeIds.Insert(pageId, newPos);
347
348 if ( m_selection != wxNOT_FOUND && newPos <= (size_t)m_selection )
349 {
350 // selection has been moved one unit toward the end
351 ++m_selection;
352 if ( m_actualSelection != wxNOT_FOUND )
353 ++m_actualSelection;
354 }
355 else if ( m_actualSelection != wxNOT_FOUND &&
356 newPos <= (size_t)m_actualSelection )
357 {
358 DoSetSelection(m_selection);
359 }
360 }
361 }
362
363 void wxTreebook::DoInternalRemovePageRange(size_t pagePos, size_t subCount)
364 {
365 // Attention: this function is only for a situation when we delete a node
366 // with all its children so pagePos is the node's index and subCount is the
367 // node children count
368 wxASSERT_MSG( pagePos + subCount < m_treeIds.GetCount(),
369 wxT("Ivalid page index") );
370
371 wxTreeItemId pageId = m_treeIds[pagePos];
372
373 m_treeIds.RemoveAt(pagePos, subCount + 1);
374
375 if ( m_selection != wxNOT_FOUND )
376 {
377 if ( (size_t)m_selection > pagePos + subCount)
378 {
379 // selection is far after the deleted page, so just update the index and move on
380 m_selection -= 1 + subCount;
381 if ( m_actualSelection != wxNOT_FOUND)
382 {
383 m_actualSelection -= subCount + 1;
384 }
385 }
386 else if ( (size_t)m_selection >= pagePos )
387 {
388 wxTreeCtrl *tree = GetTreeCtrl();
389
390 // as selected page is going to be deleted, try to select the next
391 // sibling if exists, if not then the parent
392 wxTreeItemId nodeId = tree->GetNextSibling(pageId);
393
394 m_selection = wxNOT_FOUND;
395 m_actualSelection = wxNOT_FOUND;
396
397 if ( nodeId.IsOk() )
398 {
399 // selecting next siblings
400 tree->SelectItem(nodeId);
401 }
402 else // no next sibling, select the parent
403 {
404 wxTreeItemId parentId = tree->GetItemParent(pageId);
405
406 if ( parentId.IsOk() && parentId != tree->GetRootItem() )
407 {
408 tree->SelectItem(parentId);
409 }
410 else // parent is root
411 {
412 // we can't select it as it's hidden
413 DoUpdateSelection(false, wxNOT_FOUND);
414 }
415 }
416 }
417 else if ( m_actualSelection != wxNOT_FOUND &&
418 (size_t)m_actualSelection >= pagePos )
419 {
420 // nothing to do -- selection is before the deleted node, but
421 // actually shown page (the first (sub)child with page != NULL) is
422 // already deleted
423 m_actualSelection = m_selection;
424 DoSetSelection(m_selection);
425 }
426 //else: nothing to do -- selection is before the deleted node
427 }
428 else
429 {
430 DoUpdateSelection(false, wxNOT_FOUND);
431 }
432 }
433
434
435 void wxTreebook::DoUpdateSelection(bool bSelect, int newPos)
436 {
437 int newSelPos;
438 if ( bSelect )
439 {
440 newSelPos = newPos;
441 }
442 else if ( m_selection == wxNOT_FOUND && DoInternalGetPageCount() > 0 )
443 {
444 newSelPos = 0;
445 }
446 else
447 {
448 newSelPos = wxNOT_FOUND;
449 }
450
451 if ( newSelPos != wxNOT_FOUND )
452 {
453 SetSelection((size_t)newSelPos);
454 }
455 }
456
457 wxTreeItemId wxTreebook::DoInternalGetPage(size_t pagePos) const
458 {
459 if ( pagePos >= m_treeIds.GetCount() )
460 {
461 // invalid position but ok here, in this internal function, don't assert
462 // (the caller will do it)
463 return wxTreeItemId();
464 }
465
466 return m_treeIds[pagePos];
467 }
468
469 int wxTreebook::DoInternalFindPageById(wxTreeItemId pageId) const
470 {
471 const size_t count = m_treeIds.GetCount();
472 for ( size_t i = 0; i < count; ++i )
473 {
474 if ( m_treeIds[i] == pageId )
475 return i;
476 }
477
478 return wxNOT_FOUND;
479 }
480
481 bool wxTreebook::IsNodeExpanded(size_t pagePos) const
482 {
483 wxTreeItemId pageId = DoInternalGetPage(pagePos);
484
485 wxCHECK_MSG( pageId.IsOk(), false, wxT("invalid tree item") );
486
487 return GetTreeCtrl()->IsExpanded(pageId);
488 }
489
490 bool wxTreebook::ExpandNode(size_t pagePos, bool expand)
491 {
492 wxTreeItemId pageId = DoInternalGetPage(pagePos);
493
494 wxCHECK_MSG( pageId.IsOk(), false, wxT("invalid tree item") );
495
496 if ( expand )
497 {
498 GetTreeCtrl()->Expand( pageId );
499 }
500 else // collapse
501 {
502 GetTreeCtrl()->Collapse( pageId );
503
504 // rely on the events generated by wxTreeCtrl to update selection
505 }
506
507 return true;
508 }
509
510 int wxTreebook::GetPageParent(size_t pagePos) const
511 {
512 wxTreeItemId nodeId = DoInternalGetPage( pagePos );
513 wxCHECK_MSG( nodeId.IsOk(), wxNOT_FOUND, wxT("Invalid page index spacified!") );
514
515 const wxTreeItemId parent = GetTreeCtrl()->GetItemParent( nodeId );
516
517 return parent.IsOk() ? DoInternalFindPageById(parent) : wxNOT_FOUND;
518 }
519
520 bool wxTreebook::SetPageText(size_t n, const wxString& strText)
521 {
522 wxTreeItemId pageId = DoInternalGetPage(n);
523
524 wxCHECK_MSG( pageId.IsOk(), false, wxT("invalid tree item") );
525
526 GetTreeCtrl()->SetItemText(pageId, strText);
527
528 return true;
529 }
530
531 wxString wxTreebook::GetPageText(size_t n) const
532 {
533 wxTreeItemId pageId = DoInternalGetPage(n);
534
535 wxCHECK_MSG( pageId.IsOk(), wxString(), wxT("invalid tree item") );
536
537 return GetTreeCtrl()->GetItemText(pageId);
538 }
539
540 int wxTreebook::GetPageImage(size_t n) const
541 {
542 wxTreeItemId pageId = DoInternalGetPage(n);
543
544 wxCHECK_MSG( pageId.IsOk(), wxNOT_FOUND, wxT("invalid tree item") );
545
546 return GetTreeCtrl()->GetItemImage(pageId);
547 }
548
549 bool wxTreebook::SetPageImage(size_t n, int imageId)
550 {
551 wxTreeItemId pageId = DoInternalGetPage(n);
552
553 wxCHECK_MSG( pageId.IsOk(), false, wxT("invalid tree item") );
554
555 GetTreeCtrl()->SetItemImage(pageId, imageId);
556
557 return true;
558 }
559
560 wxSize wxTreebook::CalcSizeFromPage(const wxSize& sizePage) const
561 {
562 const wxSize sizeTree = GetControllerSize();
563
564 wxSize size = sizePage;
565 size.x += sizeTree.x;
566
567 return size;
568 }
569
570 int wxTreebook::GetSelection() const
571 {
572 return m_selection;
573 }
574
575 int wxTreebook::SetSelection(size_t pagePos)
576 {
577 if ( (size_t)m_selection != pagePos )
578 return DoSetSelection(pagePos);
579
580 return m_selection;
581 }
582
583 int wxTreebook::DoSetSelection(size_t pagePos)
584 {
585 wxCHECK_MSG( IS_VALID_PAGE(pagePos), wxNOT_FOUND,
586 wxT("invalid page index in wxListbook::SetSelection()") );
587 wxASSERT_MSG( GetPageCount() == DoInternalGetPageCount(),
588 wxT("wxTreebook logic error: m_treeIds and m_pages not in sync!"));
589
590 const int oldSel = m_selection;
591 wxTreeCtrl *tree = GetTreeCtrl();
592
593 wxTreebookEvent event(wxEVT_COMMAND_TREEBOOK_PAGE_CHANGING, m_windowId);
594 event.SetEventObject(this);
595 event.SetSelection(pagePos);
596 event.SetOldSelection(m_selection);
597
598 // don't send the event if the old and new pages are the same; do send it
599 // otherwise and be prepared for it to be vetoed
600 if ( (int)pagePos == m_selection ||
601 !GetEventHandler()->ProcessEvent(event) ||
602 event.IsAllowed() )
603 {
604 // hide the previously shown page
605 wxTreebookPage * const oldPage = DoGetCurrentPage();
606 if ( oldPage )
607 oldPage->Hide();
608
609 // then show the new one
610 m_selection = pagePos;
611 wxTreebookPage *page = wxBookCtrlBase::GetPage(m_selection);
612 if ( !page )
613 {
614 // find the next page suitable to be shown: the first (grand)child
615 // of this one with a non-NULL associated page
616 wxTreeItemId childId = m_treeIds[pagePos];
617 int actualPagePos = pagePos;
618 while ( !page && childId.IsOk() )
619 {
620 wxTreeItemIdValue cookie;
621 childId = tree->GetFirstChild( childId, cookie );
622 if ( childId.IsOk() )
623 {
624 page = wxBookCtrlBase::GetPage(++actualPagePos);
625 }
626 }
627
628 m_actualSelection = page ? actualPagePos : m_selection;
629 }
630
631 if ( page )
632 page->Show();
633
634 tree->SelectItem(DoInternalGetPage(pagePos));
635
636 // notify about the (now completed) page change
637 event.SetEventType(wxEVT_COMMAND_TREEBOOK_PAGE_CHANGED);
638 (void)GetEventHandler()->ProcessEvent(event);
639 }
640 else // page change vetoed
641 {
642 // tree selection might have already had changed
643 tree->SelectItem(DoInternalGetPage(oldSel));
644 }
645
646 return oldSel;
647 }
648
649 void wxTreebook::SetImageList(wxImageList *imageList)
650 {
651 wxBookCtrlBase::SetImageList(imageList);
652 GetTreeCtrl()->SetImageList(imageList);
653 }
654
655 void wxTreebook::AssignImageList(wxImageList *imageList)
656 {
657 wxBookCtrlBase::AssignImageList(imageList);
658 GetTreeCtrl()->SetImageList(imageList);
659 }
660
661 // ----------------------------------------------------------------------------
662 // event handlers
663 // ----------------------------------------------------------------------------
664
665 void wxTreebook::OnTreeSelectionChange(wxTreeEvent& event)
666 {
667 wxTreeItemId newId = event.GetItem();
668
669 if ( (m_selection == wxNOT_FOUND &&
670 (!newId.IsOk() || newId == GetTreeCtrl()->GetRootItem())) ||
671 (m_selection != wxNOT_FOUND && newId == m_treeIds[m_selection]) )
672 {
673 // this event can only come when we modify the tree selection ourselves
674 // so we should simply ignore it
675 return;
676 }
677
678 int newPos = DoInternalFindPageById(newId);
679
680 if ( newPos != wxNOT_FOUND )
681 SetSelection( newPos );
682 }
683
684 void wxTreebook::OnTreeNodeExpandedCollapsed(wxTreeEvent & event)
685 {
686 wxTreeItemId nodeId = event.GetItem();
687 if ( !nodeId.IsOk() || nodeId == GetTreeCtrl()->GetRootItem() )
688 return;
689 int pagePos = DoInternalFindPageById(nodeId);
690 wxCHECK_RET( pagePos != wxNOT_FOUND, wxT("Internal problem in wxTreebook!..") );
691
692 wxTreebookEvent ev(GetTreeCtrl()->IsExpanded(nodeId)
693 ? wxEVT_COMMAND_TREEBOOK_NODE_EXPANDED
694 : wxEVT_COMMAND_TREEBOOK_NODE_COLLAPSED,
695 m_windowId);
696
697 ev.SetSelection(pagePos);
698 ev.SetOldSelection(pagePos);
699 ev.SetEventObject(this);
700
701 GetEventHandler()->ProcessEvent(ev);
702 }
703
704 // ----------------------------------------------------------------------------
705 // wxTreebook geometry management
706 // ----------------------------------------------------------------------------
707
708 wxTreebookPage * wxTreebook::DoGetCurrentPage() const
709 {
710 if ( m_selection == wxNOT_FOUND )
711 return NULL;
712
713 wxTreebookPage *page = wxBookCtrlBase::GetPage(m_selection);
714 if ( !page && m_actualSelection != wxNOT_FOUND )
715 {
716 page = wxBookCtrlBase::GetPage(m_actualSelection);
717 }
718
719 return page;
720 }
721
722 #endif // wxUSE_TREEBOOK