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/deprecated/wxexpr.h>
39 #include "wx/ogl/ogl.h"
42 // Control point types
43 // Rectangle and most other shapes
44 #define CONTROL_POINT_VERTICAL 1
45 #define CONTROL_POINT_HORIZONTAL 2
46 #define CONTROL_POINT_DIAGONAL 3
49 #define CONTROL_POINT_ENDPOINT_TO 4
50 #define CONTROL_POINT_ENDPOINT_FROM 5
51 #define CONTROL_POINT_LINE 6
53 IMPLEMENT_DYNAMIC_CLASS(wxShapeTextLine
, wxObject
)
54 IMPLEMENT_DYNAMIC_CLASS(wxAttachmentPoint
, wxObject
)
56 wxShapeTextLine::wxShapeTextLine(double the_x
, double the_y
, const wxString
& the_line
)
58 m_x
= the_x
; m_y
= the_y
; m_line
= the_line
;
61 wxShapeTextLine::~wxShapeTextLine()
65 IMPLEMENT_ABSTRACT_CLASS(wxShapeEvtHandler
, wxObject
)
67 wxShapeEvtHandler::wxShapeEvtHandler(wxShapeEvtHandler
*prev
, wxShape
*shape
)
69 m_previousHandler
= prev
;
70 m_handlerShape
= shape
;
73 wxShapeEvtHandler::~wxShapeEvtHandler()
77 // Creates a copy of this event handler.
78 wxShapeEvtHandler
* wxShapeEvtHandler::CreateNewCopy()
80 wxShapeEvtHandler
* newObject
= (wxShapeEvtHandler
*) GetClassInfo()->CreateObject();
82 wxASSERT( (newObject
!= NULL
) );
83 wxASSERT( (newObject
->IsKindOf(CLASSINFO(wxShapeEvtHandler
))) );
85 newObject
->m_previousHandler
= newObject
;
93 void wxShapeEvtHandler::OnDelete()
95 if (this != GetShape())
99 void wxShapeEvtHandler::OnDraw(wxDC
& dc
)
101 if (m_previousHandler
)
102 m_previousHandler
->OnDraw(dc
);
105 void wxShapeEvtHandler::OnMoveLinks(wxDC
& dc
)
107 if (m_previousHandler
)
108 m_previousHandler
->OnMoveLinks(dc
);
111 void wxShapeEvtHandler::OnMoveLink(wxDC
& dc
, bool moveControlPoints
)
113 if (m_previousHandler
)
114 m_previousHandler
->OnMoveLink(dc
, moveControlPoints
);
117 void wxShapeEvtHandler::OnDrawContents(wxDC
& dc
)
119 if (m_previousHandler
)
120 m_previousHandler
->OnDrawContents(dc
);
123 void wxShapeEvtHandler::OnDrawBranches(wxDC
& dc
, bool erase
)
125 if (m_previousHandler
)
126 m_previousHandler
->OnDrawBranches(dc
, erase
);
129 void wxShapeEvtHandler::OnSize(double x
, double y
)
131 if (m_previousHandler
)
132 m_previousHandler
->OnSize(x
, y
);
135 bool wxShapeEvtHandler::OnMovePre(wxDC
& dc
, double x
, double y
, double old_x
, double old_y
, bool display
)
137 if (m_previousHandler
)
138 return m_previousHandler
->OnMovePre(dc
, x
, y
, old_x
, old_y
, display
);
143 void wxShapeEvtHandler::OnMovePost(wxDC
& dc
, double x
, double y
, double old_x
, double old_y
, bool display
)
145 if (m_previousHandler
)
146 m_previousHandler
->OnMovePost(dc
, x
, y
, old_x
, old_y
, display
);
149 void wxShapeEvtHandler::OnErase(wxDC
& dc
)
151 if (m_previousHandler
)
152 m_previousHandler
->OnErase(dc
);
155 void wxShapeEvtHandler::OnEraseContents(wxDC
& dc
)
157 if (m_previousHandler
)
158 m_previousHandler
->OnEraseContents(dc
);
161 void wxShapeEvtHandler::OnHighlight(wxDC
& dc
)
163 if (m_previousHandler
)
164 m_previousHandler
->OnHighlight(dc
);
167 void wxShapeEvtHandler::OnLeftClick(double x
, double y
, int keys
, int attachment
)
169 if (m_previousHandler
)
170 m_previousHandler
->OnLeftClick(x
, y
, keys
, attachment
);
173 void wxShapeEvtHandler::OnLeftDoubleClick(double x
, double y
, int keys
, int attachment
)
175 if (m_previousHandler
)
176 m_previousHandler
->OnLeftDoubleClick(x
, y
, keys
, attachment
);
179 void wxShapeEvtHandler::OnRightClick(double x
, double y
, int keys
, int attachment
)
181 if (m_previousHandler
)
182 m_previousHandler
->OnRightClick(x
, y
, keys
, attachment
);
185 void wxShapeEvtHandler::OnDragLeft(bool draw
, double x
, double y
, int keys
, int attachment
)
187 if (m_previousHandler
)
188 m_previousHandler
->OnDragLeft(draw
, x
, y
, keys
, attachment
);
191 void wxShapeEvtHandler::OnBeginDragLeft(double x
, double y
, int keys
, int attachment
)
193 if (m_previousHandler
)
194 m_previousHandler
->OnBeginDragLeft(x
, y
, keys
, attachment
);
197 void wxShapeEvtHandler::OnEndDragLeft(double x
, double y
, int keys
, int attachment
)
199 if (m_previousHandler
)
200 m_previousHandler
->OnEndDragLeft(x
, y
, keys
, attachment
);
203 void wxShapeEvtHandler::OnDragRight(bool draw
, double x
, double y
, int keys
, int attachment
)
205 if (m_previousHandler
)
206 m_previousHandler
->OnDragRight(draw
, x
, y
, keys
, attachment
);
209 void wxShapeEvtHandler::OnBeginDragRight(double x
, double y
, int keys
, int attachment
)
211 if (m_previousHandler
)
212 m_previousHandler
->OnBeginDragRight(x
, y
, keys
, attachment
);
215 void wxShapeEvtHandler::OnEndDragRight(double x
, double y
, int keys
, int attachment
)
217 if (m_previousHandler
)
218 m_previousHandler
->OnEndDragRight(x
, y
, keys
, attachment
);
221 // Control points ('handles') redirect control to the actual shape, to make it easier
222 // to override sizing behaviour.
223 void wxShapeEvtHandler::OnSizingDragLeft(wxControlPoint
* pt
, bool draw
, double x
, double y
, int keys
, int attachment
)
225 if (m_previousHandler
)
226 m_previousHandler
->OnSizingDragLeft(pt
, draw
, x
, y
, keys
, attachment
);
229 void wxShapeEvtHandler::OnSizingBeginDragLeft(wxControlPoint
* pt
, double x
, double y
, int keys
, int attachment
)
231 if (m_previousHandler
)
232 m_previousHandler
->OnSizingBeginDragLeft(pt
, x
, y
, keys
, attachment
);
235 void wxShapeEvtHandler::OnSizingEndDragLeft(wxControlPoint
* pt
, double x
, double y
, int keys
, int attachment
)
237 if (m_previousHandler
)
238 m_previousHandler
->OnSizingEndDragLeft(pt
, x
, y
, keys
, attachment
);
241 void wxShapeEvtHandler::OnDrawOutline(wxDC
& dc
, double x
, double y
, double w
, double h
)
243 if (m_previousHandler
)
244 m_previousHandler
->OnDrawOutline(dc
, x
, y
, w
, h
);
247 void wxShapeEvtHandler::OnDrawControlPoints(wxDC
& dc
)
249 if (m_previousHandler
)
250 m_previousHandler
->OnDrawControlPoints(dc
);
253 void wxShapeEvtHandler::OnEraseControlPoints(wxDC
& dc
)
255 if (m_previousHandler
)
256 m_previousHandler
->OnEraseControlPoints(dc
);
259 // Can override this to prevent or intercept line reordering.
260 void wxShapeEvtHandler::OnChangeAttachment(int attachment
, wxLineShape
* line
, wxList
& ordering
)
262 if (m_previousHandler
)
263 m_previousHandler
->OnChangeAttachment(attachment
, line
, ordering
);
266 IMPLEMENT_ABSTRACT_CLASS(wxShape
, wxShapeEvtHandler
)
268 wxShape::wxShape(wxShapeCanvas
*can
)
270 m_eventHandler
= this;
275 m_xpos
= 0.0; m_ypos
= 0.0;
276 m_pen
= g_oglBlackPen
;
277 m_brush
= wxWHITE_BRUSH
;
278 m_font
= g_oglNormalFont
;
279 m_textColour
= wxBLACK
;
280 m_textColourName
= wxT("BLACK");
283 m_attachmentMode
= ATTACHMENT_MODE_NONE
;
284 m_spaceAttachments
= TRUE
;
285 m_disableLabel
= FALSE
;
286 m_fixedWidth
= FALSE
;
287 m_fixedHeight
= FALSE
;
288 m_drawHandles
= TRUE
;
289 m_sensitivity
= OP_ALL
;
292 m_formatMode
= FORMAT_CENTRE_HORIZ
| FORMAT_CENTRE_VERT
;
293 m_shadowMode
= SHADOW_NONE
;
296 m_shadowBrush
= wxBLACK_BRUSH
;
299 m_regionName
= wxT("0");
300 m_centreResize
= TRUE
;
301 m_maintainAspectRatio
= FALSE
;
302 m_highlighted
= FALSE
;
304 m_branchNeckLength
= 10;
305 m_branchStemLength
= 10;
306 m_branchSpacing
= 10;
307 m_branchStyle
= BRANCHING_ATTACHMENT_NORMAL
;
309 // Set up a default region. Much of the above will be put into
310 // the region eventually (the duplication is for compatibility)
311 wxShapeRegion
*region
= new wxShapeRegion
;
312 m_regions
.Append(region
);
313 region
->SetName(wxT("0"));
314 region
->SetFont(g_oglNormalFont
);
315 region
->SetFormatMode(FORMAT_CENTRE_HORIZ
| FORMAT_CENTRE_VERT
);
316 region
->SetColour(wxT("BLACK"));
322 m_parent
->GetChildren().DeleteObject(this);
329 m_canvas
->RemoveShape(this);
331 GetEventHandler()->OnDelete();
334 void wxShape::SetHighlight(bool hi
, bool recurse
)
339 wxNode
*node
= m_children
.GetFirst();
342 wxShape
*child
= (wxShape
*)node
->GetData();
343 child
->SetHighlight(hi
, recurse
);
344 node
= node
->GetNext();
349 void wxShape::SetSensitivityFilter(int sens
, bool recursive
)
351 if (sens
& OP_DRAG_LEFT
)
356 m_sensitivity
= sens
;
359 wxNode
*node
= m_children
.GetFirst();
362 wxShape
*obj
= (wxShape
*)node
->GetData();
363 obj
->SetSensitivityFilter(sens
, TRUE
);
364 node
= node
->GetNext();
369 void wxShape::SetDraggable(bool drag
, bool recursive
)
373 m_sensitivity
|= OP_DRAG_LEFT
;
375 if (m_sensitivity
& OP_DRAG_LEFT
)
376 m_sensitivity
= m_sensitivity
- OP_DRAG_LEFT
;
380 wxNode
*node
= m_children
.GetFirst();
383 wxShape
*obj
= (wxShape
*)node
->GetData();
384 obj
->SetDraggable(drag
, TRUE
);
385 node
= node
->GetNext();
390 void wxShape::SetDrawHandles(bool drawH
)
392 m_drawHandles
= drawH
;
393 wxNode
*node
= m_children
.GetFirst();
396 wxShape
*obj
= (wxShape
*)node
->GetData();
397 obj
->SetDrawHandles(drawH
);
398 node
= node
->GetNext();
402 void wxShape::SetShadowMode(int mode
, bool redraw
)
404 if (redraw
&& GetCanvas())
406 wxClientDC
dc(GetCanvas());
407 GetCanvas()->PrepareDC(dc
);
420 void wxShape::SetCanvas(wxShapeCanvas
*theCanvas
)
422 m_canvas
= theCanvas
;
423 wxNode
*node
= m_children
.GetFirst();
426 wxShape
*child
= (wxShape
*)node
->GetData();
427 child
->SetCanvas(theCanvas
);
428 node
= node
->GetNext();
432 void wxShape::AddToCanvas(wxShapeCanvas
*theCanvas
, wxShape
*addAfter
)
434 theCanvas
->AddShape(this, addAfter
);
435 wxNode
*node
= m_children
.GetFirst();
436 wxShape
*lastImage
= this;
439 wxShape
*object
= (wxShape
*)node
->GetData();
440 object
->AddToCanvas(theCanvas
, lastImage
);
443 node
= node
->GetNext();
447 // Insert at front of canvas
448 void wxShape::InsertInCanvas(wxShapeCanvas
*theCanvas
)
450 theCanvas
->InsertShape(this);
451 wxNode
*node
= m_children
.GetFirst();
452 wxShape
*lastImage
= this;
455 wxShape
*object
= (wxShape
*)node
->GetData();
456 object
->AddToCanvas(theCanvas
, lastImage
);
459 node
= node
->GetNext();
463 void wxShape::RemoveFromCanvas(wxShapeCanvas
*theCanvas
)
467 theCanvas
->RemoveShape(this);
468 wxNode
*node
= m_children
.GetFirst();
471 wxShape
*object
= (wxShape
*)node
->GetData();
472 object
->RemoveFromCanvas(theCanvas
);
474 node
= node
->GetNext();
478 void wxShape::ClearAttachments()
480 wxNode
*node
= m_attachmentPoints
.GetFirst();
483 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->GetData();
485 node
= node
->GetNext();
487 m_attachmentPoints
.Clear();
490 void wxShape::ClearText(int regionId
)
494 m_text
.DeleteContents(TRUE
);
496 m_text
.DeleteContents(FALSE
);
498 wxNode
*node
= m_regions
.Item(regionId
);
501 wxShapeRegion
*region
= (wxShapeRegion
*)node
->GetData();
505 void wxShape::ClearRegions()
507 wxNode
*node
= m_regions
.GetFirst();
510 wxShapeRegion
*region
= (wxShapeRegion
*)node
->GetData();
511 wxNode
*next
= node
->GetNext();
518 void wxShape::AddRegion(wxShapeRegion
*region
)
520 m_regions
.Append(region
);
523 void wxShape::SetDefaultRegionSize()
525 wxNode
*node
= m_regions
.GetFirst();
527 wxShapeRegion
*region
= (wxShapeRegion
*)node
->GetData();
529 GetBoundingBoxMin(&w
, &h
);
530 region
->SetSize(w
, h
);
533 bool wxShape::HitTest(double x
, double y
, int *attachment
, double *distance
)
538 double width
= 0.0, height
= 0.0;
539 GetBoundingBoxMin(&width
, &height
);
540 if (fabs(width
) < 4.0) width
= 4.0;
541 if (fabs(height
) < 4.0) height
= 4.0;
543 width
+= (double)4.0; height
+= (double)4.0; // Allowance for inaccurate mousing
545 double left
= (double)(m_xpos
- (width
/2.0));
546 double top
= (double)(m_ypos
- (height
/2.0));
547 double right
= (double)(m_xpos
+ (width
/2.0));
548 double bottom
= (double)(m_ypos
+ (height
/2.0));
550 int nearest_attachment
= 0;
552 // If within the bounding box, check the attachment points
553 // within the object.
555 if (x
>= left
&& x
<= right
&& y
>= top
&& y
<= bottom
)
557 int n
= GetNumberOfAttachments();
558 double nearest
= 999999.0;
560 // GetAttachmentPosition[Edge] takes a logical attachment position,
561 // i.e. if it's rotated through 90%, position 0 is East-facing.
563 for (int i
= 0; i
< n
; i
++)
566 if (GetAttachmentPositionEdge(i
, &xp
, &yp
))
568 double l
= (double)sqrt(((xp
- x
) * (xp
- x
)) +
569 ((yp
- y
) * (yp
- y
)));
574 nearest_attachment
= i
;
578 *attachment
= nearest_attachment
;
585 // Format a text string according to the region size, adding
586 // strings with positions to region text list
588 static bool GraphicsInSizeToContents
= FALSE
; // Infinite recursion elimination
589 void wxShape::FormatText(wxDC
& dc
, const wxString
& s
, int i
)
594 if (m_regions
.GetCount() < 1)
596 wxNode
*node
= m_regions
.Item(i
);
600 wxShapeRegion
*region
= (wxShapeRegion
*)node
->GetData();
601 // region->SetText(s); // don't set the formatted text yet, it will be done below
602 region
->m_regionText
= s
;
603 dc
.SetFont(* region
->GetFont());
605 region
->GetSize(&w
, &h
);
607 wxStringList
*stringList
= oglFormatText(dc
, s
, (w
-5), (h
-5), region
->GetFormatMode());
608 node
= (wxNode
*)stringList
->GetFirst();
611 wxChar
*s
= (wxChar
*)node
->GetData();
612 wxShapeTextLine
*line
= new wxShapeTextLine(0.0, 0.0, s
);
613 region
->GetFormattedText().Append((wxObject
*)line
);
614 node
= node
->GetNext();
619 // Don't try to resize an object with more than one image (this case should be dealt
620 // with by overriden handlers)
621 if ((region
->GetFormatMode() & FORMAT_SIZE_TO_CONTENTS
) &&
622 (region
->GetFormattedText().GetCount() > 0) &&
623 (m_regions
.GetCount() == 1) && !GraphicsInSizeToContents
)
625 oglGetCentredTextExtent(dc
, &(region
->GetFormattedText()), m_xpos
, m_ypos
, w
, h
, &actualW
, &actualH
);
626 if ((actualW
+m_textMarginX
!= w
) || (actualH
+m_textMarginY
!= h
))
628 // If we are a descendant of a composite, must make sure the composite gets
630 wxShape
*topAncestor
= GetTopAncestor();
632 if (topAncestor
!= this)
634 // Make sure we don't recurse infinitely
635 GraphicsInSizeToContents
= TRUE
;
637 wxCompositeShape
*composite
= (wxCompositeShape
*)topAncestor
;
638 composite
->Erase(dc
);
639 SetSize(actualW
+m_textMarginX
, actualH
+m_textMarginY
);
640 Move(dc
, m_xpos
, m_ypos
);
641 composite
->CalculateSize();
642 if (composite
->Selected())
644 composite
->DeleteControlPoints(& dc
);
645 composite
->MakeControlPoints();
646 composite
->MakeMandatoryControlPoints();
648 // Where infinite recursion might happen if we didn't stop it
651 GraphicsInSizeToContents
= FALSE
;
656 SetSize(actualW
+m_textMarginX
, actualH
+m_textMarginY
);
657 Move(dc
, m_xpos
, m_ypos
);
659 SetSize(actualW
+m_textMarginX
, actualH
+m_textMarginY
);
660 Move(dc
, m_xpos
, m_ypos
);
664 oglCentreText(dc
, &(region
->GetFormattedText()), m_xpos
, m_ypos
, actualW
, actualH
, region
->GetFormatMode());
668 void wxShape::Recentre(wxDC
& dc
)
671 GetBoundingBoxMin(&w
, &h
);
673 int noRegions
= m_regions
.GetCount();
674 for (int i
= 0; i
< noRegions
; i
++)
676 wxNode
*node
= m_regions
.Item(i
);
679 wxShapeRegion
*region
= (wxShapeRegion
*)node
->GetData();
680 oglCentreText(dc
, &(region
->GetFormattedText()), m_xpos
, m_ypos
, w
, h
, region
->GetFormatMode());
685 bool wxShape::GetPerimeterPoint(double WXUNUSED(x1
), double WXUNUSED(y1
),
686 double WXUNUSED(x2
), double WXUNUSED(y2
),
687 double *WXUNUSED(x3
), double *WXUNUSED(y3
))
692 void wxShape::SetPen(wxPen
*the_pen
)
697 void wxShape::SetBrush(wxBrush
*the_brush
)
702 // Get the top-most (non-division) ancestor, or self
703 wxShape
*wxShape::GetTopAncestor()
708 if (GetParent()->IsKindOf(CLASSINFO(wxDivisionShape
)))
710 else return GetParent()->GetTopAncestor();
717 void wxShape::SetFont(wxFont
*the_font
, int regionId
)
720 wxNode
*node
= m_regions
.Item(regionId
);
723 wxShapeRegion
*region
= (wxShapeRegion
*)node
->GetData();
724 region
->SetFont(the_font
);
727 wxFont
*wxShape::GetFont(int n
) const
729 wxNode
*node
= m_regions
.Item(n
);
732 wxShapeRegion
*region
= (wxShapeRegion
*)node
->GetData();
733 return region
->GetFont();
736 void wxShape::SetFormatMode(int mode
, int regionId
)
738 wxNode
*node
= m_regions
.Item(regionId
);
741 wxShapeRegion
*region
= (wxShapeRegion
*)node
->GetData();
742 region
->SetFormatMode(mode
);
745 int wxShape::GetFormatMode(int regionId
) const
747 wxNode
*node
= m_regions
.Item(regionId
);
750 wxShapeRegion
*region
= (wxShapeRegion
*)node
->GetData();
751 return region
->GetFormatMode();
754 void wxShape::SetTextColour(const wxString
& the_colour
, int regionId
)
756 wxColour
*wxcolour
= wxTheColourDatabase
->FindColour(the_colour
);
757 m_textColour
= wxcolour
;
758 m_textColourName
= the_colour
;
760 wxNode
*node
= m_regions
.Item(regionId
);
763 wxShapeRegion
*region
= (wxShapeRegion
*)node
->GetData();
764 region
->SetColour(the_colour
);
767 wxString
wxShape::GetTextColour(int regionId
) const
769 wxNode
*node
= m_regions
.Item(regionId
);
771 return wxEmptyString
;
772 wxShapeRegion
*region
= (wxShapeRegion
*)node
->GetData();
773 return region
->GetColour();
776 void wxShape::SetRegionName(const wxString
& name
, int regionId
)
778 wxNode
*node
= m_regions
.Item(regionId
);
781 wxShapeRegion
*region
= (wxShapeRegion
*)node
->GetData();
782 region
->SetName(name
);
785 wxString
wxShape::GetRegionName(int regionId
)
787 wxNode
*node
= m_regions
.Item(regionId
);
789 return wxEmptyString
;
790 wxShapeRegion
*region
= (wxShapeRegion
*)node
->GetData();
791 return region
->GetName();
794 int wxShape::GetRegionId(const wxString
& name
)
796 wxNode
*node
= m_regions
.GetFirst();
800 wxShapeRegion
*region
= (wxShapeRegion
*)node
->GetData();
801 if (region
->GetName() == name
)
803 node
= node
->GetNext();
809 // Name all m_regions in all subimages recursively.
810 void wxShape::NameRegions(const wxString
& parentName
)
812 int n
= GetNumberOfTextRegions();
814 for (int i
= 0; i
< n
; i
++)
816 if (parentName
.Length() > 0)
817 buff
<< parentName
<< wxT(".") << i
;
820 SetRegionName(buff
, i
);
822 wxNode
*node
= m_children
.GetFirst();
827 wxShape
*child
= (wxShape
*)node
->GetData();
828 if (parentName
.Length() > 0)
829 buff
<< parentName
<< wxT(".") << j
;
832 child
->NameRegions(buff
);
833 node
= node
->GetNext();
838 // Get a region by name, possibly looking recursively into composites.
839 wxShape
*wxShape::FindRegion(const wxString
& name
, int *regionId
)
841 int id
= GetRegionId(name
);
848 wxNode
*node
= m_children
.GetFirst();
851 wxShape
*child
= (wxShape
*)node
->GetData();
852 wxShape
*actualImage
= child
->FindRegion(name
, regionId
);
855 node
= node
->GetNext();
860 // Finds all region names for this image (composite or simple).
861 // Supply empty string list.
862 void wxShape::FindRegionNames(wxStringList
& list
)
864 int n
= GetNumberOfTextRegions();
865 for (int i
= 0; i
< n
; i
++)
867 wxString
name(GetRegionName(i
));
871 wxNode
*node
= m_children
.GetFirst();
874 wxShape
*child
= (wxShape
*)node
->GetData();
875 child
->FindRegionNames(list
);
876 node
= node
->GetNext();
880 void wxShape::AssignNewIds()
884 wxNode
*node
= m_children
.GetFirst();
887 wxShape
*child
= (wxShape
*)node
->GetData();
888 child
->AssignNewIds();
889 node
= node
->GetNext();
893 void wxShape::OnDraw(wxDC
& WXUNUSED(dc
))
897 void wxShape::OnMoveLinks(wxDC
& dc
)
899 // Want to set the ends of all attached links
900 // to point to/from this object
902 wxNode
*current
= m_lines
.GetFirst();
905 wxLineShape
*line
= (wxLineShape
*)current
->GetData();
906 line
->GetEventHandler()->OnMoveLink(dc
);
907 current
= current
->GetNext();
912 void wxShape::OnDrawContents(wxDC
& dc
)
914 double bound_x
, bound_y
;
915 GetBoundingBoxMin(&bound_x
, &bound_y
);
916 if (m_regions
.GetCount() < 1) return;
918 if (m_pen
) dc
.SetPen(* m_pen
);
920 wxShapeRegion
*region
= (wxShapeRegion
*)m_regions
.GetFirst()->GetData();
921 if (region
->GetFont()) dc
.SetFont(* region
->GetFont());
923 dc
.SetTextForeground(* (region
->GetActualColourObject()));
924 dc
.SetBackgroundMode(wxTRANSPARENT
);
927 oglCentreText(dc
, &(region
->GetFormattedText()), m_xpos
, m_ypos
, bound_x
, bound_y
, region
->GetFormatMode());
930 if (!GetDisableLabel())
932 oglDrawFormattedText(dc
, &(region
->GetFormattedText()), m_xpos
, m_ypos
, bound_x
, bound_y
, region
->GetFormatMode());
936 void wxShape::DrawContents(wxDC
& dc
)
938 GetEventHandler()->OnDrawContents(dc
);
941 void wxShape::OnSize(double WXUNUSED(x
), double WXUNUSED(y
))
945 bool wxShape::OnMovePre(wxDC
& WXUNUSED(dc
), double WXUNUSED(x
), double WXUNUSED(y
), double WXUNUSED(old_x
), double WXUNUSED(old_y
), bool WXUNUSED(display
))
950 void wxShape::OnMovePost(wxDC
& WXUNUSED(dc
), double WXUNUSED(x
), double WXUNUSED(y
), double WXUNUSED(old_x
), double WXUNUSED(old_y
), bool WXUNUSED(display
))
954 void wxShape::OnErase(wxDC
& dc
)
960 wxNode
*current
= m_lines
.GetFirst();
963 wxLineShape
*line
= (wxLineShape
*)current
->GetData();
964 line
->GetEventHandler()->OnErase(dc
);
965 current
= current
->GetNext();
967 GetEventHandler()->OnEraseContents(dc
);
970 void wxShape::OnEraseContents(wxDC
& dc
)
975 double maxX
, maxY
, minX
, minY
;
978 GetBoundingBoxMin(&minX
, &minY
);
979 GetBoundingBoxMax(&maxX
, &maxY
);
980 double topLeftX
= (double)(xp
- (maxX
/ 2.0) - 2.0);
981 double topLeftY
= (double)(yp
- (maxY
/ 2.0) - 2.0);
985 penWidth
= m_pen
->GetWidth();
987 dc
.SetPen(GetBackgroundPen());
988 dc
.SetBrush(GetBackgroundBrush());
990 dc
.DrawRectangle(WXROUND(topLeftX
- penWidth
), WXROUND(topLeftY
- penWidth
),
991 WXROUND(maxX
+ penWidth
*2.0 + 4.0), WXROUND(maxY
+ penWidth
*2.0 + 4.0));
994 void wxShape::EraseLinks(wxDC
& dc
, int attachment
, bool recurse
)
999 wxNode
*current
= m_lines
.GetFirst();
1002 wxLineShape
*line
= (wxLineShape
*)current
->GetData();
1003 if (attachment
== -1 || ((line
->GetTo() == this && line
->GetAttachmentTo() == attachment
) ||
1004 (line
->GetFrom() == this && line
->GetAttachmentFrom() == attachment
)))
1005 line
->GetEventHandler()->OnErase(dc
);
1006 current
= current
->GetNext();
1010 wxNode
*node
= m_children
.GetFirst();
1013 wxShape
*child
= (wxShape
*)node
->GetData();
1014 child
->EraseLinks(dc
, attachment
, recurse
);
1015 node
= node
->GetNext();
1020 void wxShape::DrawLinks(wxDC
& dc
, int attachment
, bool recurse
)
1025 wxNode
*current
= m_lines
.GetFirst();
1028 wxLineShape
*line
= (wxLineShape
*)current
->GetData();
1029 if (attachment
== -1 ||
1030 (line
->GetTo() == this && line
->GetAttachmentTo() == attachment
) ||
1031 (line
->GetFrom() == this && line
->GetAttachmentFrom() == attachment
))
1033 current
= current
->GetNext();
1037 wxNode
*node
= m_children
.GetFirst();
1040 wxShape
*child
= (wxShape
*)node
->GetData();
1041 child
->DrawLinks(dc
, attachment
, recurse
);
1042 node
= node
->GetNext();
1047 // Returns TRUE if pt1 <= pt2 in the sense that one point comes before another on an
1048 // edge of the shape.
1049 // attachmentPoint is the attachment point (= side) in question.
1051 // This is the default, rectangular implementation.
1052 bool wxShape::AttachmentSortTest(int attachmentPoint
, const wxRealPoint
& pt1
, const wxRealPoint
& pt2
)
1054 int physicalAttachment
= LogicalToPhysicalAttachment(attachmentPoint
);
1055 switch (physicalAttachment
)
1060 return (pt1
.x
<= pt2
.x
) ;
1065 return (pt1
.y
<= pt2
.y
) ;
1072 bool wxShape::MoveLineToNewAttachment(wxDC
& dc
, wxLineShape
*to_move
,
1075 if (GetAttachmentMode() == ATTACHMENT_MODE_NONE
)
1078 int newAttachment
, oldAttachment
;
1081 // Is (x, y) on this object? If so, find the new attachment point
1082 // the user has moved the point to
1083 bool hit
= HitTest(x
, y
, &newAttachment
, &distance
);
1089 if (to_move
->GetTo() == this)
1090 oldAttachment
= to_move
->GetAttachmentTo();
1092 oldAttachment
= to_move
->GetAttachmentFrom();
1094 // The links in a new ordering.
1097 // First, add all links to the new list.
1098 wxNode
*node
= m_lines
.GetFirst();
1101 newOrdering
.Append(node
->GetData());
1102 node
= node
->GetNext();
1105 // Delete the line object from the list of links; we're going to move
1106 // it to another position in the list
1107 newOrdering
.DeleteObject(to_move
);
1109 double old_x
= (double) -99999.9;
1110 double old_y
= (double) -99999.9;
1112 node
= newOrdering
.GetFirst();
1115 while (!found
&& node
)
1117 wxLineShape
*line
= (wxLineShape
*)node
->GetData();
1118 if ((line
->GetTo() == this && oldAttachment
== line
->GetAttachmentTo()) ||
1119 (line
->GetFrom() == this && oldAttachment
== line
->GetAttachmentFrom()))
1121 double startX
, startY
, endX
, endY
;
1123 line
->GetEnds(&startX
, &startY
, &endX
, &endY
);
1124 if (line
->GetTo() == this)
1134 wxRealPoint
thisPoint(xp
, yp
);
1135 wxRealPoint
lastPoint(old_x
, old_y
);
1136 wxRealPoint
newPoint(x
, y
);
1138 if (AttachmentSortTest(newAttachment
, newPoint
, thisPoint
) && AttachmentSortTest(newAttachment
, lastPoint
, newPoint
))
1141 newOrdering
.Insert(node
, to_move
);
1147 node
= node
->GetNext();
1151 newOrdering
.Append(to_move
);
1153 GetEventHandler()->OnChangeAttachment(newAttachment
, to_move
, newOrdering
);
1158 void wxShape::OnChangeAttachment(int attachment
, wxLineShape
* line
, wxList
& ordering
)
1160 if (line
->GetTo() == this)
1161 line
->SetAttachmentTo(attachment
);
1163 line
->SetAttachmentFrom(attachment
);
1165 ApplyAttachmentOrdering(ordering
);
1167 wxClientDC
dc(GetCanvas());
1168 GetCanvas()->PrepareDC(dc
);
1172 if (!GetCanvas()->GetQuickEditMode()) GetCanvas()->Redraw(dc
);
1175 // Reorders the lines according to the given list.
1176 void wxShape::ApplyAttachmentOrdering(wxList
& linesToSort
)
1178 // This is a temporary store of all the lines.
1181 wxNode
*node
= m_lines
.GetFirst();
1184 wxLineShape
*line
= (wxLineShape
*)node
->GetData();
1185 linesStore
.Append(line
);
1186 node
= node
->GetNext();;
1191 node
= linesToSort
.GetFirst();
1194 wxLineShape
*line
= (wxLineShape
*)node
->GetData();
1195 if (linesStore
.Member(line
))
1198 linesStore
.DeleteObject(line
);
1199 m_lines
.Append(line
);
1201 node
= node
->GetNext();
1204 // Now add any lines that haven't been listed in linesToSort.
1205 node
= linesStore
.GetFirst();
1208 wxLineShape
*line
= (wxLineShape
*)node
->GetData();
1209 m_lines
.Append(line
);
1210 node
= node
->GetNext();
1214 // Reorders the lines coming into the node image at this attachment
1215 // position, in the order in which they appear in linesToSort.
1216 // Any remaining lines not in the list will be added to the end.
1217 void wxShape::SortLines(int attachment
, wxList
& linesToSort
)
1219 // This is a temporary store of all the lines at this attachment
1220 // point. We'll tick them off as we've processed them.
1221 wxList linesAtThisAttachment
;
1223 wxNode
*node
= m_lines
.GetFirst();
1226 wxLineShape
*line
= (wxLineShape
*)node
->GetData();
1227 wxNode
*next
= node
->GetNext();
1228 if ((line
->GetTo() == this && line
->GetAttachmentTo() == attachment
) ||
1229 (line
->GetFrom() == this && line
->GetAttachmentFrom() == attachment
))
1231 linesAtThisAttachment
.Append(line
);
1235 else node
= node
->GetNext();
1238 node
= linesToSort
.GetFirst();
1241 wxLineShape
*line
= (wxLineShape
*)node
->GetData();
1242 if (linesAtThisAttachment
.Member(line
))
1245 linesAtThisAttachment
.DeleteObject(line
);
1246 m_lines
.Append(line
);
1248 node
= node
->GetNext();
1251 // Now add any lines that haven't been listed in linesToSort.
1252 node
= linesAtThisAttachment
.GetFirst();
1255 wxLineShape
*line
= (wxLineShape
*)node
->GetData();
1256 m_lines
.Append(line
);
1257 node
= node
->GetNext();
1261 void wxShape::OnHighlight(wxDC
& WXUNUSED(dc
))
1265 void wxShape::OnLeftClick(double x
, double y
, int keys
, int attachment
)
1267 if ((m_sensitivity
& OP_CLICK_LEFT
) != OP_CLICK_LEFT
)
1273 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1274 m_parent
->GetEventHandler()->OnLeftClick(x
, y
, keys
, attachment
);
1280 void wxShape::OnRightClick(double x
, double y
, int keys
, int attachment
)
1282 if ((m_sensitivity
& OP_CLICK_RIGHT
) != OP_CLICK_RIGHT
)
1288 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1289 m_parent
->GetEventHandler()->OnRightClick(x
, y
, keys
, attachment
);
1295 double DragOffsetX
= 0.0;
1296 double DragOffsetY
= 0.0;
1298 void wxShape::OnDragLeft(bool draw
, double x
, double y
, int keys
, int attachment
)
1300 if ((m_sensitivity
& OP_DRAG_LEFT
) != OP_DRAG_LEFT
)
1306 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1307 m_parent
->GetEventHandler()->OnDragLeft(draw
, x
, y
, keys
, attachment
);
1312 wxClientDC
dc(GetCanvas());
1313 GetCanvas()->PrepareDC(dc
);
1315 dc
.SetLogicalFunction(OGLRBLF
);
1317 wxPen
dottedPen(wxColour(0, 0, 0), 1, wxDOT
);
1318 dc
.SetPen(dottedPen
);
1319 dc
.SetBrush(* wxTRANSPARENT_BRUSH
);
1322 xx
= x
+ DragOffsetX
;
1323 yy
= y
+ DragOffsetY
;
1325 m_canvas
->Snap(&xx
, &yy
);
1326 // m_xpos = xx; m_ypos = yy;
1328 GetBoundingBoxMax(&w
, &h
);
1329 GetEventHandler()->OnDrawOutline(dc
, xx
, yy
, w
, h
);
1332 void wxShape::OnBeginDragLeft(double x
, double y
, int keys
, int attachment
)
1334 if ((m_sensitivity
& OP_DRAG_LEFT
) != OP_DRAG_LEFT
)
1340 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1341 m_parent
->GetEventHandler()->OnBeginDragLeft(x
, y
, keys
, attachment
);
1346 DragOffsetX
= m_xpos
- x
;
1347 DragOffsetY
= m_ypos
- y
;
1349 wxClientDC
dc(GetCanvas());
1350 GetCanvas()->PrepareDC(dc
);
1352 // New policy: don't erase shape until end of drag.
1356 xx
= x
+ DragOffsetX
;
1357 yy
= y
+ DragOffsetY
;
1358 m_canvas
->Snap(&xx
, &yy
);
1359 // m_xpos = xx; m_ypos = yy;
1360 dc
.SetLogicalFunction(OGLRBLF
);
1362 wxPen
dottedPen(wxColour(0, 0, 0), 1, wxDOT
);
1363 dc
.SetPen(dottedPen
);
1364 dc
.SetBrush((* wxTRANSPARENT_BRUSH
));
1367 GetBoundingBoxMax(&w
, &h
);
1368 GetEventHandler()->OnDrawOutline(dc
, xx
, yy
, w
, h
);
1369 m_canvas
->CaptureMouse();
1372 void wxShape::OnEndDragLeft(double x
, double y
, int keys
, int attachment
)
1374 m_canvas
->ReleaseMouse();
1375 if ((m_sensitivity
& OP_DRAG_LEFT
) != OP_DRAG_LEFT
)
1381 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1382 m_parent
->GetEventHandler()->OnEndDragLeft(x
, y
, keys
, attachment
);
1387 wxClientDC
dc(GetCanvas());
1388 GetCanvas()->PrepareDC(dc
);
1390 dc
.SetLogicalFunction(wxCOPY
);
1392 double xx
= x
+ DragOffsetX
;
1393 double yy
= y
+ DragOffsetY
;
1394 m_canvas
->Snap(&xx
, &yy
);
1395 // canvas->Snap(&m_xpos, &m_ypos);
1397 // New policy: erase shape at end of drag.
1401 if (m_canvas
&& !m_canvas
->GetQuickEditMode()) m_canvas
->Redraw(dc
);
1404 void wxShape::OnDragRight(bool draw
, double x
, double y
, int keys
, int attachment
)
1406 if ((m_sensitivity
& OP_DRAG_RIGHT
) != OP_DRAG_RIGHT
)
1412 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1413 m_parent
->GetEventHandler()->OnDragRight(draw
, x
, y
, keys
, attachment
);
1419 void wxShape::OnBeginDragRight(double x
, double y
, int keys
, int attachment
)
1421 if ((m_sensitivity
& OP_DRAG_RIGHT
) != OP_DRAG_RIGHT
)
1427 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1428 m_parent
->GetEventHandler()->OnBeginDragRight(x
, y
, keys
, attachment
);
1434 void wxShape::OnEndDragRight(double x
, double y
, int keys
, int attachment
)
1436 if ((m_sensitivity
& OP_DRAG_RIGHT
) != OP_DRAG_RIGHT
)
1442 m_parent
->HitTest(x
, y
, &attachment
, &dist
);
1443 m_parent
->GetEventHandler()->OnEndDragRight(x
, y
, keys
, attachment
);
1449 void wxShape::OnDrawOutline(wxDC
& dc
, double x
, double y
, double w
, double h
)
1451 double top_left_x
= (double)(x
- w
/2.0);
1452 double top_left_y
= (double)(y
- h
/2.0);
1453 double top_right_x
= (double)(top_left_x
+ w
);
1454 double top_right_y
= (double)top_left_y
;
1455 double bottom_left_x
= (double)top_left_x
;
1456 double bottom_left_y
= (double)(top_left_y
+ h
);
1457 double bottom_right_x
= (double)top_right_x
;
1458 double bottom_right_y
= (double)bottom_left_y
;
1461 points
[0].x
= WXROUND(top_left_x
); points
[0].y
= WXROUND(top_left_y
);
1462 points
[1].x
= WXROUND(top_right_x
); points
[1].y
= WXROUND(top_right_y
);
1463 points
[2].x
= WXROUND(bottom_right_x
); points
[2].y
= WXROUND(bottom_right_y
);
1464 points
[3].x
= WXROUND(bottom_left_x
); points
[3].y
= WXROUND(bottom_left_y
);
1465 points
[4].x
= WXROUND(top_left_x
); points
[4].y
= WXROUND(top_left_y
);
1467 dc
.DrawLines(5, points
);
1470 void wxShape::Attach(wxShapeCanvas
*can
)
1475 void wxShape::Detach()
1480 void wxShape::Move(wxDC
& dc
, double x
, double y
, bool display
)
1482 double old_x
= m_xpos
;
1483 double old_y
= m_ypos
;
1485 if (!GetEventHandler()->OnMovePre(dc
, x
, y
, old_x
, old_y
, display
))
1492 m_xpos
= x
; m_ypos
= y
;
1494 ResetControlPoints();
1501 GetEventHandler()->OnMovePost(dc
, x
, y
, old_x
, old_y
, display
);
1504 void wxShape::MoveLinks(wxDC
& dc
)
1506 GetEventHandler()->OnMoveLinks(dc
);
1510 void wxShape::Draw(wxDC
& dc
)
1514 GetEventHandler()->OnDraw(dc
);
1515 GetEventHandler()->OnDrawContents(dc
);
1516 GetEventHandler()->OnDrawControlPoints(dc
);
1517 GetEventHandler()->OnDrawBranches(dc
);
1521 void wxShape::Flash()
1525 wxClientDC
dc(GetCanvas());
1526 GetCanvas()->PrepareDC(dc
);
1528 dc
.SetLogicalFunction(OGLRBLF
);
1530 dc
.SetLogicalFunction(wxCOPY
);
1535 void wxShape::Show(bool show
)
1538 wxNode
*node
= m_children
.GetFirst();
1541 wxShape
*image
= (wxShape
*)node
->GetData();
1543 node
= node
->GetNext();
1547 void wxShape::Erase(wxDC
& dc
)
1549 GetEventHandler()->OnErase(dc
);
1550 GetEventHandler()->OnEraseControlPoints(dc
);
1551 GetEventHandler()->OnDrawBranches(dc
, TRUE
);
1554 void wxShape::EraseContents(wxDC
& dc
)
1556 GetEventHandler()->OnEraseContents(dc
);
1559 void wxShape::AddText(const wxString
& string
)
1561 wxNode
*node
= m_regions
.GetFirst();
1564 wxShapeRegion
*region
= (wxShapeRegion
*)node
->GetData();
1565 region
->ClearText();
1566 wxShapeTextLine
*new_line
=
1567 new wxShapeTextLine(0.0, 0.0, string
);
1568 region
->GetFormattedText().Append(new_line
);
1570 m_formatted
= FALSE
;
1573 void wxShape::SetSize(double x
, double y
, bool WXUNUSED(recursive
))
1575 SetAttachmentSize(x
, y
);
1576 SetDefaultRegionSize();
1579 void wxShape::SetAttachmentSize(double w
, double h
)
1583 double width
, height
;
1584 GetBoundingBoxMin(&width
, &height
);
1587 else scaleX
= w
/width
;
1590 else scaleY
= h
/height
;
1592 wxNode
*node
= m_attachmentPoints
.GetFirst();
1595 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->GetData();
1596 point
->m_x
= (double)(point
->m_x
* scaleX
);
1597 point
->m_y
= (double)(point
->m_y
* scaleY
);
1598 node
= node
->GetNext();
1602 // Add line FROM this object
1603 void wxShape::AddLine(wxLineShape
*line
, wxShape
*other
,
1604 int attachFrom
, int attachTo
,
1605 // The line ordering
1606 int positionFrom
, int positionTo
)
1608 if (positionFrom
== -1)
1610 if (!m_lines
.Member(line
))
1611 m_lines
.Append(line
);
1615 // Don't preserve old ordering if we have new ordering instructions
1616 m_lines
.DeleteObject(line
);
1617 if (positionFrom
< (int) m_lines
.GetCount())
1619 wxNode
* node
= m_lines
.Item(positionFrom
);
1620 m_lines
.Insert(node
, line
);
1623 m_lines
.Append(line
);
1626 if (positionTo
== -1)
1628 if (!other
->m_lines
.Member(line
))
1629 other
->m_lines
.Append(line
);
1633 // Don't preserve old ordering if we have new ordering instructions
1634 other
->m_lines
.DeleteObject(line
);
1635 if (positionTo
< (int) other
->m_lines
.GetCount())
1637 wxNode
* node
= other
->m_lines
.Item(positionTo
);
1638 other
->m_lines
.Insert(node
, line
);
1641 other
->m_lines
.Append(line
);
1644 // Wrong: doesn't preserve ordering of shape already linked
1645 m_lines
.DeleteObject(line
);
1646 other
->m_lines
.DeleteObject(line
);
1648 if (positionFrom
== -1)
1649 m_lines
.Append(line
);
1652 if (positionFrom
< m_lines
.GetCount())
1654 wxNode
* node
= m_lines
.Item(positionFrom
);
1655 m_lines
.Insert(node
, line
);
1658 m_lines
.Append(line
);
1661 if (positionTo
== -1)
1662 other
->m_lines
.Append(line
);
1665 if (positionTo
< other
->m_lines
.GetCount())
1667 wxNode
* node
= other
->m_lines
.Item(positionTo
);
1668 other
->m_lines
.Insert(node
, line
);
1671 other
->m_lines
.Append(line
);
1675 line
->SetFrom(this);
1677 line
->SetAttachments(attachFrom
, attachTo
);
1680 void wxShape::RemoveLine(wxLineShape
*line
)
1682 if (line
->GetFrom() == this)
1683 line
->GetTo()->m_lines
.DeleteObject(line
);
1685 line
->GetFrom()->m_lines
.DeleteObject(line
);
1687 m_lines
.DeleteObject(line
);
1691 void wxShape::WriteAttributes(wxExpr
*clause
)
1693 clause
->AddAttributeValueString(_T("type"), GetClassInfo()->GetClassName());
1694 clause
->AddAttributeValue(_T("id"), m_id
);
1698 int penWidth
= m_pen
->GetWidth();
1699 int penStyle
= m_pen
->GetStyle();
1701 clause
->AddAttributeValue(_T("pen_width"), (long)penWidth
);
1702 if (penStyle
!= wxSOLID
)
1703 clause
->AddAttributeValue(_T("pen_style"), (long)penStyle
);
1705 wxString penColour
= wxTheColourDatabase
->FindName(m_pen
->GetColour());
1706 if (penColour
== wxEmptyString
)
1708 wxString
hex(oglColourToHex(m_pen
->GetColour()));
1709 hex
= wxString(_T("#")) + hex
;
1710 clause
->AddAttributeValueString(_T("pen_colour"), hex
);
1712 else if (penColour
!= _T("BLACK"))
1713 clause
->AddAttributeValueString(_T("pen_colour"), penColour
);
1718 wxString brushColour
= wxTheColourDatabase
->FindName(m_brush
->GetColour());
1720 if (brushColour
== wxEmptyString
)
1722 wxString
hex(oglColourToHex(m_brush
->GetColour()));
1723 hex
= wxString(_T("#")) + hex
;
1724 clause
->AddAttributeValueString(_T("brush_colour"), hex
);
1726 else if (brushColour
!= _T("WHITE"))
1727 clause
->AddAttributeValueString(_T("brush_colour"), brushColour
);
1729 if (m_brush
->GetStyle() != wxSOLID
)
1730 clause
->AddAttributeValue(_T("brush_style"), (long)m_brush
->GetStyle());
1735 int n_lines
= m_lines
.GetCount();
1738 wxExpr
*list
= new wxExpr(wxExprList
);
1739 wxNode
*node
= m_lines
.GetFirst();
1742 wxShape
*line
= (wxShape
*)node
->GetData();
1743 wxExpr
*id_expr
= new wxExpr(line
->GetId());
1744 list
->Append(id_expr
);
1745 node
= node
->GetNext();
1747 clause
->AddAttributeValue(_T("arcs"), list
);
1750 // Miscellaneous members
1751 if (m_attachmentMode
!= 0)
1752 clause
->AddAttributeValue(_T("use_attachments"), (long)m_attachmentMode
);
1753 if (m_sensitivity
!= OP_ALL
)
1754 clause
->AddAttributeValue(_T("sensitivity"), (long)m_sensitivity
);
1755 if (!m_spaceAttachments
)
1756 clause
->AddAttributeValue(_T("space_attachments"), (long)m_spaceAttachments
);
1758 clause
->AddAttributeValue(_T("fixed_width"), (long)m_fixedWidth
);
1760 clause
->AddAttributeValue(_T("fixed_height"), (long)m_fixedHeight
);
1761 if (m_shadowMode
!= SHADOW_NONE
)
1762 clause
->AddAttributeValue(_T("shadow_mode"), (long)m_shadowMode
);
1763 if (m_centreResize
!= TRUE
)
1764 clause
->AddAttributeValue(_T("centre_resize"), (long)0);
1765 clause
->AddAttributeValue(_T("maintain_aspect_ratio"), (long) m_maintainAspectRatio
);
1766 if (m_highlighted
!= FALSE
)
1767 clause
->AddAttributeValue(_T("hilite"), (long)m_highlighted
);
1769 if (m_parent
) // For composite objects
1770 clause
->AddAttributeValue(_T("parent"), (long)m_parent
->GetId());
1772 if (m_rotation
!= 0.0)
1773 clause
->AddAttributeValue(_T("rotation"), m_rotation
);
1775 if (!this->IsKindOf(CLASSINFO(wxLineShape
)))
1777 clause
->AddAttributeValue(_T("neck_length"), (long) m_branchNeckLength
);
1778 clause
->AddAttributeValue(_T("stem_length"), (long) m_branchStemLength
);
1779 clause
->AddAttributeValue(_T("branch_spacing"), (long) m_branchSpacing
);
1780 clause
->AddAttributeValue(_T("branch_style"), (long) m_branchStyle
);
1783 // Write user-defined attachment points, if any
1784 if (m_attachmentPoints
.GetCount() > 0)
1786 wxExpr
*attachmentList
= new wxExpr(wxExprList
);
1787 wxNode
*node
= m_attachmentPoints
.GetFirst();
1790 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->GetData();
1791 wxExpr
*pointExpr
= new wxExpr(wxExprList
);
1792 pointExpr
->Append(new wxExpr((long)point
->m_id
));
1793 pointExpr
->Append(new wxExpr(point
->m_x
));
1794 pointExpr
->Append(new wxExpr(point
->m_y
));
1795 attachmentList
->Append(pointExpr
);
1796 node
= node
->GetNext();
1798 clause
->AddAttributeValue(_T("user_attachments"), attachmentList
);
1801 // Write text regions
1802 WriteRegions(clause
);
1805 void wxShape::WriteRegions(wxExpr
*clause
)
1807 // Output regions as region1 = (...), region2 = (...), etc
1808 // and formatted text as text1 = (...), text2 = (...) etc.
1810 wxChar regionNameBuf
[20];
1811 wxChar textNameBuf
[20];
1812 wxNode
*node
= m_regions
.GetFirst();
1815 wxShapeRegion
*region
= (wxShapeRegion
*)node
->GetData();
1816 wxSprintf(regionNameBuf
, _T("region%d"), regionNo
);
1817 wxSprintf(textNameBuf
, _T("text%d"), regionNo
);
1819 // Original text and region attributes:
1820 // region1 = (regionName regionText x y width height minWidth minHeight proportionX proportionY
1821 // formatMode fontSize fontFamily fontStyle fontWeight textColour)
1822 wxExpr
*regionExpr
= new wxExpr(wxExprList
);
1823 regionExpr
->Append(new wxExpr(wxExprString
, region
->m_regionName
));
1824 regionExpr
->Append(new wxExpr(wxExprString
, region
->m_regionText
));
1826 regionExpr
->Append(new wxExpr(region
->m_x
));
1827 regionExpr
->Append(new wxExpr(region
->m_y
));
1828 regionExpr
->Append(new wxExpr(region
->GetWidth()));
1829 regionExpr
->Append(new wxExpr(region
->GetHeight()));
1831 regionExpr
->Append(new wxExpr(region
->m_minWidth
));
1832 regionExpr
->Append(new wxExpr(region
->m_minHeight
));
1833 regionExpr
->Append(new wxExpr(region
->m_regionProportionX
));
1834 regionExpr
->Append(new wxExpr(region
->m_regionProportionY
));
1836 regionExpr
->Append(new wxExpr((long)region
->m_formatMode
));
1838 regionExpr
->Append(new wxExpr((long)(region
->m_font
? region
->m_font
->GetPointSize() : 10)));
1839 regionExpr
->Append(new wxExpr((long)(region
->m_font
? region
->m_font
->GetFamily() : wxDEFAULT
)));
1840 regionExpr
->Append(new wxExpr((long)(region
->m_font
? region
->m_font
->GetStyle() : wxDEFAULT
)));
1841 regionExpr
->Append(new wxExpr((long)(region
->m_font
? region
->m_font
->GetWeight() : wxNORMAL
)));
1842 regionExpr
->Append(new wxExpr(wxExprString
, region
->m_textColour
));
1844 // New members for pen colour/style
1845 regionExpr
->Append(new wxExpr(wxExprString
, region
->m_penColour
));
1846 regionExpr
->Append(new wxExpr((long)region
->m_penStyle
));
1849 // text1 = ((x y string) (x y string) ...)
1850 wxExpr
*textExpr
= new wxExpr(wxExprList
);
1852 wxNode
*textNode
= region
->m_formattedText
.GetFirst();
1855 wxShapeTextLine
*line
= (wxShapeTextLine
*)textNode
->GetData();
1856 wxExpr
*list2
= new wxExpr(wxExprList
);
1857 list2
->Append(new wxExpr(line
->GetX()));
1858 list2
->Append(new wxExpr(line
->GetY()));
1859 list2
->Append(new wxExpr(wxExprString
, line
->GetText()));
1860 textExpr
->Append(list2
);
1861 textNode
= textNode
->GetNext();
1864 // Now add both attributes to the clause
1865 clause
->AddAttributeValue(regionNameBuf
, regionExpr
);
1866 clause
->AddAttributeValue(textNameBuf
, textExpr
);
1868 node
= node
->GetNext();
1873 void wxShape::ReadAttributes(wxExpr
*clause
)
1875 clause
->GetAttributeValue(_T("id"), m_id
);
1878 clause
->GetAttributeValue(_T("x"), m_xpos
);
1879 clause
->GetAttributeValue(_T("y"), m_ypos
);
1881 // Input text strings (FOR COMPATIBILITY WITH OLD FILES ONLY. SEE REGION CODE BELOW.)
1883 wxExpr
*strings
= clause
->AttributeValue(_T("text"));
1884 if (strings
&& strings
->Type() == wxExprList
)
1886 m_formatted
= TRUE
; // Assume text is formatted unless we prove otherwise
1887 wxExpr
*node
= strings
->value
.first
;
1890 wxExpr
*string_expr
= node
;
1893 wxString the_string
= wxEmptyString
;
1895 // string_expr can either be a string, or a list of
1896 // 3 elements: x, y, and string.
1897 if (string_expr
->Type() == wxExprString
)
1899 the_string
= string_expr
->StringValue();
1900 m_formatted
= FALSE
;
1902 else if (string_expr
->Type() == wxExprList
)
1904 wxExpr
*first
= string_expr
->value
.first
;
1905 wxExpr
*second
= first
? first
->next
: (wxExpr
*) NULL
;
1906 wxExpr
*third
= second
? second
->next
: (wxExpr
*) NULL
;
1908 if (first
&& second
&& third
&&
1909 (first
->Type() == wxExprReal
|| first
->Type() == wxExprInteger
) &&
1910 (second
->Type() == wxExprReal
|| second
->Type() == wxExprInteger
) &&
1911 third
->Type() == wxExprString
)
1913 if (first
->Type() == wxExprReal
)
1914 the_x
= first
->RealValue();
1915 else the_x
= (double)first
->IntegerValue();
1917 if (second
->Type() == wxExprReal
)
1918 the_y
= second
->RealValue();
1919 else the_y
= (double)second
->IntegerValue();
1921 the_string
= third
->StringValue();
1924 wxShapeTextLine
*line
=
1925 new wxShapeTextLine(the_x
, the_y
, the_string
);
1926 m_text
.Append(line
);
1932 wxString pen_string
= wxEmptyString
;
1933 wxString brush_string
= wxEmptyString
;
1935 int pen_style
= wxSOLID
;
1936 int brush_style
= wxSOLID
;
1937 m_attachmentMode
= ATTACHMENT_MODE_NONE
;
1939 clause
->GetAttributeValue(_T("pen_colour"), pen_string
);
1940 clause
->GetAttributeValue(_T("text_colour"), m_textColourName
);
1942 SetTextColour(m_textColourName
);
1944 clause
->GetAttributeValue(_T("region_name"), m_regionName
);
1946 clause
->GetAttributeValue(_T("brush_colour"), brush_string
);
1947 clause
->GetAttributeValue(_T("pen_width"), pen_width
);
1948 clause
->GetAttributeValue(_T("pen_style"), pen_style
);
1949 clause
->GetAttributeValue(_T("brush_style"), brush_style
);
1951 int iVal
= (int) m_attachmentMode
;
1952 clause
->GetAttributeValue(_T("use_attachments"), iVal
);
1953 m_attachmentMode
= iVal
;
1955 clause
->GetAttributeValue(_T("sensitivity"), m_sensitivity
);
1957 iVal
= (int) m_spaceAttachments
;
1958 clause
->GetAttributeValue(_T("space_attachments"), iVal
);
1959 m_spaceAttachments
= (iVal
!= 0);
1961 iVal
= (int) m_fixedWidth
;
1962 clause
->GetAttributeValue(_T("fixed_width"), iVal
);
1963 m_fixedWidth
= (iVal
!= 0);
1965 iVal
= (int) m_fixedHeight
;
1966 clause
->GetAttributeValue(_T("fixed_height"), iVal
);
1967 m_fixedHeight
= (iVal
!= 0);
1969 clause
->GetAttributeValue(_T("format_mode"), m_formatMode
);
1970 clause
->GetAttributeValue(_T("shadow_mode"), m_shadowMode
);
1972 iVal
= m_branchNeckLength
;
1973 clause
->GetAttributeValue(_T("neck_length"), iVal
);
1974 m_branchNeckLength
= iVal
;
1976 iVal
= m_branchStemLength
;
1977 clause
->GetAttributeValue(_T("stem_length"), iVal
);
1978 m_branchStemLength
= iVal
;
1980 iVal
= m_branchSpacing
;
1981 clause
->GetAttributeValue(_T("branch_spacing"), iVal
);
1982 m_branchSpacing
= iVal
;
1984 clause
->GetAttributeValue(_T("branch_style"), m_branchStyle
);
1986 iVal
= (int) m_centreResize
;
1987 clause
->GetAttributeValue(_T("centre_resize"), iVal
);
1988 m_centreResize
= (iVal
!= 0);
1990 iVal
= (int) m_maintainAspectRatio
;
1991 clause
->GetAttributeValue(_T("maintain_aspect_ratio"), iVal
);
1992 m_maintainAspectRatio
= (iVal
!= 0);
1994 iVal
= (int) m_highlighted
;
1995 clause
->GetAttributeValue(_T("hilite"), iVal
);
1996 m_highlighted
= (iVal
!= 0);
1998 clause
->GetAttributeValue(_T("rotation"), m_rotation
);
2000 if (pen_string
== wxEmptyString
)
2001 pen_string
= _T("BLACK");
2002 if (brush_string
== wxEmptyString
)
2003 brush_string
= _T("WHITE");
2005 if (pen_string
.GetChar(0) == '#')
2007 wxColour
col(oglHexToColour(pen_string
.After('#')));
2008 m_pen
= wxThePenList
->FindOrCreatePen(col
, pen_width
, pen_style
);
2011 m_pen
= wxThePenList
->FindOrCreatePen(pen_string
, pen_width
, pen_style
);
2014 m_pen
= wxBLACK_PEN
;
2016 if (brush_string
.GetChar(0) == '#')
2018 wxColour
col(oglHexToColour(brush_string
.After('#')));
2019 m_brush
= wxTheBrushList
->FindOrCreateBrush(col
, brush_style
);
2022 m_brush
= wxTheBrushList
->FindOrCreateBrush(brush_string
, brush_style
);
2025 m_brush
= wxWHITE_BRUSH
;
2027 int point_size
= 10;
2028 clause
->GetAttributeValue(_T("point_size"), point_size
);
2029 SetFont(oglMatchFont(point_size
));
2031 // Read user-defined attachment points, if any
2032 wxExpr
*attachmentList
= clause
->AttributeValue(_T("user_attachments"));
2035 wxExpr
*pointExpr
= attachmentList
->GetFirst();
2038 wxExpr
*idExpr
= pointExpr
->Nth(0);
2039 wxExpr
*xExpr
= pointExpr
->Nth(1);
2040 wxExpr
*yExpr
= pointExpr
->Nth(2);
2041 if (idExpr
&& xExpr
&& yExpr
)
2043 wxAttachmentPoint
*point
= new wxAttachmentPoint
;
2044 point
->m_id
= (int)idExpr
->IntegerValue();
2045 point
->m_x
= xExpr
->RealValue();
2046 point
->m_y
= yExpr
->RealValue();
2047 m_attachmentPoints
.Append((wxObject
*)point
);
2049 pointExpr
= pointExpr
->GetNext();
2053 // Read text regions
2054 ReadRegions(clause
);
2057 void wxShape::ReadRegions(wxExpr
*clause
)
2061 // region1 = (regionName regionText x y width height minWidth minHeight proportionX proportionY
2062 // formatMode fontSize fontFamily fontStyle fontWeight textColour)
2064 wxChar regionNameBuf
[20];
2065 wxChar textNameBuf
[20];
2068 wxExpr
*textExpr
= NULL
;
2069 wxSprintf(regionNameBuf
, _T("region%d"), regionNo
);
2070 wxSprintf(textNameBuf
, _T("text%d"), regionNo
);
2072 m_formatted
= TRUE
; // Assume text is formatted unless we prove otherwise
2074 while ((regionExpr
= clause
->AttributeValue(regionNameBuf
)) != NULL
)
2077 * Get the region information
2081 wxString regionName
= wxEmptyString
;
2082 wxString regionText
= wxEmptyString
;
2086 double height
= 0.0;
2087 double minWidth
= 5.0;
2088 double minHeight
= 5.0;
2089 double m_regionProportionX
= -1.0;
2090 double m_regionProportionY
= -1.0;
2091 int formatMode
= FORMAT_NONE
;
2093 int fontFamily
= wxSWISS
;
2094 int fontStyle
= wxNORMAL
;
2095 int fontWeight
= wxNORMAL
;
2096 wxString regionTextColour
= wxEmptyString
;
2097 wxString penColour
= wxEmptyString
;
2098 int penStyle
= wxSOLID
;
2100 if (regionExpr
->Type() == wxExprList
)
2102 wxExpr
*nameExpr
= regionExpr
->Nth(0);
2103 wxExpr
*textExpr
= regionExpr
->Nth(1);
2104 wxExpr
*xExpr
= regionExpr
->Nth(2);
2105 wxExpr
*yExpr
= regionExpr
->Nth(3);
2106 wxExpr
*widthExpr
= regionExpr
->Nth(4);
2107 wxExpr
*heightExpr
= regionExpr
->Nth(5);
2108 wxExpr
*minWidthExpr
= regionExpr
->Nth(6);
2109 wxExpr
*minHeightExpr
= regionExpr
->Nth(7);
2110 wxExpr
*propXExpr
= regionExpr
->Nth(8);
2111 wxExpr
*propYExpr
= regionExpr
->Nth(9);
2112 wxExpr
*formatExpr
= regionExpr
->Nth(10);
2113 wxExpr
*sizeExpr
= regionExpr
->Nth(11);
2114 wxExpr
*familyExpr
= regionExpr
->Nth(12);
2115 wxExpr
*styleExpr
= regionExpr
->Nth(13);
2116 wxExpr
*weightExpr
= regionExpr
->Nth(14);
2117 wxExpr
*colourExpr
= regionExpr
->Nth(15);
2118 wxExpr
*penColourExpr
= regionExpr
->Nth(16);
2119 wxExpr
*penStyleExpr
= regionExpr
->Nth(17);
2121 regionName
= nameExpr
->StringValue();
2122 regionText
= textExpr
->StringValue();
2124 x
= xExpr
->RealValue();
2125 y
= yExpr
->RealValue();
2127 width
= widthExpr
->RealValue();
2128 height
= heightExpr
->RealValue();
2130 minWidth
= minWidthExpr
->RealValue();
2131 minHeight
= minHeightExpr
->RealValue();
2133 m_regionProportionX
= propXExpr
->RealValue();
2134 m_regionProportionY
= propYExpr
->RealValue();
2136 formatMode
= (int) formatExpr
->IntegerValue();
2137 fontSize
= (int)sizeExpr
->IntegerValue();
2138 fontFamily
= (int)familyExpr
->IntegerValue();
2139 fontStyle
= (int)styleExpr
->IntegerValue();
2140 fontWeight
= (int)weightExpr
->IntegerValue();
2144 regionTextColour
= colourExpr
->StringValue();
2147 regionTextColour
= _T("BLACK");
2150 penColour
= penColourExpr
->StringValue();
2152 penStyle
= (int)penStyleExpr
->IntegerValue();
2154 wxFont
*font
= wxTheFontList
->FindOrCreateFont(fontSize
, fontFamily
, fontStyle
, fontWeight
);
2156 wxShapeRegion
*region
= new wxShapeRegion
;
2157 region
->SetProportions(m_regionProportionX
, m_regionProportionY
);
2158 region
->SetFont(font
);
2159 region
->SetSize(width
, height
);
2160 region
->SetPosition(x
, y
);
2161 region
->SetMinSize(minWidth
, minHeight
);
2162 region
->SetFormatMode(formatMode
);
2163 region
->SetPenStyle(penStyle
);
2164 if (penColour
!= wxEmptyString
)
2165 region
->SetPenColour(penColour
);
2167 region
->m_textColour
= regionTextColour
;
2168 region
->m_regionText
= regionText
;
2169 region
->m_regionName
= regionName
;
2171 m_regions
.Append(region
);
2174 * Get the formatted text strings
2177 textExpr
= clause
->AttributeValue(textNameBuf
);
2178 if (textExpr
&& (textExpr
->Type() == wxExprList
))
2180 wxExpr
*node
= textExpr
->value
.first
;
2183 wxExpr
*string_expr
= node
;
2186 wxString the_string
= wxEmptyString
;
2188 // string_expr can either be a string, or a list of
2189 // 3 elements: x, y, and string.
2190 if (string_expr
->Type() == wxExprString
)
2192 the_string
= string_expr
->StringValue();
2193 m_formatted
= FALSE
;
2195 else if (string_expr
->Type() == wxExprList
)
2197 wxExpr
*first
= string_expr
->value
.first
;
2198 wxExpr
*second
= first
? first
->next
: (wxExpr
*) NULL
;
2199 wxExpr
*third
= second
? second
->next
: (wxExpr
*) NULL
;
2201 if (first
&& second
&& third
&&
2202 (first
->Type() == wxExprReal
|| first
->Type() == wxExprInteger
) &&
2203 (second
->Type() == wxExprReal
|| second
->Type() == wxExprInteger
) &&
2204 third
->Type() == wxExprString
)
2206 if (first
->Type() == wxExprReal
)
2207 the_x
= first
->RealValue();
2208 else the_x
= (double)first
->IntegerValue();
2210 if (second
->Type() == wxExprReal
)
2211 the_y
= second
->RealValue();
2212 else the_y
= (double)second
->IntegerValue();
2214 the_string
= third
->StringValue();
2219 wxShapeTextLine
*line
=
2220 new wxShapeTextLine(the_x
, the_y
, the_string
);
2221 region
->m_formattedText
.Append(line
);
2228 wxSprintf(regionNameBuf
, _T("region%d"), regionNo
);
2229 wxSprintf(textNameBuf
, _T("text%d"), regionNo
);
2232 // Compatibility: check for no regions (old file).
2233 // Lines and divided rectangles must deal with this compatibility
2234 // theirselves. Composites _may_ not have any regions anyway.
2235 if ((m_regions
.GetCount() == 0) &&
2236 !this->IsKindOf(CLASSINFO(wxLineShape
)) && !this->IsKindOf(CLASSINFO(wxDividedShape
)) &&
2237 !this->IsKindOf(CLASSINFO(wxCompositeShape
)))
2239 wxShapeRegion
*newRegion
= new wxShapeRegion
;
2240 newRegion
->SetName(_T("0"));
2241 m_regions
.Append((wxObject
*)newRegion
);
2242 if (m_text
.GetCount() > 0)
2244 newRegion
->ClearText();
2245 wxNode
*node
= m_text
.GetFirst();
2248 wxShapeTextLine
*textLine
= (wxShapeTextLine
*)node
->GetData();
2249 wxNode
*next
= node
->GetNext();
2250 newRegion
->GetFormattedText().Append((wxObject
*)textLine
);
2260 void wxShape::Copy(wxShape
& copy
)
2263 copy
.m_xpos
= m_xpos
;
2264 copy
.m_ypos
= m_ypos
;
2266 copy
.m_brush
= m_brush
;
2267 copy
.m_textColour
= m_textColour
;
2268 copy
.m_centreResize
= m_centreResize
;
2269 copy
.m_maintainAspectRatio
= m_maintainAspectRatio
;
2270 copy
.m_attachmentMode
= m_attachmentMode
;
2271 copy
.m_spaceAttachments
= m_spaceAttachments
;
2272 copy
.m_highlighted
= m_highlighted
;
2273 copy
.m_rotation
= m_rotation
;
2274 copy
.m_textColourName
= m_textColourName
;
2275 copy
.m_regionName
= m_regionName
;
2277 copy
.m_sensitivity
= m_sensitivity
;
2278 copy
.m_draggable
= m_draggable
;
2279 copy
.m_fixedWidth
= m_fixedWidth
;
2280 copy
.m_fixedHeight
= m_fixedHeight
;
2281 copy
.m_formatMode
= m_formatMode
;
2282 copy
.m_drawHandles
= m_drawHandles
;
2284 copy
.m_visible
= m_visible
;
2285 copy
.m_shadowMode
= m_shadowMode
;
2286 copy
.m_shadowOffsetX
= m_shadowOffsetX
;
2287 copy
.m_shadowOffsetY
= m_shadowOffsetY
;
2288 copy
.m_shadowBrush
= m_shadowBrush
;
2290 copy
.m_branchNeckLength
= m_branchNeckLength
;
2291 copy
.m_branchStemLength
= m_branchStemLength
;
2292 copy
.m_branchSpacing
= m_branchSpacing
;
2294 // Copy text regions
2295 copy
.ClearRegions();
2296 wxNode
*node
= m_regions
.GetFirst();
2299 wxShapeRegion
*region
= (wxShapeRegion
*)node
->GetData();
2300 wxShapeRegion
*newRegion
= new wxShapeRegion(*region
);
2301 copy
.m_regions
.Append(newRegion
);
2302 node
= node
->GetNext();
2306 copy
.ClearAttachments();
2307 node
= m_attachmentPoints
.GetFirst();
2310 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->GetData();
2311 wxAttachmentPoint
*newPoint
= new wxAttachmentPoint
;
2312 newPoint
->m_id
= point
->m_id
;
2313 newPoint
->m_x
= point
->m_x
;
2314 newPoint
->m_y
= point
->m_y
;
2315 copy
.m_attachmentPoints
.Append((wxObject
*)newPoint
);
2316 node
= node
->GetNext();
2320 copy
.m_lines
.Clear();
2321 node
= m_lines
.GetFirst();
2324 wxLineShape
* line
= (wxLineShape
*) node
->GetData();
2325 copy
.m_lines
.Append(line
);
2326 node
= node
->GetNext();
2330 // Create and return a new, fully copied object.
2331 wxShape
*wxShape::CreateNewCopy(bool resetMapping
, bool recompute
)
2334 oglObjectCopyMapping
.Clear();
2336 wxShape
* newObject
= (wxShape
*) GetClassInfo()->CreateObject();
2338 wxASSERT( (newObject
!= NULL
) );
2339 wxASSERT( (newObject
->IsKindOf(CLASSINFO(wxShape
))) );
2343 if (GetEventHandler() != this)
2345 wxShapeEvtHandler
* newHandler
= GetEventHandler()->CreateNewCopy();
2346 newObject
->SetEventHandler(newHandler
);
2347 newObject
->SetPreviousHandler(NULL
);
2348 newHandler
->SetPreviousHandler(newObject
);
2349 newHandler
->SetShape(newObject
);
2353 newObject
->Recompute();
2357 // Does the copying for this object, including copying event
2358 // handler data if any. Calls the virtual Copy function.
2359 void wxShape::CopyWithHandler(wxShape
& copy
)
2363 if (GetEventHandler() != this)
2365 wxASSERT( copy
.GetEventHandler() != NULL
);
2366 wxASSERT( copy
.GetEventHandler() != (©
) );
2367 wxASSERT( GetEventHandler()->GetClassInfo() == copy
.GetEventHandler()->GetClassInfo() );
2368 GetEventHandler()->CopyData(* (copy
.GetEventHandler()));
2373 // Default - make 6 control points
2374 void wxShape::MakeControlPoints()
2376 double maxX
, maxY
, minX
, minY
;
2378 GetBoundingBoxMax(&maxX
, &maxY
);
2379 GetBoundingBoxMin(&minX
, &minY
);
2381 double widthMin
= (double)(minX
+ CONTROL_POINT_SIZE
+ 2);
2382 double heightMin
= (double)(minY
+ CONTROL_POINT_SIZE
+ 2);
2384 // Offsets from main object
2385 double top
= (double)(- (heightMin
/ 2.0));
2386 double bottom
= (double)(heightMin
/ 2.0 + (maxY
- minY
));
2387 double left
= (double)(- (widthMin
/ 2.0));
2388 double right
= (double)(widthMin
/ 2.0 + (maxX
- minX
));
2390 wxControlPoint
*control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, left
, top
,
2391 CONTROL_POINT_DIAGONAL
);
2392 m_canvas
->AddShape(control
);
2393 m_controlPoints
.Append(control
);
2395 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, 0, top
,
2396 CONTROL_POINT_VERTICAL
);
2397 m_canvas
->AddShape(control
);
2398 m_controlPoints
.Append(control
);
2400 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, right
, top
,
2401 CONTROL_POINT_DIAGONAL
);
2402 m_canvas
->AddShape(control
);
2403 m_controlPoints
.Append(control
);
2405 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, right
, 0,
2406 CONTROL_POINT_HORIZONTAL
);
2407 m_canvas
->AddShape(control
);
2408 m_controlPoints
.Append(control
);
2410 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, right
, bottom
,
2411 CONTROL_POINT_DIAGONAL
);
2412 m_canvas
->AddShape(control
);
2413 m_controlPoints
.Append(control
);
2415 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, 0, bottom
,
2416 CONTROL_POINT_VERTICAL
);
2417 m_canvas
->AddShape(control
);
2418 m_controlPoints
.Append(control
);
2420 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, left
, bottom
,
2421 CONTROL_POINT_DIAGONAL
);
2422 m_canvas
->AddShape(control
);
2423 m_controlPoints
.Append(control
);
2425 control
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, left
, 0,
2426 CONTROL_POINT_HORIZONTAL
);
2427 m_canvas
->AddShape(control
);
2428 m_controlPoints
.Append(control
);
2432 void wxShape::MakeMandatoryControlPoints()
2434 wxNode
*node
= m_children
.GetFirst();
2437 wxShape
*child
= (wxShape
*)node
->GetData();
2438 child
->MakeMandatoryControlPoints();
2439 node
= node
->GetNext();
2443 void wxShape::ResetMandatoryControlPoints()
2445 wxNode
*node
= m_children
.GetFirst();
2448 wxShape
*child
= (wxShape
*)node
->GetData();
2449 child
->ResetMandatoryControlPoints();
2450 node
= node
->GetNext();
2454 void wxShape::ResetControlPoints()
2456 ResetMandatoryControlPoints();
2458 if (m_controlPoints
.GetCount() < 1)
2461 double maxX
, maxY
, minX
, minY
;
2463 GetBoundingBoxMax(&maxX
, &maxY
);
2464 GetBoundingBoxMin(&minX
, &minY
);
2466 double widthMin
= (double)(minX
+ CONTROL_POINT_SIZE
+ 2);
2467 double heightMin
= (double)(minY
+ CONTROL_POINT_SIZE
+ 2);
2469 // Offsets from main object
2470 double top
= (double)(- (heightMin
/ 2.0));
2471 double bottom
= (double)(heightMin
/ 2.0 + (maxY
- minY
));
2472 double left
= (double)(- (widthMin
/ 2.0));
2473 double right
= (double)(widthMin
/ 2.0 + (maxX
- minX
));
2475 wxNode
*node
= m_controlPoints
.GetFirst();
2476 wxControlPoint
*control
= (wxControlPoint
*)node
->GetData();
2477 control
->m_xoffset
= left
; control
->m_yoffset
= top
;
2479 node
= node
->GetNext(); control
= (wxControlPoint
*)node
->GetData();
2480 control
->m_xoffset
= 0; control
->m_yoffset
= top
;
2482 node
= node
->GetNext(); control
= (wxControlPoint
*)node
->GetData();
2483 control
->m_xoffset
= right
; control
->m_yoffset
= top
;
2485 node
= node
->GetNext(); control
= (wxControlPoint
*)node
->GetData();
2486 control
->m_xoffset
= right
; control
->m_yoffset
= 0;
2488 node
= node
->GetNext(); control
= (wxControlPoint
*)node
->GetData();
2489 control
->m_xoffset
= right
; control
->m_yoffset
= bottom
;
2491 node
= node
->GetNext(); control
= (wxControlPoint
*)node
->GetData();
2492 control
->m_xoffset
= 0; control
->m_yoffset
= bottom
;
2494 node
= node
->GetNext(); control
= (wxControlPoint
*)node
->GetData();
2495 control
->m_xoffset
= left
; control
->m_yoffset
= bottom
;
2497 node
= node
->GetNext(); control
= (wxControlPoint
*)node
->GetData();
2498 control
->m_xoffset
= left
; control
->m_yoffset
= 0;
2501 void wxShape::DeleteControlPoints(wxDC
*dc
)
2503 wxNode
*node
= m_controlPoints
.GetFirst();
2506 wxControlPoint
*control
= (wxControlPoint
*)node
->GetData();
2508 control
->GetEventHandler()->OnErase(*dc
);
2509 m_canvas
->RemoveShape(control
);
2512 node
= m_controlPoints
.GetFirst();
2514 // Children of divisions are contained objects,
2516 if (!IsKindOf(CLASSINFO(wxDivisionShape
)))
2518 node
= m_children
.GetFirst();
2521 wxShape
*child
= (wxShape
*)node
->GetData();
2522 child
->DeleteControlPoints(dc
);
2523 node
= node
->GetNext();
2528 void wxShape::OnDrawControlPoints(wxDC
& dc
)
2533 dc
.SetBrush(* wxBLACK_BRUSH
);
2534 dc
.SetPen(* wxBLACK_PEN
);
2536 wxNode
*node
= m_controlPoints
.GetFirst();
2539 wxControlPoint
*control
= (wxControlPoint
*)node
->GetData();
2541 node
= node
->GetNext();
2543 // Children of divisions are contained objects,
2545 // This test bypasses the type facility for speed
2546 // (critical when drawing)
2547 if (!IsKindOf(CLASSINFO(wxDivisionShape
)))
2549 node
= m_children
.GetFirst();
2552 wxShape
*child
= (wxShape
*)node
->GetData();
2553 child
->GetEventHandler()->OnDrawControlPoints(dc
);
2554 node
= node
->GetNext();
2559 void wxShape::OnEraseControlPoints(wxDC
& dc
)
2561 wxNode
*node
= m_controlPoints
.GetFirst();
2564 wxControlPoint
*control
= (wxControlPoint
*)node
->GetData();
2566 node
= node
->GetNext();
2568 if (!IsKindOf(CLASSINFO(wxDivisionShape
)))
2570 node
= m_children
.GetFirst();
2573 wxShape
*child
= (wxShape
*)node
->GetData();
2574 child
->GetEventHandler()->OnEraseControlPoints(dc
);
2575 node
= node
->GetNext();
2580 void wxShape::Select(bool select
, wxDC
* dc
)
2582 m_selected
= select
;
2585 MakeControlPoints();
2586 // Children of divisions are contained objects,
2588 if (!IsKindOf(CLASSINFO(wxDivisionShape
)))
2590 wxNode
*node
= m_children
.GetFirst();
2593 wxShape
*child
= (wxShape
*)node
->GetData();
2594 child
->MakeMandatoryControlPoints();
2595 node
= node
->GetNext();
2599 GetEventHandler()->OnDrawControlPoints(*dc
);
2603 DeleteControlPoints(dc
);
2604 if (!IsKindOf(CLASSINFO(wxDivisionShape
)))
2606 wxNode
*node
= m_children
.GetFirst();
2609 wxShape
*child
= (wxShape
*)node
->GetData();
2610 child
->DeleteControlPoints(dc
);
2611 node
= node
->GetNext();
2617 bool wxShape::Selected() const
2622 bool wxShape::AncestorSelected() const
2624 if (m_selected
) return TRUE
;
2628 return GetParent()->AncestorSelected();
2631 int wxShape::GetNumberOfAttachments() const
2633 // Should return the MAXIMUM attachment point id here,
2634 // so higher-level functions can iterate through all attachments,
2635 // even if they're not contiguous.
2636 if (m_attachmentPoints
.GetCount() == 0)
2641 wxNode
*node
= m_attachmentPoints
.GetFirst();
2644 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->GetData();
2645 if (point
->m_id
> maxN
)
2647 node
= node
->GetNext();
2653 bool wxShape::AttachmentIsValid(int attachment
) const
2655 if (m_attachmentPoints
.GetCount() == 0)
2657 return ((attachment
>= 0) && (attachment
< 4)) ;
2660 wxNode
*node
= m_attachmentPoints
.GetFirst();
2663 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->GetData();
2664 if (point
->m_id
== attachment
)
2666 node
= node
->GetNext();
2671 bool wxShape::GetAttachmentPosition(int attachment
, double *x
, double *y
,
2672 int nth
, int no_arcs
, wxLineShape
*line
)
2674 if (m_attachmentMode
== ATTACHMENT_MODE_NONE
)
2676 *x
= m_xpos
; *y
= m_ypos
;
2679 else if (m_attachmentMode
== ATTACHMENT_MODE_BRANCHING
)
2681 wxRealPoint pt
, stemPt
;
2682 GetBranchingAttachmentPoint(attachment
, nth
, pt
, stemPt
);
2687 else if (m_attachmentMode
== ATTACHMENT_MODE_EDGE
)
2689 if (m_attachmentPoints
.GetCount() > 0)
2691 wxNode
*node
= m_attachmentPoints
.GetFirst();
2694 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->GetData();
2695 if (point
->m_id
== attachment
)
2697 *x
= (double)(m_xpos
+ point
->m_x
);
2698 *y
= (double)(m_ypos
+ point
->m_y
);
2701 node
= node
->GetNext();
2703 *x
= m_xpos
; *y
= m_ypos
;
2708 // Assume is rectangular
2710 GetBoundingBoxMax(&w
, &h
);
2711 double top
= (double)(m_ypos
+ h
/2.0);
2712 double bottom
= (double)(m_ypos
- h
/2.0);
2713 double left
= (double)(m_xpos
- w
/2.0);
2714 double right
= (double)(m_xpos
+ w
/2.0);
2716 /* bool isEnd = */ (line
&& line
->IsEnd(this));
2718 int physicalAttachment
= LogicalToPhysicalAttachment(attachment
);
2721 switch (physicalAttachment
)
2725 wxRealPoint pt
= CalcSimpleAttachment(wxRealPoint(left
, bottom
), wxRealPoint(right
, bottom
),
2726 nth
, no_arcs
, line
);
2728 *x
= pt
.x
; *y
= pt
.y
;
2733 wxRealPoint pt
= CalcSimpleAttachment(wxRealPoint(right
, bottom
), wxRealPoint(right
, top
),
2734 nth
, no_arcs
, line
);
2736 *x
= pt
.x
; *y
= pt
.y
;
2741 wxRealPoint pt
= CalcSimpleAttachment(wxRealPoint(left
, top
), wxRealPoint(right
, top
),
2742 nth
, no_arcs
, line
);
2744 *x
= pt
.x
; *y
= pt
.y
;
2749 wxRealPoint pt
= CalcSimpleAttachment(wxRealPoint(left
, bottom
), wxRealPoint(left
, top
),
2750 nth
, no_arcs
, line
);
2752 *x
= pt
.x
; *y
= pt
.y
;
2766 void wxShape::GetBoundingBoxMax(double *w
, double *h
)
2769 GetBoundingBoxMin(&ww
, &hh
);
2770 if (m_shadowMode
!= SHADOW_NONE
)
2772 ww
+= m_shadowOffsetX
;
2773 hh
+= m_shadowOffsetY
;
2779 // Returns TRUE if image is a descendant of this composite
2780 bool wxShape::HasDescendant(wxShape
*image
)
2784 wxNode
*node
= m_children
.GetFirst();
2787 wxShape
*child
= (wxShape
*)node
->GetData();
2788 bool ans
= child
->HasDescendant(image
);
2791 node
= node
->GetNext();
2796 // Clears points from a list of wxRealPoints, and clears list
2797 void wxShape::ClearPointList(wxList
& list
)
2799 wxNode
* node
= list
.GetFirst();
2802 wxRealPoint
* pt
= (wxRealPoint
*) node
->GetData();
2805 node
= node
->GetNext();
2810 // Assuming the attachment lies along a vertical or horizontal line,
2811 // calculate the position on that point.
2812 wxRealPoint
wxShape::CalcSimpleAttachment(const wxRealPoint
& pt1
, const wxRealPoint
& pt2
,
2813 int nth
, int noArcs
, wxLineShape
* line
)
2815 bool isEnd
= (line
&& line
->IsEnd(this));
2817 // Are we horizontal or vertical?
2818 bool isHorizontal
= (oglRoughlyEqual(pt1
.y
, pt2
.y
) == TRUE
);
2824 wxRealPoint firstPoint
, secondPoint
;
2836 if (m_spaceAttachments
)
2838 if (line
&& (line
->GetAlignmentType(isEnd
) == LINE_ALIGNMENT_TO_NEXT_HANDLE
))
2840 // Align line according to the next handle along
2841 wxRealPoint
*point
= line
->GetNextControlPoint(this);
2842 if (point
->x
< firstPoint
.x
)
2844 else if (point
->x
> secondPoint
.x
)
2850 x
= firstPoint
.x
+ (nth
+ 1)*(secondPoint
.x
- firstPoint
.x
)/(noArcs
+ 1);
2852 else x
= (secondPoint
.x
- firstPoint
.x
)/2.0; // Midpoint
2858 wxASSERT( oglRoughlyEqual(pt1
.x
, pt2
.x
) == TRUE
);
2860 wxRealPoint firstPoint
, secondPoint
;
2872 if (m_spaceAttachments
)
2874 if (line
&& (line
->GetAlignmentType(isEnd
) == LINE_ALIGNMENT_TO_NEXT_HANDLE
))
2876 // Align line according to the next handle along
2877 wxRealPoint
*point
= line
->GetNextControlPoint(this);
2878 if (point
->y
< firstPoint
.y
)
2880 else if (point
->y
> secondPoint
.y
)
2886 y
= firstPoint
.y
+ (nth
+ 1)*(secondPoint
.y
- firstPoint
.y
)/(noArcs
+ 1);
2888 else y
= (secondPoint
.y
- firstPoint
.y
)/2.0; // Midpoint
2893 return wxRealPoint(x
, y
);
2896 // Return the zero-based position in m_lines of line.
2897 int wxShape::GetLinePosition(wxLineShape
* line
)
2899 for (size_t i
= 0; i
< m_lines
.GetCount(); i
++)
2900 if ((wxLineShape
*) (m_lines
.Item(i
)->GetData()) == line
)
2910 // shoulder1 ->---------<- shoulder2
2912 // <- branching attachment point N-1
2914 // This function gets information about where branching connections go.
2915 // Returns FALSE if there are no lines at this attachment.
2916 bool wxShape::GetBranchingAttachmentInfo(int attachment
, wxRealPoint
& root
, wxRealPoint
& neck
,
2917 wxRealPoint
& shoulder1
, wxRealPoint
& shoulder2
)
2919 int physicalAttachment
= LogicalToPhysicalAttachment(attachment
);
2921 // Number of lines at this attachment.
2922 int lineCount
= GetAttachmentLineCount(attachment
);
2927 int totalBranchLength
= m_branchSpacing
* (lineCount
- 1);
2929 root
= GetBranchingAttachmentRoot(attachment
);
2931 // Assume that we have attachment points 0 to 3: top, right, bottom, left.
2932 switch (physicalAttachment
)
2937 neck
.y
= root
.y
- m_branchNeckLength
;
2939 shoulder1
.x
= root
.x
- (totalBranchLength
/2.0) ;
2940 shoulder2
.x
= root
.x
+ (totalBranchLength
/2.0) ;
2942 shoulder1
.y
= neck
.y
;
2943 shoulder2
.y
= neck
.y
;
2948 neck
.x
= root
.x
+ m_branchNeckLength
;
2951 shoulder1
.x
= neck
.x
;
2952 shoulder2
.x
= neck
.x
;
2954 shoulder1
.y
= neck
.y
- (totalBranchLength
/2.0) ;
2955 shoulder2
.y
= neck
.y
+ (totalBranchLength
/2.0) ;
2961 neck
.y
= root
.y
+ m_branchNeckLength
;
2963 shoulder1
.x
= root
.x
- (totalBranchLength
/2.0) ;
2964 shoulder2
.x
= root
.x
+ (totalBranchLength
/2.0) ;
2966 shoulder1
.y
= neck
.y
;
2967 shoulder2
.y
= neck
.y
;
2972 neck
.x
= root
.x
- m_branchNeckLength
;
2975 shoulder1
.x
= neck
.x
;
2976 shoulder2
.x
= neck
.x
;
2978 shoulder1
.y
= neck
.y
- (totalBranchLength
/2.0) ;
2979 shoulder2
.y
= neck
.y
+ (totalBranchLength
/2.0) ;
2984 wxFAIL_MSG( wxT("Unrecognised attachment point in GetBranchingAttachmentInfo.") );
2991 // n is the number of the adjoining line, from 0 to N-1 where N is the number of lines
2992 // at this attachment point.
2993 // Get the attachment point where the arc joins the stem, and also the point where the
2994 // the stem meets the shoulder.
2995 bool wxShape::GetBranchingAttachmentPoint(int attachment
, int n
, wxRealPoint
& pt
, wxRealPoint
& stemPt
)
2997 int physicalAttachment
= LogicalToPhysicalAttachment(attachment
);
2999 wxRealPoint root
, neck
, shoulder1
, shoulder2
;
3000 GetBranchingAttachmentInfo(attachment
, root
, neck
, shoulder1
, shoulder2
);
3002 // Assume that we have attachment points 0 to 3: top, right, bottom, left.
3003 switch (physicalAttachment
)
3007 pt
.y
= neck
.y
- m_branchStemLength
;
3008 pt
.x
= shoulder1
.x
+ n
*m_branchSpacing
;
3016 pt
.y
= neck
.y
+ m_branchStemLength
;
3017 pt
.x
= shoulder1
.x
+ n
*m_branchSpacing
;
3025 pt
.x
= neck
.x
+ m_branchStemLength
;
3026 pt
.y
= shoulder1
.y
+ n
*m_branchSpacing
;
3034 pt
.x
= neck
.x
- m_branchStemLength
;
3035 pt
.y
= shoulder1
.y
+ n
*m_branchSpacing
;
3043 wxFAIL_MSG( wxT("Unrecognised attachment point in GetBranchingAttachmentPoint.") );
3051 // Get the number of lines at this attachment position.
3052 int wxShape::GetAttachmentLineCount(int attachment
) const
3055 wxNode
* node
= m_lines
.GetFirst();
3058 wxLineShape
* lineShape
= (wxLineShape
*) node
->GetData();
3059 if ((lineShape
->GetFrom() == this) && (lineShape
->GetAttachmentFrom() == attachment
))
3061 else if ((lineShape
->GetTo() == this) && (lineShape
->GetAttachmentTo() == attachment
))
3064 node
= node
->GetNext();
3069 // This function gets the root point at the given attachment.
3070 wxRealPoint
wxShape::GetBranchingAttachmentRoot(int attachment
)
3072 int physicalAttachment
= LogicalToPhysicalAttachment(attachment
);
3076 double width
, height
;
3077 GetBoundingBoxMax(& width
, & height
);
3079 // Assume that we have attachment points 0 to 3: top, right, bottom, left.
3080 switch (physicalAttachment
)
3085 root
.y
= GetY() - height
/2.0;
3090 root
.x
= GetX() + width
/2.0;
3097 root
.y
= GetY() + height
/2.0;
3102 root
.x
= GetX() - width
/2.0;
3108 wxFAIL_MSG( wxT("Unrecognised attachment point in GetBranchingAttachmentRoot.") );
3115 // Draw or erase the branches (not the actual arcs though)
3116 void wxShape::OnDrawBranches(wxDC
& dc
, int attachment
, bool erase
)
3118 int count
= GetAttachmentLineCount(attachment
);
3122 wxRealPoint root
, neck
, shoulder1
, shoulder2
;
3123 GetBranchingAttachmentInfo(attachment
, root
, neck
, shoulder1
, shoulder2
);
3127 dc
.SetPen(*wxWHITE_PEN
);
3128 dc
.SetBrush(*wxWHITE_BRUSH
);
3132 dc
.SetPen(*wxBLACK_PEN
);
3133 dc
.SetBrush(*wxBLACK_BRUSH
);
3137 dc
.DrawLine((long) root
.x
, (long) root
.y
, (long) neck
.x
, (long) neck
.y
);
3141 // Draw shoulder-to-shoulder line
3142 dc
.DrawLine((long) shoulder1
.x
, (long) shoulder1
.y
, (long) shoulder2
.x
, (long) shoulder2
.y
);
3144 // Draw all the little branches
3146 for (i
= 0; i
< count
; i
++)
3148 wxRealPoint pt
, stemPt
;
3149 GetBranchingAttachmentPoint(attachment
, i
, pt
, stemPt
);
3150 dc
.DrawLine((long) stemPt
.x
, (long) stemPt
.y
, (long) pt
.x
, (long) pt
.y
);
3152 if ((GetBranchStyle() & BRANCHING_ATTACHMENT_BLOB
) && (count
> 1))
3155 // dc.DrawEllipse((long) (stemPt.x + 0.5 - (blobSize/2.0)), (long) (stemPt.y + 0.5 - (blobSize/2.0)), blobSize, blobSize);
3156 dc
.DrawEllipse((long) (stemPt
.x
- (blobSize
/2.0)), (long) (stemPt
.y
- (blobSize
/2.0)), blobSize
, blobSize
);
3161 // Draw or erase the branches (not the actual arcs though)
3162 void wxShape::OnDrawBranches(wxDC
& dc
, bool erase
)
3164 if (m_attachmentMode
!= ATTACHMENT_MODE_BRANCHING
)
3167 int count
= GetNumberOfAttachments();
3169 for (i
= 0; i
< count
; i
++)
3170 OnDrawBranches(dc
, i
, erase
);
3173 // Only get the attachment position at the _edge_ of the shape, ignoring
3174 // branching mode. This is used e.g. to indicate the edge of interest, not the point
3175 // on the attachment branch.
3176 bool wxShape::GetAttachmentPositionEdge(int attachment
, double *x
, double *y
,
3177 int nth
, int no_arcs
, wxLineShape
*line
)
3179 int oldMode
= m_attachmentMode
;
3181 // Calculate as if to edge, not branch
3182 if (m_attachmentMode
== ATTACHMENT_MODE_BRANCHING
)
3183 m_attachmentMode
= ATTACHMENT_MODE_EDGE
;
3184 bool success
= GetAttachmentPosition(attachment
, x
, y
, nth
, no_arcs
, line
);
3185 m_attachmentMode
= oldMode
;
3190 // Rotate the standard attachment point from physical (0 is always North)
3191 // to logical (0 -> 1 if rotated by 90 degrees)
3192 int wxShape::PhysicalToLogicalAttachment(int physicalAttachment
) const
3194 const double pi
= 3.1415926535897932384626433832795 ;
3196 if (oglRoughlyEqual(GetRotation(), 0.0))
3198 i
= physicalAttachment
;
3200 else if (oglRoughlyEqual(GetRotation(), (pi
/2.0)))
3202 i
= physicalAttachment
- 1;
3204 else if (oglRoughlyEqual(GetRotation(), pi
))
3206 i
= physicalAttachment
- 2;
3208 else if (oglRoughlyEqual(GetRotation(), (3.0*pi
/2.0)))
3210 i
= physicalAttachment
- 3;
3213 // Can't handle -- assume the same.
3214 return physicalAttachment
;
3222 // Rotate the standard attachment point from logical
3223 // to physical (0 is always North)
3224 int wxShape::LogicalToPhysicalAttachment(int logicalAttachment
) const
3226 const double pi
= 3.1415926535897932384626433832795 ;
3228 if (oglRoughlyEqual(GetRotation(), 0.0))
3230 i
= logicalAttachment
;
3232 else if (oglRoughlyEqual(GetRotation(), (pi
/2.0)))
3234 i
= logicalAttachment
+ 1;
3236 else if (oglRoughlyEqual(GetRotation(), pi
))
3238 i
= logicalAttachment
+ 2;
3240 else if (oglRoughlyEqual(GetRotation(), (3.0*pi
/2.0)))
3242 i
= logicalAttachment
+ 3;
3245 // Can't handle -- assume the same.
3246 return logicalAttachment
;
3254 void wxShape::Rotate(double WXUNUSED(x
), double WXUNUSED(y
), double theta
)
3256 const double pi
= 3.1415926535897932384626433832795 ;
3258 if (m_rotation
< 0.0)
3262 else if (m_rotation
> 2*pi
)
3269 wxPen
wxShape::GetBackgroundPen()
3273 wxColour c
= GetCanvas()->GetBackgroundColour();
3274 return wxPen(c
, 1, wxSOLID
);
3276 return * g_oglWhiteBackgroundPen
;
3280 wxBrush
wxShape::GetBackgroundBrush()
3284 wxColour c
= GetCanvas()->GetBackgroundColour();
3285 return wxBrush(c
, wxSOLID
);
3287 return * g_oglWhiteBackgroundBrush
;