Make virtual lists send DESELECTED events consistently on both implementations

In the case when a listctrl is clicked outside of any item, the item is
visually deselected, and it is logical that a DESELECTED is sent.

For non-virtual lists this would happen, but for virtual lists it would
either happen or not happen depending on implementation (MSW/generic)
and mode (single/multi). From now on the DESELECTED event is always sent.
This commit is contained in:
Lauri Nurmi
2019-11-12 21:22:05 +02:00
parent 9d9b0c51c8
commit 96b83a1523
3 changed files with 65 additions and 56 deletions

View File

@@ -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)}

View File

@@ -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;

View File

@@ -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;
}
} }
} }