How do i make a simple view-based NSOutlineView?

不羁的心 提交于 2019-12-20 12:27:41

问题


For learning purposes i would like to convert a cell-based NSOutlineView to a view-based one,

basically i would like the following:

  • instead of a normal cell, i'd like an 'image and text table cell view'
  • the image can be the stock NSApplicationIcon and the text can just be 'hello world' :)
  • I'd like to do this without using bindings and NSTreeController

Here is the 'worlds simplest NSOutlineView' example http://www.cocoasteam.com/Cocoa_Steam/Worlds_Simplest_Demo.html

I wonder if someone could modify it to make it view-based and work like i said above :) :)

I've tried looking at apple examples, and searching elsewhere on the internet but i still can't get it to work - so thanks very much in advance :)


回答1:


OK, so you want an NSOutlineView with ImageAndTextCell cells, right?

Let's do one of the most typical examples of this kind : a simple file explorer.

What we'll need :

  • an NSOutlineView (put an outline to your AppDelegate, as fileOutlineView)
  • create 3 columns in the Outline with the following Identifiers (set them up in Interface Builder) : NameColumn, SizeColumn, ModifiedColumn

Now, as for the rest, I'll do it all programmatically, so that you get a good idea of what's going on...

How to set it up (e.g. in - (void)awakeFromNib):

// set the Data Source and Delegate
[fileOutlineView setDataSource:(id<NSOutlineViewDataSource>)self];
[fileOutlineView setDelegate:(id<NSOutlineViewDelegate>)self];

// set the first column's cells as `ImageAndTextCell`s
ImageAndTextCell* iatc = [[ImageAndTextCell alloc] init];
[iatc setEditable:NO];
[[[fileOutlineView tableColumns] objectAtIndex:0] setDataCell:iatc];

Connecting the dots :

/*******************************************************
 *
 * OUTLINE-VIEW DATASOURCE
 *
 *******************************************************/

- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
{        
    if ([item isFolder])
        return YES;
    else
        return NO;
}

- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
{    
    if (item==nil)
    {
        // Root
        return [[filePath folderContentsWithPathAndBackIgnoringHidden] count];
    }
    else
    {        
        if ([item isFolder])
        {
            return [[item folderContentsWithPathAndBackIgnoringHidden] count];
        }
        else
        {
            return 0;
        }
    }
}

- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item
{
    if (item == nil)
    { 
        // Root
        return [[filePath folderContentsWithPathAndBackIgnoringHidden] objectAtIndex:index];
    }

    if ([item isFolder])
    {
        return [[item folderContentsWithPathAndBackIgnoringHidden] objectAtIndex:index];
    }

    // File
    return nil;
}

- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)theColumn byItem:(id)item
{          
    if ([[theColumn identifier] isEqualToString:@"NameColumn"])
    {
        return [item lastPathComponent];
    }
    else if ([[theColumn identifier] isEqualToString:@"SizeColumn"])
    {
        if ([item isFolder]) return @"--";
        else return [NSString stringWithFormat:@"%d",[item getFileSize]];
    }
    else if ([[theColumn identifier] isEqualToString:@"ModifiedColumn"])
    {
        if ([item isFolder]) return @"";
        else return [NSString stringWithFormat:@"%@",[item getDateModified]];
    }

    // Never reaches here
    return nil;
}

/*******************************************************
 *
 * OUTLINE-VIEW DELEGATE
 *
 *******************************************************/

- (BOOL)outlineView:(NSOutlineView *)outlineView shouldSelectItem:(id)item
{
    return YES;
}

- (BOOL)outlineView:(NSOutlineView *)outlineView isGroupItem:(id)item
{
    return NO;
}

- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item {
    [cell setDrawsBackground:NO];

    if ([item isFileHidden]) [cell setTextColor:[NSColor grayColor]];
    else [cell setTextColor:[NSColor whiteColor]];

    if ([[tableColumn identifier] isEqualToString:@"NameColumn"])
    {
        if ([item isFolder])
            [cell setImage:[[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(kGenericFolderIcon)] size:15.0];
        else
            [cell setImage:[[NSWorkspace sharedWorkspace] iconForFile:item] size:15.0];

        if ([item isFileHidden])
        {
            [cell setFileHidden:YES];
        }
        else
        {
            [cell setFileHidden:NO];
        }

    }

}

Hint : ImageAndTextCell class can be found here. You'll also notice a few other methods I'm using, which are obviously NOT supported by Cocoa (e.g. isFileHidden, isFolder or folderContentsWithPathAndBackIgnoringHidden) but it's not that difficult to implement them yourself...)




回答2:


I have created a little sample project which does just that.

  • Display a list of items
  • Edit the items in a master-detail fashion
  • Remove and add items
  • Usage of bindings

Check out besi/mac-quickies on github. Most of the stuff is either done in IB or can be found in the AppDelegate




回答3:


To return view to OutlineView column Instead of using datasource method that return objectValue:

- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)theColumn byItem:(id)item

USE THE DATASOURCE METHOD THAT RETURN VIEW!!!!!!!!:

- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item

everything else is the same(minimal req is the first three datasource methods, you don't need the delegate methods) but, you can't use willdisplaycell its called only for cell based , do everything to the view in the viefortablecolumn method like this:

if ([[tableColumn identifier] isEqualToString:@"YourColumnIdentifier"]){
    NSTableCellView *cell = [outlineView makeViewWithIdentifier:@"YourViewsIdentifier" owner:self];
    [cell.textField setStringValue:[(YourItem *)item name]];
    [cell.imageView setImage:[(YourItem *)item image]];
    return cell;
}

return nil;

and don't forget to set identifiers , and to set the OutlineView to be View Based(in IB ...).




回答4:


Check TableViewPlayground, also View Based NSTableView Basic to Advanced from WWDC 2011.



来源:https://stackoverflow.com/questions/10084254/how-do-i-make-a-simple-view-based-nsoutlineview

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!