programming4us
 
 
 
Programming

iPad SDK : New Graphics Functionality - We Are All Tool Users (part 4) - The Ellipse and Rectangle Tools

12/18/2010 4:15:09 PM

3. The Ellipse and Rectangle Tools

Next up are the Ellipse and Rectangle tools. They are extremely similar to one another, and also to the Line tool. From a user standpoint, they function similarly: you touch in one corner, drag, and release to define the opposite corner. The Rectangle tool creates a rectangle, and the Ellipse tool creates (you guessed it) an ellipse.

Make a new RectangleTool class, and give it this code:

//  RectangleTool.h
#import <Foundation/Foundation.h>
#import "Tool.h"
@interface RectangleTool : NSObject <Tool> {
id <ToolDelegate> delegate;
NSMutableArray *trackingTouches;
NSMutableArray *startPoints;
}
+ (RectangleTool *)sharedRectangleTool;
@end

// RectangleTool.m
#import "RectangleTool.h"

#import "PathDrawingInfo.h"
#import "SynthesizeSingleton.h"
@implementation RectangleTool
@synthesize delegate;
SYNTHESIZE_SINGLETON_FOR_CLASS(RectangleTool);
- init {
if ((self = [super init])) {
trackingTouches = [[NSMutableArray array] retain];
startPoints = [[NSMutableArray array] retain];
}
return self;
}
- (void)activate {
}
- (void)deactivate {
[trackingTouches removeAllObjects];
[startPoints removeAllObjects];
}

As you can see, like the LineTool class, this class maintains arrays of startingPoints and trackingTouches.

The "touches" methods are where the interesting work of this class is done. Like the Line tool, the Rectangle tool is capable of tracking multiple simultaneous touches, ultimately creating a new line for each of them.

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UIView *touchedView = [delegate viewForUseWithTool:self];
for (UITouch *touch in [event allTouches]) {
// remember the touch, and its original start point, for future
[trackingTouches addObject:touch];
CGPoint location = [touch locationInView:touchedView];
[startPoints addObject:[NSValue valueWithCGPoint:location]];
}
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UIView *touchedView = [delegate viewForUseWithTool:self];
for (UITouch *touch in [event allTouches]) {
// make a rect from the start point to the current point
NSUInteger touchIndex = [trackingTouches indexOfObject:touch];
// only if we actually remember the start of this touch...
if (touchIndex != NSNotFound) {
CGPoint startPoint = [[startPoints objectAtIndex:touchIndex] CGPointValue];
CGPoint endPoint = [touch locationInView:touchedView];
CGRect rect = CGRectMake(startPoint.x, startPoint.y, endPoint.x - startPoint.x, endPoint.y - startPoint.y);
UIBezierPath *path = [UIBezierPath bezierPathWithRect:rect];
PathDrawingInfo *info = [PathDrawingInfo pathDrawingInfoWithPath:path fillColor:delegate.fillColor strokeColor:delegate.strokeColor];
[delegate addDrawable:info];
[trackingTouches removeObjectAtIndex:touchIndex];
[startPoints removeObjectAtIndex:touchIndex];
}
}
}


- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
}

The following method draws the current state of the rectangle while you are still dragging it around. Only later does the object being drawn here get added to the view's list of drawable items.

- (void)drawTemporary {
UIView *touchedView = [delegate viewForUseWithTool:self];
for (int i = 0; i<[trackingTouches count]; i++) {
UITouch *touch = [trackingTouches objectAtIndex:i];
CGPoint startPoint = [[startPoints objectAtIndex:i] CGPointValue];
CGPoint endPoint = [touch locationInView:touchedView];
CGRect rect = CGRectMake(startPoint.x, startPoint.y, endPoint.x - startPoint.x, endPoint.y - startPoint.y);
UIBezierPath *path = [UIBezierPath bezierPathWithRect:rect];
[delegate.fillColor setFill];
[path fill];
[delegate.strokeColor setStroke];
[path stroke];
}
}
- (void)dealloc {
[trackingTouches release];
[startPoints release];
self.delegate = nil;
[super dealloc];
}
@end


Now for the Ellipse tool. Its only substantial difference from the Rectangle tool is the creation of UIBezierPaths in touchesEnded:withEvent: and drawTemporary.

//  EllipseTool.h
#import <Foundation/Foundation.h>
#import "Tool.h"
@interface EllipseTool : NSObject <Tool> {
id <ToolDelegate> delegate;
NSMutableArray *trackingTouches;
NSMutableArray *startPoints;
}
+ (EllipseTool *)sharedEllipseTool;
@end


// EllipseTool.m
#import "EllipseTool.h"
#import "PathDrawingInfo.h"
#import "SynthesizeSingleton.h"
@implementation EllipseTool
@synthesize delegate;
SYNTHESIZE_SINGLETON_FOR_CLASS(EllipseTool);
- init {
if ((self = [super init])) {
trackingTouches = [[NSMutableArray arrayWithCapacity:100] retain];
startPoints = [[NSMutableArray arrayWithCapacity:100] retain];
}
return self;



}
- (void)activate {
}
- (void)deactivate {
[trackingTouches removeAllObjects];
[startPoints removeAllObjects];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UIView *touchedView = [delegate viewForUseWithTool:self];
for (UITouch *touch in [event allTouches]) {
// remember the touch, and its original start point, for future
[trackingTouches addObject:touch];
CGPoint location = [touch locationInView:touchedView];
[startPoints addObject:[NSValue valueWithCGPoint:location]];
}
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UIView *touchedView = [delegate viewForUseWithTool:self];
for (UITouch *touch in [event allTouches]) {
// make an ellipse/oval from the start point to the current point
NSUInteger touchIndex = [trackingTouches indexOfObject:touch];
// only if we actually remember the start of this touch...
if (touchIndex != NSNotFound) {
CGPoint startPoint = [[startPoints objectAtIndex:touchIndex] CGPointValue];
CGPoint endPoint = [touch locationInView:touchedView];
CGRect rect = CGRectMake(startPoint.x, startPoint.y, endPoint.x - startPoint.x, endPoint.y - startPoint.y);
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:rect];
PathDrawingInfo *info = [PathDrawingInfo pathDrawingInfoWithPath:path fillColor:delegate.fillColor strokeColor:delegate.strokeColor];
[delegate addDrawable:info];
[trackingTouches removeObjectAtIndex:touchIndex];
[startPoints removeObjectAtIndex:touchIndex];
}
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
}
- (void)drawTemporary {
UIView *touchedView = [delegate viewForUseWithTool:self];
for (int i = 0; i<[trackingTouches count]; i++) {
UITouch *touch = [trackingTouches objectAtIndex:i];
CGPoint startPoint = [[startPoints objectAtIndex:i] CGPointValue];
CGPoint endPoint = [touch locationInView:touchedView];
CGRect rect = CGRectMake(startPoint.x, startPoint.y, endPoint.x - startPoint.x, endPoint.y - startPoint.y);
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:rect];
[delegate.fillColor setFill];
[path fill];
[delegate.strokeColor setStroke];
[path stroke];
}
}
- (void)dealloc {
[trackingTouches release];


[startPoints release];
self.delegate = nil;
[super dealloc];
}
@end

Here are the necessary changes to DudelViewController.m:

#import "RectangleTool.h"
#import "EllipseTool.h"

- (IBAction)touchEllipseItem:(id)sender {
self.currentTool = [EllipseTool sharedEllipseTool];
[ellipseButton setImage:[UIImage imageNamed:@"button_ellipse_selected.png"]];
}
- (IBAction)touchRectangleItem:(id)sender {
self.currentTool = [RectangleTool sharedRectangleTool];
[rectangleButton setImage:[UIImage imageNamed:@"button_rectangle_selected.png"]];
}


With those in place, the next two buttons at the bottom of the GUI should now be working. Figure 3 shows some of the kinds of shapes that can be created with these tools. As with the previous tools, these also work with multitouch, so you should be able to drag multiple fingers at once to create several rectangles or ellipses simultaneously.

Figure 3. Overlapping blocks and curves
Other -----------------
- Security-As-a-[Cloud] Service : Today’s Offerings
- CSS for Mobile Browsers : CSS Sprites
- CSS for Mobile Browsers : Common Patterns (part 4)
- CSS for Mobile Browsers : Common Patterns (part 3) - Titles and Pseudoclasses
- CSS for Mobile Browsers : Common Patterns (part 2) - Rounded corners
- CSS for Mobile Browsers : Common Patterns (part 1) - Absolute and floating positions
- iPad SDK : New Graphics Functionality - The Basic Drawing Architecture
- jQuery 1.3 : Compact forms (part 6)
- jQuery 1.3 : Compact forms (part 5)
- jQuery 1.3 : Compact forms (part 4)
- jQuery 1.3 : Compact forms (part 3)
- jQuery 1.3 : Compact forms (part 2) - AJAX auto-completion
- jQuery 1.3 : Compact forms (part 1) - Placeholder text for fields
- The Art of SEO : Duplicate Content Issues (part 3)
- The Art of SEO : Duplicate Content Issues (part 2) - How Search Engines Identify Duplicate Content
- The Art of SEO : Duplicate Content Issues (part 1) - Consequences of Duplicate Content
- The Art of SEO : Content Optimization (part 2)
- The Art of SEO : Content Optimization (part 1)
- iPad SDK : New Graphics Functionality - Introducing Dudel (part 2)
- iPad SDK : New Graphics Functionality - Introducing Dudel (part 1)
 
 
Video tutorials
- How To Install Windows 8 On VMware Workstation 9

- How To Install Windows 8

- How To Install Windows Server 2012

- How To Disable Windows 8 Metro UI

- How To Change Account Picture In Windows 8

- How To Unlock Administrator Account in Windows 8

- How To Restart, Log Off And Shutdown Windows 8

- How To Login To Skype Using A Microsoft Account

- How To Enable Aero Glass Effect In Windows 8

- How To Disable Windows Update in Windows 8

- How To Disable Windows 8 Metro UI

- How To Add Widgets To Windows 8 Lock Screen
programming4us programming4us
 
Top 10
 
- Implementing Edge Services for an Exchange Server 2007 Environment : Utilizing the Basic Sender and Recipient Connection Filters (part 3) - Configuring Recipient Filtering
- Implementing Edge Services for an Exchange Server 2007 Environment : Utilizing the Basic Sender and Recipient Connection Filters (part 2)
- Implementing Edge Services for an Exchange Server 2007 Environment : Utilizing the Basic Sender and Recipient Connection Filters (part 1)
- Implementing Edge Services for an Exchange Server 2007 Environment : Installing and Configuring the Edge Transport Server Components
- What's New in SharePoint 2013 (part 7) - BCS
- What's New in SharePoint 2013 (part 6) - SEARCH
- What's New in SharePoint 2013 (part 6) - WEB CONTENT MANAGEMENT
- What's New in SharePoint 2013 (part 5) - ENTERPRISE CONTENT MANAGEMENT
- What's New in SharePoint 2013 (part 4) - WORKFLOWS
- What's New in SharePoint 2013 (part 3) - REMOTE EVENTS
 
Popular tags
 
Video Tutorail Microsoft Access Microsoft Excel Microsoft OneNote Microsoft PowerPoint Microsoft Project Microsoft Visio Microsoft Word Active Directory Biztalk Exchange Server Microsoft LynC Server Microsoft Dynamic Sharepoint Sql Server Windows Server 2008 Windows Server 2012 Windows 7 Windows 8 Adobe Indesign Adobe Flash Professional Dreamweaver Adobe Illustrator Adobe After Effects Adobe Photoshop Adobe Fireworks Adobe Flash Catalyst Corel Painter X CorelDRAW X5 CorelDraw 10 QuarkXPress 8 windows Phone 7 windows Phone 8 BlackBerry Android Ipad Iphone iOS