1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Basic OGL classes
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "basic.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include <wx/wxprec.h>
28 #include <wx/wxexpr.h>
49 // Control point types
50 // Rectangle and most other shapes
51 #define CONTROL_POINT_VERTICAL 1
52 #define CONTROL_POINT_HORIZONTAL 2
53 #define CONTROL_POINT_DIAGONAL 3
56 #define CONTROL_POINT_ENDPOINT_TO 4
57 #define CONTROL_POINT_ENDPOINT_FROM 5
58 #define CONTROL_POINT_LINE 6
60 IMPLEMENT_DYNAMIC_CLASS(wxShapeTextLine
, wxObject
)
61 IMPLEMENT_DYNAMIC_CLASS(wxAttachmentPoint
, wxObject
)
63 wxShapeTextLine::wxShapeTextLine(double the_x
, double the_y
, const wxString
& the_line
)
65 m_x
= the_x
; m_y
= the_y
; m_line
= the_line
;
68 wxShapeTextLine::~wxShapeTextLine()
72 IMPLEMENT_ABSTRACT_CLASS(wxShapeEvtHandler
, wxObject
)
74 wxShapeEvtHandler::wxShapeEvtHandler(wxShapeEvtHandler
*prev
, wxShape
*shape
)
76 m_previousHandler
= prev
;
77 m_handlerShape
= shape
;
80 wxShapeEvtHandler::~wxShapeEvtHandler()
84 // Creates a copy of this event handler.
85 wxShapeEvtHandler
* wxShapeEvtHandler::CreateNewCopy()
87 wxShapeEvtHandler
* newObject
= (wxShapeEvtHandler
*) GetClassInfo()->CreateObject();
89 wxASSERT( (newObject
!= NULL
) );
90 wxASSERT( (newObject
->IsKindOf(CLASSINFO(wxShapeEvtHandler
))) );
92 newObject
->m_previousHandler
= newObject
;
100 void wxShapeEvtHandler::OnDelete()
102 if (this != GetShape())
106 void wxShapeEvtHandler::OnDraw(wxDC
& dc
)
108 if (m_previousHandler
)
109 m_previousHandler
->OnDraw(dc
);
112 void wxShapeEvtHandler::OnMoveLinks(wxDC
& dc
)
114 if (m_previousHandler
)
115 m_previousHandler
->OnMoveLinks(dc
);
118 void wxShapeEvtHandler::OnMoveLink(wxDC
& dc
, bool moveControlPoints
)
120 if (m_previousHandler
)
121 m_previousHandler
->OnMoveLink(dc
, moveControlPoints
);
124 void wxShapeEvtHandler::OnDrawContents(wxDC
& dc
)
126 if (m_previousHandler
)
127 m_previousHandler
->OnDrawContents(dc
);
130 void wxShapeEvtHandler::OnSize(double x
, double y
)
132 if (m_previousHandler
)
133 m_previousHandler
->OnSize(x
, y
);
136 bool wxShapeEvtHandler::OnMovePre(wxDC
& dc
, double x
, double y
, double old_x
, double old_y
, bool display
)
138 if (m_previousHandler
)
139 return m_previousHandler
->OnMovePre(dc
, x
, y
, old_x
, old_y
, display
);
144 void wxShapeEvtHandler::OnMovePost(wxDC
& dc
, double x
, double y
, double old_x
, double old_y
, bool display
)
146 if (m_previousHandler
)
147 m_previousHandler
->OnMovePost(dc
, x
, y
, old_x
, old_y
, display
);
150 void wxShapeEvtHandler::OnErase(wxDC
& dc
)
152 if (m_previousHandler
)
153 m_previousHandler
->OnErase(dc
);
156 void wxShapeEvtHandler::OnEraseContents(wxDC
& dc
)
158 if (m_previousHandler
)
159 m_previousHandler
->OnEraseContents(dc
);
162 void wxShapeEvtHandler::OnHighlight(wxDC
& dc
)
164 if (m_previousHandler
)
165 m_previousHandler
->OnHighlight(dc
);
168 void wxShapeEvtHandler::OnLeftClick(double x
, double y
, int keys
, int attachment
)
170 if (m_previousHandler
)
171 m_previousHandler
->OnLeftClick(x
, y
, keys
, attachment
);
174 void wxShapeEvtHandler::OnRightClick(double x
, double y
, int keys
, int attachment
)
176 if (m_previousHandler
)
177 m_previousHandler
->OnRightClick(x
, y
, keys
, attachment
);
180 void wxShapeEvtHandler::OnDragLeft(bool draw
, double x
, double y
, int keys
, int attachment
)
182 if (m_previousHandler
)
183 m_previousHandler
->OnDragLeft(draw
, x
, y
, keys
, attachment
);
186 void wxShapeEvtHandler::OnBeginDragLeft(double x
, double y
, int keys
, int attachment
)
188 if (m_previousHandler
)
189 m_previousHandler
->OnBeginDragLeft(x
, y
, keys
, attachment
);
192 void wxShapeEvtHandler::OnEndDragLeft(double x
, double y
, int keys
, int attachment
)
194 if (m_previousHandler
)
195 m_previousHandler
->OnEndDragLeft(x
, y
, keys
, attachment
);
198 void wxShapeEvtHandler::OnDragRight(bool draw
, double x
, double y
, int keys
, int attachment
)
200 if (m_previousHandler
)
201 m_previousHandler
->OnDragRight(draw
, x
, y
, keys
, attachment
);
204 void wxShapeEvtHandler::OnBeginDragRight(double x
, double y
, int keys
, int attachment
)
206 if (m_previousHandler
)
207 m_previousHandler
->OnBeginDragRight(x
, y
, keys
, attachment
);
210 void wxShapeEvtHandler::OnEndDragRight(double x
, double y
, int keys
, int attachment
)
212 if (m_previousHandler
)
213 m_previousHandler
->OnEndDragRight(x
, y
, keys
, attachment
);
216 // Control points ('handles') redirect control to the actual shape, to make it easier
217 // to override sizing behaviour.
218 void wxShapeEvtHandler::OnSizingDragLeft(wxControlPoint
* pt
, bool draw
, double x
, double y
, int keys
, int attachment
)
220 if (m_previousHandler
)
221 m_previousHandler
->OnSizingDragLeft(pt
, draw
, x
, y
, keys
, attachment
);
224 void wxShapeEvtHandler::OnSizingBeginDragLeft(wxControlPoint
* pt
, double x
, double y
, int keys
, int attachment
)
226 if (m_previousHandler
)
227 m_previousHandler
->OnSizingBeginDragLeft(pt
, x
, y
, keys
, attachment
);
230 void wxShapeEvtHandler::OnSizingEndDragLeft(wxControlPoint
* pt
, double x
, double y
, int keys
, int attachment
)
232 if (m_previousHandler
)
233 m_previousHandler
->OnSizingEndDragLeft(pt
, x
, y
, keys
, attachment
);
236 void wxShapeEvtHandler::OnDrawOutline(wxDC
& dc
, double x
, double y
, double w
, double h
)
238 if (m_previousHandler
)
239 m_previousHandler
->OnDrawOutline(dc
, x
, y
, w
, h
);
242 void wxShapeEvtHandler::OnDrawControlPoints(wxDC
& dc
)
244 if (m_previousHandler
)
245 m_previousHandler
->OnDrawControlPoints(dc
);
248 void wxShapeEvtHandler::OnEraseControlPoints(wxDC
& dc
)
250 if (m_previousHandler
)
251 m_previousHandler
->OnEraseControlPoints(dc
);
254 // Can override this to prevent or intercept line reordering.
255 void wxShapeEvtHandler::OnChangeAttachment(int attachment
, wxLineShape
* line
, wxList
& ordering
)
257 if (m_previousHandler
)
258 m_previousHandler
->OnChangeAttachment(attachment
, line
, ordering
);
261 IMPLEMENT_ABSTRACT_CLASS(wxShape
, wxShapeEvtHandler
)
263 wxShape::wxShape(wxShapeCanvas
*can
)
265 m_eventHandler
= this;
270 m_xpos
= 0.0; m_ypos
= 0.0;
271 m_pen
= g_oglBlackPen
;
272 m_brush
= wxWHITE_BRUSH
;
273 m_font
= g_oglNormalFont
;
274 m_textColour
= wxBLACK
;
275 m_textColourName
= "BLACK";
279 m_attachmentMode
= FALSE
;
280 m_spaceAttachments
= TRUE
;
281 m_disableLabel
= FALSE
;
282 m_fixedWidth
= FALSE
;
283 m_fixedHeight
= FALSE
;
284 m_drawHandles
= TRUE
;
285 m_sensitivity
= OP_ALL
;
288 m_formatMode
= FORMAT_CENTRE_HORIZ
| FORMAT_CENTRE_VERT
;
289 m_shadowMode
= SHADOW_NONE
;
290 m_shadowOffsetX
= 6.0;
291 m_shadowOffsetY
= 6.0;
292 m_shadowBrush
= wxBLACK_BRUSH
;
296 m_centreResize
= TRUE
;
297 m_highlighted
= FALSE
;
300 // Set up a default region. Much of the above will be put into
301 // the region eventually (the duplication is for compatibility)
302 wxShapeRegion
*region
= new wxShapeRegion
;
303 m_regions
.Append(region
);
304 region
->SetName("0");
305 region
->SetFont(g_oglNormalFont
);
306 region
->SetFormatMode(FORMAT_CENTRE_HORIZ
| FORMAT_CENTRE_VERT
);
307 region
->SetColour("BLACK");
313 m_parent
->GetChildren().DeleteObject(this);
320 m_canvas
->RemoveShape(this);
322 GetEventHandler()->OnDelete();
325 void wxShape::SetHighlight(bool hi
, bool recurse
)
330 wxNode
*node
= m_children
.First();
333 wxShape
*child
= (wxShape
*)node
->Data();
334 child
->SetHighlight(hi
, recurse
);
340 void wxShape::SetSensitivityFilter(int sens
, bool recursive
)
342 if (sens
& OP_DRAG_LEFT
)
347 m_sensitivity
= sens
;
350 wxNode
*node
= m_children
.First();
353 wxShape
*obj
= (wxShape
*)node
->Data();
354 obj
->SetSensitivityFilter(sens
, TRUE
);
360 void wxShape::SetDraggable(bool drag
, bool recursive
)
364 m_sensitivity
|= OP_DRAG_LEFT
;
366 if (m_sensitivity
& OP_DRAG_LEFT
)
367 m_sensitivity
= m_sensitivity
- OP_DRAG_LEFT
;
371 wxNode
*node
= m_children
.First();
374 wxShape
*obj
= (wxShape
*)node
->Data();
375 obj
->SetDraggable(drag
, TRUE
);
381 void wxShape::SetDrawHandles(bool drawH
)
383 m_drawHandles
= drawH
;
384 wxNode
*node
= m_children
.First();
387 wxShape
*obj
= (wxShape
*)node
->Data();
388 obj
->SetDrawHandles(drawH
);
393 void wxShape::SetShadowMode(int mode
, bool redraw
)
395 if (redraw
&& GetCanvas())
397 wxClientDC
dc(GetCanvas());
398 GetCanvas()->PrepareDC(dc
);
411 void wxShape::SetCanvas(wxShapeCanvas
*theCanvas
)
413 m_canvas
= theCanvas
;
414 wxNode
*node
= m_children
.First();
417 wxShape
*child
= (wxShape
*)node
->Data();
418 child
->SetCanvas(theCanvas
);
423 void wxShape::AddToCanvas(wxShapeCanvas
*theCanvas
, wxShape
*addAfter
)
425 theCanvas
->AddShape(this, addAfter
);
426 wxNode
*node
= m_children
.First();
427 wxShape
*lastImage
= this;
430 wxShape
*object
= (wxShape
*)node
->Data();
431 object
->AddToCanvas(theCanvas
, lastImage
);
438 // Insert at front of canvas
439 void wxShape::InsertInCanvas(wxShapeCanvas
*theCanvas
)
441 theCanvas
->InsertShape(this);
442 wxNode
*node
= m_children
.First();
443 wxShape
*lastImage
= this;
446 wxShape
*object
= (wxShape
*)node
->Data();
447 object
->AddToCanvas(theCanvas
, lastImage
);
454 void wxShape::RemoveFromCanvas(wxShapeCanvas
*theCanvas
)
458 theCanvas
->RemoveShape(this);
459 wxNode
*node
= m_children
.First();
462 wxShape
*object
= (wxShape
*)node
->Data();
463 object
->RemoveFromCanvas(theCanvas
);
469 void wxShape::ClearAttachments()
471 wxNode
*node
= m_attachmentPoints
.First();
474 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->Data();
478 m_attachmentPoints
.Clear();
481 void wxShape::ClearText(int regionId
)
485 m_text
.DeleteContents(TRUE
);
487 m_text
.DeleteContents(FALSE
);
489 wxNode
*node
= m_regions
.Nth(regionId
);
492 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
496 void wxShape::ClearRegions()
498 wxNode
*node
= m_regions
.First();
501 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
502 wxNode
*next
= node
->Next();
509 void wxShape::AddRegion(wxShapeRegion
*region
)
511 m_regions
.Append(region
);
514 void wxShape::SetDefaultRegionSize()
516 wxNode
*node
= m_regions
.First();
518 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
520 GetBoundingBoxMin(&w
, &h
);
521 region
->SetSize(w
, h
);
524 bool wxShape::HitTest(double x
, double y
, int *attachment
, double *distance
)
529 double width
= 0.0, height
= 0.0;
530 GetBoundingBoxMin(&width
, &height
);
531 if (fabs(width
) < 4.0) width
= 4.0;
532 if (fabs(height
) < 4.0) height
= 4.0;
534 width
+= (double)4.0; height
+= (double)4.0; // Allowance for inaccurate mousing
536 double left
= (double)(m_xpos
- (width
/2.0));
537 double top
= (double)(m_ypos
- (height
/2.0));
538 double right
= (double)(m_xpos
+ (width
/2.0));
539 double bottom
= (double)(m_ypos
+ (height
/2.0));
541 int nearest_attachment
= 0;
544 // If within the bounding box, check the attachment points
545 // within the object.
547 if (x
>= left
&& x
<= right
&& y
>= top
&& y
<= bottom
)
549 int n
= GetNumberOfAttachments();
550 double nearest
= 999999.0;
552 for (int i
= 0; i
< n
; i
++)
555 if (GetAttachmentPosition(i
, &xp
, &yp
))
557 double l
= (double)sqrt(((xp
- x
) * (xp
- x
)) +
558 ((yp
- y
) * (yp
- y
)));
563 nearest_attachment
= i
;
567 *attachment
= nearest_attachment
;
574 // Format a text string according to the region size, adding
575 // strings with positions to region text list
577 static bool GraphicsInSizeToContents
= FALSE
; // Infinite recursion elimination
578 void wxShape::FormatText(wxDC
& dc
, const wxString
& s
, int i
)
583 if (m_regions
.Number() < 1)
585 wxNode
*node
= m_regions
.Nth(i
);
589 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
591 dc
.SetFont(region
->GetFont());
593 region
->GetSize(&w
, &h
);
595 wxStringList
*stringList
= oglFormatText(dc
, s
, (w
-5), (h
-5), region
->GetFormatMode());
596 node
= stringList
->First();
599 char *s
= (char *)node
->Data();
600 wxShapeTextLine
*line
= new wxShapeTextLine(0.0, 0.0, s
);
601 region
->GetFormattedText().Append((wxObject
*)line
);
607 // Don't try to resize an object with more than one image (this case should be dealt
608 // with by overriden handlers)
609 if ((region
->GetFormatMode() & FORMAT_SIZE_TO_CONTENTS
) &&
610 (region
->GetFormattedText().Number() > 0) &&
611 (m_regions
.Number() == 1) && !GraphicsInSizeToContents
)
613 oglGetCentredTextExtent(dc
, &(region
->GetFormattedText()), m_xpos
, m_ypos
, w
, h
, &actualW
, &actualH
);
614 if ((actualW
+m_textMarginX
!= w
) || (actualH
+m_textMarginY
!= h
))
616 // If we are a descendant of a composite, must make sure the composite gets
618 wxShape
*topAncestor
= GetTopAncestor();
620 if (topAncestor
!= this)
622 // Make sure we don't recurse infinitely
623 GraphicsInSizeToContents
= TRUE
;
625 wxCompositeShape
*composite
= (wxCompositeShape
*)topAncestor
;
626 composite
->Erase(dc
);
627 SetSize(actualW
+m_textMarginX
, actualH
+m_textMarginY
);
628 Move(dc
, m_xpos
, m_ypos
);
629 composite
->CalculateSize();
630 if (composite
->Selected())
632 composite
->DeleteControlPoints(& dc
);
633 composite
->MakeControlPoints();
634 composite
->MakeMandatoryControlPoints();
636 // Where infinite recursion might happen if we didn't stop it
639 GraphicsInSizeToContents
= FALSE
;
644 SetSize(actualW
+m_textMarginX
, actualH
+m_textMarginY
);
645 Move(dc
, m_xpos
, m_ypos
);
647 SetSize(actualW
+m_textMarginX
, actualH
+m_textMarginY
);
648 Move(dc
, m_xpos
, m_ypos
);
652 oglCentreText(dc
, &(region
->GetFormattedText()), m_xpos
, m_ypos
, actualW
, actualH
, region
->GetFormatMode());
656 void wxShape::Recentre(wxDC
& dc
)
659 GetBoundingBoxMin(&w
, &h
);
661 int noRegions
= m_regions
.Number();
662 for (int i
= 0; i
< noRegions
; i
++)
664 wxNode
*node
= m_regions
.Nth(i
);
667 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
668 oglCentreText(dc
, &(region
->GetFormattedText()), m_xpos
, m_ypos
, w
, h
, region
->GetFormatMode());
673 bool wxShape::GetPerimeterPoint(double x1
, double y1
,
674 double x2
, double y2
,
675 double *x3
, double *y3
)
680 void wxShape::SetPen(wxPen
*the_pen
)
685 void wxShape::SetBrush(wxBrush
*the_brush
)
690 // Get the top-most (non-division) ancestor, or self
691 wxShape
*wxShape::GetTopAncestor()
696 if (GetParent()->IsKindOf(CLASSINFO(wxDivisionShape
)))
698 else return GetParent()->GetTopAncestor();
705 void wxShape::SetFont(wxFont
*the_font
, int regionId
)
708 wxNode
*node
= m_regions
.Nth(regionId
);
711 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
712 region
->SetFont(the_font
);
715 wxFont
*wxShape::GetFont(int n
) const
717 wxNode
*node
= m_regions
.Nth(n
);
720 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
721 return region
->GetFont();
724 void wxShape::SetFormatMode(int mode
, int regionId
)
726 wxNode
*node
= m_regions
.Nth(regionId
);
729 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
730 region
->SetFormatMode(mode
);
733 int wxShape::GetFormatMode(int regionId
) const
735 wxNode
*node
= m_regions
.Nth(regionId
);
738 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
739 return region
->GetFormatMode();
742 void wxShape::SetTextColour(const wxString
& the_colour
, int regionId
)
744 wxColour
*wxcolour
= wxTheColourDatabase
->FindColour(the_colour
);
745 m_textColour
= wxcolour
;
746 m_textColourName
= the_colour
;
748 wxNode
*node
= m_regions
.Nth(regionId
);
751 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
752 region
->SetColour(the_colour
);
755 wxString
wxShape::GetTextColour(int regionId
) const
757 wxNode
*node
= m_regions
.Nth(regionId
);
760 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
761 return region
->GetColour();
764 void wxShape::SetRegionName(const wxString
& name
, int regionId
)
766 wxNode
*node
= m_regions
.Nth(regionId
);
769 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
770 region
->SetName(name
);
773 wxString
wxShape::GetRegionName(int regionId
)
775 wxNode
*node
= m_regions
.Nth(regionId
);
778 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
779 return region
->GetName();
782 int wxShape::GetRegionId(const wxString
& name
)
784 wxNode
*node
= m_regions
.First();
788 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
789 if (region
->GetName() == name
)
797 // Name all m_regions in all subimages recursively.
798 void wxShape::NameRegions(const wxString
& parentName
)
800 int n
= GetNumberOfTextRegions();
802 for (int i
= 0; i
< n
; i
++)
804 if (parentName
.Length() > 0)
805 sprintf(buf
, "%s.%d", (const char*) parentName
, i
);
807 sprintf(buf
, "%d", i
);
808 SetRegionName(buf
, i
);
810 wxNode
*node
= m_children
.First();
814 wxShape
*child
= (wxShape
*)node
->Data();
815 if (parentName
.Length() > 0)
816 sprintf(buf
, "%s.%d", (const char*) parentName
, j
);
818 sprintf(buf
, "%d", j
);
819 child
->NameRegions(buf
);
825 // Get a region by name, possibly looking recursively into composites.
826 wxShape
*wxShape::FindRegion(const wxString
& name
, int *regionId
)
828 int id
= GetRegionId(name
);
835 wxNode
*node
= m_children
.First();
838 wxShape
*child
= (wxShape
*)node
->Data();
839 wxShape
*actualImage
= child
->FindRegion(name
, regionId
);
847 // Finds all region names for this image (composite or simple).
848 // Supply empty string list.
849 void wxShape::FindRegionNames(wxStringList
& list
)
851 int n
= GetNumberOfTextRegions();
852 for (int i
= 0; i
< n
; i
++)
854 wxString
name(GetRegionName(i
));
855 list
.Add((const char*) name
);
858 wxNode
*node
= m_children
.First();
861 wxShape
*child
= (wxShape
*)node
->Data();
862 child
->FindRegionNames(list
);
867 void wxShape::AssignNewIds()
871 wxNode
*node
= m_children
.First();
874 wxShape
*child
= (wxShape
*)node
->Data();
875 child
->AssignNewIds();
880 void wxShape::OnDraw(wxDC
& dc
)
884 void wxShape::OnMoveLinks(wxDC
& dc
)
886 // Want to set the ends of all attached links
887 // to point to/from this object
889 wxNode
*current
= m_lines
.First();
892 wxLineShape
*line
= (wxLineShape
*)current
->Data();
893 line
->GetEventHandler()->OnMoveLink(dc
);
894 current
= current
->Next();
899 void wxShape::OnDrawContents(wxDC
& dc
)
901 double bound_x
, bound_y
;
902 GetBoundingBoxMin(&bound_x
, &bound_y
);
903 if (m_regions
.Number() < 1) return;
905 if (m_pen
) dc
.SetPen(m_pen
);
907 wxShapeRegion
*region
= (wxShapeRegion
*)m_regions
.First()->Data();
908 if (region
->GetFont()) dc
.SetFont(region
->GetFont());
910 dc
.SetTextForeground(* (region
->GetActualColourObject()));
911 dc
.SetBackgroundMode(wxTRANSPARENT
);
914 oglCentreText(dc
, &(region
->GetFormattedText()), m_xpos
, m_ypos
, bound_x
, bound_y
, region
->GetFormatMode());
917 if (!GetDisableLabel())
919 oglDrawFormattedText(dc
, &(region
->GetFormattedText()), m_xpos
, m_ypos
, bound_x
, bound_y
, region
->GetFormatMode());
923 void wxShape::DrawContents(wxDC
& dc
)
925 GetEventHandler()->OnDrawContents(dc
);
928 void wxShape::OnSize(double x
, double y
)
932 bool wxShape::OnMovePre(wxDC
& dc
, double x
, double y
, double old_x
, double old_y
, bool display
)
937 void wxShape::OnMovePost(wxDC
& dc
, double x
, double y
, double old_x
, double old_y
, bool display
)
941 void wxShape::OnErase(wxDC
& dc
)
947 wxNode
*current
= m_lines
.First();
950 wxLineShape
*line
= (wxLineShape
*)current
->Data();
951 line
->GetEventHandler()->OnErase(dc
);
952 current
= current
->Next();
954 GetEventHandler()->OnEraseContents(dc
);
957 void wxShape::OnEraseContents(wxDC
& dc
)
962 double maxX
, maxY
, minX
, minY
;
965 GetBoundingBoxMin(&minX
, &minY
);
966 GetBoundingBoxMax(&maxX
, &maxY
);
967 double topLeftX
= (double)(xp
- (maxX
/ 2.0) - 2.0);
968 double topLeftY
= (double)(yp
- (maxY
/ 2.0) - 2.0);
972 penWidth
= m_pen
->GetWidth();
974 dc
.SetPen(g_oglWhiteBackgroundPen
);
975 dc
.SetBrush(g_oglWhiteBackgroundBrush
);
976 dc
.DrawRectangle(WXROUND(topLeftX
- penWidth
), WXROUND(topLeftY
- penWidth
),
977 WXROUND(maxX
+ penWidth
*2.0 + 4.0), WXROUND(maxY
+ penWidth
*2.0 + 4.0));
980 void wxShape::EraseLinks(wxDC
& dc
, int attachment
, bool recurse
)
985 wxNode
*current
= m_lines
.First();
988 wxLineShape
*line
= (wxLineShape
*)current
->Data();
989 if (attachment
== -1 || ((line
->GetTo() == this && line
->GetAttachmentTo() == attachment
) ||
990 (line
->GetFrom() == this && line
->GetAttachmentFrom() == attachment
)))
991 line
->GetEventHandler()->OnErase(dc
);
992 current
= current
->Next();
996 wxNode
*node
= m_children
.First();
999 wxShape
*child
= (wxShape
*)node
->Data();
1000 child
->EraseLinks(dc
, attachment
, recurse
);
1001 node
= node
->Next();
1006 void wxShape::DrawLinks(wxDC
& dc
, int attachment
, bool recurse
)
1011 wxNode
*current
= m_lines
.First();
1014 wxLineShape
*line
= (wxLineShape
*)current
->Data();
1015 if (attachment
== -1 ||
1016 (line
->GetTo() == this && line
->GetAttachmentTo() == attachment
) ||
1017 (line
->GetFrom() == this && line
->GetAttachmentFrom() == attachment
))
1019 current
= current
->Next();
1023 wxNode
*node
= m_children
.First();
1026 wxShape
*child
= (wxShape
*)node
->Data();
1027 child
->DrawLinks(dc
, attachment
, recurse
);
1028 node
= node
->Next();
1033 // Returns TRUE if pt1 <= pt2 in the sense that one point comes before another on an
1034 // edge of the shape.
1035 // attachmentPoint is the attachment point (= side) in question.
1037 // This is the default, rectangular implementation.
1038 bool wxShape::AttachmentSortTest(int attachmentPoint
, const wxRealPoint
& pt1
, const wxRealPoint
& pt2
)
1040 switch (attachmentPoint
)
1045 return (pt1
.x
<= pt2
.x
) ;
1051 return (pt1
.y
<= pt2
.y
) ;
1059 bool wxShape::MoveLineToNewAttachment(wxDC
& dc
, wxLineShape
*to_move
,
1062 if (!GetAttachmentMode())
1065 int newAttachment
, oldAttachment
;
1068 // Is (x, y) on this object? If so, find the new attachment point
1069 // the user has moved the point to
1070 bool hit
= HitTest(x
, y
, &newAttachment
, &distance
);
1076 if (to_move
->GetTo() == this)
1077 oldAttachment
= to_move
->GetAttachmentTo();
1079 oldAttachment
= to_move
->GetAttachmentFrom();
1081 // The links in a new ordering.
1084 // First, add all links to the new list.
1085 wxNode
*node
= m_lines
.First();
1088 newOrdering
.Append(node
->Data());
1089 node
= node
->Next();
1092 // Delete the line object from the list of links; we're going to move
1093 // it to another position in the list
1094 newOrdering
.DeleteObject(to_move
);
1096 double old_x
= (double) -99999.9;
1097 double old_y
= (double) -99999.9;
1099 node
= newOrdering
.First();
1102 while (!found
&& node
)
1104 wxLineShape
*line
= (wxLineShape
*)node
->Data();
1105 if ((line
->GetTo() == this && oldAttachment
== line
->GetAttachmentTo()) ||
1106 (line
->GetFrom() == this && oldAttachment
== line
->GetAttachmentFrom()))
1108 double startX
, startY
, endX
, endY
;
1110 line
->GetEnds(&startX
, &startY
, &endX
, &endY
);
1111 if (line
->GetTo() == this)
1121 wxRealPoint
thisPoint(xp
, yp
);
1122 wxRealPoint
lastPoint(old_x
, old_y
);
1123 wxRealPoint
newPoint(x
, y
);
1125 if (AttachmentSortTest(newAttachment
, newPoint
, thisPoint
) && AttachmentSortTest(newAttachment
, lastPoint
, newPoint
))
1128 newOrdering
.Insert(node
, to_move
);
1134 node
= node
->Next();
1138 newOrdering
.Append(to_move
);
1140 GetEventHandler()->OnChangeAttachment(newAttachment
, to_move
, newOrdering
);
1145 void wxShape::OnChangeAttachment(int attachment
, wxLineShape
* line
, wxList
& ordering
)
1147 if (line
->GetTo() == this)
1148 line
->SetAttachmentTo(attachment
);
1150 line
->SetAttachmentFrom(attachment
);
1152 ApplyAttachmentOrdering(ordering
);
1154 wxClientDC
dc(GetCanvas());
1155 GetCanvas()->PrepareDC(dc
);
1159 if (!GetCanvas()->GetQuickEditMode()) GetCanvas()->Redraw(dc
);
1162 // Reorders the lines according to the given list.
1163 void wxShape::ApplyAttachmentOrdering(wxList
& linesToSort
)
1165 // This is a temporary store of all the lines.
1168 wxNode
*node
= m_lines
.First();
1171 wxLineShape
*line
= (wxLineShape
*)node
->Data();
1172 linesStore
.Append(line
);
1173 node
= node
->Next();;
1178 node
= linesToSort
.First();
1181 wxLineShape
*line
= (wxLineShape
*)node
->Data();
1182 if (linesStore
.Member(line
))
1185 linesStore
.DeleteObject(line
);
1186 m_lines
.Append(line
);
1188 node
= node
->Next();
1191 // Now add any lines that haven't been listed in linesToSort.
1192 node
= linesStore
.First();
1195 wxLineShape
*line
= (wxLineShape
*)node
->Data();
1196 m_lines
.Append(line
);
1197 node
= node
->Next();
1201 // Reorders the lines coming into the node image at this attachment
1202 // position, in the order in which they appear in linesToSort.
1203 // Any remaining lines not in the list will be added to the end.
1204 void wxShape::SortLines(int attachment
, wxList
& linesToSort
)
1206 // This is a temporary store of all the lines at this attachment
1207 // point. We'll tick them off as we've processed them.
1208 wxList linesAtThisAttachment
;
1210 wxNode
*node
= m_lines
.First();
1213 wxLineShape
*line
= (wxLineShape
*)node
->Data();
1214 wxNode
*next
= node
->Next();
1215 if ((line
->GetTo() == this && line
->GetAttachmentTo() == attachment
) ||
1216 (line
->GetFrom() == this && line
->GetAttachmentFrom() == attachment
))
1218 linesAtThisAttachment
.Append(line
);
1222 else node
= node
->Next();
1225 node
= linesToSort
.First();
1228 wxLineShape
*line
= (wxLineShape
*)node
->Data();
1229 if (linesAtThisAttachment
.Member(line
))
1232 linesAtThisAttachment
.DeleteObject(line
);
1233 m_lines
.Append(line
);
1235 node
= node
->Next();
1238 // Now add any lines that haven't been listed in linesToSort.
1239 node
= linesAtThisAttachment
.First();
1242 wxLineShape
*line
= (wxLineShape
*)node
->Data();
1243 m_lines
.Append(line
);
1244 node
= node
->Next();
1248 void wxShape::OnHighlight(wxDC
& dc
)
1252 void wxShape::OnLeftClick(double x
, double y
, int keys
, int attachment
)
1254 if ((m_sensitivity
& OP_CLICK_LEFT
) != OP_CLICK_LEFT
)
1260 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1261 m_parent
->GetEventHandler()->OnLeftClick(x
, y
, keys
, attachment
);
1267 void wxShape::OnRightClick(double x
, double y
, int keys
, int attachment
)
1269 if ((m_sensitivity
& OP_CLICK_RIGHT
) != OP_CLICK_RIGHT
)
1275 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1276 m_parent
->GetEventHandler()->OnRightClick(x
, y
, keys
, attachment
);
1282 double DragOffsetX
= 0.0;
1283 double DragOffsetY
= 0.0;
1285 void wxShape::OnDragLeft(bool draw
, double x
, double y
, int keys
, int attachment
)
1287 if ((m_sensitivity
& OP_DRAG_LEFT
) != OP_DRAG_LEFT
)
1293 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1294 m_parent
->GetEventHandler()->OnDragLeft(draw
, x
, y
, keys
, attachment
);
1299 wxClientDC
dc(GetCanvas());
1300 GetCanvas()->PrepareDC(dc
);
1302 dc
.SetLogicalFunction(wxXOR
);
1304 wxPen
dottedPen(wxColour(0, 0, 0), 1, wxDOT
);
1305 dc
.SetPen(dottedPen
);
1306 dc
.SetBrush(* wxTRANSPARENT_BRUSH
);
1309 xx
= x
+ DragOffsetX
;
1310 yy
= y
+ DragOffsetY
;
1312 m_canvas
->Snap(&xx
, &yy
);
1313 // m_xpos = xx; m_ypos = yy;
1315 GetBoundingBoxMax(&w
, &h
);
1316 GetEventHandler()->OnDrawOutline(dc
, xx
, yy
, w
, h
);
1319 void wxShape::OnBeginDragLeft(double x
, double y
, int keys
, int attachment
)
1321 if ((m_sensitivity
& OP_DRAG_LEFT
) != OP_DRAG_LEFT
)
1327 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1328 m_parent
->GetEventHandler()->OnBeginDragLeft(x
, y
, keys
, attachment
);
1333 DragOffsetX
= m_xpos
- x
;
1334 DragOffsetY
= m_ypos
- y
;
1336 wxClientDC
dc(GetCanvas());
1337 GetCanvas()->PrepareDC(dc
);
1339 // New policy: don't erase shape until end of drag.
1343 xx
= x
+ DragOffsetX
;
1344 yy
= y
+ DragOffsetY
;
1345 m_canvas
->Snap(&xx
, &yy
);
1346 // m_xpos = xx; m_ypos = yy;
1347 dc
.SetLogicalFunction(wxXOR
);
1349 wxPen
dottedPen(wxColour(0, 0, 0), 1, wxDOT
);
1350 dc
.SetPen(dottedPen
);
1351 dc
.SetBrush((* wxTRANSPARENT_BRUSH
));
1354 GetBoundingBoxMax(&w
, &h
);
1355 GetEventHandler()->OnDrawOutline(dc
, xx
, yy
, w
, h
);
1356 m_canvas
->CaptureMouse();
1359 void wxShape::OnEndDragLeft(double x
, double y
, int keys
, int attachment
)
1361 m_canvas
->ReleaseMouse();
1362 if ((m_sensitivity
& OP_DRAG_LEFT
) != OP_DRAG_LEFT
)
1368 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1369 m_parent
->GetEventHandler()->OnEndDragLeft(x
, y
, keys
, attachment
);
1374 wxClientDC
dc(GetCanvas());
1375 GetCanvas()->PrepareDC(dc
);
1377 dc
.SetLogicalFunction(wxCOPY
);
1379 double xx
= x
+ DragOffsetX
;
1380 double yy
= y
+ DragOffsetY
;
1381 m_canvas
->Snap(&xx
, &yy
);
1382 // canvas->Snap(&m_xpos, &m_ypos);
1384 // New policy: erase shape at end of drag.
1388 if (m_canvas
&& !m_canvas
->GetQuickEditMode()) m_canvas
->Redraw(dc
);
1391 void wxShape::OnDragRight(bool draw
, double x
, double y
, int keys
, int attachment
)
1393 if ((m_sensitivity
& OP_DRAG_RIGHT
) != OP_DRAG_RIGHT
)
1399 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1400 m_parent
->GetEventHandler()->OnDragRight(draw
, x
, y
, keys
, attachment
);
1406 void wxShape::OnBeginDragRight(double x
, double y
, int keys
, int attachment
)
1408 if ((m_sensitivity
& OP_DRAG_RIGHT
) != OP_DRAG_RIGHT
)
1414 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1415 m_parent
->GetEventHandler()->OnBeginDragRight(x
, y
, keys
, attachment
);
1421 void wxShape::OnEndDragRight(double x
, double y
, int keys
, int attachment
)
1423 if ((m_sensitivity
& OP_DRAG_RIGHT
) != OP_DRAG_RIGHT
)
1429 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1430 m_parent
->GetEventHandler()->OnEndDragRight(x
, y
, keys
, attachment
);
1436 void wxShape::OnDrawOutline(wxDC
& dc
, double x
, double y
, double w
, double h
)
1438 double top_left_x
= (double)(x
- w
/2.0);
1439 double top_left_y
= (double)(y
- h
/2.0);
1440 double top_right_x
= (double)(top_left_x
+ w
);
1441 double top_right_y
= (double)top_left_y
;
1442 double bottom_left_x
= (double)top_left_x
;
1443 double bottom_left_y
= (double)(top_left_y
+ h
);
1444 double bottom_right_x
= (double)top_right_x
;
1445 double bottom_right_y
= (double)bottom_left_y
;
1448 points
[0].x
= WXROUND(top_left_x
); points
[0].y
= WXROUND(top_left_y
);
1449 points
[1].x
= WXROUND(top_right_x
); points
[1].y
= WXROUND(top_right_y
);
1450 points
[2].x
= WXROUND(bottom_right_x
); points
[2].y
= WXROUND(bottom_right_y
);
1451 points
[3].x
= WXROUND(bottom_left_x
); points
[3].y
= WXROUND(bottom_left_y
);
1452 points
[4].x
= WXROUND(top_left_x
); points
[4].y
= WXROUND(top_left_y
);
1454 dc
.DrawLines(5, points
);
1457 void wxShape::Attach(wxShapeCanvas
*can
)
1462 void wxShape::Detach()
1467 void wxShape::Move(wxDC
& dc
, double x
, double y
, bool display
)
1469 double old_x
= m_xpos
;
1470 double old_y
= m_ypos
;
1472 if (!GetEventHandler()->OnMovePre(dc
, x
, y
, old_x
, old_y
, display
))
1479 m_xpos
= x
; m_ypos
= y
;
1481 ResetControlPoints();
1488 GetEventHandler()->OnMovePost(dc
, x
, y
, old_x
, old_y
, display
);
1491 void wxShape::MoveLinks(wxDC
& dc
)
1493 GetEventHandler()->OnMoveLinks(dc
);
1497 void wxShape::Draw(wxDC
& dc
)
1501 GetEventHandler()->OnDraw(dc
);
1502 GetEventHandler()->OnDrawContents(dc
);
1503 GetEventHandler()->OnDrawControlPoints(dc
);
1507 void wxShape::Flash()
1511 wxClientDC
dc(GetCanvas());
1512 GetCanvas()->PrepareDC(dc
);
1514 dc
.SetLogicalFunction(wxXOR
);
1516 dc
.SetLogicalFunction(wxCOPY
);
1521 void wxShape::Show(bool show
)
1524 wxNode
*node
= m_children
.First();
1527 wxShape
*image
= (wxShape
*)node
->Data();
1529 node
= node
->Next();
1533 void wxShape::Erase(wxDC
& dc
)
1535 GetEventHandler()->OnErase(dc
);
1536 GetEventHandler()->OnEraseControlPoints(dc
);
1539 void wxShape::EraseContents(wxDC
& dc
)
1541 GetEventHandler()->OnEraseContents(dc
);
1544 void wxShape::AddText(const wxString
& string
)
1546 wxNode
*node
= m_regions
.First();
1549 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
1550 region
->ClearText();
1551 wxShapeTextLine
*new_line
=
1552 new wxShapeTextLine(0.0, 0.0, string
);
1553 region
->GetFormattedText().Append(new_line
);
1555 m_formatted
= FALSE
;
1558 void wxShape::SetSize(double x
, double y
, bool recursive
)
1560 SetAttachmentSize(x
, y
);
1561 SetDefaultRegionSize();
1564 void wxShape::SetAttachmentSize(double w
, double h
)
1568 double width
, height
;
1569 GetBoundingBoxMin(&width
, &height
);
1572 else scaleX
= w
/width
;
1575 else scaleY
= h
/height
;
1577 wxNode
*node
= m_attachmentPoints
.First();
1580 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->Data();
1581 point
->m_x
= (double)(point
->m_x
* scaleX
);
1582 point
->m_y
= (double)(point
->m_y
* scaleY
);
1583 node
= node
->Next();
1587 // Add line FROM this object
1588 void wxShape::AddLine(wxLineShape
*line
, wxShape
*other
,
1589 int attachFrom
, int attachTo
,
1590 // The line ordering
1591 int positionFrom
, int positionTo
)
1593 m_lines
.DeleteObject(line
);
1594 other
->m_lines
.DeleteObject(line
);
1596 if (positionFrom
== -1)
1597 m_lines
.Append(line
);
1600 if (positionFrom
< m_lines
.Number())
1602 wxNode
* node
= m_lines
.Nth(positionFrom
);
1603 m_lines
.Insert(node
, line
);
1606 m_lines
.Append(line
);
1609 if (positionTo
== -1)
1610 other
->m_lines
.Append(line
);
1613 if (positionTo
< other
->m_lines
.Number())
1615 wxNode
* node
= other
->m_lines
.Nth(positionTo
);
1616 other
->m_lines
.Insert(node
, line
);
1619 other
->m_lines
.Append(line
);
1622 line
->SetFrom(this);
1624 line
->SetAttachments(attachFrom
, attachTo
);
1627 void wxShape::RemoveLine(wxLineShape
*line
)
1629 if (line
->GetFrom() == this)
1630 line
->GetTo()->m_lines
.DeleteObject(line
);
1632 line
->GetFrom()->m_lines
.DeleteObject(line
);
1634 m_lines
.DeleteObject(line
);
1638 void wxShape::WriteAttributes(wxExpr
*clause
)
1640 clause
->AddAttributeValueString("type", GetClassInfo()->GetClassName());
1641 clause
->AddAttributeValue("id", m_id
);
1645 int penWidth
= m_pen
->GetWidth();
1646 int penStyle
= m_pen
->GetStyle();
1648 clause
->AddAttributeValue("pen_width", (long)penWidth
);
1649 if (penStyle
!= wxSOLID
)
1650 clause
->AddAttributeValue("pen_style", (long)penStyle
);
1652 wxString penColour
= wxTheColourDatabase
->FindName(m_pen
->GetColour());
1653 if (penColour
== "")
1655 wxString
hex(oglColourToHex(m_pen
->GetColour()));
1656 hex
= wxString("#") + hex
;
1657 clause
->AddAttributeValueString("pen_colour", hex
);
1659 else if (penColour
!= "BLACK")
1660 clause
->AddAttributeValueString("pen_colour", penColour
);
1665 wxString brushColour
= wxTheColourDatabase
->FindName(m_brush
->GetColour());
1667 if (brushColour
== "")
1669 wxString
hex(oglColourToHex(m_brush
->GetColour()));
1670 hex
= wxString("#") + hex
;
1671 clause
->AddAttributeValueString("brush_colour", hex
);
1673 else if (brushColour
!= "WHITE")
1674 clause
->AddAttributeValueString("brush_colour", brushColour
);
1676 if (m_brush
->GetStyle() != wxSOLID
)
1677 clause
->AddAttributeValue("brush_style", (long)m_brush
->GetStyle());
1682 int n_lines
= m_lines
.Number();
1685 wxExpr
*list
= new wxExpr(PrologList
);
1686 wxNode
*node
= m_lines
.First();
1689 wxShape
*line
= (wxShape
*)node
->Data();
1690 wxExpr
*id_expr
= new wxExpr(line
->GetId());
1691 list
->Append(id_expr
);
1692 node
= node
->Next();
1694 clause
->AddAttributeValue("arcs", list
);
1697 // Miscellaneous members
1698 if (m_attachmentMode
!= 0)
1699 clause
->AddAttributeValue("use_attachments", (long)m_attachmentMode
);
1700 if (m_sensitivity
!= OP_ALL
)
1701 clause
->AddAttributeValue("sensitivity", (long)m_sensitivity
);
1702 if (!m_spaceAttachments
)
1703 clause
->AddAttributeValue("space_attachments", (long)m_spaceAttachments
);
1705 clause
->AddAttributeValue("fixed_width", (long)m_fixedWidth
);
1707 clause
->AddAttributeValue("fixed_height", (long)m_fixedHeight
);
1708 if (m_shadowMode
!= SHADOW_NONE
)
1709 clause
->AddAttributeValue("shadow_mode", (long)m_shadowMode
);
1710 if (m_centreResize
!= TRUE
)
1711 clause
->AddAttributeValue("centre_resize", (long)0);
1712 if (m_highlighted
!= FALSE
)
1713 clause
->AddAttributeValue("hilite", (long)m_highlighted
);
1715 if (m_parent
) // For composite objects
1716 clause
->AddAttributeValue("parent", (long)m_parent
->GetId());
1718 if (m_rotation
!= 0.0)
1719 clause
->AddAttributeValue("rotation", m_rotation
);
1721 // Write user-defined attachment points, if any
1722 if (m_attachmentPoints
.Number() > 0)
1724 wxExpr
*attachmentList
= new wxExpr(PrologList
);
1725 wxNode
*node
= m_attachmentPoints
.First();
1728 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->Data();
1729 wxExpr
*pointExpr
= new wxExpr(PrologList
);
1730 pointExpr
->Append(new wxExpr((long)point
->m_id
));
1731 pointExpr
->Append(new wxExpr(point
->m_x
));
1732 pointExpr
->Append(new wxExpr(point
->m_y
));
1733 attachmentList
->Append(pointExpr
);
1734 node
= node
->Next();
1736 clause
->AddAttributeValue("user_attachments", attachmentList
);
1739 // Write text regions
1740 WriteRegions(clause
);
1743 void wxShape::WriteRegions(wxExpr
*clause
)
1745 // Output regions as region1 = (...), region2 = (...), etc
1746 // and formatted text as text1 = (...), text2 = (...) etc.
1748 char regionNameBuf
[20];
1749 char textNameBuf
[20];
1750 wxNode
*node
= m_regions
.First();
1753 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
1754 sprintf(regionNameBuf
, "region%d", regionNo
);
1755 sprintf(textNameBuf
, "text%d", regionNo
);
1757 // Original text and region attributes:
1758 // region1 = (regionName regionText x y width height minWidth minHeight proportionX proportionY
1759 // formatMode fontSize fontFamily fontStyle fontWeight textColour)
1760 wxExpr
*regionExpr
= new wxExpr(PrologList
);
1761 regionExpr
->Append(new wxExpr(PrologString
, (region
->m_regionName
? region
->m_regionName
: "")));
1762 regionExpr
->Append(new wxExpr(PrologString
, (region
->m_regionText
? region
->m_regionText
: "")));
1764 regionExpr
->Append(new wxExpr(region
->m_x
));
1765 regionExpr
->Append(new wxExpr(region
->m_y
));
1766 regionExpr
->Append(new wxExpr(region
->GetWidth()));
1767 regionExpr
->Append(new wxExpr(region
->GetHeight()));
1769 regionExpr
->Append(new wxExpr(region
->m_minWidth
));
1770 regionExpr
->Append(new wxExpr(region
->m_minHeight
));
1771 regionExpr
->Append(new wxExpr(region
->m_regionProportionX
));
1772 regionExpr
->Append(new wxExpr(region
->m_regionProportionY
));
1774 regionExpr
->Append(new wxExpr((long)region
->m_formatMode
));
1776 regionExpr
->Append(new wxExpr((long)(region
->m_font
? region
->m_font
->GetPointSize() : 10)));
1777 regionExpr
->Append(new wxExpr((long)(region
->m_font
? region
->m_font
->GetFamily() : wxDEFAULT
)));
1778 regionExpr
->Append(new wxExpr((long)(region
->m_font
? region
->m_font
->GetStyle() : wxDEFAULT
)));
1779 regionExpr
->Append(new wxExpr((long)(region
->m_font
? region
->m_font
->GetWeight() : wxNORMAL
)));
1780 regionExpr
->Append(new wxExpr(PrologString
, region
->m_textColour
? region
->m_textColour
: "BLACK"));
1782 // New members for pen colour/style
1783 regionExpr
->Append(new wxExpr(PrologString
, region
->m_penColour
? region
->m_penColour
: "BLACK"));
1784 regionExpr
->Append(new wxExpr((long)region
->m_penStyle
));
1787 // text1 = ((x y string) (x y string) ...)
1788 wxExpr
*textExpr
= new wxExpr(PrologList
);
1790 wxNode
*textNode
= region
->m_formattedText
.First();
1793 wxShapeTextLine
*line
= (wxShapeTextLine
*)textNode
->Data();
1794 wxExpr
*list2
= new wxExpr(PrologList
);
1795 list2
->Append(new wxExpr(line
->GetX()));
1796 list2
->Append(new wxExpr(line
->GetY()));
1797 list2
->Append(new wxExpr(PrologString
, line
->GetText()));
1798 textExpr
->Append(list2
);
1799 textNode
= textNode
->Next();
1802 // Now add both attributes to the clause
1803 clause
->AddAttributeValue(regionNameBuf
, regionExpr
);
1804 clause
->AddAttributeValue(textNameBuf
, textExpr
);
1806 node
= node
->Next();
1811 void wxShape::ReadAttributes(wxExpr
*clause
)
1813 clause
->GetAttributeValue("id", m_id
);
1816 clause
->GetAttributeValue("x", m_xpos
);
1817 clause
->GetAttributeValue("y", m_ypos
);
1819 // Input text strings (FOR COMPATIBILITY WITH OLD FILES ONLY. SEE REGION CODE BELOW.)
1821 wxExpr
*strings
= clause
->AttributeValue("text");
1822 if (strings
&& strings
->Type() == PrologList
)
1824 m_formatted
= TRUE
; // Assume text is formatted unless we prove otherwise
1825 wxExpr
*node
= strings
->value
.first
;
1828 wxExpr
*string_expr
= node
;
1831 wxString
the_string("");
1833 // string_expr can either be a string, or a list of
1834 // 3 elements: x, y, and string.
1835 if (string_expr
->Type() == PrologString
)
1837 the_string
= string_expr
->StringValue();
1838 m_formatted
= FALSE
;
1840 else if (string_expr
->Type() == PrologList
)
1842 wxExpr
*first
= string_expr
->value
.first
;
1843 wxExpr
*second
= first
? first
->next
: NULL
;
1844 wxExpr
*third
= second
? second
->next
: NULL
;
1846 if (first
&& second
&& third
&&
1847 (first
->Type() == PrologReal
|| first
->Type() == PrologInteger
) &&
1848 (second
->Type() == PrologReal
|| second
->Type() == PrologInteger
) &&
1849 third
->Type() == PrologString
)
1851 if (first
->Type() == PrologReal
)
1852 the_x
= first
->RealValue();
1853 else the_x
= (double)first
->IntegerValue();
1855 if (second
->Type() == PrologReal
)
1856 the_y
= second
->RealValue();
1857 else the_y
= (double)second
->IntegerValue();
1859 the_string
= third
->StringValue();
1862 wxShapeTextLine
*line
=
1863 new wxShapeTextLine(the_x
, the_y
, (char*) (const char*) the_string
);
1864 m_text
.Append(line
);
1870 wxString pen_string
= "";
1871 wxString brush_string
= "";
1873 int pen_style
= wxSOLID
;
1874 int brush_style
= wxSOLID
;
1875 m_attachmentMode
= FALSE
;
1877 clause
->GetAttributeValue("pen_colour", pen_string
);
1878 clause
->GetAttributeValue("text_colour", m_textColourName
);
1880 SetTextColour(m_textColourName
);
1882 clause
->GetAttributeValue("region_name", m_regionName
);
1884 clause
->GetAttributeValue("brush_colour", brush_string
);
1885 clause
->GetAttributeValue("pen_width", pen_width
);
1886 clause
->GetAttributeValue("pen_style", pen_style
);
1887 clause
->GetAttributeValue("brush_style", brush_style
);
1889 int iVal
= (int) m_attachmentMode
;
1890 clause
->GetAttributeValue("use_attachments", iVal
);
1891 m_attachmentMode
= (iVal
!= 0);
1893 clause
->GetAttributeValue("sensitivity", m_sensitivity
);
1895 iVal
= (int) m_spaceAttachments
;
1896 clause
->GetAttributeValue("space_attachments", iVal
);
1897 m_spaceAttachments
= (iVal
!= 0);
1899 iVal
= (int) m_fixedWidth
;
1900 clause
->GetAttributeValue("fixed_width", iVal
);
1901 m_fixedWidth
= (iVal
!= 0);
1903 iVal
= (int) m_fixedHeight
;
1904 clause
->GetAttributeValue("fixed_height", iVal
);
1905 m_fixedHeight
= (iVal
!= 0);
1907 clause
->GetAttributeValue("format_mode", m_formatMode
);
1908 clause
->GetAttributeValue("shadow_mode", m_shadowMode
);
1910 iVal
= (int) m_centreResize
;
1911 clause
->GetAttributeValue("centre_resize", iVal
);
1912 m_centreResize
= (iVal
!= 0);
1914 iVal
= (int) m_highlighted
;
1915 clause
->GetAttributeValue("hilite", iVal
);
1916 m_highlighted
= (iVal
!= 0);
1918 clause
->GetAttributeValue("rotation", m_rotation
);
1920 if (pen_string
== "")
1921 pen_string
= "BLACK";
1922 if (brush_string
== "")
1923 brush_string
= "WHITE";
1925 if (pen_string
[0] == '#')
1927 wxColour
col(oglHexToColour(pen_string
.After('#')));
1928 m_pen
= wxThePenList
->FindOrCreatePen(col
, pen_width
, pen_style
);
1931 m_pen
= wxThePenList
->FindOrCreatePen(pen_string
, pen_width
, pen_style
);
1934 m_pen
= wxBLACK_PEN
;
1936 if (brush_string
[0] == '#')
1938 wxColour
col(oglHexToColour(brush_string
.After('#')));
1939 m_brush
= wxTheBrushList
->FindOrCreateBrush(col
, brush_style
);
1942 m_brush
= wxTheBrushList
->FindOrCreateBrush(brush_string
, brush_style
);
1945 m_brush
= wxWHITE_BRUSH
;
1947 int point_size
= 10;
1948 clause
->GetAttributeValue("point_size", point_size
);
1949 SetFont(oglMatchFont(point_size
));
1951 // Read user-defined attachment points, if any
1952 wxExpr
*attachmentList
= clause
->AttributeValue("user_attachments");
1955 wxExpr
*pointExpr
= attachmentList
->GetFirst();
1958 wxExpr
*idExpr
= pointExpr
->Nth(0);
1959 wxExpr
*xExpr
= pointExpr
->Nth(1);
1960 wxExpr
*yExpr
= pointExpr
->Nth(2);
1961 if (idExpr
&& xExpr
&& yExpr
)
1963 wxAttachmentPoint
*point
= new wxAttachmentPoint
;
1964 point
->m_id
= (int)idExpr
->IntegerValue();
1965 point
->m_x
= xExpr
->RealValue();
1966 point
->m_y
= yExpr
->RealValue();
1967 m_attachmentPoints
.Append((wxObject
*)point
);
1969 pointExpr
= pointExpr
->GetNext();
1973 // Read text regions
1974 ReadRegions(clause
);
1977 void wxShape::ReadRegions(wxExpr
*clause
)
1981 // region1 = (regionName regionText x y width height minWidth minHeight proportionX proportionY
1982 // formatMode fontSize fontFamily fontStyle fontWeight textColour)
1984 char regionNameBuf
[20];
1985 char textNameBuf
[20];
1987 wxExpr
*regionExpr
= NULL
;
1988 wxExpr
*textExpr
= NULL
;
1989 sprintf(regionNameBuf
, "region%d", regionNo
);
1990 sprintf(textNameBuf
, "text%d", regionNo
);
1992 m_formatted
= TRUE
; // Assume text is formatted unless we prove otherwise
1994 while (regionExpr
= clause
->AttributeValue(regionNameBuf
))
1997 * Get the region information
2001 wxString
regionName("");
2002 wxString
regionText("");
2006 double height
= 0.0;
2007 double minWidth
= 5.0;
2008 double minHeight
= 5.0;
2009 double m_regionProportionX
= -1.0;
2010 double m_regionProportionY
= -1.0;
2011 int formatMode
= FORMAT_NONE
;
2013 int fontFamily
= wxSWISS
;
2014 int fontStyle
= wxNORMAL
;
2015 int fontWeight
= wxNORMAL
;
2016 wxString
regionTextColour("");
2017 wxString
penColour("");
2018 int penStyle
= wxSOLID
;
2020 if (regionExpr
->Type() == PrologList
)
2022 wxExpr
*nameExpr
= regionExpr
->Nth(0);
2023 wxExpr
*textExpr
= regionExpr
->Nth(1);
2024 wxExpr
*xExpr
= regionExpr
->Nth(2);
2025 wxExpr
*yExpr
= regionExpr
->Nth(3);
2026 wxExpr
*widthExpr
= regionExpr
->Nth(4);
2027 wxExpr
*heightExpr
= regionExpr
->Nth(5);
2028 wxExpr
*minWidthExpr
= regionExpr
->Nth(6);
2029 wxExpr
*minHeightExpr
= regionExpr
->Nth(7);
2030 wxExpr
*propXExpr
= regionExpr
->Nth(8);
2031 wxExpr
*propYExpr
= regionExpr
->Nth(9);
2032 wxExpr
*formatExpr
= regionExpr
->Nth(10);
2033 wxExpr
*sizeExpr
= regionExpr
->Nth(11);
2034 wxExpr
*familyExpr
= regionExpr
->Nth(12);
2035 wxExpr
*styleExpr
= regionExpr
->Nth(13);
2036 wxExpr
*weightExpr
= regionExpr
->Nth(14);
2037 wxExpr
*colourExpr
= regionExpr
->Nth(15);
2038 wxExpr
*penColourExpr
= regionExpr
->Nth(16);
2039 wxExpr
*penStyleExpr
= regionExpr
->Nth(17);
2041 regionName
= nameExpr
->StringValue();
2042 regionText
= textExpr
->StringValue();
2044 x
= xExpr
->RealValue();
2045 y
= yExpr
->RealValue();
2047 width
= widthExpr
->RealValue();
2048 height
= heightExpr
->RealValue();
2050 minWidth
= minWidthExpr
->RealValue();
2051 minHeight
= minHeightExpr
->RealValue();
2053 m_regionProportionX
= propXExpr
->RealValue();
2054 m_regionProportionY
= propYExpr
->RealValue();
2056 formatMode
= (int) formatExpr
->IntegerValue();
2057 fontSize
= (int)sizeExpr
->IntegerValue();
2058 fontFamily
= (int)familyExpr
->IntegerValue();
2059 fontStyle
= (int)styleExpr
->IntegerValue();
2060 fontWeight
= (int)weightExpr
->IntegerValue();
2064 regionTextColour
= colourExpr
->StringValue();
2067 regionTextColour
= "BLACK";
2070 penColour
= penColourExpr
->StringValue();
2072 penStyle
= (int)penStyleExpr
->IntegerValue();
2074 wxFont
*font
= wxTheFontList
->FindOrCreateFont(fontSize
, fontFamily
, fontStyle
, fontWeight
);
2076 wxShapeRegion
*region
= new wxShapeRegion
;
2077 region
->SetProportions(m_regionProportionX
, m_regionProportionY
);
2078 region
->SetFont(font
);
2079 region
->SetSize(width
, height
);
2080 region
->SetPosition(x
, y
);
2081 region
->SetMinSize(minWidth
, minHeight
);
2082 region
->SetFormatMode(formatMode
);
2083 region
->SetPenStyle(penStyle
);
2084 if (penColour
!= "")
2085 region
->SetPenColour(penColour
);
2087 region
->m_textColour
= regionTextColour
;
2088 region
->m_regionText
= regionText
;
2089 region
->m_regionName
= regionName
;
2091 m_regions
.Append(region
);
2094 * Get the formatted text strings
2097 textExpr
= clause
->AttributeValue(textNameBuf
);
2098 if (textExpr
&& (textExpr
->Type() == PrologList
))
2100 wxExpr
*node
= textExpr
->value
.first
;
2103 wxExpr
*string_expr
= node
;
2106 wxString
the_string("");
2108 // string_expr can either be a string, or a list of
2109 // 3 elements: x, y, and string.
2110 if (string_expr
->Type() == PrologString
)
2112 the_string
= string_expr
->StringValue();
2113 m_formatted
= FALSE
;
2115 else if (string_expr
->Type() == PrologList
)
2117 wxExpr
*first
= string_expr
->value
.first
;
2118 wxExpr
*second
= first
? first
->next
: NULL
;
2119 wxExpr
*third
= second
? second
->next
: NULL
;
2121 if (first
&& second
&& third
&&
2122 (first
->Type() == PrologReal
|| first
->Type() == PrologInteger
) &&
2123 (second
->Type() == PrologReal
|| second
->Type() == PrologInteger
) &&
2124 third
->Type() == PrologString
)
2126 if (first
->Type() == PrologReal
)
2127 the_x
= first
->RealValue();
2128 else the_x
= (double)first
->IntegerValue();
2130 if (second
->Type() == PrologReal
)
2131 the_y
= second
->RealValue();
2132 else the_y
= (double)second
->IntegerValue();
2134 the_string
= third
->StringValue();
2139 wxShapeTextLine
*line
=
2140 new wxShapeTextLine(the_x
, the_y
, (char*) (const char*) the_string
);
2141 region
->m_formattedText
.Append(line
);
2148 sprintf(regionNameBuf
, "region%d", regionNo
);
2149 sprintf(textNameBuf
, "text%d", regionNo
);
2152 // Compatibility: check for no regions (old file).
2153 // Lines and divided rectangles must deal with this compatibility
2154 // theirselves. Composites _may_ not have any regions anyway.
2155 if ((m_regions
.Number() == 0) &&
2156 !this->IsKindOf(CLASSINFO(wxLineShape
)) && !this->IsKindOf(CLASSINFO(wxDividedShape
)) &&
2157 !this->IsKindOf(CLASSINFO(wxCompositeShape
)))
2159 wxShapeRegion
*newRegion
= new wxShapeRegion
;
2160 newRegion
->SetName("0");
2161 m_regions
.Append((wxObject
*)newRegion
);
2162 if (m_text
.Number() > 0)
2164 newRegion
->ClearText();
2165 wxNode
*node
= m_text
.First();
2168 wxShapeTextLine
*textLine
= (wxShapeTextLine
*)node
->Data();
2169 wxNode
*next
= node
->Next();
2170 newRegion
->GetFormattedText().Append((wxObject
*)textLine
);
2180 void wxShape::Copy(wxShape
& copy
)
2183 copy
.m_xpos
= m_xpos
;
2184 copy
.m_ypos
= m_ypos
;
2186 copy
.m_brush
= m_brush
;
2187 copy
.m_textColour
= m_textColour
;
2188 copy
.m_centreResize
= m_centreResize
;
2189 copy
.m_attachmentMode
= m_attachmentMode
;
2190 copy
.m_spaceAttachments
= m_spaceAttachments
;
2191 copy
.m_highlighted
= m_highlighted
;
2192 copy
.m_rotation
= m_rotation
;
2193 copy
.m_textColourName
= m_textColourName
;
2194 copy
.m_regionName
= m_regionName
;
2196 copy
.m_sensitivity
= m_sensitivity
;
2197 copy
.m_draggable
= m_draggable
;
2198 copy
.m_fixedWidth
= m_fixedWidth
;
2199 copy
.m_fixedHeight
= m_fixedHeight
;
2200 copy
.m_formatMode
= m_formatMode
;
2201 copy
.m_drawHandles
= m_drawHandles
;
2203 copy
.m_visible
= m_visible
;
2204 copy
.m_shadowMode
= m_shadowMode
;
2205 copy
.m_shadowOffsetX
= m_shadowOffsetX
;
2206 copy
.m_shadowOffsetY
= m_shadowOffsetY
;
2207 copy
.m_shadowBrush
= m_shadowBrush
;
2209 // Copy text regions
2210 copy
.ClearRegions();
2211 wxNode
*node
= m_regions
.First();
2214 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
2215 wxShapeRegion
*newRegion
= new wxShapeRegion(*region
);
2216 copy
.m_regions
.Append(newRegion
);
2217 node
= node
->Next();
2221 copy
.ClearAttachments();
2222 node
= m_attachmentPoints
.First();
2225 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->Data();
2226 wxAttachmentPoint
*newPoint
= new wxAttachmentPoint
;
2227 newPoint
->m_id
= point
->m_id
;
2228 newPoint
->m_x
= point
->m_x
;
2229 newPoint
->m_y
= point
->m_y
;
2230 copy
.m_attachmentPoints
.Append((wxObject
*)newPoint
);
2231 node
= node
->Next();
2235 copy
.m_lines
.Clear();
2236 node
= m_lines
.First();
2239 wxLineShape
* line
= (wxLineShape
*) node
->Data();
2240 copy
.m_lines
.Append(line
);
2241 node
= node
->Next();
2245 // Create and return a new, fully copied object.
2246 wxShape
*wxShape::CreateNewCopy(bool resetMapping
, bool recompute
)
2249 oglObjectCopyMapping
.Clear();
2251 wxShape
* newObject
= (wxShape
*) GetClassInfo()->CreateObject();
2253 wxASSERT( (newObject
!= NULL
) );
2254 wxASSERT( (newObject
->IsKindOf(CLASSINFO(wxShape
))) );
2258 if (GetEventHandler() != this)
2260 wxShapeEvtHandler
* newHandler
= GetEventHandler()->CreateNewCopy();
2261 newObject
->SetEventHandler(newHandler
);
2262 newObject
->SetPreviousHandler(NULL
);
2263 newHandler
->SetPreviousHandler(newObject
);
2264 newHandler
->SetShape(newObject
);
2268 newObject
->Recompute();
2272 // Does the copying for this object, including copying event
2273 // handler data if any. Calls the virtual Copy function.
2274 void wxShape::CopyWithHandler(wxShape
& copy
)
2278 if (GetEventHandler() != this)
2280 wxASSERT( copy
.GetEventHandler() != NULL
);
2281 wxASSERT( copy
.GetEventHandler() != (©
) );
2282 wxASSERT( GetEventHandler()->GetClassInfo() == copy
.GetEventHandler()->GetClassInfo() );
2283 GetEventHandler()->CopyData(* (copy
.GetEventHandler()));
2288 // Default - make 6 control points
2289 void wxShape::MakeControlPoints()
2291 double maxX
, maxY
, minX
, minY
;
2293 GetBoundingBoxMax(&maxX
, &maxY
);
2294 GetBoundingBoxMin(&minX
, &minY
);
2296 double widthMin
= (double)(minX
+ CONTROL_POINT_SIZE
+ 2);
2297 double heightMin
= (double)(minY
+ CONTROL_POINT_SIZE
+ 2);
2299 // Offsets from main object
2300 double top
= (double)(- (heightMin
/ 2.0));
2301 double bottom
= (double)(heightMin
/ 2.0 + (maxY
- minY
));
2302 double left
= (double)(- (widthMin
/ 2.0));
2303 double right
= (double)(widthMin
/ 2.0 + (maxX
- minX
));
2305 wxControlPoint
*control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, left
, top
,
2306 CONTROL_POINT_DIAGONAL
);
2307 m_canvas
->AddShape(control
);
2308 m_controlPoints
.Append(control
);
2310 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, 0, top
,
2311 CONTROL_POINT_VERTICAL
);
2312 m_canvas
->AddShape(control
);
2313 m_controlPoints
.Append(control
);
2315 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, right
, top
,
2316 CONTROL_POINT_DIAGONAL
);
2317 m_canvas
->AddShape(control
);
2318 m_controlPoints
.Append(control
);
2320 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, right
, 0,
2321 CONTROL_POINT_HORIZONTAL
);
2322 m_canvas
->AddShape(control
);
2323 m_controlPoints
.Append(control
);
2325 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, right
, bottom
,
2326 CONTROL_POINT_DIAGONAL
);
2327 m_canvas
->AddShape(control
);
2328 m_controlPoints
.Append(control
);
2330 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, 0, bottom
,
2331 CONTROL_POINT_VERTICAL
);
2332 m_canvas
->AddShape(control
);
2333 m_controlPoints
.Append(control
);
2335 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, left
, bottom
,
2336 CONTROL_POINT_DIAGONAL
);
2337 m_canvas
->AddShape(control
);
2338 m_controlPoints
.Append(control
);
2340 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, left
, 0,
2341 CONTROL_POINT_HORIZONTAL
);
2342 m_canvas
->AddShape(control
);
2343 m_controlPoints
.Append(control
);
2347 void wxShape::MakeMandatoryControlPoints()
2349 wxNode
*node
= m_children
.First();
2352 wxShape
*child
= (wxShape
*)node
->Data();
2353 child
->MakeMandatoryControlPoints();
2354 node
= node
->Next();
2358 void wxShape::ResetMandatoryControlPoints()
2360 wxNode
*node
= m_children
.First();
2363 wxShape
*child
= (wxShape
*)node
->Data();
2364 child
->ResetMandatoryControlPoints();
2365 node
= node
->Next();
2369 void wxShape::ResetControlPoints()
2371 ResetMandatoryControlPoints();
2373 if (m_controlPoints
.Number() < 1)
2376 double maxX
, maxY
, minX
, minY
;
2378 GetBoundingBoxMax(&maxX
, &maxY
);
2379 GetBoundingBoxMin(&minX
, &minY
);
2381 double widthMin
= (double)(minX
+ CONTROL_POINT_SIZE
+ 2);
2382 double heightMin
= (double)(minY
+ CONTROL_POINT_SIZE
+ 2);
2384 // Offsets from main object
2385 double top
= (double)(- (heightMin
/ 2.0));
2386 double bottom
= (double)(heightMin
/ 2.0 + (maxY
- minY
));
2387 double left
= (double)(- (widthMin
/ 2.0));
2388 double right
= (double)(widthMin
/ 2.0 + (maxX
- minX
));
2390 wxNode
*node
= m_controlPoints
.First();
2391 wxControlPoint
*control
= (wxControlPoint
*)node
->Data();
2392 control
->m_xoffset
= left
; control
->m_yoffset
= top
;
2394 node
= node
->Next(); control
= (wxControlPoint
*)node
->Data();
2395 control
->m_xoffset
= 0; control
->m_yoffset
= top
;
2397 node
= node
->Next(); control
= (wxControlPoint
*)node
->Data();
2398 control
->m_xoffset
= right
; control
->m_yoffset
= top
;
2400 node
= node
->Next(); control
= (wxControlPoint
*)node
->Data();
2401 control
->m_xoffset
= right
; control
->m_yoffset
= 0;
2403 node
= node
->Next(); control
= (wxControlPoint
*)node
->Data();
2404 control
->m_xoffset
= right
; control
->m_yoffset
= bottom
;
2406 node
= node
->Next(); control
= (wxControlPoint
*)node
->Data();
2407 control
->m_xoffset
= 0; control
->m_yoffset
= bottom
;
2409 node
= node
->Next(); control
= (wxControlPoint
*)node
->Data();
2410 control
->m_xoffset
= left
; control
->m_yoffset
= bottom
;
2412 node
= node
->Next(); control
= (wxControlPoint
*)node
->Data();
2413 control
->m_xoffset
= left
; control
->m_yoffset
= 0;
2416 void wxShape::DeleteControlPoints(wxDC
*dc
)
2418 wxNode
*node
= m_controlPoints
.First();
2421 wxControlPoint
*control
= (wxControlPoint
*)node
->Data();
2423 control
->GetEventHandler()->OnErase(*dc
);
2424 m_canvas
->RemoveShape(control
);
2427 node
= m_controlPoints
.First();
2429 // Children of divisions are contained objects,
2431 if (!IsKindOf(CLASSINFO(wxDivisionShape
)))
2433 node
= m_children
.First();
2436 wxShape
*child
= (wxShape
*)node
->Data();
2437 child
->DeleteControlPoints(dc
);
2438 node
= node
->Next();
2443 void wxShape::OnDrawControlPoints(wxDC
& dc
)
2448 dc
.SetBrush(wxBLACK_BRUSH
);
2449 dc
.SetPen(wxBLACK_PEN
);
2451 wxNode
*node
= m_controlPoints
.First();
2454 wxControlPoint
*control
= (wxControlPoint
*)node
->Data();
2456 node
= node
->Next();
2458 // Children of divisions are contained objects,
2460 // This test bypasses the type facility for speed
2461 // (critical when drawing)
2462 if (!IsKindOf(CLASSINFO(wxDivisionShape
)))
2464 node
= m_children
.First();
2467 wxShape
*child
= (wxShape
*)node
->Data();
2468 child
->GetEventHandler()->OnDrawControlPoints(dc
);
2469 node
= node
->Next();
2474 void wxShape::OnEraseControlPoints(wxDC
& dc
)
2476 wxNode
*node
= m_controlPoints
.First();
2479 wxControlPoint
*control
= (wxControlPoint
*)node
->Data();
2481 node
= node
->Next();
2483 if (!IsKindOf(CLASSINFO(wxDivisionShape
)))
2485 node
= m_children
.First();
2488 wxShape
*child
= (wxShape
*)node
->Data();
2489 child
->GetEventHandler()->OnEraseControlPoints(dc
);
2490 node
= node
->Next();
2495 void wxShape::Select(bool select
, wxDC
* dc
)
2497 m_selected
= select
;
2500 MakeControlPoints();
2501 // Children of divisions are contained objects,
2503 if (!IsKindOf(CLASSINFO(wxDivisionShape
)))
2505 wxNode
*node
= m_children
.First();
2508 wxShape
*child
= (wxShape
*)node
->Data();
2509 child
->MakeMandatoryControlPoints();
2510 node
= node
->Next();
2514 GetEventHandler()->OnDrawControlPoints(*dc
);
2518 DeleteControlPoints(dc
);
2519 if (!IsKindOf(CLASSINFO(wxDivisionShape
)))
2521 wxNode
*node
= m_children
.First();
2524 wxShape
*child
= (wxShape
*)node
->Data();
2525 child
->DeleteControlPoints(dc
);
2526 node
= node
->Next();
2532 bool wxShape::Selected() const
2537 bool wxShape::AncestorSelected() const
2539 if (m_selected
) return TRUE
;
2543 return GetParent()->AncestorSelected();
2546 int wxShape::GetNumberOfAttachments() const
2548 // Should return the MAXIMUM attachment point id here,
2549 // so higher-level functions can iterate through all attachments,
2550 // even if they're not contiguous.
2551 if (m_attachmentPoints
.Number() == 0)
2556 wxNode
*node
= m_attachmentPoints
.First();
2559 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->Data();
2560 if (point
->m_id
> maxN
)
2562 node
= node
->Next();
2568 bool wxShape::AttachmentIsValid(int attachment
) const
2570 if ((attachment
>= 0) && (attachment
< 4))
2573 wxNode
*node
= m_attachmentPoints
.First();
2576 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->Data();
2577 if (point
->m_id
== attachment
)
2579 node
= node
->Next();
2584 bool wxShape::GetAttachmentPosition(int attachment
, double *x
, double *y
,
2585 int nth
, int no_arcs
, wxLineShape
*line
)
2587 if (!m_attachmentMode
)
2589 *x
= m_xpos
; *y
= m_ypos
;
2594 wxNode
*node
= m_attachmentPoints
.First();
2597 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->Data();
2598 if (point
->m_id
== attachment
)
2600 *x
= (double)(m_xpos
+ point
->m_x
);
2601 *y
= (double)(m_ypos
+ point
->m_y
);
2604 node
= node
->Next();
2606 *x
= m_xpos
; *y
= m_ypos
;
2611 void wxShape::GetBoundingBoxMax(double *w
, double *h
)
2614 GetBoundingBoxMin(&ww
, &hh
);
2615 if (m_shadowMode
!= SHADOW_NONE
)
2617 ww
+= m_shadowOffsetX
;
2618 hh
+= m_shadowOffsetY
;
2624 // Returns TRUE if image is a descendant of this composite
2625 bool wxShape::HasDescendant(wxShape
*image
)
2629 wxNode
*node
= m_children
.First();
2632 wxShape
*child
= (wxShape
*)node
->Data();
2633 bool ans
= child
->HasDescendant(image
);
2636 node
= node
->Next();
2641 // Clears points from a list of wxRealPoints, and clears list
2642 void wxShape::ClearPointList(wxList
& list
)
2644 wxNode
* node
= list
.First();
2647 wxRealPoint
* pt
= (wxRealPoint
*) node
->Data();
2650 node
= node
->Next();
2655 // Assuming the attachment lies along a vertical or horizontal line,
2656 // calculate the position on that point.
2657 wxRealPoint
wxShape::CalcSimpleAttachment(const wxRealPoint
& pt1
, const wxRealPoint
& pt2
,
2658 int nth
, int noArcs
, wxLineShape
* line
)
2660 bool isEnd
= (line
&& line
->IsEnd(this));
2662 // Are we horizontal or vertical?
2663 bool isHorizontal
= (oglRoughlyEqual(pt1
.y
, pt2
.y
) == TRUE
);
2669 wxRealPoint firstPoint
, secondPoint
;
2681 if (m_spaceAttachments
)
2683 if (line
&& (line
->GetAlignmentType(isEnd
) == LINE_ALIGNMENT_TO_NEXT_HANDLE
))
2685 // Align line according to the next handle along
2686 wxRealPoint
*point
= line
->GetNextControlPoint(this);
2687 if (point
->x
< firstPoint
.x
)
2689 else if (point
->x
> secondPoint
.x
)
2695 x
= firstPoint
.x
+ (nth
+ 1)*(secondPoint
.x
- firstPoint
.x
)/(noArcs
+ 1);
2697 else x
= (secondPoint
.x
- firstPoint
.x
)/2.0; // Midpoint
2703 wxASSERT( oglRoughlyEqual(pt1
.x
, pt2
.x
) == TRUE
);
2705 wxRealPoint firstPoint
, secondPoint
;
2717 if (m_spaceAttachments
)
2719 if (line
&& (line
->GetAlignmentType(isEnd
) == LINE_ALIGNMENT_TO_NEXT_HANDLE
))
2721 // Align line according to the next handle along
2722 wxRealPoint
*point
= line
->GetNextControlPoint(this);
2723 if (point
->y
< firstPoint
.y
)
2725 else if (point
->y
> secondPoint
.y
)
2731 y
= firstPoint
.y
+ (nth
+ 1)*(secondPoint
.y
- firstPoint
.y
)/(noArcs
+ 1);
2733 else y
= (secondPoint
.y
- firstPoint
.y
)/2.0; // Midpoint
2738 return wxRealPoint(x
, y
);
2741 // Return the zero-based position in m_lines of line.
2742 int wxShape::GetLinePosition(wxLineShape
* line
)
2745 for (i
= 0; i
< m_lines
.Number(); i
++)
2746 if ((wxLineShape
*) (m_lines
.Nth(i
)->Data()) == line
)