X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/eafd76b02ce9662d48e56ce2769c97af46139bc1..3e1924dd5f5744c3e2a8973de9b3e4f372b7fd85:/src/generic/treectlg.cpp?ds=sidebyside diff --git a/src/generic/treectlg.cpp b/src/generic/treectlg.cpp index 10360a4abf..d5880b0191 100644 --- a/src/generic/treectlg.cpp +++ b/src/generic/treectlg.cpp @@ -49,7 +49,7 @@ // array types // ----------------------------------------------------------------------------- -class WXDLLEXPORT wxGenericTreeItem; +class WXDLLIMPEXP_FWD_CORE wxGenericTreeItem; WX_DEFINE_EXPORTED_ARRAY_PTR(wxGenericTreeItem *, wxArrayGenericTreeItems); @@ -92,29 +92,8 @@ class WXDLLEXPORT wxTreeTextCtrl: public wxTextCtrl public: wxTreeTextCtrl(wxGenericTreeCtrl *owner, wxGenericTreeItem *item); - void EndEdit(bool discardChanges = false) - { - if ( discardChanges ) - { - StopEditing(); - } - else - { - m_aboutToFinish = true; + void EndEdit( bool discardChanges ); - // 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: @@ -123,13 +102,12 @@ protected: void OnKillFocus( wxFocusEvent &event ); bool AcceptChanges(); - void Finish(); + void Finish( bool setfocus ); private: wxGenericTreeCtrl *m_owner; wxGenericTreeItem *m_itemEdited; wxString m_startValue; - bool m_finished; bool m_aboutToFinish; DECLARE_EVENT_TABLE() @@ -363,7 +341,6 @@ wxTreeTextCtrl::wxTreeTextCtrl(wxGenericTreeCtrl *owner, : m_itemEdited(item), m_startValue(item->GetText()) { m_owner = owner; - m_finished = false; m_aboutToFinish = false; int w = m_itemEdited->GetWidth(), @@ -407,6 +384,26 @@ wxTreeTextCtrl::wxTreeTextCtrl(wxGenericTreeCtrl *owner, wxPoint(x - 4, y - 4), wxSize(w + 11, h + 8)); } +void wxTreeTextCtrl::EndEdit(bool discardChanges) +{ + m_aboutToFinish = true; + + if ( discardChanges ) + { + m_owner->OnRenameCancelled(m_itemEdited); + + Finish( true ); + } + else + { + // Notify the owner about the changes + AcceptChanges(); + + // Even if vetoed, close the control (consistent with MSW) + Finish( true ); + } +} + bool wxTreeTextCtrl::AcceptChanges() { const wxString value = GetValue(); @@ -435,18 +432,14 @@ bool wxTreeTextCtrl::AcceptChanges() return true; } -void wxTreeTextCtrl::Finish() +void wxTreeTextCtrl::Finish( bool setfocus ) { - if ( !m_finished ) - { - m_owner->ResetTextControl(); - - wxPendingDelete.Append(this); + m_owner->ResetTextControl(); - m_finished = true; + wxPendingDelete.Append(this); + if (setfocus) m_owner->SetFocus(); - } } void wxTreeTextCtrl::OnChar( wxKeyEvent &event ) @@ -454,11 +447,11 @@ void wxTreeTextCtrl::OnChar( wxKeyEvent &event ) switch ( event.m_keyCode ) { case WXK_RETURN: - EndEdit(); + EndEdit( false ); break; case WXK_ESCAPE: - StopEditing(); + EndEdit( true ); break; default: @@ -468,7 +461,7 @@ void wxTreeTextCtrl::OnChar( wxKeyEvent &event ) void wxTreeTextCtrl::OnKeyUp( wxKeyEvent &event ) { - if ( !m_finished ) + if ( !m_aboutToFinish ) { // auto-grow the textctrl: wxSize parentSize = m_owner->GetSize(); @@ -488,18 +481,15 @@ void wxTreeTextCtrl::OnKeyUp( wxKeyEvent &event ) void wxTreeTextCtrl::OnKillFocus( wxFocusEvent &event ) { - if ( !m_finished && !m_aboutToFinish ) + if ( !m_aboutToFinish ) { - // We must finish regardless of success, otherwise we'll get - // focus problems: - Finish(); - if ( !AcceptChanges() ) m_owner->OnRenameCancelled( m_itemEdited ); + + Finish( false ); } - // We must let the native text control handle focus, too, otherwise - // it could have problems with the cursor (e.g., in wxGTK). + // We should let the native text control handle focus, too. event.Skip(); } @@ -548,7 +538,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]; @@ -570,7 +560,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; @@ -593,7 +583,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 ); @@ -668,7 +658,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, @@ -782,7 +772,6 @@ void wxGenericTreeCtrl::Init() m_textCtrl = NULL; m_renameTimer = NULL; - m_freezeCount = 0; m_findTimer = NULL; @@ -790,8 +779,8 @@ void wxGenericTreeCtrl::Init() m_lastOnSame = false; -#ifdef __WXMAC_CARBON__ - m_normalFont.MacCreateThemeFont( kThemeViewsFont ) ; +#ifdef __WXMAC__ + m_normalFont.MacCreateFromThemeFont( kThemeViewsFont ) ; #else m_normalFont = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT ); #endif @@ -813,21 +802,12 @@ bool wxGenericTreeCtrl::Create(wxWindow *parent, const wxString& name ) { #ifdef __WXMAC__ - int major,minor; - wxGetOsVersion( &major, &minor ); + int major, minor; + wxGetOsVersion(&major, &minor); - style &= ~wxTR_LINES_AT_ROOT; - style |= wxTR_NO_LINES; if (major < 10) style |= wxTR_ROW_LINES; - - if (style == 0 || style & wxTR_DEFAULT_STYLE) - style |= wxTR_FULL_ROW_HIGHLIGHT; - #endif // __WXMAC__ -#ifdef __WXGTK20__ - style |= wxTR_NO_LINES; -#endif if ( !wxControl::Create( parent, id, pos, size, style|wxHSCROLL|wxVSCROLL, @@ -850,7 +830,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); @@ -1203,7 +1190,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)++); } @@ -1239,7 +1226,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 @@ -1308,6 +1295,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()) @@ -1324,10 +1312,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 @@ -1415,6 +1430,7 @@ wxTreeItemId wxGenericTreeCtrl::DoInsertItem(const wxTreeItemId& parentId, parent->Insert( item, previous == (size_t)-1 ? parent->GetChildren().size() : previous ); + InvalidateBestSize(); return item; } @@ -1449,6 +1465,7 @@ wxTreeItemId wxGenericTreeCtrl::AddRoot(const wxString& text, m_current->SetHilight( true ); } + InvalidateBestSize(); return m_anchor; } @@ -1487,7 +1504,7 @@ void wxGenericTreeCtrl::SendDeleteEvent(wxGenericTreeItem *item) void wxGenericTreeCtrl::ChildrenClosing(wxGenericTreeItem* item) { if (m_textCtrl != NULL && item != m_textCtrl->item() && IsDescendantOf(item, m_textCtrl->item())) { - m_textCtrl->StopEditing(); + m_textCtrl->EndEdit( true ); } if (item != m_key_current && IsDescendantOf(item, m_key_current)) { m_key_current = NULL; @@ -1509,6 +1526,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) @@ -1520,7 +1538,7 @@ void wxGenericTreeCtrl::Delete(const wxTreeItemId& itemId) if (m_textCtrl != NULL && IsDescendantOf(item, m_textCtrl->item())) { // can't delete the item being edited, cancel editing it first - m_textCtrl->StopEditing(); + m_textCtrl->EndEdit( true ); } wxGenericTreeItem *parent = item->GetParent(); @@ -1573,6 +1591,8 @@ void wxGenericTreeCtrl::Delete(const wxTreeItemId& itemId) m_select_me = NULL; delete item; + + InvalidateBestSize(); } void wxGenericTreeCtrl::DeleteAllItems() @@ -1606,9 +1626,16 @@ void wxGenericTreeCtrl::Expand(const wxTreeItemId& itemId) } item->Expand(); - CalculatePositions(); + if ( !IsFrozen() ) + { + CalculatePositions(); - RefreshSubtree(item); + RefreshSubtree(item); + } + else // frozen + { + m_dirty = true; + } event.SetEventType(wxEVT_COMMAND_TREE_ITEM_EXPANDED); GetEventHandler()->ProcessEvent( event ); @@ -1636,7 +1663,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]); @@ -1690,7 +1717,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]); @@ -1726,7 +1753,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)) @@ -1870,7 +1897,7 @@ void wxGenericTreeCtrl::SelectItem(const wxTreeItemId& itemId, bool select) { 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; @@ -1908,7 +1935,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) @@ -2019,7 +2046,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; @@ -2143,7 +2170,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; @@ -2203,7 +2230,7 @@ void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc) { int flags = wxCONTROL_SELECTED; if (m_hasFocus -#ifdef __WXMAC__ +#if defined( __WXMAC__ ) && !defined(__WXUNIVERSAL__) && IsControlActive( (ControlRef)GetHandle() ) #endif ) @@ -2228,7 +2255,7 @@ void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc) #else rect.x -= 1; rect.width += 2; - + int flags = wxCONTROL_SELECTED; if (m_hasFocus) flags |= wxCONTROL_FOCUSED; @@ -2255,7 +2282,7 @@ void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc) { rect.x -= 1; rect.width += 2; - + int flags = wxCONTROL_SELECTED; if (m_hasFocus) flags |= wxCONTROL_FOCUSED; @@ -2300,7 +2327,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; @@ -2343,7 +2370,7 @@ void wxGenericTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxDC &dc, int level wxColour colText; if ( item->IsSelected() -#ifdef __WXMAC__ +#if defined( __WXMAC__ ) && !defined(__WXUNIVERSAL__) // 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 @@ -2448,7 +2475,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; @@ -2761,7 +2788,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: @@ -2770,6 +2801,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; } @@ -3438,7 +3472,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 @@ -3463,13 +3497,13 @@ void wxGenericTreeCtrl::CalculatePositions() void wxGenericTreeCtrl::Refresh(bool eraseBackground, const wxRect *rect) { - if ( !m_freezeCount ) + if ( !IsFrozen() ) wxTreeCtrlBase::Refresh(eraseBackground, rect); } void wxGenericTreeCtrl::RefreshSubtree(wxGenericTreeItem *item) { - if (m_dirty || m_freezeCount) + if (m_dirty || IsFrozen() ) return; wxSize client = GetClientSize(); @@ -3486,7 +3520,7 @@ void wxGenericTreeCtrl::RefreshSubtree(wxGenericTreeItem *item) void wxGenericTreeCtrl::RefreshLine( wxGenericTreeItem *item ) { - if (m_dirty || m_freezeCount) + if (m_dirty || IsFrozen() ) return; wxRect rect; @@ -3499,7 +3533,7 @@ void wxGenericTreeCtrl::RefreshLine( wxGenericTreeItem *item ) void wxGenericTreeCtrl::RefreshSelected() { - if (m_freezeCount) + if (IsFrozen()) return; // TODO: this is awfully inefficient, we should keep the list of all @@ -3510,7 +3544,7 @@ void wxGenericTreeCtrl::RefreshSelected() void wxGenericTreeCtrl::RefreshSelectedUnder(wxGenericTreeItem *item) { - if (m_freezeCount) + if (IsFrozen()) return; if ( item->IsSelected() ) @@ -3524,19 +3558,14 @@ void wxGenericTreeCtrl::RefreshSelectedUnder(wxGenericTreeItem *item) } } -void wxGenericTreeCtrl::Freeze() +void wxGenericTreeCtrl::DoThaw() { - m_freezeCount++; -} + wxTreeCtrlBase::DoThaw(); -void wxGenericTreeCtrl::Thaw() -{ - wxCHECK_RET( m_freezeCount > 0, _T("thawing unfrozen tree control?") ); - - if ( --m_freezeCount == 0 ) - { + if ( m_dirty ) + DoDirtyProcessing(); + else Refresh(); - } } // ---------------------------------------------------------------------------- @@ -3597,7 +3626,7 @@ wxGenericTreeCtrl::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant)) void wxGenericTreeCtrl::DoDirtyProcessing() { - if (m_freezeCount) + if (IsFrozen()) return; m_dirty = false;