问题
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, asfileOutlineView
) - 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