Views, Drawing, and Events Lecture 5 First - Representing Points and Areas NSPoint // Represents a point in a Cartesian coordinate system.

typedef struct _NSPoint { CGFloat x; CGFloat y; } NSPoint

• Pair of x, y coordinates • NSZeroPoint represents the “origin” • Create with NSMakePoint(x,y) CGPoint // A structure that contains a point in a two-dimensional coordinate system. typedef struct _CGPoint { CGFloat x; CGFloat y; } CGPoint

• Pair of x, y coordinates • CGPointZero represents the “origin” • Create with CGPointMake(x,y) NSPoint

NSMakePoint(15.0, 40.0)

NSZeroPoint CGPoint

CGPointZero

NSMakePoint(15.0, 40.0) NSSize typedef struct _NSSize { CGFloat width; // must be positive! CGFloat height; // must be positive! } NSSize

• Pair of width, height • Create with NSMakeSize(width,height) CGSize typedef struct _CGSize { CGFloat width; // must be positive! CGFloat height; // must be positive! } CGSize

• Pair of width, height • Create with CGSizeMake(width,height) NSRect

typedef struct _NSRect { NSPoint origin; NSSize size; } NSRect • Combination of a point and a size • Represents a rectangular area • Create with NSMakeRect(x,y,width,height) CGRect

typedef struct _CGRect { CGPoint origin; CGSize size; } CGRect • Combination of a point and a size • Represents a rectangular area • Create with CGRectMake(x,y,width,height) NSRect

NSMakeRect(5.0,5.0,40.0,30.0)

rect.size.width

rect.size.height rect.origin CGRect

rect.origin

rect.size.height

rect.size.width

CGRectMake(5.0,5.0,40.0,30.0) C structs

•C structs are not Objective-C classes! •Declaring variables of structs do NOT need asterisk: CGRect rect; NOT CGRect *rect; •As arguments, they are passed by value: - (void) drawRect: (CGRect *) rect; - (void) drawRect: (CGRect) rect; •No need to retain/release C structs

•C structs are not Objective-C classes! •Declaring variables of structs do NOT need asterisk: CGRect rect; NOT CGRect *rect; •As arguments, they are passed by value: - (void) drawRect: (CGRect *) rect; - (void) drawRect: (CGRect) rect; •No need to retain/release Views NSView/UIView

•Handles drawing and events for a rectangle in a window. •E.g. buttons and text fields are NS(UI)Views •A view can contain subviews •Subclass NS(UI)View to implement your own drawing and/or event handling The View Hierarchy

NSWindow NSView

[window contentView]

[contentView subviews]

[box subviews] The View Hierarchy Bounds and Frame

•NSView/UIView has two rectangles associated with it: the bounds and the frame •The frame rectangle defines the view's location and size in the superview using the superview’s coordinate system. •The bounds rectangle defines the interior coordinate system that is used when drawing the contents of the view, including the origin. and scaling. Frame and Bounds Frame and Bounds Frame and Bounds

Clipped!! Bounds and Frame frame = NSMakeRect(15.0, 15.0, 40.0, 30.0) bounds = NSMakeRect(0.0, 0.0, 40.0, 30.0)

Now this point is 0,0 when the view is drawing (40, 30)

(0, 0) Bounds and Frame frame = NSMakeRect(15.0, 15.0, 40.0, 30.0) bounds = NSMakeRect(0.0, 0.0, 1.0, 1.0)

Changing the size of the bounds scales the coordinates (1, 1)

(0, 0) Drawing Core Graphics (a quick overview) Core Graphics •Based on •Used for: • path-based drawing • image data management • transformations image creation • color management • masking • ofscreen rendering • and PDF document patterns • • creation, display, • gradients and and parsing. shadings Core Graphics

Resolution and Device Independence Core Graphics

Quartz 2D uses the “Painter’s Model” Core Graphics

All vector-based drawing is done with CGPathRefs Core Graphics

CGPathRefs are also used for clipping Core Graphics

Even Bezier curves are easy to do with Core Graphics Core Graphics

Images/paths can be easily transformed with CG functions Core Graphics Graphic Contexts

•Represents a drawing destination •Manages: Colors to use • Font information when drawing • Compositing The clipping • • options area and several Line width and • • others. style information Core Graphics Bitmapped images are handled with and CGImageRef objects Core Graphics

Manages Color Spaces

HSB Hue, saturation, brightness 240 degrees, 100%, 100%

RGB Red, green, blue 0, 0, 1

CMYK Cyan, magenta, yellow, black 1, 1, 0, 0

BGR Blue, green, red 1, 0, 0

=

BLUE! Core Graphics

Abstracts away multiple pixel representations Core Graphics Handles alpha channels and compositing

Quartz Composer Text

/Developer/Applications/ Quartz Composer.app

Combines the capabilities of Cocoa, Quartz 2D, Core Image, OpenGL, and QuickTime, all using an approachable visual programming paradigm. Core Graphics

Text can also be rendered in many different ways

kCGTextFill Perform a fill operation on the text.

kCGTextStroke Perform a stroke operation on the text.

kCGTextFillStroke Perform both fill and stroke operations on the text.

kCGTextInvisible Get text positions for the purpose of measuring text but not display the text. Note that the text position (x, y) is updated, as with all of the drawing modes.

kCGTextFillClip Perform a fill operation, then add the text to the clipping area.

kCGTextStrokeClip Perform a stroke operation, then add the text to the clipping area.

kCGTextFillStrokeClip Perform both fill and stroke operations, then add the text to the clipping area.

kCGTextClip Add the text to the clipping area, but do not draw the text. Core Graphics

Text can also be rendered in many different ways Core Graphics Since it’s a superset of PDF, it easily handles conversion to and from PDF files and other formats! Drawing

- (void)drawRect:(NSRect)rect { // draw things }

•Define it in your NSView/UIView subclass •rect is the subrect of the bounds that needs redrawing: you’re allowed to skip things outside it, but you don’t have to •Don’t call it yourself: it won’t work... Redrawing

• You can’t call drawRect: directly • [view setNeedsDisplay:YES] or [view setNeedsDisplayInRect:rect] to tell Cocoa to redisplay the proper portion of the view Events NS(UI)Application

•Manages the main run loop of your application: •Waits for events from the mouse, keyboard, etc. (Mac) or touches (iOS) •Dispatches events to the relevant objects (of class NSResponder/UIResponder) •File Owner of MainMenu.nib / MainWindow.xib Application Life Cycle

•Application starts •MainMenu.nib / MainWindow.xib loads •Run loop: •Wait for event •Handle event •Application terminates Application Life Cycle

This is you... Kinds of Events (Mac)

•Some sort of input from the user •Mouse button down/up •Mouse moved •Keyboard key pressed/released •Drawing tablet events Event Dispatch — Mouse Events

•The window server sends the event to the NSApplication that owns the window under the cursor •In -(void)sendEvent:(NSEvent *)event, the NSApplication sends the event to the appropriate NSWindow •That window finds the appropriate view using hitTest: on its contentView Mouse Events

•Depending on the event type, a different method is called on the NSView - (void)mouseDown:(NSEvent *)event mouseUp:, mouseDragged:, mouseMoved:, mouseEntered:, mouseExited: Mouse Events

NSPoint windowPos = [event locationInWindow]; NSPoint viewPos = [self convertPoint:windowPos fromView:nil];

If view nil, this method instead converts from if ([event clickCount] == 2) { window base coordinates. // handle double click } drag.x += [event deltaX]; drag.y -= [event deltaY]; Event Dispatch — Key Events

• Instead of the window under the cursor, keyboard events go to the key window [NSApp keyWindow] • Each window has a first responder [window firstResponder] • In order for your view to become the first responder, it must return YES for - (BOOL)acceptsFirstResponder Key Events

Every View inherits from NSResponder!

•There are two key event methods on NSResponder - (void)keyUp:(NSEvent *)event - (void)keyDown:(NSEvent *)event Key Events

NSString *chars = [event characters]; unsigned modifiers = [event modifierFlags]; if ((modifiers & NSCommandKeyMask) && [chars isEqualToString:@"s"]) { // “command-s” was pressed } iPhone

•No key or mouse events •Touch events instead •UIEvent contains a collection of UITouches •Multi-touch support iPhone

•No key or mouse events •Touch events instead •UIEvent contains a collection of UITouches •Multi-touch support

Touch Events

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event - (void)touchesCancelled:(NSSet *)tches withEvent:(UIEvent *)evn

Cancellation often occurs when an external event —for example, an incoming phone call—disrupts the current application’s event processing. Touch Events Touch Events

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event •[event allTouches] returns all of the touches in the multi-touch sequence •touches are just the touches associated with this particular call •If you’re only expecting one touch (e.g. multitouch is off), get it with [touches anyObject] Touch Events

UITouch *touch = [touches anyObject]; if ([touch tapCount] == 2) // handle double tap

CGPoint a, b; a = [touch previousLocationInView:self]; b = [touch locationInView:self]; drag.x += b.x - a.x; drag.y += b.y - a.y; Turning on Multi-Touch

self.multipleTouchEnabled = YES;