fill in flags parameter of HitTest() for all book controls; added new wxNB_HITTEST_ON...
[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 #if !WXWIN_COMPATIBILITY_EVENT_TYPES
52 const wxEventType wxEVT_COMMAND_TREEBOOK_PAGE_CHANGING = wxNewEventType();
53 const wxEventType wxEVT_COMMAND_TREEBOOK_PAGE_CHANGED = wxNewEventType();
54 const wxEventType wxEVT_COMMAND_TREEBOOK_NODE_COLLAPSED = wxNewEventType();
55 const wxEventType wxEVT_COMMAND_TREEBOOK_NODE_EXPANDED = wxNewEventType();
56 #endif
57 const int wxID_TREEBOOKTREEVIEW = wxNewId();
58
59 BEGIN_EVENT_TABLE(wxTreebook, wxBookCtrlBase)
60 EVT_TREE_SEL_CHANGED (wxID_TREEBOOKTREEVIEW, wxTreebook::OnTreeSelectionChange)
61 EVT_TREE_ITEM_EXPANDED (wxID_TREEBOOKTREEVIEW, wxTreebook::OnTreeNodeExpandedCollapsed)
62 EVT_TREE_ITEM_COLLAPSED(wxID_TREEBOOKTREEVIEW, wxTreebook::OnTreeNodeExpandedCollapsed)
63 END_EVENT_TABLE()
64
65 // ============================================================================
66 // wxTreebook implementation
67 // ============================================================================
68
69 // ----------------------------------------------------------------------------
70 // wxTreebook creation
71 // ----------------------------------------------------------------------------
72
73 void wxTreebook::Init()
74 {
75 m_selection =
76 m_actualSelection = wxNOT_FOUND;
77 }
78
79 bool
80 wxTreebook::Create(wxWindow *parent,
81 wxWindowID id,
82 const wxPoint& pos,
83 const wxSize& size,
84 long style,
85 const wxString& name)
86 {
87 // Check the style flag to have either wxTBK_RIGHT or wxTBK_LEFT
88 if ( (style & wxBK_ALIGN_MASK) == wxBK_DEFAULT )
89 {
90 style |= wxBK_LEFT;
91 }
92
93 // no border for this control, it doesn't look nice together with the tree
94 style &= ~wxBORDER_MASK;
95 style |= wxBORDER_NONE;
96
97 if ( !wxControl::Create(parent, id, pos, size,
98 style, wxDefaultValidator, name) )
99 return false;
100
101 m_bookctrl = new wxTreeCtrl
102 (
103 this,
104 wxID_TREEBOOKTREEVIEW,
105 wxDefaultPosition,
106 wxDefaultSize,
107 #ifndef __WXMSW__
108 wxBORDER_SIMPLE | // On wxMSW this produces a black border which is wrong
109 #endif
110 wxTR_DEFAULT_STYLE |
111 wxTR_HIDE_ROOT |
112 wxTR_SINGLE
113 );
114 GetTreeCtrl()->SetQuickBestSize(false); // do full size calculation
115 GetTreeCtrl()->AddRoot(wxEmptyString); // label doesn't matter, it's hidden
116
117 #ifdef __WXMSW__
118 // We need to add dummy size event to force possible scrollbar hiding
119 wxSizeEvent evt;
120 GetEventHandler()->AddPendingEvent(evt);
121 #endif
122
123 return true;
124 }
125
126
127 // insert a new page just before the pagePos
128 bool wxTreebook::InsertPage(size_t pagePos,
129 wxWindow *page,
130 const wxString& text,
131 bool bSelect,
132 int imageId)
133 {
134 return DoInsertPage(pagePos, page, text, bSelect, imageId);
135 }
136
137 bool wxTreebook::InsertSubPage(size_t pagePos,
138 wxWindow *page,
139 const wxString& text,
140 bool bSelect,
141 int imageId)
142 {
143 return DoInsertSubPage(pagePos, page, text, bSelect, imageId);
144 }
145
146 bool wxTreebook::AddPage(wxWindow *page, const wxString& text, bool bSelect,
147 int imageId)
148 {
149 return DoInsertPage(m_treeIds.GetCount(), page, text, bSelect, imageId);
150 }
151
152 // insertion time is linear to the number of top-pages
153 bool wxTreebook::AddSubPage(wxWindow *page, const wxString& text, bool bSelect, int imageId)
154 {
155 return DoAddSubPage(page, text, bSelect, imageId);
156 }
157
158
159 bool wxTreebook::DoInsertPage(size_t pagePos,
160 wxWindow *page,
161 const wxString& text,
162 bool bSelect,
163 int imageId)
164 {
165 wxCHECK_MSG( pagePos <= DoInternalGetPageCount(), false,
166 wxT("Invalid treebook page position") );
167
168 if ( !wxBookCtrlBase::InsertPage(pagePos, page, text, bSelect, imageId) )
169 return false;
170
171 wxTreeCtrl *tree = GetTreeCtrl();
172 wxTreeItemId newId;
173 if ( pagePos == DoInternalGetPageCount() )
174 {
175 // append the page to the end
176 wxTreeItemId rootId = tree->GetRootItem();
177
178 newId = tree->AppendItem(rootId, text, imageId);
179 }
180 else // insert the new page before the given one
181 {
182 wxTreeItemId nodeId = m_treeIds[pagePos];
183
184 wxTreeItemId previousId = tree->GetPrevSibling(nodeId);
185 wxTreeItemId parentId = tree->GetItemParent(nodeId);
186
187 if ( previousId.IsOk() )
188 {
189 // insert before the sibling - previousId
190 newId = tree->InsertItem(parentId, previousId, text, imageId);
191 }
192 else // no prev siblings -- insert as a first child
193 {
194 wxASSERT_MSG( parentId.IsOk(), wxT( "Tree has no root node?" ) );
195
196 newId = tree->PrependItem(parentId, text, imageId);
197 }
198 }
199
200 if ( !newId.IsOk() )
201 {
202 //something wrong -> cleaning and returning with false
203 (void)wxBookCtrlBase::DoRemovePage(pagePos);
204
205 wxFAIL_MSG( wxT("Failed to insert treebook page") );
206 return false;
207 }
208
209 DoInternalAddPage(pagePos, page, newId);
210
211 DoUpdateSelection(bSelect, pagePos);
212
213 return true;
214 }
215
216 bool wxTreebook::DoAddSubPage(wxWindow *page, const wxString& text, bool bSelect, int imageId)
217 {
218 wxTreeCtrl *tree = GetTreeCtrl();
219
220 wxTreeItemId rootId = tree->GetRootItem();
221
222 wxTreeItemId lastNodeId = tree->GetLastChild(rootId);
223
224 wxCHECK_MSG( lastNodeId.IsOk(), false,
225 _T("Can't insert sub page when there are no pages") );
226
227 // now calculate its position (should we save/update it too?)
228 size_t newPos = tree->GetCount() -
229 (tree->GetChildrenCount(lastNodeId, true) + 1);
230
231 return DoInsertSubPage(newPos, page, text, bSelect, imageId);
232 }
233
234 bool wxTreebook::DoInsertSubPage(size_t pagePos,
235 wxTreebookPage *page,
236 const wxString& text,
237 bool bSelect,
238 int imageId)
239 {
240 wxTreeItemId parentId = DoInternalGetPage(pagePos);
241 wxCHECK_MSG( parentId.IsOk(), false, wxT("invalid tree item") );
242
243 wxTreeCtrl *tree = GetTreeCtrl();
244
245 size_t newPos = pagePos + tree->GetChildrenCount(parentId, true) + 1;
246 wxASSERT_MSG( newPos <= DoInternalGetPageCount(),
247 wxT("Internal error in tree insert point calculation") );
248
249 if ( !wxBookCtrlBase::InsertPage(newPos, page, text, bSelect, imageId) )
250 return false;
251
252 wxTreeItemId newId = tree->AppendItem(parentId, text, imageId);
253
254 tree->InvalidateBestSize();
255
256 if ( !newId.IsOk() )
257 {
258 (void)wxBookCtrlBase::DoRemovePage(newPos);
259
260 wxFAIL_MSG( wxT("Failed to insert treebook page") );
261 return false;
262 }
263
264 DoInternalAddPage(newPos, page, newId);
265
266 DoUpdateSelection(bSelect, newPos);
267
268 return true;
269 }
270
271 bool wxTreebook::DeletePage(size_t pagePos)
272 {
273 wxCHECK_MSG( IS_VALID_PAGE(pagePos), false, wxT("Invalid tree index") );
274
275 wxTreebookPage *oldPage = DoRemovePage(pagePos);
276 if ( !oldPage )
277 return false;
278
279 delete oldPage;
280
281 return true;
282 }
283
284 wxTreebookPage *wxTreebook::DoRemovePage(size_t pagePos)
285 {
286 wxTreeItemId pageId = DoInternalGetPage(pagePos);
287 wxCHECK_MSG( pageId.IsOk(), NULL, wxT("Invalid tree index") );
288
289 wxTreebookPage * oldPage = GetPage(pagePos);
290 wxTreeCtrl *tree = GetTreeCtrl();
291
292 size_t subCount = 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 tree->DeleteChildren( pageId );
315 tree->Delete( pageId );
316
317 return oldPage;
318 }
319
320 bool wxTreebook::DeleteAllPages()
321 {
322 wxBookCtrlBase::DeleteAllPages();
323 m_treeIds.Clear();
324 m_selection =
325 m_actualSelection = wxNOT_FOUND;
326
327 wxTreeCtrl *tree = GetTreeCtrl();
328 tree->DeleteChildren(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 wxTreeCtrl *tree = GetTreeCtrl();
393
394 // as selected page is going to be deleted, try to select the next
395 // sibling if exists, if not then the parent
396 wxTreeItemId nodeId = tree->GetNextSibling(pageId);
397
398 m_selection = wxNOT_FOUND;
399 m_actualSelection = wxNOT_FOUND;
400
401 if ( nodeId.IsOk() )
402 {
403 // selecting next siblings
404 tree->SelectItem(nodeId);
405 }
406 else // no next sibling, select the parent
407 {
408 wxTreeItemId parentId = tree->GetItemParent(pageId);
409
410 if ( parentId.IsOk() && parentId != tree->GetRootItem() )
411 {
412 tree->SelectItem(parentId);
413 }
414 else // parent is root
415 {
416 // we can't select it as it's hidden
417 DoUpdateSelection(false, wxNOT_FOUND);
418 }
419 }
420 }
421 else if ( m_actualSelection != wxNOT_FOUND &&
422 (size_t)m_actualSelection >= pagePos )
423 {
424 // nothing to do -- selection is before the deleted node, but
425 // actually shown page (the first (sub)child with page != NULL) is
426 // already deleted
427 m_actualSelection = m_selection;
428 DoSetSelection(m_selection);
429 }
430 //else: nothing to do -- selection is before the deleted node
431 }
432 else
433 {
434 DoUpdateSelection(false, wxNOT_FOUND);
435 }
436 }
437
438
439 void wxTreebook::DoUpdateSelection(bool bSelect, int newPos)
440 {
441 int newSelPos;
442 if ( bSelect )
443 {
444 newSelPos = newPos;
445 }
446 else if ( m_selection == wxNOT_FOUND && DoInternalGetPageCount() > 0 )
447 {
448 newSelPos = 0;
449 }
450 else
451 {
452 newSelPos = wxNOT_FOUND;
453 }
454
455 if ( newSelPos != wxNOT_FOUND )
456 {
457 SetSelection((size_t)newSelPos);
458 }
459 }
460
461 wxTreeItemId wxTreebook::DoInternalGetPage(size_t pagePos) const
462 {
463 if ( pagePos >= m_treeIds.GetCount() )
464 {
465 // invalid position but ok here, in this internal function, don't assert
466 // (the caller will do it)
467 return wxTreeItemId();
468 }
469
470 return m_treeIds[pagePos];
471 }
472
473 int wxTreebook::DoInternalFindPageById(wxTreeItemId pageId) const
474 {
475 const size_t count = m_treeIds.GetCount();
476 for ( size_t i = 0; i < count; ++i )
477 {
478 if ( m_treeIds[i] == pageId )
479 return i;
480 }
481
482 return wxNOT_FOUND;
483 }
484
485 bool wxTreebook::IsNodeExpanded(size_t pagePos) const
486 {
487 wxTreeItemId pageId = DoInternalGetPage(pagePos);
488
489 wxCHECK_MSG( pageId.IsOk(), false, wxT("invalid tree item") );
490
491 return GetTreeCtrl()->IsExpanded(pageId);
492 }
493
494 bool wxTreebook::ExpandNode(size_t pagePos, bool expand)
495 {
496 wxTreeItemId pageId = DoInternalGetPage(pagePos);
497
498 wxCHECK_MSG( pageId.IsOk(), false, wxT("invalid tree item") );
499
500 if ( expand )
501 {
502 GetTreeCtrl()->Expand( pageId );
503 }
504 else // collapse
505 {
506 GetTreeCtrl()->Collapse( pageId );
507
508 // rely on the events generated by wxTreeCtrl to update selection
509 }
510
511 return true;
512 }
513
514 int wxTreebook::GetPageParent(size_t pagePos) const
515 {
516 wxTreeItemId nodeId = DoInternalGetPage( pagePos );
517 wxCHECK_MSG( nodeId.IsOk(), wxNOT_FOUND, wxT("Invalid page index spacified!") );
518
519 const wxTreeItemId parent = GetTreeCtrl()->GetItemParent( nodeId );
520
521 return parent.IsOk() ? DoInternalFindPageById(parent) : wxNOT_FOUND;
522 }
523
524 bool wxTreebook::SetPageText(size_t n, const wxString& strText)
525 {
526 wxTreeItemId pageId = DoInternalGetPage(n);
527
528 wxCHECK_MSG( pageId.IsOk(), false, wxT("invalid tree item") );
529
530 GetTreeCtrl()->SetItemText(pageId, strText);
531
532 return true;
533 }
534
535 wxString wxTreebook::GetPageText(size_t n) const
536 {
537 wxTreeItemId pageId = DoInternalGetPage(n);
538
539 wxCHECK_MSG( pageId.IsOk(), wxString(), wxT("invalid tree item") );
540
541 return GetTreeCtrl()->GetItemText(pageId);
542 }
543
544 int wxTreebook::GetPageImage(size_t n) const
545 {
546 wxTreeItemId pageId = DoInternalGetPage(n);
547
548 wxCHECK_MSG( pageId.IsOk(), wxNOT_FOUND, wxT("invalid tree item") );
549
550 return GetTreeCtrl()->GetItemImage(pageId);
551 }
552
553 bool wxTreebook::SetPageImage(size_t n, int imageId)
554 {
555 wxTreeItemId pageId = DoInternalGetPage(n);
556
557 wxCHECK_MSG( pageId.IsOk(), false, wxT("invalid tree item") );
558
559 GetTreeCtrl()->SetItemImage(pageId, imageId);
560
561 return true;
562 }
563
564 wxSize wxTreebook::CalcSizeFromPage(const wxSize& sizePage) const
565 {
566 const wxSize sizeTree = GetControllerSize();
567
568 wxSize size = sizePage;
569 size.x += sizeTree.x;
570
571 return size;
572 }
573
574 int wxTreebook::GetSelection() const
575 {
576 return m_selection;
577 }
578
579 int wxTreebook::SetSelection(size_t pagePos)
580 {
581 if ( (size_t)m_selection != pagePos )
582 return DoSetSelection(pagePos);
583
584 return m_selection;
585 }
586
587 int wxTreebook::DoSetSelection(size_t pagePos)
588 {
589 wxCHECK_MSG( IS_VALID_PAGE(pagePos), wxNOT_FOUND,
590 wxT("invalid page index in wxListbook::SetSelection()") );
591 wxASSERT_MSG( GetPageCount() == DoInternalGetPageCount(),
592 wxT("wxTreebook logic error: m_treeIds and m_pages not in sync!"));
593
594 const int oldSel = m_selection;
595 wxTreeCtrl *tree = GetTreeCtrl();
596
597 wxTreebookEvent event(wxEVT_COMMAND_TREEBOOK_PAGE_CHANGING, m_windowId);
598 event.SetEventObject(this);
599 event.SetSelection(pagePos);
600 event.SetOldSelection(m_selection);
601
602 // don't send the event if the old and new pages are the same; do send it
603 // otherwise and be prepared for it to be vetoed
604 if ( (int)pagePos == m_selection ||
605 !GetEventHandler()->ProcessEvent(event) ||
606 event.IsAllowed() )
607 {
608 // hide the previously shown page
609 wxTreebookPage * const oldPage = DoGetCurrentPage();
610 if ( oldPage )
611 oldPage->Hide();
612
613 // then show the new one
614 m_selection = pagePos;
615 wxTreebookPage *page = wxBookCtrlBase::GetPage(m_selection);
616 if ( !page )
617 {
618 // find the next page suitable to be shown: the first (grand)child
619 // of this one with a non-NULL associated page
620 wxTreeItemId childId = m_treeIds[pagePos];
621 int actualPagePos = pagePos;
622 while ( !page && childId.IsOk() )
623 {
624 wxTreeItemIdValue cookie;
625 childId = tree->GetFirstChild( childId, cookie );
626 if ( childId.IsOk() )
627 {
628 page = wxBookCtrlBase::GetPage(++actualPagePos);
629 }
630 }
631
632 m_actualSelection = page ? actualPagePos : m_selection;
633 }
634
635 if ( page )
636 page->Show();
637
638 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 tree->SelectItem(DoInternalGetPage(oldSel));
648 }
649
650 return oldSel;
651 }
652
653 wxTreebookPage *wxTreebook::DoGetCurrentPage() const
654 {
655 if ( m_selection == wxNOT_FOUND )
656 return NULL;
657
658 wxTreebookPage *page = wxBookCtrlBase::GetPage(m_selection);
659 if ( !page && m_actualSelection != wxNOT_FOUND )
660 {
661 page = wxBookCtrlBase::GetPage(m_actualSelection);
662 }
663
664 return page;
665 }
666
667 void wxTreebook::SetImageList(wxImageList *imageList)
668 {
669 wxBookCtrlBase::SetImageList(imageList);
670 GetTreeCtrl()->SetImageList(imageList);
671 }
672
673 void wxTreebook::AssignImageList(wxImageList *imageList)
674 {
675 wxBookCtrlBase::AssignImageList(imageList);
676 GetTreeCtrl()->SetImageList(imageList);
677 }
678
679 // ----------------------------------------------------------------------------
680 // event handlers
681 // ----------------------------------------------------------------------------
682
683 void wxTreebook::OnTreeSelectionChange(wxTreeEvent& event)
684 {
685 wxTreeItemId newId = event.GetItem();
686
687 if ( (m_selection == wxNOT_FOUND &&
688 (!newId.IsOk() || newId == GetTreeCtrl()->GetRootItem())) ||
689 (m_selection != wxNOT_FOUND && newId == m_treeIds[m_selection]) )
690 {
691 // this event can only come when we modify the tree selection ourselves
692 // so we should simply ignore it
693 return;
694 }
695
696 int newPos = DoInternalFindPageById(newId);
697
698 if ( newPos != wxNOT_FOUND )
699 SetSelection( newPos );
700 }
701
702 void wxTreebook::OnTreeNodeExpandedCollapsed(wxTreeEvent & event)
703 {
704 wxTreeItemId nodeId = event.GetItem();
705 if ( !nodeId.IsOk() || nodeId == GetTreeCtrl()->GetRootItem() )
706 return;
707 int pagePos = DoInternalFindPageById(nodeId);
708 wxCHECK_RET( pagePos != wxNOT_FOUND, wxT("Internal problem in wxTreebook!..") );
709
710 wxTreebookEvent ev(GetTreeCtrl()->IsExpanded(nodeId)
711 ? wxEVT_COMMAND_TREEBOOK_NODE_EXPANDED
712 : wxEVT_COMMAND_TREEBOOK_NODE_COLLAPSED,
713 m_windowId);
714
715 ev.SetSelection(pagePos);
716 ev.SetOldSelection(pagePos);
717 ev.SetEventObject(this);
718
719 GetEventHandler()->ProcessEvent(ev);
720 }
721
722 // ----------------------------------------------------------------------------
723 // wxTreebook geometry management
724 // ----------------------------------------------------------------------------
725
726 int wxTreebook::HitTest(wxPoint const & pt, long * flags) const
727 {
728 int pagePos = wxNOT_FOUND;
729
730 if ( flags )
731 *flags = wxNB_HITTEST_NOWHERE;
732
733 // convert from wxTreebook coorindates to wxTreeCtrl ones
734 const wxTreeCtrl * const tree = GetTreeCtrl();
735 const wxPoint treePt = tree->ScreenToClient(ClientToScreen(pt));
736
737 // is it over the tree?
738 if ( wxRect(tree->GetSize()).Inside(treePt) )
739 {
740 int flagsTree;
741 wxTreeItemId id = tree->HitTest(treePt, flagsTree);
742
743 if ( id.IsOk() && (flagsTree & wxTREE_HITTEST_ONITEM) )
744 {
745 pagePos = DoInternalFindPageById(id);
746 }
747
748 if ( flags )
749 {
750 if ( pagePos != wxNOT_FOUND )
751 *flags = 0;
752
753 if ( flagsTree & (wxTREE_HITTEST_ONITEMBUTTON |
754 wxTREE_HITTEST_ONITEMICON |
755 wxTREE_HITTEST_ONITEMSTATEICON) )
756 *flags |= wxNB_HITTEST_ONICON;
757
758 if ( flagsTree & wxTREE_HITTEST_ONITEMLABEL )
759 *flags |= wxNB_HITTEST_ONLABEL;
760 }
761 }
762 else // not over the tree
763 {
764 if ( flags && GetPageRect().Inside( pt ) )
765 *flags |= wxNB_HITTEST_ONPAGE;
766 }
767
768 return pagePos;
769 }
770
771 #endif // wxUSE_TREEBOOK