2010-01-02 3 views
5

NSArrayController에 바인딩 된 NSTableView가 있습니다. 테이블 열의 인덱스를 보여주는 테이블 열 중 하나를 갖고 싶습니다. 이 방법은 NSTableDataSource를 직접 구현할 때 쉽게 할 수 있지만 바운드 테이블 뷰로는 이해할 수 없습니다. 나는 여기 @count 키 경로와 같은 것을 찾고 있다고 생각하는데, 이는 arrayObjects (즉, @index)의 수를 알려주지 만 분명히 빠져있다.NSArrayController에 바인딩 된 NSTableView에 행 인덱스 표시

두 해명 :

  1. 각 행에 표시되는 인덱스 데이터가 실제로 모델 또는 어레이 제어기에 배치되는 방식에 전혀 관련이 행의 인덱스 아니다. 예를 들어, 전체 데이터가 10000 개 항목 일 경우 색인은 1에서 10000까지 가야합니다. 사용자가 검색어를 입력하고 표에 항목 중 4 개만 표시되면 숫자가 1에서 4로 변경되어야합니다. 표시된 항목은 실제로 원래 배열 전체에서 가져온 것입니다.
  2. 나는 이것을 클라이언트에게 요구했기 때문에 이것을 필요로한다 :-). 클라이언트는 특정 행 앞이나 뒤에 행 수를 예측할 수있는 방법이 필요합니다. 안녕하세요, 예를 들어, 추가 된 행 수를 알고 싶습니다.
+0

이유라도? 내가 생각할 수있는 유일한 앱은 오늘 iTunes이며, 나는 그 기능을위한 목적을 결코 발견하지 못했다. –

답변

3

필자가 잘 알고 있듯이 테이블 열을 바인딩하지 않고 대신 데이터 소스를 사용할 수 있습니다. NSTableView는 이러한 종류의 "이중 모드"작업을 지원하지만 어떤 문서도 찾을 수 없습니다.

+0

감사! 해결책은 충분히 간단했습니다. 아무 것도 바인딩되지 않은 열을 추가 한 다음 전체 테이블 뷰의 dataSource 아울렛을 파일 소유자로 설정 한 다음 열 내용을 요청할 때 열 인덱스를 반환하는 NSTableDataSource를 구현했습니다. –

+0

이 작업을 수행해야하지만 구현 된 외로운 datasource 메서드가 다른 tableviews 및 열을 호출하고 있습니다. 내 대리자/데이터 소스는 드래그 앤 드롭을 지원하는 테이블에 원래 표시되었습니다. 단일 테이블 뷰에서이 한 열에 대해 하나의 콜백을 가져야하지 않습니까? 다른 모든 tableviews에 걸쳐 다른 모든 바인딩은 바인딩되어 있습니다! – slashlos

+0

btw를 사용하면 tableview가 셀 (내역) 또는보기 (새 10.6?) 기준인지 여부에 따라 동작이 크게 달라집니다. 그것은 겉으로보기에는 전혀 후자와 함께 할 수 없지만 drag-n-drop (사용자 재배치 필요)에 대한 셀 동작은 다릅니다. 예. iTunes와 마찬가지로 순서가 핵심적인 일종의 재생 목록입니다. – slashlos

1

iTunes의 동작을 복제한다고 가정하면 열에는 1에서 (보이는 행 수) 만 표시하면됩니다. 실제로 모델과 관련 될 필요는 없습니다.

따라서 컨트롤러에 동적으로 생성 된 배열 속성을 지정하고 실제 모델 개체의 배열에 depend으로 지정하십시오.

array accessor methods은 인덱싱 된 게터를 사용하여 idx + 1, box을 계산하고 해당 개체를 반환합니다. 또한 KVC를 만족시키기 위해 전체 배열 게터를 구현해야 할 수도 있습니다.

열을 편집 할 수없는 것으로 설정하고 바인딩을 조건부로 enabled으로 설정하지 않았는지 확인하십시오. 그렇지 않으면 사용자가 행의 새 색인을 입력하려고 할 때 예외가 발생합니다 (이 속성에 대한 설정자가없는 경우).

주의 사항 : NSTableView는 열이 개별 배열에 바인딩 될 것으로 예상하지 않으므로 문제가 발생할 수 있습니다. 모든 열이 단일 배열에서 모델 객체의 다른 속성에 바인딩 될 것으로 기대합니다. 열의 내용 바인딩을 바인딩하는 것 외에도 테이블 뷰의 content을 모델 개체 배열에 바인딩하고 I've had trouble with that before에 바인딩해야 할 수 있습니다.

+0

저는 이것을 구현하려하지만 링크가 끊어지고 "Model Objects"에 대한 Apple 검색이 유용하다고 생각되는 것을 가져 오지 않습니다. –

+0

@boyfarrell : 헤드 업에 감사드립니다. 새 링크를 찾기 위해 사용한 검색은 "모델 객체 접근 자 메서드"였습니다. 내 대답의 문서 링크를 업데이트했습니다. –

2

최근에 TableView의 각 줄 옆에 줄 번호를 그려주는 NSRuler 하위 클래스를 사용하여이 기능을 구현했습니다. 내가 발견 한 유사한 코드를 기반으로 here.

당신은 사용하여있는 tableview이를 추가 할 수 있습니다

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 
관련 문제