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