NSTextField Key Interface Control (KIC) behaviour - objective-c

Background: I have a custom derivation of NSTextField that I am trying to use as a cell in a grid similar to a spreadsheet.
I have set the nextKeyView of my NSTextField and am confused between two states that the NSTextField can have BOTH of which involve it having the blue focus-ring drawn around it:
the cursor is blinking in it => in this case the TAB key behaves as expected and moves to the nextKeyView and it is in a "text accepting" mode
it has not quite "entered" the text field for the purposes of text editing => the TAB key does not respond with KIC behaviour and move to the nextKeyView and trying to enter any text just in fact results in the following:
-[NSEvent key]: unrecognized selector sent to instance 0x60800012bf40
From background reading and a bit of debugging it appears that the first state corresponds to control/focus being handed off to the window's shared text editor and the custom NSTextField actually loses firstResponder status in this process.
What's interesting is how this differs from the behaviour of two standard NSTextField controls dragged onto an NSView in Interface Builder. Running such a simple app only the first state above is present at all as you tab from one NSTextField to the other! I am glad to have the intermediate second state in my app (because I need it) but I don't understand why it is happening...
Summary: two related questions
How do I programmatically control the NSTextField entering these two states of effectively accepting text and not while it has the focus [I do not know how to achieve this at all so this is my main problem...]
How can I get the KIC behaviour in the situation where the NSTextField has the focus but is not in "text editing" mode since this is the behaviour I am trying to get. [My current conclusion is that KIC does not work in this situation and that standard practise would be to resort to the regular overriding of keyDown for the set of keys that would normally be associated with KIC.]

Related

Handling tabs in Cocoa view containing a text field and scrolling view

In my Cocoa app, I have a window that contains an NSTextField (as is) and an NSScrollView (sub-classed). I've got an NSViewController that manages the window's NSView containing the text field and scrolling view.
At app startup, the NSTextField has focus, and typing enters characters into that text box. When I hit the TAB key, it loses focus. But nothing else in the interface, like the NSScrollView, gains focus. I can't tell where any key down events are going.
How does one transfer focus to the NSScrollView, so that key down events can affect it (e.g., arrow keys, implicit searching, etc.)?
First, you should try hitting Tab repeatedly to see if focus ever makes it to the scroll view or comes back around to the text field.
You don't say what's in the scroll view as the document view. Rather than having the scroll view itself accept focus, it's more common that the document view or one of its descendant views accepts focus. Then, the movement keys would be delivered to that and, if nothing consumes them, they'd bubble up the responder chain to the scroll view and it would handle them automatically.
If you really want your scroll view to accept focus, you need to override the -acceptsFirstResponder method to return YES.
The behavior of Tab is governed by the window. It maintains a key view loop. It can automatically recalculate the key view loop as views are added and removed. That's probably the most reliable way. See the autorecalculatesKeyViewLoop property.
Alternatively, you can manually tell it to recalculate as you desire, by turning off autorecalculatesKeyViewLoop and calling -recalculateKeyViewLoop.
Or, you can explicitly set up the key view loop yourself by connecting each view's nextKeyView and previousKeyView properties, either in code or in Interface Builder.

How can I make command-A select all the NSTextView text in rows in an NSTableView?

So if I have an NSView based tableview and inside the views are NSTextViews which are non-editable but selectable...
how can I get that nice functionality of command-A selects all the text? I don't mean row selection. I have row selection disabled for the tableview. I mean highlighting the text in blue so you can copy it to your clipboard. But not just 1 NSTextView's text from one row, all of them from all the rows.
And in addition to command-A click and drag should do this too. But out of the box it seems I can only select one row's text. Here is video showing problem:
https://dl.dropboxusercontent.com/u/2510380/table.mov
(i keep clicking and dragging but can't highlight text on the next row)
here are two mac apps (skype and gabble) that do this:
https://dl.dropboxusercontent.com/u/2510380/skype.mov
and
https://dl.dropboxusercontent.com/u/2510380/gabble.mov
Assuming they are NOT using WebViews with just HTML inside, how do you get this control over the clipboard? i.e. in Skype you select the text and only the conversation is highlighted, not the timestamp of each message. Also the text copied to the clipboard is formatted very nicely. Can you point me in the right direction to reverse engineer skype?
Unfortunately there's no way to do this easily. This is because only ONE control can be the first responder at a time. This means that, though you can have selection in multiple text views, there are several problems:
Only one text view's text will actually be highlighted with the "live" highlight color; the others will have the gray highlight of non-focused controls.
Copy commands will only apply to the first responder text view.
Drag session starts will be initiated from the control the mouse was actually pointing at (irrespective of first responder) and will only drag that control's text.
In a view-based table view, the controls may not even "exist" for a row not currently displayed, so it'll never get the message unless you forcibly create each row, which could be costly for a large table.
Knowing all this, you might be able to "fake it" by having your controller be complicit in a text view and table view subclass's special handling of a select-all message when it's first responder. On receiving this message, the text view subclass can call super then notify the controller (to get its default behavior AND to let you know it happened), at which point the controller can turn around and send the command to all (existing) text views. Highlighting can be spoofed by overriding the text view's drawing and a drag initiation could defer to a delegate (the controller), which would handle writing ALL the strings from your model to the pasteboard (not even touching the text views in possibly-nonexistent row views). The table view subclass would simply pass the same select-all message to the controller without calling super (and even forcibly making sure nothing is selected before returning for good measure).
I hope this helps. If I've forgotten any of your requirements, let me know.
Try like this:-
First create button programatically then write this code after you create button and also write this code in your load method or awakefromnib method.
NSButton *Buttn=// alloc initwithframe;
[Buttn setKeyEquivalentModifierMask:
NSCommandKeyMask];
[Buttn setKeyEquivalent:#"A"];
[Buttn
setAction:#selector(yourmeth:)];
[Buttn setTarget:self];
// now when you press cmd a write
below code in action method
- (void)selectRowIndexes:(NSIndexSet
*)indexes byExtendingSelection:
(BOOL)extend

NSTextField click-through?

I have a static NSTextField that overlays a large error message in my OS X app. I'm trying to get it to allow the user to click controls beneath it.
In IB I've unchecked "enabled" and I've checked "Refuses First Responder"
I've also done it in code because that wasn't working:
[largeErrorText setEnabled:NO];
[largeErrorText setRefusesFirstResponder:YES];
Still, it is getting in the way of interacting with the objects below it. Any ideas what else it might be?
The only way I have found to make an object transparent to the click is to subclass that object (in your case the NSTextField) and override the hitTest method returning nil. This way that NSTextField will not respond to the click so the NSView below will respond to the click.
- (NSView*)hitTest:(NSPoint)aPoint
{
return nil;
}
I assume you are describing a scenario like the following image shows:
The inner red rectangle is the frame outline of the NSTextField label, and you're saying that even though you've disabled the text field and set refuses first responder, your clicks do not go through to the NSButton?
This design scenario describes a condition called "Overlapping sibling views". I would generally try to avoid this if at all possible. If you can't, you can get the desired behavior by making sure that the NSTextField label is "behind" all of the other UI objects that you want to be able to interact with. You can do that by selecting the label and choosing Editor > Arrange > Send to Back. That will assure that the button is in front of the text field so that it can properly intercept mouse events.

Modify multiple NSTextView with commands

I'm wondering if anyone knows if it is possible to modify multiple NSTextViews with a menu bar command. For example if the user selects "Bold" from the menu bar, the different NSTextViews that are selected update all their content to show bold.
Here is the set up I have:
#interface MyCustomTextField : NSView <NSTextViewDelegate>{
NSTextView *textView;
BOOL selected;
...
}
So basically I have my own custom class and within each custom class I have a NSTextView, a var determining whether or not this view is selected and some other stuff.
I'm able to select multiple fields however from what I've read on Apple documentation every NSTextView in the window shares one field editor. When a user edits a NSTextView they are actually sending commands to the field editor which processes it and routes it to NSTextView. If this is the case does that mean that I need to create my own custom field editor and route the commands to all my custom selected text classes instead?
==edit==
My CustomTextField classes have a variable named "selected" (see above) and by holding the shift or apple key down I'm able to "select" multiple CustomTextField instances (I put a mask in front of the NSTextView instances which catches the mouseDown message).
So by this selection, multiple instances have their "selected" attribute set to true. As far as the first responder for the window, it would be set to the mask that shows the blue halo around all the NSTextViews.
I'm wondering if I can tell the app to accept default NSTextView commands (such as bold, italicize, etc.) and that if I supply a custom field editor, it will pass all the appropriate messages to the selected CustomTextFields which will then pass it on to the NSTextViews.
In my head the message would be passed like this:
User Submits Text Toolbar Command > Custom Field Editor > MyCustomTextField > NSTextView
Hopefully my explanation made sense or maybe I'm in LaLa land now.

Changing focus from NSTextField to NSOpenGLView?

I am developing an interface for an OpenGL Simulation on the Mac using Interface Builder. All OpenGL stuff is being written in C++ (which I know fairly well). Unfortunately I have no idea about Objective-C.
Basically, I have a few NSTextField displaying info on an object selected on the Screen. Using these textfields the user is the able to manipulate the object on screen and then there is a Save Button and a Restore Button (which either save the new values or restore the original ones)
I have this all working. My problem is when I enter data into an NSTextField the "focus" of the windows seems to remain on the NSTextField (blue border remains around it).
I use the keyboard to interact with items within the NSOpenGLView, I need to pass the focus back to the NSOpenGLView when I hit either the Save or Restore buttons.
Sorry if this is a very straightforward question
Thanks
David
Have you tried using NSWindow makeFirstResponder method to make your NSOpenGLView the first responder?
Just managed to get it working.
I had to add the line:
[[NSApp keyWindow] makeFirstResponder: MyOpenGLView];
to the end of the function being called when I click on either of my buttons.
(Thanks Julio for pointing me in the right direction)