• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: While on the subject of: NSOutlineView
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: While on the subject of: NSOutlineView


  • Subject: Re: While on the subject of: NSOutlineView
  • From: Andreas Mayer <email@hidden>
  • Date: Wed, 30 Jul 2003 16:25:53 +0200

Am Mittwoch, 30.07.03 um 07:32 Uhr schrieb April Gendill:

The coverage of table and outline views is at best, brief.

That's probably because it's not that difficult, really.

Table and outline views might as
well be molecular biology as far as I'm concerned.
I have absolutely no idea how they work...

If you read all those sources, you should. :) There's even a nice picture in "Learning Cocoa".

because the compiler tells me what I can
see as plain as day, that the functions return nothing, do nothing, are
useless. one of them declares a variable that never gets used,

That does not sound like a problem with NSTableView. More like a problem with (Objective-)C in general.

I would sell my first born for a "for dummys" level explanation of
outline and table views. How they work, how to manipulate the data, and
most of all how to drag an item in a table view from one position to
the next without it making a copy.

Well, that's three different things:

1. how to display data in a table view
2. how to edit data through a table view
3. how to drag-order rows of a table view

I will try to help with 1. and 2. - didn't do 3., so no help there (I will have to do that myself soon, though).

1. You need to understand that an NSTableView does not hold any data. So this

All i need to do is take a dictionary, put it in a view

is not how it works. You _don't_ 'put data in a table view'.

Instead, you just tell the table view, whom to ask if it needs to (re)display any row/column:

[tableView setDataSource:myDataSource];

Then the table view will eventually want to know how many rows it will have to handle. It sends:

[myDataSource numberOfRowsInTableView:self];

And your data source will have to answer with an integer:

- (int)numberOfRowsInTableView:(NSTableView *)aTableView
{
return numberOfRows;
}

Whenever the table view needs to display some field (a single column of a single row) it sends:

[myDataSource tableView:self objectValueForTableColumn:theTableColumn row:theRow];

Note that 'theTableColumn' is _not_ an integer, but an object of type NSTableColumn. You can identify it by sending

[theTableColumn identifier];

(You set the identifier in Interface Builder. Double click the table view, click the column and edit 'Identifier' in the 'Attributes' tab of the 'Show Info' panel.)

Now in your data source, you will have to find the object to be display in row 'theRow' and return the part of it you want to be displayed in column 'theTableColumn':

- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
{
...
someObjectForRow = (... find object for row 'rowIndex' ...)

someObjectForColumn = (... find value to display in 'aTableColumn' ...)

return someObjectForColumn;
}

These two methods, numberOfRowsInTableView: and tableView:objectValueForTableColumn:row:, are all you need to implement, to display data in a table view.

2. If you want the table view to be able to _alter_ your data, you need to implement one more method. Every time, the user has changed a value in a table view, the table view will send this to its data source:

[myDataSource tableView:self setObjectValue:newValue forTableColumn:theTableColumn row:theRow];

So you implement:

- (void)tableView:(NSTableView *)aTableView setObjectValue:(id)anObject forTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
{
...
someObjectForRow = (... find object for row 'rowIndex' ...)

(... find out which attribute corresponds to aTableColumn ...)

[someObjectForRow setValueForSomeAtttribute:anObject]
}


That's all there is about table views and data sources. If you need to implement drag and drop, look at the tableView:acceptDrop:row:dropOperation:, tableView:validateDrop:proposedRow:proposedDropOperation: and tableView:writeRows:toPasteboard: data source methods.

Now back to your specific problem.

All i need to do is take a dictionary, put it in a view and let a user
manitpulate it

Well, that's a bit of a problem. There is no inherent order of objects inside a dictionary. But for a table view data source, you will need to know which objects to display for which row. So either you use the row numbers as keys for the dictionary (not all that efficient) or you need to maintain the order of objects somewhere else; in an NSArray for instance.

Since this takes an outline view and I
have given up any hope of grasping them

Outline views are really not _that_ different from table views. For finding the values to be displayed, they basically use the same method as do table views, only that they do this for each 'parent' object.

So instead of numberOfRowsInTableView: you implement
outlineView:numberOfChildrenOfItem:
and have to tell the outline view, how much children the asked-for item has.

Similar with tableView:objectValueForTableColumn:row: - you implement
outlineView:child:ofItem:
_and_
outlineView:objectValueForTableColumn:byItem:
instead.

In outlineView:child:ofItem: you tell the outline view which child object is at the asked-for index (ofItem: denotes the parent item).

outlineView:objectValueForTableColumn:byItem: asks a item for the value to be displayed in a single column of the outline view.

To handle changes, your data source needs to implement
outlineView:setObjectValue:forTableColumn:byItem:

I thought hmm maybe if I took a
table view for the root of each dictionary, and when a user clicked the
root item, in a second table view object they would see the dictionary
contents(and be able to change them)

Sounds like the right task for an outline view:

- (int)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
{
int result = 0;
if ([item isKindOfClass:[NSDictionary class]]) {
result = [(NSDictionary *)item count];
}
return result;
}

- (id)outlineView:(NSOutlineView *)outlineView child:(int)index ofItem:(id)item
{
// note that NSDictionary.allValues does not promise any particular order of the objects,
// so you may want to do something more specific (actually, you _should_ :))
return [[(NSDictionary *)item allValues] objectAtIndex:index];
}

- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
{
... now, here you need to find the value to be displayed for item 'item' in column 'tableColumn' ...

return <some value>;
}

This should do it, basically.

Disclaimer: Code typed in Mail.app, so beware. :)


bye. Andreas.
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.

  • Follow-Ups:
    • Re: While on the subject of: NSOutlineView
      • From: Chris Hanson <email@hidden>
References: 
 >While on the subject of: NSOutlineView (From: April Gendill <email@hidden>)

  • Prev by Date: Re: A couple of NSTable questions
  • Next by Date: Re: Floating palette close behavior
  • Previous by thread: While on the subject of: NSOutlineView
  • Next by thread: Re: While on the subject of: NSOutlineView
  • Index(es):
    • Date
    • Thread