1/*
2 Project: Graphos
3 GRBezierPathEditor.m
4
5 Copyright (C) 2000-2017 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#import "GRBezierPathEditor.h"
26#import "GRDocView.h"
27#import "GRFunctions.h"
28
29@implementation GRBezierPathEditor
30
31- (id)initEditor:(GRDrawableObject *)anObject
32{
33  self = [super initEditor:anObject];
34  if(self != nil)
35    {
36    }
37  return self;
38}
39
40
41
42- (NSPoint)moveControlAtPoint:(NSPoint)p
43{
44  GRBezierControlPoint *cp, *pntonpnt;
45  NSEvent *event;
46  CGFloat zFactor;
47  NSPoint pp;
48  BOOL found = NO;
49  NSUInteger i;
50
51  for(i = 0; i < [[(GRBezierPath *)object controlPoints] count]; i++)
52    {
53      cp = [[(GRBezierPath *)object controlPoints] objectAtIndex: i];
54      if(pointInRect([cp centerRect], p))
55        {
56	  [self selectForEditing];
57	  [(GRBezierPath *)object setCurrentPoint:cp];
58	  [cp select];
59	  found = YES;
60        }
61    }
62  if(!found)
63    return p;
64
65  pp = p;
66  zFactor = [object zoomFactor];
67
68  event = [[[object view] window] nextEventMatchingMask: NSLeftMouseUpMask | NSLeftMouseDraggedMask];
69
70  if([event type] == NSLeftMouseDragged)
71    {
72      [[object view] verifyModifiersOfEvent: event];
73      do
74        {
75          pp = [event locationInWindow];
76          pp = [[object view] convertPoint: pp fromView: nil];
77          pp = GRpointDeZoom(pp, zFactor);
78          if([[object view] shiftclick])
79            pp = pointApplyingCostrainerToPoint(pp, p);
80
81          pntonpnt = [(GRBezierPath *)object pointOnPoint: (GRBezierControlPoint *)[(GRBezierPath *)object currentPoint]];
82          if(pntonpnt)
83            {
84              if([(GRBezierPath *)object currentPoint] == [(GRBezierPath *)object firstPoint] || pntonpnt == [(GRBezierPath *)object firstPoint])
85                [pntonpnt moveToPoint: pp];
86            }
87          [[(GRBezierPath *)object currentPoint] moveToPoint: pp];
88          [(GRPathObject *)object remakePath];
89
90          [[object view] setNeedsDisplay: YES];
91          event = [[[object view] window] nextEventMatchingMask: NSLeftMouseUpMask | NSLeftMouseDraggedMask];
92          [[object view] verifyModifiersOfEvent: event];
93        }
94      while([event type] != NSLeftMouseUp);
95    }
96
97  return pp;
98}
99
100- (void)moveControlAtPoint:(NSPoint)oldp toPoint:(NSPoint)newp
101{
102  GRBezierControlPoint *cp, *pntonpnt;
103  BOOL found = NO;
104  NSUInteger i;
105
106  for(i = 0; i < [[(GRBezierPath *)object controlPoints] count]; i++)
107    {
108      cp = [[(GRBezierPath *)object controlPoints] objectAtIndex: i];
109      if(pointInRect([cp centerRect], oldp))
110        {
111          [self selectForEditing];
112          [(GRBezierPath *)object setCurrentPoint:cp];
113          [cp select];
114          found = YES;
115        }
116    }
117  if(!found)
118    return;
119
120  pntonpnt = [(GRBezierPath *)object pointOnPoint: (GRBezierControlPoint *)[(GRBezierPath *)object currentPoint]];
121  if(pntonpnt)
122    {
123      if([(GRBezierPath *)object currentPoint] == [(GRBezierPath *)object firstPoint] || pntonpnt == [(GRBezierPath *)object firstPoint])
124        [pntonpnt moveToPoint: newp];
125    }
126  [[(GRBezierPath *)object currentPoint] moveToPoint: newp];
127  [(GRPathObject *)object remakePath];
128  [[object view] setNeedsDisplay: YES];
129}
130
131- (NSPoint)moveBezierHandleAtPoint:(NSPoint)p
132{
133  GRBezierControlPoint *cp, *pntonpnt;
134  GRBezierHandle handle;
135  BOOL found = NO;
136  NSEvent *event;
137  NSPoint op, pp, c;
138  NSUInteger i;
139  CGFloat zFactor;
140
141  if(!editSelected)
142    return p;
143
144  pp = NSZeroPoint;
145  for(i = 0; i < [[(GRBezierPath *)object controlPoints] count]; i++)
146    {
147      cp = [[(GRBezierPath *)object controlPoints] objectAtIndex: i];
148      if([cp isActiveHandle])
149        {
150          handle = [cp bzHandle];
151          if(pointInRect(handle.firstHandleRect, p) || pointInRect(handle.secondHandleRect, p))
152            {
153              [cp select];
154              [(GRBezierPath *)object setCurrentPoint:cp];
155              found = YES;
156            }
157        }
158    }
159  if(!found)
160    return p;
161
162  zFactor = [object zoomFactor];
163  event = [[[object view] window] nextEventMatchingMask:
164                                    NSLeftMouseUpMask | NSLeftMouseDraggedMask];
165  if([event type] == NSLeftMouseDragged)
166    {
167      [[object view] verifyModifiersOfEvent: event];
168      op.x = p.x;
169      op.y = p.y;
170      do
171        {
172          pp = [event locationInWindow];
173          pp = [[object view] convertPoint: pp fromView: nil];
174          pp = GRpointDeZoom(pp, zFactor);
175          if([[object view] shiftclick])
176            {
177              c = [(GRBezierControlPoint *)[(GRBezierPath *)object currentPoint] center];
178              pp = pointApplyingCostrainerToPoint(pp, c);
179            }
180
181          pntonpnt = [(GRBezierPath *)object pointOnPoint: (GRBezierControlPoint *)[(GRBezierPath *)object currentPoint]];
182          if(pntonpnt)
183            {
184              if([(GRBezierPath *)object currentPoint] == [(GRBezierPath *)object firstPoint] || pntonpnt == [(GRBezierPath *)object firstPoint])
185                [pntonpnt moveBezierHandleToPosition: pp oldPosition: op];
186            }
187          [(GRBezierControlPoint *)[(GRBezierPath *)object currentPoint] moveBezierHandleToPosition: pp oldPosition: op];
188          [(GRPathObject *)object remakePath];
189
190          op.x = pp.x;
191          op.y = pp.y;
192          [[object view] setNeedsDisplay: YES];
193          event = [[[object view] window] nextEventMatchingMask: NSLeftMouseUpMask | NSLeftMouseDraggedMask];
194          [[object view] verifyModifiersOfEvent: event];
195        }
196      while([event type] != NSLeftMouseUp);
197    }
198
199  return pp;
200}
201
202- (void)moveBezierHandleAtPoint:(NSPoint)oldp toPoint:(NSPoint)newp
203{
204  GRBezierControlPoint *cp, *pntonpnt;
205  GRBezierHandle handle;
206  BOOL found = NO;
207  NSUInteger i;
208
209  for(i = 0; i < [[(GRBezierPath *)object controlPoints] count]; i++)
210    {
211      cp = [[(GRBezierPath *)object controlPoints] objectAtIndex: i];
212      if([cp isActiveHandle])
213        {
214          handle = [cp bzHandle];
215          if(pointInRect(handle.firstHandleRect, oldp)
216             || pointInRect(handle.secondHandleRect, oldp))
217            {
218              [cp select];
219              [(GRBezierPath *)object setCurrentPoint:cp];
220              found = YES;
221            }
222        }
223    }
224  if(!found)
225    return;
226
227  pntonpnt = [(GRBezierPath *)object pointOnPoint: (GRBezierControlPoint *)[(GRBezierPath *)object currentPoint]];
228  if(pntonpnt)
229    {
230      if([(GRBezierPath *)object currentPoint] == [(GRBezierPath *)object firstPoint] || pntonpnt == [(GRBezierPath *)object firstPoint])
231        [pntonpnt moveBezierHandleToPosition: newp oldPosition: oldp];
232    }
233  [(GRBezierControlPoint *)[(GRBezierPath *)object currentPoint] moveBezierHandleToPosition: newp oldPosition: oldp];
234  [(GRPathObject *)object remakePath];
235  [[object view] setNeedsDisplay: YES];
236}
237
238
239
240- (void)selectAsGroup
241{
242  [super selectAsGroup];
243}
244
245- (void)selectForEditing
246{
247  [super selectForEditing];
248}
249
250
251- (NSArray *)selectedControlPoints
252{
253  NSUInteger i;
254  NSMutableArray *points;
255
256  points = [[NSMutableArray alloc] initWithCapacity:1];
257  for(i = 0; i < [[(GRBezierPath *)object controlPoints] count]; i++)
258    {
259      GRBezierControlPoint *cp;
260      cp = [[(GRBezierPath *)object controlPoints] objectAtIndex: i];
261
262      if ([cp isSelect])
263        [points addObject:cp];
264    }
265  return [points autorelease];
266}
267
268- (void)unselect
269{
270  NSUInteger i;
271
272  [super unselect];
273  for(i = 0; i < [[(GRBezierPath *)object controlPoints] count]; i++)
274    [[[(GRBezierPath *)object controlPoints] objectAtIndex: i] unselect];
275}
276
277
278- (void)unselectOtherControls:(GRBezierControlPoint *)cp
279{
280  GRBezierControlPoint *ctrlp;
281  NSUInteger i;
282
283  [(GRBezierPath *)object setCurrentPoint:cp];
284  for(i = 0; i < [[(GRBezierPath *)object controlPoints] count]; i++)
285    {
286      ctrlp = [[(GRBezierPath *)object controlPoints] objectAtIndex: i];
287      if(ctrlp != cp)
288        [ctrlp unselect];
289    }
290}
291
292
293- (void)draw
294{
295  GRBezierControlPoint *cp;
296  NSUInteger i;
297
298  if(![[(GRBezierPath *)object controlPoints] count] || ![object visible])
299    return;
300
301  if(groupSelected)
302    {
303      for(i = 0; i < [[(GRBezierPath *)object controlPoints] count]; i++)
304        {
305          cp = [[(GRBezierPath *)object controlPoints] objectAtIndex: i];
306          [cp drawControlAsSelected:YES];
307        }
308    }
309
310  if(editSelected)
311    {
312      for(i = 0; i < [[(GRBezierPath *)object controlPoints] count]; i++)
313        {
314          cp = [[(GRBezierPath *)object controlPoints] objectAtIndex: i];
315          [cp drawControl];
316        }
317    }
318}
319
320@end
321
322
323
324