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 char *wxShape::GetFunctor()
1640 return "node_image";
1643 void wxShape::WritePrologAttributes(wxExpr
*clause
)
1645 clause
->AddAttributeValueString("type", GetClassInfo()->GetClassName());
1646 clause
->AddAttributeValue("id", m_id
);
1650 int penWidth
= m_pen
->GetWidth();
1651 int penStyle
= m_pen
->GetStyle();
1653 clause
->AddAttributeValue("pen_width", (long)penWidth
);
1654 if (penStyle
!= wxSOLID
)
1655 clause
->AddAttributeValue("pen_style", (long)penStyle
);
1657 wxString penColour
= wxTheColourDatabase
->FindName(m_pen
->GetColour());
1658 if (penColour
== "")
1660 wxString
hex(oglColourToHex(m_pen
->GetColour()));
1661 hex
= wxString("#") + hex
;
1662 clause
->AddAttributeValueString("pen_colour", hex
);
1664 else if (penColour
!= "BLACK")
1665 clause
->AddAttributeValueString("pen_colour", penColour
);
1670 wxString brushColour
= wxTheColourDatabase
->FindName(m_brush
->GetColour());
1672 if (brushColour
== "")
1674 wxString
hex(oglColourToHex(m_brush
->GetColour()));
1675 hex
= wxString("#") + hex
;
1676 clause
->AddAttributeValueString("brush_colour", hex
);
1678 else if (brushColour
!= "WHITE")
1679 clause
->AddAttributeValueString("brush_colour", brushColour
);
1681 if (m_brush
->GetStyle() != wxSOLID
)
1682 clause
->AddAttributeValue("brush_style", (long)m_brush
->GetStyle());
1687 int n_lines
= m_lines
.Number();
1690 wxExpr
*list
= new wxExpr(PrologList
);
1691 wxNode
*node
= m_lines
.First();
1694 wxShape
*line
= (wxShape
*)node
->Data();
1695 wxExpr
*id_expr
= new wxExpr(line
->GetId());
1696 list
->Append(id_expr
);
1697 node
= node
->Next();
1699 clause
->AddAttributeValue("arcs", list
);
1702 // Miscellaneous members
1703 if (m_attachmentMode
!= 0)
1704 clause
->AddAttributeValue("use_attachments", (long)m_attachmentMode
);
1705 if (m_sensitivity
!= OP_ALL
)
1706 clause
->AddAttributeValue("sensitivity", (long)m_sensitivity
);
1707 if (!m_spaceAttachments
)
1708 clause
->AddAttributeValue("space_attachments", (long)m_spaceAttachments
);
1710 clause
->AddAttributeValue("fixed_width", (long)m_fixedWidth
);
1712 clause
->AddAttributeValue("fixed_height", (long)m_fixedHeight
);
1713 if (m_shadowMode
!= SHADOW_NONE
)
1714 clause
->AddAttributeValue("shadow_mode", (long)m_shadowMode
);
1715 if (m_centreResize
!= TRUE
)
1716 clause
->AddAttributeValue("centre_resize", (long)0);
1717 if (m_highlighted
!= FALSE
)
1718 clause
->AddAttributeValue("hilite", (long)m_highlighted
);
1720 if (m_parent
) // For composite objects
1721 clause
->AddAttributeValue("parent", (long)m_parent
->GetId());
1723 if (m_rotation
!= 0.0)
1724 clause
->AddAttributeValue("rotation", m_rotation
);
1726 // Write user-defined attachment points, if any
1727 if (m_attachmentPoints
.Number() > 0)
1729 wxExpr
*attachmentList
= new wxExpr(PrologList
);
1730 wxNode
*node
= m_attachmentPoints
.First();
1733 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->Data();
1734 wxExpr
*pointExpr
= new wxExpr(PrologList
);
1735 pointExpr
->Append(new wxExpr((long)point
->m_id
));
1736 pointExpr
->Append(new wxExpr(point
->m_x
));
1737 pointExpr
->Append(new wxExpr(point
->m_y
));
1738 attachmentList
->Append(pointExpr
);
1739 node
= node
->Next();
1741 clause
->AddAttributeValue("user_attachments", attachmentList
);
1744 // Write text regions
1745 WriteRegions(clause
);
1748 void wxShape::WriteRegions(wxExpr
*clause
)
1750 // Output regions as region1 = (...), region2 = (...), etc
1751 // and formatted text as text1 = (...), text2 = (...) etc.
1753 char regionNameBuf
[20];
1754 char textNameBuf
[20];
1755 wxNode
*node
= m_regions
.First();
1758 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
1759 sprintf(regionNameBuf
, "region%d", regionNo
);
1760 sprintf(textNameBuf
, "text%d", regionNo
);
1762 // Original text and region attributes:
1763 // region1 = (regionName regionText x y width height minWidth minHeight proportionX proportionY
1764 // formatMode fontSize fontFamily fontStyle fontWeight textColour)
1765 wxExpr
*regionExpr
= new wxExpr(PrologList
);
1766 regionExpr
->Append(new wxExpr(PrologString
, (region
->m_regionName
? region
->m_regionName
: "")));
1767 regionExpr
->Append(new wxExpr(PrologString
, (region
->m_regionText
? region
->m_regionText
: "")));
1769 regionExpr
->Append(new wxExpr(region
->m_x
));
1770 regionExpr
->Append(new wxExpr(region
->m_y
));
1771 regionExpr
->Append(new wxExpr(region
->GetWidth()));
1772 regionExpr
->Append(new wxExpr(region
->GetHeight()));
1774 regionExpr
->Append(new wxExpr(region
->m_minWidth
));
1775 regionExpr
->Append(new wxExpr(region
->m_minHeight
));
1776 regionExpr
->Append(new wxExpr(region
->m_regionProportionX
));
1777 regionExpr
->Append(new wxExpr(region
->m_regionProportionY
));
1779 regionExpr
->Append(new wxExpr((long)region
->m_formatMode
));
1781 regionExpr
->Append(new wxExpr((long)(region
->m_font
? region
->m_font
->GetPointSize() : 10)));
1782 regionExpr
->Append(new wxExpr((long)(region
->m_font
? region
->m_font
->GetFamily() : wxDEFAULT
)));
1783 regionExpr
->Append(new wxExpr((long)(region
->m_font
? region
->m_font
->GetStyle() : wxDEFAULT
)));
1784 regionExpr
->Append(new wxExpr((long)(region
->m_font
? region
->m_font
->GetWeight() : wxNORMAL
)));
1785 regionExpr
->Append(new wxExpr(PrologString
, region
->m_textColour
? region
->m_textColour
: "BLACK"));
1787 // New members for pen colour/style
1788 regionExpr
->Append(new wxExpr(PrologString
, region
->m_penColour
? region
->m_penColour
: "BLACK"));
1789 regionExpr
->Append(new wxExpr((long)region
->m_penStyle
));
1792 // text1 = ((x y string) (x y string) ...)
1793 wxExpr
*textExpr
= new wxExpr(PrologList
);
1795 wxNode
*textNode
= region
->m_formattedText
.First();
1798 wxShapeTextLine
*line
= (wxShapeTextLine
*)textNode
->Data();
1799 wxExpr
*list2
= new wxExpr(PrologList
);
1800 list2
->Append(new wxExpr(line
->GetX()));
1801 list2
->Append(new wxExpr(line
->GetY()));
1802 list2
->Append(new wxExpr(PrologString
, line
->GetText()));
1803 textExpr
->Append(list2
);
1804 textNode
= textNode
->Next();
1807 // Now add both attributes to the clause
1808 clause
->AddAttributeValue(regionNameBuf
, regionExpr
);
1809 clause
->AddAttributeValue(textNameBuf
, textExpr
);
1811 node
= node
->Next();
1816 void wxShape::ReadPrologAttributes(wxExpr
*clause
)
1818 clause
->GetAttributeValue("id", m_id
);
1821 clause
->GetAttributeValue("x", m_xpos
);
1822 clause
->GetAttributeValue("y", m_ypos
);
1824 // Input text strings (FOR COMPATIBILITY WITH OLD FILES ONLY. SEE REGION CODE BELOW.)
1826 wxExpr
*strings
= clause
->AttributeValue("text");
1827 if (strings
&& strings
->Type() == PrologList
)
1829 m_formatted
= TRUE
; // Assume text is formatted unless we prove otherwise
1830 wxExpr
*node
= strings
->value
.first
;
1833 wxExpr
*string_expr
= node
;
1836 wxString
the_string("");
1838 // string_expr can either be a string, or a list of
1839 // 3 elements: x, y, and string.
1840 if (string_expr
->Type() == PrologString
)
1842 the_string
= string_expr
->StringValue();
1843 m_formatted
= FALSE
;
1845 else if (string_expr
->Type() == PrologList
)
1847 wxExpr
*first
= string_expr
->value
.first
;
1848 wxExpr
*second
= first
? first
->next
: NULL
;
1849 wxExpr
*third
= second
? second
->next
: NULL
;
1851 if (first
&& second
&& third
&&
1852 (first
->Type() == PrologReal
|| first
->Type() == PrologInteger
) &&
1853 (second
->Type() == PrologReal
|| second
->Type() == PrologInteger
) &&
1854 third
->Type() == PrologString
)
1856 if (first
->Type() == PrologReal
)
1857 the_x
= first
->RealValue();
1858 else the_x
= (double)first
->IntegerValue();
1860 if (second
->Type() == PrologReal
)
1861 the_y
= second
->RealValue();
1862 else the_y
= (double)second
->IntegerValue();
1864 the_string
= third
->StringValue();
1867 wxShapeTextLine
*line
=
1868 new wxShapeTextLine(the_x
, the_y
, (char*) (const char*) the_string
);
1869 m_text
.Append(line
);
1875 wxString pen_string
= "";
1876 wxString brush_string
= "";
1878 int pen_style
= wxSOLID
;
1879 int brush_style
= wxSOLID
;
1880 m_attachmentMode
= FALSE
;
1882 clause
->GetAttributeValue("pen_colour", pen_string
);
1883 clause
->GetAttributeValue("text_colour", m_textColourName
);
1885 SetTextColour(m_textColourName
);
1887 clause
->GetAttributeValue("region_name", m_regionName
);
1889 clause
->GetAttributeValue("brush_colour", brush_string
);
1890 clause
->GetAttributeValue("pen_width", pen_width
);
1891 clause
->GetAttributeValue("pen_style", pen_style
);
1892 clause
->GetAttributeValue("brush_style", brush_style
);
1894 int iVal
= (int) m_attachmentMode
;
1895 clause
->GetAttributeValue("use_attachments", iVal
);
1896 m_attachmentMode
= (iVal
!= 0);
1898 clause
->GetAttributeValue("sensitivity", m_sensitivity
);
1900 iVal
= (int) m_spaceAttachments
;
1901 clause
->GetAttributeValue("space_attachments", iVal
);
1902 m_spaceAttachments
= (iVal
!= 0);
1904 iVal
= (int) m_fixedWidth
;
1905 clause
->GetAttributeValue("fixed_width", iVal
);
1906 m_fixedWidth
= (iVal
!= 0);
1908 iVal
= (int) m_fixedHeight
;
1909 clause
->GetAttributeValue("fixed_height", iVal
);
1910 m_fixedHeight
= (iVal
!= 0);
1912 clause
->GetAttributeValue("format_mode", m_formatMode
);
1913 clause
->GetAttributeValue("shadow_mode", m_shadowMode
);
1915 iVal
= (int) m_centreResize
;
1916 clause
->GetAttributeValue("centre_resize", iVal
);
1917 m_centreResize
= (iVal
!= 0);
1919 iVal
= (int) m_highlighted
;
1920 clause
->GetAttributeValue("hilite", iVal
);
1921 m_highlighted
= (iVal
!= 0);
1923 clause
->GetAttributeValue("rotation", m_rotation
);
1925 if (pen_string
== "")
1926 pen_string
= "BLACK";
1927 if (brush_string
== "")
1928 brush_string
= "WHITE";
1930 if (pen_string
[0] == '#')
1932 wxColour
col(oglHexToColour(pen_string
.After('#')));
1933 m_pen
= wxThePenList
->FindOrCreatePen(col
, pen_width
, pen_style
);
1936 m_pen
= wxThePenList
->FindOrCreatePen(pen_string
, pen_width
, pen_style
);
1939 m_pen
= wxBLACK_PEN
;
1941 if (brush_string
[0] == '#')
1943 wxColour
col(oglHexToColour(brush_string
.After('#')));
1944 m_brush
= wxTheBrushList
->FindOrCreateBrush(col
, brush_style
);
1947 m_brush
= wxTheBrushList
->FindOrCreateBrush(brush_string
, brush_style
);
1950 m_brush
= wxWHITE_BRUSH
;
1952 int point_size
= 10;
1953 clause
->GetAttributeValue("point_size", point_size
);
1954 SetFont(oglMatchFont(point_size
));
1956 // Read user-defined attachment points, if any
1957 wxExpr
*attachmentList
= clause
->AttributeValue("user_attachments");
1960 wxExpr
*pointExpr
= attachmentList
->GetFirst();
1963 wxExpr
*idExpr
= pointExpr
->Nth(0);
1964 wxExpr
*xExpr
= pointExpr
->Nth(1);
1965 wxExpr
*yExpr
= pointExpr
->Nth(2);
1966 if (idExpr
&& xExpr
&& yExpr
)
1968 wxAttachmentPoint
*point
= new wxAttachmentPoint
;
1969 point
->m_id
= (int)idExpr
->IntegerValue();
1970 point
->m_x
= xExpr
->RealValue();
1971 point
->m_y
= yExpr
->RealValue();
1972 m_attachmentPoints
.Append((wxObject
*)point
);
1974 pointExpr
= pointExpr
->GetNext();
1978 // Read text regions
1979 ReadRegions(clause
);
1982 void wxShape::ReadRegions(wxExpr
*clause
)
1986 // region1 = (regionName regionText x y width height minWidth minHeight proportionX proportionY
1987 // formatMode fontSize fontFamily fontStyle fontWeight textColour)
1989 char regionNameBuf
[20];
1990 char textNameBuf
[20];
1992 wxExpr
*regionExpr
= NULL
;
1993 wxExpr
*textExpr
= NULL
;
1994 sprintf(regionNameBuf
, "region%d", regionNo
);
1995 sprintf(textNameBuf
, "text%d", regionNo
);
1997 m_formatted
= TRUE
; // Assume text is formatted unless we prove otherwise
1999 while (regionExpr
= clause
->AttributeValue(regionNameBuf
))
2002 * Get the region information
2006 wxString
regionName("");
2007 wxString
regionText("");
2011 double height
= 0.0;
2012 double minWidth
= 5.0;
2013 double minHeight
= 5.0;
2014 double m_regionProportionX
= -1.0;
2015 double m_regionProportionY
= -1.0;
2016 int formatMode
= FORMAT_NONE
;
2018 int fontFamily
= wxSWISS
;
2019 int fontStyle
= wxNORMAL
;
2020 int fontWeight
= wxNORMAL
;
2021 wxString
regionTextColour("");
2022 wxString
penColour("");
2023 int penStyle
= wxSOLID
;
2025 if (regionExpr
->Type() == PrologList
)
2027 wxExpr
*nameExpr
= regionExpr
->Nth(0);
2028 wxExpr
*textExpr
= regionExpr
->Nth(1);
2029 wxExpr
*xExpr
= regionExpr
->Nth(2);
2030 wxExpr
*yExpr
= regionExpr
->Nth(3);
2031 wxExpr
*widthExpr
= regionExpr
->Nth(4);
2032 wxExpr
*heightExpr
= regionExpr
->Nth(5);
2033 wxExpr
*minWidthExpr
= regionExpr
->Nth(6);
2034 wxExpr
*minHeightExpr
= regionExpr
->Nth(7);
2035 wxExpr
*propXExpr
= regionExpr
->Nth(8);
2036 wxExpr
*propYExpr
= regionExpr
->Nth(9);
2037 wxExpr
*formatExpr
= regionExpr
->Nth(10);
2038 wxExpr
*sizeExpr
= regionExpr
->Nth(11);
2039 wxExpr
*familyExpr
= regionExpr
->Nth(12);
2040 wxExpr
*styleExpr
= regionExpr
->Nth(13);
2041 wxExpr
*weightExpr
= regionExpr
->Nth(14);
2042 wxExpr
*colourExpr
= regionExpr
->Nth(15);
2043 wxExpr
*penColourExpr
= regionExpr
->Nth(16);
2044 wxExpr
*penStyleExpr
= regionExpr
->Nth(17);
2046 regionName
= nameExpr
->StringValue();
2047 regionText
= textExpr
->StringValue();
2049 x
= xExpr
->RealValue();
2050 y
= yExpr
->RealValue();
2052 width
= widthExpr
->RealValue();
2053 height
= heightExpr
->RealValue();
2055 minWidth
= minWidthExpr
->RealValue();
2056 minHeight
= minHeightExpr
->RealValue();
2058 m_regionProportionX
= propXExpr
->RealValue();
2059 m_regionProportionY
= propYExpr
->RealValue();
2061 formatMode
= (int) formatExpr
->IntegerValue();
2062 fontSize
= (int)sizeExpr
->IntegerValue();
2063 fontFamily
= (int)familyExpr
->IntegerValue();
2064 fontStyle
= (int)styleExpr
->IntegerValue();
2065 fontWeight
= (int)weightExpr
->IntegerValue();
2069 regionTextColour
= colourExpr
->StringValue();
2072 regionTextColour
= "BLACK";
2075 penColour
= penColourExpr
->StringValue();
2077 penStyle
= (int)penStyleExpr
->IntegerValue();
2079 wxFont
*font
= wxTheFontList
->FindOrCreateFont(fontSize
, fontFamily
, fontStyle
, fontWeight
);
2081 wxShapeRegion
*region
= new wxShapeRegion
;
2082 region
->SetProportions(m_regionProportionX
, m_regionProportionY
);
2083 region
->SetFont(font
);
2084 region
->SetSize(width
, height
);
2085 region
->SetPosition(x
, y
);
2086 region
->SetMinSize(minWidth
, minHeight
);
2087 region
->SetFormatMode(formatMode
);
2088 region
->SetPenStyle(penStyle
);
2089 if (penColour
!= "")
2090 region
->SetPenColour(penColour
);
2092 region
->m_textColour
= regionTextColour
;
2093 region
->m_regionText
= regionText
;
2094 region
->m_regionName
= regionName
;
2096 m_regions
.Append(region
);
2099 * Get the formatted text strings
2102 textExpr
= clause
->AttributeValue(textNameBuf
);
2103 if (textExpr
&& (textExpr
->Type() == PrologList
))
2105 wxExpr
*node
= textExpr
->value
.first
;
2108 wxExpr
*string_expr
= node
;
2111 wxString
the_string("");
2113 // string_expr can either be a string, or a list of
2114 // 3 elements: x, y, and string.
2115 if (string_expr
->Type() == PrologString
)
2117 the_string
= string_expr
->StringValue();
2118 m_formatted
= FALSE
;
2120 else if (string_expr
->Type() == PrologList
)
2122 wxExpr
*first
= string_expr
->value
.first
;
2123 wxExpr
*second
= first
? first
->next
: NULL
;
2124 wxExpr
*third
= second
? second
->next
: NULL
;
2126 if (first
&& second
&& third
&&
2127 (first
->Type() == PrologReal
|| first
->Type() == PrologInteger
) &&
2128 (second
->Type() == PrologReal
|| second
->Type() == PrologInteger
) &&
2129 third
->Type() == PrologString
)
2131 if (first
->Type() == PrologReal
)
2132 the_x
= first
->RealValue();
2133 else the_x
= (double)first
->IntegerValue();
2135 if (second
->Type() == PrologReal
)
2136 the_y
= second
->RealValue();
2137 else the_y
= (double)second
->IntegerValue();
2139 the_string
= third
->StringValue();
2144 wxShapeTextLine
*line
=
2145 new wxShapeTextLine(the_x
, the_y
, (char*) (const char*) the_string
);
2146 region
->m_formattedText
.Append(line
);
2153 sprintf(regionNameBuf
, "region%d", regionNo
);
2154 sprintf(textNameBuf
, "text%d", regionNo
);
2157 // Compatibility: check for no regions (old file).
2158 // Lines and divided rectangles must deal with this compatibility
2159 // theirselves. Composites _may_ not have any regions anyway.
2160 if ((m_regions
.Number() == 0) &&
2161 !this->IsKindOf(CLASSINFO(wxLineShape
)) && !this->IsKindOf(CLASSINFO(wxDividedShape
)) &&
2162 !this->IsKindOf(CLASSINFO(wxCompositeShape
)))
2164 wxShapeRegion
*newRegion
= new wxShapeRegion
;
2165 newRegion
->SetName("0");
2166 m_regions
.Append((wxObject
*)newRegion
);
2167 if (m_text
.Number() > 0)
2169 newRegion
->ClearText();
2170 wxNode
*node
= m_text
.First();
2173 wxShapeTextLine
*textLine
= (wxShapeTextLine
*)node
->Data();
2174 wxNode
*next
= node
->Next();
2175 newRegion
->GetFormattedText().Append((wxObject
*)textLine
);
2185 void wxShape::Copy(wxShape
& copy
)
2188 copy
.m_xpos
= m_xpos
;
2189 copy
.m_ypos
= m_ypos
;
2191 copy
.m_brush
= m_brush
;
2192 copy
.m_textColour
= m_textColour
;
2193 copy
.m_centreResize
= m_centreResize
;
2194 copy
.m_attachmentMode
= m_attachmentMode
;
2195 copy
.m_spaceAttachments
= m_spaceAttachments
;
2196 copy
.m_highlighted
= m_highlighted
;
2197 copy
.m_rotation
= m_rotation
;
2198 copy
.m_textColourName
= m_textColourName
;
2199 copy
.m_regionName
= m_regionName
;
2201 copy
.m_sensitivity
= m_sensitivity
;
2202 copy
.m_draggable
= m_draggable
;
2203 copy
.m_fixedWidth
= m_fixedWidth
;
2204 copy
.m_fixedHeight
= m_fixedHeight
;
2205 copy
.m_formatMode
= m_formatMode
;
2206 copy
.m_drawHandles
= m_drawHandles
;
2208 copy
.m_visible
= m_visible
;
2209 copy
.m_shadowMode
= m_shadowMode
;
2210 copy
.m_shadowOffsetX
= m_shadowOffsetX
;
2211 copy
.m_shadowOffsetY
= m_shadowOffsetY
;
2212 copy
.m_shadowBrush
= m_shadowBrush
;
2214 // Copy text regions
2215 copy
.ClearRegions();
2216 wxNode
*node
= m_regions
.First();
2219 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
2220 wxShapeRegion
*newRegion
= new wxShapeRegion(*region
);
2221 copy
.m_regions
.Append(newRegion
);
2222 node
= node
->Next();
2226 copy
.ClearAttachments();
2227 node
= m_attachmentPoints
.First();
2230 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->Data();
2231 wxAttachmentPoint
*newPoint
= new wxAttachmentPoint
;
2232 newPoint
->m_id
= point
->m_id
;
2233 newPoint
->m_x
= point
->m_x
;
2234 newPoint
->m_y
= point
->m_y
;
2235 copy
.m_attachmentPoints
.Append((wxObject
*)newPoint
);
2236 node
= node
->Next();
2240 copy
.m_lines
.Clear();
2241 node
= m_lines
.First();
2244 wxLineShape
* line
= (wxLineShape
*) node
->Data();
2245 copy
.m_lines
.Append(line
);
2246 node
= node
->Next();
2250 // Create and return a new, fully copied object.
2251 wxShape
*wxShape::CreateNewCopy(bool resetMapping
, bool recompute
)
2254 oglObjectCopyMapping
.Clear();
2256 wxShape
* newObject
= (wxShape
*) GetClassInfo()->CreateObject();
2258 wxASSERT( (newObject
!= NULL
) );
2259 wxASSERT( (newObject
->IsKindOf(CLASSINFO(wxShape
))) );
2263 if (GetEventHandler() != this)
2265 wxShapeEvtHandler
* newHandler
= GetEventHandler()->CreateNewCopy();
2266 newObject
->SetEventHandler(newHandler
);
2267 newObject
->SetPreviousHandler(NULL
);
2268 newHandler
->SetPreviousHandler(newObject
);
2269 newHandler
->SetShape(newObject
);
2273 newObject
->Recompute();
2277 // Does the copying for this object, including copying event
2278 // handler data if any. Calls the virtual Copy function.
2279 void wxShape::CopyWithHandler(wxShape
& copy
)
2283 if (GetEventHandler() != this)
2285 wxASSERT( copy
.GetEventHandler() != NULL
);
2286 wxASSERT( copy
.GetEventHandler() != (©
) );
2287 wxASSERT( GetEventHandler()->GetClassInfo() == copy
.GetEventHandler()->GetClassInfo() );
2288 GetEventHandler()->CopyData(* (copy
.GetEventHandler()));
2293 // Default - make 6 control points
2294 void wxShape::MakeControlPoints()
2296 double maxX
, maxY
, minX
, minY
;
2298 GetBoundingBoxMax(&maxX
, &maxY
);
2299 GetBoundingBoxMin(&minX
, &minY
);
2301 double widthMin
= (double)(minX
+ CONTROL_POINT_SIZE
+ 2);
2302 double heightMin
= (double)(minY
+ CONTROL_POINT_SIZE
+ 2);
2304 // Offsets from main object
2305 double top
= (double)(- (heightMin
/ 2.0));
2306 double bottom
= (double)(heightMin
/ 2.0 + (maxY
- minY
));
2307 double left
= (double)(- (widthMin
/ 2.0));
2308 double right
= (double)(widthMin
/ 2.0 + (maxX
- minX
));
2310 wxControlPoint
*control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, left
, top
,
2311 CONTROL_POINT_DIAGONAL
);
2312 m_canvas
->AddShape(control
);
2313 m_controlPoints
.Append(control
);
2315 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, 0, top
,
2316 CONTROL_POINT_VERTICAL
);
2317 m_canvas
->AddShape(control
);
2318 m_controlPoints
.Append(control
);
2320 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, right
, top
,
2321 CONTROL_POINT_DIAGONAL
);
2322 m_canvas
->AddShape(control
);
2323 m_controlPoints
.Append(control
);
2325 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, right
, 0,
2326 CONTROL_POINT_HORIZONTAL
);
2327 m_canvas
->AddShape(control
);
2328 m_controlPoints
.Append(control
);
2330 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, right
, bottom
,
2331 CONTROL_POINT_DIAGONAL
);
2332 m_canvas
->AddShape(control
);
2333 m_controlPoints
.Append(control
);
2335 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, 0, bottom
,
2336 CONTROL_POINT_VERTICAL
);
2337 m_canvas
->AddShape(control
);
2338 m_controlPoints
.Append(control
);
2340 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, left
, bottom
,
2341 CONTROL_POINT_DIAGONAL
);
2342 m_canvas
->AddShape(control
);
2343 m_controlPoints
.Append(control
);
2345 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, left
, 0,
2346 CONTROL_POINT_HORIZONTAL
);
2347 m_canvas
->AddShape(control
);
2348 m_controlPoints
.Append(control
);
2352 void wxShape::MakeMandatoryControlPoints()
2354 wxNode
*node
= m_children
.First();
2357 wxShape
*child
= (wxShape
*)node
->Data();
2358 child
->MakeMandatoryControlPoints();
2359 node
= node
->Next();
2363 void wxShape::ResetMandatoryControlPoints()
2365 wxNode
*node
= m_children
.First();
2368 wxShape
*child
= (wxShape
*)node
->Data();
2369 child
->ResetMandatoryControlPoints();
2370 node
= node
->Next();
2374 void wxShape::ResetControlPoints()
2376 ResetMandatoryControlPoints();
2378 if (m_controlPoints
.Number() < 1)
2381 double maxX
, maxY
, minX
, minY
;
2383 GetBoundingBoxMax(&maxX
, &maxY
);
2384 GetBoundingBoxMin(&minX
, &minY
);
2386 double widthMin
= (double)(minX
+ CONTROL_POINT_SIZE
+ 2);
2387 double heightMin
= (double)(minY
+ CONTROL_POINT_SIZE
+ 2);
2389 // Offsets from main object
2390 double top
= (double)(- (heightMin
/ 2.0));
2391 double bottom
= (double)(heightMin
/ 2.0 + (maxY
- minY
));
2392 double left
= (double)(- (widthMin
/ 2.0));
2393 double right
= (double)(widthMin
/ 2.0 + (maxX
- minX
));
2395 wxNode
*node
= m_controlPoints
.First();
2396 wxControlPoint
*control
= (wxControlPoint
*)node
->Data();
2397 control
->m_xoffset
= left
; control
->m_yoffset
= top
;
2399 node
= node
->Next(); control
= (wxControlPoint
*)node
->Data();
2400 control
->m_xoffset
= 0; control
->m_yoffset
= top
;
2402 node
= node
->Next(); control
= (wxControlPoint
*)node
->Data();
2403 control
->m_xoffset
= right
; control
->m_yoffset
= top
;
2405 node
= node
->Next(); control
= (wxControlPoint
*)node
->Data();
2406 control
->m_xoffset
= right
; control
->m_yoffset
= 0;
2408 node
= node
->Next(); control
= (wxControlPoint
*)node
->Data();
2409 control
->m_xoffset
= right
; control
->m_yoffset
= bottom
;
2411 node
= node
->Next(); control
= (wxControlPoint
*)node
->Data();
2412 control
->m_xoffset
= 0; control
->m_yoffset
= bottom
;
2414 node
= node
->Next(); control
= (wxControlPoint
*)node
->Data();
2415 control
->m_xoffset
= left
; control
->m_yoffset
= bottom
;
2417 node
= node
->Next(); control
= (wxControlPoint
*)node
->Data();
2418 control
->m_xoffset
= left
; control
->m_yoffset
= 0;
2421 void wxShape::DeleteControlPoints(wxDC
*dc
)
2423 wxNode
*node
= m_controlPoints
.First();
2426 wxControlPoint
*control
= (wxControlPoint
*)node
->Data();
2428 control
->GetEventHandler()->OnErase(*dc
);
2429 m_canvas
->RemoveShape(control
);
2432 node
= m_controlPoints
.First();
2434 // Children of divisions are contained objects,
2436 if (!IsKindOf(CLASSINFO(wxDivisionShape
)))
2438 node
= m_children
.First();
2441 wxShape
*child
= (wxShape
*)node
->Data();
2442 child
->DeleteControlPoints(dc
);
2443 node
= node
->Next();
2448 void wxShape::OnDrawControlPoints(wxDC
& dc
)
2453 dc
.SetBrush(wxBLACK_BRUSH
);
2454 dc
.SetPen(wxBLACK_PEN
);
2456 wxNode
*node
= m_controlPoints
.First();
2459 wxControlPoint
*control
= (wxControlPoint
*)node
->Data();
2461 node
= node
->Next();
2463 // Children of divisions are contained objects,
2465 // This test bypasses the type facility for speed
2466 // (critical when drawing)
2467 if (!IsKindOf(CLASSINFO(wxDivisionShape
)))
2469 node
= m_children
.First();
2472 wxShape
*child
= (wxShape
*)node
->Data();
2473 child
->GetEventHandler()->OnDrawControlPoints(dc
);
2474 node
= node
->Next();
2479 void wxShape::OnEraseControlPoints(wxDC
& dc
)
2481 wxNode
*node
= m_controlPoints
.First();
2484 wxControlPoint
*control
= (wxControlPoint
*)node
->Data();
2486 node
= node
->Next();
2488 if (!IsKindOf(CLASSINFO(wxDivisionShape
)))
2490 node
= m_children
.First();
2493 wxShape
*child
= (wxShape
*)node
->Data();
2494 child
->GetEventHandler()->OnEraseControlPoints(dc
);
2495 node
= node
->Next();
2500 void wxShape::Select(bool select
, wxDC
* dc
)
2502 m_selected
= select
;
2505 MakeControlPoints();
2506 // Children of divisions are contained objects,
2508 if (!IsKindOf(CLASSINFO(wxDivisionShape
)))
2510 wxNode
*node
= m_children
.First();
2513 wxShape
*child
= (wxShape
*)node
->Data();
2514 child
->MakeMandatoryControlPoints();
2515 node
= node
->Next();
2519 GetEventHandler()->OnDrawControlPoints(*dc
);
2523 DeleteControlPoints(dc
);
2524 if (!IsKindOf(CLASSINFO(wxDivisionShape
)))
2526 wxNode
*node
= m_children
.First();
2529 wxShape
*child
= (wxShape
*)node
->Data();
2530 child
->DeleteControlPoints(dc
);
2531 node
= node
->Next();
2537 bool wxShape::Selected() const
2542 bool wxShape::AncestorSelected() const
2544 if (m_selected
) return TRUE
;
2548 return GetParent()->AncestorSelected();
2551 int wxShape::GetNumberOfAttachments()
2553 // Should return the MAXIMUM attachment point id here,
2554 // so higher-level functions can iterate through all attachments,
2555 // even if they're not contiguous.
2556 if (m_attachmentPoints
.Number() == 0)
2561 wxNode
*node
= m_attachmentPoints
.First();
2564 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->Data();
2565 if (point
->m_id
> maxN
)
2567 node
= node
->Next();
2573 bool wxShape::AttachmentIsValid(int attachment
)
2575 if ((attachment
>= 0) && (attachment
< 4))
2578 wxNode
*node
= m_attachmentPoints
.First();
2581 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->Data();
2582 if (point
->m_id
== attachment
)
2584 node
= node
->Next();
2589 bool wxShape::GetAttachmentPosition(int attachment
, double *x
, double *y
,
2590 int nth
, int no_arcs
, wxLineShape
*line
)
2592 if (!m_attachmentMode
)
2594 *x
= m_xpos
; *y
= m_ypos
;
2599 wxNode
*node
= m_attachmentPoints
.First();
2602 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->Data();
2603 if (point
->m_id
== attachment
)
2605 *x
= (double)(m_xpos
+ point
->m_x
);
2606 *y
= (double)(m_ypos
+ point
->m_y
);
2609 node
= node
->Next();
2611 *x
= m_xpos
; *y
= m_ypos
;
2616 void wxShape::GetBoundingBoxMax(double *w
, double *h
)
2619 GetBoundingBoxMin(&ww
, &hh
);
2620 if (m_shadowMode
!= SHADOW_NONE
)
2622 ww
+= m_shadowOffsetX
;
2623 hh
+= m_shadowOffsetY
;
2629 // Returns TRUE if image is a descendant of this composite
2630 bool wxShape::HasDescendant(wxShape
*image
)
2634 wxNode
*node
= m_children
.First();
2637 wxShape
*child
= (wxShape
*)node
->Data();
2638 bool ans
= child
->HasDescendant(image
);
2641 node
= node
->Next();
2646 // Clears points from a list of wxRealPoints, and clears list
2647 void wxShape::ClearPointList(wxList
& list
)
2649 wxNode
* node
= list
.First();
2652 wxRealPoint
* pt
= (wxRealPoint
*) node
->Data();
2655 node
= node
->Next();
2660 // Assuming the attachment lies along a vertical or horizontal line,
2661 // calculate the position on that point.
2662 wxRealPoint
wxShape::CalcSimpleAttachment(const wxRealPoint
& pt1
, const wxRealPoint
& pt2
,
2663 int nth
, int noArcs
, wxLineShape
* line
)
2665 bool isEnd
= (line
&& line
->IsEnd(this));
2667 // Are we horizontal or vertical?
2668 bool isHorizontal
= (oglRoughlyEqual(pt1
.y
, pt2
.y
) == TRUE
);
2674 wxRealPoint firstPoint
, secondPoint
;
2686 if (m_spaceAttachments
)
2688 if (line
&& (line
->GetAlignmentType(isEnd
) == LINE_ALIGNMENT_TO_NEXT_HANDLE
))
2690 // Align line according to the next handle along
2691 wxRealPoint
*point
= line
->GetNextControlPoint(this);
2692 if (point
->x
< firstPoint
.x
)
2694 else if (point
->x
> secondPoint
.x
)
2700 x
= firstPoint
.x
+ (nth
+ 1)*(secondPoint
.x
- firstPoint
.x
)/(noArcs
+ 1);
2702 else x
= (secondPoint
.x
- firstPoint
.x
)/2.0; // Midpoint
2708 wxASSERT( oglRoughlyEqual(pt1
.x
, pt2
.x
) == TRUE
);
2710 wxRealPoint firstPoint
, secondPoint
;
2722 if (m_spaceAttachments
)
2724 if (line
&& (line
->GetAlignmentType(isEnd
) == LINE_ALIGNMENT_TO_NEXT_HANDLE
))
2726 // Align line according to the next handle along
2727 wxRealPoint
*point
= line
->GetNextControlPoint(this);
2728 if (point
->y
< firstPoint
.y
)
2730 else if (point
->y
> secondPoint
.y
)
2736 y
= firstPoint
.y
+ (nth
+ 1)*(secondPoint
.y
- firstPoint
.y
)/(noArcs
+ 1);
2738 else y
= (secondPoint
.y
- firstPoint
.y
)/2.0; // Midpoint
2743 return wxRealPoint(x
, y
);
2746 // Return the zero-based position in m_lines of line.
2747 int wxShape::GetLinePosition(wxLineShape
* line
)
2750 for (i
= 0; i
< m_lines
.Number(); i
++)
2751 if ((wxLineShape
*) (m_lines
.Nth(i
)->Data()) == line
)