]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/treectrl.cpp
Corrected byte swapping macros.
[wxWidgets.git] / src / generic / treectrl.cpp
index 804148c710fcd255cbfcdfa035135520431ec485..b3bdc84ab72391745bfdfc2b39fd3693ed400273 100644 (file)
@@ -83,7 +83,7 @@ public:
   int GetX() const { return m_x; }
   int GetY() const { return m_y; }
 
-  void SetHeight(int h) { m_height = h; }
+  void SetHeight(int h) { m_text_height = h; }
 
   void SetX(int x) { m_x = x; }
   void SetY(int y) { m_y = y; }
@@ -139,7 +139,7 @@ private:
   int                 m_isBold      :1; // render the label in bold font
 
   int                 m_x, m_y;
-  long                m_height, m_width;
+  long                m_text_height, m_text_width;
   int                 m_xCross, m_yCross;
   int                 m_level;
   wxArrayTreeItems    m_children;
@@ -189,7 +189,7 @@ wxGenericTreeItem::wxGenericTreeItem(wxGenericTreeItem *parent,
 
   m_parent = parent;
 
-  dc.GetTextExtent( m_text, &m_width, &m_height );
+  dc.GetTextExtent( m_text, &m_text_width, &m_text_height );
 }
 
 wxGenericTreeItem::~wxGenericTreeItem()
@@ -197,7 +197,7 @@ wxGenericTreeItem::~wxGenericTreeItem()
   delete m_data;
 
   wxASSERT_MSG( m_children.IsEmpty(),
-                "please call DeleteChildren() before deleting the item" );
+                _T("please call DeleteChildren() before deleting the item") );
 }
 
 void wxGenericTreeItem::DeleteChildren(wxTreeCtrl *tree)
@@ -222,7 +222,7 @@ void wxGenericTreeItem::SetText( const wxString &text, wxDC& dc )
 {
   m_text = text;
 
-  dc.GetTextExtent( m_text, &m_width, &m_height );
+  dc.GetTextExtent( m_text, &m_text_width, &m_text_height );
 }
 
 void wxGenericTreeItem::Reset()
@@ -232,7 +232,7 @@ void wxGenericTreeItem::Reset()
   m_selImage = -1;
   m_data = NULL;
   m_x = m_y =
-  m_height = m_width = 0;
+  m_text_height = m_text_width = 0;
   m_xCross =
   m_yCross = 0;
 
@@ -268,7 +268,7 @@ void wxGenericTreeItem::SetCross( int x, int y )
 void wxGenericTreeItem::GetSize( int &x, int &y )
 {
   if ( y < m_y ) y = m_y;
-  int width = m_x +  m_width;
+  int width = m_x +  m_text_width;
   if (width > x) x = width;
 
   if (IsExpanded())
@@ -284,9 +284,10 @@ void wxGenericTreeItem::GetSize( int &x, int &y )
 wxGenericTreeItem *wxGenericTreeItem::HitTest( const wxPoint& point,
                                                bool &onButton )
 {
-  if ((point.y > m_y) && (point.y < m_y + m_height))
+  if ((point.y > m_y) && (point.y < m_y + m_text_height))
   {
     // FIXME why +5?
+    //  Because that is the size of the plus sign, RR
     if ((point.x > m_xCross-5) && (point.x < m_xCross+5) &&
         (point.y > m_yCross-5) && (point.y < m_yCross+5) &&
         (IsExpanded() || HasPlus()))
@@ -295,8 +296,10 @@ wxGenericTreeItem *wxGenericTreeItem::HitTest( const wxPoint& point,
       return this;
     }
 
-    int w = m_width;
-    if (m_image != -1) w += 20;
+    /* TODO: we should do a query here like
+         m_imageListNormal->GetSize( item->GetImage(), image_w, image_h );  */
+    int w = m_text_width;
+    if (m_image != -1) w += 24;
 
     if ((point.x > m_x) && (point.x < m_x+w))
     {
@@ -350,6 +353,7 @@ void wxTreeCtrl::Init()
   m_yScroll = 0;
   m_lineHeight = 10;
   m_indent = 15;
+  m_spacing = 18;
 
   m_hilightBrush = new wxBrush
     (
@@ -400,12 +404,20 @@ size_t wxTreeCtrl::GetCount() const
 void wxTreeCtrl::SetIndent(unsigned int indent)
 {
   m_indent = indent;
+  m_dirty = TRUE;
+  Refresh();
+}
+
+void wxTreeCtrl::SetSpacing(unsigned int spacing)
+{
+  m_spacing = spacing;
+  m_dirty = TRUE;
   Refresh();
 }
 
 size_t wxTreeCtrl::GetChildrenCount(const wxTreeItemId& item, bool recursively)
 {
-  wxCHECK_MSG( item.IsOk(), 0u, "invalid tree item" );
+  wxCHECK_MSG( item.IsOk(), 0u, _T("invalid tree item") );
 
   return item.m_pItem->GetChildrenCount(recursively);
 }
@@ -416,35 +428,35 @@ size_t wxTreeCtrl::GetChildrenCount(const wxTreeItemId& item, bool recursively)
 
 wxString wxTreeCtrl::GetItemText(const wxTreeItemId& item) const
 {
-  wxCHECK_MSG( item.IsOk(), "", "invalid tree item" );
+  wxCHECK_MSG( item.IsOk(), _T(""), _T("invalid tree item") );
 
   return item.m_pItem->GetText();
 }
 
 int wxTreeCtrl::GetItemImage(const wxTreeItemId& item) const
 {
-  wxCHECK_MSG( item.IsOk(), -1, "invalid tree item" );
+  wxCHECK_MSG( item.IsOk(), -1, _T("invalid tree item") );
 
   return item.m_pItem->GetImage();
 }
 
 int wxTreeCtrl::GetItemSelectedImage(const wxTreeItemId& item) const
 {
-  wxCHECK_MSG( item.IsOk(), -1, "invalid tree item" );
+  wxCHECK_MSG( item.IsOk(), -1, _T("invalid tree item") );
 
   return item.m_pItem->GetSelectedImage();
 }
 
 wxTreeItemData *wxTreeCtrl::GetItemData(const wxTreeItemId& item) const
 {
-  wxCHECK_MSG( item.IsOk(), NULL, "invalid tree item" );
+  wxCHECK_MSG( item.IsOk(), NULL, _T("invalid tree item") );
 
   return item.m_pItem->GetData();
 }
 
 void wxTreeCtrl::SetItemText(const wxTreeItemId& item, const wxString& text)
 {
-  wxCHECK_RET( item.IsOk(), "invalid tree item" );
+  wxCHECK_RET( item.IsOk(), _T("invalid tree item") );
 
   wxClientDC dc(this);
   wxGenericTreeItem *pItem = item.m_pItem;
@@ -454,7 +466,7 @@ void wxTreeCtrl::SetItemText(const wxTreeItemId& item, const wxString& text)
 
 void wxTreeCtrl::SetItemImage(const wxTreeItemId& item, int image)
 {
-  wxCHECK_RET( item.IsOk(), "invalid tree item" );
+  wxCHECK_RET( item.IsOk(), _T("invalid tree item") );
 
   wxGenericTreeItem *pItem = item.m_pItem;
   pItem->SetImage(image);
@@ -463,7 +475,7 @@ void wxTreeCtrl::SetItemImage(const wxTreeItemId& item, int image)
 
 void wxTreeCtrl::SetItemSelectedImage(const wxTreeItemId& item, int image)
 {
-  wxCHECK_RET( item.IsOk(), "invalid tree item" );
+  wxCHECK_RET( item.IsOk(), _T("invalid tree item") );
 
   wxGenericTreeItem *pItem = item.m_pItem;
   pItem->SetSelectedImage(image);
@@ -472,14 +484,14 @@ void wxTreeCtrl::SetItemSelectedImage(const wxTreeItemId& item, int image)
 
 void wxTreeCtrl::SetItemData(const wxTreeItemId& item, wxTreeItemData *data)
 {
-  wxCHECK_RET( item.IsOk(), "invalid tree item" );
+  wxCHECK_RET( item.IsOk(), _T("invalid tree item") );
 
   item.m_pItem->SetData(data);
 }
 
 void wxTreeCtrl::SetItemHasChildren(const wxTreeItemId& item, bool has)
 {
-  wxCHECK_RET( item.IsOk(), "invalid tree item" );
+  wxCHECK_RET( item.IsOk(), _T("invalid tree item") );
 
   wxGenericTreeItem *pItem = item.m_pItem;
   pItem->SetHasPlus(has);
@@ -488,7 +500,7 @@ void wxTreeCtrl::SetItemHasChildren(const wxTreeItemId& item, bool has)
 
 void wxTreeCtrl::SetItemBold(const wxTreeItemId& item, bool bold)
 {
-  wxCHECK_RET( item.IsOk(), "invalid tree item" );
+  wxCHECK_RET( item.IsOk(), _T("invalid tree item") );
 
   // avoid redrawing the tree if no real change
   wxGenericTreeItem *pItem = item.m_pItem;
@@ -505,35 +517,35 @@ void wxTreeCtrl::SetItemBold(const wxTreeItemId& item, bool bold)
 
 bool wxTreeCtrl::IsVisible(const wxTreeItemId& WXUNUSED(item)) const
 {
-  wxFAIL_MSG("not implemented");
+  wxFAIL_MSG(_T("not implemented"));
 
   return TRUE;
 }
 
 bool wxTreeCtrl::ItemHasChildren(const wxTreeItemId& item) const
 {
-  wxCHECK_MSG( item.IsOk(), FALSE, "invalid tree item" );
+  wxCHECK_MSG( item.IsOk(), FALSE, _T("invalid tree item") );
 
   return !item.m_pItem->GetChildren().IsEmpty();
 }
 
 bool wxTreeCtrl::IsExpanded(const wxTreeItemId& item) const
 {
-  wxCHECK_MSG( item.IsOk(), FALSE, "invalid tree item" );
+  wxCHECK_MSG( item.IsOk(), FALSE, _T("invalid tree item") );
 
   return item.m_pItem->IsExpanded();
 }
 
 bool wxTreeCtrl::IsSelected(const wxTreeItemId& item) const
 {
-  wxCHECK_MSG( item.IsOk(), FALSE, "invalid tree item" );
+  wxCHECK_MSG( item.IsOk(), FALSE, _T("invalid tree item") );
 
   return item.m_pItem->HasHilight();
 }
 
 bool wxTreeCtrl::IsBold(const wxTreeItemId& item) const
 {
-  wxCHECK_MSG( item.IsOk(), FALSE, "invalid tree item" );
+  wxCHECK_MSG( item.IsOk(), FALSE, _T("invalid tree item") );
 
   return item.m_pItem->IsBold();
 }
@@ -544,14 +556,14 @@ bool wxTreeCtrl::IsBold(const wxTreeItemId& item) const
 
 wxTreeItemId wxTreeCtrl::GetParent(const wxTreeItemId& item) const
 {
-  wxCHECK_MSG( item.IsOk(), wxTreeItemId(), "invalid tree item" );
+  wxCHECK_MSG( item.IsOk(), wxTreeItemId(), _T("invalid tree item") );
 
   return item.m_pItem->GetParent();
 }
 
 wxTreeItemId wxTreeCtrl::GetFirstChild(const wxTreeItemId& item, long& cookie) const
 {
-  wxCHECK_MSG( item.IsOk(), wxTreeItemId(), "invalid tree item" );
+  wxCHECK_MSG( item.IsOk(), wxTreeItemId(), _T("invalid tree item") );
 
   cookie = 0;
   return GetNextChild(item, cookie);
@@ -559,7 +571,7 @@ wxTreeItemId wxTreeCtrl::GetFirstChild(const wxTreeItemId& item, long& cookie) c
 
 wxTreeItemId wxTreeCtrl::GetNextChild(const wxTreeItemId& item, long& cookie) const
 {
-  wxCHECK_MSG( item.IsOk(), wxTreeItemId(), "invalid tree item" );
+  wxCHECK_MSG( item.IsOk(), wxTreeItemId(), _T("invalid tree item") );
 
   wxArrayTreeItems& children = item.m_pItem->GetChildren();
   if ( (size_t)cookie < children.Count() )
@@ -575,7 +587,7 @@ wxTreeItemId wxTreeCtrl::GetNextChild(const wxTreeItemId& item, long& cookie) co
 
 wxTreeItemId wxTreeCtrl::GetLastChild(const wxTreeItemId& item) const
 {
-  wxCHECK_MSG( item.IsOk(), wxTreeItemId(), "invalid tree item" );
+  wxCHECK_MSG( item.IsOk(), wxTreeItemId(), _T("invalid tree item") );
 
   wxArrayTreeItems& children = item.m_pItem->GetChildren();
   return (children.IsEmpty() ? wxTreeItemId() : wxTreeItemId(children.Last()));
@@ -583,7 +595,7 @@ wxTreeItemId wxTreeCtrl::GetLastChild(const wxTreeItemId& item) const
 
 wxTreeItemId wxTreeCtrl::GetNextSibling(const wxTreeItemId& item) const
 {
-  wxCHECK_MSG( item.IsOk(), wxTreeItemId(), "invalid tree item" );
+  wxCHECK_MSG( item.IsOk(), wxTreeItemId(), _T("invalid tree item") );
 
   wxGenericTreeItem *i = item.m_pItem;
   wxGenericTreeItem *parent = i->GetParent();
@@ -603,7 +615,7 @@ wxTreeItemId wxTreeCtrl::GetNextSibling(const wxTreeItemId& item) const
 
 wxTreeItemId wxTreeCtrl::GetPrevSibling(const wxTreeItemId& item) const
 {
-  wxCHECK_MSG( item.IsOk(), wxTreeItemId(), "invalid tree item" );
+  wxCHECK_MSG( item.IsOk(), wxTreeItemId(), _T("invalid tree item") );
 
   wxGenericTreeItem *i = item.m_pItem;
   wxGenericTreeItem *parent = i->GetParent();
@@ -623,25 +635,25 @@ wxTreeItemId wxTreeCtrl::GetPrevSibling(const wxTreeItemId& item) const
 
 wxTreeItemId wxTreeCtrl::GetFirstVisibleItem() const
 {
-  wxFAIL_MSG("not implemented");
+  wxFAIL_MSG(_T("not implemented"));
 
   return wxTreeItemId();
 }
 
 wxTreeItemId wxTreeCtrl::GetNextVisible(const wxTreeItemId& item) const
 {
-  wxCHECK_MSG( item.IsOk(), wxTreeItemId(), "invalid tree item" );
+  wxCHECK_MSG( item.IsOk(), wxTreeItemId(), _T("invalid tree item") );
 
-  wxFAIL_MSG("not implemented");
+  wxFAIL_MSG(_T("not implemented"));
 
   return wxTreeItemId();
 }
 
 wxTreeItemId wxTreeCtrl::GetPrevVisible(const wxTreeItemId& item) const
 {
-  wxCHECK_MSG( item.IsOk(), wxTreeItemId(), "invalid tree item" );
+  wxCHECK_MSG( item.IsOk(), wxTreeItemId(), _T("invalid tree item") );
 
-  wxFAIL_MSG("not implemented");
+  wxFAIL_MSG(_T("not implemented"));
 
   return wxTreeItemId();
 }
@@ -685,7 +697,7 @@ wxTreeItemId wxTreeCtrl::AddRoot(const wxString& text,
                                  int image, int selImage,
                                  wxTreeItemData *data)
 {
-  wxCHECK_MSG( !m_anchor, wxTreeItemId(), "tree can have only one root" );
+  wxCHECK_MSG( !m_anchor, wxTreeItemId(), _T("tree can have only one root") );
 
   wxClientDC dc(this);
   m_anchor = new wxGenericTreeItem((wxGenericTreeItem *)NULL, text, dc,
@@ -724,7 +736,7 @@ wxTreeItemId wxTreeCtrl::InsertItem(const wxTreeItemId& parentId,
 
   int index = parent->GetChildren().Index(idPrevious.m_pItem);
   wxASSERT_MSG( index != wxNOT_FOUND,
-                "previous item in wxTreeCtrl::InsertItem() is not a sibling" );
+                _T("previous item in wxTreeCtrl::InsertItem() is not a sibling") );
   return DoInsertItem(parentId, (size_t)index, text, image, selImage, data);
 }
 
@@ -876,32 +888,160 @@ void wxTreeCtrl::Unselect()
   }
 }
 
-void wxTreeCtrl::SelectItem(const wxTreeItemId& itemId)
+void wxTreeCtrl::UnselectAllChildren(wxGenericTreeItem *item)
 {
-  wxGenericTreeItem *item = itemId.m_pItem;
+  item->SetHilight(FALSE);
+  RefreshLine(item);
+  
+  if (item->HasChildren())
+    {
+      wxArrayTreeItems& children = item->GetChildren();
+      size_t count = children.Count();
+      for ( size_t n = 0; n < count; ++n )
+       UnselectAllChildren(children[n]);
+    }
+}
 
-  if ( m_current != item )
-  {
+void wxTreeCtrl::UnselectAll()
+{
+  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);
+
+    wxArrayTreeItems& 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())
+    {
+      wxArrayTreeItems& 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;
+
+/*
+  cout << first->GetText() << " " << last->GetText() << " " << (int) select << endl;
+*/
+  TagNextChildren(first,last,select);  
+}
+
+void wxTreeCtrl::SelectItem(const wxTreeItemId& itemId, 
+                           bool unselect_others, 
+                           bool extended_select)
+{ 
+    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 );
+    // Here we don't send any selection mode yet ! TO SEE 
+    
+/*
+    if (m_current)
+      cout << m_current->GetText() << " " << (int)m_current->HasHilight() << endl;
+*/
+
     if ( GetEventHandler()->ProcessEvent( event ) && event.WasVetoed() )
       return;
 
-    if ( m_current )
+/*
+    if (m_current)
+      cout << m_current->GetText() << " " << (int)m_current->HasHilight() << endl;
+*/
+
+    // ctrl press
+    if (unselect_others)
     {
-      m_current->SetHilight( FALSE );
-      RefreshLine( m_current );
+        if (is_single) Unselect(); // to speed up thing
+       else UnselectAll();
     }
 
-    m_current = item;
-    m_current->SetHilight( TRUE );
-    RefreshLine( m_current );
+    // shift press
+    if (extended_select) 
+    {
+        if (m_current == NULL) m_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 = item;
+       m_current->SetHilight(select);
+       RefreshLine( m_current );
+    }
 
     event.SetEventType(wxEVT_COMMAND_TREE_SEL_CHANGED);
     GetEventHandler()->ProcessEvent( event );
-  }
 }
 
 void wxTreeCtrl::EnsureVisible(const wxTreeItemId& item)
@@ -951,27 +1091,27 @@ void wxTreeCtrl::EnsureVisible(const wxTreeItemId& item)
 
 void wxTreeCtrl::ScrollTo(const wxTreeItemId& WXUNUSED(item))
 {
-    wxFAIL_MSG("not implemented");
+    wxFAIL_MSG(_T("not implemented"));
 }
 
 wxTextCtrl *wxTreeCtrl::EditLabel( const wxTreeItemId& WXUNUSED(item),
                                    wxClassInfo* WXUNUSED(textCtrlClass) )
 {
-    wxFAIL_MSG("not implemented");
+    wxFAIL_MSG(_T("not implemented"));
 
     return (wxTextCtrl*)NULL;
 }
 
 wxTextCtrl *wxTreeCtrl::GetEditControl() const
 {
-    wxFAIL_MSG("not implemented");
+    wxFAIL_MSG(_T("not implemented"));
 
     return (wxTextCtrl*)NULL;
 }
 
 void wxTreeCtrl::EndEditLabel(const wxTreeItemId& WXUNUSED(item), bool WXUNUSED(discardChanges))
 {
-    wxFAIL_MSG("not implemented");
+    wxFAIL_MSG(_T("not implemented"));
 }
 
 // FIXME: tree sorting functions are not reentrant and not MT-safe!
@@ -980,7 +1120,7 @@ static wxTreeCtrl *s_treeBeingSorted = NULL;
 static int tree_ctrl_compare_func(wxGenericTreeItem **item1,
                                   wxGenericTreeItem **item2)
 {
-    wxCHECK_MSG( s_treeBeingSorted, 0, "bug in wxTreeCtrl::SortChildren()" );
+    wxCHECK_MSG( s_treeBeingSorted, 0, _T("bug in wxTreeCtrl::SortChildren()") );
 
     return s_treeBeingSorted->OnCompareItems(*item1, *item2);
 }
@@ -988,17 +1128,17 @@ static int tree_ctrl_compare_func(wxGenericTreeItem **item1,
 int wxTreeCtrl::OnCompareItems(const wxTreeItemId& item1,
                                const wxTreeItemId& item2)
 {
-    return strcmp(GetItemText(item1), GetItemText(item2));
+    return wxStrcmp(GetItemText(item1), GetItemText(item2));
 }
 
 void wxTreeCtrl::SortChildren(const wxTreeItemId& itemId)
 {
-    wxCHECK_RET( itemId.IsOk(), "invalid tree item" );
+    wxCHECK_RET( itemId.IsOk(), _T("invalid tree item") );
 
     wxGenericTreeItem *item = itemId.m_pItem;
 
     wxCHECK_RET( !s_treeBeingSorted,
-                 "wxTreeCtrl::SortChildren is not reentrant" );
+                 _T("wxTreeCtrl::SortChildren is not reentrant") );
 
     wxArrayTreeItems& children = item->GetChildren();
     if ( children.Count() > 1 )
@@ -1089,7 +1229,7 @@ void wxTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc)
         }
         else
         {
-            wxFAIL_MSG("wxDC::GetFont() failed!");
+            wxFAIL_MSG(_T("wxDC::GetFont() failed!"));
         }
     }
 
@@ -1113,7 +1253,7 @@ void wxTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc)
     int total_h = (image_h > text_h) ? image_h : text_h;
     if(m_lineHeight > total_h) total_h = m_lineHeight;
     
-    dc.DrawRectangle( item->GetX()-2, item->GetY(), image_w+text_w+2, total_h );
+    dc.DrawRectangle( item->GetX()-2, item->GetY(), image_w+text_w+4, total_h );
 
     if ((item->IsExpanded()) && (item->GetSelectedImage() != -1))
     {
@@ -1149,11 +1289,11 @@ void wxTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxDC &dc, int level, int &
 {
     int horizX = level*m_indent;
 
-    item->SetX( horizX+33 );
+    item->SetX( horizX+m_indent+m_spacing );
     item->SetY( y-m_lineHeight/2 );
     item->SetHeight( m_lineHeight );
 
-    item->SetCross( horizX+15, y );
+    item->SetCross( horizX+m_indent, y );
 
     int oldY = y;
 
@@ -1163,24 +1303,25 @@ void wxTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxDC &dc, int level, int &
     if (IsExposed( exposed_x, exposed_y, 10000, m_lineHeight+4 ))  // 10000 = very much
     {
         int startX = horizX;
-        int endX = horizX + 10;
+        int endX = horizX + (m_indent-5);
 
+//        if (!item->HasChildren()) endX += (m_indent+5);
         if (!item->HasChildren()) endX += 20;
 
         dc.DrawLine( startX, y, endX, y );
 
         if (item->HasPlus())
         {
-            dc.DrawLine( horizX+20, y, horizX+30, y );
+            dc.DrawLine( horizX+(m_indent+5), y, horizX+(m_indent+15), y );
             dc.SetPen( *wxGREY_PEN );
             dc.SetBrush( *wxWHITE_BRUSH );
-            dc.DrawRectangle( horizX+10, y-4, 11, 9 );
+            dc.DrawRectangle( horizX+(m_indent-5), y-4, 11, 9 );
             dc.SetPen( *wxBLACK_PEN );
-            dc.DrawLine( horizX+13, y, horizX+18, y );
+            dc.DrawLine( horizX+(m_indent-2), y, horizX+(m_indent+3), y );
 
             if (!item->IsExpanded())
             {
-                dc.DrawLine( horizX+15, y-2, horizX+15, y+3 );
+                dc.DrawLine( horizX+m_indent, y-2, horizX+m_indent, y+3 );
             }
         }
 
@@ -1229,7 +1370,7 @@ void wxTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxDC &dc, int level, int &
         // delete all its children for example) - don't draw the vertical line
         // in this case
         if (count > 0)
-            dc.DrawLine( horizX+15, oldY+5, horizX+15, semiOldY );
+            dc.DrawLine( horizX+m_indent, oldY+5, horizX+m_indent, semiOldY );
     }
 }
 
@@ -1282,6 +1423,10 @@ void wxTreeCtrl::OnChar( wxKeyEvent &event )
         return;
     }
 
+    bool is_multiple=(GetWindowStyleFlag() & wxTR_MULTIPLE);
+    bool extended_select=(event.ShiftDown() && is_multiple);
+    bool unselect_others=!(extended_select || (event.ControlDown() && is_multiple));
+
     switch (event.KeyCode())
     {
         case '+':
@@ -1324,14 +1469,17 @@ void wxTreeCtrl::OnChar( wxKeyEvent &event )
                 if (!prev)
                 {
                     prev = GetParent( m_current );
-                    long cockie = 0;
-                    wxTreeItemId current = m_current;
-                    if (current == GetFirstChild( prev, cockie ))
-                    {
-                        // otherwise we return to where we came from
-                        SelectItem( prev );
-                        EnsureVisible( prev );
-                        break;
+                   if (prev)
+                   {
+                        long cockie = 0;
+                        wxTreeItemId current = m_current;
+                        if (current == GetFirstChild( prev, cockie ))
+                        {
+                            // otherwise we return to where we came from
+                            SelectItem( prev, unselect_others, extended_select );
+                            EnsureVisible( prev );
+                            break;
+                       }
                     }
                 }
                 if (prev)
@@ -1345,7 +1493,7 @@ void wxTreeCtrl::OnChar( wxKeyEvent &event )
                         }
                     }
 
-                    SelectItem( prev );
+                    SelectItem( prev, unselect_others, extended_select );
                     EnsureVisible( prev );
                 }
             }
@@ -1358,7 +1506,7 @@ void wxTreeCtrl::OnChar( wxKeyEvent &event )
                 if (prev)
                 {
                     EnsureVisible( prev );
-                    SelectItem( prev );
+                    SelectItem( prev, unselect_others, extended_select );
                 }
             }
             break;
@@ -1375,7 +1523,7 @@ void wxTreeCtrl::OnChar( wxKeyEvent &event )
                 {
                     long cookie = 0;
                     wxTreeItemId child = GetFirstChild( m_current, cookie );
-                    SelectItem( child );
+                    SelectItem( child, unselect_others, extended_select );
                     EnsureVisible( child );
                 }
                 else
@@ -1392,7 +1540,7 @@ void wxTreeCtrl::OnChar( wxKeyEvent &event )
                     }
                     if (next != 0)
                     {
-                        SelectItem( next );
+                        SelectItem( next, unselect_others, extended_select );
                         EnsureVisible( next );
                     }
                 }
@@ -1420,7 +1568,7 @@ void wxTreeCtrl::OnChar( wxKeyEvent &event )
                 if ( last.IsOk() )
                 {
                     EnsureVisible( last );
-                    SelectItem( last );
+                    SelectItem( last, unselect_others, extended_select );
                 }
             }
             break;
@@ -1432,7 +1580,7 @@ void wxTreeCtrl::OnChar( wxKeyEvent &event )
                 if (prev)
                 {
                     EnsureVisible( prev );
-                    SelectItem( prev );
+                    SelectItem( prev, unselect_others, extended_select );
                 }
             }
             break;
@@ -1489,8 +1637,11 @@ void wxTreeCtrl::OnMouse( wxMouseEvent &event )
         return;
     }
 
-    if (!IsSelected(item))
-        SelectItem(item);  /* we dont support multiple selections, BTW */
+    bool is_multiple=(GetWindowStyleFlag() & wxTR_MULTIPLE);
+    bool extended_select=(event.ShiftDown() && is_multiple);
+    bool unselect_others=!(extended_select || (event.ControlDown() && is_multiple));
+
+    SelectItem(item, unselect_others, extended_select);
 
     if (event.LeftDClick())
     {
@@ -1528,7 +1679,7 @@ void wxTreeCtrl::CalculateLevel( wxGenericTreeItem *item, wxDC &dc, int level, i
 {
     int horizX = level*m_indent;
 
-    item->SetX( horizX+33 );
+    item->SetX( horizX+m_indent+m_spacing );
     item->SetY( y-m_lineHeight/2 );
     item->SetHeight( m_lineHeight );