Fix sending EVT_SPIN_DOWN/UP events in Cocoa implementation of wxSpinButton

To determine which wxSpinButton arrow was clicked, in the action handler there is compared current NSStepper value (after the actual change) with the value before the change. This former value is fetched in the internal mouse click event handler which is invoked before the action handler. This method of determining a delta works fine as long as the current value remains unchanged between the execution of the internal mouse click event handler and the action handler. But if the current value is explicitly changed (by calls to SetValue(), SetRange()) in some handler(s) invoked between these two (like e.g. bound EVT_LEFT_DOWN handler), calculated delta can be invalid and therefore wrong EVT_SPIN_DOWN/UP events can be sent.
To get correct delta value we should to keep track of all explicit changes made to the current value starting from the mouse click and up to the entry to the action handler.

Closes #17955.
This commit is contained in:
Artur Wieczorek
2017-09-21 13:45:13 +02:00
parent 22a4feea53
commit e2bfba21fe

View File

@@ -41,25 +41,55 @@ public :
wxWidgetCocoaImpl(peer, w)
{
m_formerValue = 0;
m_trackValue = false;
}
~wxSpinButtonCocoaImpl()
{
}
virtual void SetValue(wxInt32 v) wxOVERRIDE;
virtual void SetMinimum(wxInt32 v) wxOVERRIDE;
virtual void SetMaximum(wxInt32 v) wxOVERRIDE;
virtual void controlAction(WXWidget slf, void* _cmd, void *sender) wxOVERRIDE;
virtual void mouseEvent(WX_NSEvent event, WXWidget slf, void* _cmd) wxOVERRIDE;
private:
int m_formerValue;
bool m_trackValue;
};
void wxSpinButtonCocoaImpl::SetValue(wxInt32 v)
{
[(NSStepper*)m_osxView setIntValue:v];
if ( m_trackValue )
m_formerValue = [(NSStepper*)m_osxView intValue];
}
void wxSpinButtonCocoaImpl::SetMinimum(wxInt32 v)
{
[(NSStepper*)m_osxView setMinValue:(double)v];
// Current value might be adjusted.
if ( m_trackValue )
m_formerValue = [(NSStepper*)m_osxView intValue];
}
void wxSpinButtonCocoaImpl::SetMaximum(wxInt32 v)
{
[(NSStepper*)m_osxView setMaxValue:(double)v];
// Current value might be adjusted.
if ( m_trackValue )
m_formerValue = [(NSStepper*)m_osxView intValue];
}
void wxSpinButtonCocoaImpl::mouseEvent(WX_NSEvent event, WXWidget slf, void *_cmd)
{
// send a release event in case we've been tracking the thumb
// Save and track the current value which may be changed
// in the mouse event handler
if ( strcmp( sel_getName((SEL) _cmd) , "mouseDown:") == 0 )
{
m_formerValue = [(NSStepper*)m_osxView intValue];
m_trackValue = true;
}
wxWidgetCocoaImpl::mouseEvent(event, slf, _cmd);
@@ -89,6 +119,7 @@ void wxSpinButtonCocoaImpl::controlAction( WXWidget WXUNUSED(slf), void *WXUNUSE
wxpeer->TriggerScrollEvent(wxEVT_SCROLL_LINEDOWN);
m_formerValue = [(NSStepper*)m_osxView intValue];
m_trackValue = false;
}
}