]> git.saurik.com Git - wxWidgets.git/blame - utils/ogl/src/basic2.cpp
wxPenRefData copy ctor was somehow not declared in the class definition
[wxWidgets.git] / utils / ogl / src / basic2.cpp
CommitLineData
0fc1a713
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: basic2.cpp
3// Purpose: Basic OGL classes (2)
4// Author: Julian Smart
5// Modified by:
6// Created: 12/07/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#endif
14
15// For compilers that support precompilation, includes "wx.h".
16#include <wx/wxprec.h>
17
18#ifdef __BORLANDC__
19#pragma hdrstop
20#endif
21
22#ifndef WX_PRECOMP
23#include <wx/wx.h>
24#endif
25
26#ifdef PROLOGIO
27#include <wx/wxexpr.h>
28#endif
29
30#if USE_IOSTREAMH
31#include <iostream.h>
32#else
33#include <iostream>
34#endif
35
36#include <stdio.h>
37#include <ctype.h>
38#include <math.h>
39
40#include "basic.h"
41#include "basicp.h"
42#include "composit.h"
43#include "lines.h"
44#include "canvas.h"
45#include "divided.h"
46#include "misc.h"
47
48// Control point types
49// Rectangle and most other shapes
50#define CONTROL_POINT_VERTICAL 1
51#define CONTROL_POINT_HORIZONTAL 2
52#define CONTROL_POINT_DIAGONAL 3
53
54// Line
55#define CONTROL_POINT_ENDPOINT_TO 4
56#define CONTROL_POINT_ENDPOINT_FROM 5
57#define CONTROL_POINT_LINE 6
58
59// Two stage construction: need to call Create
60IMPLEMENT_DYNAMIC_CLASS(wxPolygonShape, wxShape)
61
62wxPolygonShape::wxPolygonShape()
63{
64 m_points = NULL;
65 m_originalPoints = NULL;
66}
67
68void wxPolygonShape::Create(wxList *the_points)
69{
5de76427
JS
70 ClearPoints();
71
0fc1a713
JS
72 m_originalPoints = the_points;
73
74 // Duplicate the list of points
75 m_points = new wxList;
76
77 wxNode *node = the_points->First();
78 while (node)
79 {
80 wxRealPoint *point = (wxRealPoint *)node->Data();
81 wxRealPoint *new_point = new wxRealPoint(point->x, point->y);
82 m_points->Append((wxObject*) new_point);
83 node = node->Next();
84 }
85 CalculateBoundingBox();
86 m_originalWidth = m_boundWidth;
87 m_originalHeight = m_boundHeight;
88 SetDefaultRegionSize();
89}
90
91wxPolygonShape::~wxPolygonShape()
5de76427
JS
92{
93 ClearPoints();
94}
95
96void wxPolygonShape::ClearPoints()
0fc1a713
JS
97{
98 if (m_points)
99 {
100 wxNode *node = m_points->First();
101 while (node)
102 {
103 wxRealPoint *point = (wxRealPoint *)node->Data();
104 delete point;
105 delete node;
106 node = m_points->First();
107 }
108 delete m_points;
5de76427 109 m_points = NULL;
0fc1a713
JS
110 }
111 if (m_originalPoints)
112 {
113 wxNode *node = m_originalPoints->First();
114 while (node)
115 {
116 wxRealPoint *point = (wxRealPoint *)node->Data();
117 delete point;
118 delete node;
119 node = m_originalPoints->First();
120 }
121 delete m_originalPoints;
5de76427 122 m_originalPoints = NULL;
0fc1a713
JS
123 }
124}
125
126
127// Width and height. Centre of object is centre of box.
42cfaf8c 128void wxPolygonShape::GetBoundingBoxMin(double *width, double *height)
0fc1a713
JS
129{
130 *width = m_boundWidth;
131 *height = m_boundHeight;
132}
133
134void wxPolygonShape::CalculateBoundingBox()
135{
136 // Calculate bounding box at construction (and presumably resize) time
42cfaf8c
JS
137 double left = 10000;
138 double right = -10000;
139 double top = 10000;
140 double bottom = -10000;
0fc1a713
JS
141
142 wxNode *node = m_points->First();
143 while (node)
144 {
145 wxRealPoint *point = (wxRealPoint *)node->Data();
146 if (point->x < left) left = point->x;
147 if (point->x > right) right = point->x;
148
149 if (point->y < top) top = point->y;
150 if (point->y > bottom) bottom = point->y;
151
152 node = node->Next();
153 }
154 m_boundWidth = right - left;
155 m_boundHeight = bottom - top;
156}
157
158// Recalculates the centre of the polygon, and
159// readjusts the point offsets accordingly.
160// Necessary since the centre of the polygon
161// is expected to be the real centre of the bounding
162// box.
163void wxPolygonShape::CalculatePolygonCentre()
164{
42cfaf8c
JS
165 double left = 10000;
166 double right = -10000;
167 double top = 10000;
168 double bottom = -10000;
0fc1a713
JS
169
170 wxNode *node = m_points->First();
171 while (node)
172 {
173 wxRealPoint *point = (wxRealPoint *)node->Data();
174 if (point->x < left) left = point->x;
175 if (point->x > right) right = point->x;
176
177 if (point->y < top) top = point->y;
178 if (point->y > bottom) bottom = point->y;
179
180 node = node->Next();
181 }
42cfaf8c
JS
182 double bwidth = right - left;
183 double bheight = bottom - top;
184
185 double newCentreX = (double)(left + (bwidth/2.0));
186 double newCentreY = (double)(top + (bheight/2.0));
0fc1a713
JS
187
188 node = m_points->First();
189 while (node)
190 {
191 wxRealPoint *point = (wxRealPoint *)node->Data();
192 point->x -= newCentreX;
193 point->y -= newCentreY;
194 node = node->Next();
195 }
196 m_xpos += newCentreX;
197 m_ypos += newCentreY;
198}
199
42cfaf8c
JS
200bool PolylineHitTest(double n, double xvec[], double yvec[],
201 double x1, double y1, double x2, double y2)
0fc1a713
JS
202{
203 bool isAHit = FALSE;
204 int i;
42cfaf8c
JS
205 double lastx = xvec[0];
206 double lasty = yvec[0];
0fc1a713 207
42cfaf8c
JS
208 double min_ratio = 1.0;
209 double line_ratio;
210 double other_ratio;
0fc1a713
JS
211
212// char buf[300];
213 for (i = 1; i < n; i++)
214 {
42cfaf8c 215 oglCheckLineIntersection(x1, y1, x2, y2, lastx, lasty, xvec[i], yvec[i],
0fc1a713
JS
216 &line_ratio, &other_ratio);
217 if (line_ratio != 1.0)
218 isAHit = TRUE;
219// sprintf(buf, "Line ratio = %.2f, other ratio = %.2f\n", line_ratio, other_ratio);
220// ClipsErrorFunction(buf);
221 lastx = xvec[i];
222 lasty = yvec[i];
223
224 if (line_ratio < min_ratio)
225 min_ratio = line_ratio;
226 }
227
42cfaf8c 228 // Do last (implicit) line if last and first doubles are not identical
0fc1a713
JS
229 if (!(xvec[0] == lastx && yvec[0] == lasty))
230 {
42cfaf8c 231 oglCheckLineIntersection(x1, y1, x2, y2, lastx, lasty, xvec[0], yvec[0],
0fc1a713
JS
232 &line_ratio, &other_ratio);
233 if (line_ratio != 1.0)
234 isAHit = TRUE;
235// sprintf(buf, "Line ratio = %.2f, other ratio = %.2f\n", line_ratio, other_ratio);
236// ClipsErrorFunction(buf);
237
238 if (line_ratio < min_ratio)
239 min_ratio = line_ratio;
240 }
241// ClipsErrorFunction("\n");
242 return isAHit;
243}
244
42cfaf8c 245bool wxPolygonShape::HitTest(double x, double y, int *attachment, double *distance)
0fc1a713
JS
246{
247 // Imagine four lines radiating from this point. If all of these lines hit the polygon,
248 // we're inside it, otherwise we're not. Obviously we'd need more radiating lines
249 // to be sure of correct results for very strange (concave) shapes.
42cfaf8c
JS
250 double endPointsX[4];
251 double endPointsY[4];
0fc1a713
JS
252 // North
253 endPointsX[0] = x;
42cfaf8c 254 endPointsY[0] = (double)(y - 1000.0);
0fc1a713 255 // East
42cfaf8c 256 endPointsX[1] = (double)(x + 1000.0);
0fc1a713
JS
257 endPointsY[1] = y;
258 // South
259 endPointsX[2] = x;
42cfaf8c 260 endPointsY[2] = (double)(y + 1000.0);
0fc1a713 261 // West
42cfaf8c 262 endPointsX[3] = (double)(x - 1000.0);
0fc1a713
JS
263 endPointsY[3] = y;
264
265 // Store polygon points in an array
266 int np = m_points->Number();
42cfaf8c
JS
267 double *xpoints = new double[np];
268 double *ypoints = new double[np];
0fc1a713
JS
269 wxNode *node = m_points->First();
270 int i = 0;
271 while (node)
272 {
273 wxRealPoint *point = (wxRealPoint *)node->Data();
274 xpoints[i] = point->x + m_xpos;
275 ypoints[i] = point->y + m_ypos;
276 node = node->Next();
277 i ++;
278 }
279
280 // We assume it's inside the polygon UNLESS one or more
281 // lines don't hit the outline.
282 bool isContained = TRUE;
283
284 int noPoints = 4;
285 for (i = 0; i < noPoints; i++)
286 {
287 if (!PolylineHitTest(np, xpoints, ypoints, x, y, endPointsX[i], endPointsY[i]))
288 isContained = FALSE;
289 }
290/*
291 if (isContained)
292 ClipsErrorFunction("It's a hit!\n");
293 else
294 ClipsErrorFunction("No hit.\n");
295*/
296 delete[] xpoints;
297 delete[] ypoints;
298
299 if (!isContained)
300 return FALSE;
301
302 int nearest_attachment = 0;
303
304 // If a hit, check the attachment points within the object.
305 int n = GetNumberOfAttachments();
42cfaf8c 306 double nearest = 999999.0;
0fc1a713
JS
307
308 for (i = 0; i < n; i++)
309 {
42cfaf8c 310 double xp, yp;
0fc1a713
JS
311 if (GetAttachmentPosition(i, &xp, &yp))
312 {
42cfaf8c 313 double l = (double)sqrt(((xp - x) * (xp - x)) +
0fc1a713
JS
314 ((yp - y) * (yp - y)));
315 if (l < nearest)
316 {
317 nearest = l;
318 nearest_attachment = i;
319 }
320 }
321 }
322 *attachment = nearest_attachment;
323 *distance = nearest;
324 return TRUE;
325}
326
327// Really need to be able to reset the shape! Otherwise, if the
328// points ever go to zero, we've lost it, and can't resize.
42cfaf8c 329void wxPolygonShape::SetSize(double new_width, double new_height, bool recursive)
0fc1a713
JS
330{
331 SetAttachmentSize(new_width, new_height);
332
333 // Multiply all points by proportion of new size to old size
42cfaf8c
JS
334 double x_proportion = (double)(fabs(new_width/m_originalWidth));
335 double y_proportion = (double)(fabs(new_height/m_originalHeight));
0fc1a713
JS
336
337 wxNode *node = m_points->First();
338 wxNode *original_node = m_originalPoints->First();
339 while (node && original_node)
340 {
341 wxRealPoint *point = (wxRealPoint *)node->Data();
342 wxRealPoint *original_point = (wxRealPoint *)original_node->Data();
343
344 point->x = (original_point->x * x_proportion);
345 point->y = (original_point->y * y_proportion);
346
347 node = node->Next();
348 original_node = original_node->Next();
349 }
350
351// CalculateBoundingBox();
42cfaf8c
JS
352 m_boundWidth = (double)fabs(new_width);
353 m_boundHeight = (double)fabs(new_height);
0fc1a713
JS
354 SetDefaultRegionSize();
355}
356
357// Make the original points the same as the working points
358void wxPolygonShape::UpdateOriginalPoints()
359{
360 if (!m_originalPoints) m_originalPoints = new wxList;
361 wxNode *original_node = m_originalPoints->First();
362 while (original_node)
363 {
364 wxNode *next_node = original_node->Next();
365 wxRealPoint *original_point = (wxRealPoint *)original_node->Data();
366 delete original_point;
367 delete original_node;
368
369 original_node = next_node;
370 }
371
372 wxNode *node = m_points->First();
373 while (node)
374 {
375 wxRealPoint *point = (wxRealPoint *)node->Data();
376 wxRealPoint *original_point = new wxRealPoint(point->x, point->y);
377 m_originalPoints->Append((wxObject*) original_point);
378
379 node = node->Next();
380 }
381 CalculateBoundingBox();
382 m_originalWidth = m_boundWidth;
383 m_originalHeight = m_boundHeight;
384}
385
386void wxPolygonShape::AddPolygonPoint(int pos)
387{
388 wxNode *node = m_points->Nth(pos);
389 if (!node) node = m_points->First();
390 wxRealPoint *firstPoint = (wxRealPoint *)node->Data();
391
392 wxNode *node2 = m_points->Nth(pos + 1);
393 if (!node2) node2 = m_points->First();
394 wxRealPoint *secondPoint = (wxRealPoint *)node2->Data();
395
42cfaf8c
JS
396 double x = (double)((secondPoint->x - firstPoint->x)/2.0 + firstPoint->x);
397 double y = (double)((secondPoint->y - firstPoint->y)/2.0 + firstPoint->y);
0fc1a713
JS
398 wxRealPoint *point = new wxRealPoint(x, y);
399
400 if (pos >= (m_points->Number() - 1))
401 m_points->Append((wxObject*) point);
402 else
403 m_points->Insert(node2, (wxObject*) point);
404
405 UpdateOriginalPoints();
406
407 if (m_selected)
408 {
409 DeleteControlPoints();
410 MakeControlPoints();
411 }
412}
413
414void wxPolygonShape::DeletePolygonPoint(int pos)
415{
416 wxNode *node = m_points->Nth(pos);
417 if (node)
418 {
419 wxRealPoint *point = (wxRealPoint *)node->Data();
420 delete point;
421 delete node;
422 UpdateOriginalPoints();
423 if (m_selected)
424 {
425 DeleteControlPoints();
426 MakeControlPoints();
427 }
428 }
429}
430
431// Assume (x1, y1) is centre of box (most generally, line end at box)
42cfaf8c
JS
432bool wxPolygonShape::GetPerimeterPoint(double x1, double y1,
433 double x2, double y2,
434 double *x3, double *y3)
0fc1a713
JS
435{
436 int n = m_points->Number();
437
438 // First check for situation where the line is vertical,
439 // and we would want to connect to a point on that vertical --
42cfaf8c 440 // oglFindEndForPolyline can't cope with this (the arrow
0fc1a713
JS
441 // gets drawn to the wrong place).
442 if ((!m_attachmentMode) && (x1 == x2))
443 {
444 // Look for the point we'd be connecting to. This is
445 // a heuristic...
446 wxNode *node = m_points->First();
447 while (node)
448 {
449 wxRealPoint *point = (wxRealPoint *)node->Data();
450 if (point->x == 0.0)
451 {
452 if ((y2 > y1) && (point->y > 0.0))
453 {
454 *x3 = point->x + m_xpos;
455 *y3 = point->y + m_ypos;
456 return TRUE;
457 }
458 else if ((y2 < y1) && (point->y < 0.0))
459 {
460 *x3 = point->x + m_xpos;
461 *y3 = point->y + m_ypos;
462 return TRUE;
463 }
464 }
465 node = node->Next();
466 }
467 }
468
42cfaf8c
JS
469 double *xpoints = new double[n];
470 double *ypoints = new double[n];
0fc1a713
JS
471
472 wxNode *node = m_points->First();
473 int i = 0;
474 while (node)
475 {
476 wxRealPoint *point = (wxRealPoint *)node->Data();
477 xpoints[i] = point->x + m_xpos;
478 ypoints[i] = point->y + m_ypos;
479 node = node->Next();
480 i ++;
481 }
0fc1a713 482
42cfaf8c 483 oglFindEndForPolyline(n, xpoints, ypoints,
0fc1a713
JS
484 x1, y1, x2, y2, x3, y3);
485
42cfaf8c
JS
486 delete[] xpoints;
487 delete[] ypoints;
0fc1a713
JS
488
489 return TRUE;
490}
491
492void wxPolygonShape::OnDraw(wxDC& dc)
493{
494 int n = m_points->Number();
495 wxPoint *intPoints = new wxPoint[n];
496 int i;
497 for (i = 0; i < n; i++)
498 {
499 wxRealPoint* point = (wxRealPoint*) m_points->Nth(i)->Data();
42cfaf8c
JS
500 intPoints[i].x = WXROUND(point->x);
501 intPoints[i].y = WXROUND(point->y);
0fc1a713
JS
502 }
503
504 if (m_shadowMode != SHADOW_NONE)
505 {
506 if (m_shadowBrush)
507 dc.SetBrush(m_shadowBrush);
42cfaf8c 508 dc.SetPen(g_oglTransparentPen);
0fc1a713 509
42cfaf8c 510 dc.DrawPolygon(n, intPoints, WXROUND(m_xpos + m_shadowOffsetX), WXROUND(m_ypos + m_shadowOffsetY));
0fc1a713
JS
511 }
512
513 if (m_pen)
514 {
515 if (m_pen->GetWidth() == 0)
42cfaf8c 516 dc.SetPen(g_oglTransparentPen);
0fc1a713
JS
517 else
518 dc.SetPen(m_pen);
519 }
520 if (m_brush)
521 dc.SetBrush(m_brush);
42cfaf8c 522 dc.DrawPolygon(n, intPoints, WXROUND(m_xpos), WXROUND(m_ypos));
0fc1a713
JS
523
524 delete[] intPoints;
525}
526
42cfaf8c 527void wxPolygonShape::OnDrawOutline(wxDC& dc, double x, double y, double w, double h)
0fc1a713
JS
528{
529 dc.SetBrush(wxTRANSPARENT_BRUSH);
34138703 530 // Multiply all points by proportion of new size to old size
42cfaf8c
JS
531 double x_proportion = (double)(fabs(w/m_originalWidth));
532 double y_proportion = (double)(fabs(h/m_originalHeight));
0fc1a713 533
34138703 534 int n = m_originalPoints->Number();
0fc1a713
JS
535 wxPoint *intPoints = new wxPoint[n];
536 int i;
537 for (i = 0; i < n; i++)
538 {
34138703 539 wxRealPoint* point = (wxRealPoint*) m_originalPoints->Nth(i)->Data();
42cfaf8c
JS
540 intPoints[i].x = WXROUND(x_proportion * point->x);
541 intPoints[i].y = WXROUND(y_proportion * point->y);
0fc1a713 542 }
42cfaf8c 543 dc.DrawPolygon(n, intPoints, WXROUND(x), WXROUND(y));
5de76427 544 delete[] intPoints;
0fc1a713
JS
545}
546
547// Make as many control points as there are vertices.
548void wxPolygonShape::MakeControlPoints()
549{
550 wxNode *node = m_points->First();
551 while (node)
552 {
553 wxRealPoint *point = (wxRealPoint *)node->Data();
554 wxPolygonControlPoint *control = new wxPolygonControlPoint(m_canvas, this, CONTROL_POINT_SIZE,
555 point, point->x, point->y);
556 m_canvas->AddShape(control);
557 m_controlPoints.Append(control);
558 node = node->Next();
559 }
560
561/*
42cfaf8c 562 double maxX, maxY, minX, minY;
0fc1a713
JS
563
564 GetBoundingBoxMax(&maxX, &maxY);
565 GetBoundingBoxMin(&minX, &minY);
566
42cfaf8c
JS
567 double widthMin = (double)(minX + CONTROL_POINT_SIZE + 2);
568 double heightMin = (double)(minY + CONTROL_POINT_SIZE + 2);
0fc1a713
JS
569
570 // Offsets from main object
42cfaf8c
JS
571 double top = (double)(- (heightMin / 2.0));
572 double bottom = (double)(heightMin / 2.0 + (maxY - minY));
573 double left = (double)(- (widthMin / 2.0));
574 double right = (double)(widthMin / 2.0 + (maxX - minX));
0fc1a713
JS
575
576 wxControlPoint *control = new wxControlPoint(m_canvas, this, CONTROL_POINT_SIZE, left, top,
577 CONTROL_POINT_DIAGONAL);
578 m_canvas->AddShape(control);
579 m_controlPoints.Append(control);
580
581 control = new wxControlPoint(m_canvas, this, CONTROL_POINT_SIZE, 0, top,
582 CONTROL_POINT_VERTICAL);
583 m_canvas->AddShape(control);
584 m_controlPoints.Append(control);
585
586 control = new wxControlPoint(m_canvas, this, CONTROL_POINT_SIZE, right, top,
587 CONTROL_POINT_DIAGONAL);
588 m_canvas->AddShape(control);
589 m_controlPoints.Append(control);
590
591 control = new wxControlPoint(m_canvas, this, CONTROL_POINT_SIZE, right, 0,
592 CONTROL_POINT_HORIZONTAL);
593 m_canvas->AddShape(control);
594 m_controlPoints.Append(control);
595
596 control = new wxControlPoint(m_canvas, this, CONTROL_POINT_SIZE, right, bottom,
597 CONTROL_POINT_DIAGONAL);
598 m_canvas->AddShape(control);
599 m_controlPoints.Append(control);
600
601 control = new wxControlPoint(m_canvas, this, CONTROL_POINT_SIZE, 0, bottom,
602 CONTROL_POINT_VERTICAL);
603 m_canvas->AddShape(control);
604 m_controlPoints.Append(control);
605
606 control = new wxControlPoint(m_canvas, this, CONTROL_POINT_SIZE, left, bottom,
607 CONTROL_POINT_DIAGONAL);
608 m_canvas->AddShape(control);
609 m_controlPoints.Append(control);
610
611 control = new wxControlPoint(m_canvas, this, CONTROL_POINT_SIZE, left, 0,
612 CONTROL_POINT_HORIZONTAL);
613 m_canvas->AddShape(control);
614 m_controlPoints.Append(control);
615*/
616}
617
618void wxPolygonShape::ResetControlPoints()
619{
620 wxNode *node = m_points->First();
621 wxNode *controlPointNode = m_controlPoints.First();
622 while (node && controlPointNode)
623 {
624 wxRealPoint *point = (wxRealPoint *)node->Data();
625 wxPolygonControlPoint *controlPoint = (wxPolygonControlPoint *)controlPointNode->Data();
626
627 controlPoint->m_xoffset = point->x;
628 controlPoint->m_yoffset = point->y;
629 controlPoint->m_polygonVertex = point;
630
631 node = node->Next();
632 controlPointNode = controlPointNode->Next();
633 }
634/*
635
636 if (m_controlPoints.Number() < 1)
637 return;
638
42cfaf8c 639 double maxX, maxY, minX, minY;
0fc1a713
JS
640
641 GetBoundingBoxMax(&maxX, &maxY);
642 GetBoundingBoxMin(&minX, &minY);
643
42cfaf8c
JS
644 double widthMin = (double)(minX + CONTROL_POINT_SIZE + 2);
645 double heightMin = (double)(minY + CONTROL_POINT_SIZE + 2);
0fc1a713
JS
646
647 // Offsets from main object
42cfaf8c
JS
648 double top = (double)(- (heightMin / 2.0));
649 double bottom = (double)(heightMin / 2.0 + (maxY - minY));
650 double left = (double)(- (widthMin / 2.0));
651 double right = (double)(widthMin / 2.0 + (maxX - minX));
0fc1a713
JS
652
653 wxNode *node = m_controlPoints.First();
654 wxControlPoint *control = (wxControlPoint *)node->Data();
655 control->xoffset = left; control->yoffset = top;
656
657 node = node->Next(); control = (wxControlPoint *)node->Data();
658 control->xoffset = 0; control->yoffset = top;
659
660 node = node->Next(); control = (wxControlPoint *)node->Data();
661 control->xoffset = right; control->yoffset = top;
662
663 node = node->Next(); control = (wxControlPoint *)node->Data();
664 control->xoffset = right; control->yoffset = 0;
665
666 node = node->Next(); control = (wxControlPoint *)node->Data();
667 control->xoffset = right; control->yoffset = bottom;
668
669 node = node->Next(); control = (wxControlPoint *)node->Data();
670 control->xoffset = 0; control->yoffset = bottom;
671
672 node = node->Next(); control = (wxControlPoint *)node->Data();
673 control->xoffset = left; control->yoffset = bottom;
674
675 node = node->Next(); control = (wxControlPoint *)node->Data();
676 control->xoffset = left; control->yoffset = 0;
677*/
678}
679
680
681#ifdef PROLOGIO
6f5f3ca0 682void wxPolygonShape::WriteAttributes(wxExpr *clause)
0fc1a713 683{
6f5f3ca0 684 wxShape::WriteAttributes(clause);
0fc1a713
JS
685
686 clause->AddAttributeValue("x", m_xpos);
687 clause->AddAttributeValue("y", m_ypos);
688
689 // Make a list of lists for the coordinates
690 wxExpr *list = new wxExpr(PrologList);
691 wxNode *node = m_points->First();
692 while (node)
693 {
694 wxRealPoint *point = (wxRealPoint *)node->Data();
695 wxExpr *point_list = new wxExpr(PrologList);
42cfaf8c
JS
696 wxExpr *x_expr = new wxExpr((double)point->x);
697 wxExpr *y_expr = new wxExpr((double)point->y);
0fc1a713
JS
698
699 point_list->Append(x_expr);
700 point_list->Append(y_expr);
701 list->Append(point_list);
702
703 node = node->Next();
704 }
705 clause->AddAttributeValue("points", list);
706
707 // Save the original (unscaled) points
708 list = new wxExpr(PrologList);
709 node = m_originalPoints->First();
710 while (node)
711 {
712 wxRealPoint *point = (wxRealPoint *)node->Data();
713 wxExpr *point_list = new wxExpr(PrologList);
42cfaf8c
JS
714 wxExpr *x_expr = new wxExpr((double) point->x);
715 wxExpr *y_expr = new wxExpr((double) point->y);
0fc1a713
JS
716 point_list->Append(x_expr);
717 point_list->Append(y_expr);
718 list->Append(point_list);
719
720 node = node->Next();
721 }
722 clause->AddAttributeValue("m_originalPoints", list);
723}
724
6f5f3ca0 725void wxPolygonShape::ReadAttributes(wxExpr *clause)
0fc1a713 726{
6f5f3ca0 727 wxShape::ReadAttributes(clause);
0fc1a713
JS
728
729 // Read a list of lists
730 m_points = new wxList;
731 m_originalPoints = new wxList;
732
733 wxExpr *points_list = NULL;
734 clause->AssignAttributeValue("points", &points_list);
735
736 // If no points_list, don't crash!! Assume a diamond instead.
42cfaf8c
JS
737 double the_height = 100.0;
738 double the_width = 100.0;
0fc1a713
JS
739 if (!points_list)
740 {
741 wxRealPoint *point = new wxRealPoint(0.0, (-the_height/2));
742 m_points->Append((wxObject*) point);
743
744 point = new wxRealPoint((the_width/2), 0.0);
745 m_points->Append((wxObject*) point);
746
747 point = new wxRealPoint(0.0, (the_height/2));
748 m_points->Append((wxObject*) point);
749
750 point = new wxRealPoint((-the_width/2), 0.0);
751 m_points->Append((wxObject*) point);
752
753 point = new wxRealPoint(0.0, (-the_height/2));
754 m_points->Append((wxObject*) point);
755 }
756 else
757 {
758 wxExpr *node = points_list->value.first;
759
760 while (node)
761 {
762 wxExpr *xexpr = node->value.first;
763 long x = xexpr->IntegerValue();
764
765 wxExpr *yexpr = xexpr->next;
766 long y = yexpr->IntegerValue();
767
42cfaf8c 768 wxRealPoint *point = new wxRealPoint((double)x, (double)y);
0fc1a713
JS
769 m_points->Append((wxObject*) point);
770
771 node = node->next;
772 }
773 }
774
775 points_list = NULL;
776 clause->AssignAttributeValue("m_originalPoints", &points_list);
777
778 // If no points_list, don't crash!! Assume a diamond instead.
779 if (!points_list)
780 {
781 wxRealPoint *point = new wxRealPoint(0.0, (-the_height/2));
782 m_originalPoints->Append((wxObject*) point);
783
784 point = new wxRealPoint((the_width/2), 0.0);
785 m_originalPoints->Append((wxObject*) point);
786
787 point = new wxRealPoint(0.0, (the_height/2));
788 m_originalPoints->Append((wxObject*) point);
789
790 point = new wxRealPoint((-the_width/2), 0.0);
791 m_originalPoints->Append((wxObject*) point);
792
793 point = new wxRealPoint(0.0, (-the_height/2));
794 m_originalPoints->Append((wxObject*) point);
795
796 m_originalWidth = the_width;
797 m_originalHeight = the_height;
798 }
799 else
800 {
801 wxExpr *node = points_list->value.first;
42cfaf8c
JS
802 double min_x = 1000;
803 double min_y = 1000;
804 double max_x = -1000;
805 double max_y = -1000;
0fc1a713
JS
806 while (node)
807 {
808 wxExpr *xexpr = node->value.first;
809 long x = xexpr->IntegerValue();
810
811 wxExpr *yexpr = xexpr->next;
812 long y = yexpr->IntegerValue();
813
42cfaf8c 814 wxRealPoint *point = new wxRealPoint((double)x, (double)y);
0fc1a713
JS
815 m_originalPoints->Append((wxObject*) point);
816
817 if (x < min_x)
42cfaf8c 818 min_x = (double)x;
0fc1a713 819 if (y < min_y)
42cfaf8c 820 min_y = (double)y;
0fc1a713 821 if (x > max_x)
42cfaf8c 822 max_x = (double)x;
0fc1a713 823 if (y > max_y)
42cfaf8c 824 max_y = (double)y;
0fc1a713
JS
825
826 node = node->next;
827 }
828 m_originalWidth = max_x - min_x;
829 m_originalHeight = max_y - min_y;
830 }
831
832 CalculateBoundingBox();
833}
834#endif
835
2bb0cd28 836void wxPolygonShape::Copy(wxShape& copy)
0fc1a713
JS
837{
838 wxShape::Copy(copy);
839
2bb0cd28 840 wxASSERT( copy.IsKindOf(CLASSINFO(wxPolygonShape)) );
0fc1a713 841
2bb0cd28 842 wxPolygonShape& polyCopy = (wxPolygonShape&) copy;
0fc1a713 843
5de76427 844 polyCopy.ClearPoints();
0fc1a713 845
2bb0cd28 846 polyCopy.m_points = new wxList;
2bb0cd28 847 polyCopy.m_originalPoints = new wxList;
0fc1a713
JS
848
849 wxNode *node = m_points->First();
850 while (node)
851 {
852 wxRealPoint *point = (wxRealPoint *)node->Data();
853 wxRealPoint *new_point = new wxRealPoint(point->x, point->y);
2bb0cd28 854 polyCopy.m_points->Append((wxObject*) new_point);
0fc1a713
JS
855 node = node->Next();
856 }
857 node = m_originalPoints->First();
858 while (node)
859 {
860 wxRealPoint *point = (wxRealPoint *)node->Data();
861 wxRealPoint *new_point = new wxRealPoint(point->x, point->y);
2bb0cd28 862 polyCopy.m_originalPoints->Append((wxObject*) new_point);
0fc1a713
JS
863 node = node->Next();
864 }
2bb0cd28
JS
865 polyCopy.m_boundWidth = m_boundWidth;
866 polyCopy.m_boundHeight = m_boundHeight;
867 polyCopy.m_originalWidth = m_originalWidth;
868 polyCopy.m_originalHeight = m_originalHeight;
0fc1a713
JS
869}
870
6f5f3ca0 871int wxPolygonShape::GetNumberOfAttachments() const
0fc1a713
JS
872{
873 int maxN = (m_points ? (m_points->Number() - 1) : 0);
874 wxNode *node = m_attachmentPoints.First();
875 while (node)
876 {
877 wxAttachmentPoint *point = (wxAttachmentPoint *)node->Data();
878 if (point->m_id > maxN)
879 maxN = point->m_id;
880 node = node->Next();
881 }
882 return maxN+1;;
883}
884
42cfaf8c 885bool wxPolygonShape::GetAttachmentPosition(int attachment, double *x, double *y,
0fc1a713
JS
886 int nth, int no_arcs, wxLineShape *line)
887{
888 if (m_attachmentMode && m_points && attachment < m_points->Number())
889 {
890 wxRealPoint *point = (wxRealPoint *)m_points->Nth(attachment)->Data();
891 *x = point->x + m_xpos;
892 *y = point->y + m_ypos;
893 return TRUE;
894 }
895 else
896 { return wxShape::GetAttachmentPosition(attachment, x, y, nth, no_arcs, line); }
897}
898
899bool wxPolygonShape::AttachmentIsValid(int attachment)
900{
901 if (!m_points)
902 return FALSE;
903
904 if ((attachment >= 0) && (attachment < m_points->Number()))
905 return TRUE;
906
907 wxNode *node = m_attachmentPoints.First();
908 while (node)
909 {
910 wxAttachmentPoint *point = (wxAttachmentPoint *)node->Data();
911 if (point->m_id == attachment)
912 return TRUE;
913 node = node->Next();
914 }
915 return FALSE;
916}
917
918// Rectangle object
919
920IMPLEMENT_DYNAMIC_CLASS(wxRectangleShape, wxShape)
921
42cfaf8c 922wxRectangleShape::wxRectangleShape(double w, double h)
0fc1a713
JS
923{
924 m_width = w; m_height = h; m_cornerRadius = 0.0;
925 SetDefaultRegionSize();
926}
927
928void wxRectangleShape::OnDraw(wxDC& dc)
929{
42cfaf8c
JS
930 double x1 = (double)(m_xpos - m_width/2.0);
931 double y1 = (double)(m_ypos - m_height/2.0);
0fc1a713
JS
932
933 if (m_shadowMode != SHADOW_NONE)
934 {
935 if (m_shadowBrush)
936 dc.SetBrush(m_shadowBrush);
42cfaf8c 937 dc.SetPen(g_oglTransparentPen);
0fc1a713
JS
938
939 if (m_cornerRadius != 0.0)
42cfaf8c
JS
940 dc.DrawRoundedRectangle(WXROUND(x1 + m_shadowOffsetX), WXROUND(y1 + m_shadowOffsetY),
941 WXROUND(m_width), WXROUND(m_height), m_cornerRadius);
0fc1a713 942 else
42cfaf8c 943 dc.DrawRectangle(WXROUND(x1 + m_shadowOffsetX), WXROUND(y1 + m_shadowOffsetY), WXROUND(m_width), WXROUND(m_height));
0fc1a713
JS
944 }
945
946 if (m_pen)
947 {
948 if (m_pen->GetWidth() == 0)
42cfaf8c 949 dc.SetPen(g_oglTransparentPen);
0fc1a713
JS
950 else
951 dc.SetPen(m_pen);
952 }
953 if (m_brush)
954 dc.SetBrush(m_brush);
955
956 if (m_cornerRadius != 0.0)
42cfaf8c 957 dc.DrawRoundedRectangle(WXROUND(x1), WXROUND(y1), WXROUND(m_width), WXROUND(m_height), m_cornerRadius);
0fc1a713 958 else
42cfaf8c 959 dc.DrawRectangle(WXROUND(x1), WXROUND(y1), WXROUND(m_width), WXROUND(m_height));
0fc1a713
JS
960}
961
42cfaf8c 962void wxRectangleShape::GetBoundingBoxMin(double *the_width, double *the_height)
0fc1a713
JS
963{
964 *the_width = m_width;
965 *the_height = m_height;
966}
967
42cfaf8c 968void wxRectangleShape::SetSize(double x, double y, bool recursive)
0fc1a713
JS
969{
970 SetAttachmentSize(x, y);
42cfaf8c
JS
971 m_width = (double)wxMax(x, 1.0);
972 m_height = (double)wxMax(y, 1.0);
0fc1a713
JS
973 SetDefaultRegionSize();
974}
975
42cfaf8c 976void wxRectangleShape::SetCornerRadius(double rad)
0fc1a713
JS
977{
978 m_cornerRadius = rad;
979}
980
981// Assume (x1, y1) is centre of box (most generally, line end at box)
42cfaf8c
JS
982bool wxRectangleShape::GetPerimeterPoint(double x1, double y1,
983 double x2, double y2,
984 double *x3, double *y3)
0fc1a713 985{
42cfaf8c 986 double bound_x, bound_y;
0fc1a713 987 GetBoundingBoxMax(&bound_x, &bound_y);
42cfaf8c 988 oglFindEndForBox(bound_x, bound_y, m_xpos, m_ypos, x2, y2, x3, y3);
0fc1a713
JS
989
990 return TRUE;
991}
992
993#ifdef PROLOGIO
6f5f3ca0 994void wxRectangleShape::WriteAttributes(wxExpr *clause)
0fc1a713 995{
6f5f3ca0 996 wxShape::WriteAttributes(clause);
0fc1a713
JS
997 clause->AddAttributeValue("x", m_xpos);
998 clause->AddAttributeValue("y", m_ypos);
999
1000 clause->AddAttributeValue("width", m_width);
1001 clause->AddAttributeValue("height", m_height);
1002 if (m_cornerRadius != 0.0)
1003 clause->AddAttributeValue("corner", m_cornerRadius);
1004}
1005
6f5f3ca0 1006void wxRectangleShape::ReadAttributes(wxExpr *clause)
0fc1a713 1007{
6f5f3ca0 1008 wxShape::ReadAttributes(clause);
0fc1a713
JS
1009 clause->AssignAttributeValue("width", &m_width);
1010 clause->AssignAttributeValue("height", &m_height);
1011 clause->AssignAttributeValue("corner", &m_cornerRadius);
1012
1013 // In case we're reading an old file, set the region's size
1014 if (m_regions.Number() == 1)
1015 {
1016 wxShapeRegion *region = (wxShapeRegion *)m_regions.First()->Data();
1017 region->SetSize(m_width, m_height);
1018 }
1019}
1020#endif
1021
2bb0cd28 1022void wxRectangleShape::Copy(wxShape& copy)
0fc1a713
JS
1023{
1024 wxShape::Copy(copy);
0fc1a713 1025
2bb0cd28 1026 wxASSERT( copy.IsKindOf(CLASSINFO(wxRectangleShape)) );
0fc1a713 1027
2bb0cd28
JS
1028 wxRectangleShape& rectCopy = (wxRectangleShape&) copy;
1029 rectCopy.m_width = m_width;
1030 rectCopy.m_height = m_height;
1031 rectCopy.m_cornerRadius = m_cornerRadius;
1032}
0fc1a713 1033
6f5f3ca0 1034int wxRectangleShape::GetNumberOfAttachments() const
0fc1a713
JS
1035{
1036 return wxShape::GetNumberOfAttachments();
1037}
1038
42cfaf8c 1039
0fc1a713
JS
1040// There are 4 attachment points on a rectangle - 0 = top, 1 = right, 2 = bottom,
1041// 3 = left.
42cfaf8c 1042bool wxRectangleShape::GetAttachmentPosition(int attachment, double *x, double *y,
0fc1a713
JS
1043 int nth, int no_arcs, wxLineShape *line)
1044{
1045 if (m_attachmentMode)
1046 {
42cfaf8c
JS
1047 double top = (double)(m_ypos + m_height/2.0);
1048 double bottom = (double)(m_ypos - m_height/2.0);
1049 double left = (double)(m_xpos - m_width/2.0);
1050 double right = (double)(m_xpos + m_width/2.0);
0fc1a713
JS
1051
1052 bool isEnd = (line && line->IsEnd(this));
1053
42cfaf8c
JS
1054 // Simplified code
1055 switch (attachment)
1056 {
1057 case 0:
1058 {
1059 wxRealPoint pt = CalcSimpleAttachment(wxRealPoint(left, bottom), wxRealPoint(right, bottom),
1060 nth, no_arcs, line);
1061
1062 *x = pt.x; *y = pt.y;
1063 break;
1064 }
1065 case 1:
1066 {
1067 wxRealPoint pt = CalcSimpleAttachment(wxRealPoint(right, bottom), wxRealPoint(right, top),
1068 nth, no_arcs, line);
1069
1070 *x = pt.x; *y = pt.y;
1071 break;
1072 }
1073 case 2:
1074 {
1075 wxRealPoint pt = CalcSimpleAttachment(wxRealPoint(left, top), wxRealPoint(right, top),
1076 nth, no_arcs, line);
1077
1078 *x = pt.x; *y = pt.y;
1079 break;
1080 }
1081 case 3:
1082 {
1083 wxRealPoint pt = CalcSimpleAttachment(wxRealPoint(left, bottom), wxRealPoint(left, top),
1084 nth, no_arcs, line);
1085
1086 *x = pt.x; *y = pt.y;
1087 break;
1088 }
1089 default:
1090 {
1091 return wxShape::GetAttachmentPosition(attachment, x, y, nth, no_arcs, line);
1092 break;
1093 }
1094 }
1095
1096 // Old code
1097#if 0
0fc1a713
JS
1098 switch (attachment)
1099 {
1100 case 0:
1101 {
1102 if (m_spaceAttachments)
1103 {
1104 if (line && (line->GetAlignmentType(isEnd) == LINE_ALIGNMENT_TO_NEXT_HANDLE))
1105 {
1106 // Align line according to the next handle along
1107 wxRealPoint *point = line->GetNextControlPoint(this);
1108 if (point->x < left)
1109 *x = left;
1110 else if (point->x > right)
1111 *x = right;
1112 else
1113 *x = point->x;
1114 }
1115 else
1116 *x = left + (nth + 1)*m_width/(no_arcs + 1);
1117 }
1118 else *x = m_xpos;
1119
1120 *y = bottom;
1121 break;
1122 }
1123 case 1:
1124 {
1125 *x = right;
1126 if (m_spaceAttachments)
1127 {
1128 if (line && (line->GetAlignmentType(isEnd) == LINE_ALIGNMENT_TO_NEXT_HANDLE))
1129 {
1130 // Align line according to the next handle along
1131 wxRealPoint *point = line->GetNextControlPoint(this);
1132 if (point->y < bottom)
1133 *y = bottom;
1134 else if (point->y > top)
1135 *y = top;
1136 else
1137 *y = point->y;
1138 }
1139 else
1140 *y = bottom + (nth + 1)*m_height/(no_arcs + 1);
1141 }
1142 else *y = m_ypos;
1143 break;
1144 }
1145 case 2:
1146 {
1147 if (m_spaceAttachments)
1148 {
1149 if (line && (line->GetAlignmentType(isEnd) == LINE_ALIGNMENT_TO_NEXT_HANDLE))
1150 {
1151 // Align line according to the next handle along
1152 wxRealPoint *point = line->GetNextControlPoint(this);
1153 if (point->x < left)
1154 *x = left;
1155 else if (point->x > right)
1156 *x = right;
1157 else
1158 *x = point->x;
1159 }
1160 else
1161 *x = left + (nth + 1)*m_width/(no_arcs + 1);
1162 }
1163 else *x = m_xpos;
1164 *y = top;
1165 break;
1166 }
1167 case 3:
1168 {
1169 *x = left;
1170 if (m_spaceAttachments)
1171 {
1172 if (line && (line->GetAlignmentType(isEnd) == LINE_ALIGNMENT_TO_NEXT_HANDLE))
1173 {
1174 // Align line according to the next handle along
1175 wxRealPoint *point = line->GetNextControlPoint(this);
1176 if (point->y < bottom)
1177 *y = bottom;
1178 else if (point->y > top)
1179 *y = top;
1180 else
1181 *y = point->y;
1182 }
1183 else
1184 *y = bottom + (nth + 1)*m_height/(no_arcs + 1);
1185 }
1186 else *y = m_ypos;
1187 break;
1188 }
1189 default:
1190 {
1191 return wxShape::GetAttachmentPosition(attachment, x, y, nth, no_arcs, line);
1192 break;
1193 }
1194 }
42cfaf8c 1195#endif
0fc1a713
JS
1196 return TRUE;
1197 }
1198 else
1199 { *x = m_xpos; *y = m_ypos; return TRUE; }
1200}
1201
1202// Text object (no box)
1203
1204IMPLEMENT_DYNAMIC_CLASS(wxTextShape, wxRectangleShape)
1205
42cfaf8c 1206wxTextShape::wxTextShape(double width, double height):
0fc1a713
JS
1207 wxRectangleShape(width, height)
1208{
1209}
1210
1211void wxTextShape::OnDraw(wxDC& dc)
1212{
1213}
1214
2bb0cd28 1215void wxTextShape::Copy(wxShape& copy)
0fc1a713
JS
1216{
1217 wxRectangleShape::Copy(copy);
1218}
1219
1220#ifdef PROLOGIO
6f5f3ca0 1221void wxTextShape::WriteAttributes(wxExpr *clause)
0fc1a713 1222{
6f5f3ca0 1223 wxRectangleShape::WriteAttributes(clause);
0fc1a713
JS
1224}
1225#endif
1226
1227// Ellipse object
1228
1229IMPLEMENT_DYNAMIC_CLASS(wxEllipseShape, wxShape)
1230
42cfaf8c 1231wxEllipseShape::wxEllipseShape(double w, double h)
0fc1a713
JS
1232{
1233 m_width = w; m_height = h;
1234 SetDefaultRegionSize();
1235}
1236
42cfaf8c 1237void wxEllipseShape::GetBoundingBoxMin(double *w, double *h)
0fc1a713
JS
1238{
1239 *w = m_width; *h = m_height;
1240}
1241
42cfaf8c
JS
1242bool wxEllipseShape::GetPerimeterPoint(double x1, double y1,
1243 double x2, double y2,
1244 double *x3, double *y3)
0fc1a713 1245{
42cfaf8c 1246 double bound_x, bound_y;
0fc1a713
JS
1247 GetBoundingBoxMax(&bound_x, &bound_y);
1248
42cfaf8c
JS
1249// oglFindEndForBox(bound_x, bound_y, m_xpos, m_ypos, x2, y2, x3, y3);
1250 oglDrawArcToEllipse(m_xpos, m_ypos, bound_x, bound_y, x2, y2, x1, y1, x3, y3);
0fc1a713
JS
1251
1252 return TRUE;
1253}
1254
1255void wxEllipseShape::OnDraw(wxDC& dc)
1256{
1257 if (m_shadowMode != SHADOW_NONE)
1258 {
1259 if (m_shadowBrush)
1260 dc.SetBrush(m_shadowBrush);
42cfaf8c 1261 dc.SetPen(g_oglTransparentPen);
0fc1a713
JS
1262 dc.DrawEllipse((m_xpos - GetWidth()/2) + m_shadowOffsetX,
1263 (m_ypos - GetHeight()/2) + m_shadowOffsetY,
1264 GetWidth(), GetHeight());
1265 }
1266
1267 if (m_pen)
1268 {
1269 if (m_pen->GetWidth() == 0)
42cfaf8c 1270 dc.SetPen(g_oglTransparentPen);
0fc1a713
JS
1271 else
1272 dc.SetPen(m_pen);
1273 }
1274 if (m_brush)
1275 dc.SetBrush(m_brush);
1276 dc.DrawEllipse((m_xpos - GetWidth()/2), (m_ypos - GetHeight()/2), GetWidth(), GetHeight());
1277}
1278
42cfaf8c 1279void wxEllipseShape::SetSize(double x, double y, bool recursive)
0fc1a713
JS
1280{
1281 SetAttachmentSize(x, y);
1282 m_width = x;
1283 m_height = y;
1284 SetDefaultRegionSize();
1285}
1286
1287#ifdef PROLOGIO
6f5f3ca0 1288void wxEllipseShape::WriteAttributes(wxExpr *clause)
0fc1a713 1289{
6f5f3ca0 1290 wxShape::WriteAttributes(clause);
0fc1a713
JS
1291 clause->AddAttributeValue("x", m_xpos);
1292 clause->AddAttributeValue("y", m_ypos);
1293
1294 clause->AddAttributeValue("width", m_width);
1295 clause->AddAttributeValue("height", m_height);
1296}
1297
6f5f3ca0 1298void wxEllipseShape::ReadAttributes(wxExpr *clause)
0fc1a713 1299{
6f5f3ca0 1300 wxShape::ReadAttributes(clause);
0fc1a713
JS
1301 clause->AssignAttributeValue("width", &m_width);
1302 clause->AssignAttributeValue("height", &m_height);
1303
1304 // In case we're reading an old file, set the region's size
1305 if (m_regions.Number() == 1)
1306 {
1307 wxShapeRegion *region = (wxShapeRegion *)m_regions.First()->Data();
1308 region->SetSize(m_width, m_height);
1309 }
1310}
1311#endif
1312
2bb0cd28 1313void wxEllipseShape::Copy(wxShape& copy)
0fc1a713
JS
1314{
1315 wxShape::Copy(copy);
1316
2bb0cd28 1317 wxASSERT( copy.IsKindOf(CLASSINFO(wxEllipseShape)) );
0fc1a713 1318
2bb0cd28
JS
1319 wxEllipseShape& ellipseCopy = (wxEllipseShape&) copy;
1320
1321 ellipseCopy.m_width = m_width;
1322 ellipseCopy.m_height = m_height;
0fc1a713
JS
1323}
1324
6f5f3ca0 1325int wxEllipseShape::GetNumberOfAttachments() const
0fc1a713
JS
1326{
1327 return wxShape::GetNumberOfAttachments();
1328}
1329
1330// There are 4 attachment points on an ellipse - 0 = top, 1 = right, 2 = bottom,
1331// 3 = left.
42cfaf8c 1332bool wxEllipseShape::GetAttachmentPosition(int attachment, double *x, double *y,
0fc1a713
JS
1333 int nth, int no_arcs, wxLineShape *line)
1334{
1335 if (m_attachmentMode)
1336 {
42cfaf8c
JS
1337 double top = (double)(m_ypos + m_height/2.0);
1338 double bottom = (double)(m_ypos - m_height/2.0);
1339 double left = (double)(m_xpos - m_width/2.0);
1340 double right = (double)(m_xpos + m_width/2.0);
0fc1a713
JS
1341 switch (attachment)
1342 {
1343 case 0:
1344 {
1345 if (m_spaceAttachments)
1346 *x = left + (nth + 1)*m_width/(no_arcs + 1);
1347 else *x = m_xpos;
1348 *y = top;
1349 // We now have the point on the bounding box: but get the point on the ellipse
1350 // by imagining a vertical line from (*x, m_ypos - m_height- 500) to (*x, m_ypos) intersecting
1351 // the ellipse.
42cfaf8c 1352 oglDrawArcToEllipse(m_xpos, m_ypos, m_width, m_height, *x, (double)(m_ypos-m_height-500), *x, m_ypos, x, y);
0fc1a713
JS
1353 break;
1354 }
1355 case 1:
1356 {
1357 *x = right;
1358 if (m_spaceAttachments)
1359 *y = bottom + (nth + 1)*m_height/(no_arcs + 1);
1360 else *y = m_ypos;
42cfaf8c 1361 oglDrawArcToEllipse(m_xpos, m_ypos, m_width, m_height, (double)(m_xpos+m_width+500), *y, m_xpos, *y, x, y);
0fc1a713
JS
1362 break;
1363 }
1364 case 2:
1365 {
1366 if (m_spaceAttachments)
1367 *x = left + (nth + 1)*m_width/(no_arcs + 1);
1368 else *x = m_xpos;
1369 *y = bottom;
42cfaf8c 1370 oglDrawArcToEllipse(m_xpos, m_ypos, m_width, m_height, *x, (double)(m_ypos+m_height+500), *x, m_ypos, x, y);
0fc1a713
JS
1371 break;
1372 }
1373 case 3:
1374 {
1375 *x = left;
1376 if (m_spaceAttachments)
1377 *y = bottom + (nth + 1)*m_height/(no_arcs + 1);
1378 else *y = m_ypos;
42cfaf8c 1379 oglDrawArcToEllipse(m_xpos, m_ypos, m_width, m_height, (double)(m_xpos-m_width-500), *y, m_xpos, *y, x, y);
0fc1a713
JS
1380 break;
1381 }
1382 default:
1383 {
1384 return wxShape::GetAttachmentPosition(attachment, x, y, nth, no_arcs, line);
1385 break;
1386 }
1387 }
1388 return TRUE;
1389 }
1390 else
1391 { *x = m_xpos; *y = m_ypos; return TRUE; }
1392}
1393
1394
1395// Circle object
1396IMPLEMENT_DYNAMIC_CLASS(wxCircleShape, wxEllipseShape)
1397
42cfaf8c 1398wxCircleShape::wxCircleShape(double diameter):wxEllipseShape(diameter, diameter)
0fc1a713
JS
1399{
1400}
1401
2bb0cd28 1402void wxCircleShape::Copy(wxShape& copy)
0fc1a713
JS
1403{
1404 wxEllipseShape::Copy(copy);
1405}
1406
42cfaf8c
JS
1407bool wxCircleShape::GetPerimeterPoint(double x1, double y1,
1408 double x2, double y2,
1409 double *x3, double *y3)
0fc1a713 1410{
42cfaf8c 1411 oglFindEndForCircle(m_width/2,
0fc1a713
JS
1412 m_xpos, m_ypos, // Centre of circle
1413 x2, y2, // Other end of line
1414 x3, y3);
1415
1416 return TRUE;
1417}
1418
1419// Control points
1420
42cfaf8c
JS
1421double wxControlPoint::controlPointDragStartX = 0.0;
1422double wxControlPoint::controlPointDragStartY = 0.0;
1423double wxControlPoint::controlPointDragStartWidth = 0.0;
1424double wxControlPoint::controlPointDragStartHeight = 0.0;
1425double wxControlPoint::controlPointDragEndWidth = 0.0;
1426double wxControlPoint::controlPointDragEndHeight = 0.0;
1427double wxControlPoint::controlPointDragPosX = 0.0;
1428double wxControlPoint::controlPointDragPosY = 0.0;
2bb0cd28 1429
0fc1a713
JS
1430IMPLEMENT_DYNAMIC_CLASS(wxControlPoint, wxRectangleShape)
1431
42cfaf8c 1432wxControlPoint::wxControlPoint(wxShapeCanvas *theCanvas, wxShape *object, double size, double the_xoffset, double the_yoffset, int the_type):wxRectangleShape(size, size)
0fc1a713
JS
1433{
1434 m_canvas = theCanvas;
1435 m_shape = object;
1436 m_xoffset = the_xoffset;
1437 m_yoffset = the_yoffset;
1438 m_type = the_type;
42cfaf8c 1439 SetPen(g_oglBlackForegroundPen);
0fc1a713
JS
1440 SetBrush(wxBLACK_BRUSH);
1441 m_oldCursor = NULL;
1442 m_visible = TRUE;
1443 m_eraseObject = TRUE;
1444}
1445
1446wxControlPoint::~wxControlPoint()
1447{
1448}
1449
1450// Don't even attempt to draw any text - waste of time!
1451void wxControlPoint::OnDrawContents(wxDC& dc)
1452{
1453}
1454
1455void wxControlPoint::OnDraw(wxDC& dc)
1456{
1457 m_xpos = m_shape->GetX() + m_xoffset;
1458 m_ypos = m_shape->GetY() + m_yoffset;
1459 wxRectangleShape::OnDraw(dc);
1460}
1461
1462void wxControlPoint::OnErase(wxDC& dc)
1463{
1464 wxRectangleShape::OnErase(dc);
1465}
1466
0fc1a713 1467// Implement resizing of canvas object
42cfaf8c 1468void wxControlPoint::OnDragLeft(bool draw, double x, double y, int keys, int attachment)
2bb0cd28
JS
1469{
1470 m_shape->GetEventHandler()->OnSizingDragLeft(this, draw, x, y, keys, attachment);
1471}
1472
42cfaf8c 1473void wxControlPoint::OnBeginDragLeft(double x, double y, int keys, int attachment)
2bb0cd28
JS
1474{
1475 m_shape->GetEventHandler()->OnSizingBeginDragLeft(this, x, y, keys, attachment);
1476}
1477
42cfaf8c 1478void wxControlPoint::OnEndDragLeft(double x, double y, int keys, int attachment)
2bb0cd28
JS
1479{
1480 m_shape->GetEventHandler()->OnSizingEndDragLeft(this, x, y, keys, attachment);
1481}
1482
6f5f3ca0 1483int wxControlPoint::GetNumberOfAttachments() const
2bb0cd28
JS
1484{
1485 return 1;
1486}
1487
42cfaf8c 1488bool wxControlPoint::GetAttachmentPosition(int attachment, double *x, double *y,
2bb0cd28
JS
1489 int nth, int no_arcs, wxLineShape *line)
1490{
1491 *x = m_xpos; *y = m_ypos;
1492 return TRUE;
1493}
1494
1495// Control points ('handles') redirect control to the actual shape, to make it easier
1496// to override sizing behaviour.
42cfaf8c 1497void wxShape::OnSizingDragLeft(wxControlPoint* pt, bool draw, double x, double y, int keys, int attachment)
0fc1a713 1498{
42cfaf8c
JS
1499 double bound_x;
1500 double bound_y;
2bb0cd28 1501 this->GetBoundingBoxMin(&bound_x, &bound_y);
0fc1a713
JS
1502
1503 wxClientDC dc(GetCanvas());
1504 GetCanvas()->PrepareDC(dc);
1505
1506 dc.SetLogicalFunction(wxXOR);
1507
1508 wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
1509 dc.SetPen(dottedPen);
1510 dc.SetBrush((* wxTRANSPARENT_BRUSH));
1511
2bb0cd28 1512 if (this->GetCentreResize())
0fc1a713
JS
1513 {
1514 // Maintain the same centre point.
42cfaf8c
JS
1515 double new_width = (double)(2.0*fabs(x - this->GetX()));
1516 double new_height = (double)(2.0*fabs(y - this->GetY()));
0fc1a713
JS
1517
1518 // Constrain sizing according to what control point you're dragging
2bb0cd28 1519 if (pt->m_type == CONTROL_POINT_HORIZONTAL)
0fc1a713 1520 new_height = bound_y;
2bb0cd28 1521 else if (pt->m_type == CONTROL_POINT_VERTICAL)
0fc1a713 1522 new_width = bound_x;
2bb0cd28 1523 else if (pt->m_type == CONTROL_POINT_DIAGONAL && (keys & KEY_SHIFT))
0fc1a713
JS
1524 new_height = bound_y*(new_width/bound_x);
1525
2bb0cd28 1526 if (this->GetFixedWidth())
0fc1a713
JS
1527 new_width = bound_x;
1528
2bb0cd28 1529 if (this->GetFixedHeight())
0fc1a713
JS
1530 new_height = bound_y;
1531
2bb0cd28
JS
1532 pt->controlPointDragEndWidth = new_width;
1533 pt->controlPointDragEndHeight = new_height;
0fc1a713 1534
2bb0cd28 1535 this->GetEventHandler()->OnDrawOutline(dc, this->GetX(), this->GetY(),
0fc1a713
JS
1536 new_width, new_height);
1537 }
1538 else
1539 {
1540 // Don't maintain the same centre point!
42cfaf8c
JS
1541 double newX1 = wxMin(pt->controlPointDragStartX, x);
1542 double newY1 = wxMin(pt->controlPointDragStartY, y);
1543 double newX2 = wxMax(pt->controlPointDragStartX, x);
1544 double newY2 = wxMax(pt->controlPointDragStartY, y);
2bb0cd28 1545 if (pt->m_type == CONTROL_POINT_HORIZONTAL)
0fc1a713 1546 {
2bb0cd28
JS
1547 newY1 = pt->controlPointDragStartY;
1548 newY2 = newY1 + pt->controlPointDragStartHeight;
0fc1a713 1549 }
2bb0cd28 1550 else if (pt->m_type == CONTROL_POINT_VERTICAL)
0fc1a713 1551 {
2bb0cd28
JS
1552 newX1 = pt->controlPointDragStartX;
1553 newX2 = newX1 + pt->controlPointDragStartWidth;
0fc1a713 1554 }
2bb0cd28 1555 else if (pt->m_type == CONTROL_POINT_DIAGONAL && (keys & KEY_SHIFT))
0fc1a713 1556 {
42cfaf8c 1557 double newH = (double)((newX2 - newX1)*(pt->controlPointDragStartHeight/pt->controlPointDragStartWidth));
2bb0cd28 1558 if (GetY() > pt->controlPointDragStartY)
42cfaf8c 1559 newY2 = (double)(newY1 + newH);
0fc1a713 1560 else
42cfaf8c 1561 newY1 = (double)(newY2 - newH);
0fc1a713 1562 }
42cfaf8c
JS
1563 double newWidth = (double)(newX2 - newX1);
1564 double newHeight = (double)(newY2 - newY1);
0fc1a713 1565
42cfaf8c
JS
1566 pt->controlPointDragPosX = (double)(newX1 + (newWidth/2.0));
1567 pt->controlPointDragPosY = (double)(newY1 + (newHeight/2.0));
2bb0cd28 1568 if (this->GetFixedWidth())
0fc1a713
JS
1569 newWidth = bound_x;
1570
2bb0cd28 1571 if (this->GetFixedHeight())
0fc1a713
JS
1572 newHeight = bound_y;
1573
2bb0cd28
JS
1574 pt->controlPointDragEndWidth = newWidth;
1575 pt->controlPointDragEndHeight = newHeight;
1576 this->GetEventHandler()->OnDrawOutline(dc, pt->controlPointDragPosX, pt->controlPointDragPosY, newWidth, newHeight);
0fc1a713
JS
1577 }
1578}
1579
42cfaf8c 1580void wxShape::OnSizingBeginDragLeft(wxControlPoint* pt, double x, double y, int keys, int attachment)
0fc1a713
JS
1581{
1582 m_canvas->CaptureMouse();
1583
1584 wxClientDC dc(GetCanvas());
1585 GetCanvas()->PrepareDC(dc);
2e5ed787 1586/*
2bb0cd28
JS
1587 if (pt->m_eraseObject)
1588 this->Erase(dc);
2e5ed787 1589*/
0fc1a713
JS
1590
1591 dc.SetLogicalFunction(wxXOR);
1592
42cfaf8c
JS
1593 double bound_x;
1594 double bound_y;
2bb0cd28 1595 this->GetBoundingBoxMin(&bound_x, &bound_y);
0fc1a713
JS
1596
1597 // Choose the 'opposite corner' of the object as the stationary
1598 // point in case this is non-centring resizing.
2bb0cd28 1599 if (pt->GetX() < this->GetX())
42cfaf8c 1600 pt->controlPointDragStartX = (double)(this->GetX() + (bound_x/2.0));
0fc1a713 1601 else
42cfaf8c 1602 pt->controlPointDragStartX = (double)(this->GetX() - (bound_x/2.0));
0fc1a713 1603
2bb0cd28 1604 if (pt->GetY() < this->GetY())
42cfaf8c 1605 pt->controlPointDragStartY = (double)(this->GetY() + (bound_y/2.0));
0fc1a713 1606 else
42cfaf8c 1607 pt->controlPointDragStartY = (double)(this->GetY() - (bound_y/2.0));
0fc1a713 1608
2bb0cd28 1609 if (pt->m_type == CONTROL_POINT_HORIZONTAL)
42cfaf8c 1610 pt->controlPointDragStartY = (double)(this->GetY() - (bound_y/2.0));
2bb0cd28 1611 else if (pt->m_type == CONTROL_POINT_VERTICAL)
42cfaf8c 1612 pt->controlPointDragStartX = (double)(this->GetX() - (bound_x/2.0));
0fc1a713
JS
1613
1614 // We may require the old width and height.
2bb0cd28
JS
1615 pt->controlPointDragStartWidth = bound_x;
1616 pt->controlPointDragStartHeight = bound_y;
0fc1a713
JS
1617
1618 wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
1619 dc.SetPen(dottedPen);
1620 dc.SetBrush((* wxTRANSPARENT_BRUSH));
1621
2bb0cd28 1622 if (this->GetCentreResize())
0fc1a713 1623 {
42cfaf8c
JS
1624 double new_width = (double)(2.0*fabs(x - this->GetX()));
1625 double new_height = (double)(2.0*fabs(y - this->GetY()));
0fc1a713
JS
1626
1627 // Constrain sizing according to what control point you're dragging
2bb0cd28 1628 if (pt->m_type == CONTROL_POINT_HORIZONTAL)
0fc1a713 1629 new_height = bound_y;
2bb0cd28 1630 else if (pt->m_type == CONTROL_POINT_VERTICAL)
0fc1a713 1631 new_width = bound_x;
2bb0cd28 1632 else if (pt->m_type == CONTROL_POINT_DIAGONAL && (keys & KEY_SHIFT))
0fc1a713
JS
1633 new_height = bound_y*(new_width/bound_x);
1634
2bb0cd28 1635 if (this->GetFixedWidth())
0fc1a713
JS
1636 new_width = bound_x;
1637
2bb0cd28 1638 if (this->GetFixedHeight())
0fc1a713
JS
1639 new_height = bound_y;
1640
2bb0cd28
JS
1641 pt->controlPointDragEndWidth = new_width;
1642 pt->controlPointDragEndHeight = new_height;
1643 this->GetEventHandler()->OnDrawOutline(dc, this->GetX(), this->GetY(),
0fc1a713
JS
1644 new_width, new_height);
1645 }
1646 else
1647 {
1648 // Don't maintain the same centre point!
42cfaf8c
JS
1649 double newX1 = wxMin(pt->controlPointDragStartX, x);
1650 double newY1 = wxMin(pt->controlPointDragStartY, y);
1651 double newX2 = wxMax(pt->controlPointDragStartX, x);
1652 double newY2 = wxMax(pt->controlPointDragStartY, y);
2bb0cd28 1653 if (pt->m_type == CONTROL_POINT_HORIZONTAL)
0fc1a713 1654 {
2bb0cd28
JS
1655 newY1 = pt->controlPointDragStartY;
1656 newY2 = newY1 + pt->controlPointDragStartHeight;
0fc1a713 1657 }
2bb0cd28 1658 else if (pt->m_type == CONTROL_POINT_VERTICAL)
0fc1a713 1659 {
2bb0cd28
JS
1660 newX1 = pt->controlPointDragStartX;
1661 newX2 = newX1 + pt->controlPointDragStartWidth;
0fc1a713 1662 }
2bb0cd28 1663 else if (pt->m_type == CONTROL_POINT_DIAGONAL && (keys & KEY_SHIFT))
0fc1a713 1664 {
42cfaf8c 1665 double newH = (double)((newX2 - newX1)*(pt->controlPointDragStartHeight/pt->controlPointDragStartWidth));
2bb0cd28 1666 if (pt->GetY() > pt->controlPointDragStartY)
42cfaf8c 1667 newY2 = (double)(newY1 + newH);
0fc1a713 1668 else
42cfaf8c 1669 newY1 = (double)(newY2 - newH);
0fc1a713 1670 }
42cfaf8c
JS
1671 double newWidth = (double)(newX2 - newX1);
1672 double newHeight = (double)(newY2 - newY1);
0fc1a713 1673
42cfaf8c
JS
1674 pt->controlPointDragPosX = (double)(newX1 + (newWidth/2.0));
1675 pt->controlPointDragPosY = (double)(newY1 + (newHeight/2.0));
2bb0cd28 1676 if (this->GetFixedWidth())
0fc1a713
JS
1677 newWidth = bound_x;
1678
2bb0cd28 1679 if (this->GetFixedHeight())
0fc1a713
JS
1680 newHeight = bound_y;
1681
2bb0cd28
JS
1682 pt->controlPointDragEndWidth = newWidth;
1683 pt->controlPointDragEndHeight = newHeight;
1684 this->GetEventHandler()->OnDrawOutline(dc, pt->controlPointDragPosX, pt->controlPointDragPosY, newWidth, newHeight);
0fc1a713
JS
1685 }
1686}
1687
42cfaf8c 1688void wxShape::OnSizingEndDragLeft(wxControlPoint* pt, double x, double y, int keys, int attachment)
0fc1a713
JS
1689{
1690 wxClientDC dc(GetCanvas());
1691 GetCanvas()->PrepareDC(dc);
1692
1693 m_canvas->ReleaseMouse();
1694 dc.SetLogicalFunction(wxCOPY);
2bb0cd28
JS
1695 this->Recompute();
1696 this->ResetControlPoints();
0fc1a713 1697
2e5ed787
JS
1698 this->Erase(dc);
1699/*
2bb0cd28
JS
1700 if (!pt->m_eraseObject)
1701 this->Show(FALSE);
2e5ed787 1702*/
0fc1a713 1703
2bb0cd28 1704 this->SetSize(pt->controlPointDragEndWidth, pt->controlPointDragEndHeight);
0fc1a713
JS
1705
1706 // The next operation could destroy this control point (it does for label objects,
1707 // via formatting the text), so save all values we're going to use, or
1708 // we'll be accessing garbage.
2bb0cd28 1709 wxShape *theObject = this;
0fc1a713 1710 wxShapeCanvas *theCanvas = m_canvas;
2bb0cd28 1711 bool eraseIt = pt->m_eraseObject;
0fc1a713
JS
1712
1713 if (theObject->GetCentreResize())
1714 theObject->Move(dc, theObject->GetX(), theObject->GetY());
1715 else
2bb0cd28 1716 theObject->Move(dc, pt->controlPointDragPosX, pt->controlPointDragPosY);
0fc1a713 1717
2e5ed787 1718/*
0fc1a713
JS
1719 if (!eraseIt)
1720 theObject->Show(TRUE);
2e5ed787 1721*/
0fc1a713
JS
1722
1723 // Recursively redraw links if we have a composite.
1724 if (theObject->GetChildren().Number() > 0)
1725 theObject->DrawLinks(dc, -1, TRUE);
1726
42cfaf8c 1727 double width, height;
0fc1a713
JS
1728 theObject->GetBoundingBoxMax(&width, &height);
1729 theObject->GetEventHandler()->OnEndSize(width, height);
1730
1731 if (!theCanvas->GetQuickEditMode() && eraseIt) theCanvas->Redraw(dc);
1732}
1733
0fc1a713
JS
1734
1735
1736// Polygon control points
1737
1738IMPLEMENT_DYNAMIC_CLASS(wxPolygonControlPoint, wxControlPoint)
1739
42cfaf8c
JS
1740wxPolygonControlPoint::wxPolygonControlPoint(wxShapeCanvas *theCanvas, wxShape *object, double size,
1741 wxRealPoint *vertex, double the_xoffset, double the_yoffset):
0fc1a713
JS
1742 wxControlPoint(theCanvas, object, size, the_xoffset, the_yoffset, 0)
1743{
1744 m_polygonVertex = vertex;
2bb0cd28 1745 m_originalDistance = 0.0;
0fc1a713
JS
1746}
1747
1748wxPolygonControlPoint::~wxPolygonControlPoint()
1749{
1750}
1751
34138703 1752// Calculate what new size would be, at end of resize
42cfaf8c 1753void wxPolygonControlPoint::CalculateNewSize(double x, double y)
34138703 1754{
42cfaf8c
JS
1755 double bound_x;
1756 double bound_y;
34138703
JS
1757 GetShape()->GetBoundingBoxMin(&bound_x, &bound_y);
1758
42cfaf8c 1759 double dist = (double)sqrt((x - m_shape->GetX())*(x - m_shape->GetX()) +
34138703
JS
1760 (y - m_shape->GetY())*(y - m_shape->GetY()));
1761
42cfaf8c
JS
1762 m_newSize.x = (double)(dist/this->m_originalDistance)*this->m_originalSize.x;
1763 m_newSize.y = (double)(dist/this->m_originalDistance)*this->m_originalSize.y;
34138703
JS
1764}
1765
1766
0fc1a713 1767// Implement resizing polygon or moving the vertex.
42cfaf8c 1768void wxPolygonControlPoint::OnDragLeft(bool draw, double x, double y, int keys, int attachment)
0fc1a713 1769{
2bb0cd28
JS
1770 m_shape->GetEventHandler()->OnSizingDragLeft(this, draw, x, y, keys, attachment);
1771}
1772
42cfaf8c 1773void wxPolygonControlPoint::OnBeginDragLeft(double x, double y, int keys, int attachment)
2bb0cd28
JS
1774{
1775 m_shape->GetEventHandler()->OnSizingBeginDragLeft(this, x, y, keys, attachment);
1776}
1777
42cfaf8c 1778void wxPolygonControlPoint::OnEndDragLeft(double x, double y, int keys, int attachment)
2bb0cd28
JS
1779{
1780 m_shape->GetEventHandler()->OnSizingEndDragLeft(this, x, y, keys, attachment);
1781}
1782
1783// Control points ('handles') redirect control to the actual shape, to make it easier
1784// to override sizing behaviour.
42cfaf8c 1785void wxPolygonShape::OnSizingDragLeft(wxControlPoint* pt, bool draw, double x, double y, int keys, int attachment)
2bb0cd28
JS
1786{
1787 wxPolygonControlPoint* ppt = (wxPolygonControlPoint*) pt;
1788
0fc1a713
JS
1789 wxClientDC dc(GetCanvas());
1790 GetCanvas()->PrepareDC(dc);
1791
1792 dc.SetLogicalFunction(wxXOR);
1793
1794 wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
1795 dc.SetPen(dottedPen);
1796 dc.SetBrush((* wxTRANSPARENT_BRUSH));
1797
34138703 1798 if (0) // keys & KEY_CTRL)
0fc1a713 1799 {
34138703
JS
1800 // TODO: mend this code. Currently we rely on altering the
1801 // actual points, but we should assume we're not, as per
1802 // the normal sizing case.
0fc1a713
JS
1803 m_canvas->Snap(&x, &y);
1804
1805 // Move point
2bb0cd28
JS
1806 ppt->m_polygonVertex->x = x - this->GetX();
1807 ppt->m_polygonVertex->y = y - this->GetY();
1808 ppt->SetX(x);
1809 ppt->SetY(y);
1810 ((wxPolygonShape *)this)->CalculateBoundingBox();
1811 ((wxPolygonShape *)this)->CalculatePolygonCentre();
0fc1a713
JS
1812 }
1813 else
1814 {
34138703 1815 ppt->CalculateNewSize(x, y);
0fc1a713 1816 }
34138703
JS
1817
1818 this->GetEventHandler()->OnDrawOutline(dc, this->GetX(), this->GetY(),
1819 ppt->GetNewSize().x, ppt->GetNewSize().y);
0fc1a713
JS
1820}
1821
42cfaf8c 1822void wxPolygonShape::OnSizingBeginDragLeft(wxControlPoint* pt, double x, double y, int keys, int attachment)
0fc1a713 1823{
2bb0cd28
JS
1824 wxPolygonControlPoint* ppt = (wxPolygonControlPoint*) pt;
1825
0fc1a713
JS
1826 wxClientDC dc(GetCanvas());
1827 GetCanvas()->PrepareDC(dc);
1828
2bb0cd28 1829 this->Erase(dc);
0fc1a713
JS
1830
1831 dc.SetLogicalFunction(wxXOR);
1832
42cfaf8c
JS
1833 double bound_x;
1834 double bound_y;
2bb0cd28 1835 this->GetBoundingBoxMin(&bound_x, &bound_y);
0fc1a713 1836
42cfaf8c 1837 double dist = (double)sqrt((x - this->GetX())*(x - this->GetX()) +
2bb0cd28 1838 (y - this->GetY())*(y - this->GetY()));
2bb0cd28
JS
1839 ppt->m_originalDistance = dist;
1840 ppt->m_originalSize.x = bound_x;
1841 ppt->m_originalSize.y = bound_y;
0fc1a713 1842
42cfaf8c 1843 if (ppt->m_originalDistance == 0.0) ppt->m_originalDistance = (double) 0.0001;
0fc1a713
JS
1844
1845 wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
1846 dc.SetPen(dottedPen);
1847 dc.SetBrush((* wxTRANSPARENT_BRUSH));
1848
34138703 1849 if (0) // keys & KEY_CTRL)
0fc1a713 1850 {
34138703
JS
1851 // TODO: mend this code. Currently we rely on altering the
1852 // actual points, but we should assume we're not, as per
1853 // the normal sizing case.
0fc1a713
JS
1854 m_canvas->Snap(&x, &y);
1855
1856 // Move point
2bb0cd28
JS
1857 ppt->m_polygonVertex->x = x - this->GetX();
1858 ppt->m_polygonVertex->y = y - this->GetY();
1859 ppt->SetX(x);
1860 ppt->SetY(y);
1861 ((wxPolygonShape *)this)->CalculateBoundingBox();
1862 ((wxPolygonShape *)this)->CalculatePolygonCentre();
0fc1a713
JS
1863 }
1864 else
1865 {
34138703 1866 ppt->CalculateNewSize(x, y);
0fc1a713
JS
1867 }
1868
34138703
JS
1869 this->GetEventHandler()->OnDrawOutline(dc, this->GetX(), this->GetY(),
1870 ppt->GetNewSize().x, ppt->GetNewSize().y);
0fc1a713
JS
1871
1872 m_canvas->CaptureMouse();
1873}
1874
42cfaf8c 1875void wxPolygonShape::OnSizingEndDragLeft(wxControlPoint* pt, double x, double y, int keys, int attachment)
0fc1a713 1876{
34138703
JS
1877 wxPolygonControlPoint* ppt = (wxPolygonControlPoint*) pt;
1878
0fc1a713
JS
1879 wxClientDC dc(GetCanvas());
1880 GetCanvas()->PrepareDC(dc);
1881
1882 m_canvas->ReleaseMouse();
1883 dc.SetLogicalFunction(wxCOPY);
1884
1885 // If we're changing shape, must reset the original points
1886 if (keys & KEY_CTRL)
1887 {
2bb0cd28
JS
1888 ((wxPolygonShape *)this)->CalculateBoundingBox();
1889 ((wxPolygonShape *)this)->UpdateOriginalPoints();
0fc1a713 1890 }
34138703
JS
1891 else
1892 {
1893 SetSize(ppt->GetNewSize().x, ppt->GetNewSize().y);
1894 }
0fc1a713 1895
2bb0cd28
JS
1896 ((wxPolygonShape *)this)->CalculateBoundingBox();
1897 ((wxPolygonShape *)this)->CalculatePolygonCentre();
0fc1a713 1898
2bb0cd28
JS
1899 this->Recompute();
1900 this->ResetControlPoints();
1901 this->Move(dc, this->GetX(), this->GetY());
0fc1a713
JS
1902 if (!m_canvas->GetQuickEditMode()) m_canvas->Redraw(dc);
1903}
1904
0fc1a713
JS
1905/*
1906 * Object region
1907 *
1908 */
1909IMPLEMENT_DYNAMIC_CLASS(wxShapeRegion, wxObject)
1910
1911wxShapeRegion::wxShapeRegion()
1912{
1913 m_regionText = "";
1914 m_font = g_oglNormalFont;
1915 m_minHeight = 5.0;
1916 m_minWidth = 5.0;
1917 m_width = 0.0;
1918 m_height = 0.0;
1919 m_x = 0.0;
1920 m_y = 0.0;
1921
1922 m_regionProportionX = -1.0;
1923 m_regionProportionY = -1.0;
1924 m_formatMode = FORMAT_CENTRE_HORIZ | FORMAT_CENTRE_VERT;
1925 m_regionName = "";
1926 m_textColour = "BLACK";
1927 m_penColour = "BLACK";
1928 m_penStyle = wxSOLID;
1929 m_actualColourObject = NULL;
1930 m_actualPenObject = NULL;
1931}
1932
1933wxShapeRegion::wxShapeRegion(wxShapeRegion& region)
1934{
1935 m_regionText = region.m_regionText;
1936 m_regionName = region.m_regionName;
1937 m_textColour = region.m_textColour;
1938
1939 m_font = region.m_font;
1940 m_minHeight = region.m_minHeight;
1941 m_minWidth = region.m_minWidth;
1942 m_width = region.m_width;
1943 m_height = region.m_height;
1944 m_x = region.m_x;
1945 m_y = region.m_y;
1946
1947 m_regionProportionX = region.m_regionProportionX;
1948 m_regionProportionY = region.m_regionProportionY;
1949 m_formatMode = region.m_formatMode;
1950 m_actualColourObject = NULL;
1951 m_actualPenObject = NULL;
1952 m_penStyle = region.m_penStyle;
1953 m_penColour = region.m_penColour;
1954
1955 ClearText();
1956 wxNode *node = region.m_formattedText.First();
1957 while (node)
1958 {
1959 wxShapeTextLine *line = (wxShapeTextLine *)node->Data();
1960 wxShapeTextLine *new_line =
1961 new wxShapeTextLine(line->GetX(), line->GetY(), line->GetText());
1962 m_formattedText.Append(new_line);
1963 node = node->Next();
1964 }
1965}
1966
1967wxShapeRegion::~wxShapeRegion()
1968{
1969 ClearText();
1970}
1971
1972void wxShapeRegion::ClearText()
1973{
1974 wxNode *node = m_formattedText.First();
1975 while (node)
1976 {
1977 wxShapeTextLine *line = (wxShapeTextLine *)node->Data();
1978 wxNode *next = node->Next();
1979 delete line;
1980 delete node;
1981 node = next;
1982 }
1983}
1984
1985void wxShapeRegion::SetFont(wxFont *f)
1986{
1987 m_font = f;
1988}
1989
42cfaf8c 1990void wxShapeRegion::SetMinSize(double w, double h)
0fc1a713
JS
1991{
1992 m_minWidth = w;
1993 m_minHeight = h;
1994}
1995
42cfaf8c 1996void wxShapeRegion::SetSize(double w, double h)
0fc1a713
JS
1997{
1998 m_width = w;
1999 m_height = h;
2000}
2001
42cfaf8c 2002void wxShapeRegion::SetPosition(double xp, double yp)
0fc1a713
JS
2003{
2004 m_x = xp;
2005 m_y = yp;
2006}
2007
42cfaf8c 2008void wxShapeRegion::SetProportions(double xp, double yp)
0fc1a713
JS
2009{
2010 m_regionProportionX = xp;
2011 m_regionProportionY = yp;
2012}
2013
2014void wxShapeRegion::SetFormatMode(int mode)
2015{
2016 m_formatMode = mode;
2017}
2018
2019void wxShapeRegion::SetColour(const wxString& col)
2020{
2021 m_textColour = col;
2022 m_actualColourObject = NULL;
2023}
2024
2025wxColour *wxShapeRegion::GetActualColourObject()
2026{
2027 if (!m_actualColourObject)
2028 m_actualColourObject = wxTheColourDatabase->FindColour(GetColour());
2029 if (!m_actualColourObject)
2030 m_actualColourObject = wxBLACK;
2031 return m_actualColourObject;
2032}
2033
2034void wxShapeRegion::SetPenColour(const wxString& col)
2035{
2036 m_penColour = col;
2037 m_actualPenObject = NULL;
2038}
2039
2040// Returns NULL if the pen is invisible
2041// (different to pen being transparent; indicates that
2042// region boundary should not be drawn.)
2043wxPen *wxShapeRegion::GetActualPen()
2044{
2045 if (m_actualPenObject)
2046 return m_actualPenObject;
2047
2048 if (!m_penColour) return NULL;
2049 if (m_penColour == "Invisible")
2050 return NULL;
2051 m_actualPenObject = wxThePenList->FindOrCreatePen(m_penColour, 1, m_penStyle);
2052 return m_actualPenObject;
2053}
2054
2055