invalidate tree size after adding/removing pages; use portable style for the tree...
[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, wxControl)
45 IMPLEMENT_DYNAMIC_CLASS(wxTreebookEvent, wxNotifyEvent)
46
47 const wxEventType wxEVT_COMMAND_TREEBOOK_PAGE_CHANGING = wxNewEventType();
48 const wxEventType wxEVT_COMMAND_TREEBOOK_PAGE_CHANGED = wxNewEventType();
49 const wxEventType wxEVT_COMMAND_TREEBOOK_NODE_COLLAPSED = wxNewEventType();
50 const wxEventType wxEVT_COMMAND_TREEBOOK_NODE_EXPANDED = wxNewEventType();
51 const int wxID_TREEBOOKTREEVIEW = wxNewId();
52
53 BEGIN_EVENT_TABLE(wxTreebook, wxBookCtrlBase)
54 EVT_SIZE(wxTreebook::OnSize)
55 EVT_TREE_SEL_CHANGED (wxID_TREEBOOKTREEVIEW, wxTreebook::OnTreeSelectionChange)
56 EVT_TREE_ITEM_EXPANDED (wxID_TREEBOOKTREEVIEW, wxTreebook::OnTreeNodeExpandedCollapsed)
57 EVT_TREE_ITEM_COLLAPSED(wxID_TREEBOOKTREEVIEW, wxTreebook::OnTreeNodeExpandedCollapsed)
58 END_EVENT_TABLE()
59
60 // ============================================================================
61 // wxTreebook implementation
62 // ============================================================================
63
64 // ----------------------------------------------------------------------------
65 // wxTreebook creation
66 // ----------------------------------------------------------------------------
67
68 void wxTreebook::Init()
69 {
70 m_tree = NULL;
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 & wxTBK_RIGHT )
85 {
86 wxASSERT_MSG( !(style & wxTBK_LEFT),
87 _T("RIGHT and LEFT can't be used together") );
88 }
89 else
90 {
91 style |= wxTBK_LEFT;
92 }
93
94 // no border for this control, it doesn't look nice together with the tree
95 style &= ~wxBORDER_MASK;
96 style |= wxBORDER_NONE;
97
98 if ( !wxControl::Create(parent, id, pos, size,
99 style, wxDefaultValidator, name) )
100 return false;
101
102 m_tree = new wxTreeCtrl
103 (
104 this,
105 wxID_TREEBOOKTREEVIEW,
106 wxDefaultPosition,
107 wxDefaultSize,
108 wxBORDER_SIMPLE |
109 wxTR_DEFAULT_STYLE |
110 wxTR_HIDE_ROOT |
111 wxTR_SINGLE
112 );
113 m_tree->AddRoot(wxEmptyString); // label doesn't matter, it's hidden
114
115 #ifdef __WXMSW__
116 // see listbook.h for origins of that
117 // On XP with themes enabled the GetViewRect used in GetListSize to
118 // determine the space needed for the list view will incorrectly return
119 // (0,0,0,0) the first time. So send a pending event so OnSize will be
120 // called again after the window is ready to go. Technically we don't
121 // need to do this on non-XP windows, but if things are already sized
122 // correctly then nothing changes and so there is no harm.
123 wxSizeEvent evt;
124 GetEventHandler()->AddPendingEvent(evt);
125 #endif
126
127 return true;
128 }
129
130
131 // insert a new page just before the pagePos
132 bool wxTreebook::InsertPage(size_t pagePos,
133 wxWindow *page,
134 const wxString& text,
135 bool bSelect,
136 int imageId)
137 {
138 return DoInsertPage(pagePos, page, text, bSelect, imageId);
139 }
140
141 bool wxTreebook::AddSubPage(size_t pagePos,
142 wxWindow *page,
143 const wxString& text,
144 bool bSelect,
145 int imageId)
146 {
147 return DoInsertSubPage(pagePos, page, text, bSelect, imageId);
148 }
149
150 bool wxTreebook::AddPage(wxWindow *page, const wxString& text, bool bSelect,
151 int imageId)
152 {
153 return DoInsertPage(m_treeIds.GetCount(), page, text, bSelect, imageId);
154 }
155
156 // insertion time is linear to the number of top-pages
157 bool wxTreebook::AddSubPage(wxWindow *page, const wxString& text, bool bSelect, int imageId)
158 {
159 return DoAddSubPage(page, text, bSelect, imageId);
160 }
161
162
163 bool wxTreebook::DoInsertPage(size_t pagePos,
164 wxWindow *page,
165 const wxString& text,
166 bool bSelect,
167 int imageId)
168 {
169 wxCHECK_MSG( pagePos <= DoInternalGetPageCount(), false,
170 wxT("Invalid treebook page position") );
171
172 if ( !wxBookCtrlBase::InsertPage(pagePos, page, text, bSelect, imageId) )
173 return false;
174
175 wxTreeItemId newId;
176 if ( pagePos == DoInternalGetPageCount() )
177 {
178 // append the page to the end
179 wxTreeItemId rootId = m_tree->GetRootItem();
180
181 newId = m_tree->AppendItem(rootId, text, imageId);
182 }
183 else // insert the new page before the given one
184 {
185 wxTreeItemId nodeId = m_treeIds[pagePos];
186
187 wxTreeItemId previousId = m_tree->GetPrevSibling(nodeId);
188 wxTreeItemId parentId = m_tree->GetItemParent(nodeId);
189
190 if ( previousId.IsOk() )
191 {
192 // insert before the sibling - previousId
193 newId = m_tree->InsertItem(parentId, previousId, text, imageId);
194 }
195 else // no prev siblings -- insert as a first child
196 {
197 wxASSERT_MSG( parentId.IsOk(), wxT( "Tree has no root node?" ) );
198
199 newId = m_tree->PrependItem(parentId, text, imageId);
200 }
201 }
202
203 if ( !newId.IsOk() )
204 {
205 //something wrong -> cleaning and returning with false
206 (void)wxBookCtrlBase::DoRemovePage(pagePos);
207
208 wxFAIL_MSG( wxT("Failed to insert treebook page") );
209 return false;
210 }
211
212 DoInternalAddPage(pagePos, page, newId);
213
214 DoUpdateSelection(bSelect, pagePos);
215
216 m_tree->InvalidateBestSize();
217
218 return true;
219 }
220
221 bool wxTreebook::DoAddSubPage(wxWindow *page, const wxString& text, bool bSelect, int imageId)
222 {
223 wxTreeItemId rootId = m_tree->GetRootItem();
224
225 wxTreeItemId lastNodeId = m_tree->GetLastChild(rootId);
226
227 wxCHECK_MSG( lastNodeId.IsOk(), false,
228 _T("Can't insert sub page when there are no pages") );
229
230 // now calculate its position (should we save/update it too?)
231 size_t newPos = m_tree->GetCount() -
232 (m_tree->GetChildrenCount(lastNodeId, true) + 1);
233
234 return DoInsertSubPage(newPos, page, text, bSelect, imageId);
235 }
236
237 bool wxTreebook::DoInsertSubPage(size_t pagePos,
238 wxTreebookPage *page,
239 const wxString& text,
240 bool bSelect,
241 int imageId)
242 {
243 wxTreeItemId parentId = DoInternalGetPage(pagePos);
244 wxCHECK_MSG( parentId.IsOk(), false, wxT("invalid tree item") );
245
246 size_t newPos = pagePos + m_tree->GetChildrenCount(parentId, true) + 1;
247 wxASSERT_MSG( newPos <= DoInternalGetPageCount(),
248 wxT("Internal error in tree insert point calculation") );
249
250 if ( !wxBookCtrlBase::InsertPage(newPos, page, text, bSelect, imageId) )
251 return false;
252
253 wxTreeItemId newId = m_tree->AppendItem(parentId, text, imageId);
254
255 if ( !newId.IsOk() )
256 {
257 (void)wxBookCtrlBase::DoRemovePage(newPos);
258
259 wxFAIL_MSG( wxT("Failed to insert treebook page") );
260 return false;
261 }
262
263 DoInternalAddPage(newPos, page, newId);
264
265 DoUpdateSelection(bSelect, newPos);
266
267 m_tree->InvalidateBestSize();
268
269 return true;
270 }
271
272 bool wxTreebook::DeletePage(size_t pagePos)
273 {
274 wxCHECK_MSG( IS_VALID_PAGE(pagePos), false, wxT("Invalid tree index") );
275
276 wxTreebookPage *oldPage = DoRemovePage(pagePos);
277 if ( !oldPage )
278 return false;
279
280 delete oldPage;
281
282 return true;
283 }
284
285 wxTreebookPage *wxTreebook::DoRemovePage(size_t pagePos)
286 {
287 wxTreeItemId pageId = DoInternalGetPage(pagePos);
288 wxCHECK_MSG( pageId.IsOk(), NULL, wxT("Invalid tree index") );
289
290 wxTreebookPage * oldPage = GetPage(pagePos);
291
292 size_t subCount = m_tree->GetChildrenCount(pageId, true);
293 wxASSERT_MSG ( IS_VALID_PAGE(pagePos + subCount),
294 wxT("Internal error in wxTreebook::DoRemovePage") );
295
296 // here we are going to delete ALL the pages in the range
297 // [pagePos, pagePos + subCount] -- the page and its children
298
299 // deleting all the pages from the base class
300 for ( size_t i = 0; i <= subCount; ++i )
301 {
302 wxTreebookPage *page = wxBookCtrlBase::DoRemovePage(pagePos);
303
304 // don't delete the page itself though -- it will be deleted in
305 // DeletePage() when we return
306 if ( i )
307 {
308 delete page;
309 }
310 }
311
312 DoInternalRemovePageRange(pagePos, subCount);
313
314 m_tree->DeleteChildren( pageId );
315 m_tree->Delete( pageId );
316 m_tree->InvalidateBestSize();
317
318 return oldPage;
319 }
320
321 bool wxTreebook::DeleteAllPages()
322 {
323 wxBookCtrlBase::DeleteAllPages();
324 m_treeIds.Clear();
325 m_selection =
326 m_actualSelection = wxNOT_FOUND;
327
328 m_tree->DeleteChildren(m_tree->GetRootItem());
329
330 return true;
331 }
332
333 void wxTreebook::DoInternalAddPage(size_t newPos,
334 wxTreebookPage *page,
335 wxTreeItemId pageId)
336 {
337 wxASSERT_MSG( newPos <= m_treeIds.GetCount(), wxT("Ivalid index passed to wxTreebook::DoInternalAddPage") );
338
339 // hide newly inserted page initially (it will be shown when selected)
340 if ( page )
341 page->Hide();
342
343 if ( newPos == m_treeIds.GetCount() )
344 {
345 // append
346 m_treeIds.Add(pageId);
347 }
348 else // insert
349 {
350 m_treeIds.Insert(pageId, newPos);
351
352 if ( m_selection != wxNOT_FOUND && newPos <= (size_t)m_selection )
353 {
354 // selection has been moved one unit toward the end
355 ++m_selection;
356 if ( m_actualSelection != wxNOT_FOUND )
357 ++m_actualSelection;
358 }
359 else if ( m_actualSelection != wxNOT_FOUND &&
360 newPos <= (size_t)m_actualSelection )
361 {
362 DoSetSelection(m_selection);
363 }
364 }
365 }
366
367 void wxTreebook::DoInternalRemovePageRange(size_t pagePos, size_t subCount)
368 {
369 // Attention: this function is only for a situation when we delete a node
370 // with all its children so pagePos is the node's index and subCount is the
371 // node children count
372 wxASSERT_MSG( pagePos + subCount < m_treeIds.GetCount(),
373 wxT("Ivalid page index") );
374
375 wxTreeItemId pageId = m_treeIds[pagePos];
376
377 m_treeIds.RemoveAt(pagePos, subCount + 1);
378
379 if ( m_selection != wxNOT_FOUND )
380 {
381 if ( (size_t)m_selection > pagePos + subCount)
382 {
383 // selection is far after the deleted page, so just update the index and move on
384 m_selection -= 1 + subCount;
385 if ( m_actualSelection != wxNOT_FOUND)
386 {
387 m_actualSelection -= subCount + 1;
388 }
389 }
390 else if ( (size_t)m_selection >= pagePos )
391 {
392 // as selected page is going to be deleted, try to select the next
393 // sibling if exists, if not then the parent
394 wxTreeItemId nodeId = m_tree->GetNextSibling(pageId);
395
396 m_selection = wxNOT_FOUND;
397 m_actualSelection = wxNOT_FOUND;
398
399 if ( nodeId.IsOk() )
400 {
401 // selecting next siblings
402 m_tree->SelectItem(nodeId);
403 }
404 else // no next sibling, select the parent
405 {
406 wxTreeItemId parentId = m_tree->GetItemParent(pageId);
407
408 if ( parentId.IsOk() && parentId != m_tree->GetRootItem() )
409 {
410 m_tree->SelectItem(parentId);
411 }
412 else // parent is root
413 {
414 // we can't select it as it's hidden
415 DoUpdateSelection(false, wxNOT_FOUND);
416 }
417 }
418 }
419 else if ( m_actualSelection != wxNOT_FOUND &&
420 (size_t)m_actualSelection >= pagePos )
421 {
422 // nothing to do -- selection is before the deleted node, but
423 // actually shown page (the first (sub)child with page != NULL) is
424 // already deleted
425 m_actualSelection = m_selection;
426 DoSetSelection(m_selection);
427 }
428 //else: nothing to do -- selection is before the deleted node
429 }
430 else
431 {
432 DoUpdateSelection(false, wxNOT_FOUND);
433 }
434 }
435
436
437 void wxTreebook::DoUpdateSelection(bool bSelect, int newPos)
438 {
439 int newSelPos;
440 if ( bSelect )
441 {
442 newSelPos = newPos;
443 }
444 else if ( m_selection == wxNOT_FOUND && DoInternalGetPageCount() > 0 )
445 {
446 newSelPos = 0;
447 }
448 else
449 {
450 newSelPos = wxNOT_FOUND;
451 }
452
453 if ( newSelPos != wxNOT_FOUND )
454 {
455 SetSelection((size_t)newSelPos);
456 }
457 }
458
459 wxTreeItemId wxTreebook::DoInternalGetPage(size_t pagePos) const
460 {
461 if ( pagePos >= m_treeIds.GetCount() )
462 {
463 // invalid position but ok here, in this internal function, don't assert
464 // (the caller will do it)
465 return wxTreeItemId();
466 }
467
468 return m_treeIds[pagePos];
469 }
470
471 int wxTreebook::DoInternalFindPageById(wxTreeItemId pageId) const
472 {
473 const size_t count = m_treeIds.GetCount();
474 for ( size_t i = 0; i < count; ++i )
475 {
476 if ( m_treeIds[i] == pageId )
477 return i;
478 }
479
480 return wxNOT_FOUND;
481 }
482
483 bool wxTreebook::IsNodeExpanded(size_t pagePos) const
484 {
485 wxTreeItemId pageId = DoInternalGetPage(pagePos);
486
487 wxCHECK_MSG( pageId.IsOk(), false, wxT("invalid tree item") );
488
489 return m_tree->IsExpanded(pageId);
490 }
491
492 bool wxTreebook::ExpandNode(size_t pagePos, bool expand)
493 {
494 wxTreeItemId pageId = DoInternalGetPage(pagePos);
495
496 wxCHECK_MSG( pageId.IsOk(), false, wxT("invalid tree item") );
497
498 if ( expand )
499 {
500 m_tree->Expand( pageId );
501 }
502 else // collapse
503 {
504 m_tree->Collapse( pageId );
505
506 // rely on the events generated by wxTreeCtrl to update selection
507 }
508
509 return true;
510 }
511
512 int wxTreebook::GetPageParent(size_t pagePos) const
513 {
514 wxTreeItemId nodeId = DoInternalGetPage( pagePos );
515 wxCHECK_MSG( nodeId.IsOk(), wxNOT_FOUND, wxT("Invalid page index spacified!") );
516
517 const wxTreeItemId parent = m_tree->GetItemParent( nodeId );
518
519 return parent.IsOk() ? DoInternalFindPageById(parent) : wxNOT_FOUND;
520 }
521
522 bool wxTreebook::SetPageText(size_t n, const wxString& strText)
523 {
524 wxTreeItemId pageId = DoInternalGetPage(n);
525
526 wxCHECK_MSG( pageId.IsOk(), false, wxT("invalid tree item") );
527
528 m_tree->SetItemText(pageId, strText);
529
530 return true;
531 }
532
533 wxString wxTreebook::GetPageText(size_t n) const
534 {
535 wxTreeItemId pageId = DoInternalGetPage(n);
536
537 wxCHECK_MSG( pageId.IsOk(), wxString(), wxT("invalid tree item") );
538
539 return m_tree->GetItemText(pageId);
540 }
541
542 int wxTreebook::GetPageImage(size_t n) const
543 {
544 wxTreeItemId pageId = DoInternalGetPage(n);
545
546 wxCHECK_MSG( pageId.IsOk(), wxNOT_FOUND, wxT("invalid tree item") );
547
548 return m_tree->GetItemImage(pageId);
549 }
550
551 bool wxTreebook::SetPageImage(size_t n, int imageId)
552 {
553 wxTreeItemId pageId = DoInternalGetPage(n);
554
555 wxCHECK_MSG( pageId.IsOk(), false, wxT("invalid tree item") );
556
557 m_tree->SetItemImage(pageId, imageId);
558
559 return true;
560 }
561
562 wxSize wxTreebook::CalcSizeFromPage(const wxSize& sizePage) const
563 {
564 const wxSize sizeTree = GetTreeSize();
565
566 wxSize size = sizePage;
567 size.x += sizeTree.x;
568
569 return size;
570 }
571
572 int wxTreebook::GetSelection() const
573 {
574 return m_selection;
575 }
576
577 int wxTreebook::SetSelection(size_t pagePos)
578 {
579 if ( (size_t)m_selection != pagePos )
580 return DoSetSelection(pagePos);
581
582 return m_selection;
583 }
584
585 int wxTreebook::DoSetSelection(size_t pagePos)
586 {
587 wxCHECK_MSG( IS_VALID_PAGE(pagePos), wxNOT_FOUND,
588 wxT("invalid page index in wxListbook::SetSelection()") );
589 wxASSERT_MSG( GetPageCount() == DoInternalGetPageCount(),
590 wxT("wxTreebook logic error: m_treeIds and m_pages not in sync!"));
591
592 const int oldSel = m_selection;
593
594 wxTreebookEvent event(wxEVT_COMMAND_TREEBOOK_PAGE_CHANGING, m_windowId);
595 event.SetEventObject(this);
596 event.SetSelection(pagePos);
597 event.SetOldSelection(m_selection);
598
599 // don't send the event if the old and new pages are the same; do send it
600 // otherwise and be prepared for it to be vetoed
601 if ( (int)pagePos == m_selection ||
602 !GetEventHandler()->ProcessEvent(event) ||
603 event.IsAllowed() )
604 {
605 // hide the previously shown page
606 wxTreebookPage * const oldPage = DoGetCurrentPage();
607 if ( oldPage )
608 oldPage->Hide();
609
610 // then show the new one
611 m_selection = pagePos;
612 wxTreebookPage *page = wxBookCtrlBase::GetPage(m_selection);
613 if ( !page )
614 {
615 // find the next page suitable to be shown: the first (grand)child
616 // of this one with a non-NULL associated page
617 wxTreeItemId childId = m_treeIds[pagePos];
618 m_actualSelection = pagePos;
619 while ( !page && childId.IsOk() )
620 {
621 wxTreeItemIdValue cookie;
622 childId = m_tree->GetFirstChild( childId, cookie );
623 if ( childId.IsOk() )
624 {
625 page = wxBookCtrlBase::GetPage(++m_actualSelection);
626 }
627 }
628
629 wxASSERT_MSG( page, wxT("no page to show found!") );
630 }
631
632 if ( page )
633 {
634 page->SetSize(GetPageRect());
635 page->Show();
636 }
637
638 m_tree->SelectItem(DoInternalGetPage(pagePos));
639
640 // notify about the (now completed) page change
641 event.SetEventType(wxEVT_COMMAND_TREEBOOK_PAGE_CHANGED);
642 (void)GetEventHandler()->ProcessEvent(event);
643 }
644 else // page change vetoed
645 {
646 // tree selection might have already had changed
647 m_tree->SelectItem(DoInternalGetPage(oldSel));
648 }
649
650 return oldSel;
651 }
652
653 void wxTreebook::SetImageList(wxImageList *imageList)
654 {
655 wxBookCtrlBase::SetImageList(imageList);
656 m_tree->SetImageList(imageList);
657 }
658
659 void wxTreebook::AssignImageList(wxImageList *imageList)
660 {
661 wxBookCtrlBase::AssignImageList(imageList);
662 m_tree->SetImageList(imageList);
663 }
664
665 // ----------------------------------------------------------------------------
666 // event handlers
667 // ----------------------------------------------------------------------------
668
669 void wxTreebook::OnTreeSelectionChange(wxTreeEvent& event)
670 {
671 wxTreeItemId newId = event.GetItem();
672
673 if ( (m_selection == wxNOT_FOUND &&
674 (!newId.IsOk() || newId == m_tree->GetRootItem())) ||
675 (m_selection != wxNOT_FOUND && newId == m_treeIds[m_selection]) )
676 {
677 // this event can only come when we modify the tree selection ourselves
678 // so we should simply ignore it
679 return;
680 }
681
682 int newPos = DoInternalFindPageById(newId);
683
684 if ( newPos != wxNOT_FOUND )
685 SetSelection( newPos );
686 }
687
688 void wxTreebook::OnTreeNodeExpandedCollapsed(wxTreeEvent & event)
689 {
690 wxTreeItemId nodeId = event.GetItem();
691 if ( !nodeId.IsOk() || nodeId == m_tree->GetRootItem() )
692 return;
693 int pagePos = DoInternalFindPageById(nodeId);
694 wxCHECK_RET( pagePos != wxNOT_FOUND, wxT("Internal problem in wxTreebook!..") );
695
696 wxTreebookEvent ev(m_tree->IsExpanded(nodeId)
697 ? wxEVT_COMMAND_TREEBOOK_NODE_EXPANDED
698 : wxEVT_COMMAND_TREEBOOK_NODE_COLLAPSED,
699 m_windowId);
700
701 ev.SetSelection(pagePos);
702 ev.SetOldSelection(pagePos);
703 ev.SetEventObject(this);
704
705 GetEventHandler()->ProcessEvent(ev);
706 }
707
708 // ----------------------------------------------------------------------------
709 // wxTreebook geometry management
710 // ----------------------------------------------------------------------------
711
712 wxSize wxTreebook::GetTreeSize() const
713 {
714 const wxSize sizeClient = GetClientSize(),
715 sizeBorder = m_tree->GetSize() - m_tree->GetClientSize(),
716 sizeTree = m_tree->GetBestSize() + sizeBorder;
717
718 wxSize size;
719
720 size.x = sizeTree.x;
721 size.y = sizeClient.y;
722
723 return size;
724 }
725
726 wxRect wxTreebook::GetPageRect() const
727 {
728 const wxSize sizeTree = m_tree->GetSize();
729
730 wxPoint pt;
731 wxRect rectPage(pt, GetClientSize());
732 switch ( GetWindowStyle() & wxTBK_ALIGN_MASK )
733 {
734 default:
735 wxFAIL_MSG( _T("unexpected wxTreebook alignment") );
736 // fall through
737
738 case wxTBK_LEFT:
739 rectPage.x = sizeTree.x; // + MARGIN;
740 // fall through
741
742 case wxTBK_RIGHT:
743 rectPage.width -= sizeTree.x; // + MARGIN;
744 break;
745 }
746
747 return rectPage;
748 }
749
750 void wxTreebook::OnSize(wxSizeEvent& event)
751 {
752 event.Skip();
753
754 if ( !m_tree )
755 {
756 // we're not fully created yet
757 return;
758 }
759
760 // resize the list control and the page area to fit inside our new size
761 const wxSize sizeClient = GetClientSize(),
762 sizeBorder = m_tree->GetSize() - m_tree->GetClientSize(),
763 sizeTree = GetTreeSize();
764
765 m_tree->SetClientSize( sizeTree.x - sizeBorder.x, sizeTree.y - sizeBorder.y );
766
767 const wxSize sizeNew = m_tree->GetSize();
768 wxPoint posTree;
769 switch ( GetWindowStyle() & wxTBK_ALIGN_MASK )
770 {
771 default:
772 wxFAIL_MSG( _T("unexpected wxTreebook alignment") );
773 // fall through
774
775 case wxTBK_LEFT:
776 // posTree is already ok
777 break;
778
779 case wxTBK_RIGHT:
780 posTree.x = sizeClient.x - sizeNew.x;
781 break;
782 }
783
784 if ( m_tree->GetPosition() != posTree )
785 m_tree->Move(posTree);
786
787 // resize the currently shown page
788 wxTreebookPage *page = DoGetCurrentPage();
789 if ( page )
790 {
791 wxRect rectPage = GetPageRect();
792 page->SetSize(rectPage);
793 }
794 }
795
796 wxTreebookPage * wxTreebook::DoGetCurrentPage() const
797 {
798 if ( m_selection == wxNOT_FOUND )
799 return NULL;
800
801 wxTreebookPage *page = wxBookCtrlBase::GetPage(m_selection);
802 if ( !page && m_actualSelection != wxNOT_FOUND )
803 {
804 page = wxBookCtrlBase::GetPage(m_actualSelection);
805 }
806
807 return page;
808 }
809
810 #endif // wxUSE_TREEBOOK
811