Re: Creating a custom hierarchical list view
Re: Creating a custom hierarchical list view
- Subject: Re: Creating a custom hierarchical list view
- From: "email@hidden" <email@hidden>
- Date: Fri, 1 May 2009 14:31:51 +0100
On 30 Apr 2009, at 21:55, Daniel Thorpe wrote:
Hi everyone, I'm wondering if anyone can put me on the right path to
create the following custom view...
I'm trying to write a new view, to displaying hierarchical data
which only uses one column. To navigate though the hierarchy, double
clicking an item in the list loads that items contents into the
list, and sets the list header to the name of the item.
Additionally, I want to have a "back" button in the list header to
go back up the hierarchy (something that looks similar to the arrow
used in iTunes to switch between selected and playing artwork).
I've briefly thought about subclassing or otherwise constraining
NSOutlineView or NSBrowser, but I think that might well make things
unnecessarily complicated. So far I've thought that it'll need the
following classes:
NSOutlineView is very flexible. You often don't need to subclass it.
It is fairly easy to concoct a range of NSCell subclasses to provide
custom behaviour.
Delegate methods allow you to manipulate the cells at will eg:
- (void)outlineView:(NSOutlineView *)anOutlineView willDisplayCell:
(id)aCell forTableColumn:(NSTableColumn *)aTableColumn item:(id)item
It's true that NSOutlineView is fairly complex but there is a lot to
be gained in working to understand its complexity.
If it was me I would work to exhaust the possibilities of using
NSOutlineView before attempting to construct an alternative.
NSView subclasses:
DTList, DTListHeader
So far, the DTList creates an NSMatrix for DTListCell cell class,
and sets this to the document view of an NSScrollView, which is
added as a subview. Additionally it'll add a DTListHeader as a
subview. This is a mixture of what NSBrowser and NSTableView have.
My DTList's initWithFrame: method looks like this at the moment...
- (id)initWithFrame:(NSRect)frame {
self = [super initWithFrame:frame];
if(self) {
// Enable subview resizing
[self setAutoresizesSubviews:YES];
// An NSMatrix is contained within an NSScrollView (the document
view)
self.matrix = [[NSMatrix alloc] initWithFrame:frame cellClass:
[DTListCell class] numberOfRows:1 numberOfColumns:1];
[matrix setAllowsEmptySelection:NO];
[matrix setAutoresizingMask:NSViewWidthSizable |
NSViewHeightSizable];
// The view contains an NSScrollView
// Leave space for the header
NSRect scrollViewFrame = frame;
scrollViewFrame.size.height -= kDTListHeaderHeight;
NSScrollView *scrollView = [[NSScrollView alloc]
initWithFrame:scrollViewFrame];
// Configure scroll view
[scrollView setHasVerticalScroller:YES];
[scrollView setHasHorizontalScroller:NO];
[scrollView setBorderType:NSNoBorder];
[scrollView setAutoresizingMask:NSViewWidthSizable |
NSViewHeightSizable];
[scrollView setDocumentView:matrix];
// Add the scroll view as a subview
[self addSubview:scrollView];
// Add a DTHeaderView
NSRect headerRect = frame;
headerRect.size.height = kDTListHeaderHeight;
headerRect.origin.y = NSMaxY(frame) - kDTListHeaderHeight;
self.header = [[DTListHeader alloc] initWithFrame:headerRect];
// Configure the header
[header setAutoresizingMask:NSViewWidthSizable];
// Add the header view as a subview
[self addSubview:header];
}
return self;
}
NSCell subclasses:
DTListHeaderCell, DTListCell
The DTListHeaderCell would actually inherit from NSActionCell as it
need to use the target/action paradigm to navigate back up the
hierarchy. DTListCell would be similar to NSBrowserCell, in that
some will be lead nodes and other branch nodes. Those that are
branch nodes need to draw a triangle (possibly a custom NSButton
subclass) at their right hand side. Leaf nodes would just draw their
string title.
Anyway, I've sort of come unstuck when it comes to the delegate/
content bindings stuff. I'm not really sure how best to start when
it comes to actually providing the objects of my hierarchy.
In terms of using a delegate, I have a protocol for DTList delegate,
it can return the number of rows, but I don't really know where to
write the code to create the DTListCell objects (presumably
retrieving the titles from the delegate?). What would my drawRect:
method look like on the DTList?
And if it used an NSTreeController? Well, I've go no idea how to
setup the bindings for that!
Bind its content to an array containing objects of type NSTreeNode.
The array elements become the top level branches in the tree.
Your tree is constructed using the documented NSTreeNode methods.
Your model objects are the NSTreeNode's represented object (unless you
want to subclass NSTreeNode for your model).
Thus your NSOutlineView tablecolumn bindings will look something like
this in IB:
entryTreeController
.arrangedObjects.representedObject.myTableColumnProperty
Note that when you get an item back/request an item from
NSTreeController it will be an NSTreeNode item (actually a subclass).
This object represents the tree from the NSTreeController's perspective.
Hence your NSTreeNode is the item's representedObject.
Any thoughts are very much appreciated, thanks for reading this far!
Cheers
Dan
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden
Jonathan Mitchell
Central Conscious Unit
http://www.mugginsoft.com
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden