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