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_maintainAspectRatio
= FALSE
;
298 m_highlighted
= FALSE
;
301 // Set up a default region. Much of the above will be put into
302 // the region eventually (the duplication is for compatibility)
303 wxShapeRegion
*region
= new wxShapeRegion
;
304 m_regions
.Append(region
);
305 region
->SetName("0");
306 region
->SetFont(g_oglNormalFont
);
307 region
->SetFormatMode(FORMAT_CENTRE_HORIZ
| FORMAT_CENTRE_VERT
);
308 region
->SetColour("BLACK");
314 m_parent
->GetChildren().DeleteObject(this);
321 m_canvas
->RemoveShape(this);
323 GetEventHandler()->OnDelete();
326 void wxShape::SetHighlight(bool hi
, bool recurse
)
331 wxNode
*node
= m_children
.First();
334 wxShape
*child
= (wxShape
*)node
->Data();
335 child
->SetHighlight(hi
, recurse
);
341 void wxShape::SetSensitivityFilter(int sens
, bool recursive
)
343 if (sens
& OP_DRAG_LEFT
)
348 m_sensitivity
= sens
;
351 wxNode
*node
= m_children
.First();
354 wxShape
*obj
= (wxShape
*)node
->Data();
355 obj
->SetSensitivityFilter(sens
, TRUE
);
361 void wxShape::SetDraggable(bool drag
, bool recursive
)
365 m_sensitivity
|= OP_DRAG_LEFT
;
367 if (m_sensitivity
& OP_DRAG_LEFT
)
368 m_sensitivity
= m_sensitivity
- OP_DRAG_LEFT
;
372 wxNode
*node
= m_children
.First();
375 wxShape
*obj
= (wxShape
*)node
->Data();
376 obj
->SetDraggable(drag
, TRUE
);
382 void wxShape::SetDrawHandles(bool drawH
)
384 m_drawHandles
= drawH
;
385 wxNode
*node
= m_children
.First();
388 wxShape
*obj
= (wxShape
*)node
->Data();
389 obj
->SetDrawHandles(drawH
);
394 void wxShape::SetShadowMode(int mode
, bool redraw
)
396 if (redraw
&& GetCanvas())
398 wxClientDC
dc(GetCanvas());
399 GetCanvas()->PrepareDC(dc
);
412 void wxShape::SetCanvas(wxShapeCanvas
*theCanvas
)
414 m_canvas
= theCanvas
;
415 wxNode
*node
= m_children
.First();
418 wxShape
*child
= (wxShape
*)node
->Data();
419 child
->SetCanvas(theCanvas
);
424 void wxShape::AddToCanvas(wxShapeCanvas
*theCanvas
, wxShape
*addAfter
)
426 theCanvas
->AddShape(this, addAfter
);
427 wxNode
*node
= m_children
.First();
428 wxShape
*lastImage
= this;
431 wxShape
*object
= (wxShape
*)node
->Data();
432 object
->AddToCanvas(theCanvas
, lastImage
);
439 // Insert at front of canvas
440 void wxShape::InsertInCanvas(wxShapeCanvas
*theCanvas
)
442 theCanvas
->InsertShape(this);
443 wxNode
*node
= m_children
.First();
444 wxShape
*lastImage
= this;
447 wxShape
*object
= (wxShape
*)node
->Data();
448 object
->AddToCanvas(theCanvas
, lastImage
);
455 void wxShape::RemoveFromCanvas(wxShapeCanvas
*theCanvas
)
459 theCanvas
->RemoveShape(this);
460 wxNode
*node
= m_children
.First();
463 wxShape
*object
= (wxShape
*)node
->Data();
464 object
->RemoveFromCanvas(theCanvas
);
470 void wxShape::ClearAttachments()
472 wxNode
*node
= m_attachmentPoints
.First();
475 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->Data();
479 m_attachmentPoints
.Clear();
482 void wxShape::ClearText(int regionId
)
486 m_text
.DeleteContents(TRUE
);
488 m_text
.DeleteContents(FALSE
);
490 wxNode
*node
= m_regions
.Nth(regionId
);
493 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
497 void wxShape::ClearRegions()
499 wxNode
*node
= m_regions
.First();
502 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
503 wxNode
*next
= node
->Next();
510 void wxShape::AddRegion(wxShapeRegion
*region
)
512 m_regions
.Append(region
);
515 void wxShape::SetDefaultRegionSize()
517 wxNode
*node
= m_regions
.First();
519 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
521 GetBoundingBoxMin(&w
, &h
);
522 region
->SetSize(w
, h
);
525 bool wxShape::HitTest(double x
, double y
, int *attachment
, double *distance
)
530 double width
= 0.0, height
= 0.0;
531 GetBoundingBoxMin(&width
, &height
);
532 if (fabs(width
) < 4.0) width
= 4.0;
533 if (fabs(height
) < 4.0) height
= 4.0;
535 width
+= (double)4.0; height
+= (double)4.0; // Allowance for inaccurate mousing
537 double left
= (double)(m_xpos
- (width
/2.0));
538 double top
= (double)(m_ypos
- (height
/2.0));
539 double right
= (double)(m_xpos
+ (width
/2.0));
540 double bottom
= (double)(m_ypos
+ (height
/2.0));
542 int nearest_attachment
= 0;
545 // If within the bounding box, check the attachment points
546 // within the object.
548 if (x
>= left
&& x
<= right
&& y
>= top
&& y
<= bottom
)
550 int n
= GetNumberOfAttachments();
551 double nearest
= 999999.0;
553 for (int i
= 0; i
< n
; i
++)
556 if (GetAttachmentPosition(i
, &xp
, &yp
))
558 double l
= (double)sqrt(((xp
- x
) * (xp
- x
)) +
559 ((yp
- y
) * (yp
- y
)));
564 nearest_attachment
= i
;
568 *attachment
= nearest_attachment
;
575 // Format a text string according to the region size, adding
576 // strings with positions to region text list
578 static bool GraphicsInSizeToContents
= FALSE
; // Infinite recursion elimination
579 void wxShape::FormatText(wxDC
& dc
, const wxString
& s
, int i
)
584 if (m_regions
.Number() < 1)
586 wxNode
*node
= m_regions
.Nth(i
);
590 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
592 dc
.SetFont(region
->GetFont());
594 region
->GetSize(&w
, &h
);
596 wxStringList
*stringList
= oglFormatText(dc
, s
, (w
-5), (h
-5), region
->GetFormatMode());
597 node
= stringList
->First();
600 char *s
= (char *)node
->Data();
601 wxShapeTextLine
*line
= new wxShapeTextLine(0.0, 0.0, s
);
602 region
->GetFormattedText().Append((wxObject
*)line
);
608 // Don't try to resize an object with more than one image (this case should be dealt
609 // with by overriden handlers)
610 if ((region
->GetFormatMode() & FORMAT_SIZE_TO_CONTENTS
) &&
611 (region
->GetFormattedText().Number() > 0) &&
612 (m_regions
.Number() == 1) && !GraphicsInSizeToContents
)
614 oglGetCentredTextExtent(dc
, &(region
->GetFormattedText()), m_xpos
, m_ypos
, w
, h
, &actualW
, &actualH
);
615 if ((actualW
+m_textMarginX
!= w
) || (actualH
+m_textMarginY
!= h
))
617 // If we are a descendant of a composite, must make sure the composite gets
619 wxShape
*topAncestor
= GetTopAncestor();
621 if (topAncestor
!= this)
623 // Make sure we don't recurse infinitely
624 GraphicsInSizeToContents
= TRUE
;
626 wxCompositeShape
*composite
= (wxCompositeShape
*)topAncestor
;
627 composite
->Erase(dc
);
628 SetSize(actualW
+m_textMarginX
, actualH
+m_textMarginY
);
629 Move(dc
, m_xpos
, m_ypos
);
630 composite
->CalculateSize();
631 if (composite
->Selected())
633 composite
->DeleteControlPoints(& dc
);
634 composite
->MakeControlPoints();
635 composite
->MakeMandatoryControlPoints();
637 // Where infinite recursion might happen if we didn't stop it
640 GraphicsInSizeToContents
= FALSE
;
645 SetSize(actualW
+m_textMarginX
, actualH
+m_textMarginY
);
646 Move(dc
, m_xpos
, m_ypos
);
648 SetSize(actualW
+m_textMarginX
, actualH
+m_textMarginY
);
649 Move(dc
, m_xpos
, m_ypos
);
653 oglCentreText(dc
, &(region
->GetFormattedText()), m_xpos
, m_ypos
, actualW
, actualH
, region
->GetFormatMode());
657 void wxShape::Recentre(wxDC
& dc
)
660 GetBoundingBoxMin(&w
, &h
);
662 int noRegions
= m_regions
.Number();
663 for (int i
= 0; i
< noRegions
; i
++)
665 wxNode
*node
= m_regions
.Nth(i
);
668 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
669 oglCentreText(dc
, &(region
->GetFormattedText()), m_xpos
, m_ypos
, w
, h
, region
->GetFormatMode());
674 bool wxShape::GetPerimeterPoint(double x1
, double y1
,
675 double x2
, double y2
,
676 double *x3
, double *y3
)
681 void wxShape::SetPen(wxPen
*the_pen
)
686 void wxShape::SetBrush(wxBrush
*the_brush
)
691 // Get the top-most (non-division) ancestor, or self
692 wxShape
*wxShape::GetTopAncestor()
697 if (GetParent()->IsKindOf(CLASSINFO(wxDivisionShape
)))
699 else return GetParent()->GetTopAncestor();
706 void wxShape::SetFont(wxFont
*the_font
, int regionId
)
709 wxNode
*node
= m_regions
.Nth(regionId
);
712 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
713 region
->SetFont(the_font
);
716 wxFont
*wxShape::GetFont(int n
) const
718 wxNode
*node
= m_regions
.Nth(n
);
721 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
722 return region
->GetFont();
725 void wxShape::SetFormatMode(int mode
, int regionId
)
727 wxNode
*node
= m_regions
.Nth(regionId
);
730 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
731 region
->SetFormatMode(mode
);
734 int wxShape::GetFormatMode(int regionId
) const
736 wxNode
*node
= m_regions
.Nth(regionId
);
739 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
740 return region
->GetFormatMode();
743 void wxShape::SetTextColour(const wxString
& the_colour
, int regionId
)
745 wxColour
*wxcolour
= wxTheColourDatabase
->FindColour(the_colour
);
746 m_textColour
= wxcolour
;
747 m_textColourName
= the_colour
;
749 wxNode
*node
= m_regions
.Nth(regionId
);
752 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
753 region
->SetColour(the_colour
);
756 wxString
wxShape::GetTextColour(int regionId
) const
758 wxNode
*node
= m_regions
.Nth(regionId
);
761 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
762 return region
->GetColour();
765 void wxShape::SetRegionName(const wxString
& name
, int regionId
)
767 wxNode
*node
= m_regions
.Nth(regionId
);
770 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
771 region
->SetName(name
);
774 wxString
wxShape::GetRegionName(int regionId
)
776 wxNode
*node
= m_regions
.Nth(regionId
);
779 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
780 return region
->GetName();
783 int wxShape::GetRegionId(const wxString
& name
)
785 wxNode
*node
= m_regions
.First();
789 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
790 if (region
->GetName() == name
)
798 // Name all m_regions in all subimages recursively.
799 void wxShape::NameRegions(const wxString
& parentName
)
801 int n
= GetNumberOfTextRegions();
803 for (int i
= 0; i
< n
; i
++)
805 if (parentName
.Length() > 0)
806 sprintf(buf
, "%s.%d", (const char*) parentName
, i
);
808 sprintf(buf
, "%d", i
);
809 SetRegionName(buf
, i
);
811 wxNode
*node
= m_children
.First();
815 wxShape
*child
= (wxShape
*)node
->Data();
816 if (parentName
.Length() > 0)
817 sprintf(buf
, "%s.%d", (const char*) parentName
, j
);
819 sprintf(buf
, "%d", j
);
820 child
->NameRegions(buf
);
826 // Get a region by name, possibly looking recursively into composites.
827 wxShape
*wxShape::FindRegion(const wxString
& name
, int *regionId
)
829 int id
= GetRegionId(name
);
836 wxNode
*node
= m_children
.First();
839 wxShape
*child
= (wxShape
*)node
->Data();
840 wxShape
*actualImage
= child
->FindRegion(name
, regionId
);
848 // Finds all region names for this image (composite or simple).
849 // Supply empty string list.
850 void wxShape::FindRegionNames(wxStringList
& list
)
852 int n
= GetNumberOfTextRegions();
853 for (int i
= 0; i
< n
; i
++)
855 wxString
name(GetRegionName(i
));
856 list
.Add((const char*) name
);
859 wxNode
*node
= m_children
.First();
862 wxShape
*child
= (wxShape
*)node
->Data();
863 child
->FindRegionNames(list
);
868 void wxShape::AssignNewIds()
872 wxNode
*node
= m_children
.First();
875 wxShape
*child
= (wxShape
*)node
->Data();
876 child
->AssignNewIds();
881 void wxShape::OnDraw(wxDC
& dc
)
885 void wxShape::OnMoveLinks(wxDC
& dc
)
887 // Want to set the ends of all attached links
888 // to point to/from this object
890 wxNode
*current
= m_lines
.First();
893 wxLineShape
*line
= (wxLineShape
*)current
->Data();
894 line
->GetEventHandler()->OnMoveLink(dc
);
895 current
= current
->Next();
900 void wxShape::OnDrawContents(wxDC
& dc
)
902 double bound_x
, bound_y
;
903 GetBoundingBoxMin(&bound_x
, &bound_y
);
904 if (m_regions
.Number() < 1) return;
906 if (m_pen
) dc
.SetPen(m_pen
);
908 wxShapeRegion
*region
= (wxShapeRegion
*)m_regions
.First()->Data();
909 if (region
->GetFont()) dc
.SetFont(region
->GetFont());
911 dc
.SetTextForeground(* (region
->GetActualColourObject()));
912 dc
.SetBackgroundMode(wxTRANSPARENT
);
915 oglCentreText(dc
, &(region
->GetFormattedText()), m_xpos
, m_ypos
, bound_x
, bound_y
, region
->GetFormatMode());
918 if (!GetDisableLabel())
920 oglDrawFormattedText(dc
, &(region
->GetFormattedText()), m_xpos
, m_ypos
, bound_x
, bound_y
, region
->GetFormatMode());
924 void wxShape::DrawContents(wxDC
& dc
)
926 GetEventHandler()->OnDrawContents(dc
);
929 void wxShape::OnSize(double x
, double y
)
933 bool wxShape::OnMovePre(wxDC
& dc
, double x
, double y
, double old_x
, double old_y
, bool display
)
938 void wxShape::OnMovePost(wxDC
& dc
, double x
, double y
, double old_x
, double old_y
, bool display
)
942 void wxShape::OnErase(wxDC
& dc
)
948 wxNode
*current
= m_lines
.First();
951 wxLineShape
*line
= (wxLineShape
*)current
->Data();
952 line
->GetEventHandler()->OnErase(dc
);
953 current
= current
->Next();
955 GetEventHandler()->OnEraseContents(dc
);
958 void wxShape::OnEraseContents(wxDC
& dc
)
963 double maxX
, maxY
, minX
, minY
;
966 GetBoundingBoxMin(&minX
, &minY
);
967 GetBoundingBoxMax(&maxX
, &maxY
);
968 double topLeftX
= (double)(xp
- (maxX
/ 2.0) - 2.0);
969 double topLeftY
= (double)(yp
- (maxY
/ 2.0) - 2.0);
973 penWidth
= m_pen
->GetWidth();
975 dc
.SetPen(g_oglWhiteBackgroundPen
);
976 dc
.SetBrush(g_oglWhiteBackgroundBrush
);
977 dc
.DrawRectangle(WXROUND(topLeftX
- penWidth
), WXROUND(topLeftY
- penWidth
),
978 WXROUND(maxX
+ penWidth
*2.0 + 4.0), WXROUND(maxY
+ penWidth
*2.0 + 4.0));
981 void wxShape::EraseLinks(wxDC
& dc
, int attachment
, bool recurse
)
986 wxNode
*current
= m_lines
.First();
989 wxLineShape
*line
= (wxLineShape
*)current
->Data();
990 if (attachment
== -1 || ((line
->GetTo() == this && line
->GetAttachmentTo() == attachment
) ||
991 (line
->GetFrom() == this && line
->GetAttachmentFrom() == attachment
)))
992 line
->GetEventHandler()->OnErase(dc
);
993 current
= current
->Next();
997 wxNode
*node
= m_children
.First();
1000 wxShape
*child
= (wxShape
*)node
->Data();
1001 child
->EraseLinks(dc
, attachment
, recurse
);
1002 node
= node
->Next();
1007 void wxShape::DrawLinks(wxDC
& dc
, int attachment
, bool recurse
)
1012 wxNode
*current
= m_lines
.First();
1015 wxLineShape
*line
= (wxLineShape
*)current
->Data();
1016 if (attachment
== -1 ||
1017 (line
->GetTo() == this && line
->GetAttachmentTo() == attachment
) ||
1018 (line
->GetFrom() == this && line
->GetAttachmentFrom() == attachment
))
1020 current
= current
->Next();
1024 wxNode
*node
= m_children
.First();
1027 wxShape
*child
= (wxShape
*)node
->Data();
1028 child
->DrawLinks(dc
, attachment
, recurse
);
1029 node
= node
->Next();
1034 // Returns TRUE if pt1 <= pt2 in the sense that one point comes before another on an
1035 // edge of the shape.
1036 // attachmentPoint is the attachment point (= side) in question.
1038 // This is the default, rectangular implementation.
1039 bool wxShape::AttachmentSortTest(int attachmentPoint
, const wxRealPoint
& pt1
, const wxRealPoint
& pt2
)
1041 switch (attachmentPoint
)
1046 return (pt1
.x
<= pt2
.x
) ;
1052 return (pt1
.y
<= pt2
.y
) ;
1060 bool wxShape::MoveLineToNewAttachment(wxDC
& dc
, wxLineShape
*to_move
,
1063 if (!GetAttachmentMode())
1066 int newAttachment
, oldAttachment
;
1069 // Is (x, y) on this object? If so, find the new attachment point
1070 // the user has moved the point to
1071 bool hit
= HitTest(x
, y
, &newAttachment
, &distance
);
1077 if (to_move
->GetTo() == this)
1078 oldAttachment
= to_move
->GetAttachmentTo();
1080 oldAttachment
= to_move
->GetAttachmentFrom();
1082 // The links in a new ordering.
1085 // First, add all links to the new list.
1086 wxNode
*node
= m_lines
.First();
1089 newOrdering
.Append(node
->Data());
1090 node
= node
->Next();
1093 // Delete the line object from the list of links; we're going to move
1094 // it to another position in the list
1095 newOrdering
.DeleteObject(to_move
);
1097 double old_x
= (double) -99999.9;
1098 double old_y
= (double) -99999.9;
1100 node
= newOrdering
.First();
1103 while (!found
&& node
)
1105 wxLineShape
*line
= (wxLineShape
*)node
->Data();
1106 if ((line
->GetTo() == this && oldAttachment
== line
->GetAttachmentTo()) ||
1107 (line
->GetFrom() == this && oldAttachment
== line
->GetAttachmentFrom()))
1109 double startX
, startY
, endX
, endY
;
1111 line
->GetEnds(&startX
, &startY
, &endX
, &endY
);
1112 if (line
->GetTo() == this)
1122 wxRealPoint
thisPoint(xp
, yp
);
1123 wxRealPoint
lastPoint(old_x
, old_y
);
1124 wxRealPoint
newPoint(x
, y
);
1126 if (AttachmentSortTest(newAttachment
, newPoint
, thisPoint
) && AttachmentSortTest(newAttachment
, lastPoint
, newPoint
))
1129 newOrdering
.Insert(node
, to_move
);
1135 node
= node
->Next();
1139 newOrdering
.Append(to_move
);
1141 GetEventHandler()->OnChangeAttachment(newAttachment
, to_move
, newOrdering
);
1146 void wxShape::OnChangeAttachment(int attachment
, wxLineShape
* line
, wxList
& ordering
)
1148 if (line
->GetTo() == this)
1149 line
->SetAttachmentTo(attachment
);
1151 line
->SetAttachmentFrom(attachment
);
1153 ApplyAttachmentOrdering(ordering
);
1155 wxClientDC
dc(GetCanvas());
1156 GetCanvas()->PrepareDC(dc
);
1160 if (!GetCanvas()->GetQuickEditMode()) GetCanvas()->Redraw(dc
);
1163 // Reorders the lines according to the given list.
1164 void wxShape::ApplyAttachmentOrdering(wxList
& linesToSort
)
1166 // This is a temporary store of all the lines.
1169 wxNode
*node
= m_lines
.First();
1172 wxLineShape
*line
= (wxLineShape
*)node
->Data();
1173 linesStore
.Append(line
);
1174 node
= node
->Next();;
1179 node
= linesToSort
.First();
1182 wxLineShape
*line
= (wxLineShape
*)node
->Data();
1183 if (linesStore
.Member(line
))
1186 linesStore
.DeleteObject(line
);
1187 m_lines
.Append(line
);
1189 node
= node
->Next();
1192 // Now add any lines that haven't been listed in linesToSort.
1193 node
= linesStore
.First();
1196 wxLineShape
*line
= (wxLineShape
*)node
->Data();
1197 m_lines
.Append(line
);
1198 node
= node
->Next();
1202 // Reorders the lines coming into the node image at this attachment
1203 // position, in the order in which they appear in linesToSort.
1204 // Any remaining lines not in the list will be added to the end.
1205 void wxShape::SortLines(int attachment
, wxList
& linesToSort
)
1207 // This is a temporary store of all the lines at this attachment
1208 // point. We'll tick them off as we've processed them.
1209 wxList linesAtThisAttachment
;
1211 wxNode
*node
= m_lines
.First();
1214 wxLineShape
*line
= (wxLineShape
*)node
->Data();
1215 wxNode
*next
= node
->Next();
1216 if ((line
->GetTo() == this && line
->GetAttachmentTo() == attachment
) ||
1217 (line
->GetFrom() == this && line
->GetAttachmentFrom() == attachment
))
1219 linesAtThisAttachment
.Append(line
);
1223 else node
= node
->Next();
1226 node
= linesToSort
.First();
1229 wxLineShape
*line
= (wxLineShape
*)node
->Data();
1230 if (linesAtThisAttachment
.Member(line
))
1233 linesAtThisAttachment
.DeleteObject(line
);
1234 m_lines
.Append(line
);
1236 node
= node
->Next();
1239 // Now add any lines that haven't been listed in linesToSort.
1240 node
= linesAtThisAttachment
.First();
1243 wxLineShape
*line
= (wxLineShape
*)node
->Data();
1244 m_lines
.Append(line
);
1245 node
= node
->Next();
1249 void wxShape::OnHighlight(wxDC
& dc
)
1253 void wxShape::OnLeftClick(double x
, double y
, int keys
, int attachment
)
1255 if ((m_sensitivity
& OP_CLICK_LEFT
) != OP_CLICK_LEFT
)
1261 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1262 m_parent
->GetEventHandler()->OnLeftClick(x
, y
, keys
, attachment
);
1268 void wxShape::OnRightClick(double x
, double y
, int keys
, int attachment
)
1270 if ((m_sensitivity
& OP_CLICK_RIGHT
) != OP_CLICK_RIGHT
)
1276 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1277 m_parent
->GetEventHandler()->OnRightClick(x
, y
, keys
, attachment
);
1283 double DragOffsetX
= 0.0;
1284 double DragOffsetY
= 0.0;
1286 void wxShape::OnDragLeft(bool draw
, double x
, double y
, int keys
, int attachment
)
1288 if ((m_sensitivity
& OP_DRAG_LEFT
) != OP_DRAG_LEFT
)
1294 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1295 m_parent
->GetEventHandler()->OnDragLeft(draw
, x
, y
, keys
, attachment
);
1300 wxClientDC
dc(GetCanvas());
1301 GetCanvas()->PrepareDC(dc
);
1303 dc
.SetLogicalFunction(wxXOR
);
1305 wxPen
dottedPen(wxColour(0, 0, 0), 1, wxDOT
);
1306 dc
.SetPen(dottedPen
);
1307 dc
.SetBrush(* wxTRANSPARENT_BRUSH
);
1310 xx
= x
+ DragOffsetX
;
1311 yy
= y
+ DragOffsetY
;
1313 m_canvas
->Snap(&xx
, &yy
);
1314 // m_xpos = xx; m_ypos = yy;
1316 GetBoundingBoxMax(&w
, &h
);
1317 GetEventHandler()->OnDrawOutline(dc
, xx
, yy
, w
, h
);
1320 void wxShape::OnBeginDragLeft(double x
, double y
, int keys
, int attachment
)
1322 if ((m_sensitivity
& OP_DRAG_LEFT
) != OP_DRAG_LEFT
)
1328 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1329 m_parent
->GetEventHandler()->OnBeginDragLeft(x
, y
, keys
, attachment
);
1334 DragOffsetX
= m_xpos
- x
;
1335 DragOffsetY
= m_ypos
- y
;
1337 wxClientDC
dc(GetCanvas());
1338 GetCanvas()->PrepareDC(dc
);
1340 // New policy: don't erase shape until end of drag.
1344 xx
= x
+ DragOffsetX
;
1345 yy
= y
+ DragOffsetY
;
1346 m_canvas
->Snap(&xx
, &yy
);
1347 // m_xpos = xx; m_ypos = yy;
1348 dc
.SetLogicalFunction(wxXOR
);
1350 wxPen
dottedPen(wxColour(0, 0, 0), 1, wxDOT
);
1351 dc
.SetPen(dottedPen
);
1352 dc
.SetBrush((* wxTRANSPARENT_BRUSH
));
1355 GetBoundingBoxMax(&w
, &h
);
1356 GetEventHandler()->OnDrawOutline(dc
, xx
, yy
, w
, h
);
1357 m_canvas
->CaptureMouse();
1360 void wxShape::OnEndDragLeft(double x
, double y
, int keys
, int attachment
)
1362 m_canvas
->ReleaseMouse();
1363 if ((m_sensitivity
& OP_DRAG_LEFT
) != OP_DRAG_LEFT
)
1369 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1370 m_parent
->GetEventHandler()->OnEndDragLeft(x
, y
, keys
, attachment
);
1375 wxClientDC
dc(GetCanvas());
1376 GetCanvas()->PrepareDC(dc
);
1378 dc
.SetLogicalFunction(wxCOPY
);
1380 double xx
= x
+ DragOffsetX
;
1381 double yy
= y
+ DragOffsetY
;
1382 m_canvas
->Snap(&xx
, &yy
);
1383 // canvas->Snap(&m_xpos, &m_ypos);
1385 // New policy: erase shape at end of drag.
1389 if (m_canvas
&& !m_canvas
->GetQuickEditMode()) m_canvas
->Redraw(dc
);
1392 void wxShape::OnDragRight(bool draw
, double x
, double y
, int keys
, int attachment
)
1394 if ((m_sensitivity
& OP_DRAG_RIGHT
) != OP_DRAG_RIGHT
)
1400 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1401 m_parent
->GetEventHandler()->OnDragRight(draw
, x
, y
, keys
, attachment
);
1407 void wxShape::OnBeginDragRight(double x
, double y
, int keys
, int attachment
)
1409 if ((m_sensitivity
& OP_DRAG_RIGHT
) != OP_DRAG_RIGHT
)
1415 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1416 m_parent
->GetEventHandler()->OnBeginDragRight(x
, y
, keys
, attachment
);
1422 void wxShape::OnEndDragRight(double x
, double y
, int keys
, int attachment
)
1424 if ((m_sensitivity
& OP_DRAG_RIGHT
) != OP_DRAG_RIGHT
)
1430 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1431 m_parent
->GetEventHandler()->OnEndDragRight(x
, y
, keys
, attachment
);
1437 void wxShape::OnDrawOutline(wxDC
& dc
, double x
, double y
, double w
, double h
)
1439 double top_left_x
= (double)(x
- w
/2.0);
1440 double top_left_y
= (double)(y
- h
/2.0);
1441 double top_right_x
= (double)(top_left_x
+ w
);
1442 double top_right_y
= (double)top_left_y
;
1443 double bottom_left_x
= (double)top_left_x
;
1444 double bottom_left_y
= (double)(top_left_y
+ h
);
1445 double bottom_right_x
= (double)top_right_x
;
1446 double bottom_right_y
= (double)bottom_left_y
;
1449 points
[0].x
= WXROUND(top_left_x
); points
[0].y
= WXROUND(top_left_y
);
1450 points
[1].x
= WXROUND(top_right_x
); points
[1].y
= WXROUND(top_right_y
);
1451 points
[2].x
= WXROUND(bottom_right_x
); points
[2].y
= WXROUND(bottom_right_y
);
1452 points
[3].x
= WXROUND(bottom_left_x
); points
[3].y
= WXROUND(bottom_left_y
);
1453 points
[4].x
= WXROUND(top_left_x
); points
[4].y
= WXROUND(top_left_y
);
1455 dc
.DrawLines(5, points
);
1458 void wxShape::Attach(wxShapeCanvas
*can
)
1463 void wxShape::Detach()
1468 void wxShape::Move(wxDC
& dc
, double x
, double y
, bool display
)
1470 double old_x
= m_xpos
;
1471 double old_y
= m_ypos
;
1473 if (!GetEventHandler()->OnMovePre(dc
, x
, y
, old_x
, old_y
, display
))
1480 m_xpos
= x
; m_ypos
= y
;
1482 ResetControlPoints();
1489 GetEventHandler()->OnMovePost(dc
, x
, y
, old_x
, old_y
, display
);
1492 void wxShape::MoveLinks(wxDC
& dc
)
1494 GetEventHandler()->OnMoveLinks(dc
);
1498 void wxShape::Draw(wxDC
& dc
)
1502 GetEventHandler()->OnDraw(dc
);
1503 GetEventHandler()->OnDrawContents(dc
);
1504 GetEventHandler()->OnDrawControlPoints(dc
);
1508 void wxShape::Flash()
1512 wxClientDC
dc(GetCanvas());
1513 GetCanvas()->PrepareDC(dc
);
1515 dc
.SetLogicalFunction(wxXOR
);
1517 dc
.SetLogicalFunction(wxCOPY
);
1522 void wxShape::Show(bool show
)
1525 wxNode
*node
= m_children
.First();
1528 wxShape
*image
= (wxShape
*)node
->Data();
1530 node
= node
->Next();
1534 void wxShape::Erase(wxDC
& dc
)
1536 GetEventHandler()->OnErase(dc
);
1537 GetEventHandler()->OnEraseControlPoints(dc
);
1540 void wxShape::EraseContents(wxDC
& dc
)
1542 GetEventHandler()->OnEraseContents(dc
);
1545 void wxShape::AddText(const wxString
& string
)
1547 wxNode
*node
= m_regions
.First();
1550 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
1551 region
->ClearText();
1552 wxShapeTextLine
*new_line
=
1553 new wxShapeTextLine(0.0, 0.0, string
);
1554 region
->GetFormattedText().Append(new_line
);
1556 m_formatted
= FALSE
;
1559 void wxShape::SetSize(double x
, double y
, bool recursive
)
1561 SetAttachmentSize(x
, y
);
1562 SetDefaultRegionSize();
1565 void wxShape::SetAttachmentSize(double w
, double h
)
1569 double width
, height
;
1570 GetBoundingBoxMin(&width
, &height
);
1573 else scaleX
= w
/width
;
1576 else scaleY
= h
/height
;
1578 wxNode
*node
= m_attachmentPoints
.First();
1581 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->Data();
1582 point
->m_x
= (double)(point
->m_x
* scaleX
);
1583 point
->m_y
= (double)(point
->m_y
* scaleY
);
1584 node
= node
->Next();
1588 // Add line FROM this object
1589 void wxShape::AddLine(wxLineShape
*line
, wxShape
*other
,
1590 int attachFrom
, int attachTo
,
1591 // The line ordering
1592 int positionFrom
, int positionTo
)
1594 if (positionFrom
== -1)
1596 if (!m_lines
.Member(line
))
1597 m_lines
.Append(line
);
1601 // Don't preserve old ordering if we have new ordering instructions
1602 m_lines
.DeleteObject(line
);
1603 if (positionFrom
< m_lines
.Number())
1605 wxNode
* node
= m_lines
.Nth(positionFrom
);
1606 m_lines
.Insert(node
, line
);
1609 m_lines
.Append(line
);
1612 if (positionTo
== -1)
1614 if (!other
->m_lines
.Member(line
))
1615 other
->m_lines
.Append(line
);
1619 // Don't preserve old ordering if we have new ordering instructions
1620 other
->m_lines
.DeleteObject(line
);
1621 if (positionTo
< other
->m_lines
.Number())
1623 wxNode
* node
= other
->m_lines
.Nth(positionTo
);
1624 other
->m_lines
.Insert(node
, line
);
1627 other
->m_lines
.Append(line
);
1630 // Wrong: doesn't preserve ordering of shape already linked
1631 m_lines
.DeleteObject(line
);
1632 other
->m_lines
.DeleteObject(line
);
1634 if (positionFrom
== -1)
1635 m_lines
.Append(line
);
1638 if (positionFrom
< m_lines
.Number())
1640 wxNode
* node
= m_lines
.Nth(positionFrom
);
1641 m_lines
.Insert(node
, line
);
1644 m_lines
.Append(line
);
1647 if (positionTo
== -1)
1648 other
->m_lines
.Append(line
);
1651 if (positionTo
< other
->m_lines
.Number())
1653 wxNode
* node
= other
->m_lines
.Nth(positionTo
);
1654 other
->m_lines
.Insert(node
, line
);
1657 other
->m_lines
.Append(line
);
1661 line
->SetFrom(this);
1663 line
->SetAttachments(attachFrom
, attachTo
);
1666 void wxShape::RemoveLine(wxLineShape
*line
)
1668 if (line
->GetFrom() == this)
1669 line
->GetTo()->m_lines
.DeleteObject(line
);
1671 line
->GetFrom()->m_lines
.DeleteObject(line
);
1673 m_lines
.DeleteObject(line
);
1677 void wxShape::WriteAttributes(wxExpr
*clause
)
1679 clause
->AddAttributeValueString("type", GetClassInfo()->GetClassName());
1680 clause
->AddAttributeValue("id", m_id
);
1684 int penWidth
= m_pen
->GetWidth();
1685 int penStyle
= m_pen
->GetStyle();
1687 clause
->AddAttributeValue("pen_width", (long)penWidth
);
1688 if (penStyle
!= wxSOLID
)
1689 clause
->AddAttributeValue("pen_style", (long)penStyle
);
1691 wxString penColour
= wxTheColourDatabase
->FindName(m_pen
->GetColour());
1692 if (penColour
== "")
1694 wxString
hex(oglColourToHex(m_pen
->GetColour()));
1695 hex
= wxString("#") + hex
;
1696 clause
->AddAttributeValueString("pen_colour", hex
);
1698 else if (penColour
!= "BLACK")
1699 clause
->AddAttributeValueString("pen_colour", penColour
);
1704 wxString brushColour
= wxTheColourDatabase
->FindName(m_brush
->GetColour());
1706 if (brushColour
== "")
1708 wxString
hex(oglColourToHex(m_brush
->GetColour()));
1709 hex
= wxString("#") + hex
;
1710 clause
->AddAttributeValueString("brush_colour", hex
);
1712 else if (brushColour
!= "WHITE")
1713 clause
->AddAttributeValueString("brush_colour", brushColour
);
1715 if (m_brush
->GetStyle() != wxSOLID
)
1716 clause
->AddAttributeValue("brush_style", (long)m_brush
->GetStyle());
1721 int n_lines
= m_lines
.Number();
1724 wxExpr
*list
= new wxExpr(wxExprList
);
1725 wxNode
*node
= m_lines
.First();
1728 wxShape
*line
= (wxShape
*)node
->Data();
1729 wxExpr
*id_expr
= new wxExpr(line
->GetId());
1730 list
->Append(id_expr
);
1731 node
= node
->Next();
1733 clause
->AddAttributeValue("arcs", list
);
1736 // Miscellaneous members
1737 if (m_attachmentMode
!= 0)
1738 clause
->AddAttributeValue("use_attachments", (long)m_attachmentMode
);
1739 if (m_sensitivity
!= OP_ALL
)
1740 clause
->AddAttributeValue("sensitivity", (long)m_sensitivity
);
1741 if (!m_spaceAttachments
)
1742 clause
->AddAttributeValue("space_attachments", (long)m_spaceAttachments
);
1744 clause
->AddAttributeValue("fixed_width", (long)m_fixedWidth
);
1746 clause
->AddAttributeValue("fixed_height", (long)m_fixedHeight
);
1747 if (m_shadowMode
!= SHADOW_NONE
)
1748 clause
->AddAttributeValue("shadow_mode", (long)m_shadowMode
);
1749 if (m_centreResize
!= TRUE
)
1750 clause
->AddAttributeValue("centre_resize", (long)0);
1751 clause
->AddAttributeValue("maintain_aspect_ratio", (long) m_maintainAspectRatio
);
1752 if (m_highlighted
!= FALSE
)
1753 clause
->AddAttributeValue("hilite", (long)m_highlighted
);
1755 if (m_parent
) // For composite objects
1756 clause
->AddAttributeValue("parent", (long)m_parent
->GetId());
1758 if (m_rotation
!= 0.0)
1759 clause
->AddAttributeValue("rotation", m_rotation
);
1761 // Write user-defined attachment points, if any
1762 if (m_attachmentPoints
.Number() > 0)
1764 wxExpr
*attachmentList
= new wxExpr(wxExprList
);
1765 wxNode
*node
= m_attachmentPoints
.First();
1768 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->Data();
1769 wxExpr
*pointExpr
= new wxExpr(wxExprList
);
1770 pointExpr
->Append(new wxExpr((long)point
->m_id
));
1771 pointExpr
->Append(new wxExpr(point
->m_x
));
1772 pointExpr
->Append(new wxExpr(point
->m_y
));
1773 attachmentList
->Append(pointExpr
);
1774 node
= node
->Next();
1776 clause
->AddAttributeValue("user_attachments", attachmentList
);
1779 // Write text regions
1780 WriteRegions(clause
);
1783 void wxShape::WriteRegions(wxExpr
*clause
)
1785 // Output regions as region1 = (...), region2 = (...), etc
1786 // and formatted text as text1 = (...), text2 = (...) etc.
1788 char regionNameBuf
[20];
1789 char textNameBuf
[20];
1790 wxNode
*node
= m_regions
.First();
1793 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
1794 sprintf(regionNameBuf
, "region%d", regionNo
);
1795 sprintf(textNameBuf
, "text%d", regionNo
);
1797 // Original text and region attributes:
1798 // region1 = (regionName regionText x y width height minWidth minHeight proportionX proportionY
1799 // formatMode fontSize fontFamily fontStyle fontWeight textColour)
1800 wxExpr
*regionExpr
= new wxExpr(wxExprList
);
1801 regionExpr
->Append(new wxExpr(wxExprString
, (region
->m_regionName
? region
->m_regionName
: "")));
1802 regionExpr
->Append(new wxExpr(wxExprString
, (region
->m_regionText
? region
->m_regionText
: "")));
1804 regionExpr
->Append(new wxExpr(region
->m_x
));
1805 regionExpr
->Append(new wxExpr(region
->m_y
));
1806 regionExpr
->Append(new wxExpr(region
->GetWidth()));
1807 regionExpr
->Append(new wxExpr(region
->GetHeight()));
1809 regionExpr
->Append(new wxExpr(region
->m_minWidth
));
1810 regionExpr
->Append(new wxExpr(region
->m_minHeight
));
1811 regionExpr
->Append(new wxExpr(region
->m_regionProportionX
));
1812 regionExpr
->Append(new wxExpr(region
->m_regionProportionY
));
1814 regionExpr
->Append(new wxExpr((long)region
->m_formatMode
));
1816 regionExpr
->Append(new wxExpr((long)(region
->m_font
? region
->m_font
->GetPointSize() : 10)));
1817 regionExpr
->Append(new wxExpr((long)(region
->m_font
? region
->m_font
->GetFamily() : wxDEFAULT
)));
1818 regionExpr
->Append(new wxExpr((long)(region
->m_font
? region
->m_font
->GetStyle() : wxDEFAULT
)));
1819 regionExpr
->Append(new wxExpr((long)(region
->m_font
? region
->m_font
->GetWeight() : wxNORMAL
)));
1820 regionExpr
->Append(new wxExpr(wxExprString
, region
->m_textColour
? region
->m_textColour
: "BLACK"));
1822 // New members for pen colour/style
1823 regionExpr
->Append(new wxExpr(wxExprString
, region
->m_penColour
? region
->m_penColour
: "BLACK"));
1824 regionExpr
->Append(new wxExpr((long)region
->m_penStyle
));
1827 // text1 = ((x y string) (x y string) ...)
1828 wxExpr
*textExpr
= new wxExpr(wxExprList
);
1830 wxNode
*textNode
= region
->m_formattedText
.First();
1833 wxShapeTextLine
*line
= (wxShapeTextLine
*)textNode
->Data();
1834 wxExpr
*list2
= new wxExpr(wxExprList
);
1835 list2
->Append(new wxExpr(line
->GetX()));
1836 list2
->Append(new wxExpr(line
->GetY()));
1837 list2
->Append(new wxExpr(wxExprString
, line
->GetText()));
1838 textExpr
->Append(list2
);
1839 textNode
= textNode
->Next();
1842 // Now add both attributes to the clause
1843 clause
->AddAttributeValue(regionNameBuf
, regionExpr
);
1844 clause
->AddAttributeValue(textNameBuf
, textExpr
);
1846 node
= node
->Next();
1851 void wxShape::ReadAttributes(wxExpr
*clause
)
1853 clause
->GetAttributeValue("id", m_id
);
1856 clause
->GetAttributeValue("x", m_xpos
);
1857 clause
->GetAttributeValue("y", m_ypos
);
1859 // Input text strings (FOR COMPATIBILITY WITH OLD FILES ONLY. SEE REGION CODE BELOW.)
1861 wxExpr
*strings
= clause
->AttributeValue("text");
1862 if (strings
&& strings
->Type() == wxExprList
)
1864 m_formatted
= TRUE
; // Assume text is formatted unless we prove otherwise
1865 wxExpr
*node
= strings
->value
.first
;
1868 wxExpr
*string_expr
= node
;
1871 wxString
the_string("");
1873 // string_expr can either be a string, or a list of
1874 // 3 elements: x, y, and string.
1875 if (string_expr
->Type() == wxExprString
)
1877 the_string
= string_expr
->StringValue();
1878 m_formatted
= FALSE
;
1880 else if (string_expr
->Type() == wxExprList
)
1882 wxExpr
*first
= string_expr
->value
.first
;
1883 wxExpr
*second
= first
? first
->next
: NULL
;
1884 wxExpr
*third
= second
? second
->next
: NULL
;
1886 if (first
&& second
&& third
&&
1887 (first
->Type() == wxExprReal
|| first
->Type() == wxExprInteger
) &&
1888 (second
->Type() == wxExprReal
|| second
->Type() == wxExprInteger
) &&
1889 third
->Type() == wxExprString
)
1891 if (first
->Type() == wxExprReal
)
1892 the_x
= first
->RealValue();
1893 else the_x
= (double)first
->IntegerValue();
1895 if (second
->Type() == wxExprReal
)
1896 the_y
= second
->RealValue();
1897 else the_y
= (double)second
->IntegerValue();
1899 the_string
= third
->StringValue();
1902 wxShapeTextLine
*line
=
1903 new wxShapeTextLine(the_x
, the_y
, (char*) (const char*) the_string
);
1904 m_text
.Append(line
);
1910 wxString pen_string
= "";
1911 wxString brush_string
= "";
1913 int pen_style
= wxSOLID
;
1914 int brush_style
= wxSOLID
;
1915 m_attachmentMode
= FALSE
;
1917 clause
->GetAttributeValue("pen_colour", pen_string
);
1918 clause
->GetAttributeValue("text_colour", m_textColourName
);
1920 SetTextColour(m_textColourName
);
1922 clause
->GetAttributeValue("region_name", m_regionName
);
1924 clause
->GetAttributeValue("brush_colour", brush_string
);
1925 clause
->GetAttributeValue("pen_width", pen_width
);
1926 clause
->GetAttributeValue("pen_style", pen_style
);
1927 clause
->GetAttributeValue("brush_style", brush_style
);
1929 int iVal
= (int) m_attachmentMode
;
1930 clause
->GetAttributeValue("use_attachments", iVal
);
1931 m_attachmentMode
= (iVal
!= 0);
1933 clause
->GetAttributeValue("sensitivity", m_sensitivity
);
1935 iVal
= (int) m_spaceAttachments
;
1936 clause
->GetAttributeValue("space_attachments", iVal
);
1937 m_spaceAttachments
= (iVal
!= 0);
1939 iVal
= (int) m_fixedWidth
;
1940 clause
->GetAttributeValue("fixed_width", iVal
);
1941 m_fixedWidth
= (iVal
!= 0);
1943 iVal
= (int) m_fixedHeight
;
1944 clause
->GetAttributeValue("fixed_height", iVal
);
1945 m_fixedHeight
= (iVal
!= 0);
1947 clause
->GetAttributeValue("format_mode", m_formatMode
);
1948 clause
->GetAttributeValue("shadow_mode", m_shadowMode
);
1950 iVal
= (int) m_centreResize
;
1951 clause
->GetAttributeValue("centre_resize", iVal
);
1952 m_centreResize
= (iVal
!= 0);
1954 iVal
= (int) m_maintainAspectRatio
;
1955 clause
->GetAttributeValue("maintain_aspect_ratio", iVal
);
1956 m_maintainAspectRatio
= (iVal
!= 0);
1958 iVal
= (int) m_highlighted
;
1959 clause
->GetAttributeValue("hilite", iVal
);
1960 m_highlighted
= (iVal
!= 0);
1962 clause
->GetAttributeValue("rotation", m_rotation
);
1964 if (pen_string
== "")
1965 pen_string
= "BLACK";
1966 if (brush_string
== "")
1967 brush_string
= "WHITE";
1969 if (pen_string
[0] == '#')
1971 wxColour
col(oglHexToColour(pen_string
.After('#')));
1972 m_pen
= wxThePenList
->FindOrCreatePen(col
, pen_width
, pen_style
);
1975 m_pen
= wxThePenList
->FindOrCreatePen(pen_string
, pen_width
, pen_style
);
1978 m_pen
= wxBLACK_PEN
;
1980 if (brush_string
[0] == '#')
1982 wxColour
col(oglHexToColour(brush_string
.After('#')));
1983 m_brush
= wxTheBrushList
->FindOrCreateBrush(col
, brush_style
);
1986 m_brush
= wxTheBrushList
->FindOrCreateBrush(brush_string
, brush_style
);
1989 m_brush
= wxWHITE_BRUSH
;
1991 int point_size
= 10;
1992 clause
->GetAttributeValue("point_size", point_size
);
1993 SetFont(oglMatchFont(point_size
));
1995 // Read user-defined attachment points, if any
1996 wxExpr
*attachmentList
= clause
->AttributeValue("user_attachments");
1999 wxExpr
*pointExpr
= attachmentList
->GetFirst();
2002 wxExpr
*idExpr
= pointExpr
->Nth(0);
2003 wxExpr
*xExpr
= pointExpr
->Nth(1);
2004 wxExpr
*yExpr
= pointExpr
->Nth(2);
2005 if (idExpr
&& xExpr
&& yExpr
)
2007 wxAttachmentPoint
*point
= new wxAttachmentPoint
;
2008 point
->m_id
= (int)idExpr
->IntegerValue();
2009 point
->m_x
= xExpr
->RealValue();
2010 point
->m_y
= yExpr
->RealValue();
2011 m_attachmentPoints
.Append((wxObject
*)point
);
2013 pointExpr
= pointExpr
->GetNext();
2017 // Read text regions
2018 ReadRegions(clause
);
2021 void wxShape::ReadRegions(wxExpr
*clause
)
2025 // region1 = (regionName regionText x y width height minWidth minHeight proportionX proportionY
2026 // formatMode fontSize fontFamily fontStyle fontWeight textColour)
2028 char regionNameBuf
[20];
2029 char textNameBuf
[20];
2031 wxExpr
*regionExpr
= NULL
;
2032 wxExpr
*textExpr
= NULL
;
2033 sprintf(regionNameBuf
, "region%d", regionNo
);
2034 sprintf(textNameBuf
, "text%d", regionNo
);
2036 m_formatted
= TRUE
; // Assume text is formatted unless we prove otherwise
2038 while (regionExpr
= clause
->AttributeValue(regionNameBuf
))
2041 * Get the region information
2045 wxString
regionName("");
2046 wxString
regionText("");
2050 double height
= 0.0;
2051 double minWidth
= 5.0;
2052 double minHeight
= 5.0;
2053 double m_regionProportionX
= -1.0;
2054 double m_regionProportionY
= -1.0;
2055 int formatMode
= FORMAT_NONE
;
2057 int fontFamily
= wxSWISS
;
2058 int fontStyle
= wxNORMAL
;
2059 int fontWeight
= wxNORMAL
;
2060 wxString
regionTextColour("");
2061 wxString
penColour("");
2062 int penStyle
= wxSOLID
;
2064 if (regionExpr
->Type() == wxExprList
)
2066 wxExpr
*nameExpr
= regionExpr
->Nth(0);
2067 wxExpr
*textExpr
= regionExpr
->Nth(1);
2068 wxExpr
*xExpr
= regionExpr
->Nth(2);
2069 wxExpr
*yExpr
= regionExpr
->Nth(3);
2070 wxExpr
*widthExpr
= regionExpr
->Nth(4);
2071 wxExpr
*heightExpr
= regionExpr
->Nth(5);
2072 wxExpr
*minWidthExpr
= regionExpr
->Nth(6);
2073 wxExpr
*minHeightExpr
= regionExpr
->Nth(7);
2074 wxExpr
*propXExpr
= regionExpr
->Nth(8);
2075 wxExpr
*propYExpr
= regionExpr
->Nth(9);
2076 wxExpr
*formatExpr
= regionExpr
->Nth(10);
2077 wxExpr
*sizeExpr
= regionExpr
->Nth(11);
2078 wxExpr
*familyExpr
= regionExpr
->Nth(12);
2079 wxExpr
*styleExpr
= regionExpr
->Nth(13);
2080 wxExpr
*weightExpr
= regionExpr
->Nth(14);
2081 wxExpr
*colourExpr
= regionExpr
->Nth(15);
2082 wxExpr
*penColourExpr
= regionExpr
->Nth(16);
2083 wxExpr
*penStyleExpr
= regionExpr
->Nth(17);
2085 regionName
= nameExpr
->StringValue();
2086 regionText
= textExpr
->StringValue();
2088 x
= xExpr
->RealValue();
2089 y
= yExpr
->RealValue();
2091 width
= widthExpr
->RealValue();
2092 height
= heightExpr
->RealValue();
2094 minWidth
= minWidthExpr
->RealValue();
2095 minHeight
= minHeightExpr
->RealValue();
2097 m_regionProportionX
= propXExpr
->RealValue();
2098 m_regionProportionY
= propYExpr
->RealValue();
2100 formatMode
= (int) formatExpr
->IntegerValue();
2101 fontSize
= (int)sizeExpr
->IntegerValue();
2102 fontFamily
= (int)familyExpr
->IntegerValue();
2103 fontStyle
= (int)styleExpr
->IntegerValue();
2104 fontWeight
= (int)weightExpr
->IntegerValue();
2108 regionTextColour
= colourExpr
->StringValue();
2111 regionTextColour
= "BLACK";
2114 penColour
= penColourExpr
->StringValue();
2116 penStyle
= (int)penStyleExpr
->IntegerValue();
2118 wxFont
*font
= wxTheFontList
->FindOrCreateFont(fontSize
, fontFamily
, fontStyle
, fontWeight
);
2120 wxShapeRegion
*region
= new wxShapeRegion
;
2121 region
->SetProportions(m_regionProportionX
, m_regionProportionY
);
2122 region
->SetFont(font
);
2123 region
->SetSize(width
, height
);
2124 region
->SetPosition(x
, y
);
2125 region
->SetMinSize(minWidth
, minHeight
);
2126 region
->SetFormatMode(formatMode
);
2127 region
->SetPenStyle(penStyle
);
2128 if (penColour
!= "")
2129 region
->SetPenColour(penColour
);
2131 region
->m_textColour
= regionTextColour
;
2132 region
->m_regionText
= regionText
;
2133 region
->m_regionName
= regionName
;
2135 m_regions
.Append(region
);
2138 * Get the formatted text strings
2141 textExpr
= clause
->AttributeValue(textNameBuf
);
2142 if (textExpr
&& (textExpr
->Type() == wxExprList
))
2144 wxExpr
*node
= textExpr
->value
.first
;
2147 wxExpr
*string_expr
= node
;
2150 wxString
the_string("");
2152 // string_expr can either be a string, or a list of
2153 // 3 elements: x, y, and string.
2154 if (string_expr
->Type() == wxExprString
)
2156 the_string
= string_expr
->StringValue();
2157 m_formatted
= FALSE
;
2159 else if (string_expr
->Type() == wxExprList
)
2161 wxExpr
*first
= string_expr
->value
.first
;
2162 wxExpr
*second
= first
? first
->next
: NULL
;
2163 wxExpr
*third
= second
? second
->next
: NULL
;
2165 if (first
&& second
&& third
&&
2166 (first
->Type() == wxExprReal
|| first
->Type() == wxExprInteger
) &&
2167 (second
->Type() == wxExprReal
|| second
->Type() == wxExprInteger
) &&
2168 third
->Type() == wxExprString
)
2170 if (first
->Type() == wxExprReal
)
2171 the_x
= first
->RealValue();
2172 else the_x
= (double)first
->IntegerValue();
2174 if (second
->Type() == wxExprReal
)
2175 the_y
= second
->RealValue();
2176 else the_y
= (double)second
->IntegerValue();
2178 the_string
= third
->StringValue();
2183 wxShapeTextLine
*line
=
2184 new wxShapeTextLine(the_x
, the_y
, (char*) (const char*) the_string
);
2185 region
->m_formattedText
.Append(line
);
2192 sprintf(regionNameBuf
, "region%d", regionNo
);
2193 sprintf(textNameBuf
, "text%d", regionNo
);
2196 // Compatibility: check for no regions (old file).
2197 // Lines and divided rectangles must deal with this compatibility
2198 // theirselves. Composites _may_ not have any regions anyway.
2199 if ((m_regions
.Number() == 0) &&
2200 !this->IsKindOf(CLASSINFO(wxLineShape
)) && !this->IsKindOf(CLASSINFO(wxDividedShape
)) &&
2201 !this->IsKindOf(CLASSINFO(wxCompositeShape
)))
2203 wxShapeRegion
*newRegion
= new wxShapeRegion
;
2204 newRegion
->SetName("0");
2205 m_regions
.Append((wxObject
*)newRegion
);
2206 if (m_text
.Number() > 0)
2208 newRegion
->ClearText();
2209 wxNode
*node
= m_text
.First();
2212 wxShapeTextLine
*textLine
= (wxShapeTextLine
*)node
->Data();
2213 wxNode
*next
= node
->Next();
2214 newRegion
->GetFormattedText().Append((wxObject
*)textLine
);
2224 void wxShape::Copy(wxShape
& copy
)
2227 copy
.m_xpos
= m_xpos
;
2228 copy
.m_ypos
= m_ypos
;
2230 copy
.m_brush
= m_brush
;
2231 copy
.m_textColour
= m_textColour
;
2232 copy
.m_centreResize
= m_centreResize
;
2233 copy
.m_maintainAspectRatio
= m_maintainAspectRatio
;
2234 copy
.m_attachmentMode
= m_attachmentMode
;
2235 copy
.m_spaceAttachments
= m_spaceAttachments
;
2236 copy
.m_highlighted
= m_highlighted
;
2237 copy
.m_rotation
= m_rotation
;
2238 copy
.m_textColourName
= m_textColourName
;
2239 copy
.m_regionName
= m_regionName
;
2241 copy
.m_sensitivity
= m_sensitivity
;
2242 copy
.m_draggable
= m_draggable
;
2243 copy
.m_fixedWidth
= m_fixedWidth
;
2244 copy
.m_fixedHeight
= m_fixedHeight
;
2245 copy
.m_formatMode
= m_formatMode
;
2246 copy
.m_drawHandles
= m_drawHandles
;
2248 copy
.m_visible
= m_visible
;
2249 copy
.m_shadowMode
= m_shadowMode
;
2250 copy
.m_shadowOffsetX
= m_shadowOffsetX
;
2251 copy
.m_shadowOffsetY
= m_shadowOffsetY
;
2252 copy
.m_shadowBrush
= m_shadowBrush
;
2254 // Copy text regions
2255 copy
.ClearRegions();
2256 wxNode
*node
= m_regions
.First();
2259 wxShapeRegion
*region
= (wxShapeRegion
*)node
->Data();
2260 wxShapeRegion
*newRegion
= new wxShapeRegion(*region
);
2261 copy
.m_regions
.Append(newRegion
);
2262 node
= node
->Next();
2266 copy
.ClearAttachments();
2267 node
= m_attachmentPoints
.First();
2270 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->Data();
2271 wxAttachmentPoint
*newPoint
= new wxAttachmentPoint
;
2272 newPoint
->m_id
= point
->m_id
;
2273 newPoint
->m_x
= point
->m_x
;
2274 newPoint
->m_y
= point
->m_y
;
2275 copy
.m_attachmentPoints
.Append((wxObject
*)newPoint
);
2276 node
= node
->Next();
2280 copy
.m_lines
.Clear();
2281 node
= m_lines
.First();
2284 wxLineShape
* line
= (wxLineShape
*) node
->Data();
2285 copy
.m_lines
.Append(line
);
2286 node
= node
->Next();
2290 // Create and return a new, fully copied object.
2291 wxShape
*wxShape::CreateNewCopy(bool resetMapping
, bool recompute
)
2294 oglObjectCopyMapping
.Clear();
2296 wxShape
* newObject
= (wxShape
*) GetClassInfo()->CreateObject();
2298 wxASSERT( (newObject
!= NULL
) );
2299 wxASSERT( (newObject
->IsKindOf(CLASSINFO(wxShape
))) );
2303 if (GetEventHandler() != this)
2305 wxShapeEvtHandler
* newHandler
= GetEventHandler()->CreateNewCopy();
2306 newObject
->SetEventHandler(newHandler
);
2307 newObject
->SetPreviousHandler(NULL
);
2308 newHandler
->SetPreviousHandler(newObject
);
2309 newHandler
->SetShape(newObject
);
2313 newObject
->Recompute();
2317 // Does the copying for this object, including copying event
2318 // handler data if any. Calls the virtual Copy function.
2319 void wxShape::CopyWithHandler(wxShape
& copy
)
2323 if (GetEventHandler() != this)
2325 wxASSERT( copy
.GetEventHandler() != NULL
);
2326 wxASSERT( copy
.GetEventHandler() != (©
) );
2327 wxASSERT( GetEventHandler()->GetClassInfo() == copy
.GetEventHandler()->GetClassInfo() );
2328 GetEventHandler()->CopyData(* (copy
.GetEventHandler()));
2333 // Default - make 6 control points
2334 void wxShape::MakeControlPoints()
2336 double maxX
, maxY
, minX
, minY
;
2338 GetBoundingBoxMax(&maxX
, &maxY
);
2339 GetBoundingBoxMin(&minX
, &minY
);
2341 double widthMin
= (double)(minX
+ CONTROL_POINT_SIZE
+ 2);
2342 double heightMin
= (double)(minY
+ CONTROL_POINT_SIZE
+ 2);
2344 // Offsets from main object
2345 double top
= (double)(- (heightMin
/ 2.0));
2346 double bottom
= (double)(heightMin
/ 2.0 + (maxY
- minY
));
2347 double left
= (double)(- (widthMin
/ 2.0));
2348 double right
= (double)(widthMin
/ 2.0 + (maxX
- minX
));
2350 wxControlPoint
*control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, left
, top
,
2351 CONTROL_POINT_DIAGONAL
);
2352 m_canvas
->AddShape(control
);
2353 m_controlPoints
.Append(control
);
2355 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, 0, top
,
2356 CONTROL_POINT_VERTICAL
);
2357 m_canvas
->AddShape(control
);
2358 m_controlPoints
.Append(control
);
2360 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, right
, top
,
2361 CONTROL_POINT_DIAGONAL
);
2362 m_canvas
->AddShape(control
);
2363 m_controlPoints
.Append(control
);
2365 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, right
, 0,
2366 CONTROL_POINT_HORIZONTAL
);
2367 m_canvas
->AddShape(control
);
2368 m_controlPoints
.Append(control
);
2370 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, right
, bottom
,
2371 CONTROL_POINT_DIAGONAL
);
2372 m_canvas
->AddShape(control
);
2373 m_controlPoints
.Append(control
);
2375 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, 0, bottom
,
2376 CONTROL_POINT_VERTICAL
);
2377 m_canvas
->AddShape(control
);
2378 m_controlPoints
.Append(control
);
2380 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, left
, bottom
,
2381 CONTROL_POINT_DIAGONAL
);
2382 m_canvas
->AddShape(control
);
2383 m_controlPoints
.Append(control
);
2385 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, left
, 0,
2386 CONTROL_POINT_HORIZONTAL
);
2387 m_canvas
->AddShape(control
);
2388 m_controlPoints
.Append(control
);
2392 void wxShape::MakeMandatoryControlPoints()
2394 wxNode
*node
= m_children
.First();
2397 wxShape
*child
= (wxShape
*)node
->Data();
2398 child
->MakeMandatoryControlPoints();
2399 node
= node
->Next();
2403 void wxShape::ResetMandatoryControlPoints()
2405 wxNode
*node
= m_children
.First();
2408 wxShape
*child
= (wxShape
*)node
->Data();
2409 child
->ResetMandatoryControlPoints();
2410 node
= node
->Next();
2414 void wxShape::ResetControlPoints()
2416 ResetMandatoryControlPoints();
2418 if (m_controlPoints
.Number() < 1)
2421 double maxX
, maxY
, minX
, minY
;
2423 GetBoundingBoxMax(&maxX
, &maxY
);
2424 GetBoundingBoxMin(&minX
, &minY
);
2426 double widthMin
= (double)(minX
+ CONTROL_POINT_SIZE
+ 2);
2427 double heightMin
= (double)(minY
+ CONTROL_POINT_SIZE
+ 2);
2429 // Offsets from main object
2430 double top
= (double)(- (heightMin
/ 2.0));
2431 double bottom
= (double)(heightMin
/ 2.0 + (maxY
- minY
));
2432 double left
= (double)(- (widthMin
/ 2.0));
2433 double right
= (double)(widthMin
/ 2.0 + (maxX
- minX
));
2435 wxNode
*node
= m_controlPoints
.First();
2436 wxControlPoint
*control
= (wxControlPoint
*)node
->Data();
2437 control
->m_xoffset
= left
; control
->m_yoffset
= top
;
2439 node
= node
->Next(); control
= (wxControlPoint
*)node
->Data();
2440 control
->m_xoffset
= 0; control
->m_yoffset
= top
;
2442 node
= node
->Next(); control
= (wxControlPoint
*)node
->Data();
2443 control
->m_xoffset
= right
; control
->m_yoffset
= top
;
2445 node
= node
->Next(); control
= (wxControlPoint
*)node
->Data();
2446 control
->m_xoffset
= right
; control
->m_yoffset
= 0;
2448 node
= node
->Next(); control
= (wxControlPoint
*)node
->Data();
2449 control
->m_xoffset
= right
; control
->m_yoffset
= bottom
;
2451 node
= node
->Next(); control
= (wxControlPoint
*)node
->Data();
2452 control
->m_xoffset
= 0; control
->m_yoffset
= bottom
;
2454 node
= node
->Next(); control
= (wxControlPoint
*)node
->Data();
2455 control
->m_xoffset
= left
; control
->m_yoffset
= bottom
;
2457 node
= node
->Next(); control
= (wxControlPoint
*)node
->Data();
2458 control
->m_xoffset
= left
; control
->m_yoffset
= 0;
2461 void wxShape::DeleteControlPoints(wxDC
*dc
)
2463 wxNode
*node
= m_controlPoints
.First();
2466 wxControlPoint
*control
= (wxControlPoint
*)node
->Data();
2468 control
->GetEventHandler()->OnErase(*dc
);
2469 m_canvas
->RemoveShape(control
);
2472 node
= m_controlPoints
.First();
2474 // Children of divisions are contained objects,
2476 if (!IsKindOf(CLASSINFO(wxDivisionShape
)))
2478 node
= m_children
.First();
2481 wxShape
*child
= (wxShape
*)node
->Data();
2482 child
->DeleteControlPoints(dc
);
2483 node
= node
->Next();
2488 void wxShape::OnDrawControlPoints(wxDC
& dc
)
2493 dc
.SetBrush(wxBLACK_BRUSH
);
2494 dc
.SetPen(wxBLACK_PEN
);
2496 wxNode
*node
= m_controlPoints
.First();
2499 wxControlPoint
*control
= (wxControlPoint
*)node
->Data();
2501 node
= node
->Next();
2503 // Children of divisions are contained objects,
2505 // This test bypasses the type facility for speed
2506 // (critical when drawing)
2507 if (!IsKindOf(CLASSINFO(wxDivisionShape
)))
2509 node
= m_children
.First();
2512 wxShape
*child
= (wxShape
*)node
->Data();
2513 child
->GetEventHandler()->OnDrawControlPoints(dc
);
2514 node
= node
->Next();
2519 void wxShape::OnEraseControlPoints(wxDC
& dc
)
2521 wxNode
*node
= m_controlPoints
.First();
2524 wxControlPoint
*control
= (wxControlPoint
*)node
->Data();
2526 node
= node
->Next();
2528 if (!IsKindOf(CLASSINFO(wxDivisionShape
)))
2530 node
= m_children
.First();
2533 wxShape
*child
= (wxShape
*)node
->Data();
2534 child
->GetEventHandler()->OnEraseControlPoints(dc
);
2535 node
= node
->Next();
2540 void wxShape::Select(bool select
, wxDC
* dc
)
2542 m_selected
= select
;
2545 MakeControlPoints();
2546 // Children of divisions are contained objects,
2548 if (!IsKindOf(CLASSINFO(wxDivisionShape
)))
2550 wxNode
*node
= m_children
.First();
2553 wxShape
*child
= (wxShape
*)node
->Data();
2554 child
->MakeMandatoryControlPoints();
2555 node
= node
->Next();
2559 GetEventHandler()->OnDrawControlPoints(*dc
);
2563 DeleteControlPoints(dc
);
2564 if (!IsKindOf(CLASSINFO(wxDivisionShape
)))
2566 wxNode
*node
= m_children
.First();
2569 wxShape
*child
= (wxShape
*)node
->Data();
2570 child
->DeleteControlPoints(dc
);
2571 node
= node
->Next();
2577 bool wxShape::Selected() const
2582 bool wxShape::AncestorSelected() const
2584 if (m_selected
) return TRUE
;
2588 return GetParent()->AncestorSelected();
2591 int wxShape::GetNumberOfAttachments() const
2593 // Should return the MAXIMUM attachment point id here,
2594 // so higher-level functions can iterate through all attachments,
2595 // even if they're not contiguous.
2596 if (m_attachmentPoints
.Number() == 0)
2601 wxNode
*node
= m_attachmentPoints
.First();
2604 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->Data();
2605 if (point
->m_id
> maxN
)
2607 node
= node
->Next();
2613 bool wxShape::AttachmentIsValid(int attachment
) const
2615 if (m_attachmentPoints
.Number() == 0)
2617 return ((attachment
>= 0) && (attachment
< 4)) ;
2620 wxNode
*node
= m_attachmentPoints
.First();
2623 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->Data();
2624 if (point
->m_id
== attachment
)
2626 node
= node
->Next();
2631 bool wxShape::GetAttachmentPosition(int attachment
, double *x
, double *y
,
2632 int nth
, int no_arcs
, wxLineShape
*line
)
2634 if (!m_attachmentMode
)
2636 *x
= m_xpos
; *y
= m_ypos
;
2641 if (m_attachmentPoints
.Number() > 0)
2643 wxNode
*node
= m_attachmentPoints
.First();
2646 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->Data();
2647 if (point
->m_id
== attachment
)
2649 *x
= (double)(m_xpos
+ point
->m_x
);
2650 *y
= (double)(m_ypos
+ point
->m_y
);
2653 node
= node
->Next();
2655 *x
= m_xpos
; *y
= m_ypos
;
2660 // Assume is rectangular
2662 GetBoundingBoxMax(&w
, &h
);
2663 double top
= (double)(m_ypos
+ h
/2.0);
2664 double bottom
= (double)(m_ypos
- h
/2.0);
2665 double left
= (double)(m_xpos
- w
/2.0);
2666 double right
= (double)(m_xpos
+ w
/2.0);
2668 bool isEnd
= (line
&& line
->IsEnd(this));
2675 wxRealPoint pt
= CalcSimpleAttachment(wxRealPoint(left
, bottom
), wxRealPoint(right
, bottom
),
2676 nth
, no_arcs
, line
);
2678 *x
= pt
.x
; *y
= pt
.y
;
2683 wxRealPoint pt
= CalcSimpleAttachment(wxRealPoint(right
, bottom
), wxRealPoint(right
, top
),
2684 nth
, no_arcs
, line
);
2686 *x
= pt
.x
; *y
= pt
.y
;
2691 wxRealPoint pt
= CalcSimpleAttachment(wxRealPoint(left
, top
), wxRealPoint(right
, top
),
2692 nth
, no_arcs
, line
);
2694 *x
= pt
.x
; *y
= pt
.y
;
2699 wxRealPoint pt
= CalcSimpleAttachment(wxRealPoint(left
, bottom
), wxRealPoint(left
, top
),
2700 nth
, no_arcs
, line
);
2702 *x
= pt
.x
; *y
= pt
.y
;
2707 return wxShape::GetAttachmentPosition(attachment
, x
, y
, nth
, no_arcs
, line
);
2717 void wxShape::GetBoundingBoxMax(double *w
, double *h
)
2720 GetBoundingBoxMin(&ww
, &hh
);
2721 if (m_shadowMode
!= SHADOW_NONE
)
2723 ww
+= m_shadowOffsetX
;
2724 hh
+= m_shadowOffsetY
;
2730 // Returns TRUE if image is a descendant of this composite
2731 bool wxShape::HasDescendant(wxShape
*image
)
2735 wxNode
*node
= m_children
.First();
2738 wxShape
*child
= (wxShape
*)node
->Data();
2739 bool ans
= child
->HasDescendant(image
);
2742 node
= node
->Next();
2747 // Clears points from a list of wxRealPoints, and clears list
2748 void wxShape::ClearPointList(wxList
& list
)
2750 wxNode
* node
= list
.First();
2753 wxRealPoint
* pt
= (wxRealPoint
*) node
->Data();
2756 node
= node
->Next();
2761 // Assuming the attachment lies along a vertical or horizontal line,
2762 // calculate the position on that point.
2763 wxRealPoint
wxShape::CalcSimpleAttachment(const wxRealPoint
& pt1
, const wxRealPoint
& pt2
,
2764 int nth
, int noArcs
, wxLineShape
* line
)
2766 bool isEnd
= (line
&& line
->IsEnd(this));
2768 // Are we horizontal or vertical?
2769 bool isHorizontal
= (oglRoughlyEqual(pt1
.y
, pt2
.y
) == TRUE
);
2775 wxRealPoint firstPoint
, secondPoint
;
2787 if (m_spaceAttachments
)
2789 if (line
&& (line
->GetAlignmentType(isEnd
) == LINE_ALIGNMENT_TO_NEXT_HANDLE
))
2791 // Align line according to the next handle along
2792 wxRealPoint
*point
= line
->GetNextControlPoint(this);
2793 if (point
->x
< firstPoint
.x
)
2795 else if (point
->x
> secondPoint
.x
)
2801 x
= firstPoint
.x
+ (nth
+ 1)*(secondPoint
.x
- firstPoint
.x
)/(noArcs
+ 1);
2803 else x
= (secondPoint
.x
- firstPoint
.x
)/2.0; // Midpoint
2809 wxASSERT( oglRoughlyEqual(pt1
.x
, pt2
.x
) == TRUE
);
2811 wxRealPoint firstPoint
, secondPoint
;
2823 if (m_spaceAttachments
)
2825 if (line
&& (line
->GetAlignmentType(isEnd
) == LINE_ALIGNMENT_TO_NEXT_HANDLE
))
2827 // Align line according to the next handle along
2828 wxRealPoint
*point
= line
->GetNextControlPoint(this);
2829 if (point
->y
< firstPoint
.y
)
2831 else if (point
->y
> secondPoint
.y
)
2837 y
= firstPoint
.y
+ (nth
+ 1)*(secondPoint
.y
- firstPoint
.y
)/(noArcs
+ 1);
2839 else y
= (secondPoint
.y
- firstPoint
.y
)/2.0; // Midpoint
2844 return wxRealPoint(x
, y
);
2847 // Return the zero-based position in m_lines of line.
2848 int wxShape::GetLinePosition(wxLineShape
* line
)
2851 for (i
= 0; i
< m_lines
.Number(); i
++)
2852 if ((wxLineShape
*) (m_lines
.Nth(i
)->Data()) == line
)