Fixed wxTreebook tree control style
[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
31 #ifndef WX_PRECOMP
32 #include "wx/settings.h"
33 #endif
34
35 #include "wx/imaglist.h"
36
37 // ----------------------------------------------------------------------------
38 // various wxWidgets macros
39 // ----------------------------------------------------------------------------
40
41 // check that the page index is valid
42 #define IS_VALID_PAGE(nPage) ((nPage) < DoInternalGetPageCount())
43
44 // ----------------------------------------------------------------------------
45 // event table
46 // ----------------------------------------------------------------------------
47
48 IMPLEMENT_DYNAMIC_CLASS(wxTreebook, wxBookCtrlBase)
49 IMPLEMENT_DYNAMIC_CLASS(wxTreebookEvent, wxNotifyEvent)
50
51 const wxEventType wxEVT_COMMAND_TREEBOOK_PAGE_CHANGING = wxNewEventType();
52 const wxEventType wxEVT_COMMAND_TREEBOOK_PAGE_CHANGED = wxNewEventType();
53 const wxEventType wxEVT_COMMAND_TREEBOOK_NODE_COLLAPSED = wxNewEventType();
54 const wxEventType wxEVT_COMMAND_TREEBOOK_NODE_EXPANDED = wxNewEventType();
55
56 BEGIN_EVENT_TABLE(wxTreebook, wxBookCtrlBase)
57 EVT_TREE_SEL_CHANGED (wxID_ANY, wxTreebook::OnTreeSelectionChange)
58 EVT_TREE_ITEM_EXPANDED (wxID_ANY, wxTreebook::OnTreeNodeExpandedCollapsed)
59 EVT_TREE_ITEM_COLLAPSED(wxID_ANY, wxTreebook::OnTreeNodeExpandedCollapsed)
60 END_EVENT_TABLE()
61
62 // ============================================================================
63 // wxTreebook implementation
64 // ============================================================================
65
66 // ----------------------------------------------------------------------------
67 // wxTreebook creation
68 // ----------------------------------------------------------------------------
69
70 void wxTreebook::Init()
71 {
72 m_selection =
73 m_actualSelection = wxNOT_FOUND;
74 }
75
76 bool
77 wxTreebook::Create(wxWindow *parent,
78 wxWindowID id,
79 const wxPoint& pos,
80 const wxSize& size,
81 long style,
82 const wxString& name)
83 {
84 // Check the style flag to have either wxTBK_RIGHT or wxTBK_LEFT
85 if ( (style & wxBK_ALIGN_MASK) == wxBK_DEFAULT )
86 {
87 style |= wxBK_LEFT;
88 }
89 style |= wxTAB_TRAVERSAL;
90
91 // no border for this control, it doesn't look nice together with the tree
92 style &= ~wxBORDER_MASK;
93 style |= wxBORDER_NONE;
94
95 if ( !wxControl::Create(parent, id, pos, size,
96 style, wxDefaultValidator, name) )
97 return false;
98
99 m_bookctrl = new wxTreeCtrl
100 (
101 this,
102 wxID_ANY,
103 wxDefaultPosition,
104 wxDefaultSize,
105 wxBORDER_THEME |
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 if ( !newId.IsOk() )
251 {
252 (void)wxBookCtrlBase::DoRemovePage(newPos);
253
254 wxFAIL_MSG( wxT("Failed to insert treebook page") );
255 return false;
256 }
257
258 DoInternalAddPage(newPos, page, newId);
259
260 DoUpdateSelection(bSelect, newPos);
261
262 return true;
263 }
264
265 bool wxTreebook::DeletePage(size_t pagePos)
266 {
267 wxCHECK_MSG( IS_VALID_PAGE(pagePos), false, wxT("Invalid tree index") );
268
269 wxTreebookPage *oldPage = DoRemovePage(pagePos);
270 if ( !oldPage )
271 return false;
272
273 delete oldPage;
274
275 return true;
276 }
277
278 wxTreebookPage *wxTreebook::DoRemovePage(size_t pagePos)
279 {
280 wxTreeItemId pageId = DoInternalGetPage(pagePos);
281 wxCHECK_MSG( pageId.IsOk(), NULL, wxT("Invalid tree index") );
282
283 wxTreebookPage * oldPage = GetPage(pagePos);
284 wxTreeCtrl *tree = GetTreeCtrl();
285
286 size_t subCount = tree->GetChildrenCount(pageId, true);
287 wxASSERT_MSG ( IS_VALID_PAGE(pagePos + subCount),
288 wxT("Internal error in wxTreebook::DoRemovePage") );
289
290 // here we are going to delete ALL the pages in the range
291 // [pagePos, pagePos + subCount] -- the page and its children
292
293 // deleting all the pages from the base class
294 for ( size_t i = 0; i <= subCount; ++i )
295 {
296 wxTreebookPage *page = wxBookCtrlBase::DoRemovePage(pagePos);
297
298 // don't delete the page itself though -- it will be deleted in
299 // DeletePage() when we return
300 if ( i )
301 {
302 delete page;
303 }
304 }
305
306 DoInternalRemovePageRange(pagePos, subCount);
307
308 tree->DeleteChildren( pageId );
309 tree->Delete( pageId );
310
311 return oldPage;
312 }
313
314 bool wxTreebook::DeleteAllPages()
315 {
316 wxBookCtrlBase::DeleteAllPages();
317 m_treeIds.Clear();
318 m_selection =
319 m_actualSelection = wxNOT_FOUND;
320
321 wxTreeCtrl *tree = GetTreeCtrl();
322 tree->DeleteChildren(tree->GetRootItem());
323
324 return true;
325 }
326
327 void wxTreebook::DoInternalAddPage(size_t newPos,
328 wxTreebookPage *page,
329 wxTreeItemId pageId)
330 {
331 wxASSERT_MSG( newPos <= m_treeIds.GetCount(), wxT("Ivalid index passed to wxTreebook::DoInternalAddPage") );
332
333 // hide newly inserted page initially (it will be shown when selected)
334 if ( page )
335 page->Hide();
336
337 if ( newPos == m_treeIds.GetCount() )
338 {
339 // append
340 m_treeIds.Add(pageId);
341 }
342 else // insert
343 {
344 m_treeIds.Insert(pageId, newPos);
345
346 if ( m_selection != wxNOT_FOUND && newPos <= (size_t)m_selection )
347 {
348 // selection has been moved one unit toward the end
349 ++m_selection;
350 if ( m_actualSelection != wxNOT_FOUND )
351 ++m_actualSelection;
352 }
353 else if ( m_actualSelection != wxNOT_FOUND &&
354 newPos <= (size_t)m_actualSelection )
355 {
356 DoSetSelection(m_selection);
357 }
358 }
359 }
360
361 void wxTreebook::DoInternalRemovePageRange(size_t pagePos, size_t subCount)
362 {
363 // Attention: this function is only for a situation when we delete a node
364 // with all its children so pagePos is the node's index and subCount is the
365 // node children count
366 wxASSERT_MSG( pagePos + subCount < m_treeIds.GetCount(),
367 wxT("Ivalid page index") );
368
369 wxTreeItemId pageId = m_treeIds[pagePos];
370
371 m_treeIds.RemoveAt(pagePos, subCount + 1);
372
373 if ( m_selection != wxNOT_FOUND )
374 {
375 if ( (size_t)m_selection > pagePos + subCount)
376 {
377 // selection is far after the deleted page, so just update the index and move on
378 m_selection -= 1 + subCount;
379 if ( m_actualSelection != wxNOT_FOUND)
380 {
381 m_actualSelection -= subCount + 1;
382 }
383 }
384 else if ( (size_t)m_selection >= pagePos )
385 {
386 wxTreeCtrl *tree = GetTreeCtrl();
387
388 // as selected page is going to be deleted, try to select the next
389 // sibling if exists, if not then the parent
390 wxTreeItemId nodeId = tree->GetNextSibling(pageId);
391
392 m_selection = wxNOT_FOUND;
393 m_actualSelection = wxNOT_FOUND;
394
395 if ( nodeId.IsOk() )
396 {
397 // selecting next siblings
398 tree->SelectItem(nodeId);
399 }
400 else // no next sibling, select the parent
401 {
402 wxTreeItemId parentId = tree->GetItemParent(pageId);
403
404 if ( parentId.IsOk() && parentId != tree->GetRootItem() )
405 {
406 tree->SelectItem(parentId);
407 }
408 else // parent is root
409 {
410 // we can't select it as it's hidden
411 DoUpdateSelection(false, wxNOT_FOUND);
412 }
413 }
414 }
415 else if ( m_actualSelection != wxNOT_FOUND &&
416 (size_t)m_actualSelection >= pagePos )
417 {
418 // nothing to do -- selection is before the deleted node, but
419 // actually shown page (the first (sub)child with page != NULL) is
420 // already deleted
421 m_actualSelection = m_selection;
422
423 // send event as documented
424 DoSetSelection(m_selection, SetSelection_SendEvent);
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::DoSetSelection(size_t pagePos, int flags)
576 {
577 wxCHECK_MSG( IS_VALID_PAGE(pagePos), wxNOT_FOUND,
578 wxT("invalid page index in wxListbook::DoSetSelection()") );
579 wxASSERT_MSG( GetPageCount() == DoInternalGetPageCount(),
580 wxT("wxTreebook logic error: m_treeIds and m_pages not in sync!"));
581
582 wxTreebookEvent event(wxEVT_COMMAND_TREEBOOK_PAGE_CHANGING, m_windowId);
583 const int oldSel = m_selection;
584 wxTreeCtrl *tree = GetTreeCtrl();
585 bool allowed = false;
586
587 if (flags & SetSelection_SendEvent)
588 {
589 event.SetEventObject(this);
590 event.SetSelection(pagePos);
591 event.SetOldSelection(m_selection);
592
593 // don't send the event if the old and new pages are the same; do send it
594 // otherwise and be prepared for it to be vetoed
595 allowed = (int)pagePos == m_selection ||
596 !GetEventHandler()->ProcessEvent(event) ||
597 event.IsAllowed();
598 }
599
600 if ( !(flags & SetSelection_SendEvent) || allowed )
601 {
602 // hide the previously shown page
603 wxTreebookPage * const oldPage = DoGetCurrentPage();
604 if ( oldPage )
605 oldPage->Hide();
606
607 // then show the new one
608 m_selection = pagePos;
609 wxTreebookPage *page = wxBookCtrlBase::GetPage(m_selection);
610 if ( !page )
611 {
612 // find the next page suitable to be shown: the first (grand)child
613 // of this one with a non-NULL associated page
614 wxTreeItemId childId = m_treeIds[pagePos];
615 int actualPagePos = pagePos;
616 while ( !page && childId.IsOk() )
617 {
618 wxTreeItemIdValue cookie;
619 childId = tree->GetFirstChild( childId, cookie );
620 if ( childId.IsOk() )
621 {
622 page = wxBookCtrlBase::GetPage(++actualPagePos);
623 }
624 }
625
626 m_actualSelection = page ? actualPagePos : m_selection;
627 }
628
629 if ( page )
630 page->Show();
631
632 tree->SelectItem(DoInternalGetPage(pagePos));
633
634 if (flags & SetSelection_SendEvent)
635 {
636 // notify about the (now completed) page change
637 event.SetEventType(wxEVT_COMMAND_TREEBOOK_PAGE_CHANGED);
638 (void)GetEventHandler()->ProcessEvent(event);
639 }
640 }
641 else if ( (flags & SetSelection_SendEvent) && !allowed) // page change vetoed
642 {
643 // tree selection might have already had changed
644 if ( oldSel != wxNOT_FOUND )
645 tree->SelectItem(DoInternalGetPage(oldSel));
646 }
647
648 return oldSel;
649 }
650
651 wxTreebookPage *wxTreebook::DoGetCurrentPage() const
652 {
653 if ( m_selection == wxNOT_FOUND )
654 return NULL;
655
656 wxTreebookPage *page = wxBookCtrlBase::GetPage(m_selection);
657 if ( !page && m_actualSelection != wxNOT_FOUND )
658 {
659 page = wxBookCtrlBase::GetPage(m_actualSelection);
660 }
661
662 return page;
663 }
664
665 void wxTreebook::SetImageList(wxImageList *imageList)
666 {
667 wxBookCtrlBase::SetImageList(imageList);
668 GetTreeCtrl()->SetImageList(imageList);
669 }
670
671 void wxTreebook::AssignImageList(wxImageList *imageList)
672 {
673 wxBookCtrlBase::AssignImageList(imageList);
674 GetTreeCtrl()->SetImageList(imageList);
675 }
676
677 // ----------------------------------------------------------------------------
678 // event handlers
679 // ----------------------------------------------------------------------------
680
681 void wxTreebook::OnTreeSelectionChange(wxTreeEvent& event)
682 {
683 if ( event.GetEventObject() != m_bookctrl )
684 {
685 event.Skip();
686 return;
687 }
688
689 wxTreeItemId newId = event.GetItem();
690
691 if ( (m_selection == wxNOT_FOUND &&
692 (!newId.IsOk() || newId == GetTreeCtrl()->GetRootItem())) ||
693 (m_selection != wxNOT_FOUND && newId == m_treeIds[m_selection]) )
694 {
695 // this event can only come when we modify the tree selection ourselves
696 // so we should simply ignore it
697 return;
698 }
699
700 int newPos = DoInternalFindPageById(newId);
701
702 if ( newPos != wxNOT_FOUND )
703 SetSelection( newPos );
704 }
705
706 void wxTreebook::OnTreeNodeExpandedCollapsed(wxTreeEvent & event)
707 {
708 if ( event.GetEventObject() != m_bookctrl )
709 {
710 event.Skip();
711 return;
712 }
713
714 wxTreeItemId nodeId = event.GetItem();
715 if ( !nodeId.IsOk() || nodeId == GetTreeCtrl()->GetRootItem() )
716 return;
717 int pagePos = DoInternalFindPageById(nodeId);
718 wxCHECK_RET( pagePos != wxNOT_FOUND, wxT("Internal problem in wxTreebook!..") );
719
720 wxTreebookEvent ev(GetTreeCtrl()->IsExpanded(nodeId)
721 ? wxEVT_COMMAND_TREEBOOK_NODE_EXPANDED
722 : wxEVT_COMMAND_TREEBOOK_NODE_COLLAPSED,
723 m_windowId);
724
725 ev.SetSelection(pagePos);
726 ev.SetOldSelection(pagePos);
727 ev.SetEventObject(this);
728
729 GetEventHandler()->ProcessEvent(ev);
730 }
731
732 // ----------------------------------------------------------------------------
733 // wxTreebook geometry management
734 // ----------------------------------------------------------------------------
735
736 int wxTreebook::HitTest(wxPoint const & pt, long * flags) const
737 {
738 int pagePos = wxNOT_FOUND;
739
740 if ( flags )
741 *flags = wxBK_HITTEST_NOWHERE;
742
743 // convert from wxTreebook coorindates to wxTreeCtrl ones
744 const wxTreeCtrl * const tree = GetTreeCtrl();
745 const wxPoint treePt = tree->ScreenToClient(ClientToScreen(pt));
746
747 // is it over the tree?
748 if ( wxRect(tree->GetSize()).Contains(treePt) )
749 {
750 int flagsTree;
751 wxTreeItemId id = tree->HitTest(treePt, flagsTree);
752
753 if ( id.IsOk() && (flagsTree & wxTREE_HITTEST_ONITEM) )
754 {
755 pagePos = DoInternalFindPageById(id);
756 }
757
758 if ( flags )
759 {
760 if ( pagePos != wxNOT_FOUND )
761 *flags = 0;
762
763 if ( flagsTree & (wxTREE_HITTEST_ONITEMBUTTON |
764 wxTREE_HITTEST_ONITEMICON |
765 wxTREE_HITTEST_ONITEMSTATEICON) )
766 *flags |= wxBK_HITTEST_ONICON;
767
768 if ( flagsTree & wxTREE_HITTEST_ONITEMLABEL )
769 *flags |= wxBK_HITTEST_ONLABEL;
770 }
771 }
772 else // not over the tree
773 {
774 if ( flags && GetPageRect().Contains( pt ) )
775 *flags |= wxBK_HITTEST_ONPAGE;
776 }
777
778 return pagePos;
779 }
780
781 #endif // wxUSE_TREEBOOK