How to make a custom trackball / eyeball control with Cocoa? - objective-c

I'm writing my first Cocoa app and I would like to make a "trackball / eyeball / arcball / whatever it's called" button to rotate a 3D OpenGL scene.
There's a perfect example of this custom Cocoa control in Pages (Apple iWork suite) when you select a 3D chart. After some hacks, this control seems to be referenced as SFC3DRotateWidget. Here's a screenshot of the control in Pages.
Maybe this widget is reusable, but I didn't find how or where. So I try to recreate it.
I'm inexperienced with Cocoa so I'm not sure how to do that nor exactly where (i.e. what to do with Interface Builder, what to do with code...).
I'm not sure if I need to override the drawing function. I thought to use a textured button (Interface Builder) with a NSTrackingArea (code) to handle mouse events (move, drag, ...) but the area is necessarily rectangular. The interactive zones of the custom control used by Apple seem to follow the shape of the arrows. I've read on S.O. I can use NSBezierPath to create a more specific area (only via code?).
Does it sound good for you?
Do I miss something?
Let met know if you have any tips, tricks or resources you can share!
Thanks!

It sounds like you want to build a custom control. You do this by subclassing NSControl, which there is a guide on how to do. You can control the circular clickable area, and the responses to the mouse events by implementing the various methods. For example you can track mouse events with mouseDown: and the related methods.
You probably do not need to use any custom drawing code, NSImageView subviews with the various arrows will probably suite your purposes fine, unless you'd rather draw them in code.

Related

How hard would it be to create a customisable GUI for mac?

What I mean by this is, how much work would be involved in rewriting/extending default AppKit controls in a way that would allow for both a standard OS X appearance and custom appearance (loaded from image files) if the user so wishes? (Think of WinAmp or Windows Media Player.) Has anyone tried to bring this to the Mac?
I understand how to redraw an NSWindow or a button cell but that's all hard coded. I want something the user can add to themselves. What are my options?
Well, it would really involved redrawing all the custom components you'd need from scratch, whether in code, or using images. AppKit wasn't meant to be customized as it strictly follows Apple's Human Interface Guidelines; Apple wants to create one consistent UI metaphor across all native applications.
What that means in practice is that you're going to have to do a lot of custom drawing to theme your app. Using images makes things easier, but not by too much. If you want a custom button, you'll have to create a subclass of NSButton and NSButtonCell to load the images you want and draw (take a look at NSDrawThreePartImage() and NSDrawNinePartImage() for how to more easily draw resizable buttons). To theme NSWindow, you'll have to subclass NSThemeFrame, a semi-private class that draws the standard OS X window look.
Essentially, you'll just need to do a lot of subclassing to get the appearance you want. Is it possible? Absolutely. Is it recommended or easy to do? Not so much.
Of course, you have to ask if this is really necessary. The point of the HIG is to try to create one standard look across OS X. If not done expertly, a themed look can be tacky, and possibly even confusing for users who are used to the default OS X look. If you want to include UI theming, there usually needs to be a good reason for it (either to maintain cross-platform compatibility, but in that case, all HIG rules are out the window; or to achieve a specific look, a là game UI), but I really wouldn't recommend doing it, let alone letting users customize your UI themselves.
Yes this fully possible. But are you shure that you want to do this using AppKit? Maybe better use crossplatform solution like QT that support skinning through CSS?

How should I design displaying a dynamic map? (Coordinates + Lines)

So I want to have a view (NSView, NSOpenGLView, something CG related?) which basically displays a map. Such as:
http://dump.tanaris4.com/map.png
Obviously that looks horrible, but I did it using an NSView, and it draws SO slow. Clearly not designed for this.
I just need to allow users to click on the individual (x,y) coordinates to make changes, and zoom into a certain area (to see it better).
Should I go the OpenGL route? And if so - any suggestions as to how to get started? (I was able to follow the guide to draw a triangle, so that's good).
I did find this post on zooming in an NSView: How to implement zoom/scale in a Cocoa AppKit-application
My concern is if I'm drawing over 6000 coordinates and the lines connecting them, this isn't efficient at all.
I don't think using OpenGL would be of any good here. The problem does not seem to be the actual painting, but rather the rendering strategy. You would need a scene graph of some kind to dynamically handle level of detail and culling.
Qt has all this packaged in a nice class class QGraphicsScene (see http://doc.qt.nokia.com/latest/qgraphicsscene.html for reference, and http://doc.qt.nokia.com/main-snapshot/demos-chip.html for an example).
Some basic concepts you should consider using:
http://en.wikipedia.org/wiki/Scene_graph
http://en.wikipedia.org/wiki/Quadtree
http://en.wikipedia.org/wiki/Level_of_detail
Try using core graphics for this, really there is so much that could be done. Watch the video Practical Drawing for iOS Developers from WWDC 2011 and it should give an over view of what can be done with CG.
I believe even CoreGraphics will suffice for what you want to achieve, and that should work under a UIView if you draw the rectangle of your view completely under the DrawRect method of your UIView (you must overload this method). Please see the UIView Class Reference. I have a mobile application that logs points on the UIMapKit, kind of like Nike+, and it certainly works well for massive amounts of points/line segments. There is no reason why this simple approach cannot work for you as well.

How to draw a "speech bubble" above NSWindow?

Notice this app:
How can I draw that sort of triangle above an existing NSWindow? I know the app in question probably draws the whole thing as a custom window, but I want to keep the existing title bar. Is there any way to draw a triangle and attach it above a NSWindow? Please note that the solution has to be MAS-compatible (i.e. no private frameworks or classes).
The only way to do this would be to create a borderless child window with no shadow that overlays the edge of the existing window. You'd need to draw any shadow yourself.
A more comprehensive solution would involve subclassing NSThemeFrame and doing some custom drawing. Take a look at Matt Gallagher's Drawing a custom window on Mac OS X. It contains a wealth of helpful information, and Google will also be of great help here.
I've written an open source (BSD) framework that draws windows similar to this: https://github.com/sbooth/SFBPopovers
It won't directly do what you need but will illustrate the basics of drawing custom window frames.

Cocoa + CoreAnimation: Animated List of Custom Subviews

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.

Creating a Quartz Composer Style interface

I'm wanting to add a Quartz Composer "patch editor" style interface element to my Cocoa/Objective C(++) application. For those unfamiliar with QC, the patch editor is a visual representation of the patch graph: effectively showing each node and it's properties, and providing a mouse driven select/click/drag interface. It looks like...
Quartz Composer Example http://files.me.com/archgrove/ya1xhh
I'll be using it to render a specific type of multi-rooted tree, where each node has some associated text and an arc joining it to its children. Users will be clicking on the tree nodes to select them, as well as dragging them around.
At the moment, I'm using a custom NSView inside a scroll view that Quartz draws each node, the arcs etc at each render, and processes mouse and keyboard input by hand (including hit testing, movement and so forth). This seems brutally wheel reinventive, and doesn't interact all that well with Core Animation. I'm hoping someone has some general alternative advice. I'm pondering along the lines of...
An existing control/3rd party library I've overlooked
Make each node in the tree an NSView, and use the normal view structure to handle the input, whilst drawing the graphics in the same way. But then, the inter-node arc rendering doesn't seem to fit naturally into the design
Something using a single NSView still, but making each tree node and arc an individual layer
Something else
Thanks kindly,
adamw
You might want to give EFLaceView a look: FlowChartView on CocoaDev
Edit: download link on page above is dead. There is a version of EFLaceView on github.