X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/cb59313ce503d859beafb94025a1c6822f59dbd6..217c78b80b34f31b4341d6257e28077255d6eb93:/src/generic/treectlg.cpp?ds=sidebyside diff --git a/src/generic/treectlg.cpp b/src/generic/treectlg.cpp index 11b04eb171..c7732185bc 100644 --- a/src/generic/treectlg.cpp +++ b/src/generic/treectlg.cpp @@ -112,7 +112,7 @@ class WXDLLEXPORT wxTreeRenameTimer: public wxTimer public: // start editing the current item after half a second (if the mouse hasn't // been clicked/moved) - static const int DELAY = 500; + enum { DELAY = 500 }; wxTreeRenameTimer( wxGenericTreeCtrl *owner ); @@ -126,26 +126,19 @@ private: class WXDLLEXPORT wxTreeTextCtrl: public wxTextCtrl { public: - wxTreeTextCtrl( wxWindow *parent, - const wxWindowID id, - bool *accept, - wxString *res, - wxGenericTreeCtrl *owner, - const wxString &value = wxEmptyString, - const wxPoint &pos = wxDefaultPosition, - const wxSize &size = wxDefaultSize, - int style = wxSIMPLE_BORDER, - const wxValidator& validator = wxDefaultValidator, - const wxString &name = wxTextCtrlNameStr ); + wxTreeTextCtrl(wxGenericTreeCtrl *owner, wxGenericTreeItem *item); +protected: void OnChar( wxKeyEvent &event ); void OnKeyUp( wxKeyEvent &event ); void OnKillFocus( wxFocusEvent &event ); + bool AcceptChanges(); + void Finish(); + private: - bool *m_accept; - wxString *m_res; wxGenericTreeCtrl *m_owner; + wxGenericTreeItem *m_itemEdited; wxString m_startValue; bool m_finished; @@ -158,7 +151,7 @@ class WXDLLEXPORT wxTreeFindTimer : public wxTimer { public: // reset the current prefix after half a second of inactivity - static const int DELAY = 500; + enum { DELAY = 500 }; wxTreeFindTimer( wxGenericTreeCtrl *owner ) { m_owner = owner; } @@ -353,99 +346,131 @@ BEGIN_EVENT_TABLE(wxTreeTextCtrl,wxTextCtrl) EVT_KILL_FOCUS (wxTreeTextCtrl::OnKillFocus) END_EVENT_TABLE() -wxTreeTextCtrl::wxTreeTextCtrl( wxWindow *parent, - const wxWindowID id, - bool *accept, - wxString *res, - wxGenericTreeCtrl *owner, - const wxString &value, - const wxPoint &pos, - const wxSize &size, - int style, - const wxValidator& validator, - const wxString &name ) - : wxTextCtrl( parent, id, value, pos, size, style, validator, name ) -{ - m_res = res; - m_accept = accept; +wxTreeTextCtrl::wxTreeTextCtrl(wxGenericTreeCtrl *owner, + wxGenericTreeItem *item) + : m_itemEdited(item), m_startValue(item->GetText()) +{ m_owner = owner; - (*m_accept) = FALSE; - (*m_res) = wxEmptyString; - m_startValue = value; m_finished = FALSE; -} -void wxTreeTextCtrl::OnChar( wxKeyEvent &event ) -{ - if (event.m_keyCode == WXK_RETURN) + int w = m_itemEdited->GetWidth(), + h = m_itemEdited->GetHeight(); + + int x, y; + m_owner->CalcScrolledPosition(item->GetX(), item->GetY(), &x, &y); + + int image_h = 0, + image_w = 0; + + int image = item->GetCurrentImage(); + if ( image != NO_IMAGE ) { - (*m_accept) = TRUE; - (*m_res) = GetValue(); + if ( m_owner->m_imageListNormal ) + { + m_owner->m_imageListNormal->GetSize( image, image_w, image_h ); + image_w += 4; + } + else + { + wxFAIL_MSG(_T("you must create an image list to use images!")); + } + } - if ((*m_res) != m_startValue) - m_owner->OnRenameAccept(); + // FIXME: what are all these hardcoded 4, 8 and 11s really? + x += image_w; + w -= image_w + 4; - if (!wxPendingDelete.Member(this)) - wxPendingDelete.Append(this); + (void)Create(m_owner, wxID_ANY, m_startValue, + wxPoint(x - 4, y - 4), wxSize(w + 11, h + 8)); +} - m_finished = TRUE; - m_owner->SetFocus(); // This doesn't work. TODO. +bool wxTreeTextCtrl::AcceptChanges() +{ + const wxString value = GetValue(); - return; + if ( value == m_startValue ) + { + // nothing changed, always accept + return TRUE; } - if (event.m_keyCode == WXK_ESCAPE) + + if ( !m_owner->OnRenameAccept(m_itemEdited, value) ) { - (*m_accept) = FALSE; - (*m_res) = ""; + // vetoed by the user + return FALSE; + } + + // accepted, do rename the item + m_owner->SetItemText(m_itemEdited, value); - if (!wxPendingDelete.Member(this)) - wxPendingDelete.Append(this); + return TRUE; +} + +void wxTreeTextCtrl::Finish() +{ + if ( !m_finished ) + { + wxPendingDelete.Append(this); m_finished = TRUE; + m_owner->SetFocus(); // This doesn't work. TODO. + } +} - return; +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 + + case WXK_ESCAPE: + Finish(); + break; + + default: + event.Skip(); } - event.Skip(); } void wxTreeTextCtrl::OnKeyUp( wxKeyEvent &event ) { - if (m_finished) + if ( !m_finished ) { - event.Skip(); - return; + // auto-grow the textctrl: + wxSize parentSize = m_owner->GetSize(); + wxPoint myPos = GetPosition(); + wxSize mySize = GetSize(); + int sx, sy; + GetTextExtent(GetValue() + _T("M"), &sx, &sy); + if (myPos.x + sx > parentSize.x) + sx = parentSize.x - myPos.x; + if (mySize.x > sx) + sx = mySize.x; + SetSize(sx, -1); } - // auto-grow the textctrl: - wxSize parentSize = m_owner->GetSize(); - wxPoint myPos = GetPosition(); - wxSize mySize = GetSize(); - int sx, sy; - GetTextExtent(GetValue() + _T("M"), &sx, &sy); - if (myPos.x + sx > parentSize.x) sx = parentSize.x - myPos.x; - if (mySize.x > sx) sx = mySize.x; - SetSize(sx, -1); - event.Skip(); } void wxTreeTextCtrl::OnKillFocus( wxFocusEvent &event ) { - if (m_finished) + if ( m_finished ) { event.Skip(); return; } - if (!wxPendingDelete.Member(this)) - wxPendingDelete.Append(this); - - (*m_accept) = TRUE; - (*m_res) = GetValue(); - - if ((*m_res) != m_startValue) - m_owner->OnRenameAccept(); + if ( AcceptChanges() ) + { + Finish(); + } } // ----------------------------------------------------------------------------- @@ -835,9 +860,17 @@ size_t wxGenericTreeCtrl::GetChildrenCount(const wxTreeItemId& item, bool recurs void wxGenericTreeCtrl::SetWindowStyle(const long styles) { - // right now, just sets the styles. Eventually, we may - // want to update the inherited styles, but right now - // none of the parents has updatable styles + if (!HasFlag(wxTR_HIDE_ROOT) && (styles & wxTR_HIDE_ROOT)) + { + // if we will hide the root, make sure children are visible + m_anchor->SetHasPlus(); + m_anchor->Expand(); + CalculatePositions(); + } + + // right now, just sets the styles. Eventually, we may + // want to update the inherited styles, but right now + // none of the parents has updatable styles m_windowStyle = styles; m_dirty = TRUE; } @@ -1195,13 +1228,40 @@ wxTreeItemId wxGenericTreeCtrl::FindItem(const wxTreeItemId& idParent, // 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; } @@ -1406,7 +1466,7 @@ 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(), + wxCHECK_RET( !HasFlag(wxTR_HIDE_ROOT) || itemId != GetRootItem(), _T("can't expand hidden root") ); if ( !item->HasPlus() ) @@ -1452,7 +1512,7 @@ void wxGenericTreeCtrl::ExpandAll(const wxTreeItemId& item) void wxGenericTreeCtrl::Collapse(const wxTreeItemId& itemId) { - wxCHECK_RET( !HasFlag(wxTR_HIDE_ROOT) || itemId != GetRootItem(), + wxCHECK_RET( !HasFlag(wxTR_HIDE_ROOT) || itemId != GetRootItem(), _T("can't collapse hidden root") ); wxGenericTreeItem *item = (wxGenericTreeItem*) itemId.m_pItem; @@ -1510,6 +1570,8 @@ void wxGenericTreeCtrl::Unselect() { m_current->SetHilight( FALSE ); RefreshLine( m_current ); + + m_current = NULL; } } @@ -2589,12 +2651,15 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event ) default: // do not use wxIsalnum() here - if ( !event.HasModifiers() && isalnum(keyCode) ) + 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 + ch); + + wxTreeItemId id = FindItem(m_current, m_findPrefix + (wxChar)ch); if ( !id.IsOk() ) { // no such item @@ -2654,8 +2719,8 @@ 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 + wxRect& rect, + bool WXUNUSED(textOnly)) const { wxCHECK_MSG( item.IsOk(), FALSE, _T("invalid item in wxGenericTreeCtrl::GetBoundingRect") ); @@ -2673,78 +2738,46 @@ bool wxGenericTreeCtrl::GetBoundingRect(const wxTreeItemId& item, return TRUE; } -/* **** */ - void wxGenericTreeCtrl::Edit( const wxTreeItemId& item ) { - if (!item.IsOk()) return; + wxCHECK_RET( item.IsOk(), _T("can't edit an invalid item") ); - m_currentEdit = (wxGenericTreeItem*) item.m_pItem; + wxGenericTreeItem *itemEdit = (wxGenericTreeItem *)item.m_pItem; wxTreeEvent te( wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT, GetId() ); - te.m_item = (long) m_currentEdit; + te.m_item = (long) itemEdit; te.SetEventObject( this ); - GetEventHandler()->ProcessEvent( te ); - - if (!te.IsAllowed()) return; + if ( GetEventHandler()->ProcessEvent( te ) && !te.IsAllowed() ) + { + // vetoed by user + return; + } // 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 ) + wxYieldIfNeeded(); - wxString s = m_currentEdit->GetText(); - int w = m_currentEdit->GetWidth(); - int h = m_currentEdit->GetHeight(); - int x, y; - CalcScrolledPosition(m_currentEdit->GetX(), m_currentEdit->GetY(), &x, &y); + wxTreeTextCtrl *text = new wxTreeTextCtrl(this, itemEdit); - int image_h = 0; - int image_w = 0; - - int image = m_currentEdit->GetCurrentImage(); - if ( image != NO_IMAGE ) - { - if ( m_imageListNormal ) - { - m_imageListNormal->GetSize( image, image_w, image_h ); - image_w += 4; - } - else - { - wxFAIL_MSG(_T("you must create an image list to use images!")); - } - } - x += image_w; - w -= image_w + 4; // I don't know why +4 is needed - - wxTreeTextCtrl *text = new wxTreeTextCtrl(this, -1, - &m_renameAccept, - &m_renameRes, - this, - s, - wxPoint(x-4,y-4), - wxSize(w+11,h+8)); text->SetFocus(); } -void wxGenericTreeCtrl::OnRenameTimer() -{ - Edit( m_current ); -} - -void wxGenericTreeCtrl::OnRenameAccept() +bool wxGenericTreeCtrl::OnRenameAccept(wxGenericTreeItem *item, + const wxString& value) { - // TODO if the validator fails this causes a crash wxTreeEvent le( wxEVT_COMMAND_TREE_END_LABEL_EDIT, GetId() ); - le.m_item = (long) m_currentEdit; + le.m_item = (long) item; le.SetEventObject( this ); - le.m_label = m_renameRes; - GetEventHandler()->ProcessEvent( le ); + le.m_label = value; - if (!le.IsAllowed()) return; + return !GetEventHandler()->ProcessEvent( le ) || le.IsAllowed(); +} - SetItemText( m_currentEdit, m_renameRes ); +void wxGenericTreeCtrl::OnRenameTimer() +{ + Edit( m_current ); } void wxGenericTreeCtrl::OnMouse( wxMouseEvent &event )