Getting the final value from an NSSlider drag

2015-12-29 Thread Roland King
I have some NSSliders hooked up on my UI to text fields with formatters, all 
set up with bindings so that the label shows the slider value. The sliders are 
continuous, looks fine, nice feedback for whoever’s driving. 

However I want to capture, in the app, the value of the slider only at the end 
when the mouse goes up, once. That value ends up being sent out over bluetooth, 
and I really don’t want to send 100 float values a second, when only the last 
one matters anyway. Probably just trying would cause bad things to happen. 

I’m used to UIKit which has the alternate form of action handling method which 
gives you the event, but AppKit doesn’t have that unfortunately. 

I can’t capture mouseDown and mouseUp because the control gets them

I tried a NSEvent.addLocalMonitorForEventsMatchingMask() but that doesn’t 
capture events inside tracking loops, so I get the mouse down, and that’s it, 
the slider eats the rest, which doesn’t help. 

In the action handing code, which gets called all the time, I can call 
NSEvent.pressedMouseButtons() and that does appear to work and let me find the 
final value. I didn’t get great comfort from the documentation that this is 
reliable however. 

I can subclass NSSlider or possibly NSSliderCell but that sounds like a whole 
world of pain, if I have to do that I’ll probably just put a coalescing delay 
into the whole thing which waits 1/2 second after an update before it actually 
does the update. 

Any good ways to do this? 
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Getting the final value from an NSSlider drag

2015-12-29 Thread Quincey Morris
On Dec 29, 2015, at 00:44 , Roland King  wrote:
> 
> I want to capture, in the app, the value of the slider only at the end when 
> the mouse goes up, once

Isn’t that what the NSControl property continuous==false is for?

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Getting the final value from an NSSlider drag

2015-12-29 Thread Roland King

> On 29 Dec 2015, at 17:40, Quincey Morris 
>  wrote:
> 
> On Dec 29, 2015, at 00:44 , Roland King  > wrote:
>> 
>> I want to capture, in the app, the value of the slider only at the end when 
>> the mouse goes up, once
> 
> Isn’t that what the NSControl property continuous==false is for?

But as I said in the post - the slider is hooked up via bindings in the UI to a 
label which shows the value *as you slide it*, so it needs to be continuous for 
that purpose. Then when you let go, only then do I want the final value to be 
delivered to the app. 

were it simply a matter of turning continuous off I wouldn’t have had a 
problem. 

Surprisingly enough the thing I assumed would be the hardest, turned out to be 
the easiest, mouseDown is documented to start a local event loop capture and it 
doesn’t return until it’s all over .. so it just took this. 

import Cocoa

public protocol RKEndValueSliderTarget : NSObjectProtocol
{
func sliderValueChangeEnded( slider : NSSlider )
}

public class RKEndValueSlider: NSSlider
{
public var endValueReceiver : RKEndValueSliderTarget?

public override func mouseDown( theEvent : NSEvent )
{
super.mouseDown( theEvent )
endValueReceiver?.sliderValueChangeEnded( self )
}
}

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Getting the final value from an NSSlider drag

2015-12-29 Thread Quincey Morris
On Dec 29, 2015, at 01:45 , Roland King  wrote:
> 
> the slider is hooked up via bindings in the UI to a label which shows the 
> value *as you slide it*, so it needs to be continuous for that purpose. Then 
> when you let go, only then do I want the final value to be delivered to the 
> app

Yeah, I realized a minute later that you wanted *both* behaviors.

The other way you can approach something like this (though what you did is more 
direct in this case) is to start a timer. The timer won’t actually run in event 
loop tracking mode, so you can use time expiry as an indication that the 
tracking is done. Something like that.


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Getting the final value from an NSSlider drag

2015-12-29 Thread Roland King

> On 29 Dec 2015, at 17:54, Quincey Morris 
>  wrote:
> 
> On Dec 29, 2015, at 01:45 , Roland King  > wrote:
>> 
>> the slider is hooked up via bindings in the UI to a label which shows the 
>> value *as you slide it*, so it needs to be continuous for that purpose. Then 
>> when you let go, only then do I want the final value to be delivered to the 
>> app
> 
> Yeah, I realized a minute later that you wanted *both* behaviors.
> 
> The other way you can approach something like this (though what you did is 
> more direct in this case) is to start a timer. The timer won’t actually run 
> in event loop tracking mode, so you can use time expiry as an indication that 
> the tracking is done. Something like that.
> 
> 

That’s really sneaky - I love it. I’m pleased there was a more direct way of 
attacking it in the end however, I may not have slept well for a week after 
using a timer for that, but it’s great idea. 
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Getting the final value from an NSSlider drag

2015-12-29 Thread Graham Cox

> On 29 Dec 2015, at 7:44 PM, Roland King  wrote:
> 
> I can subclass NSSlider or possibly NSSliderCell but that sounds like a whole 
> world of pain, if I have to do that I’ll probably just put a coalescing delay 
> into the whole thing which waits 1/2 second after an update before it 
> actually does the update. 
> 
> Any good ways to do this? 


In your action method, call another method that handles the final value using 
-performSelector:withObject:afterDelay: but just before you do that, call 
+[NSObject cancelPreviousPerformRequestsWithTarget:...] for the same message. 
This schedules a deferred message but immediately cancels it as long as the 
values come pouring in. On the last time, when you stop moving the slider, the 
final -performSelector will get to its target and do its work. The afterDelay 
parameter can be set to whatever value you think you’ll need to allow for a 
slowly moved slider NOT to fire the final message. I typically use 0.1sec.

This mechanism is available to any NSObject, and doesn’t require you to roll 
your own timer-based solution. Behind the scenes this is already doing that.

—Graham



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Getting the final value from an NSSlider drag

2015-12-29 Thread Lee Ann Rucker

> On Dec 29, 2015, at 12:44 AM, Roland King  wrote:
> 
> I have some NSSliders hooked up on my UI to text fields with formatters, all 
> set up with bindings so that the label shows the slider value. The sliders 
> are continuous, looks fine, nice feedback for whoever’s driving. 
> 
> However I want to capture, in the app, the value of the slider only at the 
> end when the mouse goes up, once. That value ends up being sent out over 
> bluetooth, and I really don’t want to send 100 float values a second, when 
> only the last one matters anyway. Probably just trying would cause bad things 
> to happen. 
> 
> I’m used to UIKit which has the alternate form of action handling method 
> which gives you the event, but AppKit doesn’t have that unfortunately. 
> 
> I can’t capture mouseDown and mouseUp because the control gets them
> 
> I tried a NSEvent.addLocalMonitorForEventsMatchingMask() but that doesn’t 
> capture events inside tracking loops, so I get the mouse down, and that’s it, 
> the slider eats the rest, which doesn’t help. 
> 
> In the action handing code, which gets called all the time, I can call 
> NSEvent.pressedMouseButtons() and that does appear to work and let me find 
> the final value. I didn’t get great comfort from the documentation that this 
> is reliable however. 
> 
> I can subclass NSSlider or possibly NSSliderCell but that sounds like a whole 
> world of pain, 


Actually it's easy. For very similar reasons I needed the same behavior - live 
update of the slider's temp value for UI elements, but only call the final 
setter when the user is done. I subclassed NSSlider's keyUp: and keyDown: to 
call super and then call my own delegate method "sliderDidEndUpdate:"


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Getting the final value from an NSSlider drag

2015-12-29 Thread Ken Thomases
On Dec 29, 2015, at 5:44 AM, Graham Cox  wrote:
> 
> On 29 Dec 2015, at 7:44 PM, Roland King  wrote:
>> 
>> I can subclass NSSlider or possibly NSSliderCell but that sounds like a 
>> whole world of pain, if I have to do that I’ll probably just put a 
>> coalescing delay into the whole thing which waits 1/2 second after an update 
>> before it actually does the update. 
>> 
>> Any good ways to do this? 
> 
> In your action method, call another method that handles the final value using 
> -performSelector:withObject:afterDelay: but just before you do that, call 
> +[NSObject cancelPreviousPerformRequestsWithTarget:...] for the same message. 
> This schedules a deferred message but immediately cancels it as long as the 
> values come pouring in. On the last time, when you stop moving the slider, 
> the final -performSelector will get to its target and do its work. The 
> afterDelay parameter can be set to whatever value you think you’ll need to 
> allow for a slowly moved slider NOT to fire the final message. I typically 
> use 0.1sec.

This gives false positives if the user simply stops moving the mouse but 
doesn't release the mouse button.  There's no delay you can specify that avoids 
this, since there's no upper bound to how long the user can hold the mouse 
button.  (With assistive technologies, the user doesn't even have to be 
actually holding anything for the duration.)

Regards,
Ken


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Getting the final value from an NSSlider drag

2015-12-29 Thread Doug Hill

> On Dec 29, 2015, at 2:45 PM, Ken Thomases  wrote:
> 
> On Dec 29, 2015, at 5:44 AM, Graham Cox  > wrote:
>> 
>> On 29 Dec 2015, at 7:44 PM, Roland King  wrote:
>>> 
>>> I can subclass NSSlider or possibly NSSliderCell but that sounds like a 
>>> whole world of pain, if I have to do that I’ll probably just put a 
>>> coalescing delay into the whole thing which waits 1/2 second after an 
>>> update before it actually does the update. 
>>> 
>>> Any good ways to do this? 
>> 
>> In your action method, call another method that handles the final value 
>> using -performSelector:withObject:afterDelay: but just before you do that, 
>> call +[NSObject cancelPreviousPerformRequestsWithTarget:...] for the same 
>> message. This schedules a deferred message but immediately cancels it as 
>> long as the values come pouring in. On the last time, when you stop moving 
>> the slider, the final -performSelector will get to its target and do its 
>> work. The afterDelay parameter can be set to whatever value you think you’ll 
>> need to allow for a slowly moved slider NOT to fire the final message. I 
>> typically use 0.1sec.
> 
> This gives false positives if the user simply stops moving the mouse but 
> doesn't release the mouse button.  There's no delay you can specify that 
> avoids this, since there's no upper bound to how long the user can hold the 
> mouse button.  (With assistive technologies, the user doesn't even have to be 
> actually holding anything for the duration.)
> 
> Regards,
> Ken

If you want to know when the last value is sent during mouse tracking, set the 
‘actionOn’ property to mouse-up.

So, something like this:

- (void)viewDidLoad
{
[super viewDidLoad];

self.slider.action = @selector(valueChangedFinally:);
self.slider.target = self;
[self.slider sendActionOn:NSLeftMouseUpMask];
}

- (IBAction)valueChangedFinally:(id)sender
{
NSLog(@“Here is the final slider value upon mouse up:%@", [sender 
stringValue]);
}

Presumably the other bindings/etc. code would still work to update your 
real-time display.

Doug Hill
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Getting the final value from an NSSlider drag

2015-12-29 Thread Roland King
> 
> If you want to know when the last value is sent during mouse tracking, set 
> the ‘actionOn’ property to mouse-up.
> 
> So, something like this:
> 
> - (void)viewDidLoad
> {
>[super viewDidLoad];
> 
>self.slider.action = @selector(valueChangedFinally:);
>self.slider.target = self;
>[self.slider sendActionOn:NSLeftMouseUpMask];
> }
> 
> - (IBAction)valueChangedFinally:(id)sender
> {
>NSLog(@“Here is the final slider value upon mouse up:%@", [sender 
> stringValue]);
> }
> 
> Presumably the other bindings/etc. code would still work to update your 
> real-time display.
> 
> Doug Hill

No they don’t - changing that to to NSLeftMouseUpMask has a similar effect to 
turning off ‘continuous’, all clients get one event, at the end, so the live 
updating realtime display doesn’t work. 

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Getting the final value from an NSSlider drag

2015-12-29 Thread Roland King

> On 30 Dec 2015, at 05:53, Lee Ann Rucker  wrote:
> 
> 
>> 
> 
> 
> Actually it's easy. For very similar reasons I needed the same behavior - 
> live update of the slider's temp value for UI elements, but only call the 
> final setter when the user is done. I subclassed NSSlider's keyUp: and 
> keyDown: to call super and then call my own delegate method 
> "sliderDidEndUpdate:"
> 

Never drove a slider with the keyboard before, so I added a keyDown and keyUp 
method to the  mouseDown: one I posted earlier, with a bit of code to try and 
be smart about when to send updates, so you don’t get them if you’re just 
tabbing though. Seems to work well enough for this use-case, keyboard and 
mouse, live update on the screen, one update at the end, 15 lines of code and 
no need to artificially compress the events. 
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Getting the final value from an NSSlider drag

2015-12-29 Thread Uli Kusterer

> On 29 Dec 2015, at 23:45, Ken Thomases  wrote:
> 
> On Dec 29, 2015, at 5:44 AM, Graham Cox  wrote:
>> 
>> On 29 Dec 2015, at 7:44 PM, Roland King  wrote:
>>> 
>>> I can subclass NSSlider or possibly NSSliderCell but that sounds like a 
>>> whole world of pain, if I have to do that I’ll probably just put a 
>>> coalescing delay into the whole thing which waits 1/2 second after an 
>>> update before it actually does the update. 
>>> 
>>> Any good ways to do this? 
>> 
>> In your action method, call another method that handles the final value 
>> using -performSelector:withObject:afterDelay: but just before you do that, 
>> call +[NSObject cancelPreviousPerformRequestsWithTarget:...] for the same 
>> message. This schedules a deferred message but immediately cancels it as 
>> long as the values come pouring in. On the last time, when you stop moving 
>> the slider, the final -performSelector will get to its target and do its 
>> work. The afterDelay parameter can be set to whatever value you think you’ll 
>> need to allow for a slowly moved slider NOT to fire the final message. I 
>> typically use 0.1sec.
> 
> This gives false positives if the user simply stops moving the mouse but 
> doesn't release the mouse button.  There's no delay you can specify that 
> avoids this, since there's no upper bound to how long the user can hold the 
> mouse button.  (With assistive technologies, the user doesn't even have to be 
> actually holding anything for the duration.)

 It shouldn't. performSelector:afterDelay: schedules using 
NSRunLoopDefaultMode, while the slider uses NSEventTrackingRunLoopMode. So it 
will never fire while the slider is still tracking. In fact, you could use 0.0 
as the delay.

Cheers,
-- Uli Kusterer
"The Witnesses of TeachText are everywhere..."
http://stacksmith.org





___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Getting the final value from an NSSlider drag

2015-12-29 Thread Lee Ann Rucker

> On Dec 29, 2015, at 3:51 PM, Roland King  wrote:
> 
> 
>> On 30 Dec 2015, at 05:53, Lee Ann Rucker  wrote:
>> 
>> 
>>> 
>> 
>> 
>> Actually it's easy. For very similar reasons I needed the same behavior - 
>> live update of the slider's temp value for UI elements, but only call the 
>> final setter when the user is done. I subclassed NSSlider's keyUp: and 
>> keyDown: to call super and then call my own delegate method 
>> "sliderDidEndUpdate:"
>> 
> 
> Never drove a slider with the keyboard before, so I added a keyDown and keyUp 
> method to the  mouseDown: one I posted earlier, with a bit of code to try and 
> be smart about when to send updates, so you don’t get them if you’re just 
> tabbing though. Seems to work well enough for this use-case, keyboard and 
> mouse, live update on the screen, one update at the end, 15 lines of code and 
> no need to artificially compress the events.

Whoops, how did I not notice that - it should've been keyUp and mouseDown! You 
don't need keyDown because nothing changes until keyUp, but mouseDown won't 
return until the mouse goes up.

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Getting the final value from an NSSlider drag

2015-12-29 Thread Roland King
>> 
>> Never drove a slider with the keyboard before, so I added a keyDown and 
>> keyUp method to the  mouseDown: one I posted earlier, with a bit of code to 
>> try and be smart about when to send updates, so you don’t get them if you’re 
>> just tabbing though. Seems to work well enough for this use-case, keyboard 
>> and mouse, live update on the screen, one update at the end, 15 lines of 
>> code and no need to artificially compress the events.
> 
> Whoops, how did I not notice that - it should've been keyUp and mouseDown! 
> You don't need keyDown because nothing changes until keyUp, but mouseDown 
> won't return until the mouse goes up.

You don’t indeed - however if you add keyDown: as well and capture the current 
value (if you don’t already have one captured) you can decide whether anything 
actually changed on keyUp: or not. That avoids a spurious callback when you 
just tab through the field. Not that it matters in this implementation but it 
was easy to do. 

Ok enough GUI fun, I better go write the actual bluetooth bit now
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Getting the final value from an NSSlider drag

2015-12-29 Thread Graham Cox

> On 30 Dec 2015, at 9:45 AM, Ken Thomases  wrote:
> 
> This gives false positives if the user simply stops moving the mouse but 
> doesn't release the mouse button.  There's no delay you can specify that 
> avoids this, since there's no upper bound to how long the user can hold the 
> mouse button.  (With assistive technologies, the user doesn't even have to be 
> actually holding anything for the duration.)
> 


True, but if that matters you can look at the mouse button state as part of 
your logic.

The point I was making is that there is a “retriggerable timer” mechanism 
available to any NSObject, so it usually makes sense to use it where possible 
rather than rolling your own timer or subclassing the control.

—Graham



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com