2012-08-27 15 views
6

Próbuję utworzyć NSOutlineVew z niestandardową grupą nagłówków (węzeł nadrzędny) dla obiektów wymienionych. (UWAGA: Mam NSOutlineView oparty na komórkach). Na przykład wygląda jak pasek boczny "Nawigator" Xcode lub Numbers. Użyłem domyślnych grup dla właściwości separacji dla każdej kategorii, ale wygląda na to, że nie tak, jak chcę. Potrzebuję węzła nadrzędnego (komórki), który będę mógł wizualnie dostosować (dodać elementy sterujące i obraz).Niestandardowe sekcje dla wyliczonych obiektów tablicy w NSOutlineView

Próbowałem to zrobić, przekazując tablicę obiektów do NSDictionary, nadając każdej grupie określony określony klucz. I wynik, przez NSLog wszystko jest wyświetlane poprawnie, ale transfer tej zmiennej jako źródła dla programu NSOulineView kończy się niepowodzeniem.

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 

Aby łatwiej byłoby sobie wyobrazić, jak to będzie wyglądać, pokazałem to na schemacie:

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

i co mam teraz (NSOulineView bez użycia NSTreeController);

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

wiem o przykład Apple „SourceView”, ale nie wiem jak dodać do utworzonej grupy, tablicę obiektów (plików i folderów), wyświetlacz NSTreeContoller tylko pierwszych elementów hierarchii (nie zawiera)

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

zmodyfikowanej metody z przykładu SourceView: tylko

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

Ta metoda wyświetla pierwsze przedmioty, jak pokazano to na drugim systemie.

Jeszcze jedno pytanie, jak już powiedziałem, jak dodać do węzła ** Przycisk "FINDER FILES" ** po prawej stronie komórki.

Czy możesz mi w tym pomóc? Wiem, może nie jest to takie trudne, ale dopiero zacząłem uczyć się Objective-C i nie wiem jak to zrobić. Dzięki.

+0

Rozumiem, że to prawdopodobnie nie jest całkowicie pomocne, ale podejrzewam, że byłoby to o wiele łatwiejsze do osiągnięcia dzięki opartemu na NSView NSOutlineView (w odróżnieniu od NSCell). Powodem jest to, że z widokami NSOutlineViews można dodawać dowolną liczbę subviews i zachować wszystkie ich standardowe funkcje. Dzięki podejściu opartemu na komórkach utkniesz w pojedynczej komórce, a łącząc zachowania kilku kontrolek, będziesz pisać niestandardową podklasę NSCell i mnóstwo niestandardowego kodu do rysowania i obsługi zdarzeń. Oparty na widoku NSOutlineView dostarczy ci tego za darmo. – ipmcc

Odpowiedz

1

Na podstawie podanego kodu początkowego udało mi się uzyskać coś działającego, korzystając z NSOutlineViews opartego na komórkach. Opublikowany kod wydawał się niekompletny, więc trudno było określić, co dokładnie chciałeś uzyskać z brakującej klasy FSEntity. Właśnie użyłem klas fundamentów: NSArray dla list węzłów (tj. Węzłów głównych i potomków), NSDictionaries dla każdego węzła (zarówno węzłów głównych i pod-węzłów), i NSURL jako odniesienie do systemu plików. Próbowałem pozostać tak blisko oryginalnego kodu, jak to tylko możliwe. W końcu, wyglądało to mniej więcej tak:

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 

napisałem całość, pracując przykładowy projekt do GitHub.

Powiązane problemy