Cocoa + CoreAnimation: Animated List of Custom Subviews - objective-c

I've been trying to get this right for weeks now, and though I've learned a lot through my misfires, at this point, I just need a solution. The issue is with unpacking the seemingly overlapping graphics and UI APIs included in Cocoa, many of which produce similar effects, but feature unique limitations that I've often discovered only after investing many hours into an implementation.
I'm new to Cocoa, but not to programming, and I'm trying to create a Mac app with a very customized UI – think Capo, Garageband, or Billings. One view in my window will display an ordered list of subviews, each of which does a lot of custom drawing, and each must support a "selected" state and drag-reordering. The subviews do not need to support being dragged outside of their superview.
Ideally, a drag will give animated feedback as it happens, pushing neighboring sibling views to make space, e.g. toolbar icons or the Safari bookmarks bar. The trouble is, I can't seem to land on the right pack of technologies to get this right. I've done the subviews as NSView subclasses in an NSCollectionView and also as CALayers in a custom CollectionView-like NSView, and neither seems to offer the perfect solution. That said, the first option seems the better of the two for its superior handling of mouse events.
I've not yet tried doing this as a TableView, and I don't want to go down that path without some indication I'm on the right track. Extensive Googling has shown only that there aren't any up-to-date resources on CoreAnimation-enabled reordering or dragging. As such a standard feature of the OS X UI, I feel like this should be easier!
Any help from anyone on what the right tools are for this job would be greatly appreciated. TIA.

Related

NSCollectionViewItems shaking and with X to remove

On Launchpad we have basically a big collection view with app icons. When you hold an app (press down with the cursor and don't stop) for a very long time, all the icons start to shake, and a little 'x' appears in the top left hand corner of each one of them, which makes removing items very easy.
I would like to know if there is some method already implemented in the API which allow us to reproduce that same behavior in a regular NSCollectionView.
I've checked NSCollectionView and NSCollectionViewDelegate documentations in Apple's Mac Developer Library, however I haven't seeing anything related to that. Should that be done manually? If so, how can I make the collection view items shake?
There is no existing method to do this, but you can recreate it with Core Animation.
Providing the full code to do that is beyond the scope of Stack Overflow (and would be highly dependent on your existing code), but a CABasicAnimation affecting the transform.rotation key of the layers of your NSCollectionViewItem views should put you on the right path.

Avoid NSView Overuse

I searched and thought about this a long time and couldn't find a satisfying answer:
I want to create an application with a NSView in which hundreds of elements are drawn which are still interactive and should react on dragging and hovering.
Now, it seems to me, that these elements should be NSViews, because the NSView can handle all these events, but at the same time if I draw hundreds of NSViews, I think it is a bit of an overuse as I have read here (Avoid the Overuse of Views).
For comprehension let's say I want to make something like the Finder Desktop with hundreds of documents and folders on it that react to drag and hover events.
What is the right approach to this?

General design for a Mac app, document based versus?

I am learning cocoa, and I am creating an application that will require similiar layout to the screenshot below (this seems like a very common layout approach).
What kind of controls/architecture would this type of Cocoa application be?
I'm still in my early stages of learning/reading, and I know of document based applications only so far, but this type of layout doesn't seem to look like a document based app since it doesn't really require multiple windows opened.
If it isn't document, is there a name for other design patters or layouts?
From what I now so far, I would describe this like:
I would be grateful if someone could give me a detailed overview of the high level design for an app like this i.e. things like: # of panels, views used, controls, controllers etc?
Also, a few quick sub-questions:
what kind of menu controls are those in the left pane, then expand and display sub elements?
When preferences windows are displayed, what is that effect called that makes it display in an animated way (like the address book does), where it is a small window that expands to its correct size in an animated fashion.
You are right that this is probably not a document based application, as they open documents in new windows by default.
To layout the window like that, there’d be an NSSplitView that contains the 3 panes. Each pane may optionally contain a view loaded from an NSViewController, which can help keep the code modularised, but it depends on what you’re trying to do if this is appropriate.
The left pane would be an NSOutlineView (a NSTableView subclass), the middle an NSTableView, but I’m not sure exactly how the right-hand side view would be created (lots of custom NSViews and other things, possibly WebView)
That popover options window is possibly a NSPopover (which contains an NSViewController), but that’s only compatible with OS X 10.7, so may also be totally custom for backwards compatibility and easier customisation.
Also note this is a fairly complicated example you’ve given, with lots of custom controls that are probably harder to create than they look:
To get the outline views on the left to have unread counts and icons (from memory) is not built into AppKit, so was all custom created. To do things like that, you’ll need a solid understanding of NSCell vs NSView, and ideally also know about Core Animation layer backed views, and what to use for different aspects.
The window has a taller-than usual title bar. This means the developer probably had to do some crazy stuff to get it to work, if not create the whole window from scratch.
That’s just the start. There’s lots of really nice design in there that’s custom and done from scratch.
Designing Mac apps can be hard sometimes. AppKit is pretty old (back from the NEXT days), and has lots of legacy stuck in it. UIKit on iOS on the other hand is quite nice – Apple clearly learned from their past and made things much better.
I’ve hardly touched on the controllers and model behind all that. There’s lots of different ways you could do it. For persistence, you could use CoreData, sqlite, NSKeyedArchived, just to name a few. Brent Simmons (past developer of another RSS reader, NetNewsWire) wrote some interesting blog posts about that:
http://inessential.com/2010/02/26/on_switching_away_from_core_data
http://inessential.com/2011/09/22/core_data_revisited
The way you design your model & controllers really depends on the specific problem. Cocoa really forces you to stick to MVC though – if you don’t, things are guaranteed to end up messy.
I hope that all helps! I’m really only just learning myself too.
Apple refers to this type of application design as Single-window, library- (or “shoebox”) style and gives a number of recommendations for this design choice in the docs.
(see Mac App Programming Guide)

Dashboard-like flip: pros/cons of 2 windows vs. 2 views in the same window?

I'm designing a simple Cocoa app. This is basically my second Cocoa app (despite being good at CocoaTouch), so I'm looking for an in-depth pros/cons analysis of 2 possible solutions for a window flipping problem.
What I'm trying to make is an utility app that sits in the menu bar and has its preferences o its “flip” side, Dashboard-style. It would flip from http://cl.ly/1G2M3J2c142Z0V3K0R2e to http://cl.ly/021z2v2h232x310z1g2q and back.
There are multiple questions on SO about the implementation of this effect:
Core Animation window flip effect
Widget "flip" behavior in Core Animation/Cocoa
Flipping a Window in Cocoa
I've looked at the example code there. Besides neither of them being as smooth as Dashboard widgets (but I'm yet to get to “making it smooth” part), they also share another trait -- they all flip between two different windows.
Now, coming from iOS, the way I started implementing it is to have a single window, but swap between two NSViews.
So what are the pros and cons of these two approaches, and why did multiple unrelated Cocoa developers pick the first one?
Have two NSWindow's, and flip between them (hiding one and showing the other halfway through the flip).
Have a single NSWindow, but two NSView's, and switch the views halfway through the flip.
Is it more convenient to have things separated into different windows in Cocoa? Is it because you can use NSWindowController to manage their lifecycle? Are people just used to using windows because pre-Core Animation you couldn't give views a CA layer? Any other reason/convenience I am missing?
To the future generations: I believe people did it this way because they often flip between windows with different sizes, and then it's just less hassle to have them separate.
Also if you are looking for a good implementation, these guys nailed it: https://github.com/mizage/Flip-Animation

Programmatically resizing NSSplitView

I used to use and love RBSplitView, however I failed at reimplementing it programmatically as a certain version of xcode does not support IB plugins anymore.
Therefore I went back to using NSSplitView. NSSplitView is fine for what I need, the thing is that the autoSave of NSSplitView is broken. So I decided to implement it myself.
The thing I am doing at the moment is resizing 1 of the subviews of the NSSplitView.
What is the proper way of resizing an NSSplitView? - setPositionOfDivider:itIndex: should be the way to go ( haven't tried it ), however I do not know how to get the current position of the divider.
-- thanks in advance
In my experience, NSSplitView hates you and wishes you harm. RBSplitView is so much better, it is worth IMO the headache of programatic layout (and I've been so burned with the ShortcutRecorder IB plugins that I will never go back to IB plugins).
That said....
The only way that I know of to determine the current position of the divider is to look at the subviews, find the divider's view, take it's frame, and work out its position keeping in mind the dividerThickness. It is insane that you have to write that code, but the code isn't that incredibly difficult, and you can put it in a category.
Or go back to RBSplitView while you still can, if your needs are ever going to be complicated.
I'm using Swift here but the same method should exist in Objective C:
mySplitter.setPosition(123, ofDividerAtIndex: 0)