1//
2//  PXLassoTool.m
3//  Pixen-XCode
4//
5//  Created by Joe Osborn on Sat Jun 12 2004.
6//  Copyright (c) 2004 Open Sword Group. All rights reserved.
7//
8
9#import "PXLassoTool.h"
10#import "PXCanvasController.h"
11#import "PXCanvas.h"
12#import "PXSelectionLayer.h"
13#import "PXToolSwitcher.h"
14
15#ifndef __COCOA__
16#import "NSArray_DeepMutableCopy.h"
17#endif
18
19@implementation PXLassoTool
20
21- (NSString *)name
22{
23	return NSLocalizedString(@"LASSO_NAME", @"Lasso Tool");
24}
25
26- init
27{
28	[super init];
29	selected = [[NSMutableArray alloc] initWithCapacity:128*128];
30	isClicking = NO;
31	return self;
32}
33
34- actionName
35{
36    return NSLocalizedString(@"LASSO_ACTION", @"Selection");
37}
38
39- movingActionName
40{
41	return NSLocalizedString(@"MOVE_ACTION", @"Moving");
42}
43
44- (BOOL)shiftKeyDown
45{
46	if (!isClicking)
47	{
48		isAdding = YES;
49		[switcher setIcon:[NSImage imageNamed:@"lassoadd"] forTool:self];
50	}
51	return YES;
52}
53
54- (BOOL)shiftKeyUp
55{
56	if (!isClicking)
57	{
58		isAdding = NO;
59		[switcher setIcon:[NSImage imageNamed:@"lasso"] forTool:self];
60	}
61	return YES;
62}
63
64- (BOOL)optionKeyDown
65{
66	if (!isClicking)
67	{
68		isSubtracting = YES;
69		[switcher setIcon:[NSImage imageNamed:@"lassosubtract"] forTool:self];
70	}
71	return YES;
72}
73
74- (BOOL)optionKeyUp
75{
76	if (!isClicking)
77	{
78		isSubtracting = NO;
79		[switcher setIcon:[NSImage imageNamed:@"lasso"] forTool:self];
80	}
81	return YES;
82}
83
84- (void)mouseDownAt:(NSPoint)aPoint fromCanvasController:controller
85{
86	if (isSubtracting && ![[controller canvas] hasSelection]) { return; }
87
88	[selected removeAllObjects];
89	isClicking = YES;
90	origin = aPoint;
91	leftMost = origin.x;
92	rightMost = origin.x;
93	bottomMost = origin.y;
94	topMost = origin.y;
95	[path release];
96	path = [[NSBezierPath bezierPath] retain];
97	[path moveToPoint:origin];
98	[self setLayers:[[[controller canvas] layers] deepMutableCopy] fromLayers:[[controller canvas] layers] ofCanvas:[controller canvas]];
99
100	if([[controller canvas] pointIsSelected:aPoint] && (!isAdding && !isSubtracting))
101	{
102		[self startMovingCanvas:[controller canvas]];
103	}
104	else
105	{
106		if (!isAdding && !isSubtracting)
107		{
108			[[controller canvas] deselect];
109			oldLayerIndex = [[[controller canvas] layers] indexOfObject:[[controller canvas] activeLayer]];
110			oldLastLayerIndex = [[[controller canvas] layers] indexOfObject:[[controller canvas] lastActiveLayer]];
111		}
112		else
113		{
114			if (oldLastLayerIndex != NSNotFound)
115			{
116				[[controller canvas] restoreActivateLayer:[[[controller canvas] layers] objectAtIndex:oldLayerIndex] lastActiveLayer:[[[controller canvas] layers] objectAtIndex:oldLastLayerIndex]];
117			}
118			else
119			{
120				[[controller canvas] restoreActivateLayer:[[[controller canvas] layers] objectAtIndex:oldLayerIndex] lastActiveLayer:nil];
121			}
122		}
123		[super mouseDownAt:aPoint fromCanvasController:controller];
124		[[controller canvas] changedInRect:NSMakeRect(leftMost-2, bottomMost-2, rightMost-leftMost-2, topMost-bottomMost-2)];
125	}
126
127	if (isSubtracting)
128	{
129		[[[[controller canvas] layers] lastObject] setIsSubtracting:YES];
130	}
131}
132
133- (void)setLayers:layers fromLayers:oldLayers ofCanvas:canvas
134{
135	[[[self undoManager] prepareWithInvocationTarget:self] setLayers:oldLayers fromLayers:layers ofCanvas:canvas];
136	[canvas setLayers:layers];
137}
138
139- (void)startMovingCanvas:canvas
140{
141	[[self undoManager] setActionName:[self movingActionName]];
142	isMoving = YES;
143}
144
145- (void)stopMovingCanvas:canvas
146{
147	isMoving = NO;
148	[[canvas activeLayer] finalizeMotion];
149}
150
151- (void)mouseDraggedFrom:(NSPoint)initialPoint to:(NSPoint)finalPoint fromCanvasController:controller
152{
153	if (isSubtracting && ![[controller canvas] hasSelection]) { return; }
154
155	if(isMoving)
156	{
157		[[[controller canvas] activeLayer] translateXBy:(finalPoint.x - initialPoint.x) yBy:(finalPoint.y - initialPoint.y)];
158		[[controller canvas] changedInRect:NSMakeRect(0,0,[[controller canvas] size].width,[[controller canvas] size].height)];
159	}
160	else
161	{
162		[[self undoManager] setActionName:[self actionName]];
163		[super mouseDraggedFrom:initialPoint to:finalPoint fromCanvasController:controller];
164	}
165}
166
167- (void)mouseUpAt:(NSPoint)aPoint fromCanvasController:controller
168{
169	if (isSubtracting && ![[controller canvas] hasSelection]) { return; }
170
171	isClicking = NO;
172	if(isMoving)
173	{
174		[self stopMovingCanvas:[controller canvas]];
175	}
176	else if(NSEqualPoints(origin, aPoint) && ([selected count] <= 1))
177	{
178		NSRect deselectRect = [[controller canvas] selectedRect];
179		[[controller canvas] deselect];
180		[[controller canvas] changedInRect:NSMakeRect(deselectRect.origin.x-2, deselectRect.origin.y-2, deselectRect.size.width+4, deselectRect.size.height+4)];
181	}
182	else
183	{
184		[path lineToPoint:aPoint];
185		id enumerator = [selected objectEnumerator];
186		id current;
187		while ( ( current = [enumerator nextObject] ) )
188		{
189			[[controller canvas] deselectPixelAtPoint:NSPointFromString(current)];
190		}
191		int i, j;
192		//go from left to right
193		for(i = leftMost; i <= rightMost; i++)
194		{
195			//go from bottom to top
196			for(j = bottomMost; j <= topMost; j++)
197			{
198				NSPoint point = NSMakePoint(i, j);
199				if([path containsPoint:point])
200				{
201					if(isSubtracting)
202					{
203						if ([[controller canvas] pointIsSelected:point] && [[[[controller canvas] layers] lastObject] colorAtPoint:point] != nil)
204						{
205							[[controller canvas] deselectPixelAtPoint:point];
206							[[controller canvas] setColor:[[[[controller canvas] layers] lastObject] colorAtPoint:point] atPoint:point];
207							[[[[controller canvas] layers] lastObject] setColor:nil atPoint:point];
208						}
209					}
210					else
211					{
212						[[controller canvas] selectPixelAtPoint:point];
213					}
214				}
215			}
216		}
217		if (isSubtracting)
218		{
219			[[[[controller canvas] layers] lastObject] setIsSubtracting:NO];
220		}
221		[[controller canvas] finalizeSelection];
222		[super mouseUpAt:aPoint fromCanvasController:controller];
223	}
224
225    if([[self undoManager] groupingLevel] != 0)
226	{
227		[[self undoManager] endUndoGrouping];
228	}
229	[[controller canvas] changedInRect:NSMakeRect(leftMost-8, bottomMost-8, rightMost-leftMost+16, topMost-bottomMost+16)];
230}
231
232
233- (void)drawPixelAtPoint:(NSPoint)point inCanvas:canvas
234{
235	leftMost = MIN(point.x, leftMost);
236	rightMost = MAX(point.x, rightMost);
237	bottomMost = MIN(point.y, bottomMost);
238	topMost = MAX(point.y, topMost);
239	[canvas selectPixelAtPoint:point];
240	[selected addObject:NSStringFromPoint(point)];
241	[canvas changedInRect:NSMakeRect(point.x-8, point.y-8, 16, 16)];
242	[path lineToPoint:point];
243}
244
245@end
246