+ UnselectAllChildren(GetRootItem().m_pItem);
+}
+
+// Recursive function !
+// To stop we must have crt_item<last_item
+// Algorithm :
+// Tag all next children, when no more children,
+// Move to parent (not to tag)
+// Keep going... if we found last_item, we stop.
+bool wxTreeCtrl::TagNextChildren(wxGenericTreeItem *crt_item, wxGenericTreeItem *last_item, bool select)
+{
+ wxGenericTreeItem *parent = crt_item->GetParent();
+
+ if ( parent == NULL ) // This is root item
+ return TagAllChildrenUntilLast(crt_item, last_item, select);
+
+ wxArrayGenericTreeItems& children = parent->GetChildren();
+ int index = children.Index(crt_item);
+ wxASSERT( index != wxNOT_FOUND ); // I'm not a child of my parent?
+
+ size_t count = children.Count();
+ for (size_t n=(size_t)(index+1); n<count; ++n)
+ if (TagAllChildrenUntilLast(children[n], last_item, select)) return TRUE;
+
+ return TagNextChildren(parent, last_item, select);
+}
+
+bool wxTreeCtrl::TagAllChildrenUntilLast(wxGenericTreeItem *crt_item, wxGenericTreeItem *last_item, bool select)
+{
+ crt_item->SetHilight(select);
+ RefreshLine(crt_item);
+
+ if (crt_item==last_item) return TRUE;
+
+ if (crt_item->HasChildren())
+ {
+ wxArrayGenericTreeItems& children = crt_item->GetChildren();
+ size_t count = children.Count();
+ for ( size_t n = 0; n < count; ++n )
+ if (TagAllChildrenUntilLast(children[n], last_item, select)) return TRUE;
+ }
+
+ return FALSE;
+}
+
+void wxTreeCtrl::SelectItemRange(wxGenericTreeItem *item1, wxGenericTreeItem *item2)
+{
+ // item2 is not necessary after item1
+ wxGenericTreeItem *first=NULL, *last=NULL;
+
+ // choice first' and 'last' between item1 and item2
+ if (item1->GetY()<item2->GetY())
+ {
+ first=item1;
+ last=item2;
+ }
+ else
+ {
+ first=item2;
+ last=item1;
+ }
+
+ bool select=m_current->HasHilight();
+
+ if (TagAllChildrenUntilLast(first,last,select)) return;
+
+ TagNextChildren(first,last,select);
+}
+
+void wxTreeCtrl::SelectItem(const wxTreeItemId& itemId,
+ bool unselect_others,
+ bool extended_select)
+{
+ wxCHECK_RET( itemId.IsOk(), _T("invalid tree item") );
+
+ bool is_single=!(GetWindowStyleFlag() & wxTR_MULTIPLE);
+
+ //wxCHECK_RET( ( (!unselect_others) && is_single),
+ // _T("this is a single selection tree") );
+
+ // to keep going anyhow !!!
+ if (is_single)
+ {
+ unselect_others=TRUE;
+ extended_select=FALSE;
+ }
+
+ wxGenericTreeItem *item = itemId.m_pItem;
+
+ wxTreeEvent event( wxEVT_COMMAND_TREE_SEL_CHANGING, GetId() );
+ event.m_item = item;
+ event.m_itemOld = m_current;
+ event.SetEventObject( this );
+ // TODO : Here we don't send any selection mode yet !
+
+ if ( GetEventHandler()->ProcessEvent( event ) && event.WasVetoed() )
+ return;
+
+ // ctrl press
+ if (unselect_others)
+ {
+ if (is_single) Unselect(); // to speed up thing
+ else UnselectAll();
+ }
+
+ // shift press
+ if (extended_select)
+ {
+ if (m_current == NULL) m_current=m_key_current=GetRootItem().m_pItem;
+ // don't change the mark (m_current)
+ SelectItemRange(m_current, item);
+ }
+ else
+ {
+ bool select=TRUE; // the default
+
+ // Check if we need to toggle hilight (ctrl mode)
+ if (!unselect_others)
+ select=!item->HasHilight();
+
+ m_current = m_key_current = item;
+ m_current->SetHilight(select);
+ RefreshLine( m_current );
+ }
+
+ event.SetEventType(wxEVT_COMMAND_TREE_SEL_CHANGED);
+ GetEventHandler()->ProcessEvent( event );
+}
+
+void wxTreeCtrl::FillArray(wxGenericTreeItem *item, wxArrayTreeItemIds &array) const
+{
+ if (item->HasHilight()) array.Add(wxTreeItemId(item));
+
+ if (item->HasChildren())
+ {
+ wxArrayGenericTreeItems& children = item->GetChildren();
+ size_t count = children.Count();
+ for ( size_t n = 0; n < count; ++n )
+ FillArray(children[n],array);
+ }
+}
+
+size_t wxTreeCtrl::GetSelections(wxArrayTreeItemIds &array) const
+{
+ array.Empty();
+ FillArray(GetRootItem().m_pItem, array);
+
+ return array.Count();
+}
+
+void wxTreeCtrl::EnsureVisible(const wxTreeItemId& item)
+{
+ if (!item.IsOk()) return;
+
+ wxGenericTreeItem *gitem = item.m_pItem;
+
+ // first expand all parent branches
+ wxGenericTreeItem *parent = gitem->GetParent();
+ while ( parent && !parent->IsExpanded() )
+ {
+ Expand(parent);
+
+ parent = parent->GetParent();
+ }
+
+ if (parent) CalculatePositions();
+
+ ScrollTo(item);
+}
+
+void wxTreeCtrl::ScrollTo(const wxTreeItemId &item)
+{
+ if (!item.IsOk()) return;
+
+ wxGenericTreeItem *gitem = item.m_pItem;
+
+ // now scroll to the item
+ int item_y = gitem->GetY();
+
+ int start_x = 0;
+ int start_y = 0;
+ ViewStart( &start_x, &start_y );
+ start_y *= PIXELS_PER_UNIT;
+
+ int client_h = 0;
+ int client_w = 0;
+ GetClientSize( &client_w, &client_h );
+
+ if (item_y < start_y+3)
+ {
+ // going down
+ int x = 0;
+ int y = 0;
+ m_anchor->GetSize( x, y, this );
+ y += PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels
+ int x_pos = GetScrollPos( wxHORIZONTAL );
+ // Item should appear at top
+ SetScrollbars( PIXELS_PER_UNIT, PIXELS_PER_UNIT, x/PIXELS_PER_UNIT, y/PIXELS_PER_UNIT, x_pos, item_y/PIXELS_PER_UNIT );
+ }
+ else if (item_y+GetLineHeight(gitem) > start_y+client_h)
+ {
+ // going up
+ int x = 0;
+ int y = 0;
+ m_anchor->GetSize( x, y, this );
+ y += PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels
+ item_y += PIXELS_PER_UNIT+2;
+ int x_pos = GetScrollPos( wxHORIZONTAL );
+ // Item should appear at bottom
+ SetScrollbars( PIXELS_PER_UNIT, PIXELS_PER_UNIT, x/PIXELS_PER_UNIT, y/PIXELS_PER_UNIT, x_pos, (item_y+GetLineHeight(gitem)-client_h)/PIXELS_PER_UNIT );
+ }
+}