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