objective-c – 如何以编程方式将项目符号列表添加到NSTextView
这个问题可能听起来很奇怪,但我已经挣扎了好几天了.
我有一个NSTextView,可以显示一些带有一些格式选项的文本.其中之一是能够为选择或当前行打开/关闭子弹列表(最简单的一个). 我知道在NSTextView上有一个orderFrontListPanel:方法打开窗口,其中包含可供选择和编辑的可用列表参数(例如,当您按Menu-> Format-> List …时在TextView中). 我试图找到以编程方式设置列表的默认方式,就像通过“列表…”菜单完成一样没有运气. 我请求帮助,每一点点的信息都会受到赞赏:). P.S.:我已经查看了TextView源代码,发现了很多有趣但没有迹象或线索如何以编程方式启用列表. 更新 还在调查.我发现当你发送orderFrontListPanel:到你的NSTextView然后选择项目符号并按回车键时,没有特殊的消息被发送到NSTextView.这意味着可以在弹出式面板中的某处构建项目符号列表,并直接设置为TextView的文本容器… 解决方法
以编程方式将项目符号列表添加到NSTextView的两种方法:
方法1: 以下链接引导我使用第一种方法,但除非您想为子弹使用一些特殊的非Unicode字形,否则它将不必要地转向: > Display hidden characters in NSTextView 这需要:(1)子类化布局管理器,用子弹字形替换某些任意字符; (2)带有firstLineHeadIndent的段落样式,比该缩进略大的制表位,以及用于组合两者的包裹线的headIndent. 布局管理器如下所示: #import <Foundation/Foundation.h> @interface TickerLayoutManager : NSLayoutManager { // Might as well let this class hold all the fonts used by the progress ticker. // That way they're all defined in one place,the init method. NSFont *fontNormal; NSFont *fontIndent; // smaller,for indented lines NSFont *fontBold; NSGlyph glyphBullet; CGFloat fWidthGlyphPlusSpace; } @property (nonatomic,retain) NSFont *fontNormal; @property (nonatomic,retain) NSFont *fontIndent; @property (nonatomic,retain) NSFont *fontBold; @property NSGlyph glyphBullet; @property CGFloat fWidthGlyphPlusSpace; @end #import "TickerLayoutManager.h" @implementation TickerLayoutManager @synthesize fontNormal; @synthesize fontIndent; @synthesize fontBold; @synthesize glyphBullet; @synthesize fWidthGlyphPlusSpace; - (id)init { self = [super init]; if (self) { self.fontNormal = [NSFont fontWithName:@"Baskerville" size:14.0f]; self.fontIndent = [NSFont fontWithName:@"Baskerville" size:12.0f]; self.fontBold = [NSFont fontWithName:@"Baskerville Bold" size:14.0f]; // Get the bullet glyph. self.glyphBullet = [self.fontIndent glyphWithName:@"bullet"]; // To determine its point size,put it in a Bezier path and take its bounds. NSBezierPath *bezierPath = [NSBezierPath bezierPath]; [bezierPath moveToPoint:NSMakePoint(0.0f,0.0f)]; // prevents "No current point for line" exception [bezierPath appendBezierPathWithGlyph:self.glyphBullet inFont:self.fontIndent]; NSRect rectGlyphOutline = [bezierPath bounds]; // The bullet should be followed with a space,so get the combined size... NSSize sizeSpace = [@" " sizeWithAttributes:[NSDictionary dictionaryWithObject:self.fontIndent forKey:NSFontAttributeName]]; self.fWidthGlyphPlusSpace = rectGlyphOutline.size.width + sizeSpace.width; // ...which is for some reason inexact. If this number is too low,your bulleted text will be thrown to the line below,so add some boost. self.fWidthGlyphPlusSpace *= 1.5; // } return self; } - (void)drawGlyphsForGlyphRange:(NSRange)range atPoint:(NSPoint)origin { // The following prints only once,even though the textview's string is set 4 times,so this implementation is not too expensive. printf("nCalling TickerLayoutManager's drawGlyphs method."); NSString *string = [[self textStorage] string]; for (int i = range.location; i < range.length; i++) { // Replace all occurrences of the ">" char with the bullet glyph. if ([string characterAtIndex:i] == '>') [self replaceGlyphAtIndex:i withGlyph:self.glyphBullet]; } [super drawGlyphsForGlyphRange:range atPoint:origin]; } @end 将布局管理器分配给窗口/视图控制器的awakeFromNib中的textview,如下所示: - (void) awakeFromNib { // regular setup... // Give the ticker display NSTextView its subclassed layout manager. TickerLayoutManager *newLayoutMgr = [[TickerLayoutManager alloc] init]; NSTextContainer *textContainer = [self.txvProgressTicker textContainer]; // Use "replaceLM" rather than "setLM," in order to keep shared relnshps intact. [textContainer replaceLayoutManager:newLayoutMgr]; [newLayoutMgr release]; // (Note: It is possible that all text-displaying controls in this class’s window will share this text container,as they would a field editor (a textview),although the fact that the ticker display is itself a textview might isolate it. Apple's "Text System Overview" is not clear on this point.) } 然后添加一个类似这样的方法: - (void) addProgressTickerLine:(NSString *)string inStyle:(uint8_t)uiStyle { // Null check. if (!string) return; // Prepare the font. // (As noted above,TickerLayoutManager holds all 3 ticker display fonts.) NSFont *font = nil; TickerLayoutManager *tickerLayoutMgr = (TickerLayoutManager *)[self.txvProgressTicker layoutManager]; switch (uiStyle) { case kTickerStyleNormal: font = tickerLayoutMgr.fontNormal; break; case kTickerStyleIndent: font = tickerLayoutMgr.fontIndent; break; case kTickerStyleBold: font = tickerLayoutMgr.fontBold; break; default: font = tickerLayoutMgr.fontNormal; break; } // Prepare the paragraph style,to govern indentation. // CAUTION: If you propertize it for re-use,make sure you don't mutate it once it has been assigned to an attributed string. (See warning in class ref.) // At the same time,add the initial line break and,if indented,the tab. NSMutableParagraphStyle *paragStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; // ALLOC [paragStyle setAlignment:NSLeftTextAlignment]; // default,but just in case if (uiStyle == kTickerStyleIndent) { // (The custom layout mgr will replace ‘>’ char with a bullet,so it should be followed with an extra space.) string = [@"n>t" stringByAppendingString:string]; // Indent the first line up to where the bullet should appear. [paragStyle setFirstLineHeadIndent:15.0f]; // Define a tab stop to the right of the bullet glyph. NSTextTab *textTabFllwgBullet = [[NSTextTab alloc] initWithType:NSLeftTabStopType location:15.0f + tickerLayoutMgr.fWidthGlyphPlusSpace]; [paragStyle setTabStops:[NSArray arrayWithObject:textTabFllwgBullet]]; [textTabFllwgBullet release]; // Set the indentation for the wrapped lines to the same place as the tab stop. [paragStyle setHeadIndent:15.0f + tickerLayoutMgr.fWidthGlyphPlusSpace]; } else { string = [@"n" stringByAppendingString:string]; } // PUT IT ALL TOGETHER. // Combine the above into a dictionary of attributes. NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: font,NSFontAttributeName,paragStyle,NSParagraphStyleAttributeName,nil]; // Use the attributes dictionary to make an attributed string out of the plain string. NSAttributedString *attrs = [[NSAttributedString alloc] initWithString:string attributes:dict]; // ALLOC // Append the attributed string to the ticker display. [[self.txvProgressTicker textStorage] appendAttributedString:attrs]; // RELEASE [attrs release]; [paragStyle release]; } 测试出来: NSString *sTicker = NSLocalizedString(@"First normal line of ticker should wrap to left margin",@"First normal line of ticker should wrap to left margin"); [self addProgressTickerLine:sTicker inStyle:kTickerStyleNormal]; sTicker = NSLocalizedString(@"Indented ticker line should have bullet point and should wrap farther to right.",@"Indented ticker line should have bullet point and should wrap farther to right."); [self addProgressTickerLine:sTicker inStyle:kTickerStyleIndent]; sTicker = NSLocalizedString(@"Try a second indented line,to make sure both line up.",@"Try a second indented line,to make sure both line up."); [self addProgressTickerLine:sTicker inStyle:kTickerStyleIndent]; sTicker = NSLocalizedString(@"Final bold line",@"Final bold line"); [self addProgressTickerLine:sTicker inStyle:kTickerStyleBold]; 你得到这个: 方法2: 但子弹是一个常规的Unicode字符,在十六进制2022.所以你可以直接把它放在字符串中,并得到一个精确的测量,如下所示: NSString *stringWithGlyph = [NSString stringWithUTF8String:"u2022"]; NSString *stringWithGlyphPlusSpace = [stringWithGlyph stringByAppendingString:@" "]; NSSize sizeGlyphPlusSpace = [stringWithGlyphPlusSpace sizeWithAttributes:[NSDictionary dictionaryWithObject:self.fontIndent forKey:NSFontAttributeName]]; self.fWidthGlyphPlusSpace = sizeGlyphPlusSpace.width; 因此不需要自定义布局管理器.只需像上面一样设置paragStyle缩进,并将文本字符串附加到一个字符串,该字符串包含行返回项目符号空格(或选项卡,在这种情况下,您仍然希望该制表符停止). 使用空格,这产生了更严格的结果: 想要使用子弹以外的角色吗?这是一个很好的Unicode图表:http://www.danshort.com/unicode/ (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |