why objectValueForTableColumn is called so many times for outlineView? - objective-c

I'm learning outline view of cocoa by Apple OS x developer library. The example source is like this:
- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item {
return (item == nil) ? [FileSystemItem rootItem] : [(FileSystemItem *)item childAtIndex:index];
}
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item {
return (item == nil) ? YES : ([item numberOfChildren] != -1);
}
- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
return (item == nil) ? 1 : [item numberOfChildren];
}
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item {
return (item == nil) ? #"/" : [item relativePath];
}
This will list all files in my system like a tree.
The question is:
1. if there are 32 files under the "/", the method
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
will be called 62 times, I don't know why?
2. the method
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
doesn't have a parameter about the row, then how the cocoa to determine which row the item should be displayed?

if there are 32 files under the "/", the method
(id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
will be called for each row and column as it is displayed. I assume you have 2 columns and 31 rows are actually shown.
the method doesn't have a parameter about the row, then how the cocoa to determine which row the item should be displayed?
The item is a pointer to the object used to populate the table. This is all the NSOutlineViewDataSource Protocol needs to know. Details of displayed rows in internal to the NSOutlineView

Related

Cocoa App NSOutlineView is not populated in Mac OS 10.10

My Cocoa app has a NSOutlineVew which is populated with data read from a text file and it's basically static and loaded only once in the beginning.
Prior to 10.10, the NSOutlineView works and user can drag and drop item from it to a NSTableView. However, if we run the app in 10.10, the NSOutlineView is not populated with the data and basically is just empty. There is no error message in the console log. Basically, what we found out is that the following codes are not executed in 10.10.
#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];
}
My app basically is written with AppController and I attach the code and screenshots for your reference.
#interface AppController : NSObject {
...
IBOutlet NSOutlineView *outlineViewCmdSet;
}
Can anyone point me to the correct direction how I can solve this to be able to run in both 10.10 and the prior versions? Our clients are using different Mac OS. It's good to be able to support all of the OSes.
The OutLine View in Interface Builder

Tooltip for Cell-based NSTableView

I have a view which (among other elements) holds a cell based NSTableView. I made the ViewController the delegate of the table. The view controller is created programmatically and added to an NSStatusItem.
I implemented:
- (BOOL)tableView:(NSTableView *)tableView shouldShowCellExpansionForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
return YES;
}
- (NSString *)tableView:(NSTableView *)aTableView toolTipForCell:(NSCell *)aCell rect:(NSRectPointer)rect tableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)row mouseLocation:(NSPoint)mouseLocation {
return #"A tooltip";
}
- (BOOL)tableView:(NSTableView *)tableView shouldTrackCell:(NSCell *)cell forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
return YES;
}
- (void)tableView:(NSTableView *)aTableView willDisplayCell:(id)aCell forTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex {
NSLog(#"Display");
}
But when I run my code the only one of these methods that gets called is:
- (void)tableView:(NSTableView *)aTableView willDisplayCell:(id)aCell forTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex;
Any idea what might be wrong?
My real objective is to dinamycally define the tooltips for my cells.
I've just needed to solve this problem for my app's development.
These delegate methods you mentioned above are only for the expansion tooltip of a text cell, that shows full text when truncated.
A possible solution is to add an observer of NSViewFrameDidChangeNotification in which the tooltip rectangles are rearranged using addToolTipRect:owner:userData:. The code is something like:
NSTableView *tableView; // the target tableview
- (void)tableViewSizeDidChange:(NSNotification *)theNotification {
[tableView removeAllToolTips];
for (NSInteger row = 0; row < tableView.numberOfRows; row ++) {
NSRect rowRect = [tableView rectOfRow:row];
for (NSInteger col = 0; col < tableView.numberOfColumns; col ++) {
NSRect colRect = [tableView rectOfColumn:col];
NSRect cellRect = NSIntersectionRect(rowRect, colRect);
[tableView addToolTipRect:cellRect owner:
/* Tooltip string for cell at row and col */ userData:NULL];
}}
}
- (void)windowDidLoad {
...
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(tableViewSizeDidChange:)
name:NSViewFrameDidChangeNotification object:tableView];
...
You may also need to call tableViewSizeDidChange: when a table column was moved or resized.

NSOutlineView, setFloatsGroupRows: not working

I know it should work, I can see it in sample projects, but in my sample project I can't force outline view to float group rows. The code is straightforward, everything works except that feature. Probably I'm missing something obvious.
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
[self.outlineView setFloatsGroupRows:YES];
}
- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item
{
if (item == nil)
return [#[#"1", #"2",#"3",#"4",#"5"] objectAtIndex:index];
return nil;
}
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
{
return NO;
}
- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
{
if (item == nil)
return 5;
return 0;
}
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
{
return item;
}
- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item
{
NSTableCellView *tableCellView = [outlineView makeViewWithIdentifier:[tableColumn identifier] owner:self];
return tableCellView;
}
- (BOOL)outlineView:(NSOutlineView *)outlineView isGroupItem:(id)item
{
if ([#[#"1", #"2",#"3",#"4",#"5"] indexOfObject:item] == 0)
return YES;
return NO;
}
Edit I added NSTableView alongside NSOutlineView to my project, added the same datasource and delegate methods and table view's group row flows, when outline view's one still doesn't. I'm wondering what I am missing, why outline view's group row doesn't want to fly?..
Solved. In NSOultineView group rows float only over its child rows. They don't float over other non group rows but NSTableView does. So if you have a group row without child items like in my example then it won't float.
In my opinion it's a bug or at least there shoud be an option for both cases (for at least a consistency with a table view behaviour).
Make sure self.outlineView IBOutlet is connected to the NSOutlineView in the xib.

Display content on NSoutlineView from NSTreeNode

I want to display data in an NSOutlineView. I have an NSTreeNode with data, but I don't know how to display the contents of the NSTreeNode in an NSOutlineView.
I have wasted a lot of time googling buy I couldn't found anything which could full-fill my requirement.. Can anyone help me?
The best thing to do is to study the example DragNDropOutlineView, Getting data wrapped inside the NSTreeNode is easy, you simply access to the representedObject property
For example take a look at (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item present in DragNDropOutlineView, where item is an NSTreeNode instance
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item {
id objectValue = nil;
SimpleNodeData *nodeData = [item representedObject];
...
...
}

NSOutlineView Problem with Child / Parent element

I am implementing NSOutlineView and having implemented following method,
-(void) initOutlineView{
pMyOutlineView = [[[MyUICustomOutlineView alloc] initWithFrame:clipViewBounds]
autorelease];
NSTableColumn* firstColumn = [[[NSTableColumn alloc] initWithIdentifier:#"firstColumn"] autorelease];
[firstColumn setWidth:25];
[pMyOutlineView addTableColumn:firstColumn];
NSTableColumn* secondColumn = [[[NSTableColumn alloc] initWithIdentifier:#"secondColumn"] autorelease];
NSTextFieldCell *pCell = [[NSTextFieldCell alloc]init];
[secondColumn setDataCell:pCell];
[secondColumn setWidth:180];
[pMyOutlineView addTableColumn:secondColumn];
[pMyOutlineView setRowHeight:30];
pNodeArray = [[NSMutableArray alloc]initWithCapacity:10];
PointerNode *pNode = pointerList.getHead();
int idx =0;
void *ptr = nil;
while ( contact ) {
[pNodeArray insertObject:[NSValue valueWithPointer:(void *)pNode]
atIndex:idx];
pNode = pNode->getNext();
idx++;
}
[pMyOutlineView setDataSource:self];
// this is to tell myCustomOutlineView to delegate Menu and Mouse event to
// this interface
[pMyOutlineView setDataDelegate:self];
[scrollView setDocumentView:pMyOutlineView];
[pMyOutlineView setDelegate:self];
}
And Implemented following delegate Method
- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
// Here it will come for the top level element
if(item==nil)
return pointerList.size();
/*
If its not NULL then it must be some child element
*/
if([item isKindOfClass:[NSValue class]])
{
// yes it may have children
PointerNode *pNode = (PointerNode *)[item pointerValue];
if(pNode->hasChildren()){
return pNode->getNoOfChild();
}
}
return 0; // means this element not going to have any children
}
Some other method
- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
and get data
i am following some blogs , tutorial,
the problem what i am facing is as par documentation it should hit in numberOfChildrenOfItem for each element where we need to calculate and send the No of child for that item,
but the problem what i am facing, its coming to above function only once and for that too item is nil, i.e. its not coming for other element,
Am i missing any method that needs to be delegate
other method which i override is as below,
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)aTableColumn byItem:(id)item
- (void)outlineView:(NSOutlineView *)outlineView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
Please tell me , which method i am missing
In outlineView:numberOfChildrenOfItem:, you need to test if item is nil and, if so, return the number of children of the top level object. Quoting the documentation,
If item is nil, this method should return the number of children for the top-level item.
If you’re returning 0 when item is nil, the outline view considers that there are no children for the top level item, hence it won’t send this message again to your data source object.
#Rohan did you implemented the datasource methods or not.
Check out the documentation for the NSOutlineView
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSOutlineView_Class/Reference/Reference.html