Drawing in NStextField - cocoa

If you wanted to implement a highlighting for specific substrings in a NSTextField like on the screenshot (Tweetie.app) how would you do it? :)
Tweetie Link Highlighting http://qkpic.com/88c61
Thanks for your help!

For an NSTextField, note that it's an NSTextFieldCell that does the drawing. You'll want to override -drawInteriorWithFrame:inView: and do the string drawing yourself. The challenge will be finding the rectangles (more than one if the range is wrapped) in which your substring is drawn. You'll end up having to use NSLayoutManager and an NSTextStorage container.
Best to use an NSTextView. The associated NSLayoutManager and NSTextStorage components are already pre-assembled and you get a lot of other functionality for free. Most importantly, there's a convenient -[NSTextView drawViewBackgroundInRect:] method so you don't have to subclass anything. You just ask the text view for its layout manager and text storage, then ask it for the rectangles for the given range. See the Text System Overview and linked documents for more details.
To find the interesting substrings efficiently, you might use custom attributes (or the built-in ones such as NSLinkAttributeName) for your interesting ranges.

An alternative to consider is an editable WebView where you can build the custom attributes with CSS.

Related

Custom drawing selection in NSTextView

I've got a NSTextView where I'd like to control drawing of the highlight/selection. Anyone know which method I have to overwrite so I can control what to draw in the selection rect?
You do not specify what you want to draw, so it's not easy to give you a straight answer.
If it's just an attributed string (Font, Style, Color, Background), you do not need anything fancy, just look for NSAttributedString. There are methods like -setSelectedTextAttributes: and the delegate method -textViewDidChangeSelection:
Generally, you should not subclass NSTextView if you don't have a very good reason to do so. You can do almost anything by just utilizing the usual delegation mechanisms.
If it's something very customized, there is a variety of possibilities depending on if you want to customize the selection (-setSelectedRange:) draw an overlay view (get the frame of the selectedRange) or mess around with the low level layout engine (-layoutManager). It really depends.
If you don't want to use the standard attributes to highlight text, eg by using an CALayer, you can get the rects containing the selection from the layoutManager of the NSTextView.

Text Field rendering

I am trying to build a really simple NSTextField with Interface Builder (XCode 4), but the rendering is really weird with default values:
The only setting I changed is the border style:
My question:
How to display a neat Text Field “squared but with rounded corners”, like in Safari:
How to remove that “overflow:hidden” (sorry for the CSS description) which cuts the focus? < Interface Builder bug, fixed.
Should I design my own, image-based component?
Thank you!
I think I've found exactly what you're looking for. Here's what it looks like:
It's called SSTextField. Download the subclass here: http://cocoatricks.com/2010/06/a-better-looking-text-field/
What you've got at the top is a NSSearchField, which is designed for filtering/searching.
Likely the reason why the focus ring is cut off is because you've got it inside a box or overlapping another object. Don't do that.
There are no standard rounded-corner (as opposed to rounded-end) text fields; if you want one, you'll need to subclass NSTextField yourself, or just wait for Lion where the standard text field will have rounded corners.
Rounded rectangle text fields are pretty straightforward and don't require subclassing the control. Instead you can simply override the way the background CALayer of the control is drawn.
Choose the square-cornered field shape, add the QuartzCore framework to your project, and then #import <QuartzCore/QuartzCore.h>. In your controller's viewDidLoad method you'll modify the text field's layer's cornerRadius property, a la:
myTextField.layer.cornerRadius = 6.0;
Poof, rounded-rectangle text field!

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

Links in NSTableView NSCell

I have been reading and experimenting with allowing links in a custom drawn NSCell for the last few days and have basically got nothing usable, there's always issues with each approach.
Does anyone know of a way of doing this that works?
I am custom drawing the NSCell using - (void)drawInteriorWithFrame:(NSRect)theCellFrame inView:(NSView *)theControlViewm
The NSCell is just a variable height block of text with links inside it, some cells have links, some do not.
I've tried using nsattributedstring with NSLinkAttributeName
I've tried intercepting all hits to the cell and then trying to match up where they clicked to where the link would be in the text but that never works out.
I've basically tried all suggestions that I could find on all boards but most comments are old so I'm hoping someone has figured out a good way to do this.
Thanks, David
I haven't tried this exactly, but give this a try:
First, for hyperlinks I use a category on NSAttributedString, akin to this post from Apple developer docs. The example here gives you a method on NSAttributedString 'hyperlinkFromString:withURL:`
Second, create a delegate for the table, and implement tableView:willDisplayCell:forTableColumn:row: method.
In that method,
setAttributedStringValue:[NSAttributedString hyperlinkFromString:YOUR_STRING withURL:YOUR_URL]
or, if you need non-hyperlinked string text as well,
setAttributedStringValue:[SOME_NON_HYPERLINKED_STRING appendAttributedString:[NSAttributedString hyperlinkFromString:YOUR_STRING withURL:YOUR_URL]]
If that is the only reason you are custom drawing an NSCell, you can try getting rid of your custom class, because this should work with an NSTextFieldCell. I've seen online, though, that some people have had trouble with centering attributed strings in text field cells, so I hope it works ok. One other caveat: with the delegate method, be sure that you set the cell attribute that you are changing for all conditions. I quote:
Because aCell is reused for every row in aTableColumn, the delegate must set the display attributes both when drawing special cells and when drawing normal cells.
from "http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/NSTableViewDelegate_Protocol/Reference/Reference.html" (sorry, StackOverflow won't let me post more than one hyperlink yet)
Hope this helps.

How do you create a custom themed NSButton?

How do you create a custom themed NSButton? I don't mean in a small way like changing the background color or changing from rounded edges to square edges. I want to replace the entire look and feel of the button. Is that even possible to do in Cocoa? Obviously I would have to subclass the NSButton class and go from there. Any help would be much appreciated.
Actually, you need to subclass NSButtonCell. You should read Apple's documentation on this to gain a better understanding of how they interact. You probably will still want to subclass NSButton so that it will use your NSButtonCell subclass, too.
For a button, most of the work is done in drawBezelWithFrame:inView:. If you want to alter the way the text or image is drawn, you would override drawTitle:withFrame:inView: and drawImage:withFrame:inView:.

Resources