How do I limit NSTextView to 2 lines? - macos

I'm trying to specify the number of lines for NSTextView. My designer is requesting 2 lines of text max. I've tried NSMutableParagraph style to add the ellipses truncation that I want, but with NSMutableParagraph I can only get NSTextView with 1 line and without NSMutableParagraph, I get a scrolling text with as many lines as needed to complete text.
var attributedString = NSMutableAttributedString(string: "This is my text, I can keep going for many characters")
var para = NSMutableParagraphStyle()
para.lineBreakMode = NSLineBreakMode.ByTruncatingTail
let globalAttributes = [
NSParagraphStyleAttributeName: para
]
let range = NSRange(location:0, length: attributedString.length)
attributedString.addAttributes(globalAttributes, range: range)
cellView.myTextView!.textStorage?.setAttributedString(attributedString)
I've tried height constraint on NSTextView. I've tried:
cellView.myTextView!.textContainer?.containerSize = NSMakeSize(300, 32)
I've tried creating IBOutlet for NSScrollView that NSTextView in within and adjusting its height. No luck with getting both 2 lines and truncation. Any help is greatly appreciated. I feel like I'm just missing a method or setup. Thanks!

From 10.11 you can use this
yourTextViewObj.textContainer.maximumNumberOfLines = 2;

You can use an NSTextField configured as a multi-line label. That means setting its cell's wraps property to true and, if desired, its truncatesLastVisibleLine to true.

For NSTextField (aka label) You can just do self.textField.maximumNumberOfLines = 2;
That's it.

Max number of lines is now a property of NSTextField
label.maximumNumberOfLines = 1;

Related

NSTextField font styling resets when selected

Context:
In Interface Builder I have a non-editable label (NSTextField). The contents of the label is created using Cocoa Bindings. The value of the binding is an NSAttributedString (created using a talue transformer). See image:
The value transformer essentially specifies the font for specific characters, as per Markdown formatting (i.e. Italic and Bold). Such that String --> NSAttributedString. The label's attributedStringValue is changed appropriately
Issue:
When selecting the label in the UI. The font resets to what is specified in IB, and not what was set as the NSAttributedString. If you don't select the text then everything looks good.
Before clicking on the label:
After clicking/selected the label:
Attempted Solutions:
I've tried subclassing NSTextField but there's nothing really to override that enables me to disable any font changes when the text is selected.
I've tried disabling rich text. This actually helps a lot by not changing the normal text, but it still strips the formatting from the bold and italic text
Most similar issues out there are with NSTextViews not NSTextFields
You need to set allowsEditingTextAttributes = true
For example:
class ViewController: NSViewController {
dynamic var markdownText : String?
#IBOutlet weak var label: NSTextField!
override func viewDidLoad() {
super.viewDidLoad()
label.allowsEditingTextAttributes = true
}
}
Then you can select text as in my example:
Here is the code:https://github.com/emankovski/BindingFormattedText
I believe I found the solution to this issue, which seems unsolved based on the original poster's comments above.
I had an NSTextField that was selectable but not editable. The text was set by creating NSAttributedString with font and text color attributes, and passing this to the NSTextField's setAttributedStringValue method.
The problem as that the line spacing of the text was wrong until I clicked a text field and then clicked a different text field, as shown in the GIF below. Once the clicking was done, the text displayed properly.
Upon examining the text attributes of the NSTextField before and after editing, I noticed that NSOriginalFont was set to .AppleSystemUIFont 12pt instead of my font, which was Helvetica Neue 11pt.
BEFORE
NSFont = "\"HelveticaNeue 11.00 pt. P [] (0x600000e46400) fobj=0x1040163d0, spc=3.06\"";
NSOriginalFont = "\".AppleSystemUIFont 12.00 pt. P [] (0x600000d8f0f0) fobj=0x10361b1a0, spc=3.39\"";
AFTER:
NSFont = "\"HelveticaNeue 11.00 pt. P [] (0x600000e46400) fobj=0x1040163d0, spc=3.06\"";
NSOriginalFont = "\"HelveticaNeue 11.00 pt. P [] (0x600000e46400) fobj=0x1040163d0, spc=3.06\"";
I solved the problem by setting the NSAttributedString's font attribute not only NSFontAttributeName (i.e., #"NSFont") but also #"NSOriginalFont".
[controlText removeAttribute:NSFontAttributeName range:(NSMakeRange(0, len))];
[controlText addAttribute:NSFontAttributeName value:font range:(NSMakeRange(0, len))];
[controlText removeAttribute:#"NSOriginalFont" range:(NSMakeRange(0, len))];
[controlText addAttribute:#"NSOriginalFont" value:font range:(NSMakeRange(0, len))];
Swift 5 solution
First you need to set this property for your NSTextField
cell.textField?.allowsEditingTextAttributes = true
Then, where you are creating the NSAttributedString, do this first
// Default font and color, to be used where no attritubes are set
let default_font = NSFont(name: "Courier New", size: 14)
let default_color = NSColor.white
let entire_str_range = NSMakeRange(0, text.string.count)
mutable_attr_str.removeAttribute(NSAttributedString.Key.font, range: entire_str_range)
mutable_attr_str.addAttribute(NSAttributedString.Key.font, value: default_font!, range: entire_str_range)
mutable_attr_str.removeAttribute(NSAttributedString.Key.foregroundColor, range: entire_str_range)
mutable_attr_str.addAttribute(NSAttributedString.Key.foregroundColor, value: default_color, range: entire_str_range)
mutable_attr_str.removeAttribute(NSAttributedString.Key(rawValue: "NSOriginalFont"), range: entire_str_range)
mutable_attr_str.addAttribute(NSAttributedString.Key(rawValue: "NSOriginalFont"), value: default_font!, range: entire_str_range)
Then set up your NSAttributedString however you like. When clicked, it should keep your additional attributes, and the parts of the string with no attributes will default to the above font and color.

How can I set NSTableView column to use monospaced numbers?

El Capitan introduced San Francisco system font, which has proportional digits by default.
This makes numbers in table columns look jagged and hard to compare:
I'd like to enable fixed-width numbers option for the font, but keep using the default system font and keep backwards compatibility with earlier versions of OS X.
In Interface Builder selecting font > Font Panel > Typography > Monospaced Numbers does not affect the font (XIB file remains unchanged).
What's the right way to set monospaced numbers in OS X table view columns? (I suspect IB is unusable for this, so a programmatic solution is OK too).
Just use +[NSFont monospacedDigitSystemFontOfSize:weight:] when it's available. It's new in 10.11, but still not in the NSFont docs. It's in the headers and was discussed in the WWDC 2015 videos. So, something like:
if ([NSFont respondsToSelector:#selector(monospacedDigitSystemFontOfSize:weight:)])
textField.font = [NSFont monospacedDigitSystemFontOfSize:textField.font.pointSize weight:NSFontWeightRegular];
Here's a Swift extension that gives you a monospaced digits font with high legibility.
extension NSFont {
var legibleNumbersVariant: NSFont {
let features = [
[NSFontFeatureTypeIdentifierKey: kNumberSpacingType,
NSFontFeatureSelectorIdentifierKey: kMonospacedNumbersSelector],
[NSFontFeatureTypeIdentifierKey: kStylisticAlternativesType,
NSFontFeatureSelectorIdentifierKey: kStylisticAltSixOnSelector]
]
let descriptor = fontDescriptor.addingAttributes([NSFontFeatureSettingsAttribute: features])
return NSFont(descriptor: descriptor, size: pointSize) ?? self
}
}
Treat the following as pseudo-code, quickly done, not throughly tested, etc.
Given an NSFont which represents a font which has monospaced numbers as a feature the following method will produce another NSFont with that feature selected:
- (NSFont *) newMonospaceNumbersFont:(NSFont *)font
{
CTFontDescriptorRef origDesc = CTFontCopyFontDescriptor((__bridge CTFontRef)font);
CTFontDescriptorRef monoDesc = CTFontDescriptorCreateCopyWithFeature(origDesc, (__bridge CFNumberRef)#(kNumberSpacingType), (__bridge CFNumberRef)#(kMonospacedNumbersSelector));
CFRelease(origDesc);
CTFontRef monoFont = CTFontCreateWithFontDescriptor(monoDesc, font.pointSize, NULL);
CFRelease(monoDesc);
return (__bridge_transfer NSFont *)monoFont;
}
You can use this, say, to take the current font of a UI element and convert it to one with monospace numbers.
HTH
Variant for Swift
Assuming res is the NSTextField with the number to display:
let origDesc = CTFontCopyFontDescriptor(res.font!)
let monoDesc = CTFontDescriptorCreateCopyWithFeature(origDesc, kNumberSpacingType, kMonospacedNumbersSelector)
let monoFont = CTFontCreateWithFontDescriptor(monoDesc, res.font!.pointSize, nil)
res.font = monoFont
In my experience, the "font panel" functionality isn't well defined and I usually just ignore it whenever I'm messing with a XIB or Storyboard.
What should work is to go back to that "Font" attribute in the Text Field Cell attributes inspector and then select "User Fixed Pitch" from the Font drop down menu (the choice should automatically default to size 11).
If you bump the font size up a point, it'll magically switch to Monaco (the default fixed width font).

set height of multi line label in OSX

I am trying to set the height of the multiline label in OSX but when i use sizetofit functionality it cuts the line width and doesn't set the height.What i want is to be able to grow multi line label as its size increases automatically setting the height and the width.This is the code i am working on right now.
self.solutionTextView.stringValue = String(format: "asjdasjdhsjf dasfjashd fjadhsf sfsdjfijijij dsfsd jsj aidjfajs jfsajf isdj sjdaofjaisdjf i dsfisdfjsdjfi sj jasof sjdf ijsdj fisjdsj fjas jsid isdf jsdi fsiajf isjfi jdsjf saof jisadfj isjdfisdj foajdfjsdawei difj jhjsahhjashashhjsahsahjhsahjsahjshajhsahsahjhjsahjsahjhjsahsahjsajhjhashjshjhjsahsjahjsahjsahsahjsahjshahsjahjsahjsahjshhsjahjsahjsahjsahjhjsahjsahsahhsahjsahsahhsajhjsahjsahjhsjahjsahjsahjhsjahjahjsahjshjahjsahjhjahjsahjhsjahjshjshajhjsahjsahjshjahjsahjsahjshjahjsahjshjahjsahjsahsahhjsahjsahjsahjsahjhjsahjahjsahhsahjjasjhhjsahjsahhjsahjhjsahjsajhhjsahjhjsahjsahjhjsahjshjahjsahjsahjjhashjshajhahjahjhsahhajshjashahjshhjahj%#", self.recommendation.valueForKey("solution") as String)
self.solutionTextView.sizeToFit()
self.linksTextView.stringValue = String(format: "First Link %#", self.recommendation.valueForKey("tip1") as String)
// self.linksTextView.sizeToFit()
self.proTipTextView.stringValue = String(format: "Pro Tip: Not available")
I am developing on iOS and although your variable is named 'self.solutionTextView' I assume we are talking about the equivalent of a UILabel. In this case you could measure the text and use this as an frame:
let frame = self.solutionTextView.frame
frame.size.height = NSString(string:self.solutionTextView.stringValue).sizeWithAttributes([NSFontAttributeName : self.solutionTextView.font]).height
self.solutionTextView.frame = frame
I also assume you have a set width and are more interested in scaling the label vertically in height. If not, the method above returns a size which you can use to get the width.

adding numbers in uitextfield to update uilabel

I have code with several uitextfields that will be used to input numbers, and I want to add these numbers together to update a uilabel.
I can do all the updating and the labels and fields, but can't get the addition to work.
Just now I have:
label.text = (textfield1.text + textfield2.text);
I assume I need to convert these textfield inputs to an int, but not sure how to do that...
there is a couple of extra steps you have to do:
convert the string value of your text filed into numerical value
do the math there
and convert it back.
For example (i use float in my case, you can change that to whatever type you want):
float textField1Value = [textfield1.text floarValue];
float textField2Value = [textfield2.text floarValue];
label.text = [NSString stringWithFormat:#"%f", textField1Value + textField2Value];
Hope that helps.

UITextField not scrolling horizontally

I am trying to make a small calculator app.
When a UIButton is pressed, the Button title is added to a UITextField.
kind of:
myuitextfield.text = [myuitextfield.text stringByAppendingString:[button currentTitle];
When I reach the end of my textfield, the text gets truncated. How can I disable this, so the textfield starts scrolling automatically and allows adding more characters?
I tried every possible option in Interface Builder, without any luck.
Isn't the UITextField supposed to scroll automatically? I can see this behavior when a native keyboard is used and text is entered.
I have chosen UITextField, as I need only 1 Line.
To illustrate the Problem:
When I enter text using my custom UIButtons text gets truncated
When I tap the UITextField and enter text using the keyboard I can enter unlimited text and the text is not truncated.
If you are facing this issue on iOS7, I've managed to fix it after been inspired by this post. In my case I had a field for entering an email address and after reaching the edge, the user could carry on typing but the text would be invisible (off-field).
First, add a callback to your UITextField so that you can track a text change to the field:
[self.field addTarget:self action:#selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
Then evaluate the size in pixels of the entered string as it is typed and change the text alignment from left to right when reaching the edge of the field area:
- (void)textFieldDidChange:(NSNotification *)aNotif{
float maxNumPixelsOnScreen = 235; // Change this value to fit your case
CGSize maximumSize = CGSizeMake(maxNumPixelsOnScreen + 10, 1);
NSString *aString = self.field.text;
CGSize stringSize = [aString sizeWithFont:fieldFont
constrainedToSize:maximumSize
lineBreakMode:NSLineBreakByWordWrapping];
self.field.textAlignment = NSTextAlignmentLeft;
if (stringSize.width >= maxNumPixelsOnScreen)
self.field.textAlignment = NSTextAlignmentRight;
}
Note:
self.field is the offending UITextField
maximumSize: I'm adding 10 the the width to be slightly over the limit defined
fieldFont is the UIFont used to render the text field
Hope it helps!
you have to add UITextview and limit the number of lines to 2.Textfield doesnt work with two lines.Textview is same as textfields except the delegates and some properties differ.

Resources