From: Václav Slavík Date: Wed, 19 Oct 2011 16:20:17 +0000 (+0000) Subject: Cleanup of wxDataViewCtrl cell activation code. X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/dc73d7f5d468881a9cbb71f1a234f364ff52ceaa Cleanup of wxDataViewCtrl cell activation code. Fix confusion of what cell activation is and inconsistence with native handling in GTK+. Document the distinction between activating (~ editing) a cell and activating (double-clicking) the whole item. Deprecate wxDataViewCustomRenderer::LeftClick() and Activate() methods, replace them with single ActivateCell() that is called for both kinds of activation. Fix implementations so that ActivateCell() is not called on double-click, when it shouldn't, and vice versa: don't send wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED for cell activation. Partially reverts r67099 -- restores old 2.9 signatures of compatibility LeftClick() and Activate() methods. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@69473 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/docs/changes.txt b/docs/changes.txt index 45548d7650..8693868a00 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -184,9 +184,13 @@ Changes in behaviour not resulting in compilation errors, please read this! wxAutomationInstance_SilentIfNone flag to prevent the error message if no currently running instances of this object are available. -- Signatures of wxDataViewCustomRenderer::Activate(), LeftClick() and - StartDrag() virtual methods changed. You will need to change them in your - derived renderer class too if you override them. +- Signature of wxDataViewCustomRenderer::StartDrag() virtual method changed. + You will need to change it in your derived renderer class too if you override + it. + +- wxDataViewCustomRenderer::Activate() and LeftClick() were replaced with the + new ActivateCell() method. You will need to change it in your derived + renderer class accordingly. - wxThread::Wait() and wxThread::Delete() used to dispatch the events while waiting for the thread to exit in wxMSW. They still do it in default build @@ -482,6 +486,7 @@ All (GUI): - Fix tooltips in wxSearchCtrl and other composite controls (Catalin Raceanu). - Allow converting to and from wxGraphicsBitmap and wxImage directly. - Allow wxGraphicsFont creation without passing by wxFont. +- Added wxDataViewCustomRenderer::ActivateCell(). OSX: diff --git a/docs/doxygen/overviews/changes_since28.h b/docs/doxygen/overviews/changes_since28.h index 8ec1c9fc1e..e56b45fd69 100644 --- a/docs/doxygen/overviews/changes_since28.h +++ b/docs/doxygen/overviews/changes_since28.h @@ -177,10 +177,14 @@ Finally, a few structure fields, notable @c wxCmdLineEntryDesc::shortName, available for the scroll target as function of the main window size, please see the documentation of this method for more details. -- Signatures of wxDataViewCustomRenderer::Activate(), - wxDataViewCustomRenderer::LeftClick() and - wxDataViewCustomRenderer::StartDrag() virtual methods changed. You will need - to change them in your derived renderer class too if you override them. +- Signature of wxDataViewCustomRenderer::StartDrag() virtual method changed. + You will need to change it in your derived renderer class too if you override + it. + +- wxDataViewCustomRenderer::Activate() and + wxDataViewCustomRenderer::LeftClick() were replaced with the new + wxDataViewCustomRenderer::ActivateCell() method. You will need to change it + in your derived renderer class accordingly. */ diff --git a/include/wx/dvrenderers.h b/include/wx/dvrenderers.h index a73d673378..7cbb7b220e 100644 --- a/include/wx/dvrenderers.h +++ b/include/wx/dvrenderers.h @@ -228,23 +228,39 @@ public: // Return the size of the item appropriate to its current value. virtual wxSize GetSize() const = 0; - // Define virtual function which are called when the item is activated - // (double-clicked or Enter is pressed on it), clicked or the user starts - // to drag it: by default they all simply return false indicating that the - // events are not handled - - virtual bool Activate(const wxRect& WXUNUSED(cell), - wxDataViewModel *WXUNUSED(model), - const wxDataViewItem & WXUNUSED(item), - unsigned int WXUNUSED(col)) - { return false; } + // Define virtual function which are called when a key is pressed on the + // item, clicked or the user starts to drag it: by default they all simply + // return false indicating that the events are not handled + + virtual bool ActivateCell(const wxRect& cell, + wxDataViewModel *model, + const wxDataViewItem & item, + unsigned int col, + const wxMouseEvent* mouseEvent) + { + // Compatibility code + if ( mouseEvent ) + return LeftClick(mouseEvent->GetPosition(), cell, model, item, col); + else + return Activate(cell, model, item, col); + } - virtual bool LeftClick(const wxPoint& WXUNUSED(cursor), - const wxRect& WXUNUSED(cell), - wxDataViewModel *WXUNUSED(model), - const wxDataViewItem & WXUNUSED(item), - unsigned int WXUNUSED(col) ) - { return false; } + // Deprecated, use (and override) ActivateCell() instead + wxDEPRECATED_BUT_USED_INTERNALLY_INLINE( + virtual bool Activate(wxRect WXUNUSED(cell), + wxDataViewModel *WXUNUSED(model), + const wxDataViewItem & WXUNUSED(item), + unsigned int WXUNUSED(col)), + return false; ) + + // Deprecated, use (and override) ActivateCell() instead + wxDEPRECATED_BUT_USED_INTERNALLY_INLINE( + virtual bool LeftClick(wxPoint WXUNUSED(cursor), + wxRect WXUNUSED(cell), + wxDataViewModel *WXUNUSED(model), + const wxDataViewItem & WXUNUSED(item), + unsigned int WXUNUSED(col)), + return false; ) virtual bool StartDrag(const wxPoint& WXUNUSED(cursor), const wxRect& WXUNUSED(cell), diff --git a/include/wx/generic/dvrenderer.h b/include/wx/generic/dvrenderer.h index aa7f6151a6..3236f41eb3 100644 --- a/include/wx/generic/dvrenderer.h +++ b/include/wx/generic/dvrenderer.h @@ -41,23 +41,16 @@ public: // implementation - // These callbacks are used by generic implementation of wxDVC itself. - // They're different from the corresponding Activate/LeftClick() methods - // which should only be overridable for the custom renderers while the - // generic implementation uses these ones for all of them, including the - // standard ones. - - virtual bool WXOnActivate(const wxRect& WXUNUSED(cell), - wxDataViewModel *WXUNUSED(model), - const wxDataViewItem & WXUNUSED(item), - unsigned int WXUNUSED(col)) - { return false; } - - virtual bool WXOnLeftClick(const wxPoint& WXUNUSED(cursor), - const wxRect& WXUNUSED(cell), - wxDataViewModel *WXUNUSED(model), - const wxDataViewItem & WXUNUSED(item), - unsigned int WXUNUSED(col) ) + // This callback is used by generic implementation of wxDVC itself. It's + // different from the corresponding ActivateCell() method which should only + // be overridable for the custom renderers while the generic implementation + // uses this one for all of them, including the standard ones. + + virtual bool WXActivateCell(const wxRect& WXUNUSED(cell), + wxDataViewModel *WXUNUSED(model), + const wxDataViewItem & WXUNUSED(item), + unsigned int WXUNUSED(col), + const wxMouseEvent* WXUNUSED(mouseEvent)) { return false; } private: diff --git a/include/wx/generic/dvrenderers.h b/include/wx/generic/dvrenderers.h index 8064d0939b..a5dc8c09b0 100644 --- a/include/wx/generic/dvrenderers.h +++ b/include/wx/generic/dvrenderers.h @@ -26,21 +26,13 @@ public: // see the explanation of the following WXOnXXX() methods in wx/generic/dvrenderer.h - virtual bool WXOnActivate(const wxRect& cell, - wxDataViewModel *model, - const wxDataViewItem& item, - unsigned int col) + virtual bool WXActivateCell(const wxRect& cell, + wxDataViewModel *model, + const wxDataViewItem& item, + unsigned int col, + const wxMouseEvent *mouseEvent) { - return Activate(cell, model, item, col); - } - - virtual bool WXOnLeftClick(const wxPoint& cursor, - const wxRect& cell, - wxDataViewModel *model, - const wxDataViewItem &item, - unsigned int col) - { - return LeftClick(cursor, cell, model, item, col); + return ActivateCell(cell, model, item, col, mouseEvent); } private: @@ -121,16 +113,11 @@ public: wxSize GetSize() const; // Implementation only, don't use nor override - virtual bool WXOnLeftClick(const wxPoint& cursor, - const wxRect& cell, - wxDataViewModel *model, - const wxDataViewItem& item, - unsigned int col); - - virtual bool WXOnActivate(const wxRect& cell, - wxDataViewModel *model, - const wxDataViewItem& item, - unsigned int col); + virtual bool WXActivateCell(const wxRect& cell, + wxDataViewModel *model, + const wxDataViewItem& item, + unsigned int col, + const wxMouseEvent *mouseEvent); private: bool m_toggle; diff --git a/interface/wx/dataview.h b/interface/wx/dataview.h index e6260676f3..2214cb4e2d 100644 --- a/interface/wx/dataview.h +++ b/interface/wx/dataview.h @@ -1322,18 +1322,54 @@ public: */ enum wxDataViewCellMode { + /** + The cell only displays information and cannot be manipulated or + otherwise interacted with in any way. + + Note that this doesn't mean that the row being drawn can't be selected, + just that a particular element of it cannot be individually modified. + */ wxDATAVIEW_CELL_INERT, /** - Indicates that the user can double click the cell and something will - happen (e.g. a window for editing a date will pop up). + Indicates that the cell can be @em activated by clicking it or using + keyboard. + + Activating a cell is an alternative to showing inline editor when the + value can be edited in a simple way that doesn't warrant full editor + control. The most typical use of cell activation is toggling the + checkbox in wxDataViewToggleRenderer; others would be e.g. an embedded + volume slider or a five-star rating column. + + The exact means of activating a cell are platform-dependent, but they + are usually similar to those used for inline editing of values. + Typically, a cell would be activated by Space or Enter keys or by left + mouse click. + + @note Do not confuse this with item activation in wxDataViewCtrl + and the wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED event. That one is + used for activating the item (or, to put it differently, the + entire row) similarly to analogous messages in wxTreeCtrl and + wxListCtrl, and the effect differs (play a song, open a file + etc.). Cell activation, on the other hand, is all about + interacting with the individual cell. + + @see wxDataViewCustomRenderer::ActivateCell() */ wxDATAVIEW_CELL_ACTIVATABLE, /** - Indicates that the user can edit the data in-place, i.e. an control - will show up after a slow click on the cell. This behaviour is best - known from changing the filename in most file managers etc. + Indicates that the user can edit the data in-place in an inline editor + control that will show up when the user wants to edit the cell. + + A typical example of this behaviour is changing the filename in a file + managers. + + Editing is typically triggered by slowly double-clicking the cell or by + a platform-dependent keyboard shortcut (F2 is typical on Windows, Space + and/or Enter is common elsewhere and supported on Windows too). + + @see wxDataViewCustomRenderer::CreateEditorCtrl() */ wxDATAVIEW_CELL_EDITABLE }; @@ -1692,20 +1728,72 @@ public: virtual ~wxDataViewCustomRenderer(); /** - Override this to react to double clicks or ENTER. - This method will only be called in wxDATAVIEW_CELL_ACTIVATABLE mode. + Override this to react to cell @em activation. Activating a cell is an + alternative to showing inline editor when the value can be edited in a + simple way that doesn't warrant full editor control. The most typical + use of cell activation is toggling the checkbox in + wxDataViewToggleRenderer; others would be e.g. an embedded volume + slider or a five-star rating column. + + The exact means of activating a cell are platform-dependent, but they + are usually similar to those used for inline editing of values. + Typically, a cell would be activated by Space or Enter keys or by left + mouse click. + + This method will only be called if the cell has the + wxDATAVIEW_CELL_ACTIVATABLE mode. + + @param cell + Coordinates of the activated cell's area. + @param model + The model to manipulate in response. + @param item + Activated item. + @param col + Activated column of @a item. + @param mouseEvent + If the activation was triggered by mouse click, contains the + corresponding event. Is @NULL otherwise (for keyboard activation). + Mouse coordinates are adjusted to be relative to the cell. + + @since 2.9.3 + + @note Do not confuse this method with item activation in wxDataViewCtrl + and the wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED event. That one is + used for activating the item (or, to put it differently, the + entire row) similarly to analogous messages in wxTreeCtrl and + wxListCtrl, and the effect differs (play a song, open a file + etc.). Cell activation, on the other hand, is all about + interacting with the individual cell. + + @see CreateEditorCtrl() */ - virtual bool Activate( const wxRect& cell, - wxDataViewModel* model, - const wxDataViewItem & item, - unsigned int col ); + virtual bool ActivateCell(const wxRect& cell, + wxDataViewModel* model, + const wxDataViewItem & item, + unsigned int col, + const wxMouseEvent *mouseEvent); /** Override this to create the actual editor control once editing is about to start. - @a parent is the parent of the editor control, @a labelRect indicates the - position and size of the editor control and @a value is its initial value: + This method will only be called if the cell has the + wxDATAVIEW_CELL_EDITABLE mode. Editing is typically triggered by slowly + double-clicking the cell or by a platform-dependent keyboard shortcut + (F2 is typical on Windows, Space and/or Enter is common elsewhere and + supported on Windows too). + + @param parent + The parent of the editor control. + @param labelRect + Indicates the position and size of the editor control. The control + should be created in place of the cell and @a labelRect should be + respected as much as possible. + @param value + Initial value of the editor. + + An example: @code { long l = value; @@ -1713,6 +1801,8 @@ public: labelRect.GetTopLeft(), labelRect.GetSize(), 0, 0, 100, l ); } @endcode + + @see ActivateCell() */ virtual wxWindow* CreateEditorCtrl(wxWindow* parent, wxRect labelRect, diff --git a/samples/dataview/dataview.cpp b/samples/dataview/dataview.cpp index 5fb2a2683d..7f872bb6d9 100644 --- a/samples/dataview/dataview.cpp +++ b/samples/dataview/dataview.cpp @@ -189,22 +189,18 @@ public: return true; } - virtual bool Activate( const wxRect& WXUNUSED(cell), - wxDataViewModel *WXUNUSED(model), - const wxDataViewItem &WXUNUSED(item), - unsigned int WXUNUSED(col) ) + virtual bool ActivateCell(const wxRect& WXUNUSED(cell), + wxDataViewModel *WXUNUSED(model), + const wxDataViewItem &WXUNUSED(item), + unsigned int WXUNUSED(col), + const wxMouseEvent *mouseEvent) { - wxLogMessage( "MyCustomRenderer Activate()" ); - return false; - } - - virtual bool LeftClick(const wxPoint& cursor, - const wxRect& WXUNUSED(cell), - wxDataViewModel *WXUNUSED(model), - const wxDataViewItem &WXUNUSED(item), - unsigned int WXUNUSED(col) ) - { - wxLogMessage( "MyCustomRenderer LeftClick( %d, %d )", cursor.x, cursor.y ); + wxString position; + if ( mouseEvent ) + position = wxString::Format("via mouse at %d, %d", mouseEvent->m_x, mouseEvent->m_y); + else + position = "from keyboard"; + wxLogMessage("MyCustomRenderer ActivateCell() %s", position); return false; } diff --git a/src/generic/datavgen.cpp b/src/generic/datavgen.cpp index 02d0a95344..042d50eaca 100644 --- a/src/generic/datavgen.cpp +++ b/src/generic/datavgen.cpp @@ -986,31 +986,24 @@ bool wxDataViewToggleRenderer::Render( wxRect cell, wxDC *dc, int WXUNUSED(state return true; } -bool wxDataViewToggleRenderer::WXOnLeftClick(const wxPoint& cursor, - const wxRect& cell, - wxDataViewModel *model, - const wxDataViewItem& item, - unsigned int col) -{ - // only react to clicks directly on the checkbox, not elsewhere in the same cell: - if (!wxRect(GetSize()).Contains(cursor)) +bool wxDataViewToggleRenderer::WXActivateCell(const wxRect& WXUNUSED(cell), + wxDataViewModel *model, + const wxDataViewItem& item, + unsigned int col, + const wxMouseEvent *mouseEvent) +{ + if ( !model->IsEnabled(item, col) ) return false; - return WXOnActivate(cell, model, item, col); -} - -bool wxDataViewToggleRenderer::WXOnActivate(const wxRect& WXUNUSED(cell), - wxDataViewModel *model, - const wxDataViewItem& item, - unsigned int col) -{ - if (model->IsEnabled(item, col)) + if ( mouseEvent ) { - model->ChangeValue(!m_toggle, item, col); - return true; + // only react to clicks directly on the checkbox, not elsewhere in the same cell: + if ( !wxRect(GetSize()).Contains(mouseEvent->GetPosition()) ) + return false; } - return false; + model->ChangeValue(!m_toggle, item, col); + return true; } wxSize wxDataViewToggleRenderer::GetSize() const @@ -3414,7 +3407,7 @@ void wxDataViewMainWindow::OnChar( wxKeyEvent &event ) wxDataViewRenderer *cell = activatableCol->GetRenderer(); cell->PrepareForItem(GetModel(), item, colIdx); - cell->WXOnActivate(cell_rect, GetModel(), item, colIdx); + cell->WXActivateCell(cell_rect, GetModel(), item, colIdx, NULL); } } break; @@ -3886,31 +3879,15 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event ) } else if ( current == m_lineLastClicked ) { - bool activated = false; - - if ((!ignore_other_columns) && (cell->GetMode() == wxDATAVIEW_CELL_ACTIVATABLE)) - { - const unsigned colIdx = col->GetModelColumn(); - - cell->PrepareForItem(model, item, colIdx); - - wxRect cell_rect( xpos, GetLineStart( current ), - col->GetWidth(), GetLineHeight( current ) ); - activated = cell->WXOnActivate( cell_rect, model, item, colIdx ); - } - - if ( !activated ) - { - wxWindow *parent = GetParent(); - wxDataViewEvent le(wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED, parent->GetId()); - le.SetItem( item ); - le.SetColumn( col->GetModelColumn() ); - le.SetDataViewColumn( col ); - le.SetEventObject(parent); - le.SetModel(GetModel()); + wxWindow *parent = GetParent(); + wxDataViewEvent le(wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED, parent->GetId()); + le.SetItem( item ); + le.SetColumn( col->GetModelColumn() ); + le.SetDataViewColumn( col ); + le.SetEventObject(parent); + le.SetModel(GetModel()); - parent->ProcessWindowEvent(le); - } + parent->ProcessWindowEvent(le); return; } else @@ -4054,7 +4031,7 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event ) m_lastOnSame = !simulateClick && ((col == oldCurrentCol) && (current == oldCurrentRow)) && oldWasSelected; - // Call LeftClick after everything else as under GTK+ + // Call ActivateCell() after everything else as under GTK+ if (cell->GetMode() & wxDATAVIEW_CELL_ACTIVATABLE) { // notify cell about click @@ -4095,14 +4072,19 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event ) } } - wxPoint pos( event.GetPosition() ); - pos.x -= rectItem.x; - pos.y -= rectItem.y; + wxMouseEvent event2(event); + event2.m_x -= rectItem.x; + event2.m_y -= rectItem.y; + m_owner->CalcUnscrolledPosition(event2.m_x, event2.m_y, &event2.m_x, &event2.m_y); - m_owner->CalcUnscrolledPosition( pos.x, pos.y, &pos.x, &pos.y ); - - /* ignore ret */ cell->WXOnLeftClick( pos, cell_rect, - model, item, col->GetModelColumn()); + /* ignore ret */ cell->WXActivateCell + ( + cell_rect, + model, + item, + col->GetModelColumn(), + &event2 + ); } } } diff --git a/src/gtk/dataview.cpp b/src/gtk/dataview.cpp index e8025a76a8..0c03c24f5b 100644 --- a/src/gtk/dataview.cpp +++ b/src/gtk/dataview.cpp @@ -34,6 +34,7 @@ #include "wx/gtk/private/gdkconv.h" #include "wx/gtk/private/list.h" +#include "wx/gtk/private/event.h" using namespace wxGTKImpl; class wxGtkDataViewModelNotifier; @@ -1209,7 +1210,6 @@ struct _GtkWxCellRenderer /*< private >*/ wxDataViewCustomRenderer *cell; - guint32 last_click; }; struct _GtkWxCellRendererClass @@ -1294,7 +1294,6 @@ static void gtk_wx_cell_renderer_init (GtkWxCellRenderer *cell) { cell->cell = NULL; - cell->last_click = 0; } static void @@ -1510,37 +1509,27 @@ gtk_wx_cell_renderer_activate( unsigned int model_col = cell->GetOwner()->GetModelColumn(); - if (!event) + if ( !event ) { - bool ret = false; - // activated by - if (cell->Activate( renderrect, model, item, model_col )) - ret = true; - - return ret; + return cell->ActivateCell(renderrect, model, item, model_col, NULL); } - else if (event->type == GDK_BUTTON_PRESS) + else if ( event->type == GDK_BUTTON_PRESS ) { - GdkEventButton *button_event = (GdkEventButton*) event; - wxPoint pt( ((int) button_event->x) - renderrect.x, - ((int) button_event->y) - renderrect.y ); - - bool ret = false; - if (button_event->button == 1) + GdkEventButton *button_event = (GdkEventButton*)event; + if ( button_event->button == 1 ) { - if (cell->LeftClick( pt, renderrect, model, item, model_col )) - ret = true; - // TODO: query system double-click time - if (button_event->time - wxrenderer->last_click < 400) - if (cell->Activate( renderrect, model, item, model_col )) - ret = true; - } - wxrenderer->last_click = button_event->time; + wxMouseEvent mouse_event(wxEVT_LEFT_DOWN); + InitMouseEvent(ctrl, mouse_event, button_event); + + mouse_event.m_x -= renderrect.x; + mouse_event.m_y -= renderrect.y; - return ret; + return cell->ActivateCell(renderrect, model, item, model_col, &mouse_event); + } } + wxLogDebug("unexpected event type in gtk_wx_cell_renderer_activate()"); return false; }