Cocoa Programming for Mac OS X - Aaron Hillegass [83]
This method brings up an Open panel as a sheet attached to the window. The second parameter, handler, is the block. The block syntax takes some getting used to, but blocks are a very powerful tool. When the Open panel is dismissed by the user, the block is run, allowing your code to respond to the user’s actions.
Composite an Image onto Your View
You will also need to change StretchView so that it uses the opacity and image. First, declare variables and methods in your StretchView.h file:
#import @interface StretchView : NSView { NSBezierPath *path; NSImage *image; float opacity; } @property (assign) float opacity; @property (strong) NSImage *image; - (NSPoint)randomPoint; @end Now implement these methods in your StretchView.m file: #pragma mark Accessors - (NSImage *)image { return image; } - (void)setImage:(NSImage *)newImage { image = newImage; [self setNeedsDisplay:YES]; } - (float)opacity { return opacity; } - (void)setOpacity:(float)x { opacity = x; [self setNeedsDisplay:YES]; } At the end of each of the methods, you inform the view that it needs to redraw itself. Near the end of the initWithFrame: method, set opacity to be 1.0: [path closePath]; opacity = 1.0; } return self; } Also in StretchView.m, you need to add compositing of the image to the drawRect: method: - (void)drawRect:(NSRect)rect { NSRect bounds = [self bounds]; [[NSColor greenColor] set]; [NSBezierPath fillRect:bounds]; [[NSColor whiteColor] set]; [path fill]; if (image) { NSRect imageRect; imageRect.origin = NSZeroPoint; imageRect.size = [image size]; NSRect drawingRect = imageRect; [image drawInRect:drawingRect fromRect:imageRect operation:NSCompositeSourceOver fraction:opacity]; } } Note that the drawInRect:fromRect:operation:fraction: method composites the image onto the view. The fraction determines the image’s opacity. Build and run your application. You will find a few images in /Developer/Examples/Sketch. When you open an image, it will appear in the lower-left corner of your StretchView object. The View’s Coordinate System Figure 18.8. Completed Application Each view has its own coordinate system. By default, (0, 0) is in the lower-left corner. This is consistent with PDF and PostScript. You can change the coordinate system of the view if you wish. You can move the origin, change the scale, or rotate the coordinates. The window also has a coordinate system. If you have two views, a and b, and you need to translate an NSPoint pb from b’s coordinate system to a’s coordinate system, it would look like this: NSPoint pa = [a convertPoint:pb fromView:b]; If b is nil, the point is converted from the window’s coordinate system. Mouse events have their locations in the window’s coordinate system, so you will nearly always have to convert the point to the local coordinate system. You are going to create variables to hold onto the corners of the rectangle where the image will be drawn. Add these instance variables to StretchView.h: NSPoint downPoint; NSPoint currentPoint; The location of the mouseDown: will be downPoint and currentPoint will be updated by mouseDragged: and mouseUp:. Edit the mouse-event-handling methods in StretchView.m to update downPoint and currentPoint: - (void)mouseDown:(NSEvent *)event { NSPoint p = [event locationInWindow]; downPoint = [self convertPoint:p fromView:nil]; currentPoint = downPoint; [self setNeedsDisplay:YES]; } - (void)mouseDragged:(NSEvent *)event { NSPoint p = [event locationInWindow]; currentPoint = [self convertPoint:p fromView:nil]; [self setNeedsDisplay:YES]; } - (void)mouseUp:(NSEvent
The final bit of fun comes from being able to choose the location and dimensions of the image, based on the user’s dragging. The mouse down will indicate one corner of the rectangle where the image will appear, and the mouse up will indicate the opposite corner. The final application will look something like Figure 18.8.