# Programming Mac OS X with Cocoa for Beginners/More shapes

Previous Page: Wikidraw's view class | Next Page: An Inspector calls
Before we can act upon the different tools, we'll need the classes that implement the different shapes. We have four tool buttons at the moment, so it would be nice to have one being a selection tool, and three being shape drawing tools. We already have the rectangle shape so we need two more. We'll create an oval shape and a slightly more complex polygonal shape. You can go on to create any number of additional shapes if you want, and just extend the tool palette to access them.
Select WKDShape.m and choose File->New File... Choose Objective-C class, and set its name to "WKDOvalShape.m". By the way the only reason to select the WKDShape file before you do this is to make sure the new files go in the same group - unfortunately Xcode doesn't automatically subclass existing classes, so we'll have to do that by hand.
Open the WKDOvalShape.h file and add #import "WKDShape.h" to the top of the file. Then change NSObject to WKDShape. Your class definition looks like this:
The only method to be implemented is 'path', and we don't need to declare it. Just add it to the implementation, like this:
Now repeat the whole exercise again, this time making files for a class called 'WKDPolyShape'. Here's the implementation we need:
Now return to WKDDrawView.m. Add imports for both of these new files to the top of the file. Add the following to the method 'shapeForCurrentTool'.
It's simple - depending on the current tool, we make one of the three different kinds of shapes. We return 'nil' as the default case, which we'll use to mean the selection tool. Build and Go and check that three kinds of shapes can be drawn. The tool with ID 0 currently will log an error because we haven't adjusted our mouseDown: method to handle the nil case as a selection yet. Let's fix that next.

## Selection marquee

The idea of a selection marquee is very simple - the user clicks in the view with the selection tool, and drags a rectangular box over a set of objects. Any objects that the box touches are selected, and any others outside the box are deselected.
To make this work, we'll need a way to tell which objects are touched by the marquee and which are not. This is straightforward, as the utility function NSIntersectsRect, which we've already seen, will figure it out. We just need to iterate over our objects, retrieve their bounds (or more accurately, the drawBounds) and test for an intersection with the marquee. If it intersects, it's selected, if not, it isn't.
To draw the marquee itself, we'll need to track its original anchor point, and use this to form a rectangle. All of the required code goes in the view class. We also add a pair of NSPoint data members, _anchor and _marquee, to track the current size of the marquee.
updateMarquee: does most of the work. It sets the _marquee data member, and then uses this and _anchor to calculate the rectangle of the marquee. Then it deselects everything, and iterates over the objects, testing each one's drawBounds against the marquee rect. If they intersect, the object is selected.
drawMarquee also calculates the marquee rectangle, and frames it in grey. Both of these methods call the utility NSRectFromTwoPoints. In fact Cocoa doesn't provide this function, so instead we define it ourselves. Note that this is a plain C function, outside of the class implementation. It should be placed above the @implementation declaration in WKDDrawView.m.
Now we need to modify our mousing methods to handle the marquee. All three methods are affected, but mouseDown: is the most complex. The logic of the method needs to be changed so that a more consistent behaviour is implemented, now we have a working tool palette. Rather than immediately locate the object under the mouse, we need to determine the current tool first - we only need to look for an object under the mouse if the selection tool is active. Otherwise, we are creating a new object. Thus the order of the logic at the top of the method needs to be altered. Here's the modified method:
If the selection tool is current, we will have a nil dragShape, so we use that to subsequently detect the marquee case by testing if the mouse hit empty space or an existing object. For mouseDown:, we set the value of _anchor, then call for an update of the marquee. On mouseDragged:, we detect the marquee case and update it again, changing the selection as needed. On mouseUp:, we refresh the marquee area and set the marquee points to zero. This will erase the marquee, leaving anything it selected still selected. The only remaining task is to make the marquee visible. To do this, we simply add a call to drawMarquee to our drawRect: method.
Now we'll find that when we compile and run the application, we have a much more standard behaviour for the selection tool.
There are some fairly serious inefficiencies here - every time the marquee size changes, the selection is recalculated entirely from scratch. For a few objects this isn't a problem, but if our drawing became complex it could well be. Once we add the inspector which will respond to selection changes, performance could suffer even more. We won't be worrying about this now, but perhaps you could think of a few simple ways to improve the efficiency?
Previous Page: Wikidraw's view class | Next Page: An Inspector calls