Determining NSNaturalTextAlignment's actual text alignment value? - objective-c

I'm currently trying to learn all I can about Cocoa's text "architecture." I've painstakingly learned all about the NSFontDescriptor, NSTextTab, and NSTextView classes, and I think I'm really understanding how it all works. However, there's one thing I can't seem to figure out: NSNaturalTextAlignment. I mean, I get it. I understand that when the font's "script" is RTL, the natural alignment is right, and when it's LTR, the natural alignment is left. All of that makes sense. However, how does one determine the natural direction of the font's script? I ask because of how my little app is set up. I currently have a mini formatting bar with the usual suspects:
NSPopUpButton to choose a font family
NSPopUpButton to choose a typeface
ACustomComboBox to choose a font size
NSSegmentedControl with segments for B, I, U, etc.
After those elements, I have my alignment control, which is also an NSSegmentedControl. In it, I have four options: left, centered, right, and justified. Again, pretty basic stuff. The neat thing about the alignment control is that I've set the tag for each segment to correspond to an NSTextAlignment value. Thus, when the "left" segment is pressed, the selected text aligns to the left. The same thing is true for "centered," "right," and "justified."
The problem is that a lot of the time an attributed string's NSParagraphStyle will return an NSNaturalTextAlignment value.
The documentation states:
The returned value is one of the alignments described in “NSTextAlignment.”
Text using NSNaturalTextAlignment is actually displayed using one of the other alignments, depending on the natural alignment of the text’s script.
Well, I'm glad Apple knows the natural alignment of the text's script, but how I do I find that out? I've currently implemented a really bad solution, but I honestly can't figure out any way around it. The bad solution looks like this:
- (void)updateTextAlignmentDisplayWithParagraphStyle:(NSParagraphStyle *)pStyle
{
NSTextAlignment alignment = pStyle.alignment;
if ( alignment == NSNaturalTextAlignment ) {
// This seems like a horrible way to determine the correct alignment ...
BOOL isRTL = ( self.textEditor.baseWritingDirection == NSWritingDirectionRightToLeft );
if ( isRTL ) {
alignment = NSRightTextAlignment;
} else {
alignment = NSLeftTextAlignment;
}
}
[self.alignmentControl selectSegmentWithTag:alignment];
}
The text view's "base" direction doesn't really tell me anything about the direction of the font itself, but at least it hints at what direction the font might go. I don't know. I just have a feeling there's a super secret NSFontDescriptor attribute which has this information, but I haven't found it. Cocoa gurus, any advice? Thanks in advance!

In the file NSText.h defines
NSNaturalTextAlignment = 4 // Indicates the default alignment for script
I think script is meant in the sense of written text.
You could change your code by using switch (pStyle.alignment or self.textEditor.baseWritingDirection) and add case: for every alignment.
I'm not an expert, but I think, that's what you need to know, to go forward. The info about the alignment maybe part of the Font, but this is speculative! It's also possible, that it is taken from user setting default language for the keyboard. NSLocale in the documentation or Internet might allow to go deeper in this theme.

Related

How to expand wxTextCtrl in wxToolbar?

There is a tool button and a textctrl in the toolbar. I'm trying to expand the textctrl in the horizontal direction to fill all the remaining space.
wxSizer maybe a good choice but it seems not suitable with toolbar because I can't add tool button directly in a sizer.
There is no built in support for this, you will need to handle wxEVT_SIZE (either in the toolbar itself or in the frame containing it, as the size of the toolbar only changes when the size of the frame does), compute the available size (which is going to be tricky, there is no function to find this out neither so I expect you'd have to do some kind of binary search using wxToolBar::FindToolForPosition()) and resize your text control.
It would definitely be much simpler to put both the toolbar and the text in a sizer instead. But it's true that it wouldn't appear quite the same, so if you really want to have the text-inside-toolbar appearance, you would have to do the above. Good luck!

NSTextField weird left margins

I've been looking for a solution for this one all day.
I have 4 NSTextFields (actually subclassed for a few custom operations), which all share the same X position.
The problem is, some have different styles (light, regular, bold) and might have different sizes.
What happens is that, even though the X origin is the same, the 1st letter always has a bit of (consistently different) left margins.
Please see pic: https://dl.dropbox.com/u/1977230/Screen%20Shot%202012-12-11%20at%2017.55.58.png
I want to make sure that all lines start exactly at the same point, say 100px from the left.
Any idea how to override that weird padding?
Cheers
The margin you're talking about I'm pretty sure is the lineFragmentPadding on the NSTextContainer that is used by the NSTextField.
See the NSTextContainer reference:
http://developer.apple.com/library/Mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSTextContainer_Class/Reference/Reference.html
And here's a page from the tutorial on Text Layout:
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/TextLayout/Concepts/CalcTextLayout.html
It states in that article:
The typesetter makes one final adjustment when it actually fits text
into the rectangle. This adjustment is a small amount fixed by the
NSTextContainer object, called the line fragment padding, which
defines the portion on each end of the line fragment rectangle left
blank. Text is inset within the line fragment rectangle by this amount
(the rectangle itself is unaffected). Padding allows for small-scale
adjustment of the text container’s region at the edges and around any
holes and keeps text from directly abutting any other graphics
displayed near the region. You can change the padding from its default
value with the setLineFragmentPadding: method. Note that line fragment
padding isn’t a suitable means for expressing margins; you should set
the NSTextView object’s position and size for document margins or the
paragraph margin attributes for text margins.
Unfortunately, it looks like NSTextField's NSTextContainer and NSLayoutManager are private and inaccessible, but it appears they are accessible in an NSTextView:
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSTextView_Class/Reference/Reference.html#//apple_ref/occ/cl/NSTextView
So that may be the class you need to subclass if you want to have minute control over this kind of functionality.
Have you looked into CoreText? I think it may provide the facilities to do what you're looking for. From the docs...
The Core Text layout engine is designed specifically to make simple text layout operations easy to do and to avoid side effects.
You are able to access "font metrics," which enable you to (from the docs)...
For every font, glyph designers provide a set of measurements, called metrics, which describe the spacing around each glyph in the font. The typesetter uses these metrics to determine glyph placement. Font metrics are parameters such as ascent, descent, leading, cap height, x-height, and so on.
EDIT:
It just may be that NSTextField was not designed for what you are trying to do. NSTextField does custom layout apart from a NSLayoutManager.
You may need to upgrade to a NSTextView, which always has a dedicated NSLayoutManager attached. Apple has some example projects you could search for using NSLayoutManager and NSTextView.
If you're using NSTextField to draw simple static text, take a look at AppKit additions to NSString. Use sizeWithAttributes: to get size of the "text" image. Then use the size to calculate rects for drawing. Finally use one of draw methods to actually draw text. Don't forget to "round" result of sizeWithAttributes! It's not pixel aligned.
But if you need to draw something more complex than simple label, use Core Text. You can find very good example of how to use it in twui source code.

Setting UIMenuController arrow direction not working

I have a UIMenuController which I have added a few extra items to. I would like the menu to be BELOW the text that I select, so I tried:
[UIMenuController sharedMenuController].arrowDirection = UIMenuControllerArrowDown;
That seemed to do nothing, and everything I try, won't put the menu below the text.
How can I do that?
According to the docs, arrowDirection sets the direction the arrow points; it has nothing to do with the location of the menu relative to its target area. It also looks like they don't give you any control over the positioning of the menu beyond setTargetRect:inView.
If you really want to put the menu below the text, you might be able to set a "fake" target area and change the arrow direction to point to the "real" area of interest.
However, there's probably a reason Apple does it this way. My guess? If you select some text with your finger, your hand is probably obscuring the part of the screen below the text... so it's not very helpful if the menu appears there. Going out of your way to break consistency with standard UI conventions isn't usually worth the effort.

Colored substring in UITextField

I would like to change the color only of particular substrings (keywords) while the user is typing in a UITextField.
In the documentation I saw the property textColor but it does change the color of the entire text string, while I would like to highlight only some keywords.
Is it possible?
The short answer is no.
It's possible if you create your own textfield from scratch using NSAttributedStrings and CATextLayers or Core Text, but this is an incredibly complex and difficult problem.
If you are mirroring what the user types in a preview box of some sort it is possible to create multiple labels or text fields that stay next to each other and have different colors or fonts or whatever. Otherwise, I'm afraid Nick's answer is accurate - within a single textField it ain't happening.
Good luck,
Damien

Objective C - UITextView letter spacing and vertical spacing

How can I set the letter spacing and vertical spacing for a UITextView?
Trying to do it from nib if possible but if not, is there a property I can set through code?
Thank you,
Tee
There is no property within the UITextView to explicitly set the letter spacing, or vertical spacing - with the native controls it can't be done.
If you want to do this you're going to have to roll your own. There's a SO thread about changing the UILabel/UIFont letter spacing which ought to provide you with a direction to go in.
With that said, I have to ask the question why you want to do this? Apple is very specific about it's interface elements, and my thought is that tweaking a UITextView is going to be very off putting to your users.
As gavin has said, really; if possible you could change to a UILabel and set the lineBreakMode property, in conjunction with the contentSize property of the label's frame to partly achieve some light modification.
You could also replace spaces with a number of spaces for example from a string object, but again as has been said, I wouldn't advise tampering too far with this, especially if its going to be a public appstore project.
Good luck!
Well if you are looking for line height you can get like this.
yourUITextView.font.lineHeight
This would give you line height according to the current font size. This works perfectly in iOS 8. Not sure about backward compatibility.