X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/17d5bdf9e953a7340b8985ffcd6535b767a8b09e..25f430fcc4e54ba5a0dae547ce6e8e0b4310147f:/src/generic/treectlg.cpp diff --git a/src/generic/treectlg.cpp b/src/generic/treectlg.cpp index 2a2e7c814d..6d56dc596d 100644 --- a/src/generic/treectlg.cpp +++ b/src/generic/treectlg.cpp @@ -45,7 +45,6 @@ class WXDLLEXPORT wxGenericTreeItem; WX_DEFINE_EXPORTED_ARRAY(wxGenericTreeItem *, wxArrayGenericTreeItems); -//WX_DEFINE_OBJARRAY(wxArrayTreeItemIds); // ---------------------------------------------------------------------------- // constants @@ -53,7 +52,55 @@ WX_DEFINE_EXPORTED_ARRAY(wxGenericTreeItem *, wxArrayGenericTreeItems); static const int NO_IMAGE = -1; -#define PIXELS_PER_UNIT 10 +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 " +}; // ----------------------------------------------------------------------------- // private classes @@ -63,12 +110,16 @@ static const int NO_IMAGE = -1; class WXDLLEXPORT wxTreeRenameTimer: public wxTimer { public: + // start editing the current item after half a second (if the mouse hasn't + // been clicked/moved) + enum { DELAY = 500 }; + wxTreeRenameTimer( wxGenericTreeCtrl *owner ); - void Notify(); + virtual void Notify(); private: - wxGenericTreeCtrl *m_owner; + wxGenericTreeCtrl *m_owner; }; // control used for in-place edit @@ -101,6 +152,22 @@ private: DECLARE_EVENT_TABLE() }; +// timer used to clear wxGenericTreeCtrl::m_findPrefix if no key was pressed +// for a sufficiently long time +class WXDLLEXPORT wxTreeFindTimer : public wxTimer +{ +public: + // reset the current prefix after half a second of inactivity + enum { DELAY = 500 }; + + wxTreeFindTimer( wxGenericTreeCtrl *owner ) { m_owner = owner; } + + virtual void Notify() { m_owner->m_findPrefix.clear(); } + +private: + wxGenericTreeCtrl *m_owner; +}; + // a tree item class WXDLLEXPORT wxGenericTreeItem { @@ -320,7 +387,7 @@ void wxTreeTextCtrl::OnChar( wxKeyEvent &event ) if (!wxPendingDelete.Member(this)) wxPendingDelete.Append(this); - + m_finished = TRUE; m_owner->SetFocus(); // This doesn't work. TODO. @@ -376,7 +443,7 @@ void wxTreeTextCtrl::OnKillFocus( wxFocusEvent &event ) (*m_accept) = TRUE; (*m_res) = GetValue(); - + if ((*m_res) != m_startValue) m_owner->OnRenameAccept(); } @@ -621,7 +688,7 @@ void wxGenericTreeCtrl::Init() m_hilightBrush = new wxBrush ( - wxSystemSettings::GetSystemColour + wxSystemSettings::GetColour ( wxSYS_COLOUR_HIGHLIGHT ), @@ -630,7 +697,7 @@ void wxGenericTreeCtrl::Init() m_hilightUnfocusedBrush = new wxBrush ( - wxSystemSettings::GetSystemColour + wxSystemSettings::GetColour ( wxSYS_COLOUR_BTNSHADOW ), @@ -646,10 +713,12 @@ void wxGenericTreeCtrl::Init() m_isDragging = FALSE; m_dropTarget = m_oldSelection = (wxGenericTreeItem *)NULL; - m_renameTimer = new wxTreeRenameTimer( this ); + m_renameTimer = NULL; + m_findTimer = NULL; + m_lastOnSame = FALSE; - m_normalFont = wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT ); + m_normalFont = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT ); m_boldFont = wxFont( m_normalFont.GetPointSize(), m_normalFont.GetFamily(), m_normalFont.GetStyle(), @@ -668,7 +737,7 @@ bool wxGenericTreeCtrl::Create(wxWindow *parent, #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; @@ -679,13 +748,23 @@ bool wxGenericTreeCtrl::Create(wxWindow *parent, style |= wxTR_AQUA_BUTTONS; #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 the tree display has no buttons, but does have - // connecting lines, we can use a narrower layout. - // It may not be a good idea to force this... + // If the tree display has no buttons, but does have + // connecting lines, we can use a narrower layout. + // It may not be a good idea to force this... if (!HasButtons() && !HasFlag(wxTR_NO_LINES)) { m_indent= 10; @@ -696,7 +775,8 @@ bool wxGenericTreeCtrl::Create(wxWindow *parent, SetValidator( validator ); #endif - SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_LISTBOX ) ); + SetForegroundColour( wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT) ); + SetBackgroundColour( wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOX) ); // m_dottedPen = wxPen( "grey", 0, wxDOT ); too slow under XFree86 m_dottedPen = wxPen( wxT("grey"), 0, 0 ); @@ -709,12 +789,20 @@ wxGenericTreeCtrl::~wxGenericTreeCtrl() delete m_hilightBrush; delete m_hilightUnfocusedBrush; + delete m_arrowRight; + delete m_arrowDown; + DeleteAllItems(); delete m_renameTimer; - if (m_ownsImageListNormal) delete m_imageListNormal; - if (m_ownsImageListState) delete m_imageListState; - if (m_ownsImageListButtons) delete m_imageListButtons; + delete m_findTimer; + + if (m_ownsImageListNormal) + delete m_imageListNormal; + if (m_ownsImageListState) + delete m_imageListState; + if (m_ownsImageListButtons) + delete m_imageListButtons; } // ----------------------------------------------------------------------------- @@ -728,13 +816,13 @@ size_t wxGenericTreeCtrl::GetCount() const void wxGenericTreeCtrl::SetIndent(unsigned int indent) { - m_indent = indent; + m_indent = (unsigned short) indent; m_dirty = TRUE; } void wxGenericTreeCtrl::SetSpacing(unsigned int spacing) { - m_spacing = spacing; + m_spacing = (unsigned short) spacing; m_dirty = TRUE; } @@ -1098,6 +1186,52 @@ wxTreeItemId wxGenericTreeCtrl::GetPrevVisible(const wxTreeItemId& item) const return wxTreeItemId(); } +// find the first item starting with the given prefix after the given item +wxTreeItemId wxGenericTreeCtrl::FindItem(const wxTreeItemId& idParent, + const wxString& prefixOrig) const +{ + // match is case insensitive as this is more convenient to the user: having + // to press Shift-letter to go to the item starting with a capital letter + // would be too bothersome + wxString prefix = prefixOrig.Lower(); + + // determine the starting point: we shouldn't take the current item (this + // allows to switch between two items starting with the same letter just by + // pressing it) but we shouldn't jump to the next one if the user is + // continuing to type as otherwise he might easily skip the item he wanted + wxTreeItemId id = idParent; + if ( prefix.length() == 1 ) + { + id = GetNext(id); + } + + // look for the item starting with the given prefix after it + while ( id.IsOk() && !GetItemText(id).Lower().StartsWith(prefix) ) + { + id = GetNext(id); + } + + // if we haven't found anything... + if ( !id.IsOk() ) + { + // ... wrap to the beginning + id = GetRootItem(); + if ( HasFlag(wxTR_HIDE_ROOT) ) + { + // can't select virtual root + id = GetNext(id); + } + + // and try all the items (stop when we get to the one we started from) + while ( id != idParent && !GetItemText(id).Lower().StartsWith(prefix) ) + { + id = GetNext(id); + } + } + + return id; +} + // ----------------------------------------------------------------------------- // operations // ----------------------------------------------------------------------------- @@ -1140,16 +1274,18 @@ wxTreeItemId wxGenericTreeCtrl::AddRoot(const wxString& text, m_anchor = new wxGenericTreeItem((wxGenericTreeItem *)NULL, text, image, selImage, data); + if ( data != NULL ) + { + data->m_pItem = (long) m_anchor; + } + if (HasFlag(wxTR_HIDE_ROOT)) { // if root is hidden, make sure we can navigate // into children m_anchor->SetHasPlus(); - Expand(m_anchor); - } - if ( data != NULL ) - { - data->m_pItem = (long) m_anchor; + m_anchor->Expand(); + CalculatePositions(); } if (!HasFlag(wxTR_MULTIPLE)) @@ -1182,9 +1318,13 @@ wxTreeItemId wxGenericTreeCtrl::InsertItem(const wxTreeItemId& parentId, return AddRoot(text, image, selImage, data); } - int index = parent->GetChildren().Index((wxGenericTreeItem*) idPrevious.m_pItem); - wxASSERT_MSG( index != wxNOT_FOUND, - wxT("previous item in wxGenericTreeCtrl::InsertItem() is not a sibling") ); + int index = -1; + if (idPrevious.IsOk()) + { + index = parent->GetChildren().Index((wxGenericTreeItem*) idPrevious.m_pItem); + wxASSERT_MSG( index != wxNOT_FOUND, + wxT("previous item in wxGenericTreeCtrl::InsertItem() is not a sibling") ); + } return DoInsertItem(parentId, (size_t)++index, text, image, selImage, data); } @@ -1293,6 +1433,8 @@ void wxGenericTreeCtrl::Expand(const wxTreeItemId& itemId) wxGenericTreeItem *item = (wxGenericTreeItem*) itemId.m_pItem; wxCHECK_RET( item, _T("invalid item in wxGenericTreeCtrl::Expand") ); + wxCHECK_RET( !HasFlag(wxTR_HIDE_ROOT) || itemId != GetRootItem(), + _T("can't expand hidden root") ); if ( !item->HasPlus() ) return; @@ -1337,6 +1479,9 @@ void wxGenericTreeCtrl::ExpandAll(const wxTreeItemId& item) void wxGenericTreeCtrl::Collapse(const wxTreeItemId& itemId) { + wxCHECK_RET( !HasFlag(wxTR_HIDE_ROOT) || itemId != GetRootItem(), + _T("can't collapse hidden root") ); + wxGenericTreeItem *item = (wxGenericTreeItem*) itemId.m_pItem; if ( !item->IsExpanded() ) @@ -1416,7 +1561,13 @@ void wxGenericTreeCtrl::UnselectAllChildren(wxGenericTreeItem *item) void wxGenericTreeCtrl::UnselectAll() { - UnselectAllChildren((wxGenericTreeItem*) GetRootItem().m_pItem); + wxTreeItemId rootItem = GetRootItem(); + + // the tree might not have the root item at all + if ( rootItem ) + { + UnselectAllChildren((wxGenericTreeItem*) rootItem.m_pItem); + } } // Recursive function ! @@ -1493,8 +1644,8 @@ void wxGenericTreeCtrl::SelectItemRange(wxGenericTreeItem *item1, wxGenericTreeI } void wxGenericTreeCtrl::SelectItem(const wxTreeItemId& itemId, - bool unselect_others, - bool extended_select) + bool unselect_others, + bool extended_select) { wxCHECK_RET( itemId.IsOk(), wxT("invalid tree item") ); @@ -1576,7 +1727,7 @@ void wxGenericTreeCtrl::SelectItem(const wxTreeItemId& itemId, } void wxGenericTreeCtrl::FillArray(wxGenericTreeItem *item, - wxArrayTreeItemIds &array) const + wxArrayTreeItemIds &array) const { if ( item->IsSelected() ) array.Add(wxTreeItemId(item)); @@ -1611,10 +1762,22 @@ void wxGenericTreeCtrl::EnsureVisible(const wxTreeItemId& item) // first expand all parent branches wxGenericTreeItem *parent = gitem->GetParent(); - while ( parent ) + + if ( HasFlag(wxTR_HIDE_ROOT) ) { - Expand(parent); - parent = parent->GetParent(); + while ( parent != m_anchor ) + { + Expand(parent); + parent = parent->GetParent(); + } + } + else + { + while ( parent ) + { + Expand(parent); + parent = parent->GetParent(); + } } //if (parent) CalculatePositions(); @@ -1770,7 +1933,10 @@ void wxGenericTreeCtrl::SetImageList(wxImageList *imageList) m_imageListNormal = imageList; m_ownsImageListNormal = FALSE; m_dirty = TRUE; - CalculateLineHeight(); + // 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) + CalculateLineHeight(); } void wxGenericTreeCtrl::SetStateImageList(wxImageList *imageList) @@ -1883,18 +2049,29 @@ void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc) int offset = HasFlag(wxTR_ROW_LINES) ? 1 : 0; - if ( item->IsSelected() && image != NO_IMAGE ) + if ( HasFlag(wxTR_FULL_ROW_HIGHLIGHT) ) { - // 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 ); + int x, y, w, h; + + DoGetPosition(&x, &y); + DoGetSize(&w, &h); + dc.DrawRectangle(x, item->GetY()+offset, w, total_h-offset); } else { - dc.DrawRectangle( item->GetX()-2, item->GetY()+offset, - item->GetWidth()+2, total_h-offset ); + if ( item->IsSelected() && image != NO_IMAGE ) + { + // 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 ); + } + else + { + dc.DrawRectangle( item->GetX()-2, item->GetY()+offset, + item->GetWidth()+2, total_h-offset ); + } } if ( image != NO_IMAGE ) @@ -1963,6 +2140,50 @@ void wxGenericTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxDC &dc, int level if (IsExposed(exposed_x, exposed_y, 10000, h)) // 10000 = very much { + wxPen *pen = +#ifndef __WXMAC__ + // don't draw rect outline if we already have the + // background color under Mac + (item->IsSelected() && m_hasFocus) ? wxBLACK_PEN : +#endif // !__WXMAC__ + wxTRANSPARENT_PEN; + + wxColour colText; + if ( item->IsSelected() ) + { + colText = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT); + } + else + { + wxTreeItemAttr *attr = item->GetAttributes(); + if (attr && attr->HasTextColour()) + colText = attr->GetTextColour(); + else + colText = GetForegroundColour(); + } + + // prepare to draw + dc.SetTextForeground(colText); + dc.SetPen(*pen); + + // draw + PaintItem(item, dc); + + if (HasFlag(wxTR_ROW_LINES)) + { + // if the background colour is white, choose a + // contrasting color for the lines + dc.SetPen(*((GetBackgroundColour() == *wxWHITE) + ? wxMEDIUM_GREY_PEN : wxWHITE_PEN)); + dc.DrawLine(0, y_top, 10000, y_top); + dc.DrawLine(0, y, 10000, y); + } + + // restore DC objects + dc.SetBrush(*wxWHITE_BRUSH); + dc.SetPen(m_dottedPen); + dc.SetTextForeground(*wxBLACK); + if (item->HasPlus() && HasButtons()) // should the item show a button? { if (!HasFlag(wxTR_NO_LINES)) @@ -1992,36 +2213,19 @@ void wxGenericTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxDC &dc, int level else if (HasFlag(wxTR_TWIST_BUTTONS)) { // draw the twisty button here - - wxPoint button[3]; - dc.SetBrush(*m_hilightBrush); - + if (HasFlag(wxTR_AQUA_BUTTONS)) { - dc.SetPen(*wxTRANSPARENT_PEN); - if (item->IsExpanded()) - { - button[0].x = x-6; - button[0].y = y_mid-2; - button[1].x = x+6; - button[1].y = y_mid-2; - button[2].x = x; - button[2].y = y_mid+7; - } + dc.DrawBitmap( *m_arrowDown, x-5, y_mid-6, TRUE ); else - { - button[0].y = y_mid-6; - button[0].x = x-2; - button[1].y = y_mid+6; - button[1].x = x-2; - button[2].y = y_mid; - button[2].x = x+7; - } + dc.DrawBitmap( *m_arrowRight, x-5, y_mid-6, TRUE ); } else { + dc.SetBrush(*m_hilightBrush); dc.SetPen(*wxBLACK_PEN); + wxPoint button[3]; if (item->IsExpanded()) { @@ -2041,10 +2245,9 @@ void wxGenericTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxDC &dc, int level button[2].y = y_mid; button[2].x = x+3; } + dc.DrawPolygon(3, button); + dc.SetPen(m_dottedPen); } - dc.DrawPolygon(3, button); - - dc.SetPen(m_dottedPen); } else // if (HasFlag(wxTR_HAS_BUTTONS)) { @@ -2069,50 +2272,6 @@ void wxGenericTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxDC &dc, int level x_start = 3; dc.DrawLine(x_start, y_mid, x + m_spacing, y_mid); } - - wxPen *pen = -#ifndef __WXMAC__ - // don't draw rect outline if we already have the - // background color under Mac - (item->IsSelected() && m_hasFocus) ? wxBLACK_PEN : -#endif // !__WXMAC__ - wxTRANSPARENT_PEN; - - wxColour colText; - if ( item->IsSelected() ) - { - colText = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHTTEXT); - } - else - { - wxTreeItemAttr *attr = item->GetAttributes(); - if (attr && attr->HasTextColour()) - colText = attr->GetTextColour(); - else - colText = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOWTEXT); - } - - // prepare to draw - dc.SetTextForeground(colText); - dc.SetPen(*pen); - - // draw - PaintItem(item, dc); - - if (HasFlag(wxTR_ROW_LINES)) - { - // if the background colour is white, choose a - // contrasting color for the lines - dc.SetPen(*((GetBackgroundColour() == *wxWHITE) - ? wxMEDIUM_GREY_PEN : wxWHITE_PEN)); - dc.DrawLine(0, y_top, 10000, y_top); - dc.DrawLine(0, y, 10000, y); - } - - // restore DC objects - dc.SetBrush(*wxWHITE_BRUSH); - dc.SetPen(m_dottedPen); - dc.SetTextForeground(*wxBLACK); } if (item->IsExpanded()) @@ -2276,7 +2435,9 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event ) // right : open if parent and go next // home : go to root // end : go to last item without opening parents - switch (event.KeyCode()) + // alnum : start or continue searching for the item with this prefix + int keyCode = event.KeyCode(); + switch ( keyCode ) { case '+': case WXK_ADD: @@ -2336,7 +2497,6 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event ) // otherwise we return to where we came from SelectItem( prev, unselect_others, extended_select ); m_key_current= (wxGenericTreeItem*) prev.m_pItem; - EnsureVisible( prev ); break; } } @@ -2354,7 +2514,6 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event ) SelectItem( prev, unselect_others, extended_select ); m_key_current=(wxGenericTreeItem*) prev.m_pItem; - EnsureVisible( prev ); } } break; @@ -2370,7 +2529,6 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event ) } if (prev) { - EnsureVisible( prev ); SelectItem( prev, unselect_others, extended_select ); } } @@ -2390,7 +2548,6 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event ) wxTreeItemId child = GetFirstChild( m_key_current, cookie ); SelectItem( child, unselect_others, extended_select ); m_key_current=(wxGenericTreeItem*) child.m_pItem; - EnsureVisible( child ); } else { @@ -2408,7 +2565,6 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event ) { SelectItem( next, unselect_others, extended_select ); m_key_current=(wxGenericTreeItem*) next.m_pItem; - EnsureVisible( next ); } } } @@ -2434,7 +2590,6 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event ) if ( last.IsOk() ) { - EnsureVisible( last ); SelectItem( last, unselect_others, extended_select ); } } @@ -2444,20 +2599,56 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event ) case WXK_HOME: { wxTreeItemId prev = GetRootItem(); - if (!prev) break; - if (HasFlag(wxTR_HIDE_ROOT)) + if (!prev) + break; + + if ( HasFlag(wxTR_HIDE_ROOT) ) { long dummy; prev = GetFirstChild(prev, dummy); - if (!prev) break; + if (!prev) + break; } - EnsureVisible( prev ); + SelectItem( prev, unselect_others, extended_select ); } break; default: - event.Skip(); + // do not use wxIsalnum() here + if ( !event.HasModifiers() && + ((keyCode >= '0' && keyCode <= '9') || + (keyCode >= 'a' && keyCode <= 'z') || + (keyCode >= 'A' && keyCode <= 'Z' ))) + { + // find the next item starting with the given prefix + char ch = (char)keyCode; + + wxTreeItemId id = FindItem(m_current, m_findPrefix + (wxChar)ch); + if ( !id.IsOk() ) + { + // no such item + break; + } + + SelectItem(id); + + m_findPrefix += ch; + + // also start the timer to reset the current prefix if the user + // doesn't press any more alnum keys soon -- we wouldn't want + // to use this prefix for a new item search + if ( !m_findTimer ) + { + m_findTimer = new wxTreeFindTimer(this); + } + + m_findTimer->Start(wxTreeFindTimer::DELAY, wxTIMER_ONE_SHOT); + } + else + { + event.Skip(); + } } } @@ -2481,14 +2672,8 @@ wxTreeItemId wxGenericTreeCtrl::HitTest(const wxPoint& point, int& flags) return wxTreeItemId(); } - wxClientDC dc(this); - PrepareDC(dc); - wxCoord x = dc.DeviceToLogicalX( point.x ); - wxCoord y = dc.DeviceToLogicalY( point.y ); - wxGenericTreeItem *hit = m_anchor->HitTest(wxPoint(x, y), - this, - flags, - 0 ); + wxGenericTreeItem *hit = m_anchor->HitTest(CalcUnscrolledPosition(point), + this, flags, 0); if (hit == NULL) { flags = wxTREE_HITTEST_NOWHERE; @@ -2539,10 +2724,10 @@ void wxGenericTreeCtrl::Edit( const wxTreeItemId& item ) if (m_dirty) wxYieldIfNeeded(); wxString s = m_currentEdit->GetText(); - int x = m_currentEdit->GetX(); - int y = m_currentEdit->GetY(); int w = m_currentEdit->GetWidth(); int h = m_currentEdit->GetHeight(); + int x, y; + CalcScrolledPosition(m_currentEdit->GetX(), m_currentEdit->GetY(), &x, &y); int image_h = 0; int image_w = 0; @@ -2563,11 +2748,6 @@ void wxGenericTreeCtrl::Edit( const wxTreeItemId& item ) x += image_w; w -= image_w + 4; // I don't know why +4 is needed - wxClientDC dc(this); - PrepareDC( dc ); - x = dc.LogicalToDeviceX( x ); - y = dc.LogicalToDeviceY( y ); - wxTreeTextCtrl *text = new wxTreeTextCtrl(this, -1, &m_renameAccept, &m_renameRes, @@ -2616,21 +2796,15 @@ void wxGenericTreeCtrl::OnMouse( wxMouseEvent &event ) return; } - wxClientDC dc(this); - PrepareDC(dc); - wxCoord x = dc.DeviceToLogicalX( event.GetX() ); - wxCoord y = dc.DeviceToLogicalY( event.GetY() ); + wxPoint pt = CalcUnscrolledPosition(event.GetPosition()); int flags = 0; - wxGenericTreeItem *item = m_anchor->HitTest( wxPoint(x,y), - this, - flags, - 0 ); + wxGenericTreeItem *item = m_anchor->HitTest(pt, this, flags, 0); if ( event.Dragging() && !m_isDragging ) { if (m_dragCount == 0) - m_dragStart = wxPoint(x,y); + m_dragStart = pt; m_dragCount++; @@ -2707,7 +2881,7 @@ void wxGenericTreeCtrl::OnMouse( wxMouseEvent &event ) wxTreeEvent event(wxEVT_COMMAND_TREE_END_DRAG, GetId()); event.m_item = (long) item; - event.m_pointDrag = wxPoint(x, y); + event.m_pointDrag = pt; event.SetEventObject(this); (void)GetEventHandler()->ProcessEvent(event); @@ -2733,9 +2907,7 @@ void wxGenericTreeCtrl::OnMouse( wxMouseEvent &event ) { wxTreeEvent nevent(wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK, GetId()); nevent.m_item = (long) item; - CalcScrolledPosition(x, y, - &nevent.m_pointDrag.x, - &nevent.m_pointDrag.y); + nevent.m_pointDrag = CalcScrolledPosition(pt); nevent.SetEventObject(this); GetEventHandler()->ProcessEvent(nevent); } @@ -2747,10 +2919,17 @@ void wxGenericTreeCtrl::OnMouse( wxMouseEvent &event ) (flags & wxTREE_HITTEST_ONITEMLABEL) && HasFlag(wxTR_EDIT_LABELS) ) { - if ( m_renameTimer->IsRunning() ) - m_renameTimer->Stop(); + if ( m_renameTimer ) + { + if ( m_renameTimer->IsRunning() ) + m_renameTimer->Stop(); + } + else + { + m_renameTimer = new wxTreeRenameTimer( this ); + } - m_renameTimer->Start( 100, TRUE ); + m_renameTimer->Start( wxTreeRenameTimer::DELAY, TRUE ); } m_lastOnSame = FALSE; @@ -2790,15 +2969,15 @@ void wxGenericTreeCtrl::OnMouse( wxMouseEvent &event ) if ( event.LeftDClick() ) { // double clicking should not start editing the item label - m_renameTimer->Stop(); + if ( m_renameTimer ) + m_renameTimer->Stop(); + m_lastOnSame = FALSE; // send activate event first wxTreeEvent nevent( wxEVT_COMMAND_TREE_ITEM_ACTIVATED, GetId() ); nevent.m_item = (long) item; - CalcScrolledPosition(x, y, - &nevent.m_pointDrag.x, - &nevent.m_pointDrag.y); + nevent.m_pointDrag = CalcScrolledPosition(pt); nevent.SetEventObject( this ); if ( !GetEventHandler()->ProcessEvent( nevent ) ) { @@ -2834,7 +3013,10 @@ void wxGenericTreeCtrl::CalculateSize( wxGenericTreeItem *item, wxDC &dc ) wxCoord text_w = 0; wxCoord text_h = 0; - if (item->IsBold()) + wxTreeItemAttr *attr = item->GetAttributes(); + if ( attr && attr->HasFont() ) + dc.SetFont(attr->GetFont()); + else if ( item->IsBold() ) dc.SetFont(m_boldFont); dc.GetTextExtent( item->GetText(), &text_w, &text_h ); @@ -2928,20 +3110,14 @@ void wxGenericTreeCtrl::RefreshSubtree(wxGenericTreeItem *item) { if (m_dirty) return; - wxClientDC dc(this); - PrepareDC(dc); - - int cw = 0; - int ch = 0; - GetClientSize( &cw, &ch ); + wxSize client = GetClientSize(); wxRect rect; - rect.x = dc.LogicalToDeviceX( 0 ); - rect.width = cw; - rect.y = dc.LogicalToDeviceY( item->GetY() ); - rect.height = ch; + CalcScrolledPosition(0, item->GetY(), NULL, &rect.y); + rect.width = client.x; + rect.height = client.y; - Refresh( TRUE, &rect ); + Refresh(TRUE, &rect); AdjustMyScrollbars(); } @@ -2950,20 +3126,12 @@ void wxGenericTreeCtrl::RefreshLine( wxGenericTreeItem *item ) { if (m_dirty) return; - wxClientDC dc(this); - PrepareDC( dc ); - - int cw = 0; - int ch = 0; - GetClientSize( &cw, &ch ); - wxRect rect; - rect.x = dc.LogicalToDeviceX( 0 ); - rect.y = dc.LogicalToDeviceY( item->GetY() ); - rect.width = cw; + 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()