I'm trying to set an attributed string in an NSTextView, and if the text is taller than the text view, the text doesn't show up at all unless you scroll the text box.
There aren't many posts about attributed strings in NSTextView, so maybe I'm just doing something wrong. Here's how I'm setting the text:
[[self.textView textStorage] appendAttributedString:attributedString];
You have to programmatically tell the NSTextView it has to make the new string visible:
NSUInteger length = [[self.textView string] length];
[self.textView scrollRangeToVisible:NSMakeRange(length,0)];
This should work independent of if the appended string is a "simple" string or an attributed string.
Call -beginEditing before making a series of changes to the text storage and -endEditing afterward. See Text System Storage Layer Overview: Changing Text Storage.
Related
I have an NSTextField to collect a format string, which is used to create some text that is then saved to a file. If I enter double quotes (") in the NSTextField, the string from NSTextField.stringValue is encoded as 0xe2 0x80 0x9d, which is unicode for double quotes. If I try to save the resulting string to a file, using NSASCIIStringEncoding, it complains that the encoding fails. Can I force NSTextEdit to use the ASCII character for double quotes, 0x22? I've tried lossy conversion:
[NSString dataUsingEncoding: NSASCIIStringEncoding
allowLossyConversion: YES]
but its solution is to remove the quote altogether.
I've tried changing the "Use smart quotes and dashes" setting in System Preferences --> Keyboard --> Text
While an NSTextField is being edited, it has an NSTextView subview that handles the actual editing. This subview is called the “field editor”.
NSTextView has an automaticQuoteSubstitutionEnabled property. You want to turn this off for the field editor.
You can do this by creating a subclass of NSTextFieldCell and overriding the setUpFieldEditorAttributes method. In Swift:
class MyTextFieldCell: NSTextFieldCell {
override func setUpFieldEditorAttributes(_ textObj: NSText) -> NSText {
super.setUpFieldEditorAttributes(textObj)
if let textView = textObj as? NSTextView {
textView.isAutomaticQuoteSubstitutionEnabled = false
}
return textObj
}
}
In your xib, select the cell of your text field and set its custom class to MyTextFieldCell.
By default, each window has a single field editor shared by all text fields in the window. So using this custom cell subclass will have the effect of leaving smart quotes turned off for all text fields in that window after that one text field has had keyboard focus. If that's not what you want, then you need to use a separate field editor just for the one text field that you want to be free of smart quotes.
To use a separate field editor for the special text field, you have two choices:
Create an NSWindow subclass. In the subclass, override fieldEditor:forObject: to return a separate NSTextView for the fields where you want to disable smart quotes, and return [super fieldEditor:createFlag forObject:object] for normal field.
Give your window a delegate (if it doesn't have one already). In the delegate, implement windowWillReturnFieldEditor:toObject: to return a separate NSTextView if the field (the client argument) should have smart quotes disabled. Return nil for other fields.
If you go with a separate-field-editor solution, you probably don't have to use a custom NSTextFieldCell subclass. You can just set the special field editor's isAutomaticQuoteSubstitutionEnabled to false before returning it.
I have a Cocoa app that shows a "quick search" window similar to Spotlight. The window contains a visual effect view and inside a NSTextField. The text field stretches across the full width of the window.
I would like to be able to move the window by dragging inside the empty area of the text field. When dragging across text in the text field, the normal editing (i.e. selection) behavior should be used instead.
In theory, moving a window by its background is easy:
window.isMovableByWindowBackground = true
However, this behavior does not work with NSTextField, because it intercepts dragging and attempts to select text instead.
Spotlight does it somehow. Here's an example:
A couple of options that I considered without success:
Tried overriding hitTest: returning nil
Tried overriding mouseDown|Up|Dragging: and forwarding to superview
Tried to use autolayout to have text field shrink to tightly wrap around its text (could not figure this one out)
For reference, I finally found a way:
Part 1: get NSTextField to grow/shrink with its content
Override intrinsicContentSize and measure its content:
private func measure(_ string:NSAttributedString) -> NSSize
{
let cell = NSTextFieldCell(textCell: stringValue)
cell.attributedStringValue = string
return cell.cellSize
}
Part 2: view setup
Add a placeholder view right after the text field
Set up auto layout to have the placeholder view to grow and shrink
Part3: all about the details
Set up the placeholder view to use the iBeam cursor to make it appear like a text field
If the user clicks in the placeholder view, make the text field the first responder
That's it.
I want to be able to highlight a portion of text in an NSTextField but I've not been able to Google a way of doing this.
I have defined an NSRange but I cannot find a way of using this range to highlight the text. The only thing I have turned up is textField.selectText but this supposedly highlights the whole field.
I'm using Swift 2.
You may have noticed that an NSTextField only shows a selection range when it has focus, i.e., is the first responder. In this case, editing is handled by an NSTextView called the field editor. So, make sure the field has focus (e.g., by using the makeFirstResponder: method of NSWindow), then use the NSControl method currentEditor to get the field editor, and then you can use the NSText method setSelectedRange:.
ObjC
NSText* fieldEditor = [myField currentEditor];
[fieldEditor setSelectedRange: mySelRange];
Swift
let fieldEditor = textfield.currentEditor()
fieldEditor?.selectedRange = range
First i need some background color on the text only. Like the headers in the F-Script Browser
Setting [cell setBackgroundColor: [NSColor blueColor]]; colors the whole cell space not only the text. Also i would need underlined and strikeout text. And to make things readable i would finally like to change the colors (foreground/background) of the selection on the styled items.
Can i do this with the default NSTextFieldCell ?
Nearly all of these things are jobs for NSAttributedString. As long as the text field cell has rich text enabled, it should accept an attributed string as its object value just fine.
As for the selection color, remember that an NSTextFieldCell is a kind of NSActionCell, and an NSActionCell is a kind of NSCell. NSCells have a method you can override to return a different highlight color. That covers the background; for the foreground, you may have to draw at least the highlighted portion yourself. You may be able to make good use of blend modes in that method.
I have a graphics app that uses a NSTextField instance for in-place text editing, this feature was added long time ago and I never had a reason to check it, however, I have recently received a report: text filed doesn't allow text formatting. Format -> Text menu subitems are all disabled, so there is no way to set the paragraph of a text item.
The question: how should I set up the NSTextField to support paragraph editing? I'm sure it did work before since I have some projects with formatted text and NSTextField was there since the app was born. Did I miss something with system/XCode updates?
My NSTextField is multiline, editable, allowed to edit text attributes.
If someone will face this in the future, I can describe the problem in details:
NSTextView refuses to apply formatting if there is no ruler used (with recent OS update, I suppose)
NSTextField itself does no text editing, it uses shared NSTextView instance driven by the owning NSWindow
Default text editor from the NSWindow doesn't use rulers.
This results disabled text formatting when using NSTextField.
Solution is to subclass the NSWindow:
#implementation MyWindow
- (NSText *)fieldEditor:(BOOL)createWhenNeeded forObject:(id)anObject
{
NSText* text = [super fieldEditor:createWhenNeeded forObject:anObject];
if ([text isKindOfClass:[NSTextView class]])
[(NSTextView *)text setUsesRuler:YES];
return text;
}
#end
And voila, formatting is back.