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