]> git.saurik.com Git - wxWidgets.git/blame - utils/ogl/src/basic2.cpp
spurious error messages from wxRegKey::HasValue() suppressed
[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.
128void wxPolygonShape::GetBoundingBoxMin(float *width, float *height)
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
137 float left = 10000;
138 float right = -10000;
139 float top = 10000;
140 float bottom = -10000;
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{
165 float left = 10000;
166 float right = -10000;
167 float top = 10000;
168 float bottom = -10000;
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 }
182 float bwidth = right - left;
183 float bheight = bottom - top;
184
185 float newCentreX = (float)(left + (bwidth/2.0));
186 float newCentreY = (float)(top + (bheight/2.0));
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
200bool PolylineHitTest(float n, float xvec[], float yvec[],
201 float x1, float y1, float x2, float y2)
202{
203 bool isAHit = FALSE;
204 int i;
205 float lastx = xvec[0];
206 float lasty = yvec[0];
207
208 float min_ratio = 1.0;
209 float line_ratio;
210 float other_ratio;
211
212// char buf[300];
213 for (i = 1; i < n; i++)
214 {
215 check_line_intersection(x1, y1, x2, y2, lastx, lasty, xvec[i], yvec[i],
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
228 // Do last (implicit) line if last and first floats are not identical
229 if (!(xvec[0] == lastx && yvec[0] == lasty))
230 {
231 check_line_intersection(x1, y1, x2, y2, lastx, lasty, xvec[0], yvec[0],
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
245bool wxPolygonShape::HitTest(float x, float y, int *attachment, float *distance)
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.
250 float endPointsX[4];
251 float endPointsY[4];
252 // North
253 endPointsX[0] = x;
254 endPointsY[0] = (float)(y - 1000.0);
255 // East
256 endPointsX[1] = (float)(x + 1000.0);
257 endPointsY[1] = y;
258 // South
259 endPointsX[2] = x;
260 endPointsY[2] = (float)(y + 1000.0);
261 // West
262 endPointsX[3] = (float)(x - 1000.0);
263 endPointsY[3] = y;
264
265 // Store polygon points in an array
266 int np = m_points->Number();
267 float *xpoints = new float[np];
268 float *ypoints = new float[np];
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();
306 float nearest = 999999.0;
307
308 for (i = 0; i < n; i++)
309 {
310 float xp, yp;
311 if (GetAttachmentPosition(i, &xp, &yp))
312 {
313 float l = (float)sqrt(((xp - x) * (xp - x)) +
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.
329void wxPolygonShape::SetSize(float new_width, float new_height, bool recursive)
330{
331 SetAttachmentSize(new_width, new_height);
332
333 // Multiply all points by proportion of new size to old size
334 float x_proportion = (float)(fabs(new_width/m_originalWidth));
335 float y_proportion = (float)(fabs(new_height/m_originalHeight));
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();
352 m_boundWidth = (float)fabs(new_width);
353 m_boundHeight = (float)fabs(new_height);
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
396 float x = (float)((secondPoint->x - firstPoint->x)/2.0 + firstPoint->x);
397 float y = (float)((secondPoint->y - firstPoint->y)/2.0 + firstPoint->y);
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)
432bool wxPolygonShape::GetPerimeterPoint(float x1, float y1,
433 float x2, float y2,
434 float *x3, float *y3)
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 --
440 // find_end_for_polyline can't cope with this (the arrow
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
469 float *xpoints = new float[n];
470 float *ypoints = new float[n];
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 }
482/*
483 wxRealPoint *point = (wxRealPoint *)m_points->First()->Data();
484 xpoints[i] = point->x + m_xpos;
485 ypoints[i] = point->y + m_ypos;
486*/
487
488 find_end_for_polyline(n, xpoints, ypoints,
489 x1, y1, x2, y2, x3, y3);
490
491 delete xpoints;
492 delete ypoints;
493
494 return TRUE;
495}
496
497void wxPolygonShape::OnDraw(wxDC& dc)
498{
499 int n = m_points->Number();
500 wxPoint *intPoints = new wxPoint[n];
501 int i;
502 for (i = 0; i < n; i++)
503 {
504 wxRealPoint* point = (wxRealPoint*) m_points->Nth(i)->Data();
505 intPoints[i].x = (int) point->x;
506 intPoints[i].y = (int) point->y;
507 }
508
509 if (m_shadowMode != SHADOW_NONE)
510 {
511 if (m_shadowBrush)
512 dc.SetBrush(m_shadowBrush);
513 dc.SetPen(transparent_pen);
514
515 dc.DrawPolygon(n, intPoints, m_xpos + m_shadowOffsetX, m_ypos + m_shadowOffsetY);
516 }
517
518 if (m_pen)
519 {
520 if (m_pen->GetWidth() == 0)
521 dc.SetPen(transparent_pen);
522 else
523 dc.SetPen(m_pen);
524 }
525 if (m_brush)
526 dc.SetBrush(m_brush);
527 dc.DrawPolygon(n, intPoints, m_xpos, m_ypos);
528
529 delete[] intPoints;
530}
531
532void wxPolygonShape::OnDrawOutline(wxDC& dc, float x, float y, float w, float h)
533{
534 dc.SetBrush(wxTRANSPARENT_BRUSH);
34138703
JS
535 // Multiply all points by proportion of new size to old size
536 float x_proportion = (float)(fabs(w/m_originalWidth));
537 float y_proportion = (float)(fabs(h/m_originalHeight));
0fc1a713 538
34138703 539 int n = m_originalPoints->Number();
0fc1a713
JS
540 wxPoint *intPoints = new wxPoint[n];
541 int i;
542 for (i = 0; i < n; i++)
543 {
34138703
JS
544 wxRealPoint* point = (wxRealPoint*) m_originalPoints->Nth(i)->Data();
545 intPoints[i].x = (int) (x_proportion * point->x);
546 intPoints[i].y = (int) (y_proportion * point->y);
0fc1a713
JS
547 }
548 dc.DrawPolygon(n, intPoints, x, y);
5de76427 549 delete[] intPoints;
0fc1a713
JS
550}
551
552// Make as many control points as there are vertices.
553void wxPolygonShape::MakeControlPoints()
554{
555 wxNode *node = m_points->First();
556 while (node)
557 {
558 wxRealPoint *point = (wxRealPoint *)node->Data();
559 wxPolygonControlPoint *control = new wxPolygonControlPoint(m_canvas, this, CONTROL_POINT_SIZE,
560 point, point->x, point->y);
561 m_canvas->AddShape(control);
562 m_controlPoints.Append(control);
563 node = node->Next();
564 }
565
566/*
567 float maxX, maxY, minX, minY;
568
569 GetBoundingBoxMax(&maxX, &maxY);
570 GetBoundingBoxMin(&minX, &minY);
571
572 float widthMin = (float)(minX + CONTROL_POINT_SIZE + 2);
573 float heightMin = (float)(minY + CONTROL_POINT_SIZE + 2);
574
575 // Offsets from main object
576 float top = (float)(- (heightMin / 2.0));
577 float bottom = (float)(heightMin / 2.0 + (maxY - minY));
578 float left = (float)(- (widthMin / 2.0));
579 float right = (float)(widthMin / 2.0 + (maxX - minX));
580
581 wxControlPoint *control = new wxControlPoint(m_canvas, this, CONTROL_POINT_SIZE, left, top,
582 CONTROL_POINT_DIAGONAL);
583 m_canvas->AddShape(control);
584 m_controlPoints.Append(control);
585
586 control = new wxControlPoint(m_canvas, this, CONTROL_POINT_SIZE, 0, top,
587 CONTROL_POINT_VERTICAL);
588 m_canvas->AddShape(control);
589 m_controlPoints.Append(control);
590
591 control = new wxControlPoint(m_canvas, this, CONTROL_POINT_SIZE, right, top,
592 CONTROL_POINT_DIAGONAL);
593 m_canvas->AddShape(control);
594 m_controlPoints.Append(control);
595
596 control = new wxControlPoint(m_canvas, this, CONTROL_POINT_SIZE, right, 0,
597 CONTROL_POINT_HORIZONTAL);
598 m_canvas->AddShape(control);
599 m_controlPoints.Append(control);
600
601 control = new wxControlPoint(m_canvas, this, CONTROL_POINT_SIZE, right, bottom,
602 CONTROL_POINT_DIAGONAL);
603 m_canvas->AddShape(control);
604 m_controlPoints.Append(control);
605
606 control = new wxControlPoint(m_canvas, this, CONTROL_POINT_SIZE, 0, bottom,
607 CONTROL_POINT_VERTICAL);
608 m_canvas->AddShape(control);
609 m_controlPoints.Append(control);
610
611 control = new wxControlPoint(m_canvas, this, CONTROL_POINT_SIZE, left, bottom,
612 CONTROL_POINT_DIAGONAL);
613 m_canvas->AddShape(control);
614 m_controlPoints.Append(control);
615
616 control = new wxControlPoint(m_canvas, this, CONTROL_POINT_SIZE, left, 0,
617 CONTROL_POINT_HORIZONTAL);
618 m_canvas->AddShape(control);
619 m_controlPoints.Append(control);
620*/
621}
622
623void wxPolygonShape::ResetControlPoints()
624{
625 wxNode *node = m_points->First();
626 wxNode *controlPointNode = m_controlPoints.First();
627 while (node && controlPointNode)
628 {
629 wxRealPoint *point = (wxRealPoint *)node->Data();
630 wxPolygonControlPoint *controlPoint = (wxPolygonControlPoint *)controlPointNode->Data();
631
632 controlPoint->m_xoffset = point->x;
633 controlPoint->m_yoffset = point->y;
634 controlPoint->m_polygonVertex = point;
635
636 node = node->Next();
637 controlPointNode = controlPointNode->Next();
638 }
639/*
640
641 if (m_controlPoints.Number() < 1)
642 return;
643
644 float maxX, maxY, minX, minY;
645
646 GetBoundingBoxMax(&maxX, &maxY);
647 GetBoundingBoxMin(&minX, &minY);
648
649 float widthMin = (float)(minX + CONTROL_POINT_SIZE + 2);
650 float heightMin = (float)(minY + CONTROL_POINT_SIZE + 2);
651
652 // Offsets from main object
653 float top = (float)(- (heightMin / 2.0));
654 float bottom = (float)(heightMin / 2.0 + (maxY - minY));
655 float left = (float)(- (widthMin / 2.0));
656 float right = (float)(widthMin / 2.0 + (maxX - minX));
657
658 wxNode *node = m_controlPoints.First();
659 wxControlPoint *control = (wxControlPoint *)node->Data();
660 control->xoffset = left; control->yoffset = top;
661
662 node = node->Next(); control = (wxControlPoint *)node->Data();
663 control->xoffset = 0; control->yoffset = top;
664
665 node = node->Next(); control = (wxControlPoint *)node->Data();
666 control->xoffset = right; control->yoffset = top;
667
668 node = node->Next(); control = (wxControlPoint *)node->Data();
669 control->xoffset = right; control->yoffset = 0;
670
671 node = node->Next(); control = (wxControlPoint *)node->Data();
672 control->xoffset = right; control->yoffset = bottom;
673
674 node = node->Next(); control = (wxControlPoint *)node->Data();
675 control->xoffset = 0; control->yoffset = bottom;
676
677 node = node->Next(); control = (wxControlPoint *)node->Data();
678 control->xoffset = left; control->yoffset = bottom;
679
680 node = node->Next(); control = (wxControlPoint *)node->Data();
681 control->xoffset = left; control->yoffset = 0;
682*/
683}
684
685
686#ifdef PROLOGIO
687void wxPolygonShape::WritePrologAttributes(wxExpr *clause)
688{
689 wxShape::WritePrologAttributes(clause);
690
691 clause->AddAttributeValue("x", m_xpos);
692 clause->AddAttributeValue("y", m_ypos);
693
694 // Make a list of lists for the coordinates
695 wxExpr *list = new wxExpr(PrologList);
696 wxNode *node = m_points->First();
697 while (node)
698 {
699 wxRealPoint *point = (wxRealPoint *)node->Data();
700 wxExpr *point_list = new wxExpr(PrologList);
701 wxExpr *x_expr = new wxExpr((float)point->x);
702 wxExpr *y_expr = new wxExpr((float)point->y);
703
704 point_list->Append(x_expr);
705 point_list->Append(y_expr);
706 list->Append(point_list);
707
708 node = node->Next();
709 }
710 clause->AddAttributeValue("points", list);
711
712 // Save the original (unscaled) points
713 list = new wxExpr(PrologList);
714 node = m_originalPoints->First();
715 while (node)
716 {
717 wxRealPoint *point = (wxRealPoint *)node->Data();
718 wxExpr *point_list = new wxExpr(PrologList);
719 wxExpr *x_expr = new wxExpr((float) point->x);
720 wxExpr *y_expr = new wxExpr((float) point->y);
721 point_list->Append(x_expr);
722 point_list->Append(y_expr);
723 list->Append(point_list);
724
725 node = node->Next();
726 }
727 clause->AddAttributeValue("m_originalPoints", list);
728}
729
730void wxPolygonShape::ReadPrologAttributes(wxExpr *clause)
731{
732 wxShape::ReadPrologAttributes(clause);
733
734 // Read a list of lists
735 m_points = new wxList;
736 m_originalPoints = new wxList;
737
738 wxExpr *points_list = NULL;
739 clause->AssignAttributeValue("points", &points_list);
740
741 // If no points_list, don't crash!! Assume a diamond instead.
742 float the_height = 100.0;
743 float the_width = 100.0;
744 if (!points_list)
745 {
746 wxRealPoint *point = new wxRealPoint(0.0, (-the_height/2));
747 m_points->Append((wxObject*) point);
748
749 point = new wxRealPoint((the_width/2), 0.0);
750 m_points->Append((wxObject*) point);
751
752 point = new wxRealPoint(0.0, (the_height/2));
753 m_points->Append((wxObject*) point);
754
755 point = new wxRealPoint((-the_width/2), 0.0);
756 m_points->Append((wxObject*) point);
757
758 point = new wxRealPoint(0.0, (-the_height/2));
759 m_points->Append((wxObject*) point);
760 }
761 else
762 {
763 wxExpr *node = points_list->value.first;
764
765 while (node)
766 {
767 wxExpr *xexpr = node->value.first;
768 long x = xexpr->IntegerValue();
769
770 wxExpr *yexpr = xexpr->next;
771 long y = yexpr->IntegerValue();
772
773 wxRealPoint *point = new wxRealPoint((float)x, (float)y);
774 m_points->Append((wxObject*) point);
775
776 node = node->next;
777 }
778 }
779
780 points_list = NULL;
781 clause->AssignAttributeValue("m_originalPoints", &points_list);
782
783 // If no points_list, don't crash!! Assume a diamond instead.
784 if (!points_list)
785 {
786 wxRealPoint *point = new wxRealPoint(0.0, (-the_height/2));
787 m_originalPoints->Append((wxObject*) point);
788
789 point = new wxRealPoint((the_width/2), 0.0);
790 m_originalPoints->Append((wxObject*) point);
791
792 point = new wxRealPoint(0.0, (the_height/2));
793 m_originalPoints->Append((wxObject*) point);
794
795 point = new wxRealPoint((-the_width/2), 0.0);
796 m_originalPoints->Append((wxObject*) point);
797
798 point = new wxRealPoint(0.0, (-the_height/2));
799 m_originalPoints->Append((wxObject*) point);
800
801 m_originalWidth = the_width;
802 m_originalHeight = the_height;
803 }
804 else
805 {
806 wxExpr *node = points_list->value.first;
807 float min_x = 1000;
808 float min_y = 1000;
809 float max_x = -1000;
810 float max_y = -1000;
811 while (node)
812 {
813 wxExpr *xexpr = node->value.first;
814 long x = xexpr->IntegerValue();
815
816 wxExpr *yexpr = xexpr->next;
817 long y = yexpr->IntegerValue();
818
819 wxRealPoint *point = new wxRealPoint((float)x, (float)y);
820 m_originalPoints->Append((wxObject*) point);
821
822 if (x < min_x)
823 min_x = (float)x;
824 if (y < min_y)
825 min_y = (float)y;
826 if (x > max_x)
827 max_x = (float)x;
828 if (y > max_y)
829 max_y = (float)y;
830
831 node = node->next;
832 }
833 m_originalWidth = max_x - min_x;
834 m_originalHeight = max_y - min_y;
835 }
836
837 CalculateBoundingBox();
838}
839#endif
840
2bb0cd28 841void wxPolygonShape::Copy(wxShape& copy)
0fc1a713
JS
842{
843 wxShape::Copy(copy);
844
2bb0cd28 845 wxASSERT( copy.IsKindOf(CLASSINFO(wxPolygonShape)) );
0fc1a713 846
2bb0cd28 847 wxPolygonShape& polyCopy = (wxPolygonShape&) copy;
0fc1a713 848
5de76427 849 polyCopy.ClearPoints();
0fc1a713 850
2bb0cd28 851 polyCopy.m_points = new wxList;
2bb0cd28 852 polyCopy.m_originalPoints = new wxList;
0fc1a713
JS
853
854 wxNode *node = m_points->First();
855 while (node)
856 {
857 wxRealPoint *point = (wxRealPoint *)node->Data();
858 wxRealPoint *new_point = new wxRealPoint(point->x, point->y);
2bb0cd28 859 polyCopy.m_points->Append((wxObject*) new_point);
0fc1a713
JS
860 node = node->Next();
861 }
862 node = m_originalPoints->First();
863 while (node)
864 {
865 wxRealPoint *point = (wxRealPoint *)node->Data();
866 wxRealPoint *new_point = new wxRealPoint(point->x, point->y);
2bb0cd28 867 polyCopy.m_originalPoints->Append((wxObject*) new_point);
0fc1a713
JS
868 node = node->Next();
869 }
2bb0cd28
JS
870 polyCopy.m_boundWidth = m_boundWidth;
871 polyCopy.m_boundHeight = m_boundHeight;
872 polyCopy.m_originalWidth = m_originalWidth;
873 polyCopy.m_originalHeight = m_originalHeight;
0fc1a713
JS
874}
875
876int wxPolygonShape::GetNumberOfAttachments()
877{
878 int maxN = (m_points ? (m_points->Number() - 1) : 0);
879 wxNode *node = m_attachmentPoints.First();
880 while (node)
881 {
882 wxAttachmentPoint *point = (wxAttachmentPoint *)node->Data();
883 if (point->m_id > maxN)
884 maxN = point->m_id;
885 node = node->Next();
886 }
887 return maxN+1;;
888}
889
890bool wxPolygonShape::GetAttachmentPosition(int attachment, float *x, float *y,
891 int nth, int no_arcs, wxLineShape *line)
892{
893 if (m_attachmentMode && m_points && attachment < m_points->Number())
894 {
895 wxRealPoint *point = (wxRealPoint *)m_points->Nth(attachment)->Data();
896 *x = point->x + m_xpos;
897 *y = point->y + m_ypos;
898 return TRUE;
899 }
900 else
901 { return wxShape::GetAttachmentPosition(attachment, x, y, nth, no_arcs, line); }
902}
903
904bool wxPolygonShape::AttachmentIsValid(int attachment)
905{
906 if (!m_points)
907 return FALSE;
908
909 if ((attachment >= 0) && (attachment < m_points->Number()))
910 return TRUE;
911
912 wxNode *node = m_attachmentPoints.First();
913 while (node)
914 {
915 wxAttachmentPoint *point = (wxAttachmentPoint *)node->Data();
916 if (point->m_id == attachment)
917 return TRUE;
918 node = node->Next();
919 }
920 return FALSE;
921}
922
923// Rectangle object
924
925IMPLEMENT_DYNAMIC_CLASS(wxRectangleShape, wxShape)
926
927wxRectangleShape::wxRectangleShape(float w, float h)
928{
929 m_width = w; m_height = h; m_cornerRadius = 0.0;
930 SetDefaultRegionSize();
931}
932
933void wxRectangleShape::OnDraw(wxDC& dc)
934{
935 float x1 = (float)(m_xpos - m_width/2.0);
936 float y1 = (float)(m_ypos - m_height/2.0);
937
938 if (m_shadowMode != SHADOW_NONE)
939 {
940 if (m_shadowBrush)
941 dc.SetBrush(m_shadowBrush);
942 dc.SetPen(transparent_pen);
943
944 if (m_cornerRadius != 0.0)
945 dc.DrawRoundedRectangle(x1 + m_shadowOffsetX, y1 + m_shadowOffsetY,
946 m_width, m_height, m_cornerRadius);
947 else
948 dc.DrawRectangle(x1 + m_shadowOffsetX, y1 + m_shadowOffsetY, m_width, m_height);
949 }
950
951 if (m_pen)
952 {
953 if (m_pen->GetWidth() == 0)
954 dc.SetPen(transparent_pen);
955 else
956 dc.SetPen(m_pen);
957 }
958 if (m_brush)
959 dc.SetBrush(m_brush);
960
961 if (m_cornerRadius != 0.0)
962 dc.DrawRoundedRectangle(x1, y1, m_width, m_height, m_cornerRadius);
963 else
964 dc.DrawRectangle(x1, y1, m_width, m_height);
965}
966
967void wxRectangleShape::GetBoundingBoxMin(float *the_width, float *the_height)
968{
969 *the_width = m_width;
970 *the_height = m_height;
971}
972
973void wxRectangleShape::SetSize(float x, float y, bool recursive)
974{
975 SetAttachmentSize(x, y);
976 m_width = (float)wxMax(x, 1.0);
977 m_height = (float)wxMax(y, 1.0);
978 SetDefaultRegionSize();
979}
980
981void wxRectangleShape::SetCornerRadius(float rad)
982{
983 m_cornerRadius = rad;
984}
985
986// Assume (x1, y1) is centre of box (most generally, line end at box)
987bool wxRectangleShape::GetPerimeterPoint(float x1, float y1,
988 float x2, float y2,
989 float *x3, float *y3)
990{
991 float bound_x, bound_y;
992 GetBoundingBoxMax(&bound_x, &bound_y);
993 find_end_for_box(bound_x, bound_y, m_xpos, m_ypos, x2, y2, x3, y3);
994
995 return TRUE;
996}
997
998#ifdef PROLOGIO
999void wxRectangleShape::WritePrologAttributes(wxExpr *clause)
1000{
1001 wxShape::WritePrologAttributes(clause);
1002 clause->AddAttributeValue("x", m_xpos);
1003 clause->AddAttributeValue("y", m_ypos);
1004
1005 clause->AddAttributeValue("width", m_width);
1006 clause->AddAttributeValue("height", m_height);
1007 if (m_cornerRadius != 0.0)
1008 clause->AddAttributeValue("corner", m_cornerRadius);
1009}
1010
1011void wxRectangleShape::ReadPrologAttributes(wxExpr *clause)
1012{
1013 wxShape::ReadPrologAttributes(clause);
1014 clause->AssignAttributeValue("width", &m_width);
1015 clause->AssignAttributeValue("height", &m_height);
1016 clause->AssignAttributeValue("corner", &m_cornerRadius);
1017
1018 // In case we're reading an old file, set the region's size
1019 if (m_regions.Number() == 1)
1020 {
1021 wxShapeRegion *region = (wxShapeRegion *)m_regions.First()->Data();
1022 region->SetSize(m_width, m_height);
1023 }
1024}
1025#endif
1026
2bb0cd28 1027void wxRectangleShape::Copy(wxShape& copy)
0fc1a713
JS
1028{
1029 wxShape::Copy(copy);
0fc1a713 1030
2bb0cd28 1031 wxASSERT( copy.IsKindOf(CLASSINFO(wxRectangleShape)) );
0fc1a713 1032
2bb0cd28
JS
1033 wxRectangleShape& rectCopy = (wxRectangleShape&) copy;
1034 rectCopy.m_width = m_width;
1035 rectCopy.m_height = m_height;
1036 rectCopy.m_cornerRadius = m_cornerRadius;
1037}
0fc1a713
JS
1038
1039int wxRectangleShape::GetNumberOfAttachments()
1040{
1041 return wxShape::GetNumberOfAttachments();
1042}
1043
1044// There are 4 attachment points on a rectangle - 0 = top, 1 = right, 2 = bottom,
1045// 3 = left.
1046bool wxRectangleShape::GetAttachmentPosition(int attachment, float *x, float *y,
1047 int nth, int no_arcs, wxLineShape *line)
1048{
1049 if (m_attachmentMode)
1050 {
1051 float top = (float)(m_ypos + m_height/2.0);
1052 float bottom = (float)(m_ypos - m_height/2.0);
1053 float left = (float)(m_xpos - m_width/2.0);
1054 float right = (float)(m_xpos + m_width/2.0);
1055
1056 bool isEnd = (line && line->IsEnd(this));
1057
1058 switch (attachment)
1059 {
1060 case 0:
1061 {
1062 if (m_spaceAttachments)
1063 {
1064 if (line && (line->GetAlignmentType(isEnd) == LINE_ALIGNMENT_TO_NEXT_HANDLE))
1065 {
1066 // Align line according to the next handle along
1067 wxRealPoint *point = line->GetNextControlPoint(this);
1068 if (point->x < left)
1069 *x = left;
1070 else if (point->x > right)
1071 *x = right;
1072 else
1073 *x = point->x;
1074 }
1075 else
1076 *x = left + (nth + 1)*m_width/(no_arcs + 1);
1077 }
1078 else *x = m_xpos;
1079
1080 *y = bottom;
1081 break;
1082 }
1083 case 1:
1084 {
1085 *x = right;
1086 if (m_spaceAttachments)
1087 {
1088 if (line && (line->GetAlignmentType(isEnd) == LINE_ALIGNMENT_TO_NEXT_HANDLE))
1089 {
1090 // Align line according to the next handle along
1091 wxRealPoint *point = line->GetNextControlPoint(this);
1092 if (point->y < bottom)
1093 *y = bottom;
1094 else if (point->y > top)
1095 *y = top;
1096 else
1097 *y = point->y;
1098 }
1099 else
1100 *y = bottom + (nth + 1)*m_height/(no_arcs + 1);
1101 }
1102 else *y = m_ypos;
1103 break;
1104 }
1105 case 2:
1106 {
1107 if (m_spaceAttachments)
1108 {
1109 if (line && (line->GetAlignmentType(isEnd) == LINE_ALIGNMENT_TO_NEXT_HANDLE))
1110 {
1111 // Align line according to the next handle along
1112 wxRealPoint *point = line->GetNextControlPoint(this);
1113 if (point->x < left)
1114 *x = left;
1115 else if (point->x > right)
1116 *x = right;
1117 else
1118 *x = point->x;
1119 }
1120 else
1121 *x = left + (nth + 1)*m_width/(no_arcs + 1);
1122 }
1123 else *x = m_xpos;
1124 *y = top;
1125 break;
1126 }
1127 case 3:
1128 {
1129 *x = left;
1130 if (m_spaceAttachments)
1131 {
1132 if (line && (line->GetAlignmentType(isEnd) == LINE_ALIGNMENT_TO_NEXT_HANDLE))
1133 {
1134 // Align line according to the next handle along
1135 wxRealPoint *point = line->GetNextControlPoint(this);
1136 if (point->y < bottom)
1137 *y = bottom;
1138 else if (point->y > top)
1139 *y = top;
1140 else
1141 *y = point->y;
1142 }
1143 else
1144 *y = bottom + (nth + 1)*m_height/(no_arcs + 1);
1145 }
1146 else *y = m_ypos;
1147 break;
1148 }
1149 default:
1150 {
1151 return wxShape::GetAttachmentPosition(attachment, x, y, nth, no_arcs, line);
1152 break;
1153 }
1154 }
1155 return TRUE;
1156 }
1157 else
1158 { *x = m_xpos; *y = m_ypos; return TRUE; }
1159}
1160
1161// Text object (no box)
1162
1163IMPLEMENT_DYNAMIC_CLASS(wxTextShape, wxRectangleShape)
1164
1165wxTextShape::wxTextShape(float width, float height):
1166 wxRectangleShape(width, height)
1167{
1168}
1169
1170void wxTextShape::OnDraw(wxDC& dc)
1171{
1172}
1173
2bb0cd28 1174void wxTextShape::Copy(wxShape& copy)
0fc1a713
JS
1175{
1176 wxRectangleShape::Copy(copy);
1177}
1178
1179#ifdef PROLOGIO
1180void wxTextShape::WritePrologAttributes(wxExpr *clause)
1181{
1182 wxRectangleShape::WritePrologAttributes(clause);
1183}
1184#endif
1185
1186// Ellipse object
1187
1188IMPLEMENT_DYNAMIC_CLASS(wxEllipseShape, wxShape)
1189
1190wxEllipseShape::wxEllipseShape(float w, float h)
1191{
1192 m_width = w; m_height = h;
1193 SetDefaultRegionSize();
1194}
1195
1196void wxEllipseShape::GetBoundingBoxMin(float *w, float *h)
1197{
1198 *w = m_width; *h = m_height;
1199}
1200
1201bool wxEllipseShape::GetPerimeterPoint(float x1, float y1,
1202 float x2, float y2,
1203 float *x3, float *y3)
1204{
1205 float bound_x, bound_y;
1206 GetBoundingBoxMax(&bound_x, &bound_y);
1207
1208// find_end_for_box(bound_x, bound_y, m_xpos, m_ypos, x2, y2, x3, y3);
1209 draw_arc_to_ellipse(m_xpos, m_ypos, bound_x, bound_y, x2, y2, x1, y1, x3, y3);
1210
1211 return TRUE;
1212}
1213
1214void wxEllipseShape::OnDraw(wxDC& dc)
1215{
1216 if (m_shadowMode != SHADOW_NONE)
1217 {
1218 if (m_shadowBrush)
1219 dc.SetBrush(m_shadowBrush);
1220 dc.SetPen(transparent_pen);
1221 dc.DrawEllipse((m_xpos - GetWidth()/2) + m_shadowOffsetX,
1222 (m_ypos - GetHeight()/2) + m_shadowOffsetY,
1223 GetWidth(), GetHeight());
1224 }
1225
1226 if (m_pen)
1227 {
1228 if (m_pen->GetWidth() == 0)
1229 dc.SetPen(transparent_pen);
1230 else
1231 dc.SetPen(m_pen);
1232 }
1233 if (m_brush)
1234 dc.SetBrush(m_brush);
1235 dc.DrawEllipse((m_xpos - GetWidth()/2), (m_ypos - GetHeight()/2), GetWidth(), GetHeight());
1236}
1237
1238void wxEllipseShape::SetSize(float x, float y, bool recursive)
1239{
1240 SetAttachmentSize(x, y);
1241 m_width = x;
1242 m_height = y;
1243 SetDefaultRegionSize();
1244}
1245
1246#ifdef PROLOGIO
1247void wxEllipseShape::WritePrologAttributes(wxExpr *clause)
1248{
1249 wxShape::WritePrologAttributes(clause);
1250 clause->AddAttributeValue("x", m_xpos);
1251 clause->AddAttributeValue("y", m_ypos);
1252
1253 clause->AddAttributeValue("width", m_width);
1254 clause->AddAttributeValue("height", m_height);
1255}
1256
1257void wxEllipseShape::ReadPrologAttributes(wxExpr *clause)
1258{
1259 wxShape::ReadPrologAttributes(clause);
1260 clause->AssignAttributeValue("width", &m_width);
1261 clause->AssignAttributeValue("height", &m_height);
1262
1263 // In case we're reading an old file, set the region's size
1264 if (m_regions.Number() == 1)
1265 {
1266 wxShapeRegion *region = (wxShapeRegion *)m_regions.First()->Data();
1267 region->SetSize(m_width, m_height);
1268 }
1269}
1270#endif
1271
2bb0cd28 1272void wxEllipseShape::Copy(wxShape& copy)
0fc1a713
JS
1273{
1274 wxShape::Copy(copy);
1275
2bb0cd28 1276 wxASSERT( copy.IsKindOf(CLASSINFO(wxEllipseShape)) );
0fc1a713 1277
2bb0cd28
JS
1278 wxEllipseShape& ellipseCopy = (wxEllipseShape&) copy;
1279
1280 ellipseCopy.m_width = m_width;
1281 ellipseCopy.m_height = m_height;
0fc1a713
JS
1282}
1283
1284int wxEllipseShape::GetNumberOfAttachments()
1285{
1286 return wxShape::GetNumberOfAttachments();
1287}
1288
1289// There are 4 attachment points on an ellipse - 0 = top, 1 = right, 2 = bottom,
1290// 3 = left.
1291bool wxEllipseShape::GetAttachmentPosition(int attachment, float *x, float *y,
1292 int nth, int no_arcs, wxLineShape *line)
1293{
1294 if (m_attachmentMode)
1295 {
1296 float top = (float)(m_ypos + m_height/2.0);
1297 float bottom = (float)(m_ypos - m_height/2.0);
1298 float left = (float)(m_xpos - m_width/2.0);
1299 float right = (float)(m_xpos + m_width/2.0);
1300 switch (attachment)
1301 {
1302 case 0:
1303 {
1304 if (m_spaceAttachments)
1305 *x = left + (nth + 1)*m_width/(no_arcs + 1);
1306 else *x = m_xpos;
1307 *y = top;
1308 // We now have the point on the bounding box: but get the point on the ellipse
1309 // by imagining a vertical line from (*x, m_ypos - m_height- 500) to (*x, m_ypos) intersecting
1310 // the ellipse.
1311 draw_arc_to_ellipse(m_xpos, m_ypos, m_width, m_height, *x, (float)(m_ypos-m_height-500), *x, m_ypos, x, y);
1312 break;
1313 }
1314 case 1:
1315 {
1316 *x = right;
1317 if (m_spaceAttachments)
1318 *y = bottom + (nth + 1)*m_height/(no_arcs + 1);
1319 else *y = m_ypos;
1320 draw_arc_to_ellipse(m_xpos, m_ypos, m_width, m_height, (float)(m_xpos+m_width+500), *y, m_xpos, *y, x, y);
1321 break;
1322 }
1323 case 2:
1324 {
1325 if (m_spaceAttachments)
1326 *x = left + (nth + 1)*m_width/(no_arcs + 1);
1327 else *x = m_xpos;
1328 *y = bottom;
1329 draw_arc_to_ellipse(m_xpos, m_ypos, m_width, m_height, *x, (float)(m_ypos+m_height+500), *x, m_ypos, x, y);
1330 break;
1331 }
1332 case 3:
1333 {
1334 *x = left;
1335 if (m_spaceAttachments)
1336 *y = bottom + (nth + 1)*m_height/(no_arcs + 1);
1337 else *y = m_ypos;
1338 draw_arc_to_ellipse(m_xpos, m_ypos, m_width, m_height, (float)(m_xpos-m_width-500), *y, m_xpos, *y, x, y);
1339 break;
1340 }
1341 default:
1342 {
1343 return wxShape::GetAttachmentPosition(attachment, x, y, nth, no_arcs, line);
1344 break;
1345 }
1346 }
1347 return TRUE;
1348 }
1349 else
1350 { *x = m_xpos; *y = m_ypos; return TRUE; }
1351}
1352
1353
1354// Circle object
1355IMPLEMENT_DYNAMIC_CLASS(wxCircleShape, wxEllipseShape)
1356
1357wxCircleShape::wxCircleShape(float diameter):wxEllipseShape(diameter, diameter)
1358{
1359}
1360
2bb0cd28 1361void wxCircleShape::Copy(wxShape& copy)
0fc1a713
JS
1362{
1363 wxEllipseShape::Copy(copy);
1364}
1365
1366bool wxCircleShape::GetPerimeterPoint(float x1, float y1,
1367 float x2, float y2,
1368 float *x3, float *y3)
1369{
1370 find_end_for_circle(m_width/2,
1371 m_xpos, m_ypos, // Centre of circle
1372 x2, y2, // Other end of line
1373 x3, y3);
1374
1375 return TRUE;
1376}
1377
1378// Control points
1379
2bb0cd28
JS
1380float wxControlPoint::controlPointDragStartX = 0.0;
1381float wxControlPoint::controlPointDragStartY = 0.0;
1382float wxControlPoint::controlPointDragStartWidth = 0.0;
1383float wxControlPoint::controlPointDragStartHeight = 0.0;
1384float wxControlPoint::controlPointDragEndWidth = 0.0;
1385float wxControlPoint::controlPointDragEndHeight = 0.0;
1386float wxControlPoint::controlPointDragPosX = 0.0;
1387float wxControlPoint::controlPointDragPosY = 0.0;
1388
0fc1a713
JS
1389IMPLEMENT_DYNAMIC_CLASS(wxControlPoint, wxRectangleShape)
1390
1391wxControlPoint::wxControlPoint(wxShapeCanvas *theCanvas, wxShape *object, float size, float the_xoffset, float the_yoffset, int the_type):wxRectangleShape(size, size)
1392{
1393 m_canvas = theCanvas;
1394 m_shape = object;
1395 m_xoffset = the_xoffset;
1396 m_yoffset = the_yoffset;
1397 m_type = the_type;
1398 SetPen(black_foreground_pen);
1399 SetBrush(wxBLACK_BRUSH);
1400 m_oldCursor = NULL;
1401 m_visible = TRUE;
1402 m_eraseObject = TRUE;
1403}
1404
1405wxControlPoint::~wxControlPoint()
1406{
1407}
1408
1409// Don't even attempt to draw any text - waste of time!
1410void wxControlPoint::OnDrawContents(wxDC& dc)
1411{
1412}
1413
1414void wxControlPoint::OnDraw(wxDC& dc)
1415{
1416 m_xpos = m_shape->GetX() + m_xoffset;
1417 m_ypos = m_shape->GetY() + m_yoffset;
1418 wxRectangleShape::OnDraw(dc);
1419}
1420
1421void wxControlPoint::OnErase(wxDC& dc)
1422{
1423 wxRectangleShape::OnErase(dc);
1424}
1425
0fc1a713
JS
1426// Implement resizing of canvas object
1427void wxControlPoint::OnDragLeft(bool draw, float x, float y, int keys, int attachment)
2bb0cd28
JS
1428{
1429 m_shape->GetEventHandler()->OnSizingDragLeft(this, draw, x, y, keys, attachment);
1430}
1431
1432void wxControlPoint::OnBeginDragLeft(float x, float y, int keys, int attachment)
1433{
1434 m_shape->GetEventHandler()->OnSizingBeginDragLeft(this, x, y, keys, attachment);
1435}
1436
1437void wxControlPoint::OnEndDragLeft(float x, float y, int keys, int attachment)
1438{
1439 m_shape->GetEventHandler()->OnSizingEndDragLeft(this, x, y, keys, attachment);
1440}
1441
1442int wxControlPoint::GetNumberOfAttachments()
1443{
1444 return 1;
1445}
1446
1447bool wxControlPoint::GetAttachmentPosition(int attachment, float *x, float *y,
1448 int nth, int no_arcs, wxLineShape *line)
1449{
1450 *x = m_xpos; *y = m_ypos;
1451 return TRUE;
1452}
1453
1454// Control points ('handles') redirect control to the actual shape, to make it easier
1455// to override sizing behaviour.
1456void wxShape::OnSizingDragLeft(wxControlPoint* pt, bool draw, float x, float y, int keys, int attachment)
0fc1a713
JS
1457{
1458 float bound_x;
1459 float bound_y;
2bb0cd28 1460 this->GetBoundingBoxMin(&bound_x, &bound_y);
0fc1a713
JS
1461
1462 wxClientDC dc(GetCanvas());
1463 GetCanvas()->PrepareDC(dc);
1464
1465 dc.SetLogicalFunction(wxXOR);
1466
1467 wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
1468 dc.SetPen(dottedPen);
1469 dc.SetBrush((* wxTRANSPARENT_BRUSH));
1470
2bb0cd28 1471 if (this->GetCentreResize())
0fc1a713
JS
1472 {
1473 // Maintain the same centre point.
2bb0cd28
JS
1474 float new_width = (float)(2.0*fabs(x - this->GetX()));
1475 float new_height = (float)(2.0*fabs(y - this->GetY()));
0fc1a713
JS
1476
1477 // Constrain sizing according to what control point you're dragging
2bb0cd28 1478 if (pt->m_type == CONTROL_POINT_HORIZONTAL)
0fc1a713 1479 new_height = bound_y;
2bb0cd28 1480 else if (pt->m_type == CONTROL_POINT_VERTICAL)
0fc1a713 1481 new_width = bound_x;
2bb0cd28 1482 else if (pt->m_type == CONTROL_POINT_DIAGONAL && (keys & KEY_SHIFT))
0fc1a713
JS
1483 new_height = bound_y*(new_width/bound_x);
1484
2bb0cd28 1485 if (this->GetFixedWidth())
0fc1a713
JS
1486 new_width = bound_x;
1487
2bb0cd28 1488 if (this->GetFixedHeight())
0fc1a713
JS
1489 new_height = bound_y;
1490
2bb0cd28
JS
1491 pt->controlPointDragEndWidth = new_width;
1492 pt->controlPointDragEndHeight = new_height;
0fc1a713 1493
2bb0cd28 1494 this->GetEventHandler()->OnDrawOutline(dc, this->GetX(), this->GetY(),
0fc1a713
JS
1495 new_width, new_height);
1496 }
1497 else
1498 {
1499 // Don't maintain the same centre point!
2bb0cd28
JS
1500 float newX1 = wxMin(pt->controlPointDragStartX, x);
1501 float newY1 = wxMin(pt->controlPointDragStartY, y);
1502 float newX2 = wxMax(pt->controlPointDragStartX, x);
1503 float newY2 = wxMax(pt->controlPointDragStartY, y);
1504 if (pt->m_type == CONTROL_POINT_HORIZONTAL)
0fc1a713 1505 {
2bb0cd28
JS
1506 newY1 = pt->controlPointDragStartY;
1507 newY2 = newY1 + pt->controlPointDragStartHeight;
0fc1a713 1508 }
2bb0cd28 1509 else if (pt->m_type == CONTROL_POINT_VERTICAL)
0fc1a713 1510 {
2bb0cd28
JS
1511 newX1 = pt->controlPointDragStartX;
1512 newX2 = newX1 + pt->controlPointDragStartWidth;
0fc1a713 1513 }
2bb0cd28 1514 else if (pt->m_type == CONTROL_POINT_DIAGONAL && (keys & KEY_SHIFT))
0fc1a713 1515 {
2bb0cd28
JS
1516 float newH = (float)((newX2 - newX1)*(pt->controlPointDragStartHeight/pt->controlPointDragStartWidth));
1517 if (GetY() > pt->controlPointDragStartY)
0fc1a713
JS
1518 newY2 = (float)(newY1 + newH);
1519 else
1520 newY1 = (float)(newY2 - newH);
1521 }
1522 float newWidth = (float)(newX2 - newX1);
1523 float newHeight = (float)(newY2 - newY1);
1524
2bb0cd28
JS
1525 pt->controlPointDragPosX = (float)(newX1 + (newWidth/2.0));
1526 pt->controlPointDragPosY = (float)(newY1 + (newHeight/2.0));
1527 if (this->GetFixedWidth())
0fc1a713
JS
1528 newWidth = bound_x;
1529
2bb0cd28 1530 if (this->GetFixedHeight())
0fc1a713
JS
1531 newHeight = bound_y;
1532
2bb0cd28
JS
1533 pt->controlPointDragEndWidth = newWidth;
1534 pt->controlPointDragEndHeight = newHeight;
1535 this->GetEventHandler()->OnDrawOutline(dc, pt->controlPointDragPosX, pt->controlPointDragPosY, newWidth, newHeight);
0fc1a713
JS
1536 }
1537}
1538
2bb0cd28 1539void wxShape::OnSizingBeginDragLeft(wxControlPoint* pt, float x, float y, int keys, int attachment)
0fc1a713
JS
1540{
1541 m_canvas->CaptureMouse();
1542
1543 wxClientDC dc(GetCanvas());
1544 GetCanvas()->PrepareDC(dc);
1545
2bb0cd28
JS
1546 if (pt->m_eraseObject)
1547 this->Erase(dc);
0fc1a713
JS
1548
1549 dc.SetLogicalFunction(wxXOR);
1550
1551 float bound_x;
1552 float bound_y;
2bb0cd28 1553 this->GetBoundingBoxMin(&bound_x, &bound_y);
0fc1a713
JS
1554
1555 // Choose the 'opposite corner' of the object as the stationary
1556 // point in case this is non-centring resizing.
2bb0cd28
JS
1557 if (pt->GetX() < this->GetX())
1558 pt->controlPointDragStartX = (float)(this->GetX() + (bound_x/2.0));
0fc1a713 1559 else
2bb0cd28 1560 pt->controlPointDragStartX = (float)(this->GetX() - (bound_x/2.0));
0fc1a713 1561
2bb0cd28
JS
1562 if (pt->GetY() < this->GetY())
1563 pt->controlPointDragStartY = (float)(this->GetY() + (bound_y/2.0));
0fc1a713 1564 else
2bb0cd28 1565 pt->controlPointDragStartY = (float)(this->GetY() - (bound_y/2.0));
0fc1a713 1566
2bb0cd28
JS
1567 if (pt->m_type == CONTROL_POINT_HORIZONTAL)
1568 pt->controlPointDragStartY = (float)(this->GetY() - (bound_y/2.0));
1569 else if (pt->m_type == CONTROL_POINT_VERTICAL)
1570 pt->controlPointDragStartX = (float)(this->GetX() - (bound_x/2.0));
0fc1a713
JS
1571
1572 // We may require the old width and height.
2bb0cd28
JS
1573 pt->controlPointDragStartWidth = bound_x;
1574 pt->controlPointDragStartHeight = bound_y;
0fc1a713
JS
1575
1576 wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
1577 dc.SetPen(dottedPen);
1578 dc.SetBrush((* wxTRANSPARENT_BRUSH));
1579
2bb0cd28 1580 if (this->GetCentreResize())
0fc1a713 1581 {
2bb0cd28
JS
1582 float new_width = (float)(2.0*fabs(x - this->GetX()));
1583 float new_height = (float)(2.0*fabs(y - this->GetY()));
0fc1a713
JS
1584
1585 // Constrain sizing according to what control point you're dragging
2bb0cd28 1586 if (pt->m_type == CONTROL_POINT_HORIZONTAL)
0fc1a713 1587 new_height = bound_y;
2bb0cd28 1588 else if (pt->m_type == CONTROL_POINT_VERTICAL)
0fc1a713 1589 new_width = bound_x;
2bb0cd28 1590 else if (pt->m_type == CONTROL_POINT_DIAGONAL && (keys & KEY_SHIFT))
0fc1a713
JS
1591 new_height = bound_y*(new_width/bound_x);
1592
2bb0cd28 1593 if (this->GetFixedWidth())
0fc1a713
JS
1594 new_width = bound_x;
1595
2bb0cd28 1596 if (this->GetFixedHeight())
0fc1a713
JS
1597 new_height = bound_y;
1598
2bb0cd28
JS
1599 pt->controlPointDragEndWidth = new_width;
1600 pt->controlPointDragEndHeight = new_height;
1601 this->GetEventHandler()->OnDrawOutline(dc, this->GetX(), this->GetY(),
0fc1a713
JS
1602 new_width, new_height);
1603 }
1604 else
1605 {
1606 // Don't maintain the same centre point!
2bb0cd28
JS
1607 float newX1 = wxMin(pt->controlPointDragStartX, x);
1608 float newY1 = wxMin(pt->controlPointDragStartY, y);
1609 float newX2 = wxMax(pt->controlPointDragStartX, x);
1610 float newY2 = wxMax(pt->controlPointDragStartY, y);
1611 if (pt->m_type == CONTROL_POINT_HORIZONTAL)
0fc1a713 1612 {
2bb0cd28
JS
1613 newY1 = pt->controlPointDragStartY;
1614 newY2 = newY1 + pt->controlPointDragStartHeight;
0fc1a713 1615 }
2bb0cd28 1616 else if (pt->m_type == CONTROL_POINT_VERTICAL)
0fc1a713 1617 {
2bb0cd28
JS
1618 newX1 = pt->controlPointDragStartX;
1619 newX2 = newX1 + pt->controlPointDragStartWidth;
0fc1a713 1620 }
2bb0cd28 1621 else if (pt->m_type == CONTROL_POINT_DIAGONAL && (keys & KEY_SHIFT))
0fc1a713 1622 {
2bb0cd28
JS
1623 float newH = (float)((newX2 - newX1)*(pt->controlPointDragStartHeight/pt->controlPointDragStartWidth));
1624 if (pt->GetY() > pt->controlPointDragStartY)
0fc1a713
JS
1625 newY2 = (float)(newY1 + newH);
1626 else
1627 newY1 = (float)(newY2 - newH);
1628 }
1629 float newWidth = (float)(newX2 - newX1);
1630 float newHeight = (float)(newY2 - newY1);
1631
2bb0cd28
JS
1632 pt->controlPointDragPosX = (float)(newX1 + (newWidth/2.0));
1633 pt->controlPointDragPosY = (float)(newY1 + (newHeight/2.0));
1634 if (this->GetFixedWidth())
0fc1a713
JS
1635 newWidth = bound_x;
1636
2bb0cd28 1637 if (this->GetFixedHeight())
0fc1a713
JS
1638 newHeight = bound_y;
1639
2bb0cd28
JS
1640 pt->controlPointDragEndWidth = newWidth;
1641 pt->controlPointDragEndHeight = newHeight;
1642 this->GetEventHandler()->OnDrawOutline(dc, pt->controlPointDragPosX, pt->controlPointDragPosY, newWidth, newHeight);
0fc1a713
JS
1643 }
1644}
1645
2bb0cd28 1646void wxShape::OnSizingEndDragLeft(wxControlPoint* pt, float x, float y, int keys, int attachment)
0fc1a713
JS
1647{
1648 wxClientDC dc(GetCanvas());
1649 GetCanvas()->PrepareDC(dc);
1650
1651 m_canvas->ReleaseMouse();
1652 dc.SetLogicalFunction(wxCOPY);
2bb0cd28
JS
1653 this->Recompute();
1654 this->ResetControlPoints();
0fc1a713 1655
2bb0cd28
JS
1656 if (!pt->m_eraseObject)
1657 this->Show(FALSE);
0fc1a713 1658
2bb0cd28 1659 this->SetSize(pt->controlPointDragEndWidth, pt->controlPointDragEndHeight);
0fc1a713
JS
1660
1661 // The next operation could destroy this control point (it does for label objects,
1662 // via formatting the text), so save all values we're going to use, or
1663 // we'll be accessing garbage.
2bb0cd28 1664 wxShape *theObject = this;
0fc1a713 1665 wxShapeCanvas *theCanvas = m_canvas;
2bb0cd28 1666 bool eraseIt = pt->m_eraseObject;
0fc1a713
JS
1667
1668 if (theObject->GetCentreResize())
1669 theObject->Move(dc, theObject->GetX(), theObject->GetY());
1670 else
2bb0cd28 1671 theObject->Move(dc, pt->controlPointDragPosX, pt->controlPointDragPosY);
0fc1a713
JS
1672
1673 if (!eraseIt)
1674 theObject->Show(TRUE);
1675
1676 // Recursively redraw links if we have a composite.
1677 if (theObject->GetChildren().Number() > 0)
1678 theObject->DrawLinks(dc, -1, TRUE);
1679
1680 float width, height;
1681 theObject->GetBoundingBoxMax(&width, &height);
1682 theObject->GetEventHandler()->OnEndSize(width, height);
1683
1684 if (!theCanvas->GetQuickEditMode() && eraseIt) theCanvas->Redraw(dc);
1685}
1686
0fc1a713
JS
1687
1688
1689// Polygon control points
1690
1691IMPLEMENT_DYNAMIC_CLASS(wxPolygonControlPoint, wxControlPoint)
1692
1693wxPolygonControlPoint::wxPolygonControlPoint(wxShapeCanvas *theCanvas, wxShape *object, float size,
1694 wxRealPoint *vertex, float the_xoffset, float the_yoffset):
1695 wxControlPoint(theCanvas, object, size, the_xoffset, the_yoffset, 0)
1696{
1697 m_polygonVertex = vertex;
2bb0cd28 1698 m_originalDistance = 0.0;
0fc1a713
JS
1699}
1700
1701wxPolygonControlPoint::~wxPolygonControlPoint()
1702{
1703}
1704
34138703
JS
1705// Calculate what new size would be, at end of resize
1706void wxPolygonControlPoint::CalculateNewSize(float x, float y)
1707{
1708 float bound_x;
1709 float bound_y;
1710 GetShape()->GetBoundingBoxMin(&bound_x, &bound_y);
1711
1712 float dist = (float)sqrt((x - m_shape->GetX())*(x - m_shape->GetX()) +
1713 (y - m_shape->GetY())*(y - m_shape->GetY()));
1714
1715 m_newSize.x = (float)(dist/this->m_originalDistance)*this->m_originalSize.x;
1716 m_newSize.y = (float)(dist/this->m_originalDistance)*this->m_originalSize.y;
1717}
1718
1719
0fc1a713
JS
1720// Implement resizing polygon or moving the vertex.
1721void wxPolygonControlPoint::OnDragLeft(bool draw, float x, float y, int keys, int attachment)
1722{
2bb0cd28
JS
1723 m_shape->GetEventHandler()->OnSizingDragLeft(this, draw, x, y, keys, attachment);
1724}
1725
1726void wxPolygonControlPoint::OnBeginDragLeft(float x, float y, int keys, int attachment)
1727{
1728 m_shape->GetEventHandler()->OnSizingBeginDragLeft(this, x, y, keys, attachment);
1729}
1730
1731void wxPolygonControlPoint::OnEndDragLeft(float x, float y, int keys, int attachment)
1732{
1733 m_shape->GetEventHandler()->OnSizingEndDragLeft(this, x, y, keys, attachment);
1734}
1735
1736// Control points ('handles') redirect control to the actual shape, to make it easier
1737// to override sizing behaviour.
1738void wxPolygonShape::OnSizingDragLeft(wxControlPoint* pt, bool draw, float x, float y, int keys, int attachment)
1739{
1740 wxPolygonControlPoint* ppt = (wxPolygonControlPoint*) pt;
1741
0fc1a713
JS
1742 wxClientDC dc(GetCanvas());
1743 GetCanvas()->PrepareDC(dc);
1744
1745 dc.SetLogicalFunction(wxXOR);
1746
1747 wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
1748 dc.SetPen(dottedPen);
1749 dc.SetBrush((* wxTRANSPARENT_BRUSH));
1750
34138703 1751 if (0) // keys & KEY_CTRL)
0fc1a713 1752 {
34138703
JS
1753 // TODO: mend this code. Currently we rely on altering the
1754 // actual points, but we should assume we're not, as per
1755 // the normal sizing case.
0fc1a713
JS
1756 m_canvas->Snap(&x, &y);
1757
1758 // Move point
2bb0cd28
JS
1759 ppt->m_polygonVertex->x = x - this->GetX();
1760 ppt->m_polygonVertex->y = y - this->GetY();
1761 ppt->SetX(x);
1762 ppt->SetY(y);
1763 ((wxPolygonShape *)this)->CalculateBoundingBox();
1764 ((wxPolygonShape *)this)->CalculatePolygonCentre();
0fc1a713
JS
1765 }
1766 else
1767 {
34138703 1768 ppt->CalculateNewSize(x, y);
0fc1a713 1769 }
34138703
JS
1770
1771 this->GetEventHandler()->OnDrawOutline(dc, this->GetX(), this->GetY(),
1772 ppt->GetNewSize().x, ppt->GetNewSize().y);
0fc1a713
JS
1773}
1774
2bb0cd28 1775void wxPolygonShape::OnSizingBeginDragLeft(wxControlPoint* pt, float x, float y, int keys, int attachment)
0fc1a713 1776{
2bb0cd28
JS
1777 wxPolygonControlPoint* ppt = (wxPolygonControlPoint*) pt;
1778
0fc1a713
JS
1779 wxClientDC dc(GetCanvas());
1780 GetCanvas()->PrepareDC(dc);
1781
2bb0cd28 1782 this->Erase(dc);
0fc1a713
JS
1783
1784 dc.SetLogicalFunction(wxXOR);
1785
1786 float bound_x;
1787 float bound_y;
2bb0cd28 1788 this->GetBoundingBoxMin(&bound_x, &bound_y);
0fc1a713 1789
2bb0cd28
JS
1790 float dist = (float)sqrt((x - this->GetX())*(x - this->GetX()) +
1791 (y - this->GetY())*(y - this->GetY()));
2bb0cd28
JS
1792 ppt->m_originalDistance = dist;
1793 ppt->m_originalSize.x = bound_x;
1794 ppt->m_originalSize.y = bound_y;
0fc1a713 1795
2bb0cd28 1796 if (ppt->m_originalDistance == 0.0) ppt->m_originalDistance = (float) 0.0001;
0fc1a713
JS
1797
1798 wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
1799 dc.SetPen(dottedPen);
1800 dc.SetBrush((* wxTRANSPARENT_BRUSH));
1801
34138703 1802 if (0) // keys & KEY_CTRL)
0fc1a713 1803 {
34138703
JS
1804 // TODO: mend this code. Currently we rely on altering the
1805 // actual points, but we should assume we're not, as per
1806 // the normal sizing case.
0fc1a713
JS
1807 m_canvas->Snap(&x, &y);
1808
1809 // Move point
2bb0cd28
JS
1810 ppt->m_polygonVertex->x = x - this->GetX();
1811 ppt->m_polygonVertex->y = y - this->GetY();
1812 ppt->SetX(x);
1813 ppt->SetY(y);
1814 ((wxPolygonShape *)this)->CalculateBoundingBox();
1815 ((wxPolygonShape *)this)->CalculatePolygonCentre();
0fc1a713
JS
1816 }
1817 else
1818 {
34138703 1819 ppt->CalculateNewSize(x, y);
0fc1a713
JS
1820 }
1821
34138703
JS
1822 this->GetEventHandler()->OnDrawOutline(dc, this->GetX(), this->GetY(),
1823 ppt->GetNewSize().x, ppt->GetNewSize().y);
0fc1a713
JS
1824
1825 m_canvas->CaptureMouse();
1826}
1827
2bb0cd28 1828void wxPolygonShape::OnSizingEndDragLeft(wxControlPoint* pt, float x, float y, int keys, int attachment)
0fc1a713 1829{
34138703
JS
1830 wxPolygonControlPoint* ppt = (wxPolygonControlPoint*) pt;
1831
0fc1a713
JS
1832 wxClientDC dc(GetCanvas());
1833 GetCanvas()->PrepareDC(dc);
1834
1835 m_canvas->ReleaseMouse();
1836 dc.SetLogicalFunction(wxCOPY);
1837
1838 // If we're changing shape, must reset the original points
1839 if (keys & KEY_CTRL)
1840 {
2bb0cd28
JS
1841 ((wxPolygonShape *)this)->CalculateBoundingBox();
1842 ((wxPolygonShape *)this)->UpdateOriginalPoints();
0fc1a713 1843 }
34138703
JS
1844 else
1845 {
1846 SetSize(ppt->GetNewSize().x, ppt->GetNewSize().y);
1847 }
0fc1a713 1848
2bb0cd28
JS
1849 ((wxPolygonShape *)this)->CalculateBoundingBox();
1850 ((wxPolygonShape *)this)->CalculatePolygonCentre();
0fc1a713 1851
2bb0cd28
JS
1852 this->Recompute();
1853 this->ResetControlPoints();
1854 this->Move(dc, this->GetX(), this->GetY());
0fc1a713
JS
1855 if (!m_canvas->GetQuickEditMode()) m_canvas->Redraw(dc);
1856}
1857
0fc1a713
JS
1858/*
1859 * Object region
1860 *
1861 */
1862IMPLEMENT_DYNAMIC_CLASS(wxShapeRegion, wxObject)
1863
1864wxShapeRegion::wxShapeRegion()
1865{
1866 m_regionText = "";
1867 m_font = g_oglNormalFont;
1868 m_minHeight = 5.0;
1869 m_minWidth = 5.0;
1870 m_width = 0.0;
1871 m_height = 0.0;
1872 m_x = 0.0;
1873 m_y = 0.0;
1874
1875 m_regionProportionX = -1.0;
1876 m_regionProportionY = -1.0;
1877 m_formatMode = FORMAT_CENTRE_HORIZ | FORMAT_CENTRE_VERT;
1878 m_regionName = "";
1879 m_textColour = "BLACK";
1880 m_penColour = "BLACK";
1881 m_penStyle = wxSOLID;
1882 m_actualColourObject = NULL;
1883 m_actualPenObject = NULL;
1884}
1885
1886wxShapeRegion::wxShapeRegion(wxShapeRegion& region)
1887{
1888 m_regionText = region.m_regionText;
1889 m_regionName = region.m_regionName;
1890 m_textColour = region.m_textColour;
1891
1892 m_font = region.m_font;
1893 m_minHeight = region.m_minHeight;
1894 m_minWidth = region.m_minWidth;
1895 m_width = region.m_width;
1896 m_height = region.m_height;
1897 m_x = region.m_x;
1898 m_y = region.m_y;
1899
1900 m_regionProportionX = region.m_regionProportionX;
1901 m_regionProportionY = region.m_regionProportionY;
1902 m_formatMode = region.m_formatMode;
1903 m_actualColourObject = NULL;
1904 m_actualPenObject = NULL;
1905 m_penStyle = region.m_penStyle;
1906 m_penColour = region.m_penColour;
1907
1908 ClearText();
1909 wxNode *node = region.m_formattedText.First();
1910 while (node)
1911 {
1912 wxShapeTextLine *line = (wxShapeTextLine *)node->Data();
1913 wxShapeTextLine *new_line =
1914 new wxShapeTextLine(line->GetX(), line->GetY(), line->GetText());
1915 m_formattedText.Append(new_line);
1916 node = node->Next();
1917 }
1918}
1919
1920wxShapeRegion::~wxShapeRegion()
1921{
1922 ClearText();
1923}
1924
1925void wxShapeRegion::ClearText()
1926{
1927 wxNode *node = m_formattedText.First();
1928 while (node)
1929 {
1930 wxShapeTextLine *line = (wxShapeTextLine *)node->Data();
1931 wxNode *next = node->Next();
1932 delete line;
1933 delete node;
1934 node = next;
1935 }
1936}
1937
1938void wxShapeRegion::SetFont(wxFont *f)
1939{
1940 m_font = f;
1941}
1942
1943void wxShapeRegion::SetMinSize(float w, float h)
1944{
1945 m_minWidth = w;
1946 m_minHeight = h;
1947}
1948
1949void wxShapeRegion::SetSize(float w, float h)
1950{
1951 m_width = w;
1952 m_height = h;
1953}
1954
1955void wxShapeRegion::SetPosition(float xp, float yp)
1956{
1957 m_x = xp;
1958 m_y = yp;
1959}
1960
1961void wxShapeRegion::SetProportions(float xp, float yp)
1962{
1963 m_regionProportionX = xp;
1964 m_regionProportionY = yp;
1965}
1966
1967void wxShapeRegion::SetFormatMode(int mode)
1968{
1969 m_formatMode = mode;
1970}
1971
1972void wxShapeRegion::SetColour(const wxString& col)
1973{
1974 m_textColour = col;
1975 m_actualColourObject = NULL;
1976}
1977
1978wxColour *wxShapeRegion::GetActualColourObject()
1979{
1980 if (!m_actualColourObject)
1981 m_actualColourObject = wxTheColourDatabase->FindColour(GetColour());
1982 if (!m_actualColourObject)
1983 m_actualColourObject = wxBLACK;
1984 return m_actualColourObject;
1985}
1986
1987void wxShapeRegion::SetPenColour(const wxString& col)
1988{
1989 m_penColour = col;
1990 m_actualPenObject = NULL;
1991}
1992
1993// Returns NULL if the pen is invisible
1994// (different to pen being transparent; indicates that
1995// region boundary should not be drawn.)
1996wxPen *wxShapeRegion::GetActualPen()
1997{
1998 if (m_actualPenObject)
1999 return m_actualPenObject;
2000
2001 if (!m_penColour) return NULL;
2002 if (m_penColour == "Invisible")
2003 return NULL;
2004 m_actualPenObject = wxThePenList->FindOrCreatePen(m_penColour, 1, m_penStyle);
2005 return m_actualPenObject;
2006}
2007
2008