i've got a Delegate class for a Source List. But i don't know what type the return variable of outlineView:objectValueForTableColumn:byItem: should be.
At the Moment my code looks like this, all the structure things work but there is no text shown:
#interface DataSource : NSObject<NSOutlineViewDelegate,NSOutlineViewDataSource>
#end
And the .m
#implementation DataSource
// Data Source methods
- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
return (item == nil) ? 1 : [item numberOfChildren];
}
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item {
return (item == nil) ? YES : ([item numberOfChildren] != -1);
}
- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item {
return (item == nil) ? [FileSystemItem rootItem] : [(FileSystemItem *)item childAtIndex:index];
}
//-(id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item
-(id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item {
return #"Some String";
}
#end
I have made a example app to show the difference. Image is here
I suppose you have view-based NSTableView. In you delegate you should implement method - (id)outlineView:(NSOutlineView *)ov viewForTableColumn:(NSTableColumn *)tableColumn. It may looks like this:
- (id)outlineView:(NSOutlineView *)ov viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item{
if ([[item representedObject] parent] == nil) {
return [ov makeViewWithIdentifier:#"HeaderCell" owner:self];
}else{
return [ov makeViewWithIdentifier:#"DataCell" owner:self];
}
}
HeaderCell and DataCell are default identifiers of the Table Cell Views.
Related
My app has a cell-based NSOutlineView which its data source is a NSMutableArray. In the initialisation, my app loads the NSMutableArray from a text file. Then, the NSOutlineView will be populated with the NSMutableArray.
NSOutlineView is populated with the NSMutableArray prior to OSX 10.10. In OSX 10.10, the NSOutlineView is empty, i.e. no data is displayed. I put the NSLog in the data source methods and found that in 10.10, only - (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item is called. The other 3 data source methods are not called.
I don't have OSX 10.10 to debug for this issue. Please help.
#interface AppController : NSObject {
...
IBOutlet NSOutlineView *outlineViewCmdSet;
}
#pragma OutlineView for CmdSet
// Data Source methods
- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
return (item == nil) ? [cmdTree count] : [item numberOfChildren];
}
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item {
return (item == nil) ? YES : [item isExpandable];
}
- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item {
return (item == nil) ? [cmdTree objectAtIndex:index] : [[item children] objectAtIndex:index];
}
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item {
return [item nodeName];
}
// Delegate methods
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldEditTableColumn:(NSTableColumn *)tableColumn item:(id)item {
return NO;
}
// Drag command to ScriptEditor
- (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pboard {
// Single Selection. items array has only 1 object
TreeItem *item = [items objectAtIndex:0];
if ([item isExpandable]) // Group Name
{
return NO;
}
else // Command Name
{
// Copy the Command Name to the pasteboard.
[pboard declareTypes:[NSArray arrayWithObject:CommandTreeViewDataType]
owner:self];
[pboard setString:[item nodeName] forType:CommandTreeViewDataType];
return YES;
}
}
Thanks everyone. I have fixed this issue by moving the initialisation of the Mutable Array from applicationDidFinishLaunching to awakeFromNib.
Strangely enough, prior to 10.10, applicationDidFinishLaunching is called before the OutlineView data source methods but not in 10.10. Anybody has any idea of this?
I am using a "SourceList" OutlineView and cannot get the content of the "header" and "data" NSTableCellViews to display. The structure of the OutlineView works and my app runs and looks similar to this, http://i.stack.imgur.com/0E4D8.png.
Here is my code:
- (id)init {
self = [super init];
if (self) {
_masterFolder = [[NSMutableArray alloc] init];
MasterFolder *trueMaster = [[MasterFolder alloc] initMaster:#"Categories"];
[_masterFolder addObject:trueMaster];
[trueMaster addChild:[[MasterFolder alloc] initMaster:#"World"]];
[trueMaster addChild:[[MasterFolder alloc] initMaster:#"Sports"]];
[trueMaster addChild:[[MasterFolder alloc] initMaster:#"Local"]];
[trueMaster addChild:[[MasterFolder alloc] initMaster:#"Business"]];
[(MasterFolder *)[trueMaster.children objectAtIndex:0] addChild:[[MasterFolder alloc] initMaster:#"Middle East"]];
}
return self;
}
- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
return !item ? [self.masterFolder count] : [[item children] count];
}
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item {
return !item ? YES : [[item children] count] != 0;
}
- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item {
return !item ? [self.masterFolder objectAtIndex:index] : [[item children] objectAtIndex:index];
}
- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item {
if (![item isKindOfClass:[MasterFolder class]]) {
return [outlineView makeViewWithIdentifier:#"HeaderCell" owner:self];
} else {
NSTableCellView *cellView = [outlineView makeViewWithIdentifier:#"DataCell" owner:self];
cellView.textField.stringValue = [((MasterFolder *)item) name];
return cellView;
}
}
I know it is an issue with this function:
- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item {
but I do not know what to change to make it work. I have viewed a lot of similar posts on Stack Overflow already, and was not able to get the solutions that were offered to work.
I have two tables (NSTableView) on a window. Well, the number is irrelevant. Anyway, the source of the first table (tableView1) is NSMutableArray with NSMutableDictionary. And I have the following code.
- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView {
if (aTableView == tableView1) {
return [itemArray1 count];
} else {
...
}
}
- tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)TableColumn row:(NSInteger)rowIndex {
// tableView1
if (aTableView == tableView1) {
NSString *foldername = [[itemArray1 objectAtIndex:rowIndex] objectForKey:key1a];
NSString *count = [[itemArray1 objectAtIndex:rowIndex] objectForKey:key1c];
if ([[TableColumn identifier] isEqualToString:#"folder"]) {
return foldername;
}
if([[TableColumn identifier] isEqualTo:#"count"]){
return count;
}
else {
return #"";
}
// tableView2
} else {
...
}
}
I get what I want, and the second column shows the number of items (count). I wonder how I can possibly draw this number like the SidebarDemo example project? (Shown at the bottom...) This project utilizes - (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item to show a static number (42). Can I show the number like that with NSTableView as well? I could just draw a circled number if it were an iOS application.
Thank you for your advice.
tableView:viewForTableColumn:row: (NSTableViewDelegate) should work similar.
After changing NSOutlineView cell-based to view-based, it's not display the icons and titles of file-system tree. Here my code:
- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item {
if ([[tableColumn identifier] isEqualToString:#"name"])
return [(ImageAndTextCell *)cell setTextFieldImage:[item icon]];
}
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item {
return [((ConstructorFSEntity *)item) title];
}
- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item {
if ([item isKindOfClass:[FSEntity class]]) {
return [outlineView makeViewWithIdentifier:#"HeaderCell" owner:self];
} else {
return [outlineView makeViewWithIdentifier:#"DataCell" owner:self];
}
}
And I've one more question. How to put the enumerated items (array of file system's item) to the cell "DataCell", and "HeaderCell" declare as parent folder (group) and assign it a title (for example, # "Root Folder") and the path of the class. Because, now previous view-based method, displayed enumerated item only in "HeaderCell" or "DataCell" and when I trying assign to "HeaderCell" a some value, the app crashing. Can you help me with this?
To display the titles and icons of items, you need just to change this method
- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item
as follows:
- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item {
if (![item isKindOfClass:[FSEntity class]]) {
return [outlineView makeViewWithIdentifier:#"HeaderCell" owner:self];
} else {
NSTableCellView *cellView = [outlineView makeViewWithIdentifier:#"DataCell" owner:self];
[(ImageAndTextCell *)cellView.textField.cell setTextFieldImage:[item icon]];
cellView.textField.stringValue = [((FSEntity *)item) title];
return cellView;
}
}
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 :)
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
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...)
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 ...).
Check TableViewPlayground, also View Based NSTableView Basic to Advanced from WWDC 2011.