X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/edb8f2985fc838f92c60d9efd42462441f3caea9..1cff04deb5c17c95bef9c83e72645f105b90e750:/src/generic/treectlg.cpp diff --git a/src/generic/treectlg.cpp b/src/generic/treectlg.cpp index 05cfdf1187..054b388fcc 100644 --- a/src/generic/treectlg.cpp +++ b/src/generic/treectlg.cpp @@ -120,6 +120,8 @@ public: private: wxGenericTreeCtrl *m_owner; + + DECLARE_NO_COPY_CLASS(wxTreeRenameTimer) }; // control used for in-place edit @@ -143,6 +145,7 @@ private: bool m_finished; DECLARE_EVENT_TABLE() + DECLARE_NO_COPY_CLASS(wxTreeTextCtrl) }; // timer used to clear wxGenericTreeCtrl::m_findPrefix if no key was pressed @@ -159,6 +162,8 @@ public: private: wxGenericTreeCtrl *m_owner; + + DECLARE_NO_COPY_CLASS(wxTreeFindTimer) }; // a tree item @@ -298,6 +303,8 @@ private: // children but has a [+] button int m_isBold :1; // render the label in bold font int m_ownsAttr :1; // delete attribute when done + + DECLARE_NO_COPY_CLASS(wxGenericTreeItem) }; // ============================================================================= @@ -322,6 +329,23 @@ static void EventFlagsToSelType(long style, unselect_others = !(extended_select || (ctrlDown && is_multiple)); } +// check if the given item is under another one +static bool IsDescendantOf(wxGenericTreeItem *parent, wxGenericTreeItem *item) +{ + while ( item ) + { + if ( item == parent ) + { + // item is a descendant of parent + return TRUE; + } + + item = item->GetParent(); + } + + return FALSE; +} + // ----------------------------------------------------------------------------- // wxTreeRenameTimer (internal) // ----------------------------------------------------------------------------- @@ -410,6 +434,8 @@ void wxTreeTextCtrl::Finish() { if ( !m_finished ) { + m_owner->ResetTextControl(); + wxPendingDelete.Append(this); m_finished = TRUE; @@ -432,6 +458,7 @@ void wxTreeTextCtrl::OnChar( wxKeyEvent &event ) case WXK_ESCAPE: Finish(); + m_owner->OnRenameCancelled(m_itemEdited); break; default: @@ -737,6 +764,7 @@ void wxGenericTreeCtrl::Init() m_dragCount = 0; m_isDragging = FALSE; m_dropTarget = m_oldSelection = (wxGenericTreeItem *)NULL; + m_textCtrl = NULL; m_renameTimer = NULL; m_findTimer = NULL; @@ -744,11 +772,13 @@ void wxGenericTreeCtrl::Init() m_lastOnSame = FALSE; m_normalFont = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT ); - m_boldFont = wxFont( m_normalFont.GetPointSize(), - m_normalFont.GetFamily(), - m_normalFont.GetStyle(), - wxBOLD, - m_normalFont.GetUnderlined()); + m_boldFont = wxFont(m_normalFont.GetPointSize(), + m_normalFont.GetFamily(), + m_normalFont.GetStyle(), + wxBOLD, + m_normalFont.GetUnderlined(), + m_normalFont.GetFaceName(), + m_normalFont.GetEncoding()); } bool wxGenericTreeCtrl::Create(wxWindow *parent, @@ -901,6 +931,30 @@ wxTreeItemData *wxGenericTreeCtrl::GetItemData(const wxTreeItemId& item) const return ((wxGenericTreeItem*) item.m_pItem)->GetData(); } +wxColour wxGenericTreeCtrl::GetItemTextColour(const wxTreeItemId& item) const +{ + wxCHECK_MSG( item.IsOk(), wxNullColour, wxT("invalid tree item") ); + + wxGenericTreeItem *pItem = (wxGenericTreeItem*) item.m_pItem; + return pItem->Attr().GetTextColour(); +} + +wxColour wxGenericTreeCtrl::GetItemBackgroundColour(const wxTreeItemId& item) const +{ + wxCHECK_MSG( item.IsOk(), wxNullColour, wxT("invalid tree item") ); + + wxGenericTreeItem *pItem = (wxGenericTreeItem*) item.m_pItem; + return pItem->Attr().GetBackgroundColour(); +} + +wxFont wxGenericTreeCtrl::GetItemFont(const wxTreeItemId& item) const +{ + wxCHECK_MSG( item.IsOk(), wxNullFont, wxT("invalid tree item") ); + + wxGenericTreeItem *pItem = (wxGenericTreeItem*) item.m_pItem; + return pItem->Attr().GetFont(); +} + void wxGenericTreeCtrl::SetItemText(const wxTreeItemId& item, const wxString& text) { wxCHECK_RET( item.IsOk(), wxT("invalid tree item") ); @@ -989,11 +1043,13 @@ bool wxGenericTreeCtrl::SetFont( const wxFont &font ) wxScrolledWindow::SetFont(font); m_normalFont = font ; - m_boldFont = wxFont( m_normalFont.GetPointSize(), - m_normalFont.GetFamily(), - m_normalFont.GetStyle(), - wxBOLD, - m_normalFont.GetUnderlined()); + m_boldFont = wxFont(m_normalFont.GetPointSize(), + m_normalFont.GetFamily(), + m_normalFont.GetStyle(), + wxBOLD, + m_normalFont.GetUnderlined(), + m_normalFont.GetFaceName(), + m_normalFont.GetEncoding()); return TRUE; } @@ -1072,7 +1128,7 @@ bool wxGenericTreeCtrl::IsBold(const wxTreeItemId& item) const // navigation // ----------------------------------------------------------------------------- -wxTreeItemId wxGenericTreeCtrl::GetParent(const wxTreeItemId& item) const +wxTreeItemId wxGenericTreeCtrl::GetItemParent(const wxTreeItemId& item) const { wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); @@ -1172,7 +1228,7 @@ wxTreeItemId wxGenericTreeCtrl::GetNext(const wxTreeItemId& item) const do { toFind = GetNextSibling(p); - p = GetParent(p); + p = GetItemParent(p); } while (p.IsOk() && !toFind.IsOk()); return toFind; } @@ -1219,6 +1275,12 @@ wxTreeItemId wxGenericTreeCtrl::GetPrevVisible(const wxTreeItemId& item) const return wxTreeItemId(); } +// called by wxTextTreeCtrl when it marks itself for deletion +void wxGenericTreeCtrl::ResetTextControl() +{ + m_textCtrl = NULL; +} + // find the first item starting with the given prefix after the given item wxTreeItemId wxGenericTreeCtrl::FindItem(const wxTreeItemId& idParent, const wxString& prefixOrig) const @@ -1416,33 +1478,31 @@ void wxGenericTreeCtrl::Delete(const wxTreeItemId& itemId) wxGenericTreeItem *item = (wxGenericTreeItem*) itemId.m_pItem; - // don't stay with invalid m_key_current or we will crash in - // the next call to OnChar() - bool changeKeyCurrent = FALSE; - wxGenericTreeItem *itemKey = m_key_current; - while ( itemKey ) + wxGenericTreeItem *parent = item->GetParent(); + + // don't keep stale pointers around! + if ( IsDescendantOf(item, m_key_current) ) { - if ( itemKey == item ) - { - // m_key_current is a descendant of the item being deleted - changeKeyCurrent = TRUE; - break; - } - itemKey = itemKey->GetParent(); + m_key_current = parent; } - wxGenericTreeItem *parent = item->GetParent(); + if ( IsDescendantOf(item, m_current) ) + { + m_current = parent; + } + + // remove the item from the tree if ( parent ) { parent->GetChildren().Remove( item ); // remove by value } - - if ( changeKeyCurrent ) + else // deleting the root { - // may be NULL or not - m_key_current = parent; + // nothing will be left in the tree + m_anchor = NULL; } + // and delete all of its children and the item itself now item->DeleteChildren(this); SendDeleteEvent(item); delete item; @@ -1452,12 +1512,7 @@ void wxGenericTreeCtrl::DeleteAllItems() { if ( m_anchor ) { - m_dirty = TRUE; - - m_anchor->DeleteChildren(this); - delete m_anchor; - - m_anchor = NULL; + Delete(m_anchor); } } @@ -1496,17 +1551,20 @@ void wxGenericTreeCtrl::Expand(const wxTreeItemId& itemId) void wxGenericTreeCtrl::ExpandAll(const wxTreeItemId& item) { - Expand(item); - if ( IsExpanded(item) ) + if ( !HasFlag(wxTR_HIDE_ROOT) || item != GetRootItem()) { - long cookie; - wxTreeItemId child = GetFirstChild(item, cookie); - while ( child.IsOk() ) - { - ExpandAll(child); + Expand(item); + if ( !IsExpanded(item) ) + return; + } - child = GetNextChild(item, cookie); - } + long cookie; + wxTreeItemId child = GetFirstChild(item, cookie); + while ( child.IsOk() ) + { + ExpandAll(child); + + child = GetNextChild(item, cookie); } } @@ -1570,6 +1628,8 @@ void wxGenericTreeCtrl::Unselect() { m_current->SetHilight( FALSE ); RefreshLine( m_current ); + + m_current = NULL; } } @@ -1713,13 +1773,13 @@ void wxGenericTreeCtrl::SelectItem(const wxTreeItemId& itemId, if ( GetEventHandler()->ProcessEvent( event ) && !event.IsAllowed() ) return; - wxTreeItemId parent = GetParent( itemId ); + wxTreeItemId parent = GetItemParent( itemId ); while (parent.IsOk()) { if (!IsExpanded(parent)) Expand( parent ); - parent = GetParent( parent ); + parent = GetItemParent( parent ); } EnsureVisible( itemId ); @@ -2469,7 +2529,7 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event ) // home : go to root // end : go to last item without opening parents // alnum : start or continue searching for the item with this prefix - int keyCode = event.KeyCode(); + int keyCode = event.GetKeyCode(); switch ( keyCode ) { case '+': @@ -2500,12 +2560,20 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event ) 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 ); } + + // in any case, also generate the normal key event for this key, + // even if we generated the ACTIVATED event above: this is what + // wxMSW does and it makes sense because you might not want to + // process ACTIVATED event at all and handle Space and Return + // directly (and differently) which would be impossible otherwise + event.Skip(); break; // up goes to the previous sibling or to the last @@ -2515,7 +2583,7 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event ) wxTreeItemId prev = GetPrevSibling( m_key_current ); if (!prev) { - prev = GetParent( m_key_current ); + prev = GetItemParent( m_key_current ); if ((prev == GetRootItem()) && HasFlag(wxTR_HIDE_ROOT)) { break; // don't go to root if it is hidden @@ -2554,7 +2622,7 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event ) // left arrow goes to the parent case WXK_LEFT: { - wxTreeItemId prev = GetParent( m_current ); + wxTreeItemId prev = GetItemParent( m_current ); if ((prev == GetRootItem()) && HasFlag(wxTR_HIDE_ROOT)) { // don't go to root if it is hidden @@ -2590,7 +2658,7 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event ) wxTreeItemId current = m_key_current; while (current && !next) { - current = GetParent( current ); + current = GetItemParent( current ); if (current) next = GetNextSibling( current ); } } @@ -2649,14 +2717,14 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event ) default: // do not use wxIsalnum() here - if ( !event.HasModifiers() && + 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() ) { @@ -2757,9 +2825,17 @@ void wxGenericTreeCtrl::Edit( const wxTreeItemId& item ) if ( m_dirty ) wxYieldIfNeeded(); - wxTreeTextCtrl *text = new wxTreeTextCtrl(this, itemEdit); + m_textCtrl = new wxTreeTextCtrl(this, itemEdit); - text->SetFocus(); + m_textCtrl->SetFocus(); +} + +// returns a pointer to the text edit control if the item is being +// edited, NULL otherwise (it's assumed that no more than one item may +// be edited simultaneously) +wxTextCtrl* wxGenericTreeCtrl::GetEditControl() const +{ + return m_textCtrl; } bool wxGenericTreeCtrl::OnRenameAccept(wxGenericTreeItem *item, @@ -2769,10 +2845,26 @@ bool wxGenericTreeCtrl::OnRenameAccept(wxGenericTreeItem *item, le.m_item = (long) item; le.SetEventObject( this ); le.m_label = value; + le.m_editCancelled = FALSE; return !GetEventHandler()->ProcessEvent( le ) || le.IsAllowed(); } +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 ); + le.m_label = wxEmptyString; + le.m_editCancelled = FALSE; + + GetEventHandler()->ProcessEvent( le ); +} + + + + void wxGenericTreeCtrl::OnRenameTimer() { Edit( m_current );