2010-01-02 62 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 
相关问题