我有NSTextfields
一本书的布局有两个,我想不出一种快速返回上一个“页面”的方法。书本大小、字体大小、行大小都会发生变化,因此必须即时计算前一页的文本字符串。图片:
NSTextfields 每个都有一个NSTextContainer
,它们共享一个NSLayoutManager
和NSTextStorage
。
前进很容易:我获取可见文本的字符范围,然后从下一个字符开始创建一个子字符串。
我回去的方法是一个杂耍。我计算出一次可以看到的最大字符数。然后,我制作了一个该长度的字符串,最后一个字符是我想要的位于书的右下角的那个。然后我循环:从头开始删除字符,每次检查可见的内容,直到我想要的字符位于右下角。这是非常非常缓慢的。
谁能建议一种更快的方法来完成我想要实现的目标?我曾想过使用,但我不知道如何为此布局scrollRangeToVisible
设置 a 。NSScrollView
任何人都可以帮忙吗?
文本容器的设置如下:
-(void)setupTextViews {
articleString = [[NSAttributedString alloc] init];
articleStringPortion = [[NSAttributedString alloc] init];
bookTextStorage = [[NSTextStorage alloc] init];
bookLayoutManager = [[NSLayoutManager alloc] init];
[[self bookTextStorage] addLayoutManager:bookLayoutManager];
leftColumnRect = NSZeroRect;
rightColumnRect = NSZeroRect;
NSDivideRect(bookRect, &leftColumnRect, &rightColumnRect, NSWidth(bookRect) / 2, NSMinXEdge);
// First column
{
NSTextContainer *textContainer = [[NSTextContainer alloc] initWithContainerSize:leftColumnRect.size];
leftColumnTextView = [[CRMouseOverTextView alloc] initWithFrame:leftColumnRect textContainer:textContainer];
[leftColumnTextView setDrawsBackground:NO];
[leftColumnTextView setEditable:NO];
[leftColumnTextView setup];
[bookView addSubview:leftColumnTextView];
[bookLayoutManager addTextContainer:textContainer];
[textContainer release];
[leftColumnTextView release];
}
// Second column
{
NSTextContainer *textContainer = [[NSTextContainer alloc] initWithContainerSize:rightColumnRect.size];
rightColumnTextView = [[CRMouseOverTextView alloc] initWithFrame:rightColumnRect textContainer:textContainer];
[rightColumnTextView setDrawsBackground:NO];
[rightColumnTextView setEditable:NO];
[rightColumnTextView setup];
[bookView addSubview:rightColumnTextView];
[bookLayoutManager addTextContainer:textContainer];
[textContainer release];
[rightColumnTextView release];
}
}
发布我糟糕的倒退代码是没有意义的,但我正在使用我发现的这种方法来找出每次可见的内容:
-(NSRange)getViewableRange:(NSTextView *)tv {
NSLayoutManager *lm = [tv layoutManager];
NSRect visRect = [tv visibleRect];
NSPoint tco = [tv textContainerOrigin];
visRect.origin.x -= tco.x;
visRect.origin.y -= tco.y;
NSRange glyphRange = [lm glyphRangeForBoundingRect:visRect inTextContainer:[tv textContainer]];
NSRange charRange = [lm characterRangeForGlyphRange:glyphRange actualGlyphRange:nil];
return charRange;
}