Merge branch 'list-deselect-event'
Consistently send DESELECTED events from virtual wxListCtrl. See https://github.com/wxWidgets/wxWidgets/pull/1857
This commit is contained in:
@@ -1442,7 +1442,7 @@ protected:
|
|||||||
control itself when this event is generated, see @ref
|
control itself when this event is generated, see @ref
|
||||||
overview_events_with_mouse_capture "event handling overview".
|
overview_events_with_mouse_capture "event handling overview".
|
||||||
@event{EVT_LIST_ITEM_DESELECTED(id, func)}
|
@event{EVT_LIST_ITEM_DESELECTED(id, func)}
|
||||||
The item has been deselected.
|
The item has been deselected. GetIndex() may be -1 with virtual lists.
|
||||||
@event{EVT_LIST_ITEM_ACTIVATED(id, func)}
|
@event{EVT_LIST_ITEM_ACTIVATED(id, func)}
|
||||||
The item has been activated (ENTER or double click).
|
The item has been activated (ENTER or double click).
|
||||||
@event{EVT_LIST_ITEM_FOCUSED(id, func)}
|
@event{EVT_LIST_ITEM_FOCUSED(id, func)}
|
||||||
|
@@ -2447,7 +2447,8 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event )
|
|||||||
else
|
else
|
||||||
m_dragCount = 0;
|
m_dragCount = 0;
|
||||||
|
|
||||||
// The only mouse event that can be generated without any valid item is
|
// The only mouse events that can be generated without any valid item are
|
||||||
|
// wxEVT_LIST_ITEM_DESELECTED for virtual lists, and
|
||||||
// wxEVT_LIST_ITEM_RIGHT_CLICK as it can be useful to have a global
|
// wxEVT_LIST_ITEM_RIGHT_CLICK as it can be useful to have a global
|
||||||
// popup menu for the list control itself which should be shown even when
|
// popup menu for the list control itself which should be shown even when
|
||||||
// the user clicks outside of any item.
|
// the user clicks outside of any item.
|
||||||
@@ -2467,6 +2468,10 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event )
|
|||||||
{
|
{
|
||||||
// reset the selection and bail out
|
// reset the selection and bail out
|
||||||
HighlightAll(false);
|
HighlightAll(false);
|
||||||
|
// generate a DESELECTED event for
|
||||||
|
// virtual multi-selection lists
|
||||||
|
if ( IsVirtual() && !IsSingleSel() )
|
||||||
|
SendNotify( m_lineLastClicked, wxEVT_LIST_ITEM_DESELECTED );
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@@ -2470,74 +2470,78 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
|
|||||||
case LVN_ITEMCHANGED:
|
case LVN_ITEMCHANGED:
|
||||||
// we translate this catch all message into more interesting
|
// we translate this catch all message into more interesting
|
||||||
// (and more easy to process) wxWidgets events
|
// (and more easy to process) wxWidgets events
|
||||||
|
|
||||||
// first of all, we deal with the state change events only and
|
|
||||||
// only for valid items (item == -1 for the virtual list
|
|
||||||
// control)
|
|
||||||
if ( nmLV->uChanged & LVIF_STATE && iItem != -1 )
|
|
||||||
{
|
{
|
||||||
// temp vars for readability
|
// temp vars for readability
|
||||||
const UINT stOld = nmLV->uOldState;
|
const UINT stOld = nmLV->uOldState;
|
||||||
const UINT stNew = nmLV->uNewState;
|
const UINT stNew = nmLV->uNewState;
|
||||||
|
|
||||||
event.m_item.SetId(iItem);
|
// first of all, we deal with the state change events only and
|
||||||
event.m_item.SetMask(wxLIST_MASK_TEXT |
|
// only for valid items (item == -1 for the virtual list
|
||||||
wxLIST_MASK_IMAGE |
|
// control)
|
||||||
wxLIST_MASK_DATA);
|
if ( nmLV->uChanged & LVIF_STATE &&
|
||||||
GetItem(event.m_item);
|
(iItem != -1 || (stNew & LVIS_SELECTED) != (stOld & LVIS_SELECTED)))
|
||||||
|
|
||||||
// has the focus changed?
|
|
||||||
if ( !(stOld & LVIS_FOCUSED) && (stNew & LVIS_FOCUSED) )
|
|
||||||
{
|
{
|
||||||
eventType = wxEVT_LIST_ITEM_FOCUSED;
|
|
||||||
event.m_itemIndex = iItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( (stNew & LVIS_SELECTED) != (stOld & LVIS_SELECTED) )
|
event.m_item.SetId(iItem);
|
||||||
{
|
event.m_item.SetMask(wxLIST_MASK_TEXT |
|
||||||
if ( eventType != wxEVT_NULL )
|
wxLIST_MASK_IMAGE |
|
||||||
|
wxLIST_MASK_DATA);
|
||||||
|
if (iItem != -1)
|
||||||
|
GetItem(event.m_item);
|
||||||
|
|
||||||
|
// has the focus changed?
|
||||||
|
if ( !(stOld & LVIS_FOCUSED) && (stNew & LVIS_FOCUSED) )
|
||||||
{
|
{
|
||||||
// focus and selection have both changed: send the
|
eventType = wxEVT_LIST_ITEM_FOCUSED;
|
||||||
// focus event from here and the selection one
|
|
||||||
// below
|
|
||||||
event.SetEventType(eventType);
|
|
||||||
(void)HandleWindowEvent(event);
|
|
||||||
}
|
|
||||||
else // no focus event to send
|
|
||||||
{
|
|
||||||
// then need to set m_itemIndex as it wasn't done
|
|
||||||
// above
|
|
||||||
event.m_itemIndex = iItem;
|
event.m_itemIndex = iItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
eventType = stNew & LVIS_SELECTED
|
if ( (stNew & LVIS_SELECTED) != (stOld & LVIS_SELECTED) )
|
||||||
? wxEVT_LIST_ITEM_SELECTED
|
{
|
||||||
: wxEVT_LIST_ITEM_DESELECTED;
|
if ( eventType != wxEVT_NULL )
|
||||||
}
|
{
|
||||||
|
// focus and selection have both changed: send the
|
||||||
|
// focus event from here and the selection one
|
||||||
|
// below
|
||||||
|
event.SetEventType(eventType);
|
||||||
|
(void)HandleWindowEvent(event);
|
||||||
|
}
|
||||||
|
else // no focus event to send
|
||||||
|
{
|
||||||
|
// then need to set m_itemIndex as it wasn't done
|
||||||
|
// above
|
||||||
|
event.m_itemIndex = iItem;
|
||||||
|
}
|
||||||
|
|
||||||
if ( (stNew & LVIS_STATEIMAGEMASK) != (stOld & LVIS_STATEIMAGEMASK) )
|
eventType = stNew & LVIS_SELECTED
|
||||||
{
|
? wxEVT_LIST_ITEM_SELECTED
|
||||||
if ( stOld == INDEXTOSTATEIMAGEMASK(0) )
|
: wxEVT_LIST_ITEM_DESELECTED;
|
||||||
{
|
|
||||||
// item does not yet have a state
|
|
||||||
// occurs when checkboxes are enabled and when a new item is added
|
|
||||||
eventType = wxEVT_NULL;
|
|
||||||
}
|
|
||||||
else if ( stNew == INDEXTOSTATEIMAGEMASK(1) )
|
|
||||||
{
|
|
||||||
eventType = wxEVT_LIST_ITEM_UNCHECKED;
|
|
||||||
}
|
|
||||||
else if ( stNew == INDEXTOSTATEIMAGEMASK(2) )
|
|
||||||
{
|
|
||||||
eventType = wxEVT_LIST_ITEM_CHECKED;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
eventType = wxEVT_NULL;
|
|
||||||
wxLogDebug(wxS("Unknown LVIS_STATEIMAGE state: %u"), stNew);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
event.m_itemIndex = iItem;
|
if ( (stNew & LVIS_STATEIMAGEMASK) != (stOld & LVIS_STATEIMAGEMASK) )
|
||||||
|
{
|
||||||
|
if ( stOld == INDEXTOSTATEIMAGEMASK(0) )
|
||||||
|
{
|
||||||
|
// item does not yet have a state
|
||||||
|
// occurs when checkboxes are enabled and when a new item is added
|
||||||
|
eventType = wxEVT_NULL;
|
||||||
|
}
|
||||||
|
else if ( stNew == INDEXTOSTATEIMAGEMASK(1) )
|
||||||
|
{
|
||||||
|
eventType = wxEVT_LIST_ITEM_UNCHECKED;
|
||||||
|
}
|
||||||
|
else if ( stNew == INDEXTOSTATEIMAGEMASK(2) )
|
||||||
|
{
|
||||||
|
eventType = wxEVT_LIST_ITEM_CHECKED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
eventType = wxEVT_NULL;
|
||||||
|
wxLogDebug(wxS("Unknown LVIS_STATEIMAGE state: %u"), stNew);
|
||||||
|
}
|
||||||
|
|
||||||
|
event.m_itemIndex = iItem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -203,6 +203,7 @@ void ListBaseTestCase::ItemClick()
|
|||||||
EventCounter focused(list, wxEVT_LIST_ITEM_FOCUSED);
|
EventCounter focused(list, wxEVT_LIST_ITEM_FOCUSED);
|
||||||
EventCounter activated(list, wxEVT_LIST_ITEM_ACTIVATED);
|
EventCounter activated(list, wxEVT_LIST_ITEM_ACTIVATED);
|
||||||
EventCounter rclick(list, wxEVT_LIST_ITEM_RIGHT_CLICK);
|
EventCounter rclick(list, wxEVT_LIST_ITEM_RIGHT_CLICK);
|
||||||
|
EventCounter deselected(list, wxEVT_LIST_ITEM_DESELECTED);
|
||||||
|
|
||||||
wxUIActionSimulator sim;
|
wxUIActionSimulator sim;
|
||||||
|
|
||||||
@@ -224,6 +225,15 @@ void ListBaseTestCase::ItemClick()
|
|||||||
sim.MouseClick(wxMOUSE_BTN_RIGHT);
|
sim.MouseClick(wxMOUSE_BTN_RIGHT);
|
||||||
wxYield();
|
wxYield();
|
||||||
|
|
||||||
|
// We want a point within the listctrl but below any items
|
||||||
|
point = list->ClientToScreen(pos.GetPosition()) + wxPoint(10, 50);
|
||||||
|
|
||||||
|
sim.MouseMove(point);
|
||||||
|
wxYield();
|
||||||
|
|
||||||
|
sim.MouseClick();
|
||||||
|
wxYield();
|
||||||
|
|
||||||
// when the first item was selected the focus changes to it, but not
|
// when the first item was selected the focus changes to it, but not
|
||||||
// on subsequent clicks
|
// on subsequent clicks
|
||||||
|
|
||||||
@@ -234,6 +244,7 @@ void ListBaseTestCase::ItemClick()
|
|||||||
#ifndef _WX_GENERIC_LISTCTRL_H_
|
#ifndef _WX_GENERIC_LISTCTRL_H_
|
||||||
CPPUNIT_ASSERT_EQUAL(1, focused.GetCount());
|
CPPUNIT_ASSERT_EQUAL(1, focused.GetCount());
|
||||||
CPPUNIT_ASSERT_EQUAL(1, selected.GetCount());
|
CPPUNIT_ASSERT_EQUAL(1, selected.GetCount());
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1, deselected.GetCount());
|
||||||
#endif
|
#endif
|
||||||
CPPUNIT_ASSERT_EQUAL(1, activated.GetCount());
|
CPPUNIT_ASSERT_EQUAL(1, activated.GetCount());
|
||||||
CPPUNIT_ASSERT_EQUAL(1, rclick.GetCount());
|
CPPUNIT_ASSERT_EQUAL(1, rclick.GetCount());
|
||||||
|
@@ -23,6 +23,8 @@
|
|||||||
#endif // WX_PRECOMP
|
#endif // WX_PRECOMP
|
||||||
|
|
||||||
#include "wx/listctrl.h"
|
#include "wx/listctrl.h"
|
||||||
|
#include "testableframe.h"
|
||||||
|
#include "wx/uiaction.h"
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// test class
|
// test class
|
||||||
@@ -39,9 +41,11 @@ public:
|
|||||||
private:
|
private:
|
||||||
CPPUNIT_TEST_SUITE( VirtListCtrlTestCase );
|
CPPUNIT_TEST_SUITE( VirtListCtrlTestCase );
|
||||||
CPPUNIT_TEST( UpdateSelection );
|
CPPUNIT_TEST( UpdateSelection );
|
||||||
|
WXUISIM_TEST( DeselectedEvent );
|
||||||
CPPUNIT_TEST_SUITE_END();
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
|
||||||
void UpdateSelection();
|
void UpdateSelection();
|
||||||
|
void DeselectedEvent();
|
||||||
|
|
||||||
wxListCtrl *m_list;
|
wxListCtrl *m_list;
|
||||||
|
|
||||||
@@ -105,4 +109,42 @@ void VirtListCtrlTestCase::UpdateSelection()
|
|||||||
CPPUNIT_ASSERT_EQUAL( 1, m_list->GetSelectedItemCount() );
|
CPPUNIT_ASSERT_EQUAL( 1, m_list->GetSelectedItemCount() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VirtListCtrlTestCase::DeselectedEvent()
|
||||||
|
{
|
||||||
|
#if wxUSE_UIACTIONSIMULATOR
|
||||||
|
m_list->AppendColumn("Col0");
|
||||||
|
m_list->SetItemCount(1);
|
||||||
|
wxListCtrl* const list = m_list;
|
||||||
|
|
||||||
|
EventCounter selected(list, wxEVT_LIST_ITEM_SELECTED);
|
||||||
|
EventCounter deselected(list, wxEVT_LIST_ITEM_DESELECTED);
|
||||||
|
|
||||||
|
wxUIActionSimulator sim;
|
||||||
|
|
||||||
|
wxRect pos;
|
||||||
|
list->GetItemRect(0, pos);
|
||||||
|
|
||||||
|
//We move in slightly so we are not on the edge
|
||||||
|
wxPoint point = list->ClientToScreen(pos.GetPosition()) + wxPoint(10, 10);
|
||||||
|
|
||||||
|
sim.MouseMove(point);
|
||||||
|
wxYield();
|
||||||
|
|
||||||
|
sim.MouseClick();
|
||||||
|
wxYield();
|
||||||
|
|
||||||
|
// We want a point within the listctrl but below any items
|
||||||
|
point = list->ClientToScreen(pos.GetPosition()) + wxPoint(10, 50);
|
||||||
|
|
||||||
|
sim.MouseMove(point);
|
||||||
|
wxYield();
|
||||||
|
|
||||||
|
sim.MouseClick();
|
||||||
|
wxYield();
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1, selected.GetCount());
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1, deselected.GetCount());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#endif // wxUSE_LISTCTRL
|
#endif // wxUSE_LISTCTRL
|
||||||
|
Reference in New Issue
Block a user