From d2ed74b912261bd91b33affbd63acfbca4c2b371 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 7 Oct 2003 08:41:54 +0000 Subject: [PATCH] send END_EDIT label if label editing is cancelled git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@24111 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/changes.txt | 2 + docs/latex/wx/listevt.tex | 28 ++++++- include/wx/listbase.h | 9 +++ src/generic/listctrl.cpp | 19 +---- src/msw/listctrl.cpp | 152 ++++++++++++++++++++------------------ 5 files changed, 117 insertions(+), 93 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index e491203b3e..7438743471 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -79,6 +79,7 @@ All (GUI): - added wxListCtrl::GetViewRect() - added wxTextCtrl::MarkDirty() - wxToolBar::ToggleTool() now works for radio buttons (Dag Ă…gren) +- wxListCtrl now sends an END_LABEL event if editing was cancelled, too - bug in wxRect ctor from two [out of order] wxPoints fixed (Steve Cornett) wxMSW: @@ -90,6 +91,7 @@ wxMSW: - several fixes to owner drawn menu items (Christian Sturmlechner) - wxGauge now supports full 32 bit range (Miroslav Rajcic) - make it possible to give focus to the notebook tabs (Hajo Kirchhoff) +- MDI child frames are not always resizeable any more (Andrei Fortuna) wxGTK: diff --git a/docs/latex/wx/listevt.tex b/docs/latex/wx/listevt.tex index 76c42a3cb1..ce4beebb84 100644 --- a/docs/latex/wx/listevt.tex +++ b/docs/latex/wx/listevt.tex @@ -26,8 +26,6 @@ functions that take a wxListEvent argument. \twocolitem{{\bf EVT\_LIST\_END\_LABEL\_EDIT(id, func)}}{Finish editing a label. This can be prevented by calling \helpref{Veto()}{wxnotifyeventveto}.} \twocolitem{{\bf EVT\_LIST\_DELETE\_ITEM(id, func)}}{Delete an item.} \twocolitem{{\bf EVT\_LIST\_DELETE\_ALL\_ITEMS(id, func)}}{Delete all items.} -%\twocolitem{{\bf EVT\_LIST\_GET\_INFO(id, func)}}{Request information from the application, usually the item text.} -%\twocolitem{{\bf EVT\_LIST\_SET\_INFO(id, func)}}{Information is being supplied (not implemented).} \twocolitem{{\bf EVT\_LIST\_ITEM\_SELECTED(id, func)}}{The item has been selected.} \twocolitem{{\bf EVT\_LIST\_ITEM\_DESELECTED(id, func)}}{The item has been deselected.} \twocolitem{{\bf EVT\_LIST\_ITEM\_ACTIVATED(id, func)}}{The item has been activated (ENTER or double click).} @@ -50,12 +48,14 @@ functions that take a wxListEvent argument. \latexignore{\rtfignore{\wxheading{Members}}} + \membersection{wxListEvent::wxListEvent} \func{}{wxListEvent}{\param{WXTYPE }{commandType = 0}, \param{int }{id = 0}} Constructor. + \membersection{wxListEvent::GetCacheFrom}\label{wxlisteventgetcachefrom} \constfunc{long}{GetCacheFrom}{\void} @@ -63,6 +63,7 @@ Constructor. For {\tt EVT\_LIST\_CACHE\_HINT} event only: return the first item which the list control advises us to cache. + \membersection{wxListEvent::GetCacheTo}\label{wxlisteventgetcacheto} \constfunc{long}{GetCacheTo}{\void} @@ -70,18 +71,21 @@ list control advises us to cache. For {\tt EVT\_LIST\_CACHE\_HINT} event only: return the last item (inclusive) which the list control advises us to cache. + \membersection{wxListEvent::GetKeyCode}\label{wxlisteventgetkeycode} \constfunc{int}{GetKeyCode}{\void} Key code if the event is a keypress event. + \membersection{wxListEvent::GetIndex}\label{wxlisteventgetindex} \constfunc{long}{GetIndex}{\void} The item index. + \membersection{wxListEvent::GetColumn}\label{wxlisteventgetcolumn} \constfunc{int}{GetColumn}{\void} @@ -91,6 +95,7 @@ dragging events, it is the column to the left of the divider being dragged, for the column click events it may be $-1$ if the user clicked in the list control header outside any column. + \membersection{wxListEvent::GetPoint}\label{wxlisteventgetpoint} \constfunc{wxPoint}{GetPoint}{\void} @@ -98,11 +103,13 @@ header outside any column. The position of the mouse pointer if the event is a drag event. + \membersection{wxListEvent::GetLabel}\label{wxlisteventgetlabel} \constfunc{const wxString\&}{GetLabel}{\void} -The label. +The (new) item label for \texttt{EVT\_LIST\_END\_LABEL\_EDIT} event. + \membersection{wxListEvent::GetText}\label{wxlisteventgettext} @@ -110,24 +117,28 @@ The label. The text. + \membersection{wxListEvent::GetImage}\label{wxlisteventgetimage} \constfunc{int}{GetImage}{\void} The image. + \membersection{wxListEvent::GetData}\label{wxlisteventgetdata} \constfunc{long}{GetData}{\void} The data. + \membersection{wxListEvent::GetMask}\label{wxlisteventgetmask} \constfunc{long}{GetMask}{\void} The mask. + \membersection{wxListEvent::GetItem}\label{wxlisteventgetitem} \constfunc{const wxListItem\&}{GetItem}{\void} @@ -135,3 +146,14 @@ The mask. An item object, used by some events. See also \helpref{wxListCtrl::SetItem}{wxlistctrlsetitem}. +\membersection{wxListEvent::IsEditCancelled}\label{wxlisteventiseditcancelled} + +\constfunc{bool}{IsEditCancelled}{\void} + +This method only makes sense for \texttt{EVT\_LIST\_END\_LABEL\_EDIT} message +and returns \true if it the label editing has been cancelled by the user +(\helpref{GetLabel}{wxlisteventgetlabel} returns an empty string in this case +but it doesn't allow to distinguish between really cancelling the edit and, +admittedly rare, case when the user wants to rename it to an empty string0. + + diff --git a/include/wx/listbase.h b/include/wx/listbase.h index 294c8bb27c..dae2b38f23 100644 --- a/include/wx/listbase.h +++ b/include/wx/listbase.h @@ -350,6 +350,7 @@ public: , m_col(0) , m_pointDrag() , m_item() + , m_editCancelled(false) { } wxListEvent(const wxListEvent& event) @@ -360,6 +361,7 @@ public: , m_col(event.m_col) , m_pointDrag(event.m_pointDrag) , m_item(event.m_item) + , m_editCancelled(event.m_editCancelled) { } int GetKeyCode() const { return m_code; } @@ -377,6 +379,10 @@ public: long GetCacheFrom() const { return m_oldItemIndex; } long GetCacheTo() const { return m_itemIndex; } + // was label editing canceled? (for wxEVT_COMMAND_LIST_END_LABEL_EDIT only) + bool IsEditCancelled() const { return m_editCancelled; } + void SetEditCanceled(bool editCancelled) { m_editCancelled = editCancelled; } + #if WXWIN_COMPATIBILITY_2_2 // these methods don't do anything at all long GetOldIndex() const { return 0; } @@ -397,6 +403,9 @@ public: wxListItem m_item; +protected: + bool m_editCancelled; + private: DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxListEvent) }; diff --git a/src/generic/listctrl.cpp b/src/generic/listctrl.cpp index fc72c9ee07..ef36a4b837 100644 --- a/src/generic/listctrl.cpp +++ b/src/generic/listctrl.cpp @@ -2834,25 +2834,12 @@ bool wxListMainWindow::OnRenameAccept(size_t itemEdit, const wxString& value) le.IsAllowed(); } -#ifdef __VMS__ // Ignore unreacheable code -# pragma message disable initnotreach -#endif - void wxListMainWindow::OnRenameCancelled(size_t WXUNUSED(itemEdit)) { - // wxMSW seems not to notify the program about - // cancelled label edits. - return; - - #if 0 - // above unconditional return cause warning about not reachable code - // let owner know that the edit was cancelled wxListEvent le( wxEVT_COMMAND_LIST_END_LABEL_EDIT, GetParent()->GetId() ); - // These only exist for wxTreeCtrl, which should probably be changed - // le.m_editCancelled = TRUE; - // le.m_label = wxEmptyString; + le.SetEditCanceled(TRUE); le.SetEventObject( GetParent() ); le.m_itemIndex = itemEdit; @@ -2863,11 +2850,7 @@ void wxListMainWindow::OnRenameCancelled(size_t WXUNUSED(itemEdit)) data->GetItem( 0, le.m_item ); GetEventHandler()->ProcessEvent( le ); - #endif } -#ifdef __VMS__ -# pragma message enable initnotreach -#endif void wxListMainWindow::OnMouse( wxMouseEvent &event ) { diff --git a/src/msw/listctrl.cpp b/src/msw/listctrl.cpp index 6060cff9e3..fc54c0de72 100644 --- a/src/msw/listctrl.cpp +++ b/src/msw/listctrl.cpp @@ -73,60 +73,77 @@ static void wxConvertToMSWListCol(int col, const wxListItem& item, // ---------------------------------------------------------------------------- // We have to handle both fooW and fooA notifications in several cases -// because of broken commctl.dll and/or unicows.dll. This class is used to +// because of broken comctl32.dll and/or unicows.dll. This class is used to // convert LV_ITEMA and LV_ITEMW to LV_ITEM (which is either LV_ITEMA or // LV_ITEMW depending on wxUSE_UNICODE setting), so that it can be processed // by wxConvertToMSWListItem(). +#if wxUSE_UNICODE + #define LV_ITEM_NATIVE LV_ITEMW + #define LV_ITEM_OTHER LV_ITEMA + + #define LV_CONV_TO_WX cMB2WX + #define LV_CONV_BUF wxMB2WXbuf +#else // ANSI + #define LV_ITEM_NATIVE LV_ITEMA + #define LV_ITEM_OTHER LV_ITEMW + + #define LV_CONV_TO_WX cWC2WX + #define LV_CONV_BUF wxWC2WXbuf +#endif // Unicode/ANSI + class wxLV_ITEM { public: - ~wxLV_ITEM() { delete m_buf; } - operator LV_ITEM&() const { return *m_item; } + // default ctor, use Init() later + wxLV_ITEM() { m_buf = NULL; m_pItem = NULL; } -#if wxUSE_UNICODE - wxLV_ITEM(LV_ITEMW &item) : m_buf(NULL), m_item(&item) {} - wxLV_ITEM(LV_ITEMA &item) + // init without conversion + void Init(LV_ITEM_NATIVE& item) { - m_item = new LV_ITEM((LV_ITEM&)item); - if ( (item.mask & LVIF_TEXT) && item.pszText ) - { - m_buf = new wxMB2WXbuf(wxConvLocal.cMB2WX(item.pszText)); - m_item->pszText = (wxChar*)m_buf->data(); - } - else - m_buf = NULL; + wxASSERT_MSG( !m_pItem, _T("Init() called twice?") ); + + m_pItem = &item; } -private: - wxMB2WXbuf *m_buf; -#else // !wxUSE_UNICODE - wxLV_ITEM(LV_ITEMW &item) + // init with conversion + void Init(LV_ITEM_OTHER& item) { - m_item = new LV_ITEM((LV_ITEM&)item); + // avoid unnecessary dynamic memory allocation, jjust make m_pItem + // point to our own m_item - // the code below doesn't compile without wxUSE_WCHAR_T and as I don't - // know if it's useful to have it at all (do we ever get Unicode - // notifications in ANSI mode? I don't think so...) I'm not going to - // write alternative implementation right now - // - // but if it is indeed used, we should simply directly use - // ::WideCharToMultiByte() here -#if wxUSE_WCHAR_T + // memcpy() can't work if the struct sizes are different + wxCOMPILE_TIME_ASSERT( sizeof(LV_ITEM_OTHER) == sizeof(LV_ITEM_NATIVE), + CodeCantWorkIfDiffSizes); + + memcpy(&m_item, &item, sizeof(LV_ITEM_NATIVE)); + + // convert text from ANSI to Unicod if necessary if ( (item.mask & LVIF_TEXT) && item.pszText ) { - m_buf = new wxWC2WXbuf(wxConvLocal.cWC2WX(item.pszText)); - m_item->pszText = (wxChar*)m_buf->data(); + m_buf = new LV_CONV_BUF(wxConvLocal.LV_CONV_TO_WX(item.pszText)); + m_item.pszText = (wxChar *)m_buf->data(); } - else -#endif // wxUSE_WCHAR_T - m_buf = NULL; } - wxLV_ITEM(LV_ITEMA &item) : m_buf(NULL), m_item(&item) {} + + // ctor without conversion + wxLV_ITEM(LV_ITEM_NATIVE& item) : m_buf(NULL), m_pItem(&item) { } + + // ctor with conversion + wxLV_ITEM(LV_ITEM_OTHER& item) : m_buf(NULL) + { + Init(item); + } + + ~wxLV_ITEM() { delete m_buf; } + + // conversion to the real LV_ITEM + operator LV_ITEM_NATIVE&() const { return *m_pItem; } + private: - wxWC2WXbuf *m_buf; -#endif // wxUSE_UNICODE/!wxUSE_UNICODE + LV_CONV_BUF *m_buf; - LV_ITEM *m_item; + LV_ITEM_NATIVE *m_pItem; + LV_ITEM_NATIVE m_item; DECLARE_NO_COPY_CLASS(wxLV_ITEM) }; @@ -1896,55 +1913,43 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) break; // NB: we have to handle both *A and *W versions here because some - // versions of comctl32.dll send ANSI message to an Unicode app + // versions of comctl32.dll send ANSI messages even to the + // Unicode windows case LVN_BEGINLABELEDITA: - { - eventType = wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT; - wxLV_ITEM item(((LV_DISPINFOA *)lParam)->item); - wxConvertFromMSWListItem(GetHwnd(), event.m_item, item); - event.m_itemIndex = event.m_item.m_itemId; - } - break; case LVN_BEGINLABELEDITW: { + wxLV_ITEM item; + if ( nmhdr->code == LVN_BEGINLABELEDITA ) + { + item.Init(((LV_DISPINFOA *)lParam)->item); + } + else // LVN_BEGINLABELEDITW + { + item.Init(((LV_DISPINFOW *)lParam)->item); + } + eventType = wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT; - wxLV_ITEM item(((LV_DISPINFOW *)lParam)->item); wxConvertFromMSWListItem(GetHwnd(), event.m_item, item); event.m_itemIndex = event.m_item.m_itemId; } break; case LVN_ENDLABELEDITA: + case LVN_ENDLABELEDITW: { - eventType = wxEVT_COMMAND_LIST_END_LABEL_EDIT; - wxLV_ITEM item(((LV_DISPINFOA *)lParam)->item); - wxConvertFromMSWListItem(NULL, event.m_item, item); - if ( ((LV_ITEM)item).pszText == NULL || - ((LV_ITEM)item).iItem == -1 ) + wxLV_ITEM item; + if ( nmhdr->code == LVN_ENDLABELEDITA ) { - // don't keep a stale wxTextCtrl around - if ( m_textCtrl ) - { - // EDIT control will be deleted by the list control itself so - // prevent us from deleting it as well - m_textCtrl->UnsubclassWin(); - m_textCtrl->SetHWND(0); - delete m_textCtrl; - m_textCtrl = NULL; - } - return FALSE; + item.Init(((LV_DISPINFOA *)lParam)->item); + } + else // LVN_ENDLABELEDITW + { + item.Init(((LV_DISPINFOW *)lParam)->item); } - event.m_itemIndex = event.m_item.m_itemId; - } - break; - case LVN_ENDLABELEDITW: - { - eventType = wxEVT_COMMAND_LIST_END_LABEL_EDIT; - wxLV_ITEM item(((LV_DISPINFOW *)lParam)->item); - wxConvertFromMSWListItem(NULL, event.m_item, item); - if ( ((LV_ITEM)item).pszText == NULL || - ((LV_ITEM)item).iItem == -1 ) + // was editing cancelled? + const LV_ITEM& lvi = (LV_ITEM)item; + if ( !lvi.pszText || lvi.iItem == -1 ) { // don't keep a stale wxTextCtrl around if ( m_textCtrl ) @@ -1956,9 +1961,12 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) delete m_textCtrl; m_textCtrl = NULL; } - return FALSE; + + event.SetEditCanceled(true); } + eventType = wxEVT_COMMAND_LIST_END_LABEL_EDIT; + wxConvertFromMSWListItem(NULL, event.m_item, item); event.m_itemIndex = event.m_item.m_itemId; } break; -- 2.45.2