]> git.saurik.com Git - wxWidgets.git/blame - src/generic/treebkg.cpp
adding constant which appears in Leopard SDK only
[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
VZ
49IMPLEMENT_DYNAMIC_CLASS(wxTreebookEvent, wxNotifyEvent)
50
51const wxEventType wxEVT_COMMAND_TREEBOOK_PAGE_CHANGING = wxNewEventType();
52const wxEventType wxEVT_COMMAND_TREEBOOK_PAGE_CHANGED = wxNewEventType();
53const wxEventType wxEVT_COMMAND_TREEBOOK_NODE_COLLAPSED = wxNewEventType();
54const wxEventType wxEVT_COMMAND_TREEBOOK_NODE_EXPANDED = wxNewEventType();
eca15c0d
VZ
55
56BEGIN_EVENT_TABLE(wxTreebook, wxBookCtrlBase)
447325a4
VZ
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)
eca15c0d
VZ
60END_EVENT_TABLE()
61
62// ============================================================================
63// wxTreebook implementation
64// ============================================================================
65
66// ----------------------------------------------------------------------------
67// wxTreebook creation
68// ----------------------------------------------------------------------------
69
70void wxTreebook::Init()
71{
eca15c0d
VZ
72 m_selection =
73 m_actualSelection = wxNOT_FOUND;
74}
75
76bool
77wxTreebook::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
2ddb4d13 85 if ( (style & wxBK_ALIGN_MASK) == wxBK_DEFAULT )
eca15c0d 86 {
2ddb4d13 87 style |= wxBK_LEFT;
eca15c0d 88 }
5e4a7f91 89 style |= wxTAB_TRAVERSAL;
eca15c0d
VZ
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
2ddb4d13 99 m_bookctrl = new wxTreeCtrl
eca15c0d
VZ
100 (
101 this,
447325a4 102 wxID_ANY,
eca15c0d
VZ
103 wxDefaultPosition,
104 wxDefaultSize,
9ca15f29 105 wxBORDER_THEME |
bc454ef8 106 wxTR_DEFAULT_STYLE |
eca15c0d 107 wxTR_HIDE_ROOT |
eca15c0d
VZ
108 wxTR_SINGLE
109 );
7c384067 110 GetTreeCtrl()->SetQuickBestSize(false); // do full size calculation
2ddb4d13 111 GetTreeCtrl()->AddRoot(wxEmptyString); // label doesn't matter, it's hidden
eca15c0d
VZ
112
113#ifdef __WXMSW__
2ddb4d13 114 // We need to add dummy size event to force possible scrollbar hiding
eca15c0d
VZ
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
124bool 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
9d5371c6
VZ
133bool wxTreebook::InsertSubPage(size_t pagePos,
134 wxWindow *page,
135 const wxString& text,
136 bool bSelect,
137 int imageId)
eca15c0d
VZ
138{
139 return DoInsertSubPage(pagePos, page, text, bSelect, imageId);
140}
141
142bool 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
149bool wxTreebook::AddSubPage(wxWindow *page, const wxString& text, bool bSelect, int imageId)
150{
151 return DoAddSubPage(page, text, bSelect, imageId);
152}
153
154
155bool 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
2ddb4d13 167 wxTreeCtrl *tree = GetTreeCtrl();
eca15c0d
VZ
168 wxTreeItemId newId;
169 if ( pagePos == DoInternalGetPageCount() )
170 {
171 // append the page to the end
2ddb4d13 172 wxTreeItemId rootId = tree->GetRootItem();
eca15c0d 173
2ddb4d13 174 newId = tree->AppendItem(rootId, text, imageId);
eca15c0d
VZ
175 }
176 else // insert the new page before the given one
177 {
178 wxTreeItemId nodeId = m_treeIds[pagePos];
179
2ddb4d13
WS
180 wxTreeItemId previousId = tree->GetPrevSibling(nodeId);
181 wxTreeItemId parentId = tree->GetItemParent(nodeId);
eca15c0d
VZ
182
183 if ( previousId.IsOk() )
184 {
185 // insert before the sibling - previousId
2ddb4d13 186 newId = tree->InsertItem(parentId, previousId, text, imageId);
eca15c0d
VZ
187 }
188 else // no prev siblings -- insert as a first child
189 {
190 wxASSERT_MSG( parentId.IsOk(), wxT( "Tree has no root node?" ) );
191
2ddb4d13 192 newId = tree->PrependItem(parentId, text, imageId);
eca15c0d
VZ
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
212bool wxTreebook::DoAddSubPage(wxWindow *page, const wxString& text, bool bSelect, int imageId)
213{
2ddb4d13 214 wxTreeCtrl *tree = GetTreeCtrl();
eca15c0d 215
2ddb4d13
WS
216 wxTreeItemId rootId = tree->GetRootItem();
217
218 wxTreeItemId lastNodeId = tree->GetLastChild(rootId);
eca15c0d
VZ
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?)
2ddb4d13
WS
224 size_t newPos = tree->GetCount() -
225 (tree->GetChildrenCount(lastNodeId, true) + 1);
eca15c0d
VZ
226
227 return DoInsertSubPage(newPos, page, text, bSelect, imageId);
228}
229
230bool 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
2ddb4d13
WS
239 wxTreeCtrl *tree = GetTreeCtrl();
240
241 size_t newPos = pagePos + tree->GetChildrenCount(parentId, true) + 1;
eca15c0d
VZ
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
2ddb4d13 248 wxTreeItemId newId = tree->AppendItem(parentId, text, imageId);
eca15c0d
VZ
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
265bool 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
278wxTreebookPage *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);
2ddb4d13 284 wxTreeCtrl *tree = GetTreeCtrl();
eca15c0d 285
2ddb4d13 286 size_t subCount = tree->GetChildrenCount(pageId, true);
eca15c0d
VZ
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
2ddb4d13
WS
308 tree->DeleteChildren( pageId );
309 tree->Delete( pageId );
eca15c0d
VZ
310
311 return oldPage;
312}
313
314bool wxTreebook::DeleteAllPages()
315{
316 wxBookCtrlBase::DeleteAllPages();
317 m_treeIds.Clear();
318 m_selection =
319 m_actualSelection = wxNOT_FOUND;
320
2ddb4d13
WS
321 wxTreeCtrl *tree = GetTreeCtrl();
322 tree->DeleteChildren(tree->GetRootItem());
eca15c0d
VZ
323
324 return true;
325}
326
327void 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
361void 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 {
2ddb4d13
WS
386 wxTreeCtrl *tree = GetTreeCtrl();
387
eca15c0d
VZ
388 // as selected page is going to be deleted, try to select the next
389 // sibling if exists, if not then the parent
2ddb4d13 390 wxTreeItemId nodeId = tree->GetNextSibling(pageId);
eca15c0d
VZ
391
392 m_selection = wxNOT_FOUND;
393 m_actualSelection = wxNOT_FOUND;
394
395 if ( nodeId.IsOk() )
396 {
397 // selecting next siblings
2ddb4d13 398 tree->SelectItem(nodeId);
eca15c0d
VZ
399 }
400 else // no next sibling, select the parent
401 {
2ddb4d13 402 wxTreeItemId parentId = tree->GetItemParent(pageId);
eca15c0d 403
2ddb4d13 404 if ( parentId.IsOk() && parentId != tree->GetRootItem() )
eca15c0d 405 {
2ddb4d13 406 tree->SelectItem(parentId);
eca15c0d
VZ
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;
1d6fcbcc
VZ
422
423 // send event as documented
424 DoSetSelection(m_selection, SetSelection_SendEvent);
eca15c0d
VZ
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
435void 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
457wxTreeItemId 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
469int 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
481bool wxTreebook::IsNodeExpanded(size_t pagePos) const
482{
483 wxTreeItemId pageId = DoInternalGetPage(pagePos);
484
485 wxCHECK_MSG( pageId.IsOk(), false, wxT("invalid tree item") );
486
2ddb4d13 487 return GetTreeCtrl()->IsExpanded(pageId);
eca15c0d
VZ
488}
489
490bool 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 {
2ddb4d13 498 GetTreeCtrl()->Expand( pageId );
eca15c0d
VZ
499 }
500 else // collapse
501 {
2ddb4d13 502 GetTreeCtrl()->Collapse( pageId );
eca15c0d
VZ
503
504 // rely on the events generated by wxTreeCtrl to update selection
505 }
506
507 return true;
508}
509
510int 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
2ddb4d13 515 const wxTreeItemId parent = GetTreeCtrl()->GetItemParent( nodeId );
eca15c0d
VZ
516
517 return parent.IsOk() ? DoInternalFindPageById(parent) : wxNOT_FOUND;
518}
519
520bool 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
2ddb4d13 526 GetTreeCtrl()->SetItemText(pageId, strText);
eca15c0d
VZ
527
528 return true;
529}
530
531wxString wxTreebook::GetPageText(size_t n) const
532{
533 wxTreeItemId pageId = DoInternalGetPage(n);
534
535 wxCHECK_MSG( pageId.IsOk(), wxString(), wxT("invalid tree item") );
536
2ddb4d13 537 return GetTreeCtrl()->GetItemText(pageId);
eca15c0d
VZ
538}
539
540int 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
2ddb4d13 546 return GetTreeCtrl()->GetItemImage(pageId);
eca15c0d
VZ
547}
548
549bool 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
2ddb4d13 555 GetTreeCtrl()->SetItemImage(pageId, imageId);
eca15c0d
VZ
556
557 return true;
558}
559
560wxSize wxTreebook::CalcSizeFromPage(const wxSize& sizePage) const
561{
2ddb4d13 562 const wxSize sizeTree = GetControllerSize();
eca15c0d
VZ
563
564 wxSize size = sizePage;
565 size.x += sizeTree.x;
566
567 return size;
568}
569
570int wxTreebook::GetSelection() const
571{
572 return m_selection;
573}
574
1d6fcbcc 575int wxTreebook::DoSetSelection(size_t pagePos, int flags)
eca15c0d
VZ
576{
577 wxCHECK_MSG( IS_VALID_PAGE(pagePos), wxNOT_FOUND,
1d6fcbcc 578 wxT("invalid page index in wxListbook::DoSetSelection()") );
eca15c0d
VZ
579 wxASSERT_MSG( GetPageCount() == DoInternalGetPageCount(),
580 wxT("wxTreebook logic error: m_treeIds and m_pages not in sync!"));
581
1d6fcbcc 582 wxTreebookEvent event(wxEVT_COMMAND_TREEBOOK_PAGE_CHANGING, m_windowId);
eca15c0d 583 const int oldSel = m_selection;
2ddb4d13 584 wxTreeCtrl *tree = GetTreeCtrl();
1d6fcbcc 585 bool allowed = false;
eca15c0d 586
1d6fcbcc
VZ
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 )
eca15c0d
VZ
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];
6bd02a43 615 int actualPagePos = pagePos;
eca15c0d
VZ
616 while ( !page && childId.IsOk() )
617 {
618 wxTreeItemIdValue cookie;
2ddb4d13 619 childId = tree->GetFirstChild( childId, cookie );
eca15c0d
VZ
620 if ( childId.IsOk() )
621 {
6bd02a43 622 page = wxBookCtrlBase::GetPage(++actualPagePos);
eca15c0d
VZ
623 }
624 }
625
6bd02a43 626 m_actualSelection = page ? actualPagePos : m_selection;
eca15c0d
VZ
627 }
628
629 if ( page )
eca15c0d 630 page->Show();
eca15c0d 631
2ddb4d13 632 tree->SelectItem(DoInternalGetPage(pagePos));
eca15c0d 633
1d6fcbcc
VZ
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 }
eca15c0d 640 }
1d6fcbcc 641 else if ( (flags & SetSelection_SendEvent) && !allowed) // page change vetoed
eca15c0d
VZ
642 {
643 // tree selection might have already had changed
9f30729a
VZ
644 if ( oldSel != wxNOT_FOUND )
645 tree->SelectItem(DoInternalGetPage(oldSel));
eca15c0d
VZ
646 }
647
648 return oldSel;
649}
650
851b88c3
VZ
651wxTreebookPage *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
eca15c0d
VZ
665void wxTreebook::SetImageList(wxImageList *imageList)
666{
667 wxBookCtrlBase::SetImageList(imageList);
2ddb4d13 668 GetTreeCtrl()->SetImageList(imageList);
eca15c0d
VZ
669}
670
671void wxTreebook::AssignImageList(wxImageList *imageList)
672{
673 wxBookCtrlBase::AssignImageList(imageList);
2ddb4d13 674 GetTreeCtrl()->SetImageList(imageList);
eca15c0d
VZ
675}
676
677// ----------------------------------------------------------------------------
678// event handlers
679// ----------------------------------------------------------------------------
680
681void wxTreebook::OnTreeSelectionChange(wxTreeEvent& event)
682{
447325a4
VZ
683 if ( event.GetEventObject() != m_bookctrl )
684 {
685 event.Skip();
686 return;
687 }
688
eca15c0d
VZ
689 wxTreeItemId newId = event.GetItem();
690
691 if ( (m_selection == wxNOT_FOUND &&
2ddb4d13 692 (!newId.IsOk() || newId == GetTreeCtrl()->GetRootItem())) ||
eca15c0d
VZ
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
706void wxTreebook::OnTreeNodeExpandedCollapsed(wxTreeEvent & event)
707{
447325a4
VZ
708 if ( event.GetEventObject() != m_bookctrl )
709 {
710 event.Skip();
711 return;
712 }
713
eca15c0d 714 wxTreeItemId nodeId = event.GetItem();
2ddb4d13 715 if ( !nodeId.IsOk() || nodeId == GetTreeCtrl()->GetRootItem() )
eca15c0d
VZ
716 return;
717 int pagePos = DoInternalFindPageById(nodeId);
718 wxCHECK_RET( pagePos != wxNOT_FOUND, wxT("Internal problem in wxTreebook!..") );
719
2ddb4d13 720 wxTreebookEvent ev(GetTreeCtrl()->IsExpanded(nodeId)
eca15c0d
VZ
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
d0a84b63 736int wxTreebook::HitTest(wxPoint const & pt, long * flags) const
eca15c0d 737{
851b88c3 738 int pagePos = wxNOT_FOUND;
eca15c0d 739
d0a84b63 740 if ( flags )
9804d540 741 *flags = wxBK_HITTEST_NOWHERE;
851b88c3 742
d0a84b63
VZ
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?
22a35096 748 if ( wxRect(tree->GetSize()).Contains(treePt) )
eca15c0d 749 {
851b88c3
VZ
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 }
d0a84b63
VZ
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) )
9804d540 766 *flags |= wxBK_HITTEST_ONICON;
d0a84b63
VZ
767
768 if ( flagsTree & wxTREE_HITTEST_ONITEMLABEL )
9804d540 769 *flags |= wxBK_HITTEST_ONLABEL;
d0a84b63
VZ
770 }
771 }
772 else // not over the tree
773 {
22a35096 774 if ( flags && GetPageRect().Contains( pt ) )
9804d540 775 *flags |= wxBK_HITTEST_ONPAGE;
eca15c0d
VZ
776 }
777
851b88c3 778 return pagePos;
eca15c0d
VZ
779}
780
781#endif // wxUSE_TREEBOOK