Tapped event fires before DoubleTapped event in WinRT - xaml

I have the follwing declaration:
<Button Tapped="Handler1" DoubleTapped="Handler2" />
Each time I double tap the button the Handler1 gets fired. Handler 2 never gets fired.
Thanks.

You can't do in this way because it will always fire the first event of tap. You can manage the double tap with the single tap event using a boolean or a counter to manage the following tap events.

I do not know why the DoubleTapped handler does not get called. It should. Maybe IsDoubleTapEnabled is set to false? This could not just happen by explicitly setting the property in XAML, but also e.g. by inheriting the value from a style.
But even when DoubleTapped works, the Tapped event will always fire once. The control is no fortune teller: When the first tap happens, it does not know that a second tap will soon follow, so it fires the Tapped event. If you do not want this, you need to implement your own behaviour and either ignore or delay Tapped events.
MSDN:
If a user interaction also fires DoubleTapped, Tapped will fire first to represent the first tap, but the second tap won't fire an additional Tapped. If you want different logic for Tapped versus DoubleTapped, your Tapped handler may need to use app-specific variables and a timer in order to avoid running on interactions that are eventually interpreted as a DoubleTap action.
But using double taps is generally discouraged by the UX guidelines. I would not use them with buttons, because buttons usually do not work that way and you are breaking user expectations.

Related

How to force an NSWindow to be always active/focused?

I have a transparent NSWindow that follows the user's screen everywhere he goes (the NSWindowstays in front of every app, no matter what, even fullscreen apps).
In that NSWindow i have a mouseDown event that shows a popup. Let's say i'm on safari in fullscreen mode and i have my Window in front of it, i click on safari and i click again on my Window: nothing happens, the mouseDown doesn't occur. I have to click again so the mouseDown event is triggered.
How can i force my NSWindow to be always active so i don't have to click it 2x to trigger the mouseDown when i click on a background app and click in my window again?
Thank you!
I'm not sure if this is exactly what you want (it's not quite a window wide setting), but, from the documentation:
By default, a mouse-down event in a window that isn’t the key window
simply brings the window forward and makes it key; the event isn’t
sent to the NSView object over which the mouse click occurs. The
NSView can claim an initial mouse-down event, however, by overriding
acceptsFirstMouse: to return YES.
The argument of this method is the
mouse-down event that occurred in the non-key window, which the view
object can examine to determine whether it wants to receive the mouse
event and potentially become first responder. You want the default
behavior of this method in, for example, a control that affects the
selected object in a window.
However, in certain cases it’s
appropriate to override this behavior, such as for controls that
should receive mouseDown: messages even when the window is inactive.
Examples of controls that support this click-through behavior are the
title-bar buttons of a window.
Or you could try fiddling with
- (void)sendEvent:(NSEvent *)theEvent
and see if you can handle events in a custom way.
If you add a borderless NSButton instance to your window's view and set your image as the button's image (and as its alternate image, to make it more beautiful), it will work out of the box: Just connect the button's action method to your app delegate (or the object where you want to process the click action). A click on the image (i.e. the button) will then trigger the button's action method, no matter which window is active.
This worked for me, hope that will be helpful, This will keep your window always on Top of all applications
[self.window makeKeyAndOrderFront:nil];
[self.window setLevel:NSStatusWindowLevel];
I think what you really should do is use an NSPanel (a floating palette -- a special kind of NSWindow) that will do exactly what you want in a way that's consistent with the OS rather than trying to fight intended behavior.
Here's the NSPanel documentation:
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/nspanel_Class/Reference/Reference.html
And here's some helpful and pithy information:
http://cocoadev.com/wiki/NSPanel
By default, an NSPanel will disappear when the application is inactive, but you can turn this off.
I apologize for not laying it out more fully ... pressed for time.
Edit:
Note that you can probably get your window to behave as desired simply:
"The NSView can claim an initial mouse-down event, however, by overriding acceptsFirstMouse: to return YES."
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/EventOverview/HandlingMouseEvents/HandlingMouseEvents.html
You'll need to do this with any NSView subclass to skip the "activation click".

is there an event for holding a button

So of course there are events for UIControlEventTouchUpInside for button presses. But what I'm wondering is if you can tell when a button is held for a certain period of time?
There aren't any UIControlEvents that correspond to a long press but there is the UILongPressGestureRecognizer class that can be applied to any view object which will call back to a method via target/action when a long press is recognized.
UILongPressGestureRecognizer Class Reference
You can set up a timer when your button receives a touch down event. If the button receives a touch up event, invalidate the timer. If instead the timer fires, then the button has been held for your designated period and you can take whatever action you like in the firing method.
This is what I've done on OS X, where the situation is somewhat different. Letting the UIKit handle this via UILongPressGestureRecognizer, as suggested by Mark Adams, is probably the better idea.

How can I get the value of an NSSlider continuously?

It seems like NSSlider in Cocoa does not provide a delegate to receive an event like Value Changed for a UISlider.
How can I get the value of an NSSlider continuously and display it in an NSTextField, for example?
You need to research Cocoa's Target/Action mechanism. This is a basic Cocoa concept you'll need to understand. The slider (and any other control) can be given a target (some controller object) and an action (the method to call against that controller object).
The action is fired when the user stops dragging by default. Check the slider's Continuous property in Interface Builder to cause it to trigger the action as you're sliding it.
One advantage of using the timer approach is that it works for the case of using the keyboard rather than the mouse to adjust the slider. If the user has "Full Keyboard Access" turned on in System Preferences, they can use the Tab key to give the slider focus. They can then hold down an arrow key so that autorepeat kicks in, whereupon you have a similar situation to dragging with the mouse: the target/action is firing repeatedly, and you want to wait for a moment of calm before saving to the database.
You do need to be careful not to delete your NSTimer prematurely. For example, if the user quits the app during those couple of seconds you probably want to "flush" the slider value to the database before terminating the process.
Programmatical solution based on the answer of Joshua Nozzi:
Swift
slider.isContinuous = true
Objective-C
slider.continuous = YES;

Growl notification like nswindow level

I am writing a notification system just like growl. The notification is a window and it's level is set to NSModalPanelWindowLevel. The only problem is, I have a button in that window and when the user wants to click that button, he/she has to click it twice. But, for example, in growl, no matter what window you have opened, you just simply click the notification and it registers a click.
So is it a level problem? If so, what should I set it to? Thanks
In your custom controls that make up the view content of the window, you will likely want to override NSView's -acceptsFirstMouse: method to return YES:
Discussion
The receiver can either
return a value unconditionally or use
the location of theEvent to determine
whether or not it wants the event. The
default implementation ignores
theEvent and returns NO.
Override this method in a subclass to
allow instances to respond to
click-through. This allows the user to
click on a view in an inactive window,
activating the view with one click,
instead of clicking first to make the
window active and then clicking the
view. Most view objects refuse a
click-through attempt, so the event
simply activates the window. Many
control objects, however, such as
instances of NSButton and NSSlider, do
accept them, so the user can
immediately manipulate the control
without having to release the mouse
button.
Not sure if this is what Growl does, but you might be able to listen for mouse over events in the window and use them to activate/deactivate the window prior to the click. I suspect your issue is that the first click is being eaten by the activation of the window.
Just a guess on that though.
To learn how to handle mouse over events, check out this documentation:
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/EventOverview/TrackingAreaObjects/TrackingAreaObjects.html

NSButton raising click event on mouseup

I am looking for an NSButton raising the click event on mouseup, even if the mouse down has been made outside the button.
Do you have any idea to get this behavior?
Thanks!
Moving the mouse outside a control before releasing the button allows the user to cancel the action.
I would think the only way to do that would be to intercept all events and handle all click tracking and movement tracking yourself.
However, it would result in a very unexpected interface behavior, so you should consider carefully why you need to do that.