1/*
2    This file is part of HelpViewer (http://www.roard.com/helpviewer)
3    Copyright (C) 2003 Nicolas Roard (nicolas@roard.com)
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18*/
19
20#include "FigureCell.h"
21
22@implementation FigureCell
23
24- (id) initWithSize: (NSSize) size
25{
26    [super init];
27    _size = size;
28    _image = nil;
29    _legends = nil;
30    return self;
31}
32
33- (void) setLegends: (NSArray*) legends
34{
35    ASSIGN (_legends, legends);
36}
37
38- (void) setImage:  (NSImage*) img
39{
40    ASSIGN (_image, img);
41}
42
43- (NSSize) cellSize
44{
45    return _size;
46}
47
48- (void) resize: (id) sender
49{
50	[self resizeWithTextView: [sender object]];
51}
52
53- (void) resizeWithTextView: (NSTextView*) textView
54{
55    float minimalHeight;
56    float imageWidth = [_image size].width;
57    float imageHeight = [_image size].height;
58
59    if (_legends)
60    {
61	      int i;
62	      float interspace = 20;
63	      float spaceMargin = 20;
64	      float border = 12;
65	      float Margin = ([textView bounds].size.width - imageWidth - 2*spaceMargin - 2*border)/2;
66
67	      NSMutableParagraphStyle* paragraph = [NSMutableParagraphStyle new];
68	      [paragraph setAlignment: NSLeftTextAlignment];
69	      [paragraph setTailIndent: Margin];
70	      [paragraph setHeadIndent: 0.0];
71	      [paragraph setFirstLineHeadIndent: 0.0];
72
73	      NSDictionary* attributes = [NSDictionary dictionaryWithObject: paragraph
74		    forKey: NSParagraphStyleAttributeName];
75
76	      NSMutableArray* preLeftLegends = [NSMutableArray array];
77	      NSMutableArray* preRightLegends = [NSMutableArray array];
78
79	      for (i=0; i<[_legends count]; i++)
80	      {
81		  Legend* current = [_legends objectAtIndex: i];
82		  [[current legend] addAttributes: attributes
83			range: NSMakeRange (0, [[current legend] length])];
84		  NSSize s = [[current legend] size];
85
86		  [current setHeight: s.height];
87		  if ([current point].x > (imageWidth/2))
88		  {
89		    [current setRightPos]; // on range � droite
90		    [preRightLegends addObject: current];
91		  }
92		  else
93		  {
94		    [preLeftLegends addObject: current];
95		  }
96	      }
97
98	      NSArray* LeftLegends = [preLeftLegends sortedArrayUsingSelector: @selector (compareLegends:)];
99	      NSArray* RightLegends = [preRightLegends sortedArrayUsingSelector: @selector (compareLegends:)];
100
101	      float LeftLegendsHeight = 0;
102	      float RightLegendsHeight = 0;
103
104	      for (i=0; i < [LeftLegends count]; i++)
105	      {
106		    LeftLegendsHeight += [[LeftLegends objectAtIndex: i] height];
107	      }
108
109	      for (i=0; i < [RightLegends count]; i++)
110	      {
111		    RightLegendsHeight += [[RightLegends objectAtIndex: i] height];
112	      }
113
114	      float minimalInterspace = 8;
115
116	      minimalHeight = LeftLegendsHeight+([LeftLegends count]+1)*minimalInterspace;
117
118	      if (imageHeight < minimalHeight) imageHeight = minimalHeight;
119    }
120
121    _size = NSMakeSize ([textView bounds].size.width, imageHeight);
122}
123
124- (void) drawLegends: (NSArray*) legends onRight: (BOOL) right
125    withInterspace: (float) interspace withAttributes: (NSDictionary*) attributes
126    withFrame: (NSRect) cellFrame withBorder: (float) border withMargin: (float) Margin
127    withSpaceMargin: (float) spaceMargin withImageWidth: (float) imageWidth withPosImage: (float) posImage
128{
129      float posY = interspace;
130      int i;
131      for (i=0; i < [legends count]; i++)
132      {
133	  NSRect r;
134          NSPoint t, tp, p;
135          Legend* current = [legends objectAtIndex: i];
136          [[current legend] addAttributes: attributes
137                range: NSMakeRange (0, [[current legend] length])];
138          NSSize s = [[current legend] size];
139//	  NSSize s = [[current legend] sizeWithAttributes: attributes];
140
141          if (!right)
142          {
143            r  = NSMakeRect (cellFrame.origin.x + border + (Margin-s.width) - 2, cellFrame.origin.y + posY - 2, s.width + 4, s.height + 4);
144            t  = NSMakePoint (cellFrame.origin.x + border + (Margin-s.width), cellFrame.origin.y + posY);
145            tp = NSMakePoint (cellFrame.origin.x + border + Margin + 2, cellFrame.origin.y + posY + s.height/2);
146          }
147          else
148          {
149            r  = NSMakeRect (cellFrame.origin.x + border + Margin + (2*spaceMargin) + imageWidth - 2,
150                    cellFrame.origin.y + posY - 2, s.width + 4, s.height + 4);
151            t  = NSMakePoint (cellFrame.origin.x + border + Margin + (2*spaceMargin) + imageWidth,
152                    cellFrame.origin.y + posY);
153            tp = NSMakePoint (cellFrame.origin.x + border + Margin + (2*spaceMargin) + imageWidth - 2,
154                    cellFrame.origin.y + posY + s.height/2);
155          }
156
157          p  = NSMakePoint (cellFrame.origin.x + border + Margin + spaceMargin + [current point].x,
158		  cellFrame.origin.y + [current point].y + posImage);
159
160         // [[NSBezierPath bezierPathWithRect: r] stroke];
161	[[NSColor colorWithCalibratedRed: 0.81 green: 0.84 blue: 0.88 alpha:1.0] set];
162	NSBezierPath* path = [[NSBezierPath alloc] init];
163
164	float radius = 8;
165
166	NSPoint p1 = NSMakePoint (r.origin.x, r.origin.y + radius);
167	NSPoint p2 = NSMakePoint (r.origin.x, r.origin.y + r.size.height - radius);
168	NSPoint p3 = NSMakePoint (r.origin.x + radius, r.origin.y + r.size.height);
169	NSPoint p4 = NSMakePoint (r.origin.x + r.size.width - radius, r.origin.y + r.size.height);
170	NSPoint p5 = NSMakePoint (r.origin.x + r.size.width, r.origin.y + r.size.height - radius);
171	NSPoint p6 = NSMakePoint (r.origin.x + r.size.width, r.origin.y + radius);
172	NSPoint p7 = NSMakePoint (r.origin.x + r.size.width - radius, r.origin.y);
173	NSPoint p8 = NSMakePoint (r.origin.x + radius, r.origin.y);
174
175	NSPoint pr1 = NSMakePoint (r.origin.x + radius, r.origin.y + r.size.height - radius);
176	NSPoint pr2 = NSMakePoint (r.origin.x + r.size.width - radius, r.origin.y + r.size.height - radius);
177	NSPoint pr3 = NSMakePoint (r.origin.x + r.size.width - radius, r.origin.y + radius);
178	NSPoint pr4 = NSMakePoint (r.origin.x + radius, r.origin.y + radius);
179
180	[path moveToPoint: p1];
181	[path lineToPoint: p2];
182	//[path appendBezierPathWithArcFromPoint: p2 toPoint: p3 radius: radius];
183	[path appendBezierPathWithArcWithCenter: pr1 radius: radius startAngle: 180 endAngle: 90 clockwise: YES];
184	//[path moveToPoint: p3];
185	[path lineToPoint: p4];
186	//[path appendBezierPathWithArcFromPoint: p4 toPoint: p5 radius: radius];
187	[path appendBezierPathWithArcWithCenter: pr2 radius: radius startAngle: 90 endAngle: 0 clockwise: YES];
188	//[path moveToPoint: p5];
189	[path lineToPoint: p6];
190	//[path appendBezierPathWithArcFromPoint: p6 toPoint: p7 radius: radius];
191	[path appendBezierPathWithArcWithCenter: pr3 radius: radius startAngle: 0 endAngle: 270 clockwise: YES];
192	//[path moveToPoint: p7];
193	[path lineToPoint: p8];
194	//[path appendBezierPathWithArcFromPoint: p8 toPoint: p1 radius: radius];
195	[path appendBezierPathWithArcWithCenter: pr4 radius: radius startAngle: 270 endAngle: 180 clockwise: YES];
196	[path fill];
197//          [[current legend] drawAtPoint: t withAttributes: attributes];
198          [[current legend] drawAtPoint: t];
199	  NSBezierPath* path2 = [NSBezierPath bezierPath];
200
201          [path2 moveToPoint: tp];
202	  [path2 lineToPoint: p];
203	  [path2 stroke];
204
205          posY += s.height + interspace;
206      }
207}
208
209
210- (void) drawWithFrame: (NSRect) cellFrame
211    inView: (NSView*) controlView
212{
213      if (![controlView window]) return;
214
215      [controlView lockFocus];
216
217	[[NSColor whiteColor] set];
218	NSRectFill (cellFrame);
219
220      //NSLog (@"drawInteriorWithFrame de FigureCell ... ");
221      //NSLog (@"image : %@", _image);
222      //NSLog (@"cellframe origin x : %.2f origin y : %.2f", cellFrame.origin.x, cellFrame.origin.y);
223      NSLog (@"cellFrame height : %.2f", cellFrame.size.height);
224
225	if (_legends)
226	{
227
228	      int i;
229	      float interspace = 20;
230	      float imageWidth = [_image size].width;
231	      float imageHeight = [_image size].height;
232	      float spaceMargin = 20;
233	      float border = 12;
234	      float Margin = (cellFrame.size.width - imageWidth - 2*spaceMargin - 2*border)/2;
235
236	      float posImage = 0;
237	      if (imageHeight < cellFrame.size.height)
238	      {
239	      	posImage = (cellFrame.size.height - imageHeight)/2;
240	      }
241	      NSPoint imageOrigin = NSMakePoint (cellFrame.origin.x + border + Margin + spaceMargin,
242		      cellFrame.origin.y + imageHeight + posImage);
243	      [_image compositeToPoint: imageOrigin operation: NSCompositeSourceAtop];
244
245	      NSMutableParagraphStyle* paragraph = [NSMutableParagraphStyle new];
246	      [paragraph setAlignment: NSLeftTextAlignment];
247	      [paragraph setTailIndent: Margin];
248	      [paragraph setHeadIndent: 0.0];
249	      [paragraph setFirstLineHeadIndent: 0.0];
250
251	      NSDictionary* attributes = [NSDictionary dictionaryWithObject: paragraph
252		    forKey: NSParagraphStyleAttributeName];
253
254	      NSMutableArray* preLeftLegends = [NSMutableArray array];
255	      NSMutableArray* preRightLegends = [NSMutableArray array];
256
257	      for (i=0; i<[_legends count]; i++)
258	      {
259		  Legend* current = [_legends objectAtIndex: i];
260		  [[current legend] addAttributes: attributes
261			range: NSMakeRange (0, [[current legend] length])];
262		  NSSize s = [[current legend] size];
263
264		  [current setHeight: s.height];
265		  if ([current point].x > (imageWidth/2))
266		  {
267		    [current setRightPos]; // on range � droite
268		    [preRightLegends addObject: current];
269		  }
270		  else
271		  {
272		    [preLeftLegends addObject: current];
273		  }
274	      }
275
276	      NSArray* LeftLegends = [preLeftLegends sortedArrayUsingSelector: @selector (compareLegends:)];
277	      NSArray* RightLegends = [preRightLegends sortedArrayUsingSelector: @selector (compareLegends:)];
278
279	      //NSLog (@"preLL : %d LL : %d", [preLeftLegends count], [LeftLegends count]);
280	      //NSLog (@"preRL : %d RL : %d", [preRightLegends count], [RightLegends count]);
281
282	      float LeftLegendsHeight = 0;
283	      float RightLegendsHeight = 0;
284
285	      for (i=0; i < [LeftLegends count]; i++)
286	      {
287		    LeftLegendsHeight += [[LeftLegends objectAtIndex: i] height];
288	      }
289
290	      for (i=0; i < [RightLegends count]; i++)
291	      {
292		    RightLegendsHeight += [[RightLegends objectAtIndex: i] height];
293	      }
294
295	      interspace = (cellFrame.size.height - LeftLegendsHeight)/ ([LeftLegends count]+1);
296
297	      [self drawLegends: LeftLegends onRight: NO withInterspace: interspace
298		    withAttributes: attributes withFrame: cellFrame withBorder: border
299		    withMargin: Margin withSpaceMargin: spaceMargin withImageWidth: imageWidth
300		    withPosImage: posImage];
301
302	      interspace = (cellFrame.size.height - RightLegendsHeight)/ ([RightLegends count]+1);
303	      [self drawLegends: RightLegends onRight: YES withInterspace: interspace
304		    withAttributes: attributes withFrame: cellFrame withBorder: border
305		    withMargin: Margin withSpaceMargin: spaceMargin withImageWidth: imageWidth
306		    withPosImage: posImage];
307
308	}
309      [controlView unlockFocus];
310}
311
312@end
313