How do I set primaryActionTriggered for a custom UIControl? - uikit

I've created a custom UIControl. The closest comparison is a UIStepper but it is a subclass of UIControl because its wholly custom.
For most UIControls you can create target actions with primaryActionTriggered to avoid needing to know which action matters. I want the same convenience for my custom UIControl. So how do I map UIControl.Event.valueChanged to UIControl.Event.primaryActionTriggered?

I think if you are listening for the valueChanged event then you just need to manually call sendActions(for: .primaryActionTriggered) when that event fires

Related

gwt canvas- handling events altogether differently

Gwt HTML5 Canvas wrapper can responds to mouse and keyboard events, it binds to 5 - 6 types of different events, my question is, it is possible to define entirely new event system such as CanvasEvent (and related handler CanvasEventHandler extends to GwtEvent etc), bind this to canvas object and then handle all events differently using a handler interface methods will be something like onDraw(), onDrag(), onMove(), onSelect() etc.
I dont have good clarity of GWT event system but i want to know is this possible without individuality attaching separate event handlers to form a logic for handling my problem, can I access all possible event as one consolidated object and fire custom event based on conditions. What would be the best way to do it, there are threads with GWT custom events but they include senders, whereas in my case sender is already present (Canvas)
Thanks much
Certainly - remember that all of the GwtEvent objects are completely artificial and are based off of events fired from the native JavaScript. That JavaScript event object, (which comes in via onBrowserEvent) gets wrapped up as a ClickEvent or a KeyDownEvent based on the details of the original object, and then fired off via the internal HandlerManager instance. In the same way, you could listen for a MouseDownEvent, set some state, then if a MouseMoveEvent occurs, fire your own CanvasDrag event. You'd probably stop listening to those move events once a MouseUpEvent happens, then you would issue something like a CanvasDropEvent. If isntead the MouseUpEvent occurred right away with no move, you could trigger a CanvasSelectEvent (or you might have something else in mind for that select event).
Each of these new event types you declare then might contain specifics about whatever is going on. For example, while a MouseMoveEvent just has the element that the mouse is over and the x/y coords, you might be indicating what is being dragged around the page. That might be in the form of the shape that was last clicked, or even the data it represents.
Yes, the 'sender', or source, is already there, but it'll be easier to use if you expose some kind of a method to add handlers like addCanvasDragHandler, etc. This is not required - all users of your code could just use addHandler, but it does make it a little ambiguous about whether or not the widget supports the event in question. You would then call fireEvent on the canvas object to make all handlers of that event type listen.
Or, you could make a new class that contains an internal Canvas widget - possibly a Composite object or just something that implements IsWidget (Canvas has a private constructor, so you can't subclass it). This would enable you to add your own particular handlers, and keep your own HandlerManager/EventBus to track the events you are concerned with.

Move controls with the mouse in Cocoa

I want to build a simple forms designer in Cocoa and need to move controls around on a form using the mouse (click, hold, move around, release).
Do I need to inherit new classes from all control classes to intercept those events ? Is there a way to implement it generically for any control?
One way might be to have a single large custom view that fills all the space the controls will be in. Implement the necessary methods to implement mouse events in this view, doing hit detection on the control views and moving them around. This approach requires only 1 custom subclass of NSView, and you can use any views or controls you want to move around without subclassing them.
Write a custom view to contain the controls. Override -hitTest: to ignore the controls and return self instead. Then when you receive mouse events, figure out which control they apply to and move as appropriate.

Whats the appropriate way to react to the delete key in an NSOutlineView

I want to remove an item from my NSOutlineView when the user presses the delete key. Is the only way to do this to over-ride the keyUp method of NSResponder? I was hoping for higher level solution.
Its possible to do this without subclassing. Set the NSOutlineView's nextResponder (using -setNextResponder:) to your controller. In the controller class you can override -keyDown: (or -keyUp: and then handle the event in your controller class.
As of 10.10 you don't need to subclass the view to override keyDown(_:) or keyUp(_:). This is because NSViewController inherits from NSResponder and is now automatically added to the responder chain. This means you can override the methods in your view controller subclass instead which is often more convenient.
I think that overriding -keyDown: or -keyUp: in a subclass is the only way to do this.

Accessing the controller in a Cocoa application

I'm beginning to think that my Cocoa application is not really done according to the principles of MVC. My problem is the following:
I have some classes in my project, one of called Copier.h and another called DropReciever.h. Copier is sort of my main view controller, as it has all the bindings and main methods. DropReciever is a custom implementation of an NSView to allow the app to accept files via drag and drop.
Now, is there an easy way to send messages to Copier from DropReceiver? Right now, the two don't know each other, and I can't think of an elegant way to connect them, since since they are both kinda instantiated seperately. How can I make them see each other? Or, is there an elegant, Coca-ish way to do this better?
(If you want to look at my source code, it's here.)
Another way would be to expose a property of the drop receiver as a binding, and bind the copier to it (programmatically). Then, in the drop method, have the drop receiver set the dropped content as the value of this property (which you would name something like droppedObject).
When you set the property, the magic of Bindings will set the bound property of your copier. The copier can react appropriately there in its setter method.
I would have a delegate property on the DropReceiver. Whatever is responsible for tying these things together would set the delegate. The delegate object can be an id, or you could create a protocol for it (both idioms are common in Cocoa). I do this all over the place. You get the separation you need, without having to work around the houses too much.
The only downside, if you don't set the delegate on initialisation, is that all your calls to it need to be protected by if( delegate ) checks.
The way I usually do it is to instantiate DropReceiver in the nib and then add an IBOutlet DropReceiver * to your Copier.h, then drag a connection from the Copier instance to your DropReceiver in the window

How to get notifications of NSView isHidden changes?

I am building a Cocoa desktop application. I want to know when a NSView's isHidden status has changed. So far using target/action doesn't help, and I can't find anything in NSNotification for this task. I would like to avoid overriding the setHidden method, because then I'll have to override all the NSView derived class that I am using.
UPDATE: I ended up using KVO. The path for "isHidden" is "hidden", probably because the setter is "setHidden".
You could use Key-Value Observing to observe the isHidden property of the NSView(s). When you receive a change notification from one of these views, you can check if it or one of its superviews is hidden with -isHiddenOrHasHiddenAncestor.
A word of warning: getting Key-Value Observing right is slightly tricky. I would highly recommend reading this post by Michael Ash, or using the -[NSObject gtm_addObserver:forKeyPath:selector:userInfo:options] method from the NSObject+KeyValueObserving category from the Google Toolbox for Mac.
More generally, one can override viewWillMoveToWindow: or the other related methods in NSView to tell when a view will actually be showing (i.e. it's window is in the window display list AND the view is not hidden). Thus the dependency on KVO for the 'hidden' key used above is removed, which only works if setIsHidden has been called on that view. In the override, 'window' (or [self window]) will indicate whether the view is being put into a visible view hierarchy (window is non-nil) or being taken out of it (window is nil).
I use it for example to start/stop a timer to update a control from online data periodically - when I only want to update while the control is visible.
Could you override the setter method for the hidden property so that it will trigger some custom notification within your application?

Resources