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