X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/0396d31b576ce6bc9441e42293dfb0c26130eac7..d949570b6673dadd764686213afb89bddb6f19da:/src/generic/treectlg.cpp diff --git a/src/generic/treectlg.cpp b/src/generic/treectlg.cpp index 2e88883895..d30b80d4f0 100644 --- a/src/generic/treectlg.cpp +++ b/src/generic/treectlg.cpp @@ -45,16 +45,11 @@ #include "wx/mac/private.h" #endif -#ifdef __WXGTK20__ - #include "wx/gtk/private.h" - #include "wx/gtk/win_gtk.h" -#endif - // ----------------------------------------------------------------------------- // array types // ----------------------------------------------------------------------------- -class WXDLLEXPORT wxGenericTreeItem; +class WXDLLIMPEXP_FWD_CORE wxGenericTreeItem; WX_DEFINE_EXPORTED_ARRAY_PTR(wxGenericTreeItem *, wxArrayGenericTreeItems); @@ -553,7 +548,7 @@ wxGenericTreeItem::~wxGenericTreeItem() void wxGenericTreeItem::DeleteChildren(wxGenericTreeCtrl *tree) { - size_t count = m_children.Count(); + size_t count = m_children.GetCount(); for ( size_t n = 0; n < count; n++ ) { wxGenericTreeItem *child = m_children[n]; @@ -575,7 +570,7 @@ void wxGenericTreeItem::SetText( const wxString &text ) size_t wxGenericTreeItem::GetChildrenCount(bool recursively) const { - size_t count = m_children.Count(); + size_t count = m_children.GetCount(); if ( !recursively ) return count; @@ -598,7 +593,7 @@ void wxGenericTreeItem::GetSize( int &x, int &y, if (IsExpanded()) { - size_t count = m_children.Count(); + size_t count = m_children.GetCount(); for ( size_t n = 0; n < count; ++n ) { m_children[n]->GetSize( x, y, theButton ); @@ -673,7 +668,7 @@ wxGenericTreeItem *wxGenericTreeItem::HitTest(const wxPoint& point, } // evaluate children - size_t count = m_children.Count(); + size_t count = m_children.GetCount(); for ( size_t n = 0; n < count; n++ ) { wxGenericTreeItem *res = m_children[n]->HitTest( point, @@ -759,13 +754,6 @@ void wxGenericTreeCtrl::Init() m_indent = 15; m_spacing = 18; -#ifdef __WXMAC__ - // OS X sel item highlight color differs from text highlight color, which is - // what wxSYS_COLOUR_HIGHLIGHT returns. - RGBColor hilight; - GetThemeBrushAsColor(kThemeBrushAlternatePrimaryHighlightColor, 32, true, &hilight); - m_hilightBrush = new wxBrush( wxColour(hilight.red, hilight.green, hilight.blue ), wxSOLID ); -#else m_hilightBrush = new wxBrush ( wxSystemSettings::GetColour @@ -774,14 +762,7 @@ void wxGenericTreeCtrl::Init() ), wxSOLID ); -#endif -#ifdef __WXMAC__ - // on Mac, this color also differs from the wxSYS_COLOUR_BTNSHADOW, enough to be noticable. - // I don't know if BTNSHADOW is appropriate in other contexts, so I'm just changing it here. - GetThemeBrushAsColor(kThemeBrushSecondaryHighlightColor, 32, true, &hilight); - m_hilightUnfocusedBrush = new wxBrush( wxColour(hilight.red, hilight.green, hilight.blue ), wxSOLID ); -#else m_hilightUnfocusedBrush = new wxBrush ( wxSystemSettings::GetColour @@ -790,7 +771,7 @@ void wxGenericTreeCtrl::Init() ), wxSOLID ); -#endif + m_imageListButtons = NULL; m_ownsImageListButtons = false; @@ -869,7 +850,14 @@ bool wxGenericTreeCtrl::Create(wxWindow *parent, if (!m_hasFont) SetOwnFont(attr.font); - m_dottedPen = wxPen( wxT("grey"), 0, 0 ); + // this is a misnomer: it's called "dotted pen" but uses (default) wxSOLID + // style because we apparently get performance problems when using dotted + // pen for drawing in some ports -- but under MSW it seems to work fine +#ifdef __WXMSW__ + m_dottedPen = wxPen(*wxLIGHT_GREY, 0, wxDOT); +#else + m_dottedPen = *wxGREY_PEN; +#endif SetInitialSize(size); @@ -1222,7 +1210,7 @@ wxTreeItemId wxGenericTreeCtrl::GetNextChild(const wxTreeItemId& item, // 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() ) + if ( *pIndex < children.GetCount() ) { return children.Item((*pIndex)++); } @@ -1233,36 +1221,6 @@ wxTreeItemId wxGenericTreeCtrl::GetNextChild(const wxTreeItemId& item, } } -#if WXWIN_COMPATIBILITY_2_4 - -wxTreeItemId wxGenericTreeCtrl::GetFirstChild(const wxTreeItemId& item, - long& cookie) const -{ - wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); - - cookie = 0; - return GetNextChild(item, cookie); -} - -wxTreeItemId wxGenericTreeCtrl::GetNextChild(const wxTreeItemId& item, - long& cookie) const -{ - wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); - - wxArrayGenericTreeItems& children = ((wxGenericTreeItem*) item.m_pItem)->GetChildren(); - if ( (size_t)cookie < children.Count() ) - { - return children.Item((size_t)cookie++); - } - else - { - // there are no more of them - return wxTreeItemId(); - } -} - -#endif // WXWIN_COMPATIBILITY_2_4 - wxTreeItemId wxGenericTreeCtrl::GetLastChild(const wxTreeItemId& item) const { wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); @@ -1288,7 +1246,7 @@ wxTreeItemId wxGenericTreeCtrl::GetNextSibling(const wxTreeItemId& item) const wxASSERT( index != wxNOT_FOUND ); // I'm not a child of my parent? size_t n = (size_t)(index + 1); - return n == siblings.Count() ? wxTreeItemId() : wxTreeItemId(siblings[n]); + return n == siblings.GetCount() ? wxTreeItemId() : wxTreeItemId(siblings[n]); } wxTreeItemId wxGenericTreeCtrl::GetPrevSibling(const wxTreeItemId& item) const @@ -1357,6 +1315,7 @@ wxTreeItemId wxGenericTreeCtrl::GetFirstVisibleItem() const wxTreeItemId wxGenericTreeCtrl::GetNextVisible(const wxTreeItemId& item) const { wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); + wxASSERT_MSG( IsVisible(item), wxT("this item itself should be visible") ); wxTreeItemId id = item; if (id.IsOk()) @@ -1373,10 +1332,37 @@ wxTreeItemId wxGenericTreeCtrl::GetNextVisible(const wxTreeItemId& item) const wxTreeItemId wxGenericTreeCtrl::GetPrevVisible(const wxTreeItemId& item) const { wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); + wxASSERT_MSG( IsVisible(item), wxT("this item itself should be visible") ); - wxFAIL_MSG(wxT("not implemented")); + // find out the starting point + wxTreeItemId prevItem = GetPrevSibling(item); + if ( !prevItem.IsOk() ) + { + prevItem = GetItemParent(item); + } - return wxTreeItemId(); + // find the first visible item after it + while ( prevItem.IsOk() && !IsVisible(prevItem) ) + { + prevItem = GetNext(prevItem); + if ( !prevItem.IsOk() || prevItem == item ) + { + // there are no visible items before item + return wxTreeItemId(); + } + } + + // from there we must be able to navigate until this item + while ( prevItem.IsOk() ) + { + const wxTreeItemId nextItem = GetNextVisible(prevItem); + if ( !nextItem.IsOk() || nextItem == item ) + break; + + prevItem = nextItem; + } + + return prevItem; } // called by wxTextTreeCtrl when it marks itself for deletion @@ -1464,6 +1450,7 @@ wxTreeItemId wxGenericTreeCtrl::DoInsertItem(const wxTreeItemId& parentId, parent->Insert( item, previous == (size_t)-1 ? parent->GetChildren().size() : previous ); + InvalidateBestSize(); return item; } @@ -1498,6 +1485,7 @@ wxTreeItemId wxGenericTreeCtrl::AddRoot(const wxString& text, m_current->SetHilight( true ); } + InvalidateBestSize(); return m_anchor; } @@ -1529,7 +1517,7 @@ wxTreeItemId wxGenericTreeCtrl::DoInsertAfter(const wxTreeItemId& parentId, void wxGenericTreeCtrl::SendDeleteEvent(wxGenericTreeItem *item) { wxTreeEvent event(wxEVT_COMMAND_TREE_DELETE_ITEM, this, item); - ProcessEvent( event ); + GetEventHandler()->ProcessEvent( event ); } // Don't leave edit or selection on a child which is about to disappear @@ -1558,6 +1546,7 @@ void wxGenericTreeCtrl::DeleteChildren(const wxTreeItemId& itemId) wxGenericTreeItem *item = (wxGenericTreeItem*) itemId.m_pItem; ChildrenClosing(item); item->DeleteChildren(this); + InvalidateBestSize(); } void wxGenericTreeCtrl::Delete(const wxTreeItemId& itemId) @@ -1622,6 +1611,8 @@ void wxGenericTreeCtrl::Delete(const wxTreeItemId& itemId) m_select_me = NULL; delete item; + + InvalidateBestSize(); } void wxGenericTreeCtrl::DeleteAllItems() @@ -1648,19 +1639,26 @@ void wxGenericTreeCtrl::Expand(const wxTreeItemId& itemId) wxTreeEvent event(wxEVT_COMMAND_TREE_ITEM_EXPANDING, this, item); - if ( ProcessEvent( event ) && !event.IsAllowed() ) + if ( GetEventHandler()->ProcessEvent( event ) && !event.IsAllowed() ) { // cancelled by program return; } item->Expand(); - CalculatePositions(); + if ( !m_freezeCount ) + { + CalculatePositions(); - RefreshSubtree(item); + RefreshSubtree(item); + } + else // frozen + { + m_dirty = true; + } event.SetEventType(wxEVT_COMMAND_TREE_ITEM_EXPANDED); - ProcessEvent( event ); + GetEventHandler()->ProcessEvent( event ); } void wxGenericTreeCtrl::Collapse(const wxTreeItemId& itemId) @@ -1674,7 +1672,7 @@ void wxGenericTreeCtrl::Collapse(const wxTreeItemId& itemId) return; wxTreeEvent event(wxEVT_COMMAND_TREE_ITEM_COLLAPSING, this, item); - if ( ProcessEvent( event ) && !event.IsAllowed() ) + if ( GetEventHandler()->ProcessEvent( event ) && !event.IsAllowed() ) { // cancelled by program return; @@ -1685,7 +1683,7 @@ void wxGenericTreeCtrl::Collapse(const wxTreeItemId& itemId) #if 0 // TODO why should items be collapsed recursively? wxArrayGenericTreeItems& children = item->GetChildren(); - size_t count = children.Count(); + size_t count = children.GetCount(); for ( size_t n = 0; n < count; n++ ) { Collapse(children[n]); @@ -1697,7 +1695,7 @@ void wxGenericTreeCtrl::Collapse(const wxTreeItemId& itemId) RefreshSubtree(item); event.SetEventType(wxEVT_COMMAND_TREE_ITEM_COLLAPSED); - ProcessEvent( event ); + GetEventHandler()->ProcessEvent( event ); } void wxGenericTreeCtrl::CollapseAndReset(const wxTreeItemId& item) @@ -1739,7 +1737,7 @@ void wxGenericTreeCtrl::UnselectAllChildren(wxGenericTreeItem *item) if (item->HasChildren()) { wxArrayGenericTreeItems& children = item->GetChildren(); - size_t count = children.Count(); + size_t count = children.GetCount(); for ( size_t n = 0; n < count; ++n ) { UnselectAllChildren(children[n]); @@ -1775,7 +1773,7 @@ bool wxGenericTreeCtrl::TagNextChildren(wxGenericTreeItem *crt_item, wxGenericTr int index = children.Index(crt_item); wxASSERT( index != wxNOT_FOUND ); // I'm not a child of my parent? - size_t count = children.Count(); + size_t count = children.GetCount(); for (size_t n=(size_t)(index+1); nHasChildren()) { wxArrayGenericTreeItems& children = crt_item->GetChildren(); - size_t count = children.Count(); + size_t count = children.GetCount(); for ( size_t n = 0; n < count; ++n ) { if (TagAllChildrenUntilLast(children[n], last_item, select)) @@ -1957,7 +1955,7 @@ size_t wxGenericTreeCtrl::GetSelections(wxArrayTreeItemIds &array) const } //else: the tree is empty, so no selections - return array.Count(); + return array.GetCount(); } void wxGenericTreeCtrl::EnsureVisible(const wxTreeItemId& item) @@ -2068,7 +2066,7 @@ void wxGenericTreeCtrl::SortChildren(const wxTreeItemId& itemId) wxT("wxGenericTreeCtrl::SortChildren is not reentrant") ); wxArrayGenericTreeItems& children = item->GetChildren(); - if ( children.Count() > 1 ) + if ( children.GetCount() > 1 ) { m_dirty = true; @@ -2192,7 +2190,7 @@ void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc) else if (item->IsBold()) dc.SetFont(m_boldFont); - long text_w = 0, text_h = 0; + wxCoord text_w = 0, text_h = 0; dc.GetTextExtent( item->GetText(), &text_w, &text_h ); int image_h = 0, image_w = 0; @@ -2241,7 +2239,7 @@ void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc) x=0; GetVirtualSize(&w, &h); wxRect rect( x, item->GetY()+offset, w, total_h-offset); -#ifndef __WXGTK20__ +#if !defined(__WXGTK20__) && !defined(__WXMAC__) dc.DrawRectangle(rect); #else if (!item->IsSelected()) @@ -2250,25 +2248,16 @@ void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc) } else { - CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y ); - - gtk_paint_flat_box( m_widget->style, - GTK_PIZZA(m_wxwindow)->bin_window, - GTK_STATE_SELECTED, - GTK_SHADOW_NONE, - NULL, - m_wxwindow, - "cell_even", - rect.x, rect.y, rect.width, rect.height ); - + int flags = wxCONTROL_SELECTED; + if (m_hasFocus +#ifdef __WXMAC__ + && IsControlActive( (ControlRef)GetHandle() ) +#endif + ) + flags |= wxCONTROL_FOCUSED; if ((item == m_current) && (m_hasFocus)) - gtk_paint_focus( m_widget->style, - GTK_PIZZA(m_wxwindow)->bin_window, - GTK_STATE_SELECTED, - NULL, - m_wxwindow, - "treeview", - rect.x, rect.y, rect.width, rect.height ); + flags |= wxCONTROL_CURRENT; + wxRendererNative::Get().DrawItemSelectionRect( this, dc, rect, flags ); } #endif } @@ -2281,31 +2270,18 @@ void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc) // background colour. wxRect rect( item->GetX() + image_w - 2, item->GetY()+offset, item->GetWidth() - image_w + 2, total_h-offset ); -#ifndef __WXGTK20__ +#if !defined(__WXGTK20__) && !defined(__WXMAC__) dc.DrawRectangle( rect ); #else - CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y ); rect.x -= 1; rect.width += 2; - gtk_paint_flat_box( m_widget->style, - GTK_PIZZA(m_wxwindow)->bin_window, - GTK_STATE_SELECTED, - GTK_SHADOW_NONE, - NULL, - m_wxwindow, - "cell_even", - rect.x, rect.y, rect.width, rect.height ); - + int flags = wxCONTROL_SELECTED; + if (m_hasFocus) + flags |= wxCONTROL_FOCUSED; if ((item == m_current) && (m_hasFocus)) - gtk_paint_focus( m_widget->style, - GTK_PIZZA(m_wxwindow)->bin_window, - GTK_STATE_SELECTED, - NULL, - m_wxwindow, - "treeview", - rect.x, rect.y, rect.width, rect.height ); - + flags |= wxCONTROL_CURRENT; + wxRendererNative::Get().DrawItemSelectionRect( this, dc, rect, flags ); #endif } // On GTK+ 2, drawing a 'normal' background is wrong for themes that @@ -2315,7 +2291,7 @@ void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc) { wxRect rect( item->GetX()-2, item->GetY()+offset, item->GetWidth()+2, total_h-offset ); -#ifndef __WXGTK20__ +#if !defined(__WXGTK20__) && !defined(__WXMAC__) dc.DrawRectangle( rect ); #else if ( attr && attr->HasBackgroundColour() ) @@ -2324,27 +2300,15 @@ void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc) } else { - CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y ); rect.x -= 1; rect.width += 2; - - gtk_paint_flat_box( m_widget->style, - GTK_PIZZA(m_wxwindow)->bin_window, - GTK_STATE_SELECTED, - GTK_SHADOW_NONE, - NULL, - m_wxwindow, - "cell_even", - rect.x, rect.y, rect.width, rect.height ); - + + int flags = wxCONTROL_SELECTED; + if (m_hasFocus) + flags |= wxCONTROL_FOCUSED; if ((item == m_current) && (m_hasFocus)) - gtk_paint_focus( m_widget->style, - GTK_PIZZA(m_wxwindow)->bin_window, - GTK_STATE_SELECTED, - NULL, - m_wxwindow, - "treeview", - rect.x, rect.y, rect.width, rect.height ); + flags |= wxCONTROL_CURRENT; + wxRendererNative::Get().DrawItemSelectionRect( this, dc, rect, flags ); } #endif } @@ -2383,7 +2347,7 @@ void wxGenericTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxDC &dc, int level // always expand hidden root int origY = y; wxArrayGenericTreeItems& children = item->GetChildren(); - int count = children.Count(); + int count = children.GetCount(); if (count > 0) { int n = 0, oldY; @@ -2431,7 +2395,7 @@ void wxGenericTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxDC &dc, int level // 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 + && m_hasFocus && IsControlActive( (ControlRef)GetHandle() ) #endif ) { @@ -2531,7 +2495,7 @@ void wxGenericTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxDC &dc, int level if (item->IsExpanded()) { wxArrayGenericTreeItems& children = item->GetChildren(); - int count = children.Count(); + int count = children.GetCount(); if (count > 0) { int n = 0, oldY; @@ -2844,7 +2808,11 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event ) case WXK_RIGHT: // this works the same as the down arrow except that we // also expand the item if it wasn't expanded yet - Expand(m_current); + if (m_current != GetRootItem().m_pItem || !HasFlag(wxTR_HIDE_ROOT)) + Expand(m_current); + //else: don't try to expand hidden root item (which can be the + // current one when the tree is empty) + // fall through case WXK_DOWN: @@ -2853,6 +2821,9 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event ) { wxTreeItemIdValue cookie; wxTreeItemId child = GetFirstChild( m_key_current, cookie ); + if ( !child ) + break; + DoSelectItem( child, unselect_others, extended_select ); m_key_current=(wxGenericTreeItem*) child.m_pItem; } @@ -3521,7 +3492,7 @@ void wxGenericTreeCtrl::CalculateLevel( wxGenericTreeItem *item, wxDC &dc, int l Recurse: wxArrayGenericTreeItems& children = item->GetChildren(); - size_t n, count = children.Count(); + size_t n, count = children.GetCount(); ++level; for (n = 0; n < count; ++n ) CalculateLevel( children[n], dc, level, y ); // recurse @@ -3618,7 +3589,10 @@ void wxGenericTreeCtrl::Thaw() if ( --m_freezeCount == 0 ) { - Refresh(); + if ( m_dirty ) + DoDirtyProcessing(); + else + Refresh(); } } @@ -3678,20 +3652,6 @@ wxGenericTreeCtrl::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant)) #endif } -#if WXWIN_COMPATIBILITY_2_4 - -int wxGenericTreeCtrl::GetItemSelectedImage(const wxTreeItemId& item) const -{ - return GetItemImage(item, wxTreeItemIcon_Selected); -} - -void wxGenericTreeCtrl::SetItemSelectedImage(const wxTreeItemId& item, int image) -{ - SetItemImage(item, image, wxTreeItemIcon_Selected); -} - -#endif // WXWIN_COMPATIBILITY_2_4 - void wxGenericTreeCtrl::DoDirtyProcessing() { if (m_freezeCount) @@ -3704,4 +3664,35 @@ void wxGenericTreeCtrl::DoDirtyProcessing() 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 size; +} + #endif // wxUSE_TREECTRL