Learn Objective-C on the Mac - Mark Dalrymple [130]
Figure 13-2. On the left, plotting points from a narrow range in a view with default bounds. On the right, the same points plotted in a view with smaller bounds.
Rects, Points, and Sizes
In Cocoa, rectangles are represented by a Cstruct called NSRect, which is composed of an NSPoint containing the origin, and an NSSize containing the size. Both the origin and size each contain two values of type CGFloat, a basic C type used throughout Cocoa’s drawing APIs; origin has x and y, size has width and height.
To confuse matters somewhat, many functions in Core Graphics make use of equivalent structures CGRect, CGPoint, and CGSize, which have the same structural layout and are all composed of CGFloat elements. The historical reasons for this divide aren’t terribly interesting. Starting with Leopard, these C structs have identical layouts, and can be converted back and forth with inline functions (for example, NSRectToCGRect, NSSizeFromCGSize, and so on) that are really little more than typecasts. In fact, there are a couple of ways you can make their definitions identical, requiring no conversion at all, by either configuring your applications for 64-bit mode, or adding NS_BUILD_32_LIKE_64 to the Preprocessor Macros section of your Xcode target’s Build settings, which we’ll describe in a page or two.
Path Basics
Cocoa’s drawing mechanism includes the concept of paths, which can contain any number of straight or curved line segments. Each path doesn’t need to be contiguous. You can “pick up the pen” at one point, and start drawing again at another. Before a path is actually drawn, you can specify values such as line thickness, color, and the like.
Those settings will be applied to every part of the path. Any shapes outlined by parts of the path can also be filled with a separate color or pattern.
Creating an NSView Subclass
Let’s start exploring a bit by creating an application that’s able to draw a very happy smiley face (see Figure 13-3). In Xcode, create a new Cocoa project named MrSmiley, and do the normal steps to enable garbage collection.
Figure 13-3. Mr Smiley is very, very happy.
Now create a new Objective-C class, a subclass of NSView, and name it SmileyView. Xcode will create the class’s files for you, including SmileyView.m, where all this section’s work will take place.
Before getting started on the code, open the project’s MainMenu.xib file in Interface Builder. Grab a custom view from the Library window, and drag it into the blank window that is created for you by default. Use the Identity Inspector to change the view’s class to SmileyView, then use the Size Inspector to change its size to 100×100. Finally, with the SmileyView selected in the window, press = to make the window resize itself to perfectly fit the view. Then save your changes.
Some C Structures
Go back to Xcode so we can start working on the code itself. A couple of pages ago, we mentioned the distinction between the two sets of geometry structures available in Cocoa: NSRect/NSPoint/NSSize vs CGRect/CGPoint/CGSize. Beginning with Mac OS X 10.5, it’s possible to use these interchangeably. In the 64-bit version of the Cocoa framework, these are defined to be identical, but we can achieve the same effect via a simple configuration that tells the compiler to compile code for 32-bit use as if it were compiling for 64-bit use.
Click on the root object in Xcode’s navigation pane, the one labeled MrSmiley. Then press I to open the Inspector panel, and switch to the Build tab at the top of the panel. A popup button lets you choose which configuration (Debug, Release, and so on) you want