]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/treectlg.cpp
include wx/thread.h in debug build which is needed after last change
[wxWidgets.git] / src / generic / treectlg.cpp
index 9255fb67cbfda708bfa5ddba409b02da0a6bf40b..258e1c36d9a069d8730f6e8e099903d246b7354d 100644 (file)
@@ -1,5 +1,5 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        treectlg.cpp
+// Name:        src/generic/treectlg.cpp
 // Purpose:     generic tree control implementation
 // Author:      Robert Roebling
 // Created:     01/02/97
 // headers
 // -----------------------------------------------------------------------------
 
-#ifdef __GNUG__
-  #pragma implementation "treectlg.h"
-#endif
-
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
 
 #if wxUSE_TREECTRL
 
-#include "wx/treebase.h"
+#include "wx/treectrl.h"
+
+#ifndef WX_PRECOMP
+    #include "wx/dcclient.h"
+    #include "wx/timer.h"
+    #include "wx/settings.h"
+    #include "wx/listbox.h"
+    #include "wx/textctrl.h"
+#endif
+
 #include "wx/generic/treectlg.h"
-#include "wx/timer.h"
-#include "wx/textctrl.h"
 #include "wx/imaglist.h"
-#include "wx/settings.h"
-#include "wx/dcclient.h"
+
+#include "wx/renderer.h"
 
 #ifdef __WXMAC__
     #include "wx/mac/private.h"
@@ -48,7 +51,7 @@
 
 class WXDLLEXPORT wxGenericTreeItem;
 
-WX_DEFINE_EXPORTED_ARRAY(wxGenericTreeItem *, wxArrayGenericTreeItems);
+WX_DEFINE_EXPORTED_ARRAY_PTR(wxGenericTreeItem *, wxArrayGenericTreeItems);
 
 // ----------------------------------------------------------------------------
 // constants
@@ -58,53 +61,8 @@ static const int NO_IMAGE = -1;
 
 static const int PIXELS_PER_UNIT = 10;
 
-// ----------------------------------------------------------------------------
-// Aqua arrows
-// ----------------------------------------------------------------------------
-
-/* XPM */
-static const char *aqua_arrow_right[] = {
-/* columns rows colors chars-per-pixel */
-"13 11 4 1",
-"  c None",
-"b c #C0C0C0",
-"c c #707070",
-"d c #A0A0A0",
-/* pixels */
-"    b        ",
-"    ddb      ",
-"    cccdb    ",
-"    cccccd   ",
-"    ccccccdb ",
-"    ccccccccd",
-"    ccccccdb ",
-"    cccccb   ",
-"    cccdb    ",
-"    ddb      ",
-"    b        "
-};
-
-/* XPM */
-static const char *aqua_arrow_down[] = {
-/* columns rows colors chars-per-pixel */
-"13 11 4 1",
-"  c None",
-"b c #C0C0C0",
-"c c #707070",
-"d c #A0A0A0",
-/* pixels */
-"             ",
-"             ",
-" bdcccccccdb ",
-"  dcccccccd  ",
-"  bcccccccb  ",
-"   dcccccd   ",
-"   bcccccb   ",
-"    bcccd    ",
-"     dcd     ",
-"     bcb     ",
-"      d      "
-};
+// the margin between the item image and the item text
+static const int MARGIN_BETWEEN_IMAGE_AND_TEXT = 4;
 
 // -----------------------------------------------------------------------------
 // private classes
@@ -134,6 +92,31 @@ class WXDLLEXPORT wxTreeTextCtrl: public wxTextCtrl
 public:
     wxTreeTextCtrl(wxGenericTreeCtrl *owner, wxGenericTreeItem *item);
 
+    void EndEdit(bool discardChanges = false)
+    {
+        if ( discardChanges )
+        {
+            StopEditing();
+        }
+        else
+        {
+            m_aboutToFinish = true;
+
+            // Notify the owner about the changes
+            AcceptChanges();
+
+            // Even if vetoed, close the control (consistent with MSW)
+            Finish();
+        }
+    }
+
+    void StopEditing()
+    {
+        Finish();
+        m_owner->OnRenameCancelled(m_itemEdited);
+    }
+    const wxGenericTreeItem* item() const { return m_itemEdited; }
+
 protected:
     void OnChar( wxKeyEvent &event );
     void OnKeyUp( wxKeyEvent &event );
@@ -147,6 +130,7 @@ private:
     wxGenericTreeItem  *m_itemEdited;
     wxString            m_startValue;
     bool                m_finished;
+    bool                m_aboutToFinish;
 
     DECLARE_EVENT_TABLE()
     DECLARE_NO_COPY_CLASS(wxTreeTextCtrl)
@@ -200,7 +184,7 @@ public:
     void SetImage(int image, wxTreeItemIcon which) { m_images[which] = image; }
     void SetData(wxTreeItemData *data) { m_data = data; }
 
-    void SetHasPlus(bool has = TRUE) { m_hasPlus = has; }
+    void SetHasPlus(bool has = true) { m_hasPlus = has; }
 
     void SetBold(bool bold) { m_isBold = bold; }
 
@@ -219,12 +203,12 @@ public:
     wxGenericTreeItem *GetParent() const { return m_parent; }
 
     // operations
-        // deletes all children notifying the treectrl about it if !NULL
-        // pointer given
-    void DeleteChildren(wxGenericTreeCtrl *tree = NULL);
+
+    // deletes all children notifying the treectrl about it
+    void DeleteChildren(wxGenericTreeCtrl *tree);
 
     // get count of all children (and grand children if 'recursively')
-    size_t GetChildrenCount(bool recursively = TRUE) const;
+    size_t GetChildrenCount(bool recursively = true) const;
 
     void Insert(wxGenericTreeItem *child, size_t index)
     { m_children.Insert(child, index); }
@@ -232,17 +216,17 @@ public:
     void GetSize( int &x, int &y, const wxGenericTreeCtrl* );
 
         // return the item at given position (or NULL if no item), onButton is
-        // TRUE if the point belongs to the item's button, otherwise it lies
-        // on the button's label
+        // true if the point belongs to the item's button, otherwise it lies
+        // on the item's label
     wxGenericTreeItem *HitTest( const wxPoint& point,
                                 const wxGenericTreeCtrl *,
                                 int &flags,
                                 int level );
 
-    void Expand() { m_isCollapsed = FALSE; }
-    void Collapse() { m_isCollapsed = TRUE; }
+    void Expand() { m_isCollapsed = false; }
+    void Collapse() { m_isCollapsed = true; }
 
-    void SetHilight( bool set = TRUE ) { m_hasHilight = set; }
+    void SetHilight( bool set = true ) { m_hasHilight = set; }
 
     // status inquiries
     bool HasChildren() const { return !m_children.IsEmpty(); }
@@ -260,7 +244,7 @@ public:
         if ( !m_attr )
         {
             m_attr = new wxTreeItemAttr;
-            m_ownsAttr = TRUE;
+            m_ownsAttr = true;
         }
         return *m_attr;
     }
@@ -269,13 +253,13 @@ public:
     {
         if ( m_ownsAttr ) delete m_attr;
         m_attr = attr;
-        m_ownsAttr = FALSE;
+        m_ownsAttr = false;
     }
         // set them and delete when done
     void AssignAttributes(wxTreeItemAttr *attr)
     {
         SetAttributes(attr);
-        m_ownsAttr = TRUE;
+        m_ownsAttr = true;
     }
 
 private:
@@ -293,20 +277,20 @@ private:
 
     // tree ctrl images for the normal, selected, expanded and
     // expanded+selected states
-    short               m_images[wxTreeItemIcon_Max];
+    int                 m_images[wxTreeItemIcon_Max];
 
     wxCoord             m_x;            // (virtual) offset from top
     wxCoord             m_y;            // (virtual) offset from left
-    short               m_width;        // width of this item
-    unsigned char       m_height;       // height of this item
+    int                 m_width;        // width of this item
+    int                 m_height;       // height of this item
 
     // use bitfields to save size
-    int                 m_isCollapsed :1;
-    int                 m_hasHilight  :1; // same as focused
-    int                 m_hasPlus     :1; // used for item which doesn't have
+    unsigned int        m_isCollapsed :1;
+    unsigned int        m_hasHilight  :1; // same as focused
+    unsigned int        m_hasPlus     :1; // used for item which doesn't have
                                           // children but has a [+] button
-    int                 m_isBold      :1; // render the label in bold font
-    int                 m_ownsAttr    :1; // delete attribute when done
+    unsigned int        m_isBold      :1; // render the label in bold font
+    unsigned int        m_ownsAttr    :1; // delete attribute when done
 
     DECLARE_NO_COPY_CLASS(wxGenericTreeItem)
 };
@@ -334,20 +318,20 @@ static void EventFlagsToSelType(long style,
 }
 
 // check if the given item is under another one
-static bool IsDescendantOf(wxGenericTreeItem *parent, wxGenericTreeItem *item)
+static bool IsDescendantOf(const wxGenericTreeItem *parent, const wxGenericTreeItem *item)
 {
     while ( item )
     {
         if ( item == parent )
         {
             // item is a descendant of parent
-            return TRUE;
+            return true;
         }
 
         item = item->GetParent();
     }
 
-    return FALSE;
+    return false;
 }
 
 // -----------------------------------------------------------------------------
@@ -379,7 +363,8 @@ wxTreeTextCtrl::wxTreeTextCtrl(wxGenericTreeCtrl *owner,
               : m_itemEdited(item), m_startValue(item->GetText())
 {
     m_owner = owner;
-    m_finished = FALSE;
+    m_finished = false;
+    m_aboutToFinish = false;
 
     int w = m_itemEdited->GetWidth(),
         h = m_itemEdited->GetHeight();
@@ -396,7 +381,7 @@ wxTreeTextCtrl::wxTreeTextCtrl(wxGenericTreeCtrl *owner,
         if ( m_owner->m_imageListNormal )
         {
             m_owner->m_imageListNormal->GetSize( image, image_w, image_h );
-            image_w += 4;
+            image_w += MARGIN_BETWEEN_IMAGE_AND_TEXT;
         }
         else
         {
@@ -407,6 +392,16 @@ wxTreeTextCtrl::wxTreeTextCtrl(wxGenericTreeCtrl *owner,
     // FIXME: what are all these hardcoded 4, 8 and 11s really?
     x += image_w;
     w -= image_w + 4;
+#ifdef __WXMAC__
+    wxSize bs = DoGetBestSize() ;
+    // edit control height
+    if ( h > bs.y - 8 )
+    {
+        int diff = h - ( bs.y - 8 ) ;
+        h -= diff ;
+        y += diff / 2 ;
+    }
+#endif
 
     (void)Create(m_owner, wxID_ANY, m_startValue,
                  wxPoint(x - 4, y - 4), wxSize(w + 11, h + 8));
@@ -419,32 +414,38 @@ bool wxTreeTextCtrl::AcceptChanges()
     if ( value == m_startValue )
     {
         // nothing changed, always accept
-        return TRUE;
+        // when an item remains unchanged, the owner
+        // needs to be notified that the user decided
+        // not to change the tree item label, and that
+        // the edit has been cancelled
+
+        m_owner->OnRenameCancelled(m_itemEdited);
+        return true;
     }
 
     if ( !m_owner->OnRenameAccept(m_itemEdited, value) )
     {
         // vetoed by the user
-        return FALSE;
+        return false;
     }
 
     // accepted, do rename the item
     m_owner->SetItemText(m_itemEdited, value);
 
-    return TRUE;
+    return true;
 }
 
 void wxTreeTextCtrl::Finish()
 {
-    if ( !m_finished )
+    if ( !m_finished  )
     {
         m_owner->ResetTextControl();
 
         wxPendingDelete.Append(this);
 
-        m_finished = TRUE;
+        m_finished = true;
 
-        m_owner->SetFocus(); // This doesn't work. TODO.
+        m_owner->SetFocus();
     }
 }
 
@@ -453,16 +454,11 @@ void wxTreeTextCtrl::OnChar( wxKeyEvent &event )
     switch ( event.m_keyCode )
     {
         case WXK_RETURN:
-            if ( !AcceptChanges() )
-            {
-                // vetoed by the user, don't disappear
-                break;
-            }
-            //else: fall through
+            EndEdit();
+            break;
 
         case WXK_ESCAPE:
-            Finish();
-            m_owner->OnRenameCancelled(m_itemEdited);
+            StopEditing();
             break;
 
         default:
@@ -484,7 +480,7 @@ void wxTreeTextCtrl::OnKeyUp( wxKeyEvent &event )
             sx = parentSize.x - myPos.x;
         if (mySize.x > sx)
             sx = mySize.x;
-        SetSize(sx, -1);
+        SetSize(sx, wxDefaultCoord);
     }
 
     event.Skip();
@@ -492,16 +488,19 @@ void wxTreeTextCtrl::OnKeyUp( wxKeyEvent &event )
 
 void wxTreeTextCtrl::OnKillFocus( wxFocusEvent &event )
 {
-    if ( m_finished )
-    {
-        event.Skip();
-        return;
-    }
-
-    if ( AcceptChanges() )
+    if ( !m_finished && !m_aboutToFinish )
     {
+        // We must finish regardless of success, otherwise we'll get
+        // focus problems:
         Finish();
+
+        if ( !AcceptChanges() )
+            m_owner->OnRenameCancelled( m_itemEdited );
     }
+
+    // We must let the native text control handle focus, too, otherwise
+    // it could have problems with the cursor (e.g., in wxGTK).
+    event.Skip();
 }
 
 // -----------------------------------------------------------------------------
@@ -522,15 +521,15 @@ wxGenericTreeItem::wxGenericTreeItem(wxGenericTreeItem *parent,
     m_data = data;
     m_x = m_y = 0;
 
-    m_isCollapsed = TRUE;
-    m_hasHilight = FALSE;
-    m_hasPlus = FALSE;
-    m_isBold = FALSE;
+    m_isCollapsed = true;
+    m_hasHilight = false;
+    m_hasPlus = false;
+    m_isBold = false;
 
     m_parent = parent;
 
     m_attr = (wxTreeItemAttr *)NULL;
-    m_ownsAttr = FALSE;
+    m_ownsAttr = false;
 
     // We don't know the height here yet.
     m_width = 0;
@@ -553,10 +552,11 @@ void wxGenericTreeItem::DeleteChildren(wxGenericTreeCtrl *tree)
     for ( size_t n = 0; n < count; n++ )
     {
         wxGenericTreeItem *child = m_children[n];
-        if (tree)
-            tree->SendDeleteEvent(child);
+        tree->SendDeleteEvent(child);
 
         child->DeleteChildren(tree);
+        if ( child == tree->m_select_me )
+            tree->m_select_me = NULL;
         delete child;
     }
 
@@ -619,11 +619,19 @@ wxGenericTreeItem *wxGenericTreeItem::HitTest(const wxPoint& point,
             else
                 flags |= wxTREE_HITTEST_ONITEMLOWERPART;
 
-            // 5 is the size of the plus sign
             int xCross = m_x - theCtrl->GetSpacing();
-            if ((point.x > xCross-5) && (point.x < xCross+5) &&
-                (point.y > y_mid-5) && (point.y < y_mid+5) &&
+#ifdef __WXMAC__
+            // according to the drawing code the triangels are drawn
+            // at -4 , -4  from the position up to +10/+10 max
+            if ((point.x > xCross-4) && (point.x < xCross+10) &&
+                (point.y > y_mid-4) && (point.y < y_mid+10) &&
+                HasPlus() && theCtrl->HasButtons() )
+#else
+            // 5 is the size of the plus sign
+            if ((point.x > xCross-6) && (point.x < xCross+6) &&
+                (point.y > y_mid-6) && (point.y < y_mid+6) &&
                 HasPlus() && theCtrl->HasButtons() )
+#endif
             {
                 flags |= wxTREE_HITTEST_ONITEMBUTTON;
                 return this;
@@ -708,18 +716,19 @@ int wxGenericTreeItem::GetCurrentImage() const
 // wxGenericTreeCtrl implementation
 // -----------------------------------------------------------------------------
 
-IMPLEMENT_DYNAMIC_CLASS(wxGenericTreeCtrl, wxScrolledWindow)
+IMPLEMENT_DYNAMIC_CLASS(wxGenericTreeCtrl, wxControl)
 
-BEGIN_EVENT_TABLE(wxGenericTreeCtrl,wxScrolledWindow)
+BEGIN_EVENT_TABLE(wxGenericTreeCtrl, wxTreeCtrlBase)
     EVT_PAINT          (wxGenericTreeCtrl::OnPaint)
+    EVT_SIZE           (wxGenericTreeCtrl::OnSize)
     EVT_MOUSE_EVENTS   (wxGenericTreeCtrl::OnMouse)
     EVT_CHAR           (wxGenericTreeCtrl::OnChar)
     EVT_SET_FOCUS      (wxGenericTreeCtrl::OnSetFocus)
     EVT_KILL_FOCUS     (wxGenericTreeCtrl::OnKillFocus)
-    EVT_IDLE           (wxGenericTreeCtrl::OnIdle)
+    EVT_TREE_ITEM_GETTOOLTIP(wxID_ANY, wxGenericTreeCtrl::OnGetToolTip)
 END_EVENT_TABLE()
 
-#if !defined(__WXMSW__) || defined(__WIN16__) || defined(__WXUNIVERSAL__)
+#if !defined(__WXMSW__) || defined(__WXUNIVERSAL__)
 /*
  * wxTreeCtrl has to be a real class or we have problems with
  * the run-time information.
@@ -734,9 +743,12 @@ IMPLEMENT_DYNAMIC_CLASS(wxTreeCtrl, wxGenericTreeCtrl)
 
 void wxGenericTreeCtrl::Init()
 {
-    m_current = m_key_current = m_anchor = m_select_me = (wxGenericTreeItem *) NULL;
-    m_hasFocus = FALSE;
-    m_dirty = FALSE;
+    m_current =
+    m_key_current =
+    m_anchor =
+    m_select_me = (wxGenericTreeItem *) NULL;
+    m_hasFocus = false;
+    m_dirty = false;
 
     m_lineHeight = 10;
     m_indent = 15;
@@ -760,22 +772,29 @@ void wxGenericTreeCtrl::Init()
                                  wxSOLID
                               );
 
-    m_imageListNormal = m_imageListButtons =
-    m_imageListState = (wxImageList *) NULL;
-    m_ownsImageListNormal = m_ownsImageListButtons =
-    m_ownsImageListState = FALSE;
+    m_imageListButtons = NULL;
+    m_ownsImageListButtons = false;
 
     m_dragCount = 0;
-    m_isDragging = FALSE;
-    m_dropTarget = m_oldSelection = (wxGenericTreeItem *)NULL;
+    m_isDragging = false;
+    m_dropTarget = m_oldSelection = NULL;
+    m_underMouse = NULL;
     m_textCtrl = NULL;
 
     m_renameTimer = NULL;
+    m_freezeCount = 0;
+
     m_findTimer = NULL;
 
-    m_lastOnSame = FALSE;
+    m_dropEffectAboveItem = false;
+
+    m_lastOnSame = false;
 
+#ifdef __WXMAC_CARBON__
+    m_normalFont.MacCreateThemeFont( kThemeViewsFont ) ;
+#else
     m_normalFont = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT );
+#endif
     m_boldFont = wxFont(m_normalFont.GetPointSize(),
                         m_normalFont.GetFamily(),
                         m_normalFont.GetStyle(),
@@ -790,36 +809,31 @@ bool wxGenericTreeCtrl::Create(wxWindow *parent,
                                const wxPoint& pos,
                                const wxSize& size,
                                long style,
-                               const wxValidator &validator,
+                               const wxValidatorvalidator,
                                const wxString& name )
 {
 #ifdef __WXMAC__
     int major,minor;
     wxGetOsVersion( &major, &minor );
 
-    if (style & wxTR_HAS_BUTTONS) style |= wxTR_MAC_BUTTONS;
-    if (style & wxTR_HAS_BUTTONS) style &= ~wxTR_HAS_BUTTONS;
     style &= ~wxTR_LINES_AT_ROOT;
     style |= wxTR_NO_LINES;
     if (major < 10)
         style |= wxTR_ROW_LINES;
-    if (major >= 10)
-        style |= wxTR_AQUA_BUTTONS;
+        
+    if (style == 0 || style & wxTR_DEFAULT_STYLE)
+        style |= wxTR_FULL_ROW_HIGHLIGHT;
+        
+#endif // __WXMAC__
+#ifdef __WXGTK20__
+    style |= wxTR_NO_LINES;
 #endif
 
-    if (style & wxTR_AQUA_BUTTONS)
-    {
-        m_arrowRight = new wxBitmap( aqua_arrow_right );
-        m_arrowDown = new wxBitmap( aqua_arrow_down );
-    }
-    else
-    {
-        m_arrowRight = NULL;
-        m_arrowDown = NULL;
-    }
-
-    wxScrolledWindow::Create( parent, id, pos, size,
-                              style|wxHSCROLL|wxVSCROLL, name );
+    if ( !wxControl::Create( parent, id, pos, size,
+                             style|wxHSCROLL|wxVSCROLL,
+                             validator,
+                             name ) )
+        return false;
 
     // If the tree display has no buttons, but does have
     // connecting lines, we can use a narrower layout.
@@ -830,17 +844,17 @@ bool wxGenericTreeCtrl::Create(wxWindow *parent,
         m_spacing = 10;
     }
 
-#if wxUSE_VALIDATORS
-    SetValidator( validator );
-#endif
-
-    SetForegroundColour( wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT) );
-    SetBackgroundColour( wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOX) );
+    wxVisualAttributes attr = GetDefaultAttributes();
+    SetOwnForegroundColour( attr.colFg );
+    SetOwnBackgroundColour( attr.colBg );
+    if (!m_hasFont)
+        SetOwnFont(attr.font);
 
-//  m_dottedPen = wxPen( "grey", 0, wxDOT );  too slow under XFree86
     m_dottedPen = wxPen( wxT("grey"), 0, 0 );
 
-    return TRUE;
+    SetInitialSize(size);
+
+    return true;
 }
 
 wxGenericTreeCtrl::~wxGenericTreeCtrl()
@@ -848,18 +862,11 @@ wxGenericTreeCtrl::~wxGenericTreeCtrl()
     delete m_hilightBrush;
     delete m_hilightUnfocusedBrush;
 
-    delete m_arrowRight;
-    delete m_arrowDown;
-
     DeleteAllItems();
 
     delete m_renameTimer;
     delete m_findTimer;
 
-    if (m_ownsImageListNormal)
-        delete m_imageListNormal;
-    if (m_ownsImageListState)
-        delete m_imageListState;
     if (m_ownsImageListButtons)
         delete m_imageListButtons;
 }
@@ -868,24 +875,33 @@ wxGenericTreeCtrl::~wxGenericTreeCtrl()
 // accessors
 // -----------------------------------------------------------------------------
 
-size_t wxGenericTreeCtrl::GetCount() const
+unsigned int wxGenericTreeCtrl::GetCount() const
 {
-    return m_anchor == NULL ? 0u : m_anchor->GetChildrenCount();
+    if ( !m_anchor )
+    {
+        // the tree is empty
+        return 0;
+    }
+
+    unsigned int count = m_anchor->GetChildrenCount();
+    if ( !HasFlag(wxTR_HIDE_ROOT) )
+    {
+        // take the root itself into account
+        count++;
+    }
+
+    return count;
 }
 
 void wxGenericTreeCtrl::SetIndent(unsigned int indent)
 {
     m_indent = (unsigned short) indent;
-    m_dirty = TRUE;
-}
-
-void wxGenericTreeCtrl::SetSpacing(unsigned int spacing)
-{
-    m_spacing = (unsigned short) spacing;
-    m_dirty = TRUE;
+    m_dirty = true;
 }
 
-size_t wxGenericTreeCtrl::GetChildrenCount(const wxTreeItemId& item, bool recursively)
+size_t
+wxGenericTreeCtrl::GetChildrenCount(const wxTreeItemId& item,
+                                    bool recursively) const
 {
     wxCHECK_MSG( item.IsOk(), 0u, wxT("invalid tree item") );
 
@@ -894,7 +910,8 @@ size_t wxGenericTreeCtrl::GetChildrenCount(const wxTreeItemId& item, bool recurs
 
 void wxGenericTreeCtrl::SetWindowStyle(const long styles)
 {
-    if (!HasFlag(wxTR_HIDE_ROOT) && (styles & wxTR_HIDE_ROOT))
+    // Do not try to expand the root node if it hasn't been created yet
+    if (m_anchor && !HasFlag(wxTR_HIDE_ROOT) && (styles & wxTR_HIDE_ROOT))
     {
         // if we will hide the root, make sure children are visible
         m_anchor->SetHasPlus();
@@ -906,7 +923,7 @@ void wxGenericTreeCtrl::SetWindowStyle(const long styles)
     // want to update the inherited styles, but right now
     // none of the parents has updatable styles
     m_windowStyle = styles;
-    m_dirty = TRUE;
+    m_dirty = true;
 }
 
 // -----------------------------------------------------------------------------
@@ -915,7 +932,7 @@ void wxGenericTreeCtrl::SetWindowStyle(const long styles)
 
 wxString wxGenericTreeCtrl::GetItemText(const wxTreeItemId& item) const
 {
-    wxCHECK_MSG( item.IsOk(), wxT(""), wxT("invalid tree item") );
+    wxCHECK_MSG( item.IsOk(), wxEmptyString, wxT("invalid tree item") );
 
     return ((wxGenericTreeItem*) item.m_pItem)->GetText();
 }
@@ -988,6 +1005,9 @@ void wxGenericTreeCtrl::SetItemData(const wxTreeItemId& item, wxTreeItemData *da
 {
     wxCHECK_RET( item.IsOk(), wxT("invalid tree item") );
 
+    if (data)
+        data->SetId( item );
+
     ((wxGenericTreeItem*) item.m_pItem)->SetData(data);
 }
 
@@ -1009,10 +1029,35 @@ void wxGenericTreeCtrl::SetItemBold(const wxTreeItemId& item, bool bold)
     if ( pItem->IsBold() != bold )
     {
         pItem->SetBold(bold);
+
+        // recalculate the item size as bold and non bold fonts have different
+        // widths
+        wxClientDC dc(this);
+        CalculateSize(pItem, dc);
+
         RefreshLine(pItem);
     }
 }
 
+void wxGenericTreeCtrl::SetItemDropHighlight(const wxTreeItemId& item,
+                                             bool highlight)
+{
+    wxCHECK_RET( item.IsOk(), wxT("invalid tree item") );
+
+    wxColour fg, bg;
+
+    if (highlight)
+    {
+        bg = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT);
+        fg = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT);
+    }
+
+    wxGenericTreeItem *pItem = (wxGenericTreeItem*) item.m_pItem;
+    pItem->Attr().SetTextColour(fg);
+    pItem->Attr().SetBackgroundColour(bg);
+    RefreshLine(pItem);
+}
+
 void wxGenericTreeCtrl::SetItemTextColour(const wxTreeItemId& item,
                                    const wxColour& col)
 {
@@ -1044,7 +1089,7 @@ void wxGenericTreeCtrl::SetItemFont(const wxTreeItemId& item, const wxFont& font
 
 bool wxGenericTreeCtrl::SetFont( const wxFont &font )
 {
-    wxScrolledWindow::SetFont(font);
+    wxTreeCtrlBase::SetFont(font);
 
     m_normalFont = font ;
     m_boldFont = wxFont(m_normalFont.GetPointSize(),
@@ -1055,7 +1100,7 @@ bool wxGenericTreeCtrl::SetFont( const wxFont &font )
                         m_normalFont.GetFaceName(),
                         m_normalFont.GetEncoding());
 
-    return TRUE;
+    return true;
 }
 
 
@@ -1065,7 +1110,7 @@ bool wxGenericTreeCtrl::SetFont( const wxFont &font )
 
 bool wxGenericTreeCtrl::IsVisible(const wxTreeItemId& item) const
 {
-    wxCHECK_MSG( item.IsOk(), FALSE, wxT("invalid tree item") );
+    wxCHECK_MSG( item.IsOk(), false, wxT("invalid tree item") );
 
     // An item is only visible if it's not a descendant of a collapsed item
     wxGenericTreeItem *pItem = (wxGenericTreeItem*) item.m_pItem;
@@ -1073,7 +1118,7 @@ bool wxGenericTreeCtrl::IsVisible(const wxTreeItemId& item) const
     while (parent)
     {
         if (!parent->IsExpanded())
-            return FALSE;
+            return false;
         parent = parent->GetParent();
     }
 
@@ -1084,20 +1129,20 @@ bool wxGenericTreeCtrl::IsVisible(const wxTreeItemId& item) const
 
     wxRect rect;
     if (!GetBoundingRect(item, rect))
-        return FALSE;
+        return false;
     if (rect.GetWidth() == 0 || rect.GetHeight() == 0)
-        return FALSE;
+        return false;
     if (rect.GetBottom() < 0 || rect.GetTop() > clientSize.y)
-        return FALSE;
+        return false;
     if (rect.GetRight() < 0 || rect.GetLeft() > clientSize.x)
-        return FALSE;
+        return false;
 
-    return TRUE;
+    return true;
 }
 
 bool wxGenericTreeCtrl::ItemHasChildren(const wxTreeItemId& item) const
 {
-    wxCHECK_MSG( item.IsOk(), FALSE, wxT("invalid tree item") );
+    wxCHECK_MSG( item.IsOk(), false, wxT("invalid tree item") );
 
     // consider that the item does have children if it has the "+" button: it
     // might not have them (if it had never been expanded yet) but then it
@@ -1109,21 +1154,21 @@ bool wxGenericTreeCtrl::ItemHasChildren(const wxTreeItemId& item) const
 
 bool wxGenericTreeCtrl::IsExpanded(const wxTreeItemId& item) const
 {
-    wxCHECK_MSG( item.IsOk(), FALSE, wxT("invalid tree item") );
+    wxCHECK_MSG( item.IsOk(), false, wxT("invalid tree item") );
 
     return ((wxGenericTreeItem*) item.m_pItem)->IsExpanded();
 }
 
 bool wxGenericTreeCtrl::IsSelected(const wxTreeItemId& item) const
 {
-    wxCHECK_MSG( item.IsOk(), FALSE, wxT("invalid tree item") );
+    wxCHECK_MSG( item.IsOk(), false, wxT("invalid tree item") );
 
     return ((wxGenericTreeItem*) item.m_pItem)->IsSelected();
 }
 
 bool wxGenericTreeCtrl::IsBold(const wxTreeItemId& item) const
 {
-    wxCHECK_MSG( item.IsOk(), FALSE, wxT("invalid tree item") );
+    wxCHECK_MSG( item.IsOk(), false, wxT("invalid tree item") );
 
     return ((wxGenericTreeItem*) item.m_pItem)->IsBold();
 }
@@ -1139,7 +1184,8 @@ wxTreeItemId wxGenericTreeCtrl::GetItemParent(const wxTreeItemId& item) const
     return ((wxGenericTreeItem*) item.m_pItem)->GetParent();
 }
 
-wxTreeItemId wxGenericTreeCtrl::GetFirstChild(const wxTreeItemId& item, long& cookie) const
+wxTreeItemId wxGenericTreeCtrl::GetFirstChild(const wxTreeItemId& item,
+                                              wxTreeItemIdValue& cookie) const
 {
     wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") );
 
@@ -1147,14 +1193,19 @@ wxTreeItemId wxGenericTreeCtrl::GetFirstChild(const wxTreeItemId& item, long& co
     return GetNextChild(item, cookie);
 }
 
-wxTreeItemId wxGenericTreeCtrl::GetNextChild(const wxTreeItemId& item, long& cookie) const
+wxTreeItemId wxGenericTreeCtrl::GetNextChild(const wxTreeItemId& item,
+                                             wxTreeItemIdValue& cookie) const
 {
     wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") );
 
     wxArrayGenericTreeItems& children = ((wxGenericTreeItem*) item.m_pItem)->GetChildren();
-    if ( (size_t)cookie < children.Count() )
+
+    // it's ok to cast cookie to size_t, we never have indices big enough to
+    // overflow "void *"
+    size_t *pIndex = (size_t *)&cookie;
+    if ( *pIndex < children.Count() )
     {
-        return children.Item((size_t)cookie++);
+        return children.Item((*pIndex)++);
     }
     else
     {
@@ -1282,7 +1333,7 @@ wxTreeItemId wxGenericTreeCtrl::GetPrevVisible(const wxTreeItemId& item) const
 // called by wxTextTreeCtrl when it marks itself for deletion
 void wxGenericTreeCtrl::ResetTextControl()
 {
-  m_textCtrl = NULL;
+    m_textCtrl = NULL;
 }
 
 // find the first item starting with the given prefix after the given item
@@ -1322,10 +1373,12 @@ wxTreeItemId wxGenericTreeCtrl::FindItem(const wxTreeItemId& idParent,
         }
 
         // and try all the items (stop when we get to the one we started from)
-        while ( id != idParent && !GetItemText(id).Lower().StartsWith(prefix) )
+        while (id.IsOk() && id != idParent && !GetItemText(id).Lower().StartsWith(prefix) )
         {
             id = GetNext(id);
         }
+        // If we haven't found the item, id.IsOk() will be false, as per
+        // documentation
     }
 
     return id;
@@ -1336,10 +1389,11 @@ wxTreeItemId wxGenericTreeCtrl::FindItem(const wxTreeItemId& idParent,
 // -----------------------------------------------------------------------------
 
 wxTreeItemId wxGenericTreeCtrl::DoInsertItem(const wxTreeItemId& parentId,
-                                      size_t previous,
-                                      const wxString& text,
-                                      int image, int selImage,
-                                      wxTreeItemData *data)
+                                             size_t previous,
+                                             const wxString& text,
+                                             int image,
+                                             int selImage,
+                                             wxTreeItemData *data)
 {
     wxGenericTreeItem *parent = (wxGenericTreeItem*) parentId.m_pItem;
     if ( !parent )
@@ -1348,34 +1402,36 @@ wxTreeItemId wxGenericTreeCtrl::DoInsertItem(const wxTreeItemId& parentId,
         return AddRoot(text, image, selImage, data);
     }
 
-    m_dirty = TRUE;     // do this first so stuff below doesn't cause flicker
+    m_dirty = true;     // do this first so stuff below doesn't cause flicker
 
     wxGenericTreeItem *item =
         new wxGenericTreeItem( parent, text, image, selImage, data );
 
     if ( data != NULL )
     {
-        data->m_pItem = (long) item;
+        data->m_pItem = item;
     }
 
-    parent->Insert( item, previous );
+    parent->Insert( item, previous == (size_t)-1 ? parent->GetChildren().size()
+                                                 : previous );
 
     return item;
 }
 
 wxTreeItemId wxGenericTreeCtrl::AddRoot(const wxString& text,
-                                 int image, int selImage,
-                                 wxTreeItemData *data)
+                                        int image,
+                                        int selImage,
+                                        wxTreeItemData *data)
 {
     wxCHECK_MSG( !m_anchor, wxTreeItemId(), wxT("tree can have only one root") );
 
-    m_dirty = TRUE;     // do this first so stuff below doesn't cause flicker
+    m_dirty = true;     // do this first so stuff below doesn't cause flicker
 
     m_anchor = new wxGenericTreeItem((wxGenericTreeItem *)NULL, text,
                                    image, selImage, data);
     if ( data != NULL )
     {
-        data->m_pItem = (long) m_anchor;
+        data->m_pItem = m_anchor;
     }
 
     if (HasFlag(wxTR_HIDE_ROOT))
@@ -1390,25 +1446,17 @@ wxTreeItemId wxGenericTreeCtrl::AddRoot(const wxString& text,
     if (!HasFlag(wxTR_MULTIPLE))
     {
         m_current = m_key_current = m_anchor;
-        m_current->SetHilight( TRUE );
+        m_current->SetHilight( true );
     }
 
     return m_anchor;
 }
 
-wxTreeItemId wxGenericTreeCtrl::PrependItem(const wxTreeItemId& parent,
-                                     const wxString& text,
-                                     int image, int selImage,
-                                     wxTreeItemData *data)
-{
-    return DoInsertItem(parent, 0u, text, image, selImage, data);
-}
-
-wxTreeItemId wxGenericTreeCtrl::InsertItem(const wxTreeItemId& parentId,
-                                    const wxTreeItemId& idPrevious,
-                                    const wxString& text,
-                                    int image, int selImage,
-                                    wxTreeItemData *data)
+wxTreeItemId wxGenericTreeCtrl::DoInsertAfter(const wxTreeItemId& parentId,
+                                              const wxTreeItemId& idPrevious,
+                                              const wxString& text,
+                                              int image, int selImage,
+                                              wxTreeItemData *data)
 {
     wxGenericTreeItem *parent = (wxGenericTreeItem*) parentId.m_pItem;
     if ( !parent )
@@ -1428,60 +1476,53 @@ wxTreeItemId wxGenericTreeCtrl::InsertItem(const wxTreeItemId& parentId,
     return DoInsertItem(parentId, (size_t)++index, text, image, selImage, data);
 }
 
-wxTreeItemId wxGenericTreeCtrl::InsertItem(const wxTreeItemId& parentId,
-                                    size_t before,
-                                    const wxString& text,
-                                    int image, int selImage,
-                                    wxTreeItemData *data)
-{
-    wxGenericTreeItem *parent = (wxGenericTreeItem*) parentId.m_pItem;
-    if ( !parent )
-    {
-        // should we give a warning here?
-        return AddRoot(text, image, selImage, data);
-    }
-
-    return DoInsertItem(parentId, before, text, image, selImage, data);
-}
 
-wxTreeItemId wxGenericTreeCtrl::AppendItem(const wxTreeItemId& parentId,
-                                    const wxString& text,
-                                    int image, int selImage,
-                                    wxTreeItemData *data)
+void wxGenericTreeCtrl::SendDeleteEvent(wxGenericTreeItem *item)
 {
-    wxGenericTreeItem *parent = (wxGenericTreeItem*) parentId.m_pItem;
-    if ( !parent )
-    {
-        // should we give a warning here?
-        return AddRoot(text, image, selImage, data);
-    }
-
-    return DoInsertItem( parent, parent->GetChildren().Count(), text,
-                         image, selImage, data);
+    wxTreeEvent event(wxEVT_COMMAND_TREE_DELETE_ITEM, this, item);
+    ProcessEvent( event );
 }
 
-void wxGenericTreeCtrl::SendDeleteEvent(wxGenericTreeItem *item)
+// Don't leave edit or selection on a child which is about to disappear
+void wxGenericTreeCtrl::ChildrenClosing(wxGenericTreeItem* item)
 {
-    wxTreeEvent event( wxEVT_COMMAND_TREE_DELETE_ITEM, GetId() );
-    event.m_item = (long) item;
-    event.SetEventObject( this );
-    ProcessEvent( event );
+    if (m_textCtrl != NULL && item != m_textCtrl->item() && IsDescendantOf(item, m_textCtrl->item())) {
+        m_textCtrl->StopEditing();
+    }
+    if (item != m_key_current && IsDescendantOf(item, m_key_current)) {
+        m_key_current = NULL;
+    }
+    if (IsDescendantOf(item, m_select_me)) {
+        m_select_me = item;
+    }
+    if (item != m_current && IsDescendantOf(item, m_current)) {
+        m_current->SetHilight( false );
+        m_current = NULL;
+        m_select_me = item;
+    }
 }
 
 void wxGenericTreeCtrl::DeleteChildren(const wxTreeItemId& itemId)
 {
-    m_dirty = TRUE;     // do this first so stuff below doesn't cause flicker
+    m_dirty = true;     // do this first so stuff below doesn't cause flicker
 
     wxGenericTreeItem *item = (wxGenericTreeItem*) itemId.m_pItem;
+    ChildrenClosing(item);
     item->DeleteChildren(this);
 }
 
 void wxGenericTreeCtrl::Delete(const wxTreeItemId& itemId)
 {
-    m_dirty = TRUE;     // do this first so stuff below doesn't cause flicker
+    m_dirty = true;     // do this first so stuff below doesn't cause flicker
 
     wxGenericTreeItem *item = (wxGenericTreeItem*) itemId.m_pItem;
 
+    if (m_textCtrl != NULL && IsDescendantOf(item, m_textCtrl->item()))
+    {
+        // can't delete the item being edited, cancel editing it first
+        m_textCtrl->StopEditing();
+    }
+
     wxGenericTreeItem *parent = item->GetParent();
 
     // don't keep stale pointers around!
@@ -1490,7 +1531,7 @@ void wxGenericTreeCtrl::Delete(const wxTreeItemId& itemId)
         // Don't silently change the selection:
         // do it properly in idle time, so event
         // handlers get called.
-        
+
         // m_key_current = parent;
         m_key_current = NULL;
     }
@@ -1507,7 +1548,7 @@ void wxGenericTreeCtrl::Delete(const wxTreeItemId& itemId)
         // Don't silently change the selection:
         // do it properly in idle time, so event
         // handlers get called.
-        
+
         // m_current = parent;
         m_current = NULL;
         m_select_me = parent;
@@ -1527,6 +1568,10 @@ void wxGenericTreeCtrl::Delete(const wxTreeItemId& itemId)
     // and delete all of its children and the item itself now
     item->DeleteChildren(this);
     SendDeleteEvent(item);
+
+    if (item == m_select_me)
+        m_select_me = NULL;
+
     delete item;
 }
 
@@ -1552,9 +1597,7 @@ void wxGenericTreeCtrl::Expand(const wxTreeItemId& itemId)
     if ( item->IsExpanded() )
         return;
 
-    wxTreeEvent event( wxEVT_COMMAND_TREE_ITEM_EXPANDING, GetId() );
-    event.m_item = (long) item;
-    event.SetEventObject( this );
+    wxTreeEvent event(wxEVT_COMMAND_TREE_ITEM_EXPANDING, this, item);
 
     if ( ProcessEvent( event ) && !event.IsAllowed() )
     {
@@ -1571,25 +1614,6 @@ void wxGenericTreeCtrl::Expand(const wxTreeItemId& itemId)
     ProcessEvent( event );
 }
 
-void wxGenericTreeCtrl::ExpandAll(const wxTreeItemId& item)
-{
-    if ( !HasFlag(wxTR_HIDE_ROOT) || item != GetRootItem())
-    {
-        Expand(item);
-        if ( !IsExpanded(item) )
-            return;
-    }
-
-    long cookie;
-    wxTreeItemId child = GetFirstChild(item, cookie);
-    while ( child.IsOk() )
-    {
-        ExpandAll(child);
-
-        child = GetNextChild(item, cookie);
-    }
-}
-
 void wxGenericTreeCtrl::Collapse(const wxTreeItemId& itemId)
 {
     wxCHECK_RET( !HasFlag(wxTR_HIDE_ROOT) || itemId != GetRootItem(),
@@ -1600,15 +1624,14 @@ void wxGenericTreeCtrl::Collapse(const wxTreeItemId& itemId)
     if ( !item->IsExpanded() )
         return;
 
-    wxTreeEvent event( wxEVT_COMMAND_TREE_ITEM_COLLAPSING, GetId() );
-    event.m_item = (long) item;
-    event.SetEventObject( this );
+    wxTreeEvent event(wxEVT_COMMAND_TREE_ITEM_COLLAPSING, this, item);
     if ( ProcessEvent( event ) && !event.IsAllowed() )
     {
         // cancelled by program
         return;
     }
 
+    ChildrenClosing(item);
     item->Collapse();
 
 #if 0  // TODO why should items be collapsed recursively?
@@ -1648,7 +1671,7 @@ void wxGenericTreeCtrl::Unselect()
 {
     if (m_current)
     {
-        m_current->SetHilight( FALSE );
+        m_current->SetHilight( false );
         RefreshLine( m_current );
 
         m_current = NULL;
@@ -1660,7 +1683,7 @@ void wxGenericTreeCtrl::UnselectAllChildren(wxGenericTreeItem *item)
 {
     if (item->IsSelected())
     {
-        item->SetHilight(FALSE);
+        item->SetHilight(false);
         RefreshLine(item);
     }
 
@@ -1706,7 +1729,7 @@ bool wxGenericTreeCtrl::TagNextChildren(wxGenericTreeItem *crt_item, wxGenericTr
     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;
+        if (TagAllChildrenUntilLast(children[n], last_item, select)) return true;
     }
 
     return TagNextChildren(parent, last_item, select);
@@ -1718,7 +1741,7 @@ bool wxGenericTreeCtrl::TagAllChildrenUntilLast(wxGenericTreeItem *crt_item, wxG
     RefreshLine(crt_item);
 
     if (crt_item==last_item)
-        return TRUE;
+        return true;
 
     if (crt_item->HasChildren())
     {
@@ -1727,30 +1750,21 @@ bool wxGenericTreeCtrl::TagAllChildrenUntilLast(wxGenericTreeItem *crt_item, wxG
         for ( size_t n = 0; n < count; ++n )
         {
             if (TagAllChildrenUntilLast(children[n], last_item, select))
-                return TRUE;
+                return true;
         }
     }
 
-  return FALSE;
+  return false;
 }
 
 void wxGenericTreeCtrl::SelectItemRange(wxGenericTreeItem *item1, wxGenericTreeItem *item2)
 {
-    // item2 is not necessary after item1
-    wxGenericTreeItem *first=NULL, *last=NULL;
     m_select_me = NULL;
 
+    // item2 is not necessary after item1
     // choice first' and 'last' between item1 and item2
-    if (item1->GetY()<item2->GetY())
-    {
-        first=item1;
-        last=item2;
-    }
-    else
-    {
-        first=item2;
-        last=item1;
-    }
+    wxGenericTreeItem *first= (item1->GetY()<item2->GetY()) ? item1 : item2;
+    wxGenericTreeItem *last = (item1->GetY()<item2->GetY()) ? item2 : item1;
 
     bool select = m_current->IsSelected();
 
@@ -1760,14 +1774,14 @@ void wxGenericTreeCtrl::SelectItemRange(wxGenericTreeItem *item1, wxGenericTreeI
     TagNextChildren(first,last,select);
 }
 
-void wxGenericTreeCtrl::SelectItem(const wxTreeItemId& itemId,
-                                   bool unselect_others,
-                                   bool extended_select)
+void wxGenericTreeCtrl::DoSelectItem(const wxTreeItemId& itemId,
+                                     bool unselect_others,
+                                     bool extended_select)
 {
     wxCHECK_RET( itemId.IsOk(), wxT("invalid tree item") );
 
     m_select_me = NULL;
-    
+
     bool is_single=!(GetWindowStyleFlag() & wxTR_MULTIPLE);
     wxGenericTreeItem *item = (wxGenericTreeItem*) itemId.m_pItem;
 
@@ -1779,8 +1793,8 @@ void wxGenericTreeCtrl::SelectItem(const wxTreeItemId& itemId,
     {
         if (item->IsSelected())
             return; // nothing to do
-        unselect_others = TRUE;
-        extended_select = FALSE;
+        unselect_others = true;
+        extended_select = false;
     }
     else if ( unselect_others && item->IsSelected() )
     {
@@ -1790,10 +1804,8 @@ void wxGenericTreeCtrl::SelectItem(const wxTreeItemId& itemId,
             return;
     }
 
-    wxTreeEvent event( wxEVT_COMMAND_TREE_SEL_CHANGING, GetId() );
-    event.m_item = (long) item;
-    event.m_itemOld = (long) m_current;
-    event.SetEventObject( this );
+    wxTreeEvent event(wxEVT_COMMAND_TREE_SEL_CHANGING, this, item);
+    event.m_itemOld = m_current;
     // TODO : Here we don't send any selection mode yet !
 
     if ( GetEventHandler()->ProcessEvent( event ) && !event.IsAllowed() )
@@ -1808,8 +1820,6 @@ void wxGenericTreeCtrl::SelectItem(const wxTreeItemId& itemId,
         parent = GetItemParent( parent );
     }
 
-    EnsureVisible( itemId );
-
     // ctrl press
     if (unselect_others)
     {
@@ -1830,7 +1840,7 @@ void wxGenericTreeCtrl::SelectItem(const wxTreeItemId& itemId,
     }
     else
     {
-        bool select=TRUE; // the default
+        bool select = true; // the default
 
         // Check if we need to toggle hilight (ctrl mode)
         if (!unselect_others)
@@ -1841,10 +1851,38 @@ void wxGenericTreeCtrl::SelectItem(const wxTreeItemId& itemId,
         RefreshLine( m_current );
     }
 
+    // This can cause idle processing to select the root
+    // if no item is selected, so it must be after the
+    // selection is set
+    EnsureVisible( itemId );
+
     event.SetEventType(wxEVT_COMMAND_TREE_SEL_CHANGED);
     GetEventHandler()->ProcessEvent( event );
 }
 
+void wxGenericTreeCtrl::SelectItem(const wxTreeItemId& itemId, bool select)
+{
+    if ( select )
+    {
+        DoSelectItem(itemId, !HasFlag(wxTR_MULTIPLE));
+    }
+    else // deselect
+    {
+        wxGenericTreeItem *item = (wxGenericTreeItem*) itemId.m_pItem;
+        wxCHECK_RET( item, wxT("SelectItem(): invalid tree item") );
+        
+        wxTreeEvent event(wxEVT_COMMAND_TREE_SEL_CHANGING, this, item);
+        if ( GetEventHandler()->ProcessEvent( event ) && !event.IsAllowed() )
+            return;
+
+        item->SetHilight(false);
+        RefreshLine(item);
+
+        event.SetEventType(wxEVT_COMMAND_TREE_SEL_CHANGED);
+        GetEventHandler()->ProcessEvent( event );
+    }
+}
+
 void wxGenericTreeCtrl::FillArray(wxGenericTreeItem *item,
                                   wxArrayTreeItemIds &array) const
 {
@@ -1875,6 +1913,8 @@ size_t wxGenericTreeCtrl::GetSelections(wxArrayTreeItemIds &array) const
 
 void wxGenericTreeCtrl::EnsureVisible(const wxTreeItemId& item)
 {
+    wxCHECK_RET( item.IsOk(), wxT("invalid tree item") );
+
     if (!item.IsOk()) return;
 
     wxGenericTreeItem *gitem = (wxGenericTreeItem*) item.m_pItem;
@@ -1911,8 +1951,12 @@ void wxGenericTreeCtrl::ScrollTo(const wxTreeItemId &item)
     // We have to call this here because the label in
     // question might just have been added and no screen
     // update taken place.
-    if (m_dirty) wxYieldIfNeeded();
-
+    if (m_dirty)
+#if defined( __WXMSW__ ) || defined(__WXMAC__)
+        Update();
+#else
+        DoDirtyProcessing();
+#endif
     wxGenericTreeItem *gitem = (wxGenericTreeItem*) item.m_pItem;
 
     // now scroll to the item
@@ -1965,12 +2009,6 @@ static int LINKAGEMODE tree_ctrl_compare_func(wxGenericTreeItem **item1,
     return s_treeBeingSorted->OnCompareItems(*item1, *item2);
 }
 
-int wxGenericTreeCtrl::OnCompareItems(const wxTreeItemId& item1,
-                               const wxTreeItemId& item2)
-{
-    return wxStrcmp(GetItemText(item1), GetItemText(item2));
-}
-
 void wxGenericTreeCtrl::SortChildren(const wxTreeItemId& itemId)
 {
     wxCHECK_RET( itemId.IsOk(), wxT("invalid tree item") );
@@ -1983,7 +2021,7 @@ void wxGenericTreeCtrl::SortChildren(const wxTreeItemId& itemId)
     wxArrayGenericTreeItems& children = item->GetChildren();
     if ( children.Count() > 1 )
     {
-        m_dirty = TRUE;
+        m_dirty = true;
 
         s_treeBeingSorted = this;
         children.Sort(tree_ctrl_compare_func);
@@ -1992,21 +2030,6 @@ void wxGenericTreeCtrl::SortChildren(const wxTreeItemId& itemId)
     //else: don't make the tree dirty as nothing changed
 }
 
-wxImageList *wxGenericTreeCtrl::GetImageList() const
-{
-    return m_imageListNormal;
-}
-
-wxImageList *wxGenericTreeCtrl::GetButtonsImageList() const
-{
-    return m_imageListButtons;
-}
-
-wxImageList *wxGenericTreeCtrl::GetStateImageList() const
-{
-    return m_imageListState;
-}
-
 void wxGenericTreeCtrl::CalculateLineHeight()
 {
     wxClientDC dc(this);
@@ -2050,8 +2073,8 @@ void wxGenericTreeCtrl::SetImageList(wxImageList *imageList)
 {
     if (m_ownsImageListNormal) delete m_imageListNormal;
     m_imageListNormal = imageList;
-    m_ownsImageListNormal = FALSE;
-    m_dirty = TRUE;
+    m_ownsImageListNormal = false;
+    m_dirty = true;
     // Don't do any drawing if we're setting the list to NULL,
     // since we may be in the process of deleting the tree control.
     if (imageList)
@@ -2062,34 +2085,22 @@ void wxGenericTreeCtrl::SetStateImageList(wxImageList *imageList)
 {
     if (m_ownsImageListState) delete m_imageListState;
     m_imageListState = imageList;
-    m_ownsImageListState = FALSE;
+    m_ownsImageListState = false;
 }
 
 void wxGenericTreeCtrl::SetButtonsImageList(wxImageList *imageList)
 {
     if (m_ownsImageListButtons) delete m_imageListButtons;
     m_imageListButtons = imageList;
-    m_ownsImageListButtons = FALSE;
-    m_dirty = TRUE;
+    m_ownsImageListButtons = false;
+    m_dirty = true;
     CalculateLineHeight();
 }
 
-void wxGenericTreeCtrl::AssignImageList(wxImageList *imageList)
-{
-    SetImageList(imageList);
-    m_ownsImageListNormal = TRUE;
-}
-
-void wxGenericTreeCtrl::AssignStateImageList(wxImageList *imageList)
-{
-    SetStateImageList(imageList);
-    m_ownsImageListState = TRUE;
-}
-
 void wxGenericTreeCtrl::AssignButtonsImageList(wxImageList *imageList)
 {
     SetButtonsImageList(imageList);
-    m_ownsImageListButtons = TRUE;
+    m_ownsImageListButtons = true;
 }
 
 // -----------------------------------------------------------------------------
@@ -2142,7 +2153,7 @@ void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc)
         if ( m_imageListNormal )
         {
             m_imageListNormal->GetSize( image, image_w, image_h );
-            image_w += 4;
+            image_w += MARGIN_BETWEEN_IMAGE_AND_TEXT;
         }
         else
         {
@@ -2151,31 +2162,25 @@ void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc)
     }
 
     int total_h = GetLineHeight(item);
+    bool drawItemBackground = false;
 
     if ( item->IsSelected() )
     {
-// under mac selections are only a rectangle in case they don't have the focus
-#ifdef __WXMAC__
-        if ( !m_hasFocus )
-        {
-            dc.SetBrush( *wxTRANSPARENT_BRUSH ) ;
-            dc.SetPen( wxPen( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) , 1 , wxSOLID ) ) ;
-        }
-        else
-        {
-            dc.SetBrush( *m_hilightBrush ) ;
-        }
-#else
         dc.SetBrush(*(m_hasFocus ? m_hilightBrush : m_hilightUnfocusedBrush));
-#endif
+        drawItemBackground = true;
     }
     else
     {
         wxColour colBg;
         if ( attr && attr->HasBackgroundColour() )
+        {
+            drawItemBackground = true;
             colBg = attr->GetBackgroundColour();
+        }
         else
-            colBg = m_backgroundColour;
+        {
+            colBg = GetBackgroundColour();
+        }
         dc.SetBrush(wxBrush(colBg, wxSOLID));
     }
 
@@ -2183,11 +2188,31 @@ void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc)
 
     if ( HasFlag(wxTR_FULL_ROW_HIGHLIGHT) )
     {
-        int x, y, w, h;
-
-        DoGetPosition(&x, &y);
-        DoGetSize(&w, &h);
-        dc.DrawRectangle(x, item->GetY()+offset, w, total_h-offset);
+        int x, w, h;
+        x=0;
+        GetVirtualSize(&w, &h);
+        wxRect rect( x, item->GetY()+offset, w, total_h-offset);
+#if !defined(__WXGTK20__) && !defined(__WXMAC__)
+        dc.DrawRectangle(rect);
+#else
+        if (!item->IsSelected())
+        {
+            dc.DrawRectangle(rect);
+        }
+        else
+        {
+            int flags = wxCONTROL_SELECTED;
+            if (m_hasFocus
+#ifdef __WXMAC__
+                && IsControlActive( (ControlRef)GetHandle() )
+#endif
+            )
+                flags |= wxCONTROL_FOCUSED;
+            if ((item == m_current) && (m_hasFocus))
+                flags |= wxCONTROL_CURRENT;
+            wxRendererNative::Get().DrawItemSelectionRect( this, dc, rect, flags );
+        }
+#endif
     }
     else
     {
@@ -2196,13 +2221,49 @@ void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc)
             // If it's selected, and there's an image, then we should
             // take care to leave the area under the image painted in the
             // background colour.
-            dc.DrawRectangle( item->GetX() + image_w - 2, item->GetY()+offset,
-                              item->GetWidth() - image_w + 2, total_h-offset );
+            wxRect rect( item->GetX() + image_w - 2, item->GetY()+offset,
+                         item->GetWidth() - image_w + 2, total_h-offset );
+#if !defined(__WXGTK20__) && !defined(__WXMAC__)
+            dc.DrawRectangle( rect );
+#else
+            rect.x -= 1;
+            rect.width += 2;
+        
+            int flags = wxCONTROL_SELECTED;
+            if (m_hasFocus)
+                flags |= wxCONTROL_FOCUSED;
+            if ((item == m_current) && (m_hasFocus))
+                flags |= wxCONTROL_CURRENT;
+            wxRendererNative::Get().DrawItemSelectionRect( this, dc, rect, flags );
+#endif
         }
-        else
+        // On GTK+ 2, drawing a 'normal' background is wrong for themes that
+        // don't allow backgrounds to be customized. Not drawing the background,
+        // except for custom item backgrounds, works for both kinds of theme.
+        else if (drawItemBackground)
         {
-            dc.DrawRectangle( item->GetX()-2, item->GetY()+offset,
-                              item->GetWidth()+2, total_h-offset );
+            wxRect rect( item->GetX()-2, item->GetY()+offset,
+                         item->GetWidth()+2, total_h-offset );
+#if !defined(__WXGTK20__) && !defined(__WXMAC__)
+            dc.DrawRectangle( rect );
+#else
+            if ( attr && attr->HasBackgroundColour() )
+            {
+                dc.DrawRectangle( rect );
+            }
+            else
+            {
+                rect.x -= 1;
+                rect.width += 2;
+                
+                int flags = wxCONTROL_SELECTED;
+                if (m_hasFocus)
+                    flags |= wxCONTROL_FOCUSED;
+                if ((item == m_current) && (m_hasFocus))
+                    flags |= wxCONTROL_CURRENT;
+                wxRendererNative::Get().DrawItemSelectionRect( this, dc, rect, flags );
+            }
+#endif
         }
     }
 
@@ -2272,7 +2333,7 @@ void wxGenericTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxDC &dc, int level
 
     if (IsExposed(exposed_x, exposed_y, 10000, h))  // 10000 = very much
     {
-        wxPen *pen =
+        const wxPen *pen =
 #ifndef __WXMAC__
             // don't draw rect outline if we already have the
             // background color under Mac
@@ -2281,9 +2342,21 @@ void wxGenericTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxDC &dc, int level
             wxTRANSPARENT_PEN;
 
         wxColour colText;
-        if ( item->IsSelected() )
+        if ( item->IsSelected()
+#ifdef __WXMAC__
+            // On wxMac, if the tree doesn't have the focus we draw an empty
+            // rectangle, so we want to make sure that the text is visible
+            // against the normal background, not the highlightbackground, so
+            // don't use the highlight text colour unless we have the focus.
+             && m_hasFocus && IsControlActive( (ControlRef)GetHandle() )
+#endif
+            )
         {
+#ifdef __WXMAC__
+            colText = *wxWHITE;
+#else
             colText = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT);
+#endif
         }
         else
         {
@@ -2316,110 +2389,60 @@ void wxGenericTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxDC &dc, int level
         dc.SetPen(m_dottedPen);
         dc.SetTextForeground(*wxBLACK);
 
-        if (item->HasPlus() && HasButtons())  // should the item show a button?
+        if ( !HasFlag(wxTR_NO_LINES) )
         {
-            if (!HasFlag(wxTR_NO_LINES))
-            {
-                if (x > (signed)m_indent)
-                    dc.DrawLine(x - m_indent, y_mid, x - 5, y_mid);
-                else if (HasFlag(wxTR_LINES_AT_ROOT))
-                    dc.DrawLine(3, y_mid, x - 5, y_mid);
-                dc.DrawLine(x + 5, y_mid, x + m_spacing, y_mid);
-            }
+            // draw the horizontal line here
+            int x_start = x;
+            if (x > (signed)m_indent)
+                x_start -= m_indent;
+            else if (HasFlag(wxTR_LINES_AT_ROOT))
+                x_start = 3;
+            dc.DrawLine(x_start, y_mid, x + m_spacing, y_mid);
+        }
 
-            if (m_imageListButtons != NULL)
+        // should the item show a button?
+        if ( item->HasPlus() && HasButtons() )
+        {
+            if ( m_imageListButtons )
             {
                 // draw the image button here
-                int image_h = 0, image_w = 0, image = wxTreeItemIcon_Normal;
-                if (item->IsExpanded()) image = wxTreeItemIcon_Expanded;
-                if (item->IsSelected())
+                int image_h = 0,
+                    image_w = 0;
+                int image = item->IsExpanded() ? wxTreeItemIcon_Expanded
+                                               : wxTreeItemIcon_Normal;
+                if ( item->IsSelected() )
                     image += wxTreeItemIcon_Selected - wxTreeItemIcon_Normal;
+
                 m_imageListButtons->GetSize(image, image_w, image_h);
-                int xx = x - (image_w>>1);
-                int yy = y_mid - (image_h>>1);
-                dc.SetClippingRegion(xx, yy, image_w, image_h);
+                int xx = x - image_w/2;
+                int yy = y_mid - image_h/2;
+
+                wxDCClipper clip(dc, xx, yy, image_w, image_h);
                 m_imageListButtons->Draw(image, dc, xx, yy,
                                          wxIMAGELIST_DRAW_TRANSPARENT);
-                dc.DestroyClippingRegion();
-            }
-            else if (HasFlag(wxTR_TWIST_BUTTONS))
-            {
-                // draw the twisty button here
-
-                if (HasFlag(wxTR_AQUA_BUTTONS))
-                {
-                    // This causes update problems, so disabling for now.
-#if 0 // def __WXMAC__
-                    wxMacPortSetter helper(&dc) ;
-                    wxMacWindowClipper clipper(this) ;
-                    wxDC::MacSetupBackgroundForCurrentPort( MacGetBackgroundBrush() ) ;
-
-                    int loc_x = x - 5 ;
-                    int loc_y = y_mid - 6 ;
-                    MacWindowToRootWindow( & loc_x , & loc_y ) ;
-                    Rect bounds = { loc_y , loc_x , loc_y + 18 , loc_x + 12 } ;
-                    ThemeButtonDrawInfo info = { kThemeStateActive , item->IsExpanded() ? kThemeDisclosureDown : kThemeDisclosureRight ,
-                        kThemeAdornmentNone }; 
-                    DrawThemeButton( &bounds, kThemeDisclosureButton , 
-                        &info , NULL , NULL , NULL , NULL ) ;
-#else
-                    if (item->IsExpanded())
-                        dc.DrawBitmap( *m_arrowDown, x-5, y_mid-6, TRUE );
-                    else
-                        dc.DrawBitmap( *m_arrowRight, x-5, y_mid-6, TRUE );
-#endif
-                }
-                else
-                {
-                    dc.SetBrush(*m_hilightBrush);
-                    dc.SetPen(*wxBLACK_PEN);
-                    wxPoint button[3];
-
-                    if (item->IsExpanded())
-                    {
-                        button[0].x = x-5;
-                        button[0].y = y_mid-2;
-                        button[1].x = x+5;
-                        button[1].y = y_mid-2;
-                        button[2].x = x;
-                        button[2].y = y_mid+3;
-                    }
-                    else
-                    {
-                        button[0].y = y_mid-5;
-                        button[0].x = x-2;
-                        button[1].y = y_mid+5;
-                        button[1].x = x-2;
-                        button[2].y = y_mid;
-                        button[2].x = x+3;
-                    }
-                    dc.DrawPolygon(3, button);
-                    dc.SetPen(m_dottedPen);
-                }
             }
-            else // if (HasFlag(wxTR_HAS_BUTTONS))
+            else // no custom buttons
             {
-                // draw the plus sign here
-                dc.SetPen(*wxGREY_PEN);
-                dc.SetBrush(*wxWHITE_BRUSH);
-                dc.DrawRectangle(x-5, y_mid-4, 11, 9);
-                dc.SetPen(*wxBLACK_PEN);
-                dc.DrawLine(x-2, y_mid, x+3, y_mid);
-                if (!item->IsExpanded())
-                    dc.DrawLine(x, y_mid-2, x, y_mid+3);
-                dc.SetPen(m_dottedPen);
+                static const int wImage = 9;
+                static const int hImage = 9;
+
+                int flag = 0;
+                if (item->IsExpanded())
+                    flag |= wxCONTROL_EXPANDED;
+                if (item == m_underMouse)
+                    flag |= wxCONTROL_CURRENT;
+
+                wxRendererNative::Get().DrawTreeItemButton
+                                        (
+                                            this,
+                                            dc,
+                                            wxRect(x - wImage/2,
+                                                   y_mid - hImage/2,
+                                                   wImage, hImage),
+                                            flag
+                                        );
             }
         }
-        else if (!HasFlag(wxTR_NO_LINES))  // no button; maybe a line?
-        {
-            // draw the horizontal line here
-            int x_start = x;
-            if (x > (signed)m_indent)
-                x_start -= m_indent;
-            else if (HasFlag(wxTR_LINES_AT_ROOT))
-                x_start = 3;
-            dc.DrawLine(x_start, y_mid, x + m_spacing, y_mid);
-        }
     }
 
     if (item->IsExpanded())
@@ -2442,7 +2465,7 @@ void wxGenericTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxDC &dc, int level
                 if (HasButtons()) y_mid += 5;
 
                 // Only draw the portion of the line that is visible, in case it is huge
-                wxCoord        xOrigin=0, yOrigin=0, width, height;
+                wxCoord xOrigin=0, yOrigin=0, width, height;
                 dc.GetDeviceOrigin(&xOrigin, &yOrigin);
                 yOrigin = abs(yOrigin);
                 GetClientSize(&width, &height);
@@ -2475,7 +2498,7 @@ void wxGenericTreeCtrl::DrawDropEffect(wxGenericTreeItem *item)
         {
             // draw a line under the drop target because the item will be
             // dropped there
-            DrawLine(item, TRUE /* below */);
+            DrawLine(item, !m_dropEffectAboveItem );
         }
 
         SetCursor(wxCURSOR_BULLSEYE);
@@ -2525,9 +2548,19 @@ void wxGenericTreeCtrl::DrawLine(const wxTreeItemId &item, bool below)
 }
 
 // -----------------------------------------------------------------------------
-// wxWindows callbacks
+// wxWidgets callbacks
 // -----------------------------------------------------------------------------
 
+void wxGenericTreeCtrl::OnSize( wxSizeEvent &event )
+{
+#ifdef __WXGTK__
+    if (HasFlag( wxTR_FULL_ROW_HIGHLIGHT) && m_current)
+        RefreshLine( m_current );
+#endif
+
+    event.Skip(true);
+}
+
 void wxGenericTreeCtrl::OnPaint( wxPaintEvent &WXUNUSED(event) )
 {
     wxPaintDC dc(this);
@@ -2549,7 +2582,7 @@ void wxGenericTreeCtrl::OnPaint( wxPaintEvent &WXUNUSED(event) )
 
 void wxGenericTreeCtrl::OnSetFocus( wxFocusEvent &event )
 {
-    m_hasFocus = TRUE;
+    m_hasFocus = true;
 
     RefreshSelected();
 
@@ -2558,7 +2591,7 @@ void wxGenericTreeCtrl::OnSetFocus( wxFocusEvent &event )
 
 void wxGenericTreeCtrl::OnKillFocus( wxFocusEvent &event )
 {
-    m_hasFocus = FALSE;
+    m_hasFocus = false;
 
     RefreshSelected();
 
@@ -2567,9 +2600,8 @@ void wxGenericTreeCtrl::OnKillFocus( wxFocusEvent &event )
 
 void wxGenericTreeCtrl::OnChar( wxKeyEvent &event )
 {
-    wxTreeEvent te( wxEVT_COMMAND_TREE_KEY_DOWN, GetId() );
+    wxTreeEvent te( wxEVT_COMMAND_TREE_KEY_DOWN, this);
     te.m_evtKey = event;
-    te.SetEventObject( this );
     if ( GetEventHandler()->ProcessEvent( te ) )
     {
         // intercepted by the user code
@@ -2586,9 +2618,17 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event )
     bool is_multiple, extended_select, unselect_others;
     EventFlagsToSelType(GetWindowStyleFlag(),
                         event.ShiftDown(),
-                        event.ControlDown(),
+                        event.CmdDown(),
                         is_multiple, extended_select, unselect_others);
 
+    if (GetLayoutDirection() == wxLayout_RightToLeft)
+    {
+        if (event.GetKeyCode() == WXK_RIGHT)
+            event.m_keyCode = WXK_LEFT;
+        else if (event.GetKeyCode() == WXK_LEFT)
+            event.m_keyCode = WXK_RIGHT;
+    }
+
     // + : Expand
     // - : Collaspe
     // * : Expand all/Collapse all
@@ -2616,7 +2656,7 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event )
             if ( !IsExpanded(m_current) )
             {
                 // expand all
-                ExpandAll(m_current);
+                ExpandAllChildren(m_current);
                 break;
             }
             //else: fall through to Collapse() it
@@ -2629,14 +2669,26 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event )
             }
             break;
 
+        case WXK_MENU:
+            {
+                // Use the item's bounding rectangle to determine position for the event
+                wxRect ItemRect;
+                GetBoundingRect(m_current, ItemRect, true);
+
+                wxTreeEvent eventMenu(wxEVT_COMMAND_TREE_ITEM_MENU, this, m_current);
+                // Use the left edge, vertical middle
+                eventMenu.m_pointDrag = wxPoint(ItemRect.GetX(),
+                                                ItemRect.GetY() + ItemRect.GetHeight() / 2);
+                GetEventHandler()->ProcessEvent( eventMenu );
+            }
+            break;
+
         case ' ':
         case WXK_RETURN:
             if ( !event.HasModifiers() )
             {
-                wxTreeEvent event( wxEVT_COMMAND_TREE_ITEM_ACTIVATED, GetId() );
-                event.m_item = (long) m_current;
-                event.SetEventObject( this );
-                GetEventHandler()->ProcessEvent( event );
+                wxTreeEvent eventAct(wxEVT_COMMAND_TREE_ITEM_ACTIVATED, this, m_current);
+                GetEventHandler()->ProcessEvent( eventAct );
             }
 
             // in any case, also generate the normal key event for this key,
@@ -2661,13 +2713,13 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event )
                     }
                     if (prev)
                     {
-                        long cookie = 0;
+                        wxTreeItemIdValue cookie;
                         wxTreeItemId current = m_key_current;
                         // TODO: Huh?  If we get here, we'd better be the first child of our parent.  How else could it be?
                         if (current == GetFirstChild( prev, cookie ))
                         {
                             // otherwise we return to where we came from
-                            SelectItem( prev, unselect_others, extended_select );
+                            DoSelectItem( prev, unselect_others, extended_select );
                             m_key_current= (wxGenericTreeItem*) prev.m_pItem;
                             break;
                         }
@@ -2684,7 +2736,7 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event )
                         }
                     }
 
-                    SelectItem( prev, unselect_others, extended_select );
+                    DoSelectItem( prev, unselect_others, extended_select );
                     m_key_current=(wxGenericTreeItem*) prev.m_pItem;
                 }
             }
@@ -2701,7 +2753,7 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event )
                 }
                 if (prev)
                 {
-                    SelectItem( prev, unselect_others, extended_select );
+                    DoSelectItem( prev, unselect_others, extended_select );
                 }
             }
             break;
@@ -2716,9 +2768,9 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event )
             {
                 if (IsExpanded(m_key_current) && HasChildren(m_key_current))
                 {
-                    long cookie = 0;
+                    wxTreeItemIdValue cookie;
                     wxTreeItemId child = GetFirstChild( m_key_current, cookie );
-                    SelectItem( child, unselect_others, extended_select );
+                    DoSelectItem( child, unselect_others, extended_select );
                     m_key_current=(wxGenericTreeItem*) child.m_pItem;
                 }
                 else
@@ -2727,7 +2779,7 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event )
                     if (!next)
                     {
                         wxTreeItemId current = m_key_current;
-                        while (current && !next)
+                        while (current.IsOk() && !next)
                         {
                             current = GetItemParent( current );
                             if (current) next = GetNextSibling( current );
@@ -2735,7 +2787,7 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event )
                     }
                     if (next)
                     {
-                        SelectItem( next, unselect_others, extended_select );
+                        DoSelectItem( next, unselect_others, extended_select );
                         m_key_current=(wxGenericTreeItem*) next.m_pItem;
                     }
                 }
@@ -2753,7 +2805,7 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event )
 
                     // it may happen if the item was expanded but then all of
                     // its children have been deleted - so IsExpanded() returned
-                    // TRUE, but GetLastChild() returned invalid item
+                    // true, but GetLastChild() returned invalid item
                     if ( !lastChild )
                         break;
 
@@ -2762,7 +2814,7 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event )
 
                 if ( last.IsOk() )
                 {
-                    SelectItem( last, unselect_others, extended_select );
+                    DoSelectItem( last, unselect_others, extended_select );
                 }
             }
             break;
@@ -2776,13 +2828,13 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event )
 
                 if ( HasFlag(wxTR_HIDE_ROOT) )
                 {
-                    long dummy;
-                    prev = GetFirstChild(prev, dummy);
+                    wxTreeItemIdValue cookie;
+                    prev = GetFirstChild(prev, cookie);
                     if (!prev)
                         break;
                 }
 
-                SelectItem( prev, unselect_others, extended_select );
+                DoSelectItem( prev, unselect_others, extended_select );
             }
             break;
 
@@ -2794,9 +2846,9 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event )
                   (keyCode >= 'A' && keyCode <= 'Z' )))
             {
                 // find the next item starting with the given prefix
-                char ch = (char)keyCode;
+                wxChar ch = (wxChar)keyCode;
 
-                wxTreeItemId id = FindItem(m_current, m_findPrefix + (wxChar)ch);
+                wxTreeItemId id = FindItem(m_current, m_findPrefix + ch);
                 if ( !id.IsOk() )
                 {
                     // no such item
@@ -2824,11 +2876,9 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event )
     }
 }
 
-wxTreeItemId wxGenericTreeCtrl::HitTest(const wxPoint& point, int& flags)
+wxTreeItemId
+wxGenericTreeCtrl::DoTreeHitTest(const wxPoint& point, int& flags) const
 {
-    // JACS: removed wxYieldIfNeeded() because it can cause the window
-    // to be deleted from under us if a close window event is pending
-
     int w, h;
     GetSize(&w, &h);
     flags=0;
@@ -2857,48 +2907,69 @@ wxTreeItemId wxGenericTreeCtrl::HitTest(const wxPoint& point, int& flags)
 // get the bounding rectangle of the item (or of its label only)
 bool wxGenericTreeCtrl::GetBoundingRect(const wxTreeItemId& item,
                                         wxRect& rect,
-                                        bool WXUNUSED(textOnly)) const
+                                        bool textOnly) const
 {
-    wxCHECK_MSG( item.IsOk(), FALSE, _T("invalid item in wxGenericTreeCtrl::GetBoundingRect") );
+    wxCHECK_MSG( item.IsOk(), false, _T("invalid item in wxGenericTreeCtrl::GetBoundingRect") );
 
     wxGenericTreeItem *i = (wxGenericTreeItem*) item.m_pItem;
 
-    int startX, startY;
-    GetViewStart(& startX, & startY);
+    if ( textOnly )
+    {
+        rect.x = i->GetX();
+        rect.width = i->GetWidth();
+
+        if ( m_imageListNormal )
+        {
+            int image_w, image_h;
+            m_imageListNormal->GetSize( 0, image_w, image_h );
+            rect.width += image_w + MARGIN_BETWEEN_IMAGE_AND_TEXT;
+        }
+    }
+    else // the entire line
+    {
+        rect.x = 0;
+        rect.width = GetClientSize().x;
+    }
 
-    rect.x = i->GetX() - startX*PIXELS_PER_UNIT;
-    rect.y = i->GetY() - startY*PIXELS_PER_UNIT;
-    rect.width = i->GetWidth();
-    //rect.height = i->GetHeight();
+    rect.y = i->GetY();
     rect.height = GetLineHeight(i);
 
-    return TRUE;
+    // we have to return the logical coordinates, not physical ones
+    rect.SetTopLeft(CalcScrolledPosition(rect.GetTopLeft()));
+
+    return true;
 }
 
-void wxGenericTreeCtrl::Edit( const wxTreeItemId& item )
+wxTextCtrl *wxGenericTreeCtrl::EditLabel(const wxTreeItemId& item,
+                                  wxClassInfo * WXUNUSED(textCtrlClass))
 {
-    wxCHECK_RET( item.IsOk(), _T("can't edit an invalid item") );
+    wxCHECK_MSG( item.IsOk(), NULL, _T("can't edit an invalid item") );
 
     wxGenericTreeItem *itemEdit = (wxGenericTreeItem *)item.m_pItem;
 
-    wxTreeEvent te( wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT, GetId() );
-    te.m_item = (long) itemEdit;
-    te.SetEventObject( this );
+    wxTreeEvent te(wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT, this, itemEdit);
     if ( GetEventHandler()->ProcessEvent( te ) && !te.IsAllowed() )
     {
         // vetoed by user
-        return;
+        return NULL;
     }
 
     // We have to call this here because the label in
     // question might just have been added and no screen
     // update taken place.
     if ( m_dirty )
-        wxYieldIfNeeded();
+#if defined( __WXMSW__ ) || defined(__WXMAC__)
+        Update();
+#else
+        DoDirtyProcessing();
+#endif
 
+    // TODO: use textCtrlClass here to create the control of correct class
     m_textCtrl = new wxTreeTextCtrl(this, itemEdit);
 
     m_textCtrl->SetFocus();
+
+    return m_textCtrl;
 }
 
 // returns a pointer to the text edit control if the item is being
@@ -2909,14 +2980,20 @@ wxTextCtrl* wxGenericTreeCtrl::GetEditControl() const
     return m_textCtrl;
 }
 
+void wxGenericTreeCtrl::EndEditLabel(const wxTreeItemId& WXUNUSED(item),
+                                     bool discardChanges)
+{
+    wxCHECK_RET( m_textCtrl, _T("not editing label") );
+
+    m_textCtrl->EndEdit(discardChanges);
+}
+
 bool wxGenericTreeCtrl::OnRenameAccept(wxGenericTreeItem *item,
                                        const wxString& value)
 {
-    wxTreeEvent le( wxEVT_COMMAND_TREE_END_LABEL_EDIT, GetId() );
-    le.m_item = (long) item;
-    le.SetEventObject( this );
+    wxTreeEvent le(wxEVT_COMMAND_TREE_END_LABEL_EDIT, this, item);
     le.m_label = value;
-    le.m_editCancelled = FALSE;
+    le.m_editCancelled = false;
 
     return !GetEventHandler()->ProcessEvent( le ) || le.IsAllowed();
 }
@@ -2924,32 +3001,82 @@ bool wxGenericTreeCtrl::OnRenameAccept(wxGenericTreeItem *item,
 void wxGenericTreeCtrl::OnRenameCancelled(wxGenericTreeItem *item)
 {
     // let owner know that the edit was cancelled
-    wxTreeEvent le( wxEVT_COMMAND_TREE_END_LABEL_EDIT, GetId() );
-    le.m_item = (long) item;
-    le.SetEventObject( this );
+    wxTreeEvent le(wxEVT_COMMAND_TREE_END_LABEL_EDIT, this, item);
     le.m_label = wxEmptyString;
-    le.m_editCancelled = TRUE;
+    le.m_editCancelled = true;
 
     GetEventHandler()->ProcessEvent( le );
 }
 
-
-
-
 void wxGenericTreeCtrl::OnRenameTimer()
 {
-    Edit( m_current );
+    EditLabel( m_current );
 }
 
 void wxGenericTreeCtrl::OnMouse( wxMouseEvent &event )
 {
-    if ( !m_anchor ) return;
+    if ( !m_anchor )return;
+
+    wxPoint pt = CalcUnscrolledPosition(event.GetPosition());
+
+    // Is the mouse over a tree item button?
+    int flags = 0;
+    wxGenericTreeItem *thisItem = m_anchor->HitTest(pt, this, flags, 0);
+    wxGenericTreeItem *underMouse = thisItem;
+#if wxUSE_TOOLTIPS
+    bool underMouseChanged = (underMouse != m_underMouse) ;
+#endif // wxUSE_TOOLTIPS
+
+    if ((underMouse) &&
+        (flags & wxTREE_HITTEST_ONITEMBUTTON) &&
+        (!event.LeftIsDown()) &&
+        (!m_isDragging) &&
+        (!m_renameTimer || !m_renameTimer->IsRunning()))
+    {
+    }
+    else
+    {
+        underMouse = NULL;
+    }
+
+    if (underMouse != m_underMouse)
+    {
+         if (m_underMouse)
+         {
+            // unhighlight old item
+            wxGenericTreeItem *tmp = m_underMouse;
+            m_underMouse = NULL;
+            RefreshLine( tmp );
+         }
+
+         m_underMouse = underMouse;
+         if (m_underMouse)
+            RefreshLine( m_underMouse );
+    }
+
+#if wxUSE_TOOLTIPS
+    // Determines what item we are hovering over and need a tooltip for
+    wxTreeItemId hoverItem = thisItem;
 
-    // we process left mouse up event (enables in-place edit), right down
+    // We do not want a tooltip if we are dragging, or if the rename timer is running
+    if (underMouseChanged && hoverItem.IsOk() && !m_isDragging && (!m_renameTimer || !m_renameTimer->IsRunning()))
+    {
+        // Ask the tree control what tooltip (if any) should be shown
+        wxTreeEvent hevent(wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP,  this, hoverItem);
+
+        if ( GetEventHandler()->ProcessEvent(hevent) && hevent.IsAllowed() )
+        {
+            SetToolTip(hevent.m_label);
+        }
+    }
+#endif
+
+    // we process left mouse up event (enables in-place edit), middle/right down
     // (pass to the user code), left dbl click (activate item) and
     // dragging/moving events for items drag-and-drop
     if ( !(event.LeftDown() ||
            event.LeftUp() ||
+           event.MiddleDown() ||
            event.RightDown() ||
            event.LeftDClick() ||
            event.Dragging() ||
@@ -2960,9 +3087,8 @@ void wxGenericTreeCtrl::OnMouse( wxMouseEvent &event )
         return;
     }
 
-    wxPoint pt = CalcUnscrolledPosition(event.GetPosition());
 
-    int flags = 0;
+    flags = 0;
     wxGenericTreeItem *item = m_anchor->HitTest(pt, this, flags, 0);
 
     if ( event.Dragging() && !m_isDragging )
@@ -2982,9 +3108,8 @@ void wxGenericTreeCtrl::OnMouse( wxMouseEvent &event )
                               ? wxEVT_COMMAND_TREE_BEGIN_RDRAG
                               : wxEVT_COMMAND_TREE_BEGIN_DRAG;
 
-        wxTreeEvent nevent( command, GetId() );
-        nevent.m_item = (long) m_current;
-        nevent.SetEventObject(this);
+        wxTreeEvent nevent(command,  this, m_current);
+        nevent.SetPoint(CalcScrolledPosition(pt));
 
         // by default the dragging is not supported, the user code must
         // explicitly allow the event for it to take place
@@ -2993,7 +3118,7 @@ void wxGenericTreeCtrl::OnMouse( wxMouseEvent &event )
         if ( GetEventHandler()->ProcessEvent(nevent) && nevent.IsAllowed() )
         {
             // we're going to drag this item
-            m_isDragging = TRUE;
+            m_isDragging = true;
 
             // remember the old cursor because we will change it while
             // dragging
@@ -3006,7 +3131,7 @@ void wxGenericTreeCtrl::OnMouse( wxMouseEvent &event )
 
                 if ( m_oldSelection )
                 {
-                    m_oldSelection->SetHilight(FALSE);
+                    m_oldSelection->SetHilight(false);
                     RefreshLine(m_oldSelection);
                 }
             }
@@ -3014,7 +3139,7 @@ void wxGenericTreeCtrl::OnMouse( wxMouseEvent &event )
             CaptureMouse();
         }
     }
-    else if ( event.Moving() )
+    else if ( event.Dragging() )
     {
         if ( item != m_dropTarget )
         {
@@ -3026,41 +3151,57 @@ void wxGenericTreeCtrl::OnMouse( wxMouseEvent &event )
             // highlight the current drop target if any
             DrawDropEffect(m_dropTarget);
 
+#if defined(__WXMSW__) || defined(__WXMAC__) || defined(__WXGTK20__)
+            Update();
+#else
             wxYieldIfNeeded();
+#endif
         }
     }
     else if ( (event.LeftUp() || event.RightUp()) && m_isDragging )
     {
+        ReleaseMouse();
+
         // erase the highlighting
         DrawDropEffect(m_dropTarget);
 
         if ( m_oldSelection )
         {
-            m_oldSelection->SetHilight(TRUE);
+            m_oldSelection->SetHilight(true);
             RefreshLine(m_oldSelection);
             m_oldSelection = (wxGenericTreeItem *)NULL;
         }
 
         // generate the drag end event
-        wxTreeEvent event(wxEVT_COMMAND_TREE_END_DRAG, GetId());
+        wxTreeEvent eventEndDrag(wxEVT_COMMAND_TREE_END_DRAG,  this, item);
 
-        event.m_item = (long) item;
-        event.m_pointDrag = pt;
-        event.SetEventObject(this);
+        eventEndDrag.m_pointDrag = CalcScrolledPosition(pt);
 
-        (void)GetEventHandler()->ProcessEvent(event);
+        (void)GetEventHandler()->ProcessEvent(eventEndDrag);
 
-        m_isDragging = FALSE;
+        m_isDragging = false;
         m_dropTarget = (wxGenericTreeItem *)NULL;
 
-        ReleaseMouse();
-
         SetCursor(m_oldCursor);
 
+#if defined( __WXMSW__ ) || defined(__WXMAC__)
+        Update();
+#else
         wxYieldIfNeeded();
+#endif
     }
     else
     {
+        // If we got to this point, we are not dragging or moving the mouse.
+        // Because the code in carbon/toplevel.cpp will only set focus to the tree
+        // if we skip for EVT_LEFT_DOWN, we MUST skip this event here for focus to work.
+        // We skip even if we didn't hit an item because we still should
+        // restore focus to the tree control even if we didn't exactly hit an item.
+        if ( event.LeftDown() )
+        {
+            event.Skip();
+        }
+
         // here we process only the messages which happen on tree items
 
         m_dragCount = 0;
@@ -3069,14 +3210,46 @@ void wxGenericTreeCtrl::OnMouse( wxMouseEvent &event )
 
         if ( event.RightDown() )
         {
-            wxTreeEvent nevent(wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK, GetId());
-            nevent.m_item = (long) item;
+            // If the item is already selected, do not update the selection.
+            // Multi-selections should not be cleared if a selected item is clicked.
+            if (!IsSelected(item))
+            {
+                DoSelectItem(item, true, false);
+            }
+
+            wxTreeEvent nevent(wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK,  this, item);
+            nevent.m_pointDrag = CalcScrolledPosition(pt);
+            event.Skip(!GetEventHandler()->ProcessEvent(nevent));
+
+            // Consistent with MSW (for now), send the ITEM_MENU *after*
+            // the RIGHT_CLICK event. TODO: This behavior may change.
+            wxTreeEvent nevent2(wxEVT_COMMAND_TREE_ITEM_MENU,  this, item);
+            nevent2.m_pointDrag = CalcScrolledPosition(pt);
+            GetEventHandler()->ProcessEvent(nevent2);
+        }
+        else if ( event.MiddleDown() )
+        {
+            wxTreeEvent nevent(wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK,  this, item);
             nevent.m_pointDrag = CalcScrolledPosition(pt);
-            nevent.SetEventObject(this);
-            GetEventHandler()->ProcessEvent(nevent);
+            event.Skip(!GetEventHandler()->ProcessEvent(nevent));
         }
         else if ( event.LeftUp() )
         {
+            // this facilitates multiple-item drag-and-drop
+
+            if ( /* item && */ HasFlag(wxTR_MULTIPLE))
+            {
+                wxArrayTreeItemIds selections;
+                size_t count = GetSelections(selections);
+
+                if (count > 1 &&
+                    !event.CmdDown() &&
+                    !event.ShiftDown())
+                {
+                    DoSelectItem(item, true, false);
+                }
+            }
+
             if ( m_lastOnSame )
             {
                 if ( (item == m_current) &&
@@ -3093,13 +3266,13 @@ void wxGenericTreeCtrl::OnMouse( wxMouseEvent &event )
                         m_renameTimer = new wxTreeRenameTimer( this );
                     }
 
-                    m_renameTimer->Start( wxTreeRenameTimer::DELAY, TRUE );
+                    m_renameTimer->Start( wxTreeRenameTimer::DELAY, true );
                 }
 
-                m_lastOnSame = FALSE;
+                m_lastOnSame = false;
             }
         }
-        else // !RightDown() && !LeftUp() ==> LeftDown() || LeftDClick()
+        else // !RightDown() && !MiddleDown() && !LeftUp() ==> LeftDown() || LeftDClick()
         {
             if ( event.LeftDown() )
             {
@@ -3119,14 +3292,24 @@ void wxGenericTreeCtrl::OnMouse( wxMouseEvent &event )
                 return;
             }
 
-            // how should the selection work for this event?
-            bool is_multiple, extended_select, unselect_others;
-            EventFlagsToSelType(GetWindowStyleFlag(),
-                                event.ShiftDown(),
-                                event.ControlDown(),
-                                is_multiple, extended_select, unselect_others);
 
-            SelectItem(item, unselect_others, extended_select);
+            // clear the previously selected items, if the
+            // user clicked outside of the present selection.
+            // otherwise, perform the deselection on mouse-up.
+            // this allows multiple drag and drop to work.
+            // but if Cmd is down, toggle selection of the clicked item
+            if (!IsSelected(item) || event.CmdDown())
+            {
+                // how should the selection work for this event?
+                bool is_multiple, extended_select, unselect_others;
+                EventFlagsToSelType(GetWindowStyleFlag(),
+                                    event.ShiftDown(),
+                                    event.CmdDown(),
+                                    is_multiple, extended_select, unselect_others);
+
+                DoSelectItem(item, unselect_others, extended_select);
+            }
+
 
             // For some reason, Windows isn't recognizing a left double-click,
             // so we need to simulate it here.  Allow 200 milliseconds for now.
@@ -3136,13 +3319,11 @@ void wxGenericTreeCtrl::OnMouse( wxMouseEvent &event )
                 if ( m_renameTimer )
                     m_renameTimer->Stop();
 
-                m_lastOnSame = FALSE;
+                m_lastOnSame = false;
 
                 // send activate event first
-                wxTreeEvent nevent( wxEVT_COMMAND_TREE_ITEM_ACTIVATED, GetId() );
-                nevent.m_item = (long) item;
+                wxTreeEvent nevent(wxEVT_COMMAND_TREE_ITEM_ACTIVATED,  this, item);
                 nevent.m_pointDrag = CalcScrolledPosition(pt);
-                nevent.SetEventObject( this );
                 if ( !GetEventHandler()->ProcessEvent( nevent ) )
                 {
                     // if the user code didn't process the activate event,
@@ -3158,8 +3339,10 @@ void wxGenericTreeCtrl::OnMouse( wxMouseEvent &event )
     }
 }
 
-void wxGenericTreeCtrl::OnIdle( wxIdleEvent &WXUNUSED(event) )
+void wxGenericTreeCtrl::OnInternalIdle()
 {
+    wxWindow::OnInternalIdle();
+
     // Check if we need to select the root item
     // because nothing else has been selected.
     // Delaying it means that we can invoke event handlers
@@ -3172,16 +3355,10 @@ void wxGenericTreeCtrl::OnIdle( wxIdleEvent &WXUNUSED(event) )
             SelectItem(GetRootItem());
     }
 
-    /* after all changes have been done to the tree control,
-     * we actually redraw the tree when everything is over */
-
-    if (!m_dirty) return;
-
-    m_dirty = FALSE;
-
-    CalculatePositions();
-    Refresh();
-    AdjustMyScrollbars();
+    // after all changes have been done to the tree control,
+    // actually redraw the tree when everything is over
+    if (m_dirty)
+        DoDirtyProcessing();
 }
 
 void wxGenericTreeCtrl::CalculateSize( wxGenericTreeItem *item, wxDC &dc )
@@ -3194,6 +3371,8 @@ void wxGenericTreeCtrl::CalculateSize( wxGenericTreeItem *item, wxDC &dc )
         dc.SetFont(attr->GetFont());
     else if ( item->IsBold() )
         dc.SetFont(m_boldFont);
+    else
+        dc.SetFont(m_normalFont);
 
     dc.GetTextExtent( item->GetText(), &text_w, &text_h );
     text_h+=2;
@@ -3209,7 +3388,7 @@ void wxGenericTreeCtrl::CalculateSize( wxGenericTreeItem *item, wxDC &dc )
         if ( m_imageListNormal )
         {
             m_imageListNormal->GetSize( image, image_w, image_h );
-            image_w += 4;
+            image_w += MARGIN_BETWEEN_IMAGE_AND_TEXT;
         }
     }
 
@@ -3282,9 +3461,16 @@ void wxGenericTreeCtrl::CalculatePositions()
     CalculateLevel( m_anchor, dc, 0, y ); // start recursion
 }
 
+void wxGenericTreeCtrl::Refresh(bool eraseBackground, const wxRect *rect)
+{
+    if ( !m_freezeCount )
+        wxTreeCtrlBase::Refresh(eraseBackground, rect);
+}
+
 void wxGenericTreeCtrl::RefreshSubtree(wxGenericTreeItem *item)
 {
-    if (m_dirty) return;
+    if (m_dirty || m_freezeCount)
+        return;
 
     wxSize client = GetClientSize();
 
@@ -3293,25 +3479,29 @@ void wxGenericTreeCtrl::RefreshSubtree(wxGenericTreeItem *item)
     rect.width = client.x;
     rect.height = client.y;
 
-    Refresh(TRUE, &rect);
+    Refresh(true, &rect);
 
     AdjustMyScrollbars();
 }
 
 void wxGenericTreeCtrl::RefreshLine( wxGenericTreeItem *item )
 {
-    if (m_dirty) return;
+    if (m_dirty || m_freezeCount)
+        return;
 
     wxRect rect;
     CalcScrolledPosition(0, item->GetY(), NULL, &rect.y);
     rect.width = GetClientSize().x;
     rect.height = GetLineHeight(item); //dc.GetCharHeight() + 6;
 
-    Refresh(TRUE, &rect);
+    Refresh(true, &rect);
 }
 
 void wxGenericTreeCtrl::RefreshSelected()
 {
+    if (m_freezeCount)
+        return;
+
     // TODO: this is awfully inefficient, we should keep the list of all
     //       selected items internally, should be much faster
     if ( m_anchor )
@@ -3320,6 +3510,9 @@ void wxGenericTreeCtrl::RefreshSelected()
 
 void wxGenericTreeCtrl::RefreshSelectedUnder(wxGenericTreeItem *item)
 {
+    if (m_freezeCount)
+        return;
+
     if ( item->IsSelected() )
         RefreshLine(item);
 
@@ -3331,6 +3524,21 @@ void wxGenericTreeCtrl::RefreshSelectedUnder(wxGenericTreeItem *item)
     }
 }
 
+void wxGenericTreeCtrl::Freeze()
+{
+    m_freezeCount++;
+}
+
+void wxGenericTreeCtrl::Thaw()
+{
+    wxCHECK_RET( m_freezeCount > 0, _T("thawing unfrozen tree control?") );
+
+    if ( --m_freezeCount == 0 )
+    {
+        Refresh();
+    }
+}
+
 // ----------------------------------------------------------------------------
 // changing colours: we need to refresh the tree control
 // ----------------------------------------------------------------------------
@@ -3338,21 +3546,96 @@ void wxGenericTreeCtrl::RefreshSelectedUnder(wxGenericTreeItem *item)
 bool wxGenericTreeCtrl::SetBackgroundColour(const wxColour& colour)
 {
     if ( !wxWindow::SetBackgroundColour(colour) )
-        return FALSE;
+        return false;
 
     Refresh();
 
-    return TRUE;
+    return true;
 }
 
 bool wxGenericTreeCtrl::SetForegroundColour(const wxColour& colour)
 {
     if ( !wxWindow::SetForegroundColour(colour) )
-        return FALSE;
+        return false;
+
+    Refresh();
+
+    return true;
+}
 
+// Process the tooltip event, to speed up event processing.
+// Doesn't actually get a tooltip.
+void wxGenericTreeCtrl::OnGetToolTip( wxTreeEvent &event )
+{
+    event.Veto();
+}
+
+
+// NOTE: If using the wxListBox visual attributes works everywhere then this can
+// be removed, as well as the #else case below.
+#define _USE_VISATTR 0
+
+//static
+wxVisualAttributes
+#if _USE_VISATTR
+wxGenericTreeCtrl::GetClassDefaultAttributes(wxWindowVariant variant)
+#else
+wxGenericTreeCtrl::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
+#endif
+{
+#if _USE_VISATTR
+    // Use the same color scheme as wxListBox
+    return wxListBox::GetClassDefaultAttributes(variant);
+#else
+    wxVisualAttributes attr;
+    attr.colFg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
+    attr.colBg = wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOX);
+    attr.font  = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
+    return attr;
+#endif
+}
+
+void wxGenericTreeCtrl::DoDirtyProcessing()
+{
+    if (m_freezeCount)
+        return;
+
+    m_dirty = false;
+
+    CalculatePositions();
     Refresh();
+    AdjustMyScrollbars();
+}
+
+wxSize wxGenericTreeCtrl::DoGetBestSize() const
+{
+    // make sure all positions are calculated as normally this only done during
+    // idle time but we need them for base class DoGetBestSize() to return the
+    // correct result
+    wxConstCast(this, wxGenericTreeCtrl)->CalculatePositions();
+
+    wxSize size = wxTreeCtrlBase::DoGetBestSize();
+
+    // there seems to be an implicit extra border around the items, although
+    // I'm not really sure where does it come from -- but without this, the
+    // scrollbars appear in a tree with default/best size
+    size.IncBy(4, 4);
+
+    // and the border has to be rounded up to a multiple of PIXELS_PER_UNIT or
+    // scrollbars still appear
+    const wxSize& borderSize = GetWindowBorderSize();
+
+    int dx = (size.x - borderSize.x) % PIXELS_PER_UNIT;
+    if ( dx )
+        size.x += PIXELS_PER_UNIT - dx;
+    int dy = (size.y - borderSize.y) % PIXELS_PER_UNIT;
+    if ( dy )
+        size.y += PIXELS_PER_UNIT - dy;
+
+    // we need to update the cache too as the base class cached its own value
+    CacheBestSize(size);
 
-    return TRUE;
+    return size;
 }
 
 #endif // wxUSE_TREECTRL