gpt4 book ai didi

cocoa - NSTextView 中的硬包装

转载 作者:行者123 更新时间:2023-12-03 17:24:27 25 4
gpt4 key购买 nike

我正在尝试创建一个 NSTextView,其行为有点像一系列打字机页面 - 每个页面都有固定数量的可用行和列。

底层表示与显示完美匹配,而显示又与文件格式匹配。页面以换页符 '\f' 结尾。例如,两个 4x4 页面在保存时将如下所示(字符之间有空格以提高可读性):

T  H  I  S  \n
P A G E \n
I S \n
F U L L \n
\f
N O T \n
T H I S \n
O N E \n
\n
\f

需要注意的几点:

  • 换行符和换页符不计入行/列总数
  • 短于列数的行不会用尾随空格填充(尽管如果编辑器在覆盖模式下工作,则可能会填充)
  • 短于行数的页面用换行符填充

我尝试了几种方法,例如将文本转换为行的 NSArray 并在每个 textDidChange 通知上分割长行,然后将文本设置为连接的行,但它确实效率低下,如果在文档末尾以外的任何地方打字,就会丢失光标位置。

最后,我想我希望它表现为一个填充有空格的大页面,并且键入仅发生在覆盖模式下,但在行尾换行。我不知道从哪里开始这种方法。有什么建议吗?

最佳答案

我找到了一个可以接受的(即使不是完美的)解决方案,通过子类化 NSTextStorage 来进行包装。

在文档末尾添加文本(无论是粘贴还是键入)时,它的行为完全符合预期。删除或替换文本时它也会起作用。唯一有点奇怪的地方是在已经满的行中间插入文本时。这将导致插入文本之前换行。它工作正常,但这意味着继续在该位置键入将创建许多短行。

例如,下面的文本按 20 列换行。原始文本为x,插入文本为o。插入的文本从第二行第 8 个字符开始。

xxxxxxxxxxxxxxxxxxxx
xxxxxxx
ooooooo
ooooooo
oooooooxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxx

代码如下:

- (void)breakLinesInArray:(NSMutableArray *)lines atLength:(NSUInteger)length
charsPreceding:(NSUInteger)preceding charsFollowing:(NSUInteger)following
{
NSUInteger line = 0;
while (line < [lines count]) {
NSUInteger maxLineLength = length;
if (line == 0) {
maxLineLength = length - preceding;
} else if (line == [lines count] - 1) {
maxLineLength = length - following;
}
NSString *original = [lines objectAtIndex:line];
if (maxLineLength > 0 && [original length] > maxLineLength) {
NSString *first = [original substringToIndex:maxLineLength];
NSString *second = [original substringFromIndex:maxLineLength];
[lines replaceObjectAtIndex:line withObject:first];
[lines insertObject:second atIndex:line + 1];
}
++line;
}
}

- (void)replaceCharactersInRange:(NSRange)range withString:(NSString *)str
{
static const NSUInteger kMaxLineLength = 20;
NSString *text = [text_ string];
NSUInteger firstLineStart = 0;
NSUInteger lastLineEnd = 0;
NSMutableArray *lines = [NSMutableArray arrayWithArray:[str componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]]];
[text getLineStart:&firstLineStart end:nil contentsEnd:&lastLineEnd forRange:range];
NSUInteger firstLineStartFragmentLength = range.location - firstLineStart;
NSUInteger lastLineEndFragmentLength = lastLineEnd - (range.location + range.length);
[self breakLinesInArray:lines atLength:kMaxLineLength charsPreceding:firstLineStartFragmentLength charsFollowing:lastLineEndFragmentLength];
NSString *newString = [lines componentsJoinedByString:@"\n"];
NSInteger changeInLength = [newString length] - range.length;
NSInteger newLastLineLength = firstLineStartFragmentLength + lastLineEndFragmentLength + changeInLength;
if ((firstLineStartFragmentLength || lastLineEndFragmentLength) && newLastLineLength > (NSInteger)kMaxLineLength) {
newString = [@"\n" stringByAppendingString:newString];
++changeInLength;
}
[text_ replaceCharactersInRange:range withString:newString];
[self edited:NSTextStorageEditedCharacters range:range changeInLength:changeInLength];
}

关于cocoa - NSTextView 中的硬包装,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10957243/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com