1/* 2 Project: Graphos 3 GRText.m 4 5 Copyright (C) 2000-2018 GNUstep Application Project 6 7 Author: Enrico Sersale (original GDraw implementation) 8 Author: Ing. Riccardo Mottola 9 10 This application is free software; you can redistribute it and/or 11 modify it under the terms of the GNU General Public 12 License as published by the Free Software Foundation; either 13 version 2 of the License, or (at your option) any later version. 14 15 This application is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 Library General Public License for more details. 19 20 You should have received a copy of the GNU General Public 21 License along with this library; if not, write to the Free 22 Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 23 */ 24 25 26#import "GRText.h" 27#import "GRDocView.h" 28#import "GRFunctions.h" 29#import "Graphos.h" 30#import "GRTextEditor.h" 31 32@implementation GRText 33 34- (GRObjectEditor *)allocEditor 35{ 36 return [[GRTextEditor alloc] initEditor:self]; 37} 38 39- (id)initInView:(GRDocView *)aView 40 atPoint:(NSPoint)p 41 zoomFactor:(CGFloat)zf 42 withProperties:(NSDictionary *) properties 43 openEditor:(BOOL)openedit 44{ 45 self = [super initInView:aView zoomFactor:zf withProperties:properties]; 46 if(self) 47 { 48 int result; 49 NSString *s; 50 NSFont *f; 51 NSParagraphStyle *parStyle; 52 NSDictionary *parAttr; 53 54 pos = p; 55 selRect = NSMakeRect(pos.x - 3, pos.y - 3, 6, 6); 56 rotation = 0; 57 scalex = 1; 58 scaley = 1; 59 60 s = [properties objectForKey:@"string"]; 61 if (nil == s) 62 s = @""; 63 f = [properties objectForKey:@"font"]; 64 if (nil == f) 65 f = [NSFont systemFontOfSize:12]; 66 parStyle = [properties objectForKey:@"paragraphstyle"]; 67 if (nil == parStyle) 68 parStyle = [NSParagraphStyle defaultParagraphStyle]; 69 parAttr = [NSDictionary dictionaryWithObjectsAndKeys: 70 f, NSFontAttributeName, 71 parStyle, NSParagraphStyleAttributeName, nil]; 72 [self setString:s attributes:parAttr]; 73 74 if(openedit) 75 { 76 [(GRTextEditor *)editor setPoint: pos 77 withString: nil 78 attributes: nil]; 79 result = [(GRTextEditor *)editor runModal]; 80 if(result == NSAlertDefaultReturn) 81 { 82 [self setString: [[(GRTextEditor *)editor editorView] textString] 83 attributes: [[(GRTextEditor *)editor editorView] textAttributes]]; 84 } 85 else 86 { 87 [self release]; 88 return nil; 89 } 90 } 91 } 92 return self; 93} 94 95- (id)initFromData:(NSDictionary *)description 96 inView:(GRDocView *)aView 97 zoomFactor:(CGFloat)zf 98{ 99 self = [super initFromData:description inView:aView zoomFactor:zf]; 100 if(self) 101 { 102 NSString *s; 103 NSString *fontname; 104 CGFloat fsize; 105 NSFont *fontObj; 106 float parspace; 107 NSTextAlignment align; 108 NSMutableParagraphStyle *style; 109 NSDictionary *parAttr; 110 id obj; 111 112 s = [description objectForKey: @"string"]; 113 114 pos = NSMakePoint([[description objectForKey: @"posx"] floatValue], 115 [[description objectForKey: @"posy"] floatValue]); 116 117 fontname = [description objectForKey: @"fontname"]; 118 fsize = [[description objectForKey: @"fontsize"] floatValue]; 119 if (fsize == 0) 120 { 121 NSLog(@"font size invalid"); 122 fsize = 12.0; 123 } 124 fontObj = [NSFont fontWithName: fontname size: fsize]; 125 if (nil == fontObj) 126 { 127 NSLog(@"font %@ of size %f not found using system", fontname, fsize); 128 fontObj = [NSFont systemFontOfSize:fsize]; 129 } 130 131 align = [[description objectForKey: @"txtalign"] intValue]; 132 parspace = [[description objectForKey: @"parspace"] floatValue]; 133 style = [[NSMutableParagraphStyle alloc] init]; 134 [style setParagraphStyle:[NSParagraphStyle defaultParagraphStyle]]; 135 [style setAlignment: align]; 136 [style setParagraphSpacing: parspace]; 137 parAttr = [NSDictionary dictionaryWithObjectsAndKeys: 138 fontObj, NSFontAttributeName, 139 style, NSParagraphStyleAttributeName, nil]; 140 [self setString:s attributes:parAttr]; 141 [style release]; 142 143 144 obj = [description objectForKey: @"rotation"]; 145 if (obj) 146 rotation = [obj floatValue]; 147 148 scalex = [[description objectForKey: @"scalex"] floatValue]; 149 scaley = [[description objectForKey: @"scaley"] floatValue]; 150 } 151 return self; 152} 153 154- (id)copyWithZone:(NSZone *)zone 155{ 156 GRText *objCopy; 157 158 objCopy = [super copyWithZone:zone]; 159 160 objCopy->str = [str copy]; 161 objCopy->parAttributes = [parAttributes copy]; 162 163 objCopy->pos = NSMakePoint(pos.x, pos.y); 164 objCopy->size = NSMakeSize(size.width, size.height); 165 objCopy->bounds = NSMakeRect(bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height); 166 objCopy->rotation = rotation; 167 objCopy->scalex = scalex; 168 objCopy->scaley = scaley; 169 objCopy->selRect = NSMakeRect(selRect.origin.x, selRect.origin.y, selRect.size.width, selRect.size.height); 170 171 return objCopy; 172} 173 174 175 176- (NSDictionary *)objectDescription 177{ 178 NSMutableDictionary *dict; 179 NSString *s; 180 float strokeCol[3]; 181 float fillCol[3]; 182 float strokeAlpha; 183 float fillAlpha; 184 float parspace; 185 NSTextAlignment align; 186 NSFont *font; 187 float fsize; 188 NSParagraphStyle *pstyle; 189 190 font = [parAttributes objectForKey: NSFontAttributeName]; 191 fsize = [font pointSize]; 192 pstyle = [parAttributes objectForKey: NSParagraphStyleAttributeName]; 193 parspace = [pstyle paragraphSpacing]; 194 align = [pstyle alignment]; 195 196 197 strokeCol[0] = [strokeColor redComponent]; 198 strokeCol[1] = [strokeColor greenComponent]; 199 strokeCol[2] = [strokeColor blueComponent]; 200 strokeAlpha = [strokeColor alphaComponent]; 201 202 fillCol[0] = [fillColor redComponent]; 203 fillCol[1] = [fillColor greenComponent]; 204 fillCol[2] = [fillColor blueComponent]; 205 fillAlpha = [fillColor alphaComponent]; 206 207 dict = [NSMutableDictionary dictionaryWithCapacity: 1]; 208 [dict setObject: @"text" forKey: @"type"]; 209 210 [dict setObject: str forKey: @"string"]; 211 s = [NSString stringWithFormat: @"%.3f", pos.x]; 212 [dict setObject: s forKey: @"posx"]; 213 s = [NSString stringWithFormat: @"%.3f", pos.y]; 214 [dict setObject: s forKey: @"posy"]; 215 s = [font fontName]; 216 [dict setObject: s forKey: @"fontname"]; 217 s = [NSString stringWithFormat: @"%.3f", fsize]; 218 [dict setObject: s forKey: @"fontsize"]; 219 s = [NSString stringWithFormat: @"%.3f", parspace]; 220 [dict setObject: s forKey: @"parspace"]; 221 s = [NSString stringWithFormat: @"%i", (int)align]; 222 [dict setObject: s forKey: @"txtalign"]; 223 s = [NSString stringWithFormat: @"%.3f", scalex]; 224 [dict setObject: s forKey: @"scalex"]; 225 s = [NSString stringWithFormat: @"%.3f", scaley]; 226 [dict setObject: s forKey: @"scaley"]; 227 s = [NSString stringWithFormat: @"%.3f", rotation]; 228 [dict setObject: s forKey: @"rotation"]; 229 [dict setObject: [NSNumber numberWithBool:stroked] forKey: @"stroked"]; 230 s = [NSString stringWithFormat: @"%.3f %.3f %.3f", 231 strokeCol[0], strokeCol[1], strokeCol[2]]; 232 [dict setObject: s forKey: @"strokecolor"]; 233 s = [NSString stringWithFormat: @"%.3f", strokeAlpha]; 234 [dict setObject: s forKey: @"strokealpha"]; 235 [dict setObject: [NSNumber numberWithBool: filled] forKey: @"filled"]; 236 s = [NSString stringWithFormat: @"%.3f %.3f %.3f", 237 fillCol[0], fillCol[1], fillCol[2]]; 238 [dict setObject: s forKey: @"fillcolor"]; 239 s = [NSString stringWithFormat: @"%.3f", fillAlpha]; 240 [dict setObject: s forKey: @"fillalpha"]; 241 [dict setObject: [NSNumber numberWithBool: visible] forKey: @"visible"]; 242 [dict setObject: [NSNumber numberWithBool: locked] forKey: @"locked"]; 243 244 return dict; 245} 246 247 248- (void)dealloc 249{ 250 [str release]; 251 [parAttributes release]; 252 [super dealloc]; 253} 254 255- (void)setString:(NSString *)aString attributes:(NSDictionary *)attrs 256{ 257 ASSIGN(str, aString); 258 ASSIGN(parAttributes, attrs); 259 260 size = NSMakeSize(0, 0); 261 if (str) 262 size = [str sizeWithAttributes: attrs]; 263 bounds = NSMakeRect(pos.x, pos.y, size.width, size.height); 264} 265 266// maybe should be moved into the editor 267- (void)edit 268{ 269 int result; 270 271 [(GRTextEditor *)editor setPoint: pos 272 withString: str 273 attributes: parAttributes]; 274 result = [(GRTextEditor *)editor runModal]; 275 if(result == NSAlertDefaultReturn) 276 [self setString: [[(GRTextEditor *)editor editorView] textString] 277 attributes: [[(GRTextEditor *)editor editorView] textAttributes]]; 278} 279 280- (BOOL)objectHitForSelection:(NSPoint)p 281{ 282 if(pointInRect(bounds, p) || pointInRect(selRect, p)) 283 return YES; 284 return NO; 285} 286 287- (void)moveAddingCoordsOfPoint:(NSPoint)p 288{ 289 pos.x += p.x; 290 pos.y += p.y; 291 bounds = NSMakeRect(pos.x, pos.y, size.width, size.height); 292 selRect = NSMakeRect(pos.x - 3, pos.y - 3, 6, 6); 293} 294 295- (void)setZoomFactor:(CGFloat)f 296{ 297 zmFactor = f; 298} 299 300- (void)setScalex:(float)x scaley:(float)y 301{ 302 scalex = x; 303 scaley = y; 304} 305 306- (void)setRotation:(float)r 307{ 308 rotation = r; 309} 310 311- (void)setLocked:(BOOL)value 312{ 313 [super setLocked:value]; 314 if(!locked) 315 [editor unselect]; 316 else 317 [editor selectAsGroup]; 318} 319 320 321 322- (NSBezierPath *) makePathFromString: (NSString *) aString 323 forFont: (NSFont *) aFont 324 atPoint: (NSPoint) aPoint 325{ 326 NSTextView *textview; 327 NSGlyph *glyphs; 328 NSBezierPath *path; 329 NSRange range; 330 NSLayoutManager *layoutManager; 331 332 333 textview = [[NSTextView alloc] init]; 334 335 [textview setString: aString]; 336 [textview setFont: aFont]; 337 338 layoutManager = [textview layoutManager]; 339 340 range = [layoutManager glyphRangeForCharacterRange: 341 NSMakeRange (0, [aString length]) 342 actualCharacterRange: NULL]; 343 344 glyphs = (NSGlyph *) malloc (sizeof(NSGlyph) * (range.length * 2)); 345 [layoutManager getGlyphs: glyphs range: range]; 346 347 348 path = [NSBezierPath bezierPath]; 349 350 [path moveToPoint: aPoint]; 351 [path appendBezierPathWithGlyphs: glyphs 352 count: range.length inFont: aFont]; 353 354 free (glyphs); 355 [textview release]; 356 357 return (path); 358} 359 360- (void)draw 361{ 362 NSArray *lines; 363 float baselny; 364 NSInteger i; 365 NSBezierPath *bezp; 366 NSMutableParagraphStyle *style; 367 CGFloat parSpacing; 368 NSDictionary *strAttr; 369 NSFont *font; 370 NSFont *tempFont; 371 CGFloat fontSize; 372 NSPoint posZ; 373 NSRect boundsZ; 374 NSSize sizeZ; 375 376 if(!visible) 377 return; 378 379 posZ = pos; 380 font = [parAttributes objectForKey: NSFontAttributeName]; 381 fontSize = [font pointSize]; 382 if ([[NSGraphicsContext currentContext] isDrawingToScreen]) 383 { 384 posZ = GRpointZoom(pos, zmFactor); 385 fontSize = fontSize * zmFactor; 386 } 387 388 NSAssert (font != nil, @"Font object nil during drawing"); 389 style = [parAttributes objectForKey: NSParagraphStyleAttributeName]; 390 parSpacing = [style paragraphSpacing]; 391 392 tempFont = [NSFont fontWithName:[font fontName] size:fontSize]; 393 if (tempFont == nil) 394 { 395 NSLog(@"temp font obtained from %@ zoomFactor: %f is nil", font, zmFactor); 396 tempFont = font; 397 } 398 if (filled) 399 { 400 strAttr = [[NSDictionary dictionaryWithObjectsAndKeys: 401 tempFont, NSFontAttributeName, 402 strokeColor, NSForegroundColorAttributeName, 403 fillColor, NSBackgroundColorAttributeName, 404 style, NSParagraphStyleAttributeName, nil] retain]; 405 } 406 else 407 { 408 strAttr = [[NSDictionary dictionaryWithObjectsAndKeys: 409 tempFont, NSFontAttributeName, 410 strokeColor, NSForegroundColorAttributeName, 411 style, NSParagraphStyleAttributeName, nil] retain]; 412 } 413 baselny = posZ.y; 414 415 sizeZ = [str sizeWithAttributes: strAttr]; 416 boundsZ = NSMakeRect(posZ.x, posZ.y, sizeZ.width, sizeZ.height); 417 418 [str drawInRect:boundsZ withAttributes:strAttr]; 419 420 if ([[NSGraphicsContext currentContext] isDrawingToScreen] && [editor isSelected]) 421 { 422 NSRect selRectZ; 423 424 selRectZ = NSMakeRect(selRect.origin.x * zmFactor, selRect.origin.y * zmFactor, selRect.size.width, selRect.size.height); 425 426 bezp = [NSBezierPath bezierPath]; 427 [bezp setLineWidth:0]; 428 if([str length] > 0) 429 { 430 lines = [str componentsSeparatedByString: @"\n"]; 431 for(i = 0; i < [lines count]; i++) 432 { 433 NSString *line; 434 NSSize lineSize; 435 436 line = [lines objectAtIndex: i]; 437 lineSize = [line sizeWithAttributes:strAttr]; 438 439 [[NSColor blackColor] set]; 440 [bezp moveToPoint:NSMakePoint(posZ.x, baselny)]; 441 [bezp lineToPoint:NSMakePoint(posZ.x + bounds.size.width*zmFactor, baselny)]; 442 443 baselny += lineSize.height + parSpacing; 444 } 445 446 [bezp stroke]; 447 [[NSColor blackColor] set]; 448 NSRectFill(selRectZ); 449 } 450 } 451 [strAttr release]; 452} 453 454@end 455