1/* 2 Project: Graphos 3 GRCircle.m 4 5 Copyright (C) 2009-2018 GNUstep Application Project 6 7 Author: Ing. Riccardo Mottola 8 9 Created: 2009-12-27 10 11 This application is free software; you can redistribute it and/or 12 modify it under the terms of the GNU General Public 13 License as published by the Free Software Foundation; either 14 version 2 of the License, or (at your option) any later version. 15 16 This application is distributed in the hope that it will be useful, 17 but WITHOUT ANY WARRANTY; without even the implied warranty of 18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 Library General Public License for more details. 20 21 You should have received a copy of the GNU General Public 22 License along with this library; if not, write to the Free 23 Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 24 */ 25 26#import <AppKit/NSColor.h> 27#import <AppKit/NSGraphics.h> 28#import <AppKit/NSGraphicsContext.h> 29#import "GRCircle.h" 30#import "GRCircleEditor.h" 31#import "GRFunctions.h" 32 33@implementation GRCircle 34 35- (GRObjectEditor *)allocEditor 36{ 37 return [[GRCircleEditor alloc] initEditor:self]; 38} 39 40/** initializes by using the properties array as defaults */ 41- (id)initInView:(GRDocView *)aView 42 zoomFactor:(CGFloat)zf 43 withProperties:(NSDictionary *)properties 44{ 45 self = [super initInView:aView zoomFactor:zf withProperties:properties]; 46 if(self) 47 { 48 id obj; 49 50 pos = NSMakePoint([[properties objectForKey: @"posx"] floatValue], 51 [[properties objectForKey: @"posy"] floatValue]); 52 size = NSMakeSize([[properties objectForKey: @"width"] floatValue], 53 [[properties objectForKey: @"height"] floatValue]); 54 bounds = GRMakeBounds(pos.x, pos.y, size.width, size.height); 55 56 isCircle = NO; 57 obj = [properties objectForKey: @"circle"]; 58 if (obj) 59 isCircle = [obj boolValue]; 60 61 rotation = 0; 62 obj = [properties objectForKey: @"rotation"]; 63 if (obj) 64 rotation = [obj floatValue]; 65 66 startControlPoint = [[GRObjectControlPoint alloc] initAtPoint: pos zoomFactor:zf]; 67 endControlPoint = [[GRObjectControlPoint alloc] initAtPoint: NSMakePoint(pos.x + size.width, pos.y + size.height) zoomFactor:zf]; 68 [self setZoomFactor: zf]; 69 } 70 71 return self; 72} 73 74/** initializes all parameters from a description dictionary */ 75- (id)initFromData:(NSDictionary *)description 76 inView:(GRDocView *)aView 77 zoomFactor:(CGFloat)zf 78{ 79 self = [super initFromData:description inView:aView zoomFactor:zf]; 80 if(self) 81 { 82 id obj; 83 84 pos = NSMakePoint([[description objectForKey: @"posx"] floatValue], 85 [[description objectForKey: @"posy"] floatValue]); 86 size = NSMakeSize([[description objectForKey: @"width"] floatValue], 87 [[description objectForKey: @"height"] floatValue]); 88 bounds = GRMakeBounds(pos.x, pos.y, size.width, size.height); 89 90 isCircle = NO; 91 obj = [description objectForKey: @"circle"]; 92 if (obj) 93 isCircle = [obj boolValue]; 94 95 rotation = 0; 96 obj = [description objectForKey: @"rotation"]; 97 if (obj) 98 rotation = [obj floatValue]; 99 100 startControlPoint = [[GRObjectControlPoint alloc] initAtPoint: pos zoomFactor:zf]; 101 endControlPoint = [[GRObjectControlPoint alloc] initAtPoint: NSMakePoint(pos.x + size.width, pos.y + size.height) zoomFactor:zf]; 102 [self setZoomFactor: zf]; 103 } 104 return self; 105} 106 107- (id)copyWithZone:(NSZone *)zone 108{ 109 GRCircle *objCopy; 110 111 objCopy = [super copyWithZone:zone]; 112 113 objCopy->startControlPoint = [[GRObjectControlPoint alloc] initAtPoint: pos zoomFactor:zmFactor]; 114 objCopy->endControlPoint = [[GRObjectControlPoint alloc] initAtPoint: NSMakePoint(pos.x + size.width, pos.y + size.height) zoomFactor:zmFactor]; 115 116 117 objCopy->pos = NSMakePoint(pos.x, pos.y); 118 objCopy->size = NSMakeSize(size.width, size.height); 119 objCopy->bounds = NSMakeRect(bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height); 120 objCopy->boundsZ = NSMakeRect(boundsZ.origin.x, boundsZ.origin.y, boundsZ.size.width, boundsZ.size.height); 121 objCopy->rotation = rotation; 122 objCopy->isCircle = isCircle; 123 124 return objCopy; 125} 126 127- (void)dealloc 128{ 129 [startControlPoint release]; 130 [endControlPoint release]; 131 [super dealloc]; 132} 133 134- (NSDictionary *)objectDescription 135{ 136 NSMutableDictionary *dict; 137 NSString *str; 138 float strokeCol[3]; 139 float fillCol[3]; 140 float strokeAlpha; 141 float fillAlpha; 142 143 strokeCol[0] = [strokeColor redComponent]; 144 strokeCol[1] = [strokeColor greenComponent]; 145 strokeCol[2] = [strokeColor blueComponent]; 146 strokeAlpha = [strokeColor alphaComponent]; 147 148 fillCol[0] = [fillColor redComponent]; 149 fillCol[1] = [fillColor greenComponent]; 150 fillCol[2] = [fillColor blueComponent]; 151 fillAlpha = [fillColor alphaComponent]; 152 153 dict = [NSMutableDictionary dictionaryWithCapacity: 1]; 154 [dict setObject: @"circle" forKey: @"type"]; 155 156 str = [NSString stringWithFormat: @"%i", isCircle]; 157 [dict setObject: str forKey: @"circle"]; 158 159 str = [NSString stringWithFormat: @"%.3f", pos.x]; 160 [dict setObject: str forKey: @"posx"]; 161 str = [NSString stringWithFormat: @"%.3f", pos.y]; 162 [dict setObject: str forKey: @"posy"]; 163 164 str = [NSString stringWithFormat: @"%.3f", size.width]; 165 [dict setObject: str forKey: @"width"]; 166 str = [NSString stringWithFormat: @"%.3f", size.height]; 167 [dict setObject: str forKey: @"height"]; 168 169 str = [NSString stringWithFormat: @"%.3f", flatness]; 170 [dict setObject: str forKey: @"flatness"]; 171 str = [NSString stringWithFormat: @"%i", linejoin]; 172 [dict setObject: str forKey: @"linejoin"]; 173 str = [NSString stringWithFormat: @"%i", linecap]; 174 [dict setObject: str forKey: @"linecap"]; 175 str = [NSString stringWithFormat: @"%.3f", miterlimit]; 176 [dict setObject: str forKey: @"miterlimit"]; 177 str = [NSString stringWithFormat: @"%.3f", linewidth]; 178 [dict setObject: str forKey: @"linewidth"]; 179 str = [NSString stringWithFormat: @"%i", stroked]; 180 [dict setObject: str forKey: @"stroked"]; 181 str = [NSString stringWithFormat: @"%.3f %.3f %.3f", 182 strokeCol[0], strokeCol[1], strokeCol[2]]; 183 [dict setObject: str forKey: @"strokecolor"]; 184 str = [NSString stringWithFormat: @"%.3f", strokeAlpha]; 185 [dict setObject: str forKey: @"strokealpha"]; 186 str = [NSString stringWithFormat: @"%i", filled]; 187 [dict setObject: str forKey: @"filled"]; 188 str = [NSString stringWithFormat: @"%.3f %.3f %.3f", 189 fillCol[0], fillCol[1], fillCol[2]]; 190 [dict setObject: str forKey: @"fillcolor"]; 191 str = [NSString stringWithFormat: @"%.3f", fillAlpha]; 192 [dict setObject: str forKey: @"fillalpha"]; 193 str = [NSString stringWithFormat: @"%i", visible]; 194 [dict setObject: str forKey: @"visible"]; 195 str = [NSString stringWithFormat: @"%i", locked]; 196 [dict setObject: str forKey: @"locked"]; 197 198 return dict; 199} 200 201- (BOOL)circle 202{ 203 return isCircle; 204} 205 206- (void)setCircle:(BOOL)flag 207{ 208 isCircle = flag; 209} 210 211- (void)setStartAtPoint:(NSPoint)aPoint 212{ 213 pos = aPoint; 214 [startControlPoint moveToPoint: aPoint]; 215 [startControlPoint select]; 216} 217 218- (void)setEndAtPoint:(NSPoint)aPoint 219{ 220 size.width = aPoint.x - pos.x; 221 size.height = aPoint.y- pos.y; 222 bounds = GRMakeBounds(pos.x, pos.y, size.width, size.height); 223 [endControlPoint moveToPoint: aPoint]; 224 [endControlPoint select]; 225 226 boundsZ = GRMakeBounds(pos.x * zmFactor, pos.y * zmFactor, size.width * zmFactor, size.height * zmFactor); 227} 228 229- (void)remakePath 230{ 231 [self setStartAtPoint:[startControlPoint center]]; 232 [self setEndAtPoint:[endControlPoint center]]; 233 [(GRCircleEditor *)editor setIsDone:YES]; 234} 235 236 237- (void)setLocked:(BOOL)value 238{ 239 [super setLocked:value]; 240 if(!locked) 241 [(GRCircleEditor *)editor unselect]; 242 else 243 [(GRCircleEditor *)editor selectAsGroup]; 244} 245 246- (BOOL)objectHitForSelection:(NSPoint)p 247{ 248 return (pointInRect(bounds, p)); 249} 250 251- (BOOL)onControlPoint:(NSPoint)p 252{ 253 if (pointInRect([startControlPoint centerRect], p)) 254 return YES; 255 if (pointInRect([endControlPoint centerRect], p)) 256 return YES; 257 return NO; 258} 259 260- (GRObjectControlPoint *) startControlPoint 261{ 262 return startControlPoint; 263} 264 265- (GRObjectControlPoint *) endControlPoint 266{ 267 return endControlPoint; 268} 269 270 271- (void)moveAddingCoordsOfPoint:(NSPoint)p 272{ 273 pos.x += p.x; 274 pos.y += p.y; 275 bounds = GRMakeBounds(pos.x, pos.y, size.width, size.height); 276 [startControlPoint moveToPoint: pos]; 277 [endControlPoint moveToPoint: NSMakePoint(pos.x + size.width, pos.y + size.height)]; 278 279 boundsZ = GRMakeBounds(pos.x * zmFactor, pos.y * zmFactor, size.width * zmFactor, size.height * zmFactor); 280} 281 282- (void)setZoomFactor:(CGFloat)f 283{ 284 [super setZoomFactor:f]; 285 286 [startControlPoint setZoomFactor:f]; 287 [endControlPoint setZoomFactor:f]; 288 [self remakePath]; 289} 290 291/** bounds accessor */ 292- (NSRect)bounds 293{ 294 return bounds; 295} 296 297/** position accessor */ 298- (NSPoint) position 299{ 300 return pos; 301} 302 303/** draws the object and calls the editor to draw itself afterwards */ 304- (void)draw 305{ 306 NSBezierPath *bzp; 307 NSPoint center; 308 CGFloat radius; 309 CGFloat w,h; 310 CGFloat minLength; 311 CGFloat linew; 312 NSRect drawBounds; 313 314 drawBounds = bounds; 315 linew = linewidth; 316 if ([[NSGraphicsContext currentContext] isDrawingToScreen]) 317 { 318 drawBounds = boundsZ; 319 linew = linewidth * zmFactor; 320 } 321 322 center = NSMakePoint(NSMidX(drawBounds), NSMidY(drawBounds)); 323 w = NSWidth(drawBounds); 324 h = NSHeight(drawBounds); 325 if (w > h) 326 minLength = h; 327 else 328 minLength = w; 329 radius = minLength / 2; 330 331 bzp = [NSBezierPath bezierPath]; 332 if (isCircle) 333 [bzp appendBezierPathWithArcWithCenter:center radius:radius startAngle:0 endAngle:360]; 334 else 335 [bzp appendBezierPathWithOvalInRect: drawBounds]; 336 337 if(filled) 338 { 339 [NSGraphicsContext saveGraphicsState]; 340 [fillColor set]; 341 [bzp fill]; 342 [NSGraphicsContext restoreGraphicsState]; 343 } 344 if(stroked) 345 { 346 [NSGraphicsContext saveGraphicsState]; 347 [bzp setLineJoinStyle:linejoin]; 348 [bzp setLineCapStyle:linecap]; 349 [bzp setLineWidth:linew]; 350 [strokeColor set]; 351 [bzp stroke]; 352 [NSGraphicsContext restoreGraphicsState]; 353 } 354 355 if ([[NSGraphicsContext currentContext] isDrawingToScreen]) 356 [editor draw]; 357} 358 359 360@end 361