NSTableView early detection of edit session - objective-c

I've a NSTableView (view-based) whose delegate (my windowcontroller, in this case) needs to be notified as early as possibile of Text editing session starts.
I've tried with the Text Delegate method
- (BOOL)control:(NSControl *)control textShouldBeginEditing:(NSText *)fieldEditor;
but this not working in my case.
The event gets triggered (and the delegate invoked) if and only if i hit some key in the keyboard.
If, by any chance, i click outside the control without having typed anything, the edit session silently stops without notifying anybody.
Any help is appreciated.

#theAmateurProgrammer
Thank you for your suggestion. Well, what you suggest would do only in case of mouse events. Instead, i need to detect the start edit session event always, also in case of, for example, programmatically triggered editing.
However i've found the solution. I subclass the table view and then i override the validateProposedFirstResponder method.
The responder, actually, is the TextField which is about to start editing.

Related

Is there a way to disable sounds (such as "beeps") in my mac app?

I know I need to dig the reason why my app is beeping in the code, etc.
But I was wondering, is there a global setting to disable sounds all over my app screens?
this is very little information to go on, but usually your application is beeping when the responder chain comes up with no object that can respond to an event on the screen or keyboard.
For instance, if you type text in an active view and the view doesn't allow for text editing, the view sends the key down event to its super view. For a view this can end by the NSPanel or NSWindow or BSWindow controller. The last responder in the chain invokes the noResponderFor: method, which, when not implemented, will give a beep. If you don't want it to beep, override this method to do something else.
Based on your information I can't give you any other information.

Invoke NSTextField's action to be send when clicked ouside

I have a NSTextField that have been edited. If I press enter then action is being called as expected.
I would like to have the same effect when I click anywhere outside of NSTextField. Resigning First Responder could be the key, but that happens only when some elements are clicked/selected/focused (e.g. another NSTextField or NSTableView) and doesn't happen with others (e.g. NSButton or NSSlider).
NSTextField focus can be unset using [[self window] makeFirstResponder:nil] but that would be too ugly to call this line in every object's action.
Is there a better solution?
You will want to delve into the Cocoa Event Handling Guide.
Take a good look at NSResponder.
Many objects inherit from NSResponder, including NSWindow and NSApplication.
Taking a guess at what you are trying to accomplish, committing an edit when the view is not in focus, you may want to also include observing notifications when the app will terminate, go into the background, etc...

- (void)flagsChanged is not called for webview

I have created an editable WebView, and I am trying to write some code in
- (void)flagsChanged:(NSEvent *)theEvent
to detect, if the user presses the option key.
But if I type anything this method is not called. What might cause this problem and how can I solve it?
Have you checked that some other method is not getting the event?
In that case, you should send the event to the next responder, that probably will be your method.

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".

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;