2012-06-08 51 views
0

我想創建一個NSTextView,其行爲有點像一系列打字機頁面 - 每個頁面都有固定數量的行和列可用。在NSTextView中硬包裝

底層表示理想地匹配顯示,而顯示依次匹配文件格式。頁面以換頁符'\f'結束。例如,兩個4×4的頁面看起來像這樣保存時(爲便於閱讀,字符之間空格):

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 

有幾件事情需要注意:

  • 換行符和形式的飼料都在不計行/列總
  • 比列數較短行不尾隨空格填充比排短
  • 頁面(雖然他們可能是,如果編輯在覆蓋模式工作)數填充W¯¯第i個換行符

我嘗試了一些方法,如將文本轉換爲直線和分裂排長隊的NSArraytextDidChange通知,然後設置文本的串聯線,但它確實是低效的,並失去光標如果鍵入發生在文檔結尾以外的任何位置,則爲位置。最後,我想我希望這是一個填充空白的大頁面,並且只能在覆蓋模式下進行輸入,但是會在行尾換行。我不知道該從哪裏開始。有什麼建議麼?

+0

也許一個更基本的問題嗎?我不確定是否在文本視圖,佈局管理器,排字機,文本存儲或其他地方解決這個問題的最佳位置。也許只是一個指向正確方向的指針就足以讓其他人知道。 – squidpickles

回答

0

我發現一個可接受的,如果不是完美的解決方案,通過繼承進行包裝。

將文本添加到文檔末尾(無論是粘貼還是鍵入),其行爲完全如預期。它還可以在刪除或替換文本時發揮作用。唯一有點奇怪的地方是將文本插入已滿線條的中間。那會在之前造成只包含的插入文字。它工作正常,但這意味着繼續在該位置鍵入將創建一些短行。

例如,下面的文本包含20列。原始文本是x,插入的文本是o。插入的文本從第二行開始,在第八個字符處。下面

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]; 
}