2012-08-27 11 views
6

Sto cercando di creare un NSOutlineVew con un gruppo di intestazione personalizzato (nodo padre) per gli oggetti elencati. (NOTA: ho NSOutlineView basato su cella). Ad esempio assomiglia a Xcode "Navigator" o alla barra laterale di Numbers. Ho usato i gruppi predefiniti per le proprietà di separazione per categoria, ma sembra non come quello che voglio. Ho bisogno di un nodo genitore (cella), che potrò modificare visivamente (aggiungere elementi di controllo e immagine).Sezioni personalizzate per gli oggetti enumerati dell'array in NSOutlineView

Ho provato a farlo passando una serie di oggetti a NSDictionary, assegnando a ciascun gruppo una certa chiave specifica. E un risultato, via NSLog, tutto viene visualizzato correttamente, ma il trasferimento di questa variabile come sorgente per il programma NSOulineView fallisce.

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 

Per più facile sarebbe immaginare come sarebbe risultato, ho mostrato sullo schema:

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

e quello che ho ora (NSOulineView senza utilizzare NSTreeController);

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

che so l'esempio di Apple "SourceView", ma non so come aggiungere al gruppo creato, un array di oggetti (file e cartelle), display NSTreeContoller solo i primi elementi della gerarchia (senza comprende):

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

metodo modificato di SourceView esempio:

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

Questo metodo visualizza solo i primi oggetti, come mostrato sul quest'ultimo regime.

E un'altra domanda, come ho detto prima, come aggiungere al nodo ** "FINDER FILES" ** pulsante sul lato destro della cella.

Potete aiutarmi con questo? Lo so, forse non è così difficile, ma ho appena iniziato a imparare Objective-C e non so come farlo. Grazie.

+0

Mi rendo conto che probabilmente non è del tutto utile, ma ho il sospetto che lo troviate molto più facile da realizzare con un NSOutlineView basato su NSView (rispetto a NSCell). La ragione è che con NSOutlineViews basata sulla vista, è possibile aggiungere qualsiasi numero di sotto-visualizzazioni e conservare tutte le loro funzionalità standard. Con un approccio basato su celle, sarai bloccato con una singola cella, e combinando i comportamenti di diversi controlli comporterà la scrittura di una sottoclasse NSCell personalizzata e un sacco di codice personalizzato per il disegno e la gestione degli eventi. NSOutlineView basato sulla visualizzazione ti fornirà questo gratuitamente. – ipmcc

risposta

1

In base al codice di partenza che hai fornito, sono riuscito a ottenere qualcosa di funzionante, utilizzando NSOutlineViews su base cellulare. Il codice che hai postato sembrava incompleto, quindi era difficile sapere cosa esattamente volevi ottenere dalla classe FSEntity mancante. Ho appena usato le classi di base: NSArray per elenchi di nodi (cioè nodi radice e figli), NSDictionaries per ogni nodo stesso (entrambi i nodi radice e sub-nodi) e NSURL come riferimento per il file system. Ho cercato di rimanere il più vicino possibile al tuo codice originale. Alla fine, sembrava qualcosa di simile:

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 

ho postato l'intero, progetto di esempio lavorando per GitHub.

Problemi correlati