1//
2//  PXLinearTool.m
3//  Pixen-XCode
4//
5//  Created by Ian Henderson on Mon Mar 15 2004.
6//  Copyright (c) 2004 Open Sword Group. All rights reserved.
7//
8
9#import "PXLinearTool.h"
10#import "PXCanvas.h"
11#import "PXCanvasController.h"
12
13
14@implementation PXLinearTool
15- init
16{
17    [super init];
18    locked = NO;
19	centeredOnOrigin = NO;
20    return self;
21}
22
23- (NSPoint)originWithDrawingPoint:(NSPoint)aPoint
24{
25	if (centeredOnOrigin) {
26		//  .      *      .
27		//  3      10     17
28		return NSMakePoint(2*_origin.x - aPoint.x, 2*_origin.y - aPoint.y);
29	}
30	return _origin;
31}
32- (BOOL)shiftKeyDown
33{
34    locked = YES;
35    return YES;
36}
37
38- (BOOL)shiftKeyUp
39{
40  locked = NO;
41  return YES;
42}
43
44- (BOOL)optionKeyDown
45{
46	centeredOnOrigin = YES;
47	return YES;
48}
49
50- (BOOL)optionKeyUp
51{
52	centeredOnOrigin = NO;
53	return YES;
54}
55
56- (void)mouseDownAt:(NSPoint)aPoint fromCanvasController:controller
57{
58    _origin = aPoint;
59    [super mouseDownAt:aPoint fromCanvasController:controller];
60	[[self undoManager] beginUndoGrouping];
61}
62
63- (void)finalDrawFromPoint:(NSPoint)origin toPoint:(NSPoint)finalPoint inCanvas:canvas
64{
65    // General class, no implementation.
66}
67
68- (void)drawFromPoint:(NSPoint)origin toPoint:(NSPoint)finalPoint inCanvas:canvas
69{
70    // General class, no implementation.
71}
72
73- (BOOL)supportsAdditionalLocking
74{
75    return NO;
76}
77
78- (NSPoint)lockedPointFromUnlockedPoint:(NSPoint)unlockedPoint withOrigin:(NSPoint)origin
79{
80    NSPoint modifiedFinal = unlockedPoint;
81    if (locked) {
82		float slope = (unlockedPoint.y - origin.y) / (unlockedPoint.x - origin.x);
83		if ([self supportsAdditionalLocking]) {
84			if (fabs(slope) < .25) {
85				modifiedFinal.y = origin.y;
86				return modifiedFinal;
87			} else if (fabs(slope) < .75) {
88				//x=2y ((but why do we need the +1??))
89				modifiedFinal.x = origin.x + (slope > 0 ? 1 : -1) * 2 * (modifiedFinal.y-origin.y) + (unlockedPoint.x > origin.x ? 1 : -1);
90				return modifiedFinal;
91			} else if (fabs(slope) < 1.5) {
92				//x=y
93				modifiedFinal.x = origin.x + (slope > 0 ? 1 : -1) * (modifiedFinal.y - origin.y);
94				return modifiedFinal;
95			} else if (fabs(slope) < 3) {
96				//y=2x ((but why do we need the +1??))
97				modifiedFinal.y = origin.y + (slope > 0 ? 1 : -1) * 2 * (unlockedPoint.x-origin.x) + (unlockedPoint.x > origin.x ? 1 : -1);
98				return modifiedFinal;
99			} else {
100				modifiedFinal.x = origin.x;
101				return modifiedFinal;
102			}
103		}
104		if (slope < 0) { // different diagonal
105			modifiedFinal.x = origin.x - (unlockedPoint.y - origin.y);
106		} else {
107			modifiedFinal.x = origin.x + (unlockedPoint.y - origin.y);
108		}
109    }
110    return modifiedFinal;
111}
112
113- (void)mouseUpAt:(NSPoint)aPoint fromCanvasController:controller
114{
115	NSPoint origin = [self originWithDrawingPoint:[self lockedPointFromUnlockedPoint:aPoint withOrigin:_origin]];
116	[[self undoManager] endUndoGrouping];
117    [self finalDrawFromPoint:origin toPoint:[self lockedPointFromUnlockedPoint:aPoint withOrigin:origin] inCanvas:[controller canvas]];
118    [super mouseUpAt:aPoint fromCanvasController:controller];
119}
120
121- (void)mouseDraggedFrom:(NSPoint)initialPoint to:(NSPoint)finalPoint fromCanvasController:controller
122{
123	NSPoint origin = [self originWithDrawingPoint:[self lockedPointFromUnlockedPoint:finalPoint withOrigin:_origin]];
124    if (!NSEqualPoints(initialPoint, finalPoint)) {
125		[[self undoManager] endUndoGrouping];
126		[[self undoManager] undoNestedGroup];
127        [[self undoManager] beginUndoGrouping];
128		[self drawFromPoint:origin toPoint:[self lockedPointFromUnlockedPoint:finalPoint withOrigin:origin] inCanvas:[controller canvas]];
129    }
130}
131@end
132