Getting accented characters in a custom NSView - cocoa

In Mac OSX text views, it's possible to enter accented characters with a sequence of key presses (e.g. option-e e to get e-acute). Is there a way to access this functionality in a custom NSView. In my case I have class derived from NSOpenGLView. I've implemented a responder for keyDown: so I can get the unicode characters that come from a single press, but with the sequences I just get events for the individual presses. I hoped that interpretKeyEvents: from NSResponder would help but it doesn't seem to.
I could implement it myself by copying what NSTextView does but I imagine it will be tricky, especially if people use a different keyboard setup to mine.

Calling interpretKeyEvents: is the right way to go, but you need to also implement other methods that will notify you when marked text (which I always called 'in progress text') or text to be inserted arrives in your view.
Your NSView must implement NSTextInputClient. See the Cocoa reference here. A search for some of the methods in that protocol found this chunk of code on github. which looks like a very good starting point.
For what you're asking for, it will be sufficient to test with English and at least one other Western language (French is a good one). But longer term, you'll also want to test with at least one of the Kotoeri and Hangul layouts. The code I linked to above, however, looks like it will handle the vast majority of text you can throw at it.

Hhhmm.. that sounds pretty tricky.
NSTextField does some pretty similar things as it does not have its own editing facilities but rather delegates them to the parent window's "field editor" which is an instance of an invisible NSTextView. You also get a lot of the NSTextView behavior without a window in NSText.
It might be worth checking how NSTextFields delegate to the field editor and see whether you can hook yourself into the field editor in the same way rather than doing your keyDown: events.
Another possibility could be to create an invisible NSTextView and delegate each key press to it and then display the NSTextStorage associated with it in your own view.
It sounds like you are in for a bit of pain, but that's what I would start by exploring.
Of course, I'm no Cocoa Text Subsystem wizard..
I hope this helps.

Related

Adding controls to NSTextView and binding them to (ranges of) characters

When editing code, Xcode is capabale of displaying in-text controls, like drop down buttons which can show context menu's. I've seen other OS X apps that handle text capable of similar features. See the attached sample.
I presume this effect is obtained using NSTextAttachmentCell - although I'm not sure whether this is the proper way to implement this.
For my own app I would like to use this technique as well.
I have the following questions:
Is NSTextAttachmentCell the correct way to implement such a feature? If not, what would be?
How do I attach a control -comparable to the one in the above sample- to a specific range of text so that its location within NSTextView is dynamic and follows layout actions?
I found this which gives some hints but does not cover the attachment to specific text ranges.
Although NSTextAttachmentCell will work, it has a disadvantage: the cell will become just a glyph in the text which was not what I wanted. It distorts the layout of the text, is selectable etc. I wanted the cell to be drawn over the text, just like the behaviour in Xcode.
The challenge was to find a way of translating a point from a Mouse Moved event to the position of a particular string of characters inside the NSTextView.
After some more digging I found a little gem in Apple's demo apps called LayoutManagerDemo. This demo shows a custom subclass of NSTextView capable of highlighting individual characters, words and lines while the mouse is hoovering its view. From there on it was pretty easy to fade in a button at the required NSPoint and then show a popup menu with some options.

NSButtonCell vs NSButton

I've been reading through the Apple documentation about NSButtons and cells and I really can't seem to understand the distinction between the two. Adding to this complexity, it looks like both of them have a large overlap of methods like setTitle: etc. and I'm not sure which ones I should use.
Can anyone explain what the basic differences are?
Thanks,
Teja
You can think of a control as a cell's representative, or "agent".1 The control is an NSView, which means two important things in these circumstances. First, that it represents an area of a window to be drawn in. Second, that it accepts user interaction.2
The control doesn't do very much itself, though. The cell is the thing that does all the work -- notice, for example, that cells can draw themselves into a given frame. This is the responsibility of a view, but the control defers that to the cell, simply providing an area for drawing.
Likewise, when a user clicks on a control, the control receives the event and figures out what it means, but the work of performing an action in response to the event is passed on to the cell.
If you look at the docs for various control/cell pairs (NSButton and NSButtonCell being one such pair), you will see mention of "cover" methods. This means that the control has methods with the same names as its counterpart cell, which simply call through to the cell's. That's the source of the duplication that you mentioned. When you want to use one of these methods, call it on the control -- as the public face of the pair, it will most likely simply ask the cell anyways.
The best Apple-provided description of the interaction is "How Controls and Cells Interact" in the Control and Cell Programming Topics guide.
1In the sense of a actor having an agent who procures gigs.
2This is not strictly true of all views; it's actually a feature of NSResponder from which NSView inherits.
Excerpted from Cocoa Programming for OS X: The Big Nerd Ranch Guide
“A cell handles the implementation details of the control. For the
most part, the cell’s properties and methods are “covered” by
identical properties and methods in the corresponding control. For
instance, when you change the title on a label, the label’s cell is
doing the work, but you interact with the label’s stringValue
property.
Cells have a long history in Cocoa. They were originally
added to address performance issues: many of the basic tasks of a
control were handed off to the cell, which could do them more
efficiently than the control.
Mac computers are much more powerful
than they were in those days, and cells have become an encumbrance.
Apple has stated that it is in the process of deprecating cells, but
you will still see them in your document outline and in older code.”
NSButtonCell is a subclass of NSActionCell used to implement the user interfaces of push buttons, switches, and radio buttons. It can also be used for any other region of a view that's designed to send a message to a target when clicked.
The NSButton subclass of NSControl uses a single NSButtonCell. To create groups of switches or radio buttons, use an NSMatrix holding a set of NSButtonCells.
NSButton Cell has alot more cutomizable options for drawing and behaviour. The differences are better seen in the classes they inherit from (NSButtonCell inherits from the ActionCell class, while the NSButton inherits from the NSControl class.
Take a look at the documentation better:
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSButton_Class/Reference/Reference.html
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSButtonCell_Class/Reference/Reference.html
You should choose based on how you want the buttons to be drawn and behave. If its a simple button you want, use NSButton.

Implementing custom NSView in Cocoa on OS X

I am creating a Cocoa application wherein one view will contain the "hex dump" of the currently loaded document. Up until this point, I have been using a bog-standard (and very unappealing) NSTextField, but I am now looking for something more powerful.
I am a great fan of 0xED.app and would love to replicate its main "hex dump" view. How would I go about doing this?
I'm not necessarily after the eye-candy, but the ability to select a range of bytes without also selecting the offset or text columns. I am a loss as to where I would even begin to implement this effectively. Surely this is not drawn upon a blank canvas?
To get started and see how things basically work:
Subclass NSView.
Add an instance variable to hold your NSData.
Override drawRect:
Iterate your NSData
Use methods from NSString drawing AppKit additions to draw the bytes.
This approach will be slow for a large amount of data, but will give you a good handle on implementing a NSView subclass. After that, you'll want to improve the drawing performance by implementing something better than repeated calls to draw strings one at a time. You'll also want to implement overrides of methods like mouseDown: and keyDown: to handle input from the user to allow things like selecting a range of bytes.
That should get you started, once you have that going, I'd suggest asking follow up questions.
My guess is that it's probably accomplished using a NSTableView or subclass of it.
It might be a little tricky to get the correct text selection accomplished this way, but it's probably possible.
If you want to take a look at how a Cocoa interface is built you can use NibToXibConverter.
Download 0xED, right click on 0xED.app and select "Show Package Contents". Extract the Contents/Resources/English.lproj folder.
Run NibToXibConverter, browse to the folder extracted above, and put a tick next to "Decompile NIBs".
Select the "Convert" button and it will convert the NIBs to XIBs
Double click a XIB to open it in XCode and you can see how they are constructed
You will note that in the case of 0xED he is using a custom class (most likely a subclass of UIView with custom drawing as Jon Hess suggests).

How to get notification whenever a character is inputted into NSTextField?

I'm a little rusty on my Cocoa, so bear with me on terminology and such.
I want to write something that is essentially a reverse spell checker. As in, if a word is spell correctly, then for random words it changes it to a misspelled version. Harmless prank to play on someone.
So then, my main hitch is that I have no idea how to do this (major problem, I know). I like the way that textedit performs on-the-fly spellchecking, but I'd like to incorporate that sort of behavior into the generic behavior of the NSTextField. Is there some way for an application to be notified whenever a character is input into an NSTextField?
EDIT: My aim is to make this system-wide, as in any NSTextField in the system would get this behavior as a matter of inheritance. I'm open to some serious hacking here.
To answer your question: attach a delegate to the NSTextField control, and implement
- (void)controlTextDidChange:(NSNotification *)aNotification
Note that NSTextField uses the shared field editor to edit text, which is a NSText object. You might be able to manipulate that to do what you want.
I like the idea! This should be fairly easy to do. First you have to decide if you want to use NSTextField or NSTextView. TextEdit.app uses NSTextView which is appropriate for more extensive word processing-type tasks. NSTextField is more for smaller, minimally-formatted chunks of text. There's lots of ways to tackle this, but I'll give you a couple.
For NSTextField, set your controller object to be the delegate for the text field and override the controlTextDidChange: method. Whenever the user types a character into the text field, you'll get this message. You can then modify the field's string to introduce the misspelled word.
For NSTextView, you can activate spell checking and use the text view's delegate method textView:didCheckTextInRange:types:options:results:orthography:wordCount:. You should be able to modify the results of the spell check.

Cocoa: What NSTextView the insertion point is currently blinking in?

Given an NSApp object (aka [NSApplication sharedApplication]), how can I get the currently active NSTextView, where the insertion point is blinking right now (if there is one)? :-)
I can go [[NSApp keyWindow] contentView] and try traversing the whole view hierarchy, but that seems too hard. Ideal code would be: [NSApp focusedTextView].
I tryed firstResponder for an app and a window, and also fieldEditor:forObject:, but this does not return anything interesting (at least, to me).
By the way, if anybody knows how to get the system wide current text view, that would be even cooler (Accessibility APIs won’t work: it won’t return a Cocoa NSTextView).
Thanks
The -firstResponder function returns the field editor. So if you want the real view you might need to check the first responder's delegate to get to it. Also see field editor for details.
There is probably no way to get it system wide as a NSTextViews since that object is in general in a different process space.
By the way, if anybody knows how to get the system wide current text view, that would be even cooler (Accessibility APIs won’t work: it won’t return a Cocoa NSTextView).
Not possible. NSTextViews are per-process; you can't get a proxy to an NSTextView from another process without that other process serving it up through an NSConnection. You're just going to have to use Accessibility.
On the bright side, using Accessibility means your app should (in theory) also work with Carbon apps that use MLTE/HITextView.

Resources