1// 2// PXRectangularSelectionTool.m 3// Pixen-XCode 4// 5// Created by Joe Osborn on Sun Jan 04 2004. 6// Copyright (c) 2004 Open Sword Group. All rights reserved. 7// 8 9#import "PXRectangularSelectionTool.h" 10#import "PXCanvasController.h" 11#import "PXCanvas.h" 12#import "PXCanvasView.h" 13#import "PXLayer.h" 14#import "PXSelectionLayer.h" 15#import "PXToolSwitcher.h" 16 17@implementation PXRectangularSelectionTool 18 19- (NSString *)name 20{ 21 return NSLocalizedString(@"RECTANGULARSELECTION_NAME", @"Rectangular Selection Tool"); 22} 23 24- movingActionName 25{ 26 return NSLocalizedString(@"MOVE_ACTION", @"Moving"); 27} 28 29- actionName 30{ 31 return NSLocalizedString(@"RECTANGULARSELECTION_ACTION", @"Selection"); 32} 33 34- (BOOL)shiftKeyDown 35{ 36 if (!isClicking) 37 { 38 isAdding = YES; 39 [switcher setIcon:[NSImage imageNamed:@"squareselectadd"] forTool:self]; 40 } 41 return YES; 42} 43 44- (BOOL)shiftKeyUp 45{ 46 if (!isClicking) 47 { 48 isAdding = NO; 49 [switcher setIcon:[NSImage imageNamed:@"squareselect"] forTool:self]; 50 } 51 return YES; 52} 53 54- (BOOL)optionKeyDown 55{ 56 if (!isClicking) 57 { 58 isSubtracting = YES; 59 [switcher setIcon:[NSImage imageNamed:@"squareselectsubtract"] forTool:self]; 60 } 61 return YES; 62} 63 64- (BOOL)optionKeyUp 65{ 66 if (!isClicking) 67 { 68 isSubtracting = NO; 69 [switcher setIcon:[NSImage imageNamed:@"squareselect"] forTool:self]; 70 } 71 return YES; 72} 73 74- (void)mouseDownAt:(NSPoint)aPoint fromCanvasController:controller 75{ 76 if (isSubtracting && ![[controller canvas] hasSelection]) { return; } 77 78 isClicking = YES; 79 origin = aPoint; 80 81 [[self undoManager] beginUndoGrouping]; 82 [self setLayers:[[[controller canvas] layers] deepMutableCopy] fromLayers:[[controller canvas] layers] ofCanvas:[controller canvas]]; 83 84 if([[controller canvas] pointIsSelected:aPoint] && (!isAdding && !isSubtracting)) 85 { 86 lastSelectedRect = [[controller canvas] selectedRect]; 87 [self startMovingCanvas:[controller canvas]]; 88 } 89 else 90 { 91 if (!isAdding && !isSubtracting) 92 { 93 [[controller canvas] deselect]; 94 oldLayerIndex = [[[controller canvas] layers] indexOfObject:[[controller canvas] activeLayer]]; 95 oldLastLayerIndex = [[[controller canvas] layers] indexOfObject:[[controller canvas] lastActiveLayer]]; 96 selectedRect = NSZeroRect; 97 } 98 else 99 { 100 if (oldLastLayerIndex != NSNotFound) 101 { 102 [[controller canvas] restoreActivateLayer:[[[controller canvas] layers] objectAtIndex:oldLayerIndex] lastActiveLayer:[[[controller canvas] layers] objectAtIndex:oldLastLayerIndex]]; 103 } 104 else 105 { 106 [[controller canvas] restoreActivateLayer:[[[controller canvas] layers] objectAtIndex:oldLayerIndex] lastActiveLayer:nil]; 107 } 108 } 109 [[controller canvas] changedInRect:NSMakeRect(lastSelectedRect.origin.x-2, lastSelectedRect.origin.y-2, lastSelectedRect.size.width+4, lastSelectedRect.size.height+4)]; 110 lastSelectedRect = NSZeroRect; 111 } 112 113 if (isSubtracting) 114 [[[[controller canvas] layers] lastObject] setIsSubtracting:YES]; 115} 116 117- (void)setLayers:layers fromLayers:oldLayers ofCanvas:canvas 118{ 119 [[[self undoManager] prepareWithInvocationTarget:self] setLayers:oldLayers fromLayers:layers ofCanvas:canvas]; 120 [canvas setLayers:layers]; 121 lastSelectedRect = NSZeroRect; 122} 123 124- (void)startMovingCanvas:canvas 125{ 126 [[self undoManager] setActionName:[self movingActionName]]; 127 isMoving = YES; 128} 129 130- (void)stopMovingCanvas:canvas 131{ 132 isMoving = NO; 133 selectedRect = lastSelectedRect; 134 [[canvas activeLayer] finalizeMotion]; 135} 136 137- (void)refreshRect:(NSRect)rectangle inView:view 138{ 139 NSRect modifiedRect = rectangle; 140 modifiedRect.origin.x -= 1; 141 modifiedRect.origin.y -= 1; 142 modifiedRect.size.width += 2; 143 modifiedRect.size.height += 2; 144 [view displayRect:[view convertFromCanvasToViewRect:modifiedRect]]; 145} 146 147- (void)mouseDraggedFrom:(NSPoint)initialPoint to:(NSPoint)finalPoint fromCanvasController:(PXCanvasController *)controller 148{ 149 if (isSubtracting && ![[controller canvas] hasSelection]) { return; } 150 151 if(isMoving) 152 { 153 [[[controller canvas] activeLayer] translateXBy:(finalPoint.x - initialPoint.x) yBy:(finalPoint.y - initialPoint.y)]; 154 [[controller canvas] changedInRect:NSMakeRect(0,0,[[controller canvas] size].width,[[controller canvas] size].height)]; 155 } 156 else 157 { 158 [[self undoManager] setActionName:[self actionName]]; 159 int i, j; 160 for(i = lastSelectedRect.origin.x; i < NSMaxX(lastSelectedRect); i++) 161 { 162 for(j = lastSelectedRect.origin.y; j < NSMaxY(lastSelectedRect); j++) 163 { 164 [[controller canvas] deselectPixelAtPoint:NSMakePoint(i, j)]; 165 } 166 } 167 selectedRect = NSIntersectionRect(NSUnionRect(NSMakeRect(origin.x, origin.y, 1, 1), NSMakeRect(finalPoint.x, finalPoint.y, 1, 1)), NSMakeRect(0, 0, [[controller canvas] size].width, [[controller canvas] size].height)); 168 if(!NSEqualPoints(origin, finalPoint)) 169 { 170 int i, j; 171 for(i = selectedRect.origin.x; i < NSMaxX(selectedRect); i++) 172 { 173 for(j = selectedRect.origin.y; j < NSMaxY(selectedRect); j++) 174 { 175 [[controller canvas] selectPixelAtPoint:NSMakePoint(i, j)]; 176 } 177 } 178 //selectedRect = [[controller canvas] selectedRect]; 179 //selectedRect = NSMakeRect(0,0,[[controller canvas] size].width,[[controller canvas] size].height); 180 181 // really ugly code! 182 // DO NOT READ BELOW THIS LINE IF YOU WISH TO RETAIN YOUR SANITY 183 184 NSRect shortVerticalDirty, longVerticalDirty, shortHorizontalDirty, longHorizontalDirty, lastVerticalDirty, lastHorizontalDirty; // phew 185 186 if (NSEqualPoints(selectedRect.origin, lastSelectedRect.origin)) { // quadrant I 187 // ------- 4 -- 188 // | | 189 // 1 2 190 // ...6... | 191 // : 5 | 192 // :.....:_3__| 193 194 // 1) 195 shortVerticalDirty = NSMakeRect(selectedRect.origin.x, selectedRect.origin.y + MIN(lastSelectedRect.size.height, selectedRect.size.height), 196 1, fabs(selectedRect.size.height - lastSelectedRect.size.height) + 1); 197 // 2) 198 longVerticalDirty = NSMakeRect(selectedRect.origin.x + selectedRect.size.width, selectedRect.origin.y, 199 1, selectedRect.size.height + 1); 200 // 3) 201 shortHorizontalDirty = NSMakeRect(selectedRect.origin.x + MIN(lastSelectedRect.size.width, selectedRect.size.width), selectedRect.origin.y, 202 fabs(selectedRect.size.width - lastSelectedRect.size.width) + 1, 1); 203 // 4) 204 longHorizontalDirty = NSMakeRect(selectedRect.origin.x, selectedRect.origin.y + selectedRect.size.height, 205 selectedRect.size.width + 1, 1); 206 // 5) 207 lastVerticalDirty = NSMakeRect(selectedRect.origin.x + lastSelectedRect.size.width, selectedRect.origin.y, 208 1, lastSelectedRect.size.height + 1); 209 // 6) 210 lastHorizontalDirty = NSMakeRect(selectedRect.origin.x, selectedRect.origin.y + lastSelectedRect.size.height, 211 lastSelectedRect.size.width + 1, 1); 212 213 } else if (selectedRect.origin.x + selectedRect.size.width == lastSelectedRect.origin.x + lastSelectedRect.size.width && 214 selectedRect.origin.y == lastSelectedRect.origin.y) { // quadrant II 215 // ------- 4 -- 216 // | | 217 // 2 1 218 // | ...6... 219 // | 5 : 220 // |__3_:.....: 221 222 // 1) 223 shortVerticalDirty = NSMakeRect(selectedRect.origin.x + selectedRect.size.width, selectedRect.origin.y + MIN(lastSelectedRect.size.height, selectedRect.size.height), 224 1, fabs(selectedRect.size.height - lastSelectedRect.size.height) + 1); 225 // 2) 226 longVerticalDirty = NSMakeRect(selectedRect.origin.x, selectedRect.origin.y, 227 1, selectedRect.size.height + 1); 228 // 3) 229 shortHorizontalDirty = NSMakeRect(selectedRect.origin.x + MIN(selectedRect.size.width - lastSelectedRect.size.width, 0), selectedRect.origin.y, 230 fabs(selectedRect.size.width - lastSelectedRect.size.width) + 1, 1); 231 // 4) 232 longHorizontalDirty = NSMakeRect(selectedRect.origin.x, selectedRect.origin.y + selectedRect.size.height, 233 selectedRect.size.width + 1, 1); 234 // 5) 235 lastVerticalDirty = NSMakeRect(selectedRect.origin.x + selectedRect.size.width - lastSelectedRect.size.width, selectedRect.origin.y, 236 1, lastSelectedRect.size.height + 1); 237 // 6) 238 lastHorizontalDirty = NSMakeRect(selectedRect.origin.x + selectedRect.size.width - lastSelectedRect.size.width, selectedRect.origin.y + lastSelectedRect.size.height, 239 lastSelectedRect.size.width + 1, 1); 240 241 242 } else if (selectedRect.origin.x + selectedRect.size.width == lastSelectedRect.origin.x + lastSelectedRect.size.width && 243 selectedRect.origin.y + selectedRect.size.height == lastSelectedRect.origin.y + lastSelectedRect.size.height) { // quadrant III 244 // - 3 -....... 245 // | 5 : 246 // 2 :..6..: 247 // | | 248 // | 1 249 // |__4_______| 250 251 // 1) 252 shortVerticalDirty = NSMakeRect(selectedRect.origin.x + selectedRect.size.width, selectedRect.origin.y + MIN(selectedRect.size.height - lastSelectedRect.size.height, 0), 253 1, fabs(selectedRect.size.height - lastSelectedRect.size.height) + 1); 254 // 2) 255 longVerticalDirty = NSMakeRect(selectedRect.origin.x, selectedRect.origin.y, 256 1, selectedRect.size.height + 1); 257 // 3) 258 shortHorizontalDirty = NSMakeRect(selectedRect.origin.x + MIN(selectedRect.size.width - lastSelectedRect.size.width, 0), selectedRect.origin.y + selectedRect.size.height, 259 fabs(selectedRect.size.width - lastSelectedRect.size.width) + 1, 1); 260 // 4) 261 longHorizontalDirty = NSMakeRect(selectedRect.origin.x, selectedRect.origin.y, 262 selectedRect.size.width + 1, 1); 263 // 5) 264 lastVerticalDirty = NSMakeRect(selectedRect.origin.x + selectedRect.size.width - lastSelectedRect.size.width, selectedRect.origin.y + selectedRect.size.height - lastSelectedRect.size.height, 265 1, lastSelectedRect.size.height + 1); 266 // 6) 267 lastHorizontalDirty = NSMakeRect(selectedRect.origin.x + selectedRect.size.width - lastSelectedRect.size.width, selectedRect.origin.y + selectedRect.size.height - lastSelectedRect.size.height, 268 lastSelectedRect.size.width + 1, 1); 269 270 271 } else if (selectedRect.origin.x == lastSelectedRect.origin.x && 272 selectedRect.origin.y + selectedRect.size.height == lastSelectedRect.origin.y + lastSelectedRect.size.height) { // quadrant IV 273 // .......- 3 - 274 // : 5 | 275 // :..6..: | 276 // | | 277 // 1 2 278 // |________4_| 279 280 // 1) 281 shortVerticalDirty = NSMakeRect(selectedRect.origin.x, selectedRect.origin.y + MIN(selectedRect.size.height - lastSelectedRect.size.height, 0), 282 1, fabs(selectedRect.size.height - lastSelectedRect.size.height) + 1); 283 // 2) 284 longVerticalDirty = NSMakeRect(selectedRect.origin.x + selectedRect.size.width, selectedRect.origin.y, 285 1, selectedRect.size.height + 1); 286 // 3) 287 shortHorizontalDirty = NSMakeRect(selectedRect.origin.x + MIN(lastSelectedRect.size.width, selectedRect.size.width), selectedRect.origin.y + selectedRect.size.height, 288 fabs(selectedRect.size.width - lastSelectedRect.size.width) + 1, 1); 289 // 4) 290 longHorizontalDirty = NSMakeRect(selectedRect.origin.x, selectedRect.origin.y, 291 selectedRect.size.width + 1, 1); 292 // 5) 293 lastVerticalDirty = NSMakeRect(selectedRect.origin.x + lastSelectedRect.size.width, selectedRect.origin.y + selectedRect.size.height - lastSelectedRect.size.height, 294 1, lastSelectedRect.size.height + 1); 295 // 6) 296 lastHorizontalDirty = NSMakeRect(selectedRect.origin.x, selectedRect.origin.y + selectedRect.size.height - lastSelectedRect.size.height, 297 lastSelectedRect.size.width + 1, 1); 298 } else { // TRANSITION OMG 299 // ? 300 lastHorizontalDirty = NSZeroRect; 301 lastVerticalDirty = NSZeroRect; 302 shortVerticalDirty = NSUnionRect(NSMakeRect(selectedRect.origin.x, selectedRect.origin.y, 1, selectedRect.size.height), 303 NSMakeRect(lastSelectedRect.origin.x, lastSelectedRect.origin.y, 1, lastSelectedRect.size.height)); 304 305 shortHorizontalDirty = NSUnionRect(NSMakeRect(selectedRect.origin.x, selectedRect.origin.y, selectedRect.size.width, 1), 306 NSMakeRect(lastSelectedRect.origin.x, lastSelectedRect.origin.y, lastSelectedRect.size.width, 1)); 307 308 longVerticalDirty = NSUnionRect(NSMakeRect(selectedRect.origin.x + selectedRect.size.width, selectedRect.origin.y, 1, selectedRect.size.height), 309 NSMakeRect(lastSelectedRect.origin.x + lastSelectedRect.size.width, lastSelectedRect.origin.y, 1, lastSelectedRect.size.height)); 310 311 longHorizontalDirty = NSUnionRect(NSMakeRect(selectedRect.origin.x, selectedRect.origin.y + selectedRect.size.height, selectedRect.size.width, 1), 312 NSMakeRect(lastSelectedRect.origin.x, lastSelectedRect.origin.y + lastSelectedRect.size.height, lastSelectedRect.size.width, 1)); 313 } 314 315 if (lastVerticalDirty.size.height >= 1) { 316 [self refreshRect:lastVerticalDirty inView:[controller view]]; 317 } 318 if (lastHorizontalDirty.size.width >= 1) { 319 [self refreshRect:lastHorizontalDirty inView:[controller view]]; 320 } 321 [self refreshRect:longVerticalDirty inView:[controller view]]; 322 [self refreshRect:longHorizontalDirty inView:[controller view]]; 323 [self refreshRect:shortVerticalDirty inView:[controller view]]; 324 [self refreshRect:shortHorizontalDirty inView:[controller view]]; 325 326 lastSelectedRect = selectedRect; 327 } 328 } 329} 330 331- (void)mouseUpAt:(NSPoint)aPoint fromCanvasController:controller 332{ 333 if (isSubtracting && ![[controller canvas] hasSelection]) { return; } 334 335 isClicking = NO; 336 if(isMoving) 337 { 338 [self stopMovingCanvas:[controller canvas]]; 339 } 340 else if(NSEqualPoints(origin, aPoint)) 341 { 342 NSRect deselectRect = [[controller canvas] selectedRect]; 343 [[controller canvas] deselect]; 344 [[controller canvas] changedInRect:NSMakeRect(deselectRect.origin.x-2, deselectRect.origin.y-2, deselectRect.size.width+4, deselectRect.size.height+4)]; 345 } 346 else 347 { 348 NSRect changeRect = [[controller canvas] selectedRect]; 349 350 if (isSubtracting) 351 { 352 int i, j; 353 for (i = lastSelectedRect.origin.x; i < NSMaxX(lastSelectedRect); i++) 354 { 355 for (j = lastSelectedRect.origin.y; j < NSMaxY(lastSelectedRect); j++) 356 { 357 NSPoint point = NSMakePoint(i, j); 358 [[controller canvas] deselectPixelAtPoint:point]; 359 if ([[controller canvas] pointIsSelected:point]) 360 { 361 [[controller canvas] setColor:[[[[controller canvas] layers] lastObject] colorAtPoint:point] atPoint:point]; 362 } 363 [[[[controller canvas] layers] lastObject] setColor:nil atPoint:point]; 364 365 } 366 } 367 [[[[controller canvas] layers] lastObject] finalize]; 368 [[controller canvas] activateLayer:[[[controller canvas] layers] lastObject]]; 369 changeRect = NSUnionRect(changeRect, lastSelectedRect); 370 } 371 else 372 [[controller canvas] finalizeSelection]; 373 changeRect.size.width++; 374 changeRect.size.height++; 375 [[controller canvas] changedInRect:changeRect]; 376 } 377 378 if (isSubtracting && !(NSEqualPoints(origin, aPoint))) 379 [[[[controller canvas] layers] lastObject] setIsSubtracting:NO]; 380 381 [[self undoManager] endUndoGrouping]; 382} 383 384@end 385