Created
January 16, 2012 23:06
-
-
Save Me1000/1623499 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Created by Randall Luecke or RCLConcepts | |
// Copyright 2010 all rights reserved | |
/* | |
Canvas object is an abstract view class that takes care of all the resizing, rotating, and repositiong | |
*/ | |
@import <Foundation/CPObject.j> | |
var SMResizeLeft = 1 << 0, | |
SMResizeCenter = 1 << 1, | |
SMResizeRight = 1 << 2, | |
SMResizeTop = 1 << 3, | |
SMResizeBottom = 1 << 4; | |
@implementation CanvasObject : CPView | |
{ | |
BOOL isSelected @accessors; | |
id delegate @accessors; | |
CGPoint dragBeginPoint; | |
SMResizeMask resizeMask; | |
} | |
- (id)initWithFrame:(CGRect)aRect | |
{ | |
self = [super initWithFrame:aRect]; | |
if (self) | |
{ | |
dragBeginPoint = nil; | |
} | |
return self; | |
} | |
- (void)setIsSelected:(BOOL)aBool { | |
isSelected = aBool; | |
[self setNeedsDisplay:YES]; | |
if ( aBool ) | |
[delegate hasBeenSelected:self]; | |
} | |
- (id)_dragVerticalHitTestForPoint:(CGPoint)aPoint | |
{ | |
var bounds = [self bounds]; | |
if (aPoint.y < 7) | |
return SMResizeTop; | |
else if (ABS(aPoint.y - CGRectGetMidY(bounds)) < 7) | |
return SMResizeCenter; | |
else if (aPoint.y > bounds.size.height - 7) | |
return SMResizeBottom; | |
else | |
return CPNotFound; | |
} | |
- (id)_dragHorizontalHitTestForPoint:(CGPoint)aPoint | |
{ | |
var bounds = [self bounds]; | |
if (aPoint.x < 7) | |
return SMResizeLeft; | |
else if (ABS(aPoint.x - CGRectGetMidX(bounds)) < 7) | |
return SMResizeCenter; | |
else if (aPoint.x > bounds.size.width - 7) | |
return SMResizeRight; | |
else | |
return CPNotFound; | |
} | |
// --- CPView Methods | |
- (void)drawRect:(CGRect)aRect | |
{ | |
if (!isSelected) | |
return; | |
var context = [[CPGraphicsContext currentContext] graphicsPort]; | |
[[CPColor grayColor] setStroke]; | |
CGContextSetLineWidth(context, 2.0); | |
// FIX ME: clean this up... we should go from the edge of one circle to the edge of another... | |
CGContextStrokeRect(context, aRect); | |
// now draw the little resizy thingies | |
// top left | |
var circle = CGRectMake(1,1,5,5); | |
CGContextStrokeEllipseInRect(context, circle); | |
// top center | |
circle = CGRectMake(CGRectGetMidX(aRect) - 5,1,5,5); | |
CGContextStrokeEllipseInRect(context, circle); | |
// top right | |
circle = CGRectMake(CGRectGetMaxX(aRect) - 6,1,5,5); | |
CGContextStrokeEllipseInRect(context, circle); | |
// center left | |
circle = CGRectMake(1, CGRectGetMidY(aRect) - 3,5,5); | |
CGContextStrokeEllipseInRect(context, circle); | |
// center right | |
circle = CGRectMake(CGRectGetMaxX(aRect) - 6, CGRectGetMidY(aRect) -3,5,5); | |
CGContextStrokeEllipseInRect(context, circle); | |
// bottom left | |
circle = CGRectMake(1, CGRectGetMaxY(aRect) -6,5,5); | |
CGContextStrokeEllipseInRect(context, circle); | |
// bottom center | |
circle = CGRectMake(CGRectGetMidX(aRect) - 6, CGRectGetMaxY(aRect) -5,5,5); | |
CGContextStrokeEllipseInRect(context, circle); | |
// bottom right | |
circle = CGRectMake(CGRectGetMaxX(aRect) - 6, CGRectGetMaxY(aRect) -5,5,5); | |
CGContextStrokeEllipseInRect(context, circle); | |
} | |
// --- CPResponder Methods | |
- (void)mouseDown:(CPEvent)theEvent | |
{ | |
// when the mouse is clicked register the location it was clicked from within the view | |
// we will use that location to recalculate the views new position in mouse dragged | |
dragBeginPoint = [self convertPoint:[theEvent locationInWindow] fromView:nil]; | |
[self setIsSelected:YES]; | |
[self setNeedsDisplay:YES]; | |
var verticalMask = [self _dragVerticalHitTestForPoint:dragBeginPoint], | |
horizontalMask = [self _dragHorizontalHitTestForPoint:dragBeginPoint]; | |
if (verticalMask === CPNotFound || horizontalMask === CPNotFound || verticalMask === horizontalMask) | |
return; | |
resizeMask = verticalMask | horizontalMask; | |
// reset it early here so we don't drag it around... | |
dragBeginPoint = nil; | |
} | |
- (void)mouseDragged:(CPEvent)theEvent | |
{ | |
if (!dragBeginPoint && !resizeMask) | |
return; | |
var dragPoint = [[self superview] convertPoint:[theEvent locationInWindow] fromView:nil], | |
currentFrame = [self frame], | |
newY = { }, | |
newX = { }; | |
if (dragBeginPoint) | |
{ | |
var newOrigin = CGPointMake(dragPoint.x - dragBeginPoint.x, dragPoint.y - dragBeginPoint.y); | |
if ( [delegate item:self shouldMoveToLocation:newOrigin] ) | |
var newFrame = CGRectMake(newOrigin.x, newOrigin.y, currentFrame.size.width, currentFrame.size.height); | |
} | |
if (resizeMask) | |
{ | |
if (resizeMask & SMResizeTop) | |
{ | |
newY.origin = dragPoint.y; | |
newY.size = size = currentFrame.size.height + (currentFrame.origin.y - dragPoint.y); | |
} | |
if (resizeMask & SMResizeBottom) | |
{ | |
newY.size = dragPoint.y - currentFrame.origin.y; | |
} | |
if (resizeMask & SMResizeLeft) | |
{ | |
newX.origin = dragPoint.x; | |
newX.size = currentFrame.size.width + (currentFrame.origin.x - dragPoint.x); | |
} | |
else if (resizeMask & SMResizeRight) | |
{ | |
newX.size = dragPoint.x - currentFrame.origin.x; | |
} | |
var newFrame = CGRectMake(newX["origin"] || currentFrame.origin.x, newY["origin"] || currentFrame.origin.y, newX["size"] || currentFrame.size.width, newY["size"] || currentFrame.size.height); | |
} | |
[self setFrame:newFrame]; | |
} | |
- (void)mouseUp:(CPEvent)anEvent | |
{ | |
dragBeginPoint = nil; | |
resizeMask = nil; | |
// register the undo here | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment