2010-01-02 46 views
5

我有一個綁定到NSArrayController的NSTableView。我想有一個表列顯示錶格行的索引。當你自己實現NSTableDataSource時,這很容易實現,但我無法用綁定的表視圖來解決它。 我想我在這裏尋找類似@count鍵路徑的東西,它給了我排列的對象(即@index)的數量,但這顯然缺失。在綁定到NSArrayController的NSTableView中顯示行索引

兩個澄清:

  1. 即每行中所示的索引是該行的索引,而不是在所有相關的數據被實際設置在模型或陣列控制器的方式。例如,如果整個數據是10000個項目,那麼索引應該從1到10000,如果用戶輸入搜索詞並且表格只顯示4個項目,則數字應該從1到4,即使顯示的項目實際上來自整個原始數組。
  2. 我需要這個,因爲我被要求這樣做的客戶端:-)。客戶端需要一種方法來估計某一行之前或之後的行數。嗨,例如,可能想知道添加了多少行。
+0

任何理由嗎?我能想到的唯一一個應用程序是iTunes,我從未找到該功能的目的。 – 2010-01-02 15:00:27

回答

3

據我所知,你可以選擇不綁定該表的列,而是使用數據源。我記得NSTableView支持這種「雙模」操作,但找不到任何文檔來確認它。

+0

謝謝!該解決方案非常簡單。我添加了一個未綁定任何內容的列,然後將整個表視圖的dataSource出口設置爲文件所有者,然後在詢問列內容時實現NSTableDataSource返回列索引。 – 2010-01-04 13:49:03

+0

我需要這樣做,但我的獨立數據源方法實施正在被稱爲其他tableviews和列。我的委託/數據源最初標記爲支持拖放的表格。我不應該在單個tableview中爲這一列獲取單個回調嗎?其他所有桌面瀏覽器中的所有其他瀏覽器都有綁定! – slashlos 2017-03-03 01:00:03

+0

順便說一句,不管tableview是基於單元格(歷史)還是視圖(新的自10.6?),行爲都會有很大差異。對後者來說看起來根本不可行,但單元行爲拖拽(用戶重新排列需求)不同。是的,就像iTunes一樣,它是一種播放列表,需要訂購是關鍵。 – slashlos 2017-03-05 22:45:42

1

假設您的目標是複製iTunes的行爲,您的列只需要顯示1(可見行數)。它實際上並不需要與你的模型有關。

因此,給你的控制器一個動態生成的數組屬性,並在實際模型對象數組上創建它depend

對於此屬性,實現array accessor methods,與索引的getter簡單計算idx + 1box荷蘭國際集團起來,並返回一個對象。您可能還需要實現全數組獲取器來滿足KVC。

確保將列設置爲不可編輯,並將綁定設置爲無條件地設置enabled。否則,當用戶嘗試輸入一行的新索引時,會得到一個異常(對於沒有此屬性的setter)。

需要注意的一點是:這可能會導致問題,因爲NSTableView不希望其列被綁定到離散數組;它期望其所有列都綁定到單個數組中的模型對象的不同屬性。除了綁定列的內容綁定和I've had trouble with that before之外,您可能需要將表視圖本身的content綁定到您的模型對象數組。

+0

我試圖實現這一點,但現在鏈接斷開,蘋果搜索「模型對象」並沒有帶來任何看起來有用的東西。 – 2013-02-10 08:49:53

+0

@boyfarrell:謝謝你的提醒。我用來查找新鏈接的搜索是「模型對象訪問器方法」。我更新了我的答案的文檔鏈接。 – 2013-02-10 20:00:21

2

我最近使用NSRuler子類實現了這一點,該子類在TableView中的每一行旁邊繪製行號。我基於類似的代碼,我發現here

您可以使用添加到您的實現代碼如下:

NSScrollView *scrollView = [tableView enclosingScrollView]; 
TableLineNumberRulerView *lineNumberView = [[TableLineNumberRulerView alloc] initWithTableView:tableView 
                      usingArrayController:arrayController]; 

[scrollView setVerticalRulerView:lineNumberView]; 
[scrollView setHasVerticalRuler:YES]; 
[scrollView setRulersVisible:YES]; 

這裏的接口文件:

// 
// TableLineNumberRulerView 
// Line View Test 
// 
// Created by Ben Golding, Object Craft Pty Ltd on 7 May 2014. 
// Based on code by Paul Kim on 9/28/08. 


#import <Cocoa/Cocoa.h> 

@interface TableLineNumberRulerView : NSRulerView<NSCoding> 

@property (strong) NSArrayController *arrayController; 

@property (strong) NSFont  *font; 
@property (strong) NSColor *textColor; 
@property (strong) NSColor *alternateTextColor; 
@property (strong) NSColor *backgroundColor; 
@property (strong) NSDictionary *textAttributes; 
@property (assign) NSUInteger rowCount; 

- (id)initWithTableView:(NSTableView *)tableView usingArrayController:(NSArrayController *)arrayController; 

@end 

這裏的實現:

// 
// TableLineNumberRulerView.m 
// Line View Test 
// 
// Created by Ben Golding, Object Craft Pty Ltd on 7 May 2014. 
// Based on code by Paul Kim on 9/28/08. 

#import "TableLineNumberRulerView.h" 

#define DEFAULT_THICKNESS 22.0 
#define RULER_MARGIN  5.0 

@implementation TableLineNumberRulerView 

@synthesize font; 
@synthesize textColor; 
@synthesize alternateTextColor; 
@synthesize backgroundColor; 
@synthesize textAttributes; 
@synthesize rowCount; 


- (id)initWithTableView:(NSTableView *)tableView usingArrayController:(NSArrayController *)arrayController 
{ 
    NSScrollView *scrollView = [tableView enclosingScrollView]; 

    if ((self = [super initWithScrollView:scrollView orientation:NSVerticalRuler]) == nil) 
     return nil; 

    [self setClientView:tableView]; 

    self.arrayController = arrayController; 
    [arrayController addObserver:self forKeyPath:@"arrangedObjects" options:NSKeyValueObservingOptionNew context:nil]; 

    self.font = [NSFont labelFontOfSize:[NSFont systemFontSizeForControlSize:NSMiniControlSize]]; 
    self.textColor = [NSColor colorWithCalibratedWhite:0.42 alpha:1.0]; 
    self.alternateTextColor = [NSColor whiteColor]; 
    self.textAttributes = @{ 
     NSFontAttributeName: [self font], 
     NSForegroundColorAttributeName: [self textColor] 
    }; 

    self.rowCount = [[arrayController arrangedObjects] count]; 

    return self; 
} 

- (void)awakeFromNib 
{ 
    [self setClientView:[[self scrollView] documentView]];  // this will be an NSTableView instance 
} 

- (void)finalize 
{ 
    [self.arrayController removeObserver:self forKeyPath:@"arrangedObjects"]; 
} 

#pragma mark - 
#pragma mark Key-Value observing of changes to array controller 

/* 
* This picks up changes to the arrayController's arrangedObjects using KVO. 
* We check the size of the old and new rowCounts and compare them to see if the number 
* digits has changed, and if so, we adjust the ruler width. 
*/ 

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
{ 
    if ([keyPath isEqualToString:@"arrangedObjects"]) { 
     NSUInteger newRowCount = [[self.arrayController arrangedObjects] count]; 

     if ((int)log10(self.rowCount) != (int)log10(newRowCount)) 
      [self setRuleThickness:[self requiredThickness]]; 
     self.rowCount = newRowCount; 
     // we need to redisplay because line numbers may change or disappear in view 
     [self setNeedsDisplay:YES]; 
    } 
} 


- (CGFloat)requiredThickness 
{ 
    NSUInteger  lineCount = [[self.arrayController arrangedObjects] count], 
        digits = (unsigned)log10((lineCount < 1) ? 1: lineCount) + 1; 
    NSMutableString *sampleString = [NSMutableString string]; 
    NSSize   stringSize; 

    for (NSUInteger i = 0; i < digits; i++) { 
     // Use "8" since it is one of the fatter numbers. Anything but "1" 
     // will probably be ok here. I could be pedantic and actually find the fattest 
     // number for the current font but nah. 
     [sampleString appendString:@"8"]; 
    } 

    stringSize = [sampleString sizeWithAttributes:[self textAttributes]]; 

    // Round up the value. There is a bug on 10.4 where the display gets all wonky when scrolling if you don't 
    // return an integral value here. 
    return ceil(MAX(DEFAULT_THICKNESS, stringSize.width + RULER_MARGIN * 2)); 
} 

- (void)drawHashMarksAndLabelsInRect:(NSRect)aRect 
{ 
    NSTableView *tableView = (NSTableView *)[self clientView]; 
    NSRect bounds = [self bounds]; 
    NSRect visibleRect = [[tableView enclosingScrollView] documentVisibleRect]; 
    NSRange visibleRowRange = [tableView rowsInRect:visibleRect]; 
    CGFloat yinset = NSHeight([[tableView headerView] bounds]); 

    if (backgroundColor != nil) { 
     [backgroundColor set]; 
     NSRectFill(bounds); 

     [[NSColor colorWithCalibratedWhite:0.58 alpha:1.0] set]; 
     [NSBezierPath strokeLineFromPoint:NSMakePoint(NSMaxX(bounds) - 0/5, NSMinY(bounds)) 
            toPoint:NSMakePoint(NSMaxX(bounds) - 0.5, NSMaxY(bounds))]; 
    } 

// NSLog(@"drawHashMarksAndLabelsInRect: bounds %@, ruleThickness %lf", NSStringFromRect(bounds), [self ruleThickness]); 

    for (NSUInteger row = visibleRowRange.location; NSLocationInRange(row, visibleRowRange); row++) { 
     // Line numbers are internally stored starting at 0 
     NSString *labelText = [NSString stringWithFormat:@"%lu", row + 1]; 
     NSSize stringSize = [labelText sizeWithAttributes:self.textAttributes]; 
     NSRect rowRect = [tableView rectOfRow:row]; 
     CGFloat ypos = yinset + NSMinY(rowRect) - NSMinY(visibleRect); 

     [labelText drawInRect:NSMakeRect(NSWidth(bounds) - stringSize.width - RULER_MARGIN, 
             ypos + (NSHeight(rowRect) - stringSize.height)/2.0, 
             NSWidth(bounds) - RULER_MARGIN * 2.0, NSHeight(rowRect)) 
       withAttributes:self.textAttributes]; 
    } 
} 

#pragma mark - 
#pragma mark NSCoding methods 

#define FONT_CODING_KEY   @"font" 
#define TEXT_COLOR_CODING_KEY  @"textColor" 
#define ALT_TEXT_COLOR_CODING_KEY @"alternateTextColor" 
#define BACKGROUND_COLOR_CODING_KEY @"backgroundColor" 

- (id)initWithCoder:(NSCoder *)decoder 
{ 
    if ((self = [super initWithCoder:decoder]) != nil) { 
     if ([decoder allowsKeyedCoding]) { 
      font = [decoder decodeObjectForKey:FONT_CODING_KEY]; 
      textColor = [decoder decodeObjectForKey:TEXT_COLOR_CODING_KEY]; 
      alternateTextColor = [decoder decodeObjectForKey:ALT_TEXT_COLOR_CODING_KEY]; 
      backgroundColor = [decoder decodeObjectForKey:BACKGROUND_COLOR_CODING_KEY]; 
     } else { 
      font = [decoder decodeObject]; 
      textColor = [decoder decodeObject]; 
      alternateTextColor = [decoder decodeObject]; 
      backgroundColor = [decoder decodeObject]; 
     } 
    } 
    return self; 
} 

- (void)encodeWithCoder:(NSCoder *)encoder 
{ 
    [super encodeWithCoder:encoder]; 

    if ([encoder allowsKeyedCoding]) { 
     [encoder encodeObject:font forKey:FONT_CODING_KEY]; 
     [encoder encodeObject:textColor forKey:TEXT_COLOR_CODING_KEY]; 
     [encoder encodeObject:alternateTextColor forKey:ALT_TEXT_COLOR_CODING_KEY]; 
     [encoder encodeObject:backgroundColor forKey:BACKGROUND_COLOR_CODING_KEY]; 
    } else { 
     [encoder encodeObject:font]; 
     [encoder encodeObject:textColor]; 
     [encoder encodeObject:alternateTextColor]; 
     [encoder encodeObject:backgroundColor]; 
    } 
} 

@end 
相關問題