1/*
2 Project: Graphos
3 GRBox.m
4
5 Copyright (C) 2007-2018 GNUstep Application Project
6
7 Author: Ing. Riccardo Mottola
8
9 Created: 2007-09-21
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 "GRBox.h"
30#import "GRBoxEditor.h"
31#import "GRFunctions.h"
32
33
34@implementation GRBox
35
36- (GRObjectEditor *)allocEditor
37{
38  return [[GRBoxEditor alloc] initEditor:self];
39}
40
41
42/** initializes by using the properties array as defaults */
43- (id)initInView:(GRDocView *)aView
44      zoomFactor:(CGFloat)zf
45      withProperties:(NSDictionary *)properties
46{
47  self = [super initInView:aView zoomFactor:zf withProperties:properties];
48  if(self)
49    {
50      id obj;
51
52      pos = NSMakePoint([[properties objectForKey: @"posx"]  floatValue],
53			[[properties objectForKey: @"posy"]  floatValue]);
54      size = NSMakeSize([[properties objectForKey: @"width"]  floatValue],
55			[[properties objectForKey: @"height"]  floatValue]);
56      bounds = GRMakeBounds(pos.x, pos.y, size.width, size.height);
57
58      rotation = 0;
59      obj = [properties objectForKey: @"rotation"];
60      if (obj)
61	rotation = [obj floatValue];
62
63      startControlPoint = [[GRObjectControlPoint alloc] initAtPoint: pos zoomFactor:zf];
64      endControlPoint = [[GRObjectControlPoint alloc] initAtPoint: NSMakePoint(pos.x + size.width, pos.y + size.height) zoomFactor:zf];
65      [self setZoomFactor: zf];
66    }
67
68  return self;
69}
70
71/** initializes all parameters from a description dictionary */
72- (id)initFromData:(NSDictionary *)description
73            inView:(GRDocView *)aView
74        zoomFactor:(CGFloat)zf
75{
76  self = [super initFromData:description inView:aView zoomFactor:zf];
77  if(self)
78    {
79      id obj;
80
81
82      pos = NSMakePoint([[description objectForKey: @"posx"]  floatValue],
83			[[description objectForKey: @"posy"]  floatValue]);
84      size = NSMakeSize([[description objectForKey: @"width"]  floatValue],
85			[[description objectForKey: @"height"]  floatValue]);
86      bounds = GRMakeBounds(pos.x, pos.y, size.width, size.height);
87
88      rotation = 0;
89      obj = [description objectForKey: @"rotation"];
90      if (obj)
91	rotation = [obj floatValue];
92
93      startControlPoint = [[GRObjectControlPoint alloc] initAtPoint: pos zoomFactor:zf];
94      endControlPoint = [[GRObjectControlPoint alloc] initAtPoint: NSMakePoint(pos.x + size.width, pos.y + size.height) zoomFactor:zf];
95      [self setZoomFactor: zf];
96    }
97  return self;
98}
99
100- (id)copyWithZone:(NSZone *)zone
101{
102    GRBox *objCopy;
103
104    objCopy = [super copyWithZone:zone];
105
106    objCopy->startControlPoint = [[GRObjectControlPoint alloc] initAtPoint: pos zoomFactor:zmFactor];
107    objCopy->endControlPoint = [[GRObjectControlPoint alloc] initAtPoint: NSMakePoint(pos.x + size.width, pos.y + size.height) zoomFactor:zmFactor];
108    objCopy->pos = NSMakePoint(pos.x, pos.y);
109    objCopy->size = NSMakeSize(size.width, size.height);
110    objCopy->bounds = NSMakeRect(bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height);
111    objCopy->boundsZ = NSMakeRect(boundsZ.origin.x, boundsZ.origin.y, boundsZ.size.width, boundsZ.size.height);
112    objCopy->rotation = rotation;
113
114    return objCopy;
115}
116
117- (void)dealloc
118{
119    [startControlPoint release];
120    [endControlPoint release];
121    [super dealloc];
122}
123
124- (NSDictionary *)objectDescription
125{
126    NSMutableDictionary *dict;
127    NSString *str;
128    float strokeCol[3];
129    float fillCol[3];
130    float strokeAlpha;
131    float fillAlpha;
132
133    strokeCol[0] = [strokeColor redComponent];
134    strokeCol[1] = [strokeColor greenComponent];
135    strokeCol[2] = [strokeColor blueComponent];
136    strokeAlpha = [strokeColor alphaComponent];
137
138    fillCol[0] = [fillColor redComponent];
139    fillCol[1] = [fillColor greenComponent];
140    fillCol[2] = [fillColor blueComponent];
141    fillAlpha = [fillColor alphaComponent];
142
143    dict = [NSMutableDictionary dictionaryWithCapacity: 1];
144    [dict setObject: @"box" forKey: @"type"];
145
146    str = [NSString stringWithFormat: @"%.3f", pos.x];
147    [dict setObject: str forKey: @"posx"];
148    str = [NSString stringWithFormat: @"%.3f", pos.y];
149    [dict setObject: str forKey: @"posy"];
150
151    str = [NSString stringWithFormat: @"%.3f", size.width];
152    [dict setObject: str forKey: @"width"];
153    str = [NSString stringWithFormat: @"%.3f", size.height];
154    [dict setObject: str forKey: @"height"];
155
156    str = [NSString stringWithFormat: @"%.3f", flatness];
157    [dict setObject: str forKey: @"flatness"];
158    str = [NSString stringWithFormat: @"%u", (unsigned)linejoin];
159    [dict setObject: str forKey: @"linejoin"];
160    str = [NSString stringWithFormat: @"%u", (unsigned)linecap];
161    [dict setObject: str forKey: @"linecap"];
162    str = [NSString stringWithFormat: @"%.3f", miterlimit];
163    [dict setObject: str forKey: @"miterlimit"];
164    str = [NSString stringWithFormat: @"%.3f", linewidth];
165    [dict setObject: str forKey: @"linewidth"];
166    [dict setObject:[NSNumber numberWithBool:stroked]  forKey: @"stroked"];
167    str = [NSString stringWithFormat: @"%.3f %.3f %.3f",
168        strokeCol[0], strokeCol[1], strokeCol[2]];
169    [dict setObject: str forKey: @"strokecolor"];
170    str = [NSString stringWithFormat: @"%.3f", strokeAlpha];
171    [dict setObject: str forKey: @"strokealpha"];
172    [dict setObject:[NSNumber numberWithBool:filled] forKey: @"filled"];
173    str = [NSString stringWithFormat: @"%.3f %.3f %.3f",
174        fillCol[0], fillCol[1], fillCol[2]];
175    [dict setObject: str forKey: @"fillcolor"];
176    str = [NSString stringWithFormat: @"%.3f", fillAlpha];
177    [dict setObject: str forKey: @"fillalpha"];
178    [dict setObject:[NSNumber numberWithBool:visible] forKey: @"visible"];
179    [dict setObject:[NSNumber numberWithBool:locked] forKey: @"locked"];
180
181    return dict;
182}
183
184- (void)setStartAtPoint:(NSPoint)aPoint
185{
186    pos = aPoint;
187    [startControlPoint moveToPoint: aPoint];
188    [startControlPoint select];
189}
190
191- (void)setEndAtPoint:(NSPoint)aPoint
192{
193  size.width = aPoint.x - pos.x;
194  size.height = aPoint.y- pos.y;
195  bounds = GRMakeBounds(pos.x, pos.y, size.width, size.height);
196
197  [endControlPoint moveToPoint: aPoint];
198  [endControlPoint select];
199
200  boundsZ = GRMakeBounds(pos.x * zmFactor, pos.y * zmFactor, size.width * zmFactor, size.height * zmFactor);
201}
202
203- (void)remakePath
204{
205  [self setStartAtPoint:[startControlPoint center]];
206  [self setEndAtPoint:[endControlPoint center]];
207  [(GRBoxEditor *)editor setIsDone:YES];
208}
209
210
211
212- (void)setLocked:(BOOL)value
213{
214    [super setLocked:value];
215    if(!locked)
216        [(GRBoxEditor *)editor unselect];
217    else
218        [(GRBoxEditor *)editor selectAsGroup];
219}
220
221- (BOOL)objectHitForSelection:(NSPoint)p
222{
223  return (pointInRect(bounds, p));
224}
225
226- (BOOL)onControlPoint:(NSPoint)p
227{
228    if (pointInRect([startControlPoint centerRect], p))
229        return YES;
230    if (pointInRect([endControlPoint centerRect], p))
231        return YES;
232    return NO;
233}
234
235- (GRObjectControlPoint *) startControlPoint
236{
237    return startControlPoint;
238}
239
240- (GRObjectControlPoint *) endControlPoint
241{
242    return endControlPoint;
243}
244
245- (NSPoint) position
246{
247  return pos;
248}
249
250- (void)moveAddingCoordsOfPoint:(NSPoint)p
251{
252  pos.x += p.x;
253  pos.y += p.y;
254  bounds = GRMakeBounds(pos.x, pos.y, size.width, size.height);
255  [startControlPoint moveToPoint: pos];
256  [endControlPoint moveToPoint: NSMakePoint(pos.x + size.width, pos.y + size.height)];
257
258  boundsZ = GRMakeBounds(pos.x * zmFactor, pos.y * zmFactor, size.width * zmFactor, size.height * zmFactor);
259}
260
261- (void)setZoomFactor:(CGFloat)f
262{
263  [super setZoomFactor:f];
264
265  [startControlPoint setZoomFactor:f];
266  [endControlPoint setZoomFactor:f];
267  [self remakePath];
268}
269
270/** draws the object and calls the editor to draw itself afterwards */
271- (void)draw
272{
273  NSBezierPath *bzp;
274  CGFloat linew;
275  NSRect drawBounds;
276
277  drawBounds = bounds;
278  linew = linewidth;
279  if ([[NSGraphicsContext currentContext] isDrawingToScreen])
280    {
281      drawBounds = boundsZ;
282      linew = linewidth * zmFactor;
283    }
284
285  bzp = [NSBezierPath bezierPath];
286  [bzp appendBezierPathWithRect:drawBounds];
287  if(filled)
288    {
289      [NSGraphicsContext saveGraphicsState];
290      [fillColor set];
291      [bzp fill];
292      [NSGraphicsContext restoreGraphicsState];
293    }
294  if(stroked)
295    {
296      [NSGraphicsContext saveGraphicsState];
297      [bzp setLineJoinStyle:linejoin];
298      [bzp setLineCapStyle:linecap];
299      [bzp setLineWidth:linew];
300      [strokeColor set];
301      [bzp stroke];
302      [NSGraphicsContext restoreGraphicsState];
303    }
304
305  if ([[NSGraphicsContext currentContext] isDrawingToScreen])
306    [editor draw];
307}
308
309
310@end
311