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 void 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
);
1143 void wxShape::OnChangeAttachment(int attachment
, wxLineShape
* line
, wxList
& ordering
)
1145 if (line
->GetTo() == this)
1146 line
->SetAttachmentTo(attachment
);
1148 line
->SetAttachmentFrom(attachment
);
1150 ApplyAttachmentOrdering(ordering
);
1152 wxClientDC
dc(GetCanvas());
1153 GetCanvas()->PrepareDC(dc
);
1157 if (!GetCanvas()->GetQuickEditMode()) GetCanvas()->Redraw(dc
);
1160 // Reorders the lines according to the given list.
1161 void wxShape::ApplyAttachmentOrdering(wxList
& linesToSort
)
1163 // This is a temporary store of all the lines.
1166 wxNode
*node
= m_lines
.First();
1169 wxLineShape
*line
= (wxLineShape
*)node
->Data();
1170 linesStore
.Append(line
);
1171 node
= node
->Next();;
1176 node
= linesToSort
.First();
1179 wxLineShape
*line
= (wxLineShape
*)node
->Data();
1180 if (linesStore
.Member(line
))
1183 linesStore
.DeleteObject(line
);
1184 m_lines
.Append(line
);
1186 node
= node
->Next();
1189 // Now add any lines that haven't been listed in linesToSort.
1190 node
= linesStore
.First();
1193 wxLineShape
*line
= (wxLineShape
*)node
->Data();
1194 m_lines
.Append(line
);
1195 node
= node
->Next();
1199 // Reorders the lines coming into the node image at this attachment
1200 // position, in the order in which they appear in linesToSort.
1201 // Any remaining lines not in the list will be added to the end.
1202 void wxShape::SortLines(int attachment
, wxList
& linesToSort
)
1204 // This is a temporary store of all the lines at this attachment
1205 // point. We'll tick them off as we've processed them.
1206 wxList linesAtThisAttachment
;
1208 wxNode
*node
= m_lines
.First();
1211 wxLineShape
*line
= (wxLineShape
*)node
->Data();
1212 wxNode
*next
= node
->Next();
1213 if ((line
->GetTo() == this && line
->GetAttachmentTo() == attachment
) ||
1214 (line
->GetFrom() == this && line
->GetAttachmentFrom() == attachment
))
1216 linesAtThisAttachment
.Append(line
);
1220 else node
= node
->Next();
1223 node
= linesToSort
.First();
1226 wxLineShape
*line
= (wxLineShape
*)node
->Data();
1227 if (linesAtThisAttachment
.Member(line
))
1230 linesAtThisAttachment
.DeleteObject(line
);
1231 m_lines
.Append(line
);
1233 node
= node
->Next();
1236 // Now add any lines that haven't been listed in linesToSort.
1237 node
= linesAtThisAttachment
.First();
1240 wxLineShape
*line
= (wxLineShape
*)node
->Data();
1241 m_lines
.Append(line
);
1242 node
= node
->Next();
1246 void wxShape::OnHighlight(wxDC
& dc
)
1250 void wxShape::OnLeftClick(double x
, double y
, int keys
, int attachment
)
1252 if ((m_sensitivity
& OP_CLICK_LEFT
) != OP_CLICK_LEFT
)
1258 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1259 m_parent
->GetEventHandler()->OnLeftClick(x
, y
, keys
, attachment
);
1265 void wxShape::OnRightClick(double x
, double y
, int keys
, int attachment
)
1267 if ((m_sensitivity
& OP_CLICK_RIGHT
) != OP_CLICK_RIGHT
)
1273 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1274 m_parent
->GetEventHandler()->OnRightClick(x
, y
, keys
, attachment
);
1280 double DragOffsetX
= 0.0;
1281 double DragOffsetY
= 0.0;
1283 void wxShape::OnDragLeft(bool draw
, double x
, double y
, int keys
, int attachment
)
1285 if ((m_sensitivity
& OP_DRAG_LEFT
) != OP_DRAG_LEFT
)
1291 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1292 m_parent
->GetEventHandler()->OnDragLeft(draw
, x
, y
, keys
, attachment
);
1297 wxClientDC
dc(GetCanvas());
1298 GetCanvas()->PrepareDC(dc
);
1300 dc
.SetLogicalFunction(wxXOR
);
1302 wxPen
dottedPen(wxColour(0, 0, 0), 1, wxDOT
);
1303 dc
.SetPen(dottedPen
);
1304 dc
.SetBrush(* wxTRANSPARENT_BRUSH
);
1307 xx
= x
+ DragOffsetX
;
1308 yy
= y
+ DragOffsetY
;
1310 m_canvas
->Snap(&xx
, &yy
);
1311 // m_xpos = xx; m_ypos = yy;
1313 GetBoundingBoxMax(&w
, &h
);
1314 GetEventHandler()->OnDrawOutline(dc
, xx
, yy
, w
, h
);
1317 void wxShape::OnBeginDragLeft(double x
, double y
, int keys
, int attachment
)
1319 if ((m_sensitivity
& OP_DRAG_LEFT
) != OP_DRAG_LEFT
)
1325 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1326 m_parent
->GetEventHandler()->OnBeginDragLeft(x
, y
, keys
, attachment
);
1331 DragOffsetX
= m_xpos
- x
;
1332 DragOffsetY
= m_ypos
- y
;
1334 wxClientDC
dc(GetCanvas());
1335 GetCanvas()->PrepareDC(dc
);
1337 // New policy: don't erase shape until end of drag.
1341 xx
= x
+ DragOffsetX
;
1342 yy
= y
+ DragOffsetY
;
1343 m_canvas
->Snap(&xx
, &yy
);
1344 // m_xpos = xx; m_ypos = yy;
1345 dc
.SetLogicalFunction(wxXOR
);
1347 wxPen
dottedPen(wxColour(0, 0, 0), 1, wxDOT
);
1348 dc
.SetPen(dottedPen
);
1349 dc
.SetBrush((* wxTRANSPARENT_BRUSH
));
1352 GetBoundingBoxMax(&w
, &h
);
1353 GetEventHandler()->OnDrawOutline(dc
, xx
, yy
, w
, h
);
1354 m_canvas
->CaptureMouse();
1357 void wxShape::OnEndDragLeft(double x
, double y
, int keys
, int attachment
)
1359 m_canvas
->ReleaseMouse();
1360 if ((m_sensitivity
& OP_DRAG_LEFT
) != OP_DRAG_LEFT
)
1366 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1367 m_parent
->GetEventHandler()->OnEndDragLeft(x
, y
, keys
, attachment
);
1372 wxClientDC
dc(GetCanvas());
1373 GetCanvas()->PrepareDC(dc
);
1375 dc
.SetLogicalFunction(wxCOPY
);
1377 double xx
= x
+ DragOffsetX
;
1378 double yy
= y
+ DragOffsetY
;
1379 m_canvas
->Snap(&xx
, &yy
);
1380 // canvas->Snap(&m_xpos, &m_ypos);
1382 // New policy: erase shape at end of drag.
1386 if (m_canvas
&& !m_canvas
->GetQuickEditMode()) m_canvas
->Redraw(dc
);
1389 void wxShape::OnDragRight(bool draw
, double x
, double y
, int keys
, int attachment
)
1391 if ((m_sensitivity
& OP_DRAG_RIGHT
) != OP_DRAG_RIGHT
)
1397 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1398 m_parent
->GetEventHandler()->OnDragRight(draw
, x
, y
, keys
, attachment
);
1404 void wxShape::OnBeginDragRight(double x
, double y
, int keys
, int attachment
)
1406 if ((m_sensitivity
& OP_DRAG_RIGHT
) != OP_DRAG_RIGHT
)
1412 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1413 m_parent
->GetEventHandler()->OnBeginDragRight(x
, y
, keys
, attachment
);
1419 void wxShape::OnEndDragRight(double x
, double y
, int keys
, int attachment
)
1421 if ((m_sensitivity
& OP_DRAG_RIGHT
) != OP_DRAG_RIGHT
)
1427 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1428 m_parent
->GetEventHandler()->OnEndDragRight(x
, y
, keys
, attachment
);
1434 void wxShape::OnDrawOutline(wxDC
& dc
, double x
, double y
, double w
, double h
)
1436 double top_left_x
= (double)(x
- w
/2.0);
1437 double top_left_y
= (double)(y
- h
/2.0);
1438 double top_right_x
= (double)(top_left_x
+ w
);
1439 double top_right_y
= (double)top_left_y
;
1440 double bottom_left_x
= (double)top_left_x
;
1441 double bottom_left_y
= (double)(top_left_y
+ h
);
1442 double bottom_right_x
= (double)top_right_x
;
1443 double bottom_right_y
= (double)bottom_left_y
;
1446 points
[0].x
= WXROUND(top_left_x
); points
[0].y
= WXROUND(top_left_y
);
1447 points
[1].x
= WXROUND(top_right_x
); points
[1].y
= WXROUND(top_right_y
);
1448 points
[2].x
= WXROUND(bottom_right_x
); points
[2].y
= WXROUND(bottom_right_y
);
1449 points
[3].x
= WXROUND(bottom_left_x
); points
[3].y
= WXROUND(bottom_left_y
);
1450 points
[4].x
= WXROUND(top_left_x
); points
[4].y
= WXROUND(top_left_y
);
1452 dc
.DrawLines(5, points
);
1455 void wxShape::Attach(wxShapeCanvas
*can
)
1460 void wxShape::Detach()
1465 void wxShape::Move(wxDC
& dc
, double x
, double y
, bool display
)
1467 double old_x
= m_xpos
;
1468 double old_y
= m_ypos
;
1470 m_xpos
= x
; m_ypos
= y
;
1472 if (!GetEventHandler()->OnMovePre(dc
, x
, y
, old_x
, old_y
, display
))
1479 ResetControlPoints();
1486 GetEventHandler()->OnMovePost(dc
, x
, y
, old_x
, old_y
, display
);
1489 void wxShape::MoveLinks(wxDC
& dc
)
1491 GetEventHandler()->OnMoveLinks(dc
);
1495 void wxShape::Draw(wxDC
& dc
)
1499 GetEventHandler()->OnDraw(dc
);
1500 GetEventHandler()->OnDrawContents(dc
);
1501 GetEventHandler()->OnDrawControlPoints(dc
);
1505 void wxShape::Flash()
1509 wxClientDC
dc(GetCanvas());
1510 GetCanvas()->PrepareDC(dc
);
1512 dc
.SetLogicalFunction(wxXOR
);
1514 dc
.SetLogicalFunction(wxCOPY
);
1519 void wxShape::Show(bool show
)
1522 wxNode
*node
= m_children
.First();
1525 wxShape
*image
= (wxShape
*)node
->Data();
1527 node
= node
->Next();
1531 void wxShape::Erase(wxDC
& dc
)
1533 GetEventHandler()->OnErase(dc
);
1534 GetEventHandler()->OnEraseControlPoints(dc
);
1537 void wxShape::EraseContents(wxDC
& dc
)
1539 GetEventHandler()->OnEraseContents(dc
);
1542 void wxShape::AddText(const wxString
& string
)
1544 wxNode
*node
= m_regions
.First();
1547 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
1548 region
->ClearText();
1549 wxShapeTextLine
*new_line
=
1550 new wxShapeTextLine(0.0, 0.0, string
);
1551 region
->GetFormattedText().Append(new_line
);
1553 m_formatted
= FALSE
;
1556 void wxShape::SetSize(double x
, double y
, bool recursive
)
1558 SetAttachmentSize(x
, y
);
1559 SetDefaultRegionSize();
1562 void wxShape::SetAttachmentSize(double w
, double h
)
1566 double width
, height
;
1567 GetBoundingBoxMin(&width
, &height
);
1570 else scaleX
= w
/width
;
1573 else scaleY
= h
/height
;
1575 wxNode
*node
= m_attachmentPoints
.First();
1578 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->Data();
1579 point
->m_x
= (double)(point
->m_x
* scaleX
);
1580 point
->m_y
= (double)(point
->m_y
* scaleY
);
1581 node
= node
->Next();
1585 // Add line FROM this object
1586 void wxShape::AddLine(wxLineShape
*line
, wxShape
*other
,
1587 int attachFrom
, int attachTo
,
1588 // The line ordering
1589 int positionFrom
, int positionTo
)
1591 m_lines
.DeleteObject(line
);
1592 other
->m_lines
.DeleteObject(line
);
1594 if (positionFrom
== -1)
1595 m_lines
.Append(line
);
1598 if (positionFrom
< m_lines
.Number())
1600 wxNode
* node
= m_lines
.Nth(positionFrom
);
1601 m_lines
.Insert(node
, line
);
1604 m_lines
.Append(line
);
1607 if (positionTo
== -1)
1608 other
->m_lines
.Append(line
);
1611 if (positionTo
< other
->m_lines
.Number())
1613 wxNode
* node
= other
->m_lines
.Nth(positionTo
);
1614 other
->m_lines
.Insert(node
, line
);
1617 other
->m_lines
.Append(line
);
1620 line
->SetFrom(this);
1622 line
->SetAttachments(attachFrom
, attachTo
);
1625 void wxShape::RemoveLine(wxLineShape
*line
)
1627 if (line
->GetFrom() == this)
1628 line
->GetTo()->m_lines
.DeleteObject(line
);
1630 line
->GetFrom()->m_lines
.DeleteObject(line
);
1632 m_lines
.DeleteObject(line
);
1636 char *wxShape::GetFunctor()
1638 return "node_image";
1641 void wxShape::WritePrologAttributes(wxExpr
*clause
)
1643 clause
->AddAttributeValueString("type", GetClassInfo()->GetClassName());
1644 clause
->AddAttributeValue("id", m_id
);
1648 int penWidth
= m_pen
->GetWidth();
1649 int penStyle
= m_pen
->GetStyle();
1651 clause
->AddAttributeValue("pen_width", (long)penWidth
);
1652 if (penStyle
!= wxSOLID
)
1653 clause
->AddAttributeValue("pen_style", (long)penStyle
);
1655 wxString penColour
= wxTheColourDatabase
->FindName(m_pen
->GetColour());
1656 if (penColour
== "")
1658 wxString
hex(oglColourToHex(m_pen
->GetColour()));
1659 hex
= wxString("#") + hex
;
1660 clause
->AddAttributeValueString("pen_colour", hex
);
1662 else if (penColour
!= "BLACK")
1663 clause
->AddAttributeValueString("pen_colour", penColour
);
1668 wxString brushColour
= wxTheColourDatabase
->FindName(m_brush
->GetColour());
1670 if (brushColour
== "")
1672 wxString
hex(oglColourToHex(m_brush
->GetColour()));
1673 hex
= wxString("#") + hex
;
1674 clause
->AddAttributeValueString("brush_colour", hex
);
1676 else if (brushColour
!= "WHITE")
1677 clause
->AddAttributeValueString("brush_colour", brushColour
);
1679 if (m_brush
->GetStyle() != wxSOLID
)
1680 clause
->AddAttributeValue("brush_style", (long)m_brush
->GetStyle());
1685 int n_lines
= m_lines
.Number();
1688 wxExpr
*list
= new wxExpr(PrologList
);
1689 wxNode
*node
= m_lines
.First();
1692 wxShape
*line
= (wxShape
*)node
->Data();
1693 wxExpr
*id_expr
= new wxExpr(line
->GetId());
1694 list
->Append(id_expr
);
1695 node
= node
->Next();
1697 clause
->AddAttributeValue("arcs", list
);
1700 // Miscellaneous members
1701 if (m_attachmentMode
!= 0)
1702 clause
->AddAttributeValue("use_attachments", (long)m_attachmentMode
);
1703 if (m_sensitivity
!= OP_ALL
)
1704 clause
->AddAttributeValue("sensitivity", (long)m_sensitivity
);
1705 if (!m_spaceAttachments
)
1706 clause
->AddAttributeValue("space_attachments", (long)m_spaceAttachments
);
1708 clause
->AddAttributeValue("fixed_width", (long)m_fixedWidth
);
1710 clause
->AddAttributeValue("fixed_height", (long)m_fixedHeight
);
1711 if (m_shadowMode
!= SHADOW_NONE
)
1712 clause
->AddAttributeValue("shadow_mode", (long)m_shadowMode
);
1713 if (m_centreResize
!= TRUE
)
1714 clause
->AddAttributeValue("centre_resize", (long)0);
1715 if (m_highlighted
!= FALSE
)
1716 clause
->AddAttributeValue("hilite", (long)m_highlighted
);
1718 if (m_parent
) // For composite objects
1719 clause
->AddAttributeValue("parent", (long)m_parent
->GetId());
1721 if (m_rotation
!= 0.0)
1722 clause
->AddAttributeValue("rotation", m_rotation
);
1724 // Write user-defined attachment points, if any
1725 if (m_attachmentPoints
.Number() > 0)
1727 wxExpr
*attachmentList
= new wxExpr(PrologList
);
1728 wxNode
*node
= m_attachmentPoints
.First();
1731 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->Data();
1732 wxExpr
*pointExpr
= new wxExpr(PrologList
);
1733 pointExpr
->Append(new wxExpr((long)point
->m_id
));
1734 pointExpr
->Append(new wxExpr(point
->m_x
));
1735 pointExpr
->Append(new wxExpr(point
->m_y
));
1736 attachmentList
->Append(pointExpr
);
1737 node
= node
->Next();
1739 clause
->AddAttributeValue("user_attachments", attachmentList
);
1742 // Write text regions
1743 WriteRegions(clause
);
1746 void wxShape::WriteRegions(wxExpr
*clause
)
1748 // Output regions as region1 = (...), region2 = (...), etc
1749 // and formatted text as text1 = (...), text2 = (...) etc.
1751 char regionNameBuf
[20];
1752 char textNameBuf
[20];
1753 wxNode
*node
= m_regions
.First();
1756 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
1757 sprintf(regionNameBuf
, "region%d", regionNo
);
1758 sprintf(textNameBuf
, "text%d", regionNo
);
1760 // Original text and region attributes:
1761 // region1 = (regionName regionText x y width height minWidth minHeight proportionX proportionY
1762 // formatMode fontSize fontFamily fontStyle fontWeight textColour)
1763 wxExpr
*regionExpr
= new wxExpr(PrologList
);
1764 regionExpr
->Append(new wxExpr(PrologString
, (region
->m_regionName
? region
->m_regionName
: "")));
1765 regionExpr
->Append(new wxExpr(PrologString
, (region
->m_regionText
? region
->m_regionText
: "")));
1767 regionExpr
->Append(new wxExpr(region
->m_x
));
1768 regionExpr
->Append(new wxExpr(region
->m_y
));
1769 regionExpr
->Append(new wxExpr(region
->GetWidth()));
1770 regionExpr
->Append(new wxExpr(region
->GetHeight()));
1772 regionExpr
->Append(new wxExpr(region
->m_minWidth
));
1773 regionExpr
->Append(new wxExpr(region
->m_minHeight
));
1774 regionExpr
->Append(new wxExpr(region
->m_regionProportionX
));
1775 regionExpr
->Append(new wxExpr(region
->m_regionProportionY
));
1777 regionExpr
->Append(new wxExpr((long)region
->m_formatMode
));
1779 regionExpr
->Append(new wxExpr((long)(region
->m_font
? region
->m_font
->GetPointSize() : 10)));
1780 regionExpr
->Append(new wxExpr((long)(region
->m_font
? region
->m_font
->GetFamily() : wxDEFAULT
)));
1781 regionExpr
->Append(new wxExpr((long)(region
->m_font
? region
->m_font
->GetStyle() : wxDEFAULT
)));
1782 regionExpr
->Append(new wxExpr((long)(region
->m_font
? region
->m_font
->GetWeight() : wxNORMAL
)));
1783 regionExpr
->Append(new wxExpr(PrologString
, region
->m_textColour
? region
->m_textColour
: "BLACK"));
1785 // New members for pen colour/style
1786 regionExpr
->Append(new wxExpr(PrologString
, region
->m_penColour
? region
->m_penColour
: "BLACK"));
1787 regionExpr
->Append(new wxExpr((long)region
->m_penStyle
));
1790 // text1 = ((x y string) (x y string) ...)
1791 wxExpr
*textExpr
= new wxExpr(PrologList
);
1793 wxNode
*textNode
= region
->m_formattedText
.First();
1796 wxShapeTextLine
*line
= (wxShapeTextLine
*)textNode
->Data();
1797 wxExpr
*list2
= new wxExpr(PrologList
);
1798 list2
->Append(new wxExpr(line
->GetX()));
1799 list2
->Append(new wxExpr(line
->GetY()));
1800 list2
->Append(new wxExpr(PrologString
, line
->GetText()));
1801 textExpr
->Append(list2
);
1802 textNode
= textNode
->Next();
1805 // Now add both attributes to the clause
1806 clause
->AddAttributeValue(regionNameBuf
, regionExpr
);
1807 clause
->AddAttributeValue(textNameBuf
, textExpr
);
1809 node
= node
->Next();
1814 void wxShape::ReadPrologAttributes(wxExpr
*clause
)
1816 clause
->GetAttributeValue("id", m_id
);
1819 clause
->GetAttributeValue("x", m_xpos
);
1820 clause
->GetAttributeValue("y", m_ypos
);
1822 // Input text strings (FOR COMPATIBILITY WITH OLD FILES ONLY. SEE REGION CODE BELOW.)
1824 wxExpr
*strings
= clause
->AttributeValue("text");
1825 if (strings
&& strings
->Type() == PrologList
)
1827 m_formatted
= TRUE
; // Assume text is formatted unless we prove otherwise
1828 wxExpr
*node
= strings
->value
.first
;
1831 wxExpr
*string_expr
= node
;
1834 wxString
the_string("");
1836 // string_expr can either be a string, or a list of
1837 // 3 elements: x, y, and string.
1838 if (string_expr
->Type() == PrologString
)
1840 the_string
= string_expr
->StringValue();
1841 m_formatted
= FALSE
;
1843 else if (string_expr
->Type() == PrologList
)
1845 wxExpr
*first
= string_expr
->value
.first
;
1846 wxExpr
*second
= first
? first
->next
: NULL
;
1847 wxExpr
*third
= second
? second
->next
: NULL
;
1849 if (first
&& second
&& third
&&
1850 (first
->Type() == PrologReal
|| first
->Type() == PrologInteger
) &&
1851 (second
->Type() == PrologReal
|| second
->Type() == PrologInteger
) &&
1852 third
->Type() == PrologString
)
1854 if (first
->Type() == PrologReal
)
1855 the_x
= first
->RealValue();
1856 else the_x
= (double)first
->IntegerValue();
1858 if (second
->Type() == PrologReal
)
1859 the_y
= second
->RealValue();
1860 else the_y
= (double)second
->IntegerValue();
1862 the_string
= third
->StringValue();
1865 wxShapeTextLine
*line
=
1866 new wxShapeTextLine(the_x
, the_y
, (char*) (const char*) the_string
);
1867 m_text
.Append(line
);
1873 wxString pen_string
= "";
1874 wxString brush_string
= "";
1876 int pen_style
= wxSOLID
;
1877 int brush_style
= wxSOLID
;
1878 m_attachmentMode
= FALSE
;
1880 clause
->GetAttributeValue("pen_colour", pen_string
);
1881 clause
->GetAttributeValue("text_colour", m_textColourName
);
1883 SetTextColour(m_textColourName
);
1885 clause
->GetAttributeValue("region_name", m_regionName
);
1887 clause
->GetAttributeValue("brush_colour", brush_string
);
1888 clause
->GetAttributeValue("pen_width", pen_width
);
1889 clause
->GetAttributeValue("pen_style", pen_style
);
1890 clause
->GetAttributeValue("brush_style", brush_style
);
1892 int iVal
= (int) m_attachmentMode
;
1893 clause
->GetAttributeValue("use_attachments", iVal
);
1894 m_attachmentMode
= (iVal
!= 0);
1896 clause
->GetAttributeValue("sensitivity", m_sensitivity
);
1898 iVal
= (int) m_spaceAttachments
;
1899 clause
->GetAttributeValue("space_attachments", iVal
);
1900 m_spaceAttachments
= (iVal
!= 0);
1902 iVal
= (int) m_fixedWidth
;
1903 clause
->GetAttributeValue("fixed_width", iVal
);
1904 m_fixedWidth
= (iVal
!= 0);
1906 iVal
= (int) m_fixedHeight
;
1907 clause
->GetAttributeValue("fixed_height", iVal
);
1908 m_fixedHeight
= (iVal
!= 0);
1910 clause
->GetAttributeValue("format_mode", m_formatMode
);
1911 clause
->GetAttributeValue("shadow_mode", m_shadowMode
);
1913 iVal
= (int) m_centreResize
;
1914 clause
->GetAttributeValue("centre_resize", iVal
);
1915 m_centreResize
= (iVal
!= 0);
1917 iVal
= (int) m_highlighted
;
1918 clause
->GetAttributeValue("hilite", iVal
);
1919 m_highlighted
= (iVal
!= 0);
1921 clause
->GetAttributeValue("rotation", m_rotation
);
1923 if (pen_string
== "")
1924 pen_string
= "BLACK";
1925 if (brush_string
== "")
1926 brush_string
= "WHITE";
1928 if (pen_string
[0] == '#')
1930 wxColour
col(oglHexToColour(pen_string
.After('#')));
1931 m_pen
= wxThePenList
->FindOrCreatePen(col
, pen_width
, pen_style
);
1934 m_pen
= wxThePenList
->FindOrCreatePen(pen_string
, pen_width
, pen_style
);
1937 m_pen
= wxBLACK_PEN
;
1939 if (brush_string
[0] == '#')
1941 wxColour
col(oglHexToColour(brush_string
.After('#')));
1942 m_brush
= wxTheBrushList
->FindOrCreateBrush(col
, brush_style
);
1945 m_brush
= wxTheBrushList
->FindOrCreateBrush(brush_string
, brush_style
);
1948 m_brush
= wxWHITE_BRUSH
;
1950 int point_size
= 10;
1951 clause
->GetAttributeValue("point_size", point_size
);
1952 SetFont(oglMatchFont(point_size
));
1954 // Read user-defined attachment points, if any
1955 wxExpr
*attachmentList
= clause
->AttributeValue("user_attachments");
1958 wxExpr
*pointExpr
= attachmentList
->GetFirst();
1961 wxExpr
*idExpr
= pointExpr
->Nth(0);
1962 wxExpr
*xExpr
= pointExpr
->Nth(1);
1963 wxExpr
*yExpr
= pointExpr
->Nth(2);
1964 if (idExpr
&& xExpr
&& yExpr
)
1966 wxAttachmentPoint
*point
= new wxAttachmentPoint
;
1967 point
->m_id
= (int)idExpr
->IntegerValue();
1968 point
->m_x
= xExpr
->RealValue();
1969 point
->m_y
= yExpr
->RealValue();
1970 m_attachmentPoints
.Append((wxObject
*)point
);
1972 pointExpr
= pointExpr
->GetNext();
1976 // Read text regions
1977 ReadRegions(clause
);
1980 void wxShape::ReadRegions(wxExpr
*clause
)
1984 // region1 = (regionName regionText x y width height minWidth minHeight proportionX proportionY
1985 // formatMode fontSize fontFamily fontStyle fontWeight textColour)
1987 char regionNameBuf
[20];
1988 char textNameBuf
[20];
1990 wxExpr
*regionExpr
= NULL
;
1991 wxExpr
*textExpr
= NULL
;
1992 sprintf(regionNameBuf
, "region%d", regionNo
);
1993 sprintf(textNameBuf
, "text%d", regionNo
);
1995 m_formatted
= TRUE
; // Assume text is formatted unless we prove otherwise
1997 while (regionExpr
= clause
->AttributeValue(regionNameBuf
))
2000 * Get the region information
2004 wxString
regionName("");
2005 wxString
regionText("");
2009 double height
= 0.0;
2010 double minWidth
= 5.0;
2011 double minHeight
= 5.0;
2012 double m_regionProportionX
= -1.0;
2013 double m_regionProportionY
= -1.0;
2014 int formatMode
= FORMAT_NONE
;
2016 int fontFamily
= wxSWISS
;
2017 int fontStyle
= wxNORMAL
;
2018 int fontWeight
= wxNORMAL
;
2019 wxString
regionTextColour("");
2020 wxString
penColour("");
2021 int penStyle
= wxSOLID
;
2023 if (regionExpr
->Type() == PrologList
)
2025 wxExpr
*nameExpr
= regionExpr
->Nth(0);
2026 wxExpr
*textExpr
= regionExpr
->Nth(1);
2027 wxExpr
*xExpr
= regionExpr
->Nth(2);
2028 wxExpr
*yExpr
= regionExpr
->Nth(3);
2029 wxExpr
*widthExpr
= regionExpr
->Nth(4);
2030 wxExpr
*heightExpr
= regionExpr
->Nth(5);
2031 wxExpr
*minWidthExpr
= regionExpr
->Nth(6);
2032 wxExpr
*minHeightExpr
= regionExpr
->Nth(7);
2033 wxExpr
*propXExpr
= regionExpr
->Nth(8);
2034 wxExpr
*propYExpr
= regionExpr
->Nth(9);
2035 wxExpr
*formatExpr
= regionExpr
->Nth(10);
2036 wxExpr
*sizeExpr
= regionExpr
->Nth(11);
2037 wxExpr
*familyExpr
= regionExpr
->Nth(12);
2038 wxExpr
*styleExpr
= regionExpr
->Nth(13);
2039 wxExpr
*weightExpr
= regionExpr
->Nth(14);
2040 wxExpr
*colourExpr
= regionExpr
->Nth(15);
2041 wxExpr
*penColourExpr
= regionExpr
->Nth(16);
2042 wxExpr
*penStyleExpr
= regionExpr
->Nth(17);
2044 regionName
= nameExpr
->StringValue();
2045 regionText
= textExpr
->StringValue();
2047 x
= xExpr
->RealValue();
2048 y
= yExpr
->RealValue();
2050 width
= widthExpr
->RealValue();
2051 height
= heightExpr
->RealValue();
2053 minWidth
= minWidthExpr
->RealValue();
2054 minHeight
= minHeightExpr
->RealValue();
2056 m_regionProportionX
= propXExpr
->RealValue();
2057 m_regionProportionY
= propYExpr
->RealValue();
2059 formatMode
= (int) formatExpr
->IntegerValue();
2060 fontSize
= (int)sizeExpr
->IntegerValue();
2061 fontFamily
= (int)familyExpr
->IntegerValue();
2062 fontStyle
= (int)styleExpr
->IntegerValue();
2063 fontWeight
= (int)weightExpr
->IntegerValue();
2067 regionTextColour
= colourExpr
->StringValue();
2070 regionTextColour
= "BLACK";
2073 penColour
= penColourExpr
->StringValue();
2075 penStyle
= (int)penStyleExpr
->IntegerValue();
2077 wxFont
*font
= wxTheFontList
->FindOrCreateFont(fontSize
, fontFamily
, fontStyle
, fontWeight
);
2079 wxShapeRegion
*region
= new wxShapeRegion
;
2080 region
->SetProportions(m_regionProportionX
, m_regionProportionY
);
2081 region
->SetFont(font
);
2082 region
->SetSize(width
, height
);
2083 region
->SetPosition(x
, y
);
2084 region
->SetMinSize(minWidth
, minHeight
);
2085 region
->SetFormatMode(formatMode
);
2086 region
->SetPenStyle(penStyle
);
2087 if (penColour
!= "")
2088 region
->SetPenColour(penColour
);
2090 region
->m_textColour
= regionTextColour
;
2091 region
->m_regionText
= regionText
;
2092 region
->m_regionName
= regionName
;
2094 m_regions
.Append(region
);
2097 * Get the formatted text strings
2100 textExpr
= clause
->AttributeValue(textNameBuf
);
2101 if (textExpr
&& (textExpr
->Type() == PrologList
))
2103 wxExpr
*node
= textExpr
->value
.first
;
2106 wxExpr
*string_expr
= node
;
2109 wxString
the_string("");
2111 // string_expr can either be a string, or a list of
2112 // 3 elements: x, y, and string.
2113 if (string_expr
->Type() == PrologString
)
2115 the_string
= string_expr
->StringValue();
2116 m_formatted
= FALSE
;
2118 else if (string_expr
->Type() == PrologList
)
2120 wxExpr
*first
= string_expr
->value
.first
;
2121 wxExpr
*second
= first
? first
->next
: NULL
;
2122 wxExpr
*third
= second
? second
->next
: NULL
;
2124 if (first
&& second
&& third
&&
2125 (first
->Type() == PrologReal
|| first
->Type() == PrologInteger
) &&
2126 (second
->Type() == PrologReal
|| second
->Type() == PrologInteger
) &&
2127 third
->Type() == PrologString
)
2129 if (first
->Type() == PrologReal
)
2130 the_x
= first
->RealValue();
2131 else the_x
= (double)first
->IntegerValue();
2133 if (second
->Type() == PrologReal
)
2134 the_y
= second
->RealValue();
2135 else the_y
= (double)second
->IntegerValue();
2137 the_string
= third
->StringValue();
2142 wxShapeTextLine
*line
=
2143 new wxShapeTextLine(the_x
, the_y
, (char*) (const char*) the_string
);
2144 region
->m_formattedText
.Append(line
);
2151 sprintf(regionNameBuf
, "region%d", regionNo
);
2152 sprintf(textNameBuf
, "text%d", regionNo
);
2155 // Compatibility: check for no regions (old file).
2156 // Lines and divided rectangles must deal with this compatibility
2157 // theirselves. Composites _may_ not have any regions anyway.
2158 if ((m_regions
.Number() == 0) &&
2159 !this->IsKindOf(CLASSINFO(wxLineShape
)) && !this->IsKindOf(CLASSINFO(wxDividedShape
)) &&
2160 !this->IsKindOf(CLASSINFO(wxCompositeShape
)))
2162 wxShapeRegion
*newRegion
= new wxShapeRegion
;
2163 newRegion
->SetName("0");
2164 m_regions
.Append((wxObject
*)newRegion
);
2165 if (m_text
.Number() > 0)
2167 newRegion
->ClearText();
2168 wxNode
*node
= m_text
.First();
2171 wxShapeTextLine
*textLine
= (wxShapeTextLine
*)node
->Data();
2172 wxNode
*next
= node
->Next();
2173 newRegion
->GetFormattedText().Append((wxObject
*)textLine
);
2183 void wxShape::Copy(wxShape
& copy
)
2186 copy
.m_xpos
= m_xpos
;
2187 copy
.m_ypos
= m_ypos
;
2189 copy
.m_brush
= m_brush
;
2190 copy
.m_textColour
= m_textColour
;
2191 copy
.m_centreResize
= m_centreResize
;
2192 copy
.m_attachmentMode
= m_attachmentMode
;
2193 copy
.m_spaceAttachments
= m_spaceAttachments
;
2194 copy
.m_highlighted
= m_highlighted
;
2195 copy
.m_rotation
= m_rotation
;
2196 copy
.m_textColourName
= m_textColourName
;
2197 copy
.m_regionName
= m_regionName
;
2199 copy
.m_sensitivity
= m_sensitivity
;
2200 copy
.m_draggable
= m_draggable
;
2201 copy
.m_fixedWidth
= m_fixedWidth
;
2202 copy
.m_fixedHeight
= m_fixedHeight
;
2203 copy
.m_formatMode
= m_formatMode
;
2204 copy
.m_drawHandles
= m_drawHandles
;
2206 copy
.m_visible
= m_visible
;
2207 copy
.m_shadowMode
= m_shadowMode
;
2208 copy
.m_shadowOffsetX
= m_shadowOffsetX
;
2209 copy
.m_shadowOffsetY
= m_shadowOffsetY
;
2210 copy
.m_shadowBrush
= m_shadowBrush
;
2212 // Copy text regions
2213 copy
.ClearRegions();
2214 wxNode
*node
= m_regions
.First();
2217 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
2218 wxShapeRegion
*newRegion
= new wxShapeRegion(*region
);
2219 copy
.m_regions
.Append(newRegion
);
2220 node
= node
->Next();
2224 copy
.ClearAttachments();
2225 node
= m_attachmentPoints
.First();
2228 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->Data();
2229 wxAttachmentPoint
*newPoint
= new wxAttachmentPoint
;
2230 newPoint
->m_id
= point
->m_id
;
2231 newPoint
->m_x
= point
->m_x
;
2232 newPoint
->m_y
= point
->m_y
;
2233 copy
.m_attachmentPoints
.Append((wxObject
*)newPoint
);
2234 node
= node
->Next();
2238 copy
.m_lines
.Clear();
2239 node
= m_lines
.First();
2242 wxLineShape
* line
= (wxLineShape
*) node
->Data();
2243 copy
.m_lines
.Append(line
);
2244 node
= node
->Next();
2248 // Create and return a new, fully copied object.
2249 wxShape
*wxShape::CreateNewCopy(bool resetMapping
, bool recompute
)
2252 oglObjectCopyMapping
.Clear();
2254 wxShape
* newObject
= (wxShape
*) GetClassInfo()->CreateObject();
2256 wxASSERT( (newObject
!= NULL
) );
2257 wxASSERT( (newObject
->IsKindOf(CLASSINFO(wxShape
))) );
2261 if (GetEventHandler() != this)
2263 wxShapeEvtHandler
* newHandler
= GetEventHandler()->CreateNewCopy();
2264 newObject
->SetEventHandler(newHandler
);
2265 newObject
->SetPreviousHandler(NULL
);
2266 newHandler
->SetPreviousHandler(newObject
);
2267 newHandler
->SetShape(newObject
);
2271 newObject
->Recompute();
2275 // Does the copying for this object, including copying event
2276 // handler data if any. Calls the virtual Copy function.
2277 void wxShape::CopyWithHandler(wxShape
& copy
)
2281 if (GetEventHandler() != this)
2283 wxASSERT( copy
.GetEventHandler() != NULL
);
2284 wxASSERT( copy
.GetEventHandler() != (©
) );
2285 wxASSERT( GetEventHandler()->GetClassInfo() == copy
.GetEventHandler()->GetClassInfo() );
2286 GetEventHandler()->CopyData(* (copy
.GetEventHandler()));
2291 // Default - make 6 control points
2292 void wxShape::MakeControlPoints()
2294 double maxX
, maxY
, minX
, minY
;
2296 GetBoundingBoxMax(&maxX
, &maxY
);
2297 GetBoundingBoxMin(&minX
, &minY
);
2299 double widthMin
= (double)(minX
+ CONTROL_POINT_SIZE
+ 2);
2300 double heightMin
= (double)(minY
+ CONTROL_POINT_SIZE
+ 2);
2302 // Offsets from main object
2303 double top
= (double)(- (heightMin
/ 2.0));
2304 double bottom
= (double)(heightMin
/ 2.0 + (maxY
- minY
));
2305 double left
= (double)(- (widthMin
/ 2.0));
2306 double right
= (double)(widthMin
/ 2.0 + (maxX
- minX
));
2308 wxControlPoint
*control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, left
, top
,
2309 CONTROL_POINT_DIAGONAL
);
2310 m_canvas
->AddShape(control
);
2311 m_controlPoints
.Append(control
);
2313 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, 0, top
,
2314 CONTROL_POINT_VERTICAL
);
2315 m_canvas
->AddShape(control
);
2316 m_controlPoints
.Append(control
);
2318 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, right
, top
,
2319 CONTROL_POINT_DIAGONAL
);
2320 m_canvas
->AddShape(control
);
2321 m_controlPoints
.Append(control
);
2323 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, right
, 0,
2324 CONTROL_POINT_HORIZONTAL
);
2325 m_canvas
->AddShape(control
);
2326 m_controlPoints
.Append(control
);
2328 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, right
, bottom
,
2329 CONTROL_POINT_DIAGONAL
);
2330 m_canvas
->AddShape(control
);
2331 m_controlPoints
.Append(control
);
2333 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, 0, bottom
,
2334 CONTROL_POINT_VERTICAL
);
2335 m_canvas
->AddShape(control
);
2336 m_controlPoints
.Append(control
);
2338 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, left
, bottom
,
2339 CONTROL_POINT_DIAGONAL
);
2340 m_canvas
->AddShape(control
);
2341 m_controlPoints
.Append(control
);
2343 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, left
, 0,
2344 CONTROL_POINT_HORIZONTAL
);
2345 m_canvas
->AddShape(control
);
2346 m_controlPoints
.Append(control
);
2350 void wxShape::MakeMandatoryControlPoints()
2352 wxNode
*node
= m_children
.First();
2355 wxShape
*child
= (wxShape
*)node
->Data();
2356 child
->MakeMandatoryControlPoints();
2357 node
= node
->Next();
2361 void wxShape::ResetMandatoryControlPoints()
2363 wxNode
*node
= m_children
.First();
2366 wxShape
*child
= (wxShape
*)node
->Data();
2367 child
->ResetMandatoryControlPoints();
2368 node
= node
->Next();
2372 void wxShape::ResetControlPoints()
2374 ResetMandatoryControlPoints();
2376 if (m_controlPoints
.Number() < 1)
2379 double maxX
, maxY
, minX
, minY
;
2381 GetBoundingBoxMax(&maxX
, &maxY
);
2382 GetBoundingBoxMin(&minX
, &minY
);
2384 double widthMin
= (double)(minX
+ CONTROL_POINT_SIZE
+ 2);
2385 double heightMin
= (double)(minY
+ CONTROL_POINT_SIZE
+ 2);
2387 // Offsets from main object
2388 double top
= (double)(- (heightMin
/ 2.0));
2389 double bottom
= (double)(heightMin
/ 2.0 + (maxY
- minY
));
2390 double left
= (double)(- (widthMin
/ 2.0));
2391 double right
= (double)(widthMin
/ 2.0 + (maxX
- minX
));
2393 wxNode
*node
= m_controlPoints
.First();
2394 wxControlPoint
*control
= (wxControlPoint
*)node
->Data();
2395 control
->m_xoffset
= left
; control
->m_yoffset
= top
;
2397 node
= node
->Next(); control
= (wxControlPoint
*)node
->Data();
2398 control
->m_xoffset
= 0; control
->m_yoffset
= top
;
2400 node
= node
->Next(); control
= (wxControlPoint
*)node
->Data();
2401 control
->m_xoffset
= right
; control
->m_yoffset
= top
;
2403 node
= node
->Next(); control
= (wxControlPoint
*)node
->Data();
2404 control
->m_xoffset
= right
; control
->m_yoffset
= 0;
2406 node
= node
->Next(); control
= (wxControlPoint
*)node
->Data();
2407 control
->m_xoffset
= right
; control
->m_yoffset
= bottom
;
2409 node
= node
->Next(); control
= (wxControlPoint
*)node
->Data();
2410 control
->m_xoffset
= 0; control
->m_yoffset
= bottom
;
2412 node
= node
->Next(); control
= (wxControlPoint
*)node
->Data();
2413 control
->m_xoffset
= left
; control
->m_yoffset
= bottom
;
2415 node
= node
->Next(); control
= (wxControlPoint
*)node
->Data();
2416 control
->m_xoffset
= left
; control
->m_yoffset
= 0;
2419 void wxShape::DeleteControlPoints(wxDC
*dc
)
2421 wxNode
*node
= m_controlPoints
.First();
2424 wxControlPoint
*control
= (wxControlPoint
*)node
->Data();
2426 control
->GetEventHandler()->OnErase(*dc
);
2427 m_canvas
->RemoveShape(control
);
2430 node
= m_controlPoints
.First();
2432 // Children of divisions are contained objects,
2434 if (!IsKindOf(CLASSINFO(wxDivisionShape
)))
2436 node
= m_children
.First();
2439 wxShape
*child
= (wxShape
*)node
->Data();
2440 child
->DeleteControlPoints(dc
);
2441 node
= node
->Next();
2446 void wxShape::OnDrawControlPoints(wxDC
& dc
)
2451 dc
.SetBrush(wxBLACK_BRUSH
);
2452 dc
.SetPen(wxBLACK_PEN
);
2454 wxNode
*node
= m_controlPoints
.First();
2457 wxControlPoint
*control
= (wxControlPoint
*)node
->Data();
2459 node
= node
->Next();
2461 // Children of divisions are contained objects,
2463 // This test bypasses the type facility for speed
2464 // (critical when drawing)
2465 if (!IsKindOf(CLASSINFO(wxDivisionShape
)))
2467 node
= m_children
.First();
2470 wxShape
*child
= (wxShape
*)node
->Data();
2471 child
->GetEventHandler()->OnDrawControlPoints(dc
);
2472 node
= node
->Next();
2477 void wxShape::OnEraseControlPoints(wxDC
& dc
)
2479 wxNode
*node
= m_controlPoints
.First();
2482 wxControlPoint
*control
= (wxControlPoint
*)node
->Data();
2484 node
= node
->Next();
2486 if (!IsKindOf(CLASSINFO(wxDivisionShape
)))
2488 node
= m_children
.First();
2491 wxShape
*child
= (wxShape
*)node
->Data();
2492 child
->GetEventHandler()->OnEraseControlPoints(dc
);
2493 node
= node
->Next();
2498 void wxShape::Select(bool select
, wxDC
* dc
)
2500 m_selected
= select
;
2503 MakeControlPoints();
2504 // Children of divisions are contained objects,
2506 if (!IsKindOf(CLASSINFO(wxDivisionShape
)))
2508 wxNode
*node
= m_children
.First();
2511 wxShape
*child
= (wxShape
*)node
->Data();
2512 child
->MakeMandatoryControlPoints();
2513 node
= node
->Next();
2517 GetEventHandler()->OnDrawControlPoints(*dc
);
2521 DeleteControlPoints(dc
);
2522 if (!IsKindOf(CLASSINFO(wxDivisionShape
)))
2524 wxNode
*node
= m_children
.First();
2527 wxShape
*child
= (wxShape
*)node
->Data();
2528 child
->DeleteControlPoints(dc
);
2529 node
= node
->Next();
2535 bool wxShape::Selected() const
2540 bool wxShape::AncestorSelected() const
2542 if (m_selected
) return TRUE
;
2546 return GetParent()->AncestorSelected();
2549 int wxShape::GetNumberOfAttachments()
2551 // Should return the MAXIMUM attachment point id here,
2552 // so higher-level functions can iterate through all attachments,
2553 // even if they're not contiguous.
2554 if (m_attachmentPoints
.Number() == 0)
2559 wxNode
*node
= m_attachmentPoints
.First();
2562 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->Data();
2563 if (point
->m_id
> maxN
)
2565 node
= node
->Next();
2571 bool wxShape::AttachmentIsValid(int attachment
)
2573 if ((attachment
>= 0) && (attachment
< 4))
2576 wxNode
*node
= m_attachmentPoints
.First();
2579 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->Data();
2580 if (point
->m_id
== attachment
)
2582 node
= node
->Next();
2587 bool wxShape::GetAttachmentPosition(int attachment
, double *x
, double *y
,
2588 int nth
, int no_arcs
, wxLineShape
*line
)
2590 if (!m_attachmentMode
)
2592 *x
= m_xpos
; *y
= m_ypos
;
2597 wxNode
*node
= m_attachmentPoints
.First();
2600 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->Data();
2601 if (point
->m_id
== attachment
)
2603 *x
= (double)(m_xpos
+ point
->m_x
);
2604 *y
= (double)(m_ypos
+ point
->m_y
);
2607 node
= node
->Next();
2609 *x
= m_xpos
; *y
= m_ypos
;
2614 void wxShape::GetBoundingBoxMax(double *w
, double *h
)
2617 GetBoundingBoxMin(&ww
, &hh
);
2618 if (m_shadowMode
!= SHADOW_NONE
)
2620 ww
+= m_shadowOffsetX
;
2621 hh
+= m_shadowOffsetY
;
2627 // Returns TRUE if image is a descendant of this composite
2628 bool wxShape::HasDescendant(wxShape
*image
)
2632 wxNode
*node
= m_children
.First();
2635 wxShape
*child
= (wxShape
*)node
->Data();
2636 bool ans
= child
->HasDescendant(image
);
2639 node
= node
->Next();
2644 // Clears points from a list of wxRealPoints, and clears list
2645 void wxShape::ClearPointList(wxList
& list
)
2647 wxNode
* node
= list
.First();
2650 wxRealPoint
* pt
= (wxRealPoint
*) node
->Data();
2653 node
= node
->Next();
2658 // Assuming the attachment lies along a vertical or horizontal line,
2659 // calculate the position on that point.
2660 wxRealPoint
wxShape::CalcSimpleAttachment(const wxRealPoint
& pt1
, const wxRealPoint
& pt2
,
2661 int nth
, int noArcs
, wxLineShape
* line
)
2663 bool isEnd
= (line
&& line
->IsEnd(this));
2665 // Are we horizontal or vertical?
2666 bool isHorizontal
= (oglRoughlyEqual(pt1
.y
, pt2
.y
) == TRUE
);
2672 wxRealPoint firstPoint
, secondPoint
;
2684 if (m_spaceAttachments
)
2686 if (line
&& (line
->GetAlignmentType(isEnd
) == LINE_ALIGNMENT_TO_NEXT_HANDLE
))
2688 // Align line according to the next handle along
2689 wxRealPoint
*point
= line
->GetNextControlPoint(this);
2690 if (point
->x
< firstPoint
.x
)
2692 else if (point
->x
> secondPoint
.x
)
2698 x
= firstPoint
.x
+ (nth
+ 1)*(secondPoint
.x
- firstPoint
.x
)/(noArcs
+ 1);
2700 else x
= (secondPoint
.x
- firstPoint
.x
)/2.0; // Midpoint
2706 wxASSERT( oglRoughlyEqual(pt1
.x
, pt2
.x
) == TRUE
);
2708 wxRealPoint firstPoint
, secondPoint
;
2720 if (m_spaceAttachments
)
2722 if (line
&& (line
->GetAlignmentType(isEnd
) == LINE_ALIGNMENT_TO_NEXT_HANDLE
))
2724 // Align line according to the next handle along
2725 wxRealPoint
*point
= line
->GetNextControlPoint(this);
2726 if (point
->y
< firstPoint
.y
)
2728 else if (point
->y
> secondPoint
.y
)
2734 y
= firstPoint
.y
+ (nth
+ 1)*(secondPoint
.y
- firstPoint
.y
)/(noArcs
+ 1);
2736 else y
= (secondPoint
.y
- firstPoint
.y
)/2.0; // Midpoint
2741 return wxRealPoint(x
, y
);
2744 // Return the zero-based position in m_lines of line.
2745 int wxShape::GetLinePosition(wxLineShape
* line
)
2748 for (i
= 0; i
< m_lines
.Number(); i
++)
2749 if ((wxLineShape
*) (m_lines
.Nth(i
)->Data()) == line
)