2012-08-27 54 views
6

我想創建一個NSOutlineVew與列出的對象的自定義標題組(父節點)。 (注意:我有基於單元格的NSOutlineView)。例如,它看起來像Xcode「Navigator」或Numbers側欄。我爲每個類別的分離屬性使用了默認組,但它看起來不像我想要的那樣。我需要一個父節點(單元),我可以在視覺上調整它(添加一個控件元素和圖像)。NSOutlineView中的數組枚舉對象的自定義節

我試圖通過傳遞一個對象數組NSDictionary,給每個組一個特定的關鍵。結果,通過NSLog一切正常顯示,但作爲程序NSOulineView源的這個變量的傳輸失敗。

ProjectViewController.h

@interface ProjectViewController : NSViewController <NSOutlineViewDataSource, NSObject> { 
    IBOutlet NSOutlineView   *outlineView; 
    FSEntity      *content; 
} 

@property (readonly, assign) NSMutableArray *objects; 

@end 

ProjectViewController.m

@implementation ProjectViewController 

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { 
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 
    if (self) { 
     // Initialization code here.  
     // Setting default path to the local file or directory 
     NSString *home = NSHomeDirectory(); 
     NSURL *url = [[NSURL alloc] initFileURLWithPath:home]; 
     content = [[FSEntity alloc] initWithURL:url]; 

     [self defineContentNSOutlineView]; 
     NSLog(@"Array: %@",_objects); 

     // Basic сonfiguration an instance NSOutlineView 
     [self configurationNSOutlineView]; 
    } return self; 
} 

@synthesize objects = _objects; 

- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item { 
    return (item == nil) ? [content.children objectAtIndex:index] : [((FSEntity *)item).children objectAtIndex:index]; 
} 

- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item { 
    return (item == nil) ? content.children.count > 0 : ((FSEntity *)item).children.count > 0; 
} 

- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item { 
    return (item == nil) ? content.children.count : ((FSEntity *)item).children.count; 
} 

- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item { 
    if ([item isKindOfClass:[FSEntity class]]) { 
     return [((FSEntity *)item) title]; 
    } 

    return nil; 
} 

- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item { 
    if ([cell isKindOfClass:[ImageAndTextCell class]]) { 
     ImageAndTextCell *textField = (ImageAndTextCell *)cell; 
     [textField setImage:[item icon]]; 
    } 
} 

- (void)defineContentNSOutlineView { 
    NSMutableArray *objects = [NSMutableArray arrayWithObjects:[NSDictionary dictionaryWithObjectsAndKeys:@"FINDER", @"title", [NSArray arrayWithObjects:[NSDictionary dictionaryWithObject:content.children forKey:@"title"], nil], @"children",[NSNumber numberWithBool:YES], @"header", nil], nil]; 
    _objects = objects; 
} 

- (void)configurationNSOutlineView { 
    [outlineView sizeLastColumnToFit]; 
    [outlineView setFloatsGroupRows:NO]; 
    [outlineView reloadData]; 
    [outlineView expandItem:nil expandChildren:YES]; 
} 

@end 

要容易想象它會怎麼看,我發現它的方案:

    +--------------------------------------------+ 
       | ▼ FINDER FILES      ₪ ✱ | 
       |  03143553.file       | 
       | ▶ Desktop        | 
       | ▶ Documents        | 
       | ▶ Downloads        | 
       | ▶ Movies        | 
       | ▶ Music         | 
       | ▶ Pictures        | 
       +--------------------------------------------+ 

和我現在擁有的(NSOulineView不使用NSTreeController);

    +--------------------------------------------+ 
       |  03143553.file       | 
       | ▶ Desktop        | 
       | ▶ Documents        | 
       | ▶ Downloads        | 
       | ▶ Movies        | 
       | ▶ Music         | 
       | ▶ Pictures        | 
       +--------------------------------------------+ 

我知道的例子蘋果「SourceView」,但我不知道如何添加到創建的組,對象(文件和文件夾),NSTreeContoller只顯示層次結構的第一要素陣列(不包括):

    +--------------------------------------------+ 
       | ▼ FINDER FILES       | 
       |  03143553.file       | 
       |  Desktop        | 
       |  Documents        | 
       |  Downloads        | 
       |  Movies        | 
       |  Music         | 
       |  Pictures        | 
       +--------------------------------------------+ 

改性SourceView示例的方法:

- (void)addFinderSection { 
    [self addFolder:@"FINDER FILES"]; 

    NSError *error = nil; 
    NSEnumerator *urls = [[[NSFileManager defaultManager] contentsOfDirectoryAtURL:self.url includingPropertiesForKeys:[NSArray arrayWithObjects: nil] options:(NSDirectoryEnumerationSkipsHiddenFiles) error:&error] objectEnumerator]; 
    for (NSURL *url in urls) { 
     BOOL isDirectory; 
     if ([[NSFileManager defaultManager] fileExistsAtPath:[url path] isDirectory:&isDirectory]) { 
      if (isDirectory) { 
       [self addChild:[url path] withName:NO selectParent:YES]; 
      } else { 
       [self addChild:[url path] withName:NO selectParent:YES]; 
      } 
     } 
    } 

    [self selectParentFromSelection]; 
} 

此方法只顯示第一對象,如它在後一方案。

還有一個問題,正如我之前說的,如何將節點**「FINDER FILES」**添加到單元格的右側。

你能幫我嗎?我知道,也許並不那麼辛苦,但我剛開始學習Objective-C,我不知道該怎麼做。謝謝。

+0

我意識到這可能不是完全有用,但我懷疑你會發現這很容易完成與基於NSView的NSOutlineView(基於NSCell的)。原因在於,對於基於視圖的NSOutlineViews,您可以添加任意數量的子視圖並保留其所有標準功能。使用基於單元格的方法,您將被困在單個單元格中,並且將多個控件的行爲組合在一起將涉及編寫自定義NSCell子類以及大量自定義繪圖和事件處理代碼。基於視圖的NSOutlineView將爲您提供免費的。 – ipmcc

回答

1

根據您提供的開始代碼,我可以使用基於Cell的NSOutlineViews獲得一些工作。您發佈的代碼似乎不完整,因此很難知道您想要從缺失的FSEntity課程中獲得什麼。我只使用基礎類:NSArray用於節點列表(即根節點和子節點),NS節點本身(根節點和子節點)以及NSURL作爲文件系統引用。我儘量保持儘可能接近您的原始代碼。最後,它看起來是這樣的:

ProjectViewController.h

@interface ProjectViewController : NSViewController <NSOutlineViewDataSource, NSObject> 
{ 
    IBOutlet NSOutlineView   *outlineView; 
    NSURL       *content; 
} 

@end 

ProjectViewController.m

#import "ProjectViewController.h" 

@interface ProjectViewController() { 
    NSMutableArray* _objects; 
} 
@property (nonatomic, retain, readwrite) NSMutableArray* objects; 
@end 

@implementation ProjectViewController 

@synthesize objects = _objects; 

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { 
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) { 
     // Initialization code here. 
     // Setting default path to the local file or directory 
     NSString *home = NSHomeDirectory(); 
     content = [[NSURL alloc] initFileURLWithPath:home]; 

     [self defineContentNSOutlineView]; 
     NSLog(@"Array: %@",_objects); 

     // Basic сonfiguration an instance NSOutlineView 
     [self configurationNSOutlineView]; 
    } 
    return self; 
} 

// nodes have 3 keys: title, url, icon 
- (NSArray*)p_childrenForNode: (NSMutableDictionary*)node { 
    if (nil == node) 
     return self.objects; 

    NSArray* retVal = nil; 
    if (nil == (retVal = [node valueForKey: @"children"])) 
    { 
     NSMutableArray* children = [NSMutableArray array]; 
     for (NSURL* urlInDir in [[NSFileManager defaultManager] contentsOfDirectoryAtURL: [node objectForKey: @"url"] 
                  includingPropertiesForKeys: [NSArray arrayWithObjects: NSURLNameKey, NSURLEffectiveIconKey, nil] 
                       options: 0 
                       error: NULL]) 
     { 
      id name = [urlInDir getResourceValue: &name forKey: NSURLNameKey error: NULL] ? name : @"<Couldn't get name>"; 
      id icon = [urlInDir getResourceValue: &icon forKey: NSURLEffectiveIconKey error: NULL] ? icon : nil; 

      NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithObjectsAndKeys: urlInDir, @"url", name, @"title", nil]; 

      if (icon) 
       [dict setObject: icon forKey: @"icon"]; 

      [children addObject: dict]; 
     } 

     retVal = children; 

     if (children) 
      [node setValue: children forKey: @"children"]; 
    } 
    return retVal; 
} 

- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item { 
    NSMutableDictionary* itemDict = (NSMutableDictionary*)item; 
    NSArray* children = [self p_childrenForNode: itemDict]; 
    return children.count > index ? [[[children objectAtIndex: index] retain] autorelease] : nil; 
} 

- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item { 
    NSMutableDictionary* itemDict = (NSMutableDictionary*)item; 
    NSArray* children = [self p_childrenForNode: itemDict]; 
    return children.count > 0; 
} 

- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item { 
    NSMutableDictionary* itemDict = (NSMutableDictionary*)item; 
    NSArray* children = [self p_childrenForNode: itemDict]; 
    NSInteger retVal = children.count; 
    return retVal; 
} 

- (id)outlineView:(NSOutlineView *)pOutlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item { 

    NSImage* icon = [item objectForKey: @"icon"]; 
    NSString* title = [item objectForKey: @"title"]; 
    id value = nil; 

    if (icon) { 
     [icon setSize: NSMakeSize(pOutlineView.rowHeight - 2, pOutlineView.rowHeight - 2)]; 
     NSTextAttachment* attachment = [[[NSTextAttachment alloc] init] autorelease]; 
     [(NSCell *)[attachment attachmentCell] setImage: icon]; 
     NSMutableAttributedString *aString = [[[NSAttributedString attributedStringWithAttachment:attachment] mutableCopy] autorelease]; 
     [[aString mutableString] appendFormat: @" %@", title]; 
     value = aString; 
    } else { 
     value = title; 
    } 

    return value; 
} 

- (void)defineContentNSOutlineView { 
    // Make root object 
    NSMutableDictionary* rootObj = [NSMutableDictionary dictionaryWithObjectsAndKeys: 
            @"FINDER", @"title", 
            content, @"url", 
            nil]; 

    id icon = [content getResourceValue: &icon forKey: NSURLEffectiveIconKey error: NULL] ? icon : nil; 
    if (icon) 
     [rootObj setObject: icon forKey: @"icon"]; 

    // Set it 
    self.objects = [NSMutableArray arrayWithObject: rootObj]; 
} 

- (void)configurationNSOutlineView { 
    [outlineView sizeLastColumnToFit]; 
    [outlineView setFloatsGroupRows:NO]; 
    [outlineView reloadData]; 
    [outlineView expandItem:nil expandChildren:YES]; 
} 

@end 

我張貼的整體,工作示例項目GitHub