How to lock parent rows in NSOutlineView populated by NSTreeController - objective-c

I have an NSOutlineView that is populated from an array via an NSTreeController. I would like to make it so that rows that have children are not editable and popups in those rows are hidden. You can see my outlineview in the attached screenshot – it's essentially a tree of settings.
How can I go about this or do I need to implement the datasource via a delegate instead of using the NSTreeController to do it?

Have you looked into the delegate methods?
Specifically interesting are
– outlineView:shouldEditTableColumn:item:
which allows to determine if an item can be edited. Just check for children, if item is an parent and return NO;
Hiding the popup buttons depends on how you have setup your NSOutlineView. In a cell-based outline view use for example
– outlineView:willDisplayCell:forTableColumn:item:
to hide cell content for parent rows. In a view based outline view another method comes into play to customize certain columns:
– outlineView:viewForTableColumn:item:
This should be easy to use to achieve your results.

Related

Detect which NSTableView is active

I have an NSSplitView showing two NSTableView instances. I need to detect which table view has become "active" (of focused), which means the one that the user has clicked. I need to know that because each table view acts as a source list for another view that shows the content of the selected row(s). This other view is shared for both tables.
I could do it by subclassing NSTableView and reacting to mouseDown: or another method but it I'd rather avoid subclassing just for that. I also don't want to track any NSWindow event just to know if the user has clicked one of the tables (I'd rather subclass NSTableView).
Currently, I use the delegate method tableViewSelectionDidChange:, but this method is, obviously, only called when the selected row changes. I need to know that a table becomes active even if the selected row hasn't changed.
Observing the clickedRow property of the table views doesn't appear to work. If may not be KVO compliant.
Any ideas?
For those interested, the most convenient solution I found was to take advantage of the fact that NSTableView is a subclass of NSControl. So just like NSButton it can send action messages when clicked (upon mouse up).
For each tableView, I wired its "action" to the same ibaction selector of my controller object in interface builder.
The controller identifies the sender and acts accordingly.
No need to subclass NSTableView.

Mac: Display hierarchical lists of data plus detail view (similar to UINavigationController + UITableViewController)

I am having a serious "best-practice" issue porting my iOS app to the Mac.
I'd like to display a (searchable) list whose entries are either other lists or single entries, for which the user can then show a detail view. Under iOS, this is simply implemented by using a stack of UITableViewControllers for the lists, with another (different) UITableViewController for displaying an entry's details.
However, under OS X, we don't have UINavigationController. It might be possible to implement such a structure via an NSOutlineView or NSBrowser (which are used to display hierarchical data), but I fear that the detail view (which could be implemented as a view on the bottom-most level in the outline view or as the preview controller for the browser) will look out-of-place then. In addition, I'd like to display the list in an NSPopover (as I do on iOS), and placing an NSOutlineView or a NSBrowser inside a NSPopover might look less than elegant.
Any (more-or-less) simple solutions?
I ended up using an NSOutlineView which hierarchically shows all the lists, with a secondary popover (invoked by a button to the right of an entry's cell) for details on the individual entries.

Custom NSPopUpButtonCell outlet / bindings

I'm having a problem with a custom NSPopUpButtonCell in a table that's instantiated when the table view is populated via bindings and a NSArrayController.
The pop up button cell is created but when attempting to access the outlet by overriding the pop up button cell's setMenuItem:item method it's nil.
Is this the expected behaviour..?
Should another method be used to replace the menu at creation time?
Basically I need the outlet to link back to my controller (NSWindowController) for that document window so I can customize the NSPopUpButtonCell menu accordingly from the custom popup button when it's populated.
A solution using bindings would be even better - but when overriding setObjectValue: I can see it's only never called with a nil parameter.. using a stock NSPopUpButtonCell results in a properly populated pop up menu, though.
(see also Why is NSPopUpButtonCell showing correctly when only setObjectValue:nil is called).
You don't need to override anything to populate an NSPopUpButtonCell in an NSTableView column. The thing to know is that you set the bindings on the NSTableColumn and not on the cell itself. Typically, you would have an NSArrayController in your xib that is bound to an NSArray containing all the options for the pop-up, and then you would select the column with the pop-up cell and go to it's bindings. Like in this screenshot (note the populated Content, Content Objects, and Selected Object bindings in the inspector on the right):
If you want a working example, you can check out this project I whipped up for another StackOverflow question. There's a bunch of unrelated stuff pertaining to making the NSPopUpButtonCell use NSAttributedStrings, but the bindings in the xib constitute a working example of how to bind an NSTableColumn with a pop-up whose options are populated by bindings.

When using a view-based NSOutlineView (source list) using bindings, is it possible to not display rows from the data source based on some condition?

For example the image below shows an NSOutlineView bound to a tree structure based on folders and items using an NSTreeController:
What I want is the Item objects to remain in the model, but not to be displayed as rows, i.e:
The NSOutlineView delegate protocol has a method that informs the delegate that an item is about to be displayed, but doesn't give the option not to display it.
Is there some way in which to subclass NSOutlineView to implement this (or some other method)?
Thanks.
Presumably you're using NSTreeController which organizes your model objects according to the key path they use to identify their children.
If you want to filter anything out of the view, all you need to do is implement your child key path method to only return the children you want to display. (If you need to continue keeping track of the "real" children in your model, this may mean some extra bookkeeping to be able to return a separate list of children for display.)

Retrieving the selected object in an NSOutlineView

I am looking to retrieve the selected object in an NSOutlineView so I can see if the selected object has any children. How would I do this?
NSOutlineView inherits the -selectedRow method from NSTableView. I suspect though, that what you really want is the current selection from whatever NSController is acting as your outline view's data source.