1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Basic OGL classes (2)
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
15 // For compilers that support precompilation, includes "wx.h".
16 #include <wx/wxprec.h>
27 #include <wx/wxexpr.h>
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
55 #define CONTROL_POINT_ENDPOINT_TO 4
56 #define CONTROL_POINT_ENDPOINT_FROM 5
57 #define CONTROL_POINT_LINE 6
59 // Two stage construction: need to call Create
60 IMPLEMENT_DYNAMIC_CLASS(wxPolygonShape
, wxShape
)
62 wxPolygonShape::wxPolygonShape()
65 m_originalPoints
= NULL
;
68 void wxPolygonShape::Create(wxList
*the_points
)
70 m_originalPoints
= the_points
;
72 // Duplicate the list of points
73 m_points
= new wxList
;
75 wxNode
*node
= the_points
->First();
78 wxRealPoint
*point
= (wxRealPoint
*)node
->Data();
79 wxRealPoint
*new_point
= new wxRealPoint(point
->x
, point
->y
);
80 m_points
->Append((wxObject
*) new_point
);
83 CalculateBoundingBox();
84 m_originalWidth
= m_boundWidth
;
85 m_originalHeight
= m_boundHeight
;
86 SetDefaultRegionSize();
89 wxPolygonShape::~wxPolygonShape()
93 wxNode
*node
= m_points
->First();
96 wxRealPoint
*point
= (wxRealPoint
*)node
->Data();
99 node
= m_points
->First();
103 if (m_originalPoints
)
105 wxNode
*node
= m_originalPoints
->First();
108 wxRealPoint
*point
= (wxRealPoint
*)node
->Data();
111 node
= m_originalPoints
->First();
113 delete m_originalPoints
;
118 // Width and height. Centre of object is centre of box.
119 void wxPolygonShape::GetBoundingBoxMin(float *width
, float *height
)
121 *width
= m_boundWidth
;
122 *height
= m_boundHeight
;
125 void wxPolygonShape::CalculateBoundingBox()
127 // Calculate bounding box at construction (and presumably resize) time
129 float right
= -10000;
131 float bottom
= -10000;
133 wxNode
*node
= m_points
->First();
136 wxRealPoint
*point
= (wxRealPoint
*)node
->Data();
137 if (point
->x
< left
) left
= point
->x
;
138 if (point
->x
> right
) right
= point
->x
;
140 if (point
->y
< top
) top
= point
->y
;
141 if (point
->y
> bottom
) bottom
= point
->y
;
145 m_boundWidth
= right
- left
;
146 m_boundHeight
= bottom
- top
;
149 // Recalculates the centre of the polygon, and
150 // readjusts the point offsets accordingly.
151 // Necessary since the centre of the polygon
152 // is expected to be the real centre of the bounding
154 void wxPolygonShape::CalculatePolygonCentre()
157 float right
= -10000;
159 float bottom
= -10000;
161 wxNode
*node
= m_points
->First();
164 wxRealPoint
*point
= (wxRealPoint
*)node
->Data();
165 if (point
->x
< left
) left
= point
->x
;
166 if (point
->x
> right
) right
= point
->x
;
168 if (point
->y
< top
) top
= point
->y
;
169 if (point
->y
> bottom
) bottom
= point
->y
;
173 float bwidth
= right
- left
;
174 float bheight
= bottom
- top
;
176 float newCentreX
= (float)(left
+ (bwidth
/2.0));
177 float newCentreY
= (float)(top
+ (bheight
/2.0));
179 node
= m_points
->First();
182 wxRealPoint
*point
= (wxRealPoint
*)node
->Data();
183 point
->x
-= newCentreX
;
184 point
->y
-= newCentreY
;
187 m_xpos
+= newCentreX
;
188 m_ypos
+= newCentreY
;
191 bool PolylineHitTest(float n
, float xvec
[], float yvec
[],
192 float x1
, float y1
, float x2
, float y2
)
196 float lastx
= xvec
[0];
197 float lasty
= yvec
[0];
199 float min_ratio
= 1.0;
204 for (i
= 1; i
< n
; i
++)
206 check_line_intersection(x1
, y1
, x2
, y2
, lastx
, lasty
, xvec
[i
], yvec
[i
],
207 &line_ratio
, &other_ratio
);
208 if (line_ratio
!= 1.0)
210 // sprintf(buf, "Line ratio = %.2f, other ratio = %.2f\n", line_ratio, other_ratio);
211 // ClipsErrorFunction(buf);
215 if (line_ratio
< min_ratio
)
216 min_ratio
= line_ratio
;
219 // Do last (implicit) line if last and first floats are not identical
220 if (!(xvec
[0] == lastx
&& yvec
[0] == lasty
))
222 check_line_intersection(x1
, y1
, x2
, y2
, lastx
, lasty
, xvec
[0], yvec
[0],
223 &line_ratio
, &other_ratio
);
224 if (line_ratio
!= 1.0)
226 // sprintf(buf, "Line ratio = %.2f, other ratio = %.2f\n", line_ratio, other_ratio);
227 // ClipsErrorFunction(buf);
229 if (line_ratio
< min_ratio
)
230 min_ratio
= line_ratio
;
232 // ClipsErrorFunction("\n");
236 bool wxPolygonShape::HitTest(float x
, float y
, int *attachment
, float *distance
)
238 // Imagine four lines radiating from this point. If all of these lines hit the polygon,
239 // we're inside it, otherwise we're not. Obviously we'd need more radiating lines
240 // to be sure of correct results for very strange (concave) shapes.
245 endPointsY
[0] = (float)(y
- 1000.0);
247 endPointsX
[1] = (float)(x
+ 1000.0);
251 endPointsY
[2] = (float)(y
+ 1000.0);
253 endPointsX
[3] = (float)(x
- 1000.0);
256 // Store polygon points in an array
257 int np
= m_points
->Number();
258 float *xpoints
= new float[np
];
259 float *ypoints
= new float[np
];
260 wxNode
*node
= m_points
->First();
264 wxRealPoint
*point
= (wxRealPoint
*)node
->Data();
265 xpoints
[i
] = point
->x
+ m_xpos
;
266 ypoints
[i
] = point
->y
+ m_ypos
;
271 // We assume it's inside the polygon UNLESS one or more
272 // lines don't hit the outline.
273 bool isContained
= TRUE
;
276 for (i
= 0; i
< noPoints
; i
++)
278 if (!PolylineHitTest(np
, xpoints
, ypoints
, x
, y
, endPointsX
[i
], endPointsY
[i
]))
283 ClipsErrorFunction("It's a hit!\n");
285 ClipsErrorFunction("No hit.\n");
293 int nearest_attachment
= 0;
295 // If a hit, check the attachment points within the object.
296 int n
= GetNumberOfAttachments();
297 float nearest
= 999999.0;
299 for (i
= 0; i
< n
; i
++)
302 if (GetAttachmentPosition(i
, &xp
, &yp
))
304 float l
= (float)sqrt(((xp
- x
) * (xp
- x
)) +
305 ((yp
- y
) * (yp
- y
)));
309 nearest_attachment
= i
;
313 *attachment
= nearest_attachment
;
318 // Really need to be able to reset the shape! Otherwise, if the
319 // points ever go to zero, we've lost it, and can't resize.
320 void wxPolygonShape::SetSize(float new_width
, float new_height
, bool recursive
)
322 SetAttachmentSize(new_width
, new_height
);
324 // Multiply all points by proportion of new size to old size
325 float x_proportion
= (float)(fabs(new_width
/m_originalWidth
));
326 float y_proportion
= (float)(fabs(new_height
/m_originalHeight
));
328 wxNode
*node
= m_points
->First();
329 wxNode
*original_node
= m_originalPoints
->First();
330 while (node
&& original_node
)
332 wxRealPoint
*point
= (wxRealPoint
*)node
->Data();
333 wxRealPoint
*original_point
= (wxRealPoint
*)original_node
->Data();
335 point
->x
= (original_point
->x
* x_proportion
);
336 point
->y
= (original_point
->y
* y_proportion
);
339 original_node
= original_node
->Next();
342 // CalculateBoundingBox();
343 m_boundWidth
= (float)fabs(new_width
);
344 m_boundHeight
= (float)fabs(new_height
);
345 SetDefaultRegionSize();
348 // Make the original points the same as the working points
349 void wxPolygonShape::UpdateOriginalPoints()
351 if (!m_originalPoints
) m_originalPoints
= new wxList
;
352 wxNode
*original_node
= m_originalPoints
->First();
353 while (original_node
)
355 wxNode
*next_node
= original_node
->Next();
356 wxRealPoint
*original_point
= (wxRealPoint
*)original_node
->Data();
357 delete original_point
;
358 delete original_node
;
360 original_node
= next_node
;
363 wxNode
*node
= m_points
->First();
366 wxRealPoint
*point
= (wxRealPoint
*)node
->Data();
367 wxRealPoint
*original_point
= new wxRealPoint(point
->x
, point
->y
);
368 m_originalPoints
->Append((wxObject
*) original_point
);
372 CalculateBoundingBox();
373 m_originalWidth
= m_boundWidth
;
374 m_originalHeight
= m_boundHeight
;
377 void wxPolygonShape::AddPolygonPoint(int pos
)
379 wxNode
*node
= m_points
->Nth(pos
);
380 if (!node
) node
= m_points
->First();
381 wxRealPoint
*firstPoint
= (wxRealPoint
*)node
->Data();
383 wxNode
*node2
= m_points
->Nth(pos
+ 1);
384 if (!node2
) node2
= m_points
->First();
385 wxRealPoint
*secondPoint
= (wxRealPoint
*)node2
->Data();
387 float x
= (float)((secondPoint
->x
- firstPoint
->x
)/2.0 + firstPoint
->x
);
388 float y
= (float)((secondPoint
->y
- firstPoint
->y
)/2.0 + firstPoint
->y
);
389 wxRealPoint
*point
= new wxRealPoint(x
, y
);
391 if (pos
>= (m_points
->Number() - 1))
392 m_points
->Append((wxObject
*) point
);
394 m_points
->Insert(node2
, (wxObject
*) point
);
396 UpdateOriginalPoints();
400 DeleteControlPoints();
405 void wxPolygonShape::DeletePolygonPoint(int pos
)
407 wxNode
*node
= m_points
->Nth(pos
);
410 wxRealPoint
*point
= (wxRealPoint
*)node
->Data();
413 UpdateOriginalPoints();
416 DeleteControlPoints();
422 // Assume (x1, y1) is centre of box (most generally, line end at box)
423 bool wxPolygonShape::GetPerimeterPoint(float x1
, float y1
,
425 float *x3
, float *y3
)
427 int n
= m_points
->Number();
429 // First check for situation where the line is vertical,
430 // and we would want to connect to a point on that vertical --
431 // find_end_for_polyline can't cope with this (the arrow
432 // gets drawn to the wrong place).
433 if ((!m_attachmentMode
) && (x1
== x2
))
435 // Look for the point we'd be connecting to. This is
437 wxNode
*node
= m_points
->First();
440 wxRealPoint
*point
= (wxRealPoint
*)node
->Data();
443 if ((y2
> y1
) && (point
->y
> 0.0))
445 *x3
= point
->x
+ m_xpos
;
446 *y3
= point
->y
+ m_ypos
;
449 else if ((y2
< y1
) && (point
->y
< 0.0))
451 *x3
= point
->x
+ m_xpos
;
452 *y3
= point
->y
+ m_ypos
;
460 float *xpoints
= new float[n
];
461 float *ypoints
= new float[n
];
463 wxNode
*node
= m_points
->First();
467 wxRealPoint
*point
= (wxRealPoint
*)node
->Data();
468 xpoints
[i
] = point
->x
+ m_xpos
;
469 ypoints
[i
] = point
->y
+ m_ypos
;
474 wxRealPoint *point = (wxRealPoint *)m_points->First()->Data();
475 xpoints[i] = point->x + m_xpos;
476 ypoints[i] = point->y + m_ypos;
479 find_end_for_polyline(n
, xpoints
, ypoints
,
480 x1
, y1
, x2
, y2
, x3
, y3
);
488 void wxPolygonShape::OnDraw(wxDC
& dc
)
490 int n
= m_points
->Number();
491 wxPoint
*intPoints
= new wxPoint
[n
];
493 for (i
= 0; i
< n
; i
++)
495 wxRealPoint
* point
= (wxRealPoint
*) m_points
->Nth(i
)->Data();
496 intPoints
[i
].x
= (int) point
->x
;
497 intPoints
[i
].y
= (int) point
->y
;
500 if (m_shadowMode
!= SHADOW_NONE
)
503 dc
.SetBrush(m_shadowBrush
);
504 dc
.SetPen(transparent_pen
);
506 dc
.DrawPolygon(n
, intPoints
, m_xpos
+ m_shadowOffsetX
, m_ypos
+ m_shadowOffsetY
);
511 if (m_pen
->GetWidth() == 0)
512 dc
.SetPen(transparent_pen
);
517 dc
.SetBrush(m_brush
);
518 dc
.DrawPolygon(n
, intPoints
, m_xpos
, m_ypos
);
523 void wxPolygonShape::OnDrawOutline(wxDC
& dc
, float x
, float y
, float w
, float h
)
525 dc
.SetBrush(wxTRANSPARENT_BRUSH
);
527 int n
= m_points
->Number();
528 wxPoint
*intPoints
= new wxPoint
[n
];
530 for (i
= 0; i
< n
; i
++)
532 wxRealPoint
* point
= (wxRealPoint
*) m_points
->Nth(i
)->Data();
533 intPoints
[i
].x
= (int) point
->x
;
534 intPoints
[i
].y
= (int) point
->y
;
536 dc
.DrawPolygon(n
, intPoints
, x
, y
);
537 // wxShape::OnDrawOutline(x, y, w, h);
540 // Make as many control points as there are vertices.
541 void wxPolygonShape::MakeControlPoints()
543 wxNode
*node
= m_points
->First();
546 wxRealPoint
*point
= (wxRealPoint
*)node
->Data();
547 wxPolygonControlPoint
*control
= new wxPolygonControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
,
548 point
, point
->x
, point
->y
);
549 m_canvas
->AddShape(control
);
550 m_controlPoints
.Append(control
);
555 float maxX, maxY, minX, minY;
557 GetBoundingBoxMax(&maxX, &maxY);
558 GetBoundingBoxMin(&minX, &minY);
560 float widthMin = (float)(minX + CONTROL_POINT_SIZE + 2);
561 float heightMin = (float)(minY + CONTROL_POINT_SIZE + 2);
563 // Offsets from main object
564 float top = (float)(- (heightMin / 2.0));
565 float bottom = (float)(heightMin / 2.0 + (maxY - minY));
566 float left = (float)(- (widthMin / 2.0));
567 float right = (float)(widthMin / 2.0 + (maxX - minX));
569 wxControlPoint *control = new wxControlPoint(m_canvas, this, CONTROL_POINT_SIZE, left, top,
570 CONTROL_POINT_DIAGONAL);
571 m_canvas->AddShape(control);
572 m_controlPoints.Append(control);
574 control = new wxControlPoint(m_canvas, this, CONTROL_POINT_SIZE, 0, top,
575 CONTROL_POINT_VERTICAL);
576 m_canvas->AddShape(control);
577 m_controlPoints.Append(control);
579 control = new wxControlPoint(m_canvas, this, CONTROL_POINT_SIZE, right, top,
580 CONTROL_POINT_DIAGONAL);
581 m_canvas->AddShape(control);
582 m_controlPoints.Append(control);
584 control = new wxControlPoint(m_canvas, this, CONTROL_POINT_SIZE, right, 0,
585 CONTROL_POINT_HORIZONTAL);
586 m_canvas->AddShape(control);
587 m_controlPoints.Append(control);
589 control = new wxControlPoint(m_canvas, this, CONTROL_POINT_SIZE, right, bottom,
590 CONTROL_POINT_DIAGONAL);
591 m_canvas->AddShape(control);
592 m_controlPoints.Append(control);
594 control = new wxControlPoint(m_canvas, this, CONTROL_POINT_SIZE, 0, bottom,
595 CONTROL_POINT_VERTICAL);
596 m_canvas->AddShape(control);
597 m_controlPoints.Append(control);
599 control = new wxControlPoint(m_canvas, this, CONTROL_POINT_SIZE, left, bottom,
600 CONTROL_POINT_DIAGONAL);
601 m_canvas->AddShape(control);
602 m_controlPoints.Append(control);
604 control = new wxControlPoint(m_canvas, this, CONTROL_POINT_SIZE, left, 0,
605 CONTROL_POINT_HORIZONTAL);
606 m_canvas->AddShape(control);
607 m_controlPoints.Append(control);
611 void wxPolygonShape::ResetControlPoints()
613 wxNode
*node
= m_points
->First();
614 wxNode
*controlPointNode
= m_controlPoints
.First();
615 while (node
&& controlPointNode
)
617 wxRealPoint
*point
= (wxRealPoint
*)node
->Data();
618 wxPolygonControlPoint
*controlPoint
= (wxPolygonControlPoint
*)controlPointNode
->Data();
620 controlPoint
->m_xoffset
= point
->x
;
621 controlPoint
->m_yoffset
= point
->y
;
622 controlPoint
->m_polygonVertex
= point
;
625 controlPointNode
= controlPointNode
->Next();
629 if (m_controlPoints.Number() < 1)
632 float maxX, maxY, minX, minY;
634 GetBoundingBoxMax(&maxX, &maxY);
635 GetBoundingBoxMin(&minX, &minY);
637 float widthMin = (float)(minX + CONTROL_POINT_SIZE + 2);
638 float heightMin = (float)(minY + CONTROL_POINT_SIZE + 2);
640 // Offsets from main object
641 float top = (float)(- (heightMin / 2.0));
642 float bottom = (float)(heightMin / 2.0 + (maxY - minY));
643 float left = (float)(- (widthMin / 2.0));
644 float right = (float)(widthMin / 2.0 + (maxX - minX));
646 wxNode *node = m_controlPoints.First();
647 wxControlPoint *control = (wxControlPoint *)node->Data();
648 control->xoffset = left; control->yoffset = top;
650 node = node->Next(); control = (wxControlPoint *)node->Data();
651 control->xoffset = 0; control->yoffset = top;
653 node = node->Next(); control = (wxControlPoint *)node->Data();
654 control->xoffset = right; control->yoffset = top;
656 node = node->Next(); control = (wxControlPoint *)node->Data();
657 control->xoffset = right; control->yoffset = 0;
659 node = node->Next(); control = (wxControlPoint *)node->Data();
660 control->xoffset = right; control->yoffset = bottom;
662 node = node->Next(); control = (wxControlPoint *)node->Data();
663 control->xoffset = 0; control->yoffset = bottom;
665 node = node->Next(); control = (wxControlPoint *)node->Data();
666 control->xoffset = left; control->yoffset = bottom;
668 node = node->Next(); control = (wxControlPoint *)node->Data();
669 control->xoffset = left; control->yoffset = 0;
675 void wxPolygonShape::WritePrologAttributes(wxExpr
*clause
)
677 wxShape::WritePrologAttributes(clause
);
679 clause
->AddAttributeValue("x", m_xpos
);
680 clause
->AddAttributeValue("y", m_ypos
);
682 // Make a list of lists for the coordinates
683 wxExpr
*list
= new wxExpr(PrologList
);
684 wxNode
*node
= m_points
->First();
687 wxRealPoint
*point
= (wxRealPoint
*)node
->Data();
688 wxExpr
*point_list
= new wxExpr(PrologList
);
689 wxExpr
*x_expr
= new wxExpr((float)point
->x
);
690 wxExpr
*y_expr
= new wxExpr((float)point
->y
);
692 point_list
->Append(x_expr
);
693 point_list
->Append(y_expr
);
694 list
->Append(point_list
);
698 clause
->AddAttributeValue("points", list
);
700 // Save the original (unscaled) points
701 list
= new wxExpr(PrologList
);
702 node
= m_originalPoints
->First();
705 wxRealPoint
*point
= (wxRealPoint
*)node
->Data();
706 wxExpr
*point_list
= new wxExpr(PrologList
);
707 wxExpr
*x_expr
= new wxExpr((float) point
->x
);
708 wxExpr
*y_expr
= new wxExpr((float) point
->y
);
709 point_list
->Append(x_expr
);
710 point_list
->Append(y_expr
);
711 list
->Append(point_list
);
715 clause
->AddAttributeValue("m_originalPoints", list
);
718 void wxPolygonShape::ReadPrologAttributes(wxExpr
*clause
)
720 wxShape::ReadPrologAttributes(clause
);
722 // Read a list of lists
723 m_points
= new wxList
;
724 m_originalPoints
= new wxList
;
726 wxExpr
*points_list
= NULL
;
727 clause
->AssignAttributeValue("points", &points_list
);
729 // If no points_list, don't crash!! Assume a diamond instead.
730 float the_height
= 100.0;
731 float the_width
= 100.0;
734 wxRealPoint
*point
= new wxRealPoint(0.0, (-the_height
/2));
735 m_points
->Append((wxObject
*) point
);
737 point
= new wxRealPoint((the_width
/2), 0.0);
738 m_points
->Append((wxObject
*) point
);
740 point
= new wxRealPoint(0.0, (the_height
/2));
741 m_points
->Append((wxObject
*) point
);
743 point
= new wxRealPoint((-the_width
/2), 0.0);
744 m_points
->Append((wxObject
*) point
);
746 point
= new wxRealPoint(0.0, (-the_height
/2));
747 m_points
->Append((wxObject
*) point
);
751 wxExpr
*node
= points_list
->value
.first
;
755 wxExpr
*xexpr
= node
->value
.first
;
756 long x
= xexpr
->IntegerValue();
758 wxExpr
*yexpr
= xexpr
->next
;
759 long y
= yexpr
->IntegerValue();
761 wxRealPoint
*point
= new wxRealPoint((float)x
, (float)y
);
762 m_points
->Append((wxObject
*) point
);
769 clause
->AssignAttributeValue("m_originalPoints", &points_list
);
771 // If no points_list, don't crash!! Assume a diamond instead.
774 wxRealPoint
*point
= new wxRealPoint(0.0, (-the_height
/2));
775 m_originalPoints
->Append((wxObject
*) point
);
777 point
= new wxRealPoint((the_width
/2), 0.0);
778 m_originalPoints
->Append((wxObject
*) point
);
780 point
= new wxRealPoint(0.0, (the_height
/2));
781 m_originalPoints
->Append((wxObject
*) point
);
783 point
= new wxRealPoint((-the_width
/2), 0.0);
784 m_originalPoints
->Append((wxObject
*) point
);
786 point
= new wxRealPoint(0.0, (-the_height
/2));
787 m_originalPoints
->Append((wxObject
*) point
);
789 m_originalWidth
= the_width
;
790 m_originalHeight
= the_height
;
794 wxExpr
*node
= points_list
->value
.first
;
801 wxExpr
*xexpr
= node
->value
.first
;
802 long x
= xexpr
->IntegerValue();
804 wxExpr
*yexpr
= xexpr
->next
;
805 long y
= yexpr
->IntegerValue();
807 wxRealPoint
*point
= new wxRealPoint((float)x
, (float)y
);
808 m_originalPoints
->Append((wxObject
*) point
);
821 m_originalWidth
= max_x
- min_x
;
822 m_originalHeight
= max_y
- min_y
;
825 CalculateBoundingBox();
829 void wxPolygonShape::Copy(wxPolygonShape
& copy
)
834 delete copy
.m_points
;
836 copy
.m_points
= new wxList
;
838 if (copy
.m_originalPoints
)
839 delete copy
.m_originalPoints
;
841 copy
.m_originalPoints
= new wxList
;
843 wxNode
*node
= m_points
->First();
846 wxRealPoint
*point
= (wxRealPoint
*)node
->Data();
847 wxRealPoint
*new_point
= new wxRealPoint(point
->x
, point
->y
);
848 copy
.m_points
->Append((wxObject
*) new_point
);
851 node
= m_originalPoints
->First();
854 wxRealPoint
*point
= (wxRealPoint
*)node
->Data();
855 wxRealPoint
*new_point
= new wxRealPoint(point
->x
, point
->y
);
856 copy
.m_originalPoints
->Append((wxObject
*) new_point
);
859 copy
.m_boundWidth
= m_boundWidth
;
860 copy
.m_boundHeight
= m_boundHeight
;
861 copy
.m_originalWidth
= m_originalWidth
;
862 copy
.m_originalHeight
= m_originalHeight
;
865 wxShape
*wxPolygonShape::PrivateCopy()
867 wxPolygonShape
*obj
= new wxPolygonShape
;
872 int wxPolygonShape::GetNumberOfAttachments()
874 int maxN
= (m_points
? (m_points
->Number() - 1) : 0);
875 wxNode
*node
= m_attachmentPoints
.First();
878 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->Data();
879 if (point
->m_id
> maxN
)
886 bool wxPolygonShape::GetAttachmentPosition(int attachment
, float *x
, float *y
,
887 int nth
, int no_arcs
, wxLineShape
*line
)
889 if (m_attachmentMode
&& m_points
&& attachment
< m_points
->Number())
891 wxRealPoint
*point
= (wxRealPoint
*)m_points
->Nth(attachment
)->Data();
892 *x
= point
->x
+ m_xpos
;
893 *y
= point
->y
+ m_ypos
;
897 { return wxShape::GetAttachmentPosition(attachment
, x
, y
, nth
, no_arcs
, line
); }
900 bool wxPolygonShape::AttachmentIsValid(int attachment
)
905 if ((attachment
>= 0) && (attachment
< m_points
->Number()))
908 wxNode
*node
= m_attachmentPoints
.First();
911 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->Data();
912 if (point
->m_id
== attachment
)
921 IMPLEMENT_DYNAMIC_CLASS(wxRectangleShape
, wxShape
)
923 wxRectangleShape::wxRectangleShape(float w
, float h
)
925 m_width
= w
; m_height
= h
; m_cornerRadius
= 0.0;
926 SetDefaultRegionSize();
929 void wxRectangleShape::OnDraw(wxDC
& dc
)
931 float x1
= (float)(m_xpos
- m_width
/2.0);
932 float y1
= (float)(m_ypos
- m_height
/2.0);
934 if (m_shadowMode
!= SHADOW_NONE
)
937 dc
.SetBrush(m_shadowBrush
);
938 dc
.SetPen(transparent_pen
);
940 if (m_cornerRadius
!= 0.0)
941 dc
.DrawRoundedRectangle(x1
+ m_shadowOffsetX
, y1
+ m_shadowOffsetY
,
942 m_width
, m_height
, m_cornerRadius
);
944 dc
.DrawRectangle(x1
+ m_shadowOffsetX
, y1
+ m_shadowOffsetY
, m_width
, m_height
);
949 if (m_pen
->GetWidth() == 0)
950 dc
.SetPen(transparent_pen
);
955 dc
.SetBrush(m_brush
);
957 if (m_cornerRadius
!= 0.0)
958 dc
.DrawRoundedRectangle(x1
, y1
, m_width
, m_height
, m_cornerRadius
);
960 dc
.DrawRectangle(x1
, y1
, m_width
, m_height
);
963 void wxRectangleShape::GetBoundingBoxMin(float *the_width
, float *the_height
)
965 *the_width
= m_width
;
966 *the_height
= m_height
;
969 void wxRectangleShape::SetSize(float x
, float y
, bool recursive
)
971 SetAttachmentSize(x
, y
);
972 m_width
= (float)wxMax(x
, 1.0);
973 m_height
= (float)wxMax(y
, 1.0);
974 SetDefaultRegionSize();
977 void wxRectangleShape::SetCornerRadius(float rad
)
979 m_cornerRadius
= rad
;
982 // Assume (x1, y1) is centre of box (most generally, line end at box)
983 bool wxRectangleShape::GetPerimeterPoint(float x1
, float y1
,
985 float *x3
, float *y3
)
987 float bound_x
, bound_y
;
988 GetBoundingBoxMax(&bound_x
, &bound_y
);
989 find_end_for_box(bound_x
, bound_y
, m_xpos
, m_ypos
, x2
, y2
, x3
, y3
);
995 void wxRectangleShape::WritePrologAttributes(wxExpr
*clause
)
997 wxShape::WritePrologAttributes(clause
);
998 clause
->AddAttributeValue("x", m_xpos
);
999 clause
->AddAttributeValue("y", m_ypos
);
1001 clause
->AddAttributeValue("width", m_width
);
1002 clause
->AddAttributeValue("height", m_height
);
1003 if (m_cornerRadius
!= 0.0)
1004 clause
->AddAttributeValue("corner", m_cornerRadius
);
1007 void wxRectangleShape::ReadPrologAttributes(wxExpr
*clause
)
1009 wxShape::ReadPrologAttributes(clause
);
1010 clause
->AssignAttributeValue("width", &m_width
);
1011 clause
->AssignAttributeValue("height", &m_height
);
1012 clause
->AssignAttributeValue("corner", &m_cornerRadius
);
1014 // In case we're reading an old file, set the region's size
1015 if (m_regions
.Number() == 1)
1017 wxShapeRegion
*region
= (wxShapeRegion
*)m_regions
.First()->Data();
1018 region
->SetSize(m_width
, m_height
);
1023 void wxRectangleShape::Copy(wxRectangleShape
& copy
)
1025 wxShape::Copy(copy
);
1026 copy
.m_width
= m_width
;
1027 copy
.m_height
= m_height
;
1028 copy
.m_cornerRadius
= m_cornerRadius
;
1031 wxShape
*wxRectangleShape::PrivateCopy()
1033 wxRectangleShape
*obj
= new wxRectangleShape(0.0, 0.0);
1039 int wxRectangleShape::GetNumberOfAttachments()
1041 return wxShape::GetNumberOfAttachments();
1044 // There are 4 attachment points on a rectangle - 0 = top, 1 = right, 2 = bottom,
1046 bool wxRectangleShape::GetAttachmentPosition(int attachment
, float *x
, float *y
,
1047 int nth
, int no_arcs
, wxLineShape
*line
)
1049 if (m_attachmentMode
)
1051 float top
= (float)(m_ypos
+ m_height
/2.0);
1052 float bottom
= (float)(m_ypos
- m_height
/2.0);
1053 float left
= (float)(m_xpos
- m_width
/2.0);
1054 float right
= (float)(m_xpos
+ m_width
/2.0);
1056 bool isEnd
= (line
&& line
->IsEnd(this));
1062 if (m_spaceAttachments
)
1064 if (line
&& (line
->GetAlignmentType(isEnd
) == LINE_ALIGNMENT_TO_NEXT_HANDLE
))
1066 // Align line according to the next handle along
1067 wxRealPoint
*point
= line
->GetNextControlPoint(this);
1068 if (point
->x
< left
)
1070 else if (point
->x
> right
)
1076 *x
= left
+ (nth
+ 1)*m_width
/(no_arcs
+ 1);
1086 if (m_spaceAttachments
)
1088 if (line
&& (line
->GetAlignmentType(isEnd
) == LINE_ALIGNMENT_TO_NEXT_HANDLE
))
1090 // Align line according to the next handle along
1091 wxRealPoint
*point
= line
->GetNextControlPoint(this);
1092 if (point
->y
< bottom
)
1094 else if (point
->y
> top
)
1100 *y
= bottom
+ (nth
+ 1)*m_height
/(no_arcs
+ 1);
1107 if (m_spaceAttachments
)
1109 if (line
&& (line
->GetAlignmentType(isEnd
) == LINE_ALIGNMENT_TO_NEXT_HANDLE
))
1111 // Align line according to the next handle along
1112 wxRealPoint
*point
= line
->GetNextControlPoint(this);
1113 if (point
->x
< left
)
1115 else if (point
->x
> right
)
1121 *x
= left
+ (nth
+ 1)*m_width
/(no_arcs
+ 1);
1130 if (m_spaceAttachments
)
1132 if (line
&& (line
->GetAlignmentType(isEnd
) == LINE_ALIGNMENT_TO_NEXT_HANDLE
))
1134 // Align line according to the next handle along
1135 wxRealPoint
*point
= line
->GetNextControlPoint(this);
1136 if (point
->y
< bottom
)
1138 else if (point
->y
> top
)
1144 *y
= bottom
+ (nth
+ 1)*m_height
/(no_arcs
+ 1);
1151 return wxShape::GetAttachmentPosition(attachment
, x
, y
, nth
, no_arcs
, line
);
1158 { *x
= m_xpos
; *y
= m_ypos
; return TRUE
; }
1161 // Text object (no box)
1163 IMPLEMENT_DYNAMIC_CLASS(wxTextShape
, wxRectangleShape
)
1165 wxTextShape::wxTextShape(float width
, float height
):
1166 wxRectangleShape(width
, height
)
1170 void wxTextShape::OnDraw(wxDC
& dc
)
1174 wxShape
*wxTextShape::PrivateCopy()
1176 wxTextShape
*obj
= new wxTextShape(0.0, 0.0);
1181 void wxTextShape::Copy(wxTextShape
& copy
)
1183 wxRectangleShape::Copy(copy
);
1187 void wxTextShape::WritePrologAttributes(wxExpr
*clause
)
1189 wxRectangleShape::WritePrologAttributes(clause
);
1195 IMPLEMENT_DYNAMIC_CLASS(wxEllipseShape
, wxShape
)
1197 wxEllipseShape::wxEllipseShape(float w
, float h
)
1199 m_width
= w
; m_height
= h
;
1200 SetDefaultRegionSize();
1203 void wxEllipseShape::GetBoundingBoxMin(float *w
, float *h
)
1205 *w
= m_width
; *h
= m_height
;
1208 bool wxEllipseShape::GetPerimeterPoint(float x1
, float y1
,
1210 float *x3
, float *y3
)
1212 float bound_x
, bound_y
;
1213 GetBoundingBoxMax(&bound_x
, &bound_y
);
1215 // find_end_for_box(bound_x, bound_y, m_xpos, m_ypos, x2, y2, x3, y3);
1216 draw_arc_to_ellipse(m_xpos
, m_ypos
, bound_x
, bound_y
, x2
, y2
, x1
, y1
, x3
, y3
);
1221 void wxEllipseShape::OnDraw(wxDC
& dc
)
1223 if (m_shadowMode
!= SHADOW_NONE
)
1226 dc
.SetBrush(m_shadowBrush
);
1227 dc
.SetPen(transparent_pen
);
1228 dc
.DrawEllipse((m_xpos
- GetWidth()/2) + m_shadowOffsetX
,
1229 (m_ypos
- GetHeight()/2) + m_shadowOffsetY
,
1230 GetWidth(), GetHeight());
1235 if (m_pen
->GetWidth() == 0)
1236 dc
.SetPen(transparent_pen
);
1241 dc
.SetBrush(m_brush
);
1242 dc
.DrawEllipse((m_xpos
- GetWidth()/2), (m_ypos
- GetHeight()/2), GetWidth(), GetHeight());
1245 void wxEllipseShape::SetSize(float x
, float y
, bool recursive
)
1247 SetAttachmentSize(x
, y
);
1250 SetDefaultRegionSize();
1254 void wxEllipseShape::WritePrologAttributes(wxExpr
*clause
)
1256 wxShape::WritePrologAttributes(clause
);
1257 clause
->AddAttributeValue("x", m_xpos
);
1258 clause
->AddAttributeValue("y", m_ypos
);
1260 clause
->AddAttributeValue("width", m_width
);
1261 clause
->AddAttributeValue("height", m_height
);
1264 void wxEllipseShape::ReadPrologAttributes(wxExpr
*clause
)
1266 wxShape::ReadPrologAttributes(clause
);
1267 clause
->AssignAttributeValue("width", &m_width
);
1268 clause
->AssignAttributeValue("height", &m_height
);
1270 // In case we're reading an old file, set the region's size
1271 if (m_regions
.Number() == 1)
1273 wxShapeRegion
*region
= (wxShapeRegion
*)m_regions
.First()->Data();
1274 region
->SetSize(m_width
, m_height
);
1279 void wxEllipseShape::Copy(wxEllipseShape
& copy
)
1281 wxShape::Copy(copy
);
1283 copy
.m_width
= m_width
;
1284 copy
.m_height
= m_height
;
1287 wxShape
*wxEllipseShape::PrivateCopy()
1289 wxEllipseShape
*obj
= new wxEllipseShape(0.0, 0.0);
1294 int wxEllipseShape::GetNumberOfAttachments()
1296 return wxShape::GetNumberOfAttachments();
1299 // There are 4 attachment points on an ellipse - 0 = top, 1 = right, 2 = bottom,
1301 bool wxEllipseShape::GetAttachmentPosition(int attachment
, float *x
, float *y
,
1302 int nth
, int no_arcs
, wxLineShape
*line
)
1304 if (m_attachmentMode
)
1306 float top
= (float)(m_ypos
+ m_height
/2.0);
1307 float bottom
= (float)(m_ypos
- m_height
/2.0);
1308 float left
= (float)(m_xpos
- m_width
/2.0);
1309 float right
= (float)(m_xpos
+ m_width
/2.0);
1314 if (m_spaceAttachments
)
1315 *x
= left
+ (nth
+ 1)*m_width
/(no_arcs
+ 1);
1318 // We now have the point on the bounding box: but get the point on the ellipse
1319 // by imagining a vertical line from (*x, m_ypos - m_height- 500) to (*x, m_ypos) intersecting
1321 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 if (m_spaceAttachments
)
1328 *y
= bottom
+ (nth
+ 1)*m_height
/(no_arcs
+ 1);
1330 draw_arc_to_ellipse(m_xpos
, m_ypos
, m_width
, m_height
, (float)(m_xpos
+m_width
+500), *y
, m_xpos
, *y
, x
, y
);
1335 if (m_spaceAttachments
)
1336 *x
= left
+ (nth
+ 1)*m_width
/(no_arcs
+ 1);
1339 draw_arc_to_ellipse(m_xpos
, m_ypos
, m_width
, m_height
, *x
, (float)(m_ypos
+m_height
+500), *x
, m_ypos
, x
, y
);
1345 if (m_spaceAttachments
)
1346 *y
= bottom
+ (nth
+ 1)*m_height
/(no_arcs
+ 1);
1348 draw_arc_to_ellipse(m_xpos
, m_ypos
, m_width
, m_height
, (float)(m_xpos
-m_width
-500), *y
, m_xpos
, *y
, x
, y
);
1353 return wxShape::GetAttachmentPosition(attachment
, x
, y
, nth
, no_arcs
, line
);
1360 { *x
= m_xpos
; *y
= m_ypos
; return TRUE
; }
1365 IMPLEMENT_DYNAMIC_CLASS(wxCircleShape
, wxEllipseShape
)
1367 wxCircleShape::wxCircleShape(float diameter
):wxEllipseShape(diameter
, diameter
)
1371 wxShape
*wxCircleShape::PrivateCopy()
1373 wxCircleShape
*obj
= new wxCircleShape(0.0);
1378 void wxCircleShape::Copy(wxCircleShape
& copy
)
1380 wxEllipseShape::Copy(copy
);
1383 bool wxCircleShape::GetPerimeterPoint(float x1
, float y1
,
1385 float *x3
, float *y3
)
1387 find_end_for_circle(m_width
/2,
1388 m_xpos
, m_ypos
, // Centre of circle
1389 x2
, y2
, // Other end of line
1397 IMPLEMENT_DYNAMIC_CLASS(wxControlPoint
, wxRectangleShape
)
1399 wxControlPoint::wxControlPoint(wxShapeCanvas
*theCanvas
, wxShape
*object
, float size
, float the_xoffset
, float the_yoffset
, int the_type
):wxRectangleShape(size
, size
)
1401 m_canvas
= theCanvas
;
1403 m_xoffset
= the_xoffset
;
1404 m_yoffset
= the_yoffset
;
1406 SetPen(black_foreground_pen
);
1407 SetBrush(wxBLACK_BRUSH
);
1410 m_eraseObject
= TRUE
;
1413 wxControlPoint::~wxControlPoint()
1417 // Don't even attempt to draw any text - waste of time!
1418 void wxControlPoint::OnDrawContents(wxDC
& dc
)
1422 void wxControlPoint::OnDraw(wxDC
& dc
)
1424 m_xpos
= m_shape
->GetX() + m_xoffset
;
1425 m_ypos
= m_shape
->GetY() + m_yoffset
;
1426 wxRectangleShape::OnDraw(dc
);
1429 void wxControlPoint::OnErase(wxDC
& dc
)
1431 wxRectangleShape::OnErase(dc
);
1435 * Store original top-left, bottom-right coordinates
1436 * in case we're doing non-vertical resizing.
1438 static float controlPointDragStartX
= 0.0;
1439 static float controlPointDragStartY
= 0.0;
1440 static float controlPointDragStartWidth
= 0.0;
1441 static float controlPointDragStartHeight
= 0.0;
1442 static float controlPointDragEndWidth
= 0.0;
1443 static float controlPointDragEndHeight
= 0.0;
1444 static float controlPointDragPosX
= 0.0;
1445 static float controlPointDragPosY
= 0.0;
1447 // Implement resizing of canvas object
1448 void wxControlPoint::OnDragLeft(bool draw
, float x
, float y
, int keys
, int attachment
)
1452 m_shape
->GetBoundingBoxMin(&bound_x
, &bound_y
);
1454 wxClientDC
dc(GetCanvas());
1455 GetCanvas()->PrepareDC(dc
);
1457 dc
.SetLogicalFunction(wxXOR
);
1459 wxPen
dottedPen(wxColour(0, 0, 0), 1, wxDOT
);
1460 dc
.SetPen(dottedPen
);
1461 dc
.SetBrush((* wxTRANSPARENT_BRUSH
));
1463 if (m_shape
->GetCentreResize())
1465 // Maintain the same centre point.
1466 float new_width
= (float)(2.0*fabs(x
- m_shape
->GetX()));
1467 float new_height
= (float)(2.0*fabs(y
- m_shape
->GetY()));
1469 // Constrain sizing according to what control point you're dragging
1470 if (m_type
== CONTROL_POINT_HORIZONTAL
)
1471 new_height
= bound_y
;
1472 else if (m_type
== CONTROL_POINT_VERTICAL
)
1473 new_width
= bound_x
;
1474 else if (m_type
== CONTROL_POINT_DIAGONAL
&& (keys
& KEY_SHIFT
))
1475 new_height
= bound_y
*(new_width
/bound_x
);
1477 // m_shape->OnBeginSize(m_shape->m_fixedWidth ? bound_x : new_width,
1478 // m_shape->m_fixedHeight ? bound_y : new_height);
1480 // m_shape->SetSize(m_shape->m_fixedWidth ? bound_x : new_width,
1481 // m_shape->m_fixedHeight ? bound_y : new_height);
1482 if (m_shape
->GetFixedWidth())
1483 new_width
= bound_x
;
1485 if (m_shape
->GetFixedHeight())
1486 new_height
= bound_y
;
1488 controlPointDragEndWidth
= new_width
;
1489 controlPointDragEndHeight
= new_height
;
1491 m_shape
->GetEventHandler()->OnDrawOutline(dc
, m_shape
->GetX(), m_shape
->GetY(),
1492 new_width
, new_height
);
1496 // Don't maintain the same centre point!
1497 float newX1
= wxMin(controlPointDragStartX
, x
);
1498 float newY1
= wxMin(controlPointDragStartY
, y
);
1499 float newX2
= wxMax(controlPointDragStartX
, x
);
1500 float newY2
= wxMax(controlPointDragStartY
, y
);
1501 if (m_type
== CONTROL_POINT_HORIZONTAL
)
1503 newY1
= controlPointDragStartY
;
1504 newY2
= newY1
+ controlPointDragStartHeight
;
1506 else if (m_type
== CONTROL_POINT_VERTICAL
)
1508 newX1
= controlPointDragStartX
;
1509 newX2
= newX1
+ controlPointDragStartWidth
;
1511 else if (m_type
== CONTROL_POINT_DIAGONAL
&& (keys
& KEY_SHIFT
))
1513 float newH
= (float)((newX2
- newX1
)*(controlPointDragStartHeight
/controlPointDragStartWidth
));
1514 if (GetY() > controlPointDragStartY
)
1515 newY2
= (float)(newY1
+ newH
);
1517 newY1
= (float)(newY2
- newH
);
1519 float newWidth
= (float)(newX2
- newX1
);
1520 float newHeight
= (float)(newY2
- newY1
);
1522 // m_shape->OnBeginSize(newWidth,
1525 // m_shape->SetSize(newWidth,
1527 controlPointDragPosX
= (float)(newX1
+ (newWidth
/2.0));
1528 controlPointDragPosY
= (float)(newY1
+ (newHeight
/2.0));
1529 if (m_shape
->GetFixedWidth())
1532 if (m_shape
->GetFixedHeight())
1533 newHeight
= bound_y
;
1535 controlPointDragEndWidth
= newWidth
;
1536 controlPointDragEndHeight
= newHeight
;
1537 m_shape
->GetEventHandler()->OnDrawOutline(dc
, controlPointDragPosX
, controlPointDragPosY
, newWidth
, newHeight
);
1541 void wxControlPoint::OnBeginDragLeft(float x
, float y
, int keys
, int attachment
)
1543 m_canvas
->CaptureMouse();
1545 wxClientDC
dc(GetCanvas());
1546 GetCanvas()->PrepareDC(dc
);
1551 dc
.SetLogicalFunction(wxXOR
);
1555 m_shape
->GetBoundingBoxMin(&bound_x
, &bound_y
);
1557 // Choose the 'opposite corner' of the object as the stationary
1558 // point in case this is non-centring resizing.
1559 if (GetX() < m_shape
->GetX())
1560 controlPointDragStartX
= (float)(m_shape
->GetX() + (bound_x
/2.0));
1562 controlPointDragStartX
= (float)(m_shape
->GetX() - (bound_x
/2.0));
1564 if (GetY() < m_shape
->GetY())
1565 controlPointDragStartY
= (float)(m_shape
->GetY() + (bound_y
/2.0));
1567 controlPointDragStartY
= (float)(m_shape
->GetY() - (bound_y
/2.0));
1569 if (m_type
== CONTROL_POINT_HORIZONTAL
)
1570 controlPointDragStartY
= (float)(m_shape
->GetY() - (bound_y
/2.0));
1571 else if (m_type
== CONTROL_POINT_VERTICAL
)
1572 controlPointDragStartX
= (float)(m_shape
->GetX() - (bound_x
/2.0));
1574 // We may require the old width and height.
1575 controlPointDragStartWidth
= bound_x
;
1576 controlPointDragStartHeight
= bound_y
;
1578 wxPen
dottedPen(wxColour(0, 0, 0), 1, wxDOT
);
1579 dc
.SetPen(dottedPen
);
1580 dc
.SetBrush((* wxTRANSPARENT_BRUSH
));
1582 if (m_shape
->GetCentreResize())
1584 float new_width
= (float)(2.0*fabs(x
- m_shape
->GetX()));
1585 float new_height
= (float)(2.0*fabs(y
- m_shape
->GetY()));
1587 // Constrain sizing according to what control point you're dragging
1588 if (m_type
== CONTROL_POINT_HORIZONTAL
)
1589 new_height
= bound_y
;
1590 else if (m_type
== CONTROL_POINT_VERTICAL
)
1591 new_width
= bound_x
;
1592 else if (m_type
== CONTROL_POINT_DIAGONAL
&& (keys
& KEY_SHIFT
))
1593 new_height
= bound_y
*(new_width
/bound_x
);
1595 // Non-recursive SetSize for speed
1596 // m_shape->SetSize(new_width, new_height, FALSE);
1598 if (m_shape
->GetFixedWidth())
1599 new_width
= bound_x
;
1601 if (m_shape
->GetFixedHeight())
1602 new_height
= bound_y
;
1604 controlPointDragEndWidth
= new_width
;
1605 controlPointDragEndHeight
= new_height
;
1606 m_shape
->GetEventHandler()->OnDrawOutline(dc
, m_shape
->GetX(), m_shape
->GetY(),
1607 new_width
, new_height
);
1611 // Don't maintain the same centre point!
1612 float newX1
= wxMin(controlPointDragStartX
, x
);
1613 float newY1
= wxMin(controlPointDragStartY
, y
);
1614 float newX2
= wxMax(controlPointDragStartX
, x
);
1615 float newY2
= wxMax(controlPointDragStartY
, y
);
1616 if (m_type
== CONTROL_POINT_HORIZONTAL
)
1618 newY1
= controlPointDragStartY
;
1619 newY2
= newY1
+ controlPointDragStartHeight
;
1621 else if (m_type
== CONTROL_POINT_VERTICAL
)
1623 newX1
= controlPointDragStartX
;
1624 newX2
= newX1
+ controlPointDragStartWidth
;
1626 else if (m_type
== CONTROL_POINT_DIAGONAL
&& (keys
& KEY_SHIFT
))
1628 float newH
= (float)((newX2
- newX1
)*(controlPointDragStartHeight
/controlPointDragStartWidth
));
1629 if (GetY() > controlPointDragStartY
)
1630 newY2
= (float)(newY1
+ newH
);
1632 newY1
= (float)(newY2
- newH
);
1634 float newWidth
= (float)(newX2
- newX1
);
1635 float newHeight
= (float)(newY2
- newY1
);
1637 // m_shape->OnBeginSize(newWidth,
1640 // m_shape->SetSize(newWidth,
1642 controlPointDragPosX
= (float)(newX1
+ (newWidth
/2.0));
1643 controlPointDragPosY
= (float)(newY1
+ (newHeight
/2.0));
1644 if (m_shape
->GetFixedWidth())
1647 if (m_shape
->GetFixedHeight())
1648 newHeight
= bound_y
;
1650 controlPointDragEndWidth
= newWidth
;
1651 controlPointDragEndHeight
= newHeight
;
1652 m_shape
->GetEventHandler()->OnDrawOutline(dc
, controlPointDragPosX
, controlPointDragPosY
, newWidth
, newHeight
);
1656 void wxControlPoint::OnEndDragLeft(float x
, float y
, int keys
, int attachment
)
1658 wxClientDC
dc(GetCanvas());
1659 GetCanvas()->PrepareDC(dc
);
1661 m_canvas
->ReleaseMouse();
1662 dc
.SetLogicalFunction(wxCOPY
);
1663 m_shape
->Recompute();
1664 m_shape
->ResetControlPoints();
1667 m_shape
->Show(FALSE
);
1669 m_shape
->SetSize(controlPointDragEndWidth
, controlPointDragEndHeight
);
1671 // The next operation could destroy this control point (it does for label objects,
1672 // via formatting the text), so save all values we're going to use, or
1673 // we'll be accessing garbage.
1674 wxShape
*theObject
= m_shape
;
1675 wxShapeCanvas
*theCanvas
= m_canvas
;
1676 bool eraseIt
= m_eraseObject
;
1678 if (theObject
->GetCentreResize())
1679 theObject
->Move(dc
, theObject
->GetX(), theObject
->GetY());
1681 theObject
->Move(dc
, controlPointDragPosX
, controlPointDragPosY
);
1684 theObject
->Show(TRUE
);
1686 // Recursively redraw links if we have a composite.
1687 if (theObject
->GetChildren().Number() > 0)
1688 theObject
->DrawLinks(dc
, -1, TRUE
);
1690 float width
, height
;
1691 theObject
->GetBoundingBoxMax(&width
, &height
);
1692 theObject
->GetEventHandler()->OnEndSize(width
, height
);
1694 if (!theCanvas
->GetQuickEditMode() && eraseIt
) theCanvas
->Redraw(dc
);
1697 int wxControlPoint::GetNumberOfAttachments()
1702 bool wxControlPoint::GetAttachmentPosition(int attachment
, float *x
, float *y
,
1703 int nth
, int no_arcs
, wxLineShape
*line
)
1705 *x
= m_xpos
; *y
= m_ypos
;
1710 // Polygon control points
1712 IMPLEMENT_DYNAMIC_CLASS(wxPolygonControlPoint
, wxControlPoint
)
1714 wxPolygonControlPoint::wxPolygonControlPoint(wxShapeCanvas
*theCanvas
, wxShape
*object
, float size
,
1715 wxRealPoint
*vertex
, float the_xoffset
, float the_yoffset
):
1716 wxControlPoint(theCanvas
, object
, size
, the_xoffset
, the_yoffset
, 0)
1718 m_polygonVertex
= vertex
;
1721 wxPolygonControlPoint::~wxPolygonControlPoint()
1725 // Implement resizing polygon or moving the vertex.
1726 void wxPolygonControlPoint::OnDragLeft(bool draw
, float x
, float y
, int keys
, int attachment
)
1728 wxClientDC
dc(GetCanvas());
1729 GetCanvas()->PrepareDC(dc
);
1731 dc
.SetLogicalFunction(wxXOR
);
1733 wxPen
dottedPen(wxColour(0, 0, 0), 1, wxDOT
);
1734 dc
.SetPen(dottedPen
);
1735 dc
.SetBrush((* wxTRANSPARENT_BRUSH
));
1739 m_shape
->GetBoundingBoxMin(&bound_x
, &bound_y
);
1741 float new_width = (float)(2.0*fabs(x - m_shape->GetX()));
1742 float new_height = (float)(2.0*fabs(y - m_shape->GetY()));
1744 float dist
= (float)sqrt((x
- m_shape
->GetX())*(x
- m_shape
->GetX()) +
1745 (y
- m_shape
->GetY())*(y
- m_shape
->GetY()));
1747 if (keys
& KEY_CTRL
)
1749 m_canvas
->Snap(&x
, &y
);
1752 m_polygonVertex
->x
= x
- m_shape
->GetX();
1753 m_polygonVertex
->y
= y
- m_shape
->GetY();
1756 ((wxPolygonShape
*)m_shape
)->CalculateBoundingBox();
1757 ((wxPolygonShape
*)m_shape
)->CalculatePolygonCentre();
1761 float new_width
= (float)(dist
/m_originalDistance
)*m_originalSize
.x
;
1762 float new_height
= (float)(dist
/m_originalDistance
)*m_originalSize
.y
;
1764 // Non-recursive SetSize for speed
1765 m_shape
->SetSize(new_width
, new_height
, FALSE
);
1768 m_shape
->GetBoundingBoxMax(&w
, &h
);
1769 m_shape
->GetEventHandler()->OnDrawOutline(dc
, m_shape
->GetX(), m_shape
->GetY(), w
, h
);
1772 void wxPolygonControlPoint::OnBeginDragLeft(float x
, float y
, int keys
, int attachment
)
1774 wxClientDC
dc(GetCanvas());
1775 GetCanvas()->PrepareDC(dc
);
1779 dc
.SetLogicalFunction(wxXOR
);
1783 m_shape
->GetBoundingBoxMin(&bound_x
, &bound_y
);
1785 float dist
= (float)sqrt((x
- m_shape
->GetX())*(x
- m_shape
->GetX()) +
1786 (y
- m_shape
->GetY())*(y
- m_shape
->GetY()));
1788 m_originalDistance
= dist
;
1789 m_originalSize
.x
= bound_x
;
1790 m_originalSize
.y
= bound_y
;
1792 if (m_originalDistance
== 0.0) m_originalDistance
= (float) 0.0001;
1794 wxPen
dottedPen(wxColour(0, 0, 0), 1, wxDOT
);
1795 dc
.SetPen(dottedPen
);
1796 dc
.SetBrush((* wxTRANSPARENT_BRUSH
));
1798 if (keys
& KEY_CTRL
)
1800 m_canvas
->Snap(&x
, &y
);
1803 m_polygonVertex
->x
= x
- m_shape
->GetX();
1804 m_polygonVertex
->y
= y
- m_shape
->GetY();
1807 ((wxPolygonShape
*)m_shape
)->CalculateBoundingBox();
1808 ((wxPolygonShape
*)m_shape
)->CalculatePolygonCentre();
1812 float new_width
= (float)(dist
/m_originalDistance
)*m_originalSize
.x
;
1813 float new_height
= (float)(dist
/m_originalDistance
)*m_originalSize
.y
;
1815 // Non-recursive SetSize for speed
1816 m_shape
->SetSize(new_width
, new_height
, FALSE
);
1820 m_shape
->GetBoundingBoxMax(&w
, &h
);
1821 m_shape
->GetEventHandler()->OnDrawOutline(dc
, m_shape
->GetX(), m_shape
->GetY(), w
, h
);
1823 m_canvas
->CaptureMouse();
1826 void wxPolygonControlPoint::OnEndDragLeft(float x
, float y
, int keys
, int attachment
)
1828 wxClientDC
dc(GetCanvas());
1829 GetCanvas()->PrepareDC(dc
);
1831 m_canvas
->ReleaseMouse();
1832 dc
.SetLogicalFunction(wxCOPY
);
1834 // If we're changing shape, must reset the original points
1835 if (keys
& KEY_CTRL
)
1837 ((wxPolygonShape
*)m_shape
)->CalculateBoundingBox();
1838 ((wxPolygonShape
*)m_shape
)->UpdateOriginalPoints();
1841 ((wxPolygonShape
*)m_shape
)->CalculateBoundingBox();
1842 ((wxPolygonShape
*)m_shape
)->CalculatePolygonCentre();
1844 m_shape
->Recompute();
1845 m_shape
->ResetControlPoints();
1846 m_shape
->Move(dc
, m_shape
->GetX(), m_shape
->GetY());
1847 if (!m_canvas
->GetQuickEditMode()) m_canvas
->Redraw(dc
);
1855 IMPLEMENT_DYNAMIC_CLASS(wxShapeRegion
, wxObject
)
1857 wxShapeRegion::wxShapeRegion()
1860 m_font
= g_oglNormalFont
;
1868 m_regionProportionX
= -1.0;
1869 m_regionProportionY
= -1.0;
1870 m_formatMode
= FORMAT_CENTRE_HORIZ
| FORMAT_CENTRE_VERT
;
1872 m_textColour
= "BLACK";
1873 m_penColour
= "BLACK";
1874 m_penStyle
= wxSOLID
;
1875 m_actualColourObject
= NULL
;
1876 m_actualPenObject
= NULL
;
1879 wxShapeRegion::wxShapeRegion(wxShapeRegion
& region
)
1881 m_regionText
= region
.m_regionText
;
1882 m_regionName
= region
.m_regionName
;
1883 m_textColour
= region
.m_textColour
;
1885 m_font
= region
.m_font
;
1886 m_minHeight
= region
.m_minHeight
;
1887 m_minWidth
= region
.m_minWidth
;
1888 m_width
= region
.m_width
;
1889 m_height
= region
.m_height
;
1893 m_regionProportionX
= region
.m_regionProportionX
;
1894 m_regionProportionY
= region
.m_regionProportionY
;
1895 m_formatMode
= region
.m_formatMode
;
1896 m_actualColourObject
= NULL
;
1897 m_actualPenObject
= NULL
;
1898 m_penStyle
= region
.m_penStyle
;
1899 m_penColour
= region
.m_penColour
;
1902 wxNode
*node
= region
.m_formattedText
.First();
1905 wxShapeTextLine
*line
= (wxShapeTextLine
*)node
->Data();
1906 wxShapeTextLine
*new_line
=
1907 new wxShapeTextLine(line
->GetX(), line
->GetY(), line
->GetText());
1908 m_formattedText
.Append(new_line
);
1909 node
= node
->Next();
1913 wxShapeRegion::~wxShapeRegion()
1918 void wxShapeRegion::ClearText()
1920 wxNode
*node
= m_formattedText
.First();
1923 wxShapeTextLine
*line
= (wxShapeTextLine
*)node
->Data();
1924 wxNode
*next
= node
->Next();
1931 void wxShapeRegion::SetFont(wxFont
*f
)
1936 void wxShapeRegion::SetMinSize(float w
, float h
)
1942 void wxShapeRegion::SetSize(float w
, float h
)
1948 void wxShapeRegion::SetPosition(float xp
, float yp
)
1954 void wxShapeRegion::SetProportions(float xp
, float yp
)
1956 m_regionProportionX
= xp
;
1957 m_regionProportionY
= yp
;
1960 void wxShapeRegion::SetFormatMode(int mode
)
1962 m_formatMode
= mode
;
1965 void wxShapeRegion::SetColour(const wxString
& col
)
1968 m_actualColourObject
= NULL
;
1971 wxColour
*wxShapeRegion::GetActualColourObject()
1973 if (!m_actualColourObject
)
1974 m_actualColourObject
= wxTheColourDatabase
->FindColour(GetColour());
1975 if (!m_actualColourObject
)
1976 m_actualColourObject
= wxBLACK
;
1977 return m_actualColourObject
;
1980 void wxShapeRegion::SetPenColour(const wxString
& col
)
1983 m_actualPenObject
= NULL
;
1986 // Returns NULL if the pen is invisible
1987 // (different to pen being transparent; indicates that
1988 // region boundary should not be drawn.)
1989 wxPen
*wxShapeRegion::GetActualPen()
1991 if (m_actualPenObject
)
1992 return m_actualPenObject
;
1994 if (!m_penColour
) return NULL
;
1995 if (m_penColour
== "Invisible")
1997 m_actualPenObject
= wxThePenList
->FindOrCreatePen(m_penColour
, 1, m_penStyle
);
1998 return m_actualPenObject
;