How do I implement a customized list in Cocoa? - cocoa

I want to build a Cocoa App with a list of entries very similar to the ToDo list of Things.app (see the screencast). The question is whether I should use
a TableView,
a CollectionView or
a WebView.
I think it could work with all of them, but which one suits the following requirements best?
have a list of entries -> 1 column & many rows
reordering with drag & drop
select single entries & use keys for actions like delete
open up an entry: the row should expand to show more input fields
customized look: rounded corners, shadow, background gradient
So far my research says that the TableView has most of the functionality, but is harder to customize in its appearance, the CollectionView doesn't have drag & drop (right?) but is easy to design and the WebView would take much effort to not hurt the user experience and I can't bind my model directly to input fields.
What pros and cons am I missing and what would you recommend to use?

A WebView doesn't make sense. You might as well create a web application if you use a WebView. An NSCollectionView is more for grid like data, like TV listings per hour.
NSTableView is the only one that makes sense in this case. I've implemented all 5 bullet points with with an NSTableView without issue. You need to extend NSTableView and do some custom drawing for the customized look. That's the hardest part.

open up an entry: the row should expand to show more input fields
You need an outline view. A table view is for flat lists.
Note that NSOutlineView is a subclass of NSTableView, so all the table-view features work on an outline view as well.

There are people who've done this already. One that I've used successfully is by Matteo Bertozzi and is available here: http://th30z.netsons.org/2009/03/cocoa-sidebar-with-badges-take-2/ It might take a bit of massaging to get it to work properly (especially if you need complex drag-and-drop behavior), but for basic functionality, such as getting the section titles and items in the list, it works excellently.
Edit: This has come up before and is a common question on the cocoa-dev email list. Here are some other options.

Just took a look at Things.app itself using "F-script anywhere".
They've used a subclass of NSTableView called "DetailTableView" which presents the condensed todo items. Collapsed todo items are implemented using a custom cell called "ToDoCell", but the expanded look you get when editing is interesting. In that case they've got a custom view called "ToDoEditView" which is inserted as a subview of the DetailTableView when required. I suspect this editing view is temporarily added as a subview in the correct location and the corresponding row of the tableview gets resized temporarily while it is present.
All pretty speculative .. I'd love to know the details of how this was done. It's an awesome UI.

I'm approaching the very same problem in my app (with one big list similar to the Things todo list) and I think a table view would make a lot of sense here.
The trick is having your cells ("rows") expand when double-clicked. That's about all the progress I've made so far.

Related

Cocoa OSX custom widgets/controls

I want to know how can I create custom widgets/controls in Cocoa.
Not a full tutorial, but some guidance on what to start looking into. I'm confused by custom views, Core Animation, etc. I feel lost.
I see a lot of cool looking controls, like in Reeder App, or Sparrow etc. For example:
The left side is a collapsable menu that includes animations etc. How can I achieve something similar? I thought of using a WebView + HTML + JavaScript, but that doesn't seem like a very optimized solution.
Controls are views, so if custom views confuse you, you'll need to get that figured out before moving on to custom controls. Although you should really read the entire View Programming Guide, the section called Creating a Custom View will get you started on creating your own views. Try creating a simple view that draws a circle, for example, or the time.
When you've got views figured out, move on to custom controls. Most controls work about the same way. The user touches them, and the control responds by: a) tracking the user's input, b) changing its value, c) sending its action message to its target, and d) giving the user some feedback by redrawing itself. To get started, first make sure that you know how to use controls. Reading Control and Cell Programming Topics should help, and the section titled Subclassing NSControl covers (obviously) creating your own subclasses.
The example you provided is pretty clearly Apple's Mail.app. The view on the left side of the window might be an instance of NSOutlineView, or it might be a custom class. Either way, NSOutlineView would be a good starting point if you want to duplicate that functionality. NSOutlineView is a subclass of NSTableView, which in turn is a subclass of NSControl, which in turn is a subclass of NSView. Read Outline View Programming Topics for help getting started -- tables and outlines are extremely useful, but also more complicated to use than basic controls like buttons and text fields.
I know it's only a part of the UI, but I've recently coded something similar to the sidebar. If you look though the source-code it may give you some help on learning how to use custom controls and cells.
You can check it out on Github:
https://github.com/iluuu1994/ITSidebar

Choosing between NSTableView and NSOutlineView

I'd really like to create a table view that is segmented similar to the screen shown ( which is taken from the XCode->Build Phases view ). To be honest, I'm a bit lost on how to start there.
I could use a NSTableView + a custom NSTableCellView that manages the expanding/collapsing behaviour, but I'm entirely not sure if the resizing of an individual row is possible or permitted ( the doc isn't too verbose here ).
The second approach would be to choose a NSOutlineView to accomplish this behaviour, yet it would require some serious subclassing to get where I'd like to go.
So, before I'm doing it wrong again, what would you do? Thanks a lot for your time
– Moritz
I am quite sure that is an NSOutlineView (not sure if is one big outline or 4). The subclassing isn't as hard as it looks. The only item that requires custom drawing is the root element (that's the row with the disclosure triangle.)

XCode iPad split view controller with detail views containing several form controls

Fairly new to Mac and XCode 3.2.6 and iPad. I have a fairly simple business data model to implement on the iPad, but can't seem to find the combination of views and controllers to use.
It's a simple data collection program, but there are too many data fields to fit on a single screen so I've resorted to the Split View approach.
I've got eight rows of table data on the left; RootViewController is the default UITableViewController. I'm trying to write the program such that when any of those table rows are selected, the view on the right (Detail View) gets redrawn and populated with a bunch of different controls (labels, buttons, text fields, etc.) that correspond to the selection on the left. Currently all the Details views are plain UIViewControllers.
For instance, the first "tab" might be titled "Personal", and I need to display fields to collect info such as Name, DOB, Height, Weight, etc. The next one might be "Address" where I need to collect Street, City, ZIP Code, etc. The next one might be "Employer", where I'd like to collect the employer's name, address, phone number, etc. These are mostly static and unchanging, but there are enough fields for about 8 screens worth.
I've got all this laid out in Interface Builder, but when I run it on the iPad simulator and click the very first button on the very first view, the connected delegate isn't called. I've put a breakpoint there and it's not being hit.
Is there some special magic to using simple UIViewControllers on the right side of a UISplitViewController, as far as letting them contain other simple Label, TextBox, and Button controls?
Also is there any special magic in that the framework built the original start-up code with a RootViewController.h/.m and DetailViewController.h/.m pair? Am I correct in thinking that a single detail view represents the entire iPad screen to the right of the Table View, and that to add more "pages" we need to write more files and .XIBs like DetailViewController?
Final question is how to implement the data model for this app. I noticed when the project was first auto-created, there weren't any source files for the model. (Maybe most of the predefined app types don't auto-generate anything for the model, but I understand that's a big part of model-view-controller paradigm.) Anyway these data fields on all the various views will eventually be part of a SQLite record that I'd like to save and load from storage. Where would I begin to wire all that stuff in to all the auto-generated "view centric" code?
If anyone has seen a "how to write real business apps for the iPad" website along the lines of anything like this, please post the link. I'm not trying to display jpegs of various fruits in a single (reused) view on the right side; I'm trying to display several real controls for real-world data collection for a real business app.
Thanks!
Basic things if you haven't already done them:
Have you connected the interface object the user is pressing from it's INSIDE TOUCH UP event to an IBOUTLET that then refreshes the right side?
If you have, and you've mucked about a bit (ie renaming and moving stuff around), try deleting it from the right-click event panel and then reconnecting it to the same IBOUTLET again (you don't have to delete any code).
Also, if you are counting on some event to fire that isn't firing, you should search on that (ie VIEWDIDLOAD NOT FIRING) because that can both occasionally be "broken" (ie no connection to the Files Owner) but more often one might misunderstand when that actually gets fired (ie VIEWDIDLOAD vs VIEWDIDAPPEAR vs VIEWWILLAPPEAR etc.)
For your data model, CoreData is your friend. It provides a modell-oriented approach and easily allows to persist data.
For your navigation needs, I think a tabBarController better suits your needs.
Changing the detail view from the master view can be troublesome, especially when using a NavigationController as detail view. The best way I've found is using the NSNotificationCenter.
When using UISplitview I strongly recommend to support the iPad only when it's a business requirement - there are some changes in iOs 8 that make easier to use.

How to imitate the workflow view of Automator?

I’m starting to develop my first full-blown Cocoa application containing a view which I would like to behave (and look) similar to Automator’s AMWorkflowView.
The basic features I’d like to achieve:
Positioning of subviews
Display of subviews in expanded / collapsed states
Multiple selection
Drag and drop
In order to get accustomed to Cocoa, I started with a custom NSView which mainly served as a container for the custom subviews and handled their positioning and multiple selection.
The subviews are also subclasses of NSView, and contain a variable amount of views themselves, like buttons, labels and popup menus, and therefore can have different heights.
This worked quite well, but before going on, I want to make sure to have everything neat and tidy according to the MVC pattern.
I suspect that there already is a class in Cocoa that facilitates the implementation of a view container, like maybe NSCollectionView.
It seems that there is no (easy) way to display differently sized views in an NSCollectionView, though. Should I continue implementing my custom NSView (probably using an NSArrayController for selection and sorting support), or are there better ways to go?
Any help is much appreciated
Unfortunately the answer is you'll have to roll your own. NSCollectionView does not allow for variable-sized items (which also rules out expanded/collapsed states).
For a limited number of items, you can accomplish this rather easily (you just need a container view that arranges the subviews properly when asked to layout, then you need to make sure you re-layout when things change). For many subviews, however, you'll need to take care to be as efficient as possible. This can start with laying out as little as possible (only those "after" the resized view, for example) and get as complex as caching a visual representation of a prototype view, drawing the cached images (fast!) for all but the view being edited, and only using/positioning a "real" view for the view being edited.
Drag and drop works the same as it always has, but none of the above accounts for the pretty animation NSCollectionView gives you. :-) It's fast and beautifully-animated precisely because all the subviews are uniform (so the layout calculations are fast and simple). Once you add irregular sizes, the problem becomes significantly more complicated.
The bottom line: If you need variably-sized views, NSCollectionView will not work and you'll need to roll your own or find someone else's shared code, but performance and beautiful animation will not be easy.

How would one implement a sidebar similar to Mail/iTunes/Finder/etc in Cocoa/IB?

I think the title pretty much says it all... I'm looking to implement an interface similar to the standard OS X sidebar used in all the above mentioned programs, and I'm wondering if anybody has any thoughts as to the easiest way to do it, namely about what view to use for the left hand selection pane. Really I don't think I even need the hierarchical component as seen in the apple apps, I just need a good looking flat list of choices which determine what's shown in the right hand pane.
The obvious start is a vertical split layout view, but beyond that I'm not entirely sure where to go. A collection view with only one column or something like that?
I've done a few applications that use a similar setup.
I generally use an NSSplitView, with a single column NSTableView in the left pane. Don't forget to disable the headers, and make it display as a "Source View" style.
If you want the disclosure triangles, then you'll want to use NSOutlineView instead of NSTableView, but at least for the first go, I'd stick to a simple NSTableView.
A pattern I also use is to make the NSTableView slightly shorter than the NSSplitView, and have buttons at the bottom (add, delete, etc). I've usually built the program around Core Data, so it's easy to hook up these to methods to create/delete objects, and then bind the NSTableView to the array of objects.
Direct support for this sort of thing was added in Leopard. It's called a 'source list'.
Please see the AppKit release notes. Search for NSTableViewSelectionHighlightStyleSourceList in the document.
Or, drag out a table view and select Highlight: Source List in Interface Builder.

Resources