fix crash when the user code refuses to validate the new text when editing the item and a generic label editing code cleanup

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@16083 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2002-07-08 16:38:46 +00:00
parent 9602d7ae69
commit edb8f2985f
2 changed files with 129 additions and 139 deletions

View File

@@ -353,8 +353,7 @@ protected:
wxGenericTreeItem *m_anchor; wxGenericTreeItem *m_anchor;
wxGenericTreeItem *m_current, wxGenericTreeItem *m_current,
*m_key_current, *m_key_current;
*m_currentEdit;
unsigned short m_indent; unsigned short m_indent;
unsigned short m_spacing; unsigned short m_spacing;
int m_lineHeight; int m_lineHeight;
@@ -367,7 +366,6 @@ protected:
m_ownsImageListState, m_ownsImageListState,
m_ownsImageListButtons; m_ownsImageListButtons;
bool m_isDragging; // true between BEGIN/END drag events bool m_isDragging; // true between BEGIN/END drag events
bool m_renameAccept;
bool m_lastOnSame; // last click on the same item as prev bool m_lastOnSame; // last click on the same item as prev
wxImageList *m_imageListNormal, wxImageList *m_imageListNormal,
*m_imageListState, *m_imageListState,
@@ -380,7 +378,6 @@ protected:
wxGenericTreeItem *m_oldSelection; wxGenericTreeItem *m_oldSelection;
wxTimer *m_renameTimer; wxTimer *m_renameTimer;
wxString m_renameRes;
wxBitmap *m_arrowRight, wxBitmap *m_arrowRight,
*m_arrowDown; *m_arrowDown;
@@ -431,7 +428,7 @@ protected:
void RefreshSelectedUnder(wxGenericTreeItem *item); void RefreshSelectedUnder(wxGenericTreeItem *item);
void OnRenameTimer(); void OnRenameTimer();
void OnRenameAccept(); bool OnRenameAccept(wxGenericTreeItem *item, const wxString& value);
void FillArray(wxGenericTreeItem*, wxArrayTreeItemIds&) const; void FillArray(wxGenericTreeItem*, wxArrayTreeItemIds&) const;
void SelectItemRange( wxGenericTreeItem *item1, wxGenericTreeItem *item2 ); void SelectItemRange( wxGenericTreeItem *item1, wxGenericTreeItem *item2 );

View File

@@ -126,26 +126,19 @@ private:
class WXDLLEXPORT wxTreeTextCtrl: public wxTextCtrl class WXDLLEXPORT wxTreeTextCtrl: public wxTextCtrl
{ {
public: public:
wxTreeTextCtrl( wxWindow *parent, wxTreeTextCtrl(wxGenericTreeCtrl *owner, wxGenericTreeItem *item);
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 );
protected:
void OnChar( wxKeyEvent &event ); void OnChar( wxKeyEvent &event );
void OnKeyUp( wxKeyEvent &event ); void OnKeyUp( wxKeyEvent &event );
void OnKillFocus( wxFocusEvent &event ); void OnKillFocus( wxFocusEvent &event );
bool AcceptChanges();
void Finish();
private: private:
bool *m_accept;
wxString *m_res;
wxGenericTreeCtrl *m_owner; wxGenericTreeCtrl *m_owner;
wxGenericTreeItem *m_itemEdited;
wxString m_startValue; wxString m_startValue;
bool m_finished; bool m_finished;
@@ -353,99 +346,131 @@ BEGIN_EVENT_TABLE(wxTreeTextCtrl,wxTextCtrl)
EVT_KILL_FOCUS (wxTreeTextCtrl::OnKillFocus) EVT_KILL_FOCUS (wxTreeTextCtrl::OnKillFocus)
END_EVENT_TABLE() END_EVENT_TABLE()
wxTreeTextCtrl::wxTreeTextCtrl( wxWindow *parent, wxTreeTextCtrl::wxTreeTextCtrl(wxGenericTreeCtrl *owner,
const wxWindowID id, wxGenericTreeItem *item)
bool *accept, : m_itemEdited(item), m_startValue(item->GetText())
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;
m_owner = owner; m_owner = owner;
(*m_accept) = FALSE;
(*m_res) = wxEmptyString;
m_startValue = value;
m_finished = FALSE; m_finished = FALSE;
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 )
{
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!"));
}
}
// FIXME: what are all these hardcoded 4, 8 and 11s really?
x += image_w;
w -= image_w + 4;
(void)Create(m_owner, wxID_ANY, m_startValue,
wxPoint(x - 4, y - 4), wxSize(w + 11, h + 8));
}
bool wxTreeTextCtrl::AcceptChanges()
{
const wxString value = GetValue();
if ( value == m_startValue )
{
// nothing changed, always accept
return TRUE;
}
if ( !m_owner->OnRenameAccept(m_itemEdited, value) )
{
// vetoed by the user
return FALSE;
}
// accepted, do rename the item
m_owner->SetItemText(m_itemEdited, value);
return TRUE;
}
void wxTreeTextCtrl::Finish()
{
if ( !m_finished )
{
wxPendingDelete.Append(this);
m_finished = TRUE;
m_owner->SetFocus(); // This doesn't work. TODO.
}
} }
void wxTreeTextCtrl::OnChar( wxKeyEvent &event ) void wxTreeTextCtrl::OnChar( wxKeyEvent &event )
{ {
if (event.m_keyCode == WXK_RETURN) switch ( event.m_keyCode )
{ {
(*m_accept) = TRUE; case WXK_RETURN:
(*m_res) = GetValue(); if ( !AcceptChanges() )
{
// vetoed by the user, don't disappear
break;
}
//else: fall through
if ((*m_res) != m_startValue) case WXK_ESCAPE:
m_owner->OnRenameAccept(); Finish();
break;
if (!wxPendingDelete.Member(this)) default:
wxPendingDelete.Append(this); event.Skip();
m_finished = TRUE;
m_owner->SetFocus(); // This doesn't work. TODO.
return;
} }
if (event.m_keyCode == WXK_ESCAPE)
{
(*m_accept) = FALSE;
(*m_res) = "";
if (!wxPendingDelete.Member(this))
wxPendingDelete.Append(this);
m_finished = TRUE;
m_owner->SetFocus(); // This doesn't work. TODO.
return;
}
event.Skip();
} }
void wxTreeTextCtrl::OnKeyUp( wxKeyEvent &event ) void wxTreeTextCtrl::OnKeyUp( wxKeyEvent &event )
{ {
if (m_finished) if ( !m_finished )
{ {
event.Skip(); // auto-grow the textctrl:
return; 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(); event.Skip();
} }
void wxTreeTextCtrl::OnKillFocus( wxFocusEvent &event ) void wxTreeTextCtrl::OnKillFocus( wxFocusEvent &event )
{ {
if (m_finished) if ( m_finished )
{ {
event.Skip(); event.Skip();
return; return;
} }
if (!wxPendingDelete.Member(this)) if ( AcceptChanges() )
wxPendingDelete.Append(this); {
Finish();
(*m_accept) = TRUE; }
(*m_res) = GetValue();
if ((*m_res) != m_startValue)
m_owner->OnRenameAccept();
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@@ -2692,8 +2717,8 @@ wxTreeItemId wxGenericTreeCtrl::HitTest(const wxPoint& point, int& flags)
// get the bounding rectangle of the item (or of its label only) // get the bounding rectangle of the item (or of its label only)
bool wxGenericTreeCtrl::GetBoundingRect(const wxTreeItemId& item, bool wxGenericTreeCtrl::GetBoundingRect(const wxTreeItemId& item,
wxRect& rect, wxRect& rect,
bool WXUNUSED(textOnly)) const bool WXUNUSED(textOnly)) const
{ {
wxCHECK_MSG( item.IsOk(), FALSE, _T("invalid item in wxGenericTreeCtrl::GetBoundingRect") ); wxCHECK_MSG( item.IsOk(), FALSE, _T("invalid item in wxGenericTreeCtrl::GetBoundingRect") );
@@ -2711,80 +2736,48 @@ bool wxGenericTreeCtrl::GetBoundingRect(const wxTreeItemId& item,
return TRUE; return TRUE;
} }
/* **** */
void wxGenericTreeCtrl::Edit( const wxTreeItemId& item ) 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() ); wxTreeEvent te( wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT, GetId() );
te.m_item = (long) m_currentEdit; te.m_item = (long) itemEdit;
te.SetEventObject( this ); te.SetEventObject( this );
GetEventHandler()->ProcessEvent( te ); if ( GetEventHandler()->ProcessEvent( te ) && !te.IsAllowed() )
{
if (!te.IsAllowed()) return; // vetoed by user
return;
}
// We have to call this here because the label in // We have to call this here because the label in
// question might just have been added and no screen // question might just have been added and no screen
// update taken place. // update taken place.
if (m_dirty) wxYieldIfNeeded(); if ( m_dirty )
wxYieldIfNeeded();
wxString s = m_currentEdit->GetText(); wxTreeTextCtrl *text = new wxTreeTextCtrl(this, itemEdit);
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;
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(); text->SetFocus();
} }
bool wxGenericTreeCtrl::OnRenameAccept(wxGenericTreeItem *item,
const wxString& value)
{
wxTreeEvent le( wxEVT_COMMAND_TREE_END_LABEL_EDIT, GetId() );
le.m_item = (long) item;
le.SetEventObject( this );
le.m_label = value;
return !GetEventHandler()->ProcessEvent( le ) || le.IsAllowed();
}
void wxGenericTreeCtrl::OnRenameTimer() void wxGenericTreeCtrl::OnRenameTimer()
{ {
Edit( m_current ); Edit( m_current );
} }
void wxGenericTreeCtrl::OnRenameAccept()
{
// 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.SetEventObject( this );
le.m_label = m_renameRes;
GetEventHandler()->ProcessEvent( le );
if (!le.IsAllowed()) return;
SetItemText( m_currentEdit, m_renameRes );
}
void wxGenericTreeCtrl::OnMouse( wxMouseEvent &event ) void wxGenericTreeCtrl::OnMouse( wxMouseEvent &event )
{ {
if ( !m_anchor ) return; if ( !m_anchor ) return;