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> 
  38 #include "wx/ogl/ogl.h" 
  41 // Control point types 
  42 // Rectangle and most other shapes 
  43 #define CONTROL_POINT_VERTICAL   1 
  44 #define CONTROL_POINT_HORIZONTAL 2 
  45 #define CONTROL_POINT_DIAGONAL   3 
  48 #define CONTROL_POINT_ENDPOINT_TO 4 
  49 #define CONTROL_POINT_ENDPOINT_FROM 5 
  50 #define CONTROL_POINT_LINE       6 
  52 IMPLEMENT_DYNAMIC_CLASS(wxShapeTextLine
, wxObject
) 
  53 IMPLEMENT_DYNAMIC_CLASS(wxAttachmentPoint
, wxObject
) 
  55 wxShapeTextLine::wxShapeTextLine(double the_x
, double the_y
, const wxString
& the_line
) 
  57   m_x 
= the_x
; m_y 
= the_y
; m_line 
= the_line
; 
  60 wxShapeTextLine::~wxShapeTextLine() 
  64 IMPLEMENT_ABSTRACT_CLASS(wxShapeEvtHandler
, wxObject
) 
  66 wxShapeEvtHandler::wxShapeEvtHandler(wxShapeEvtHandler 
*prev
, wxShape 
*shape
) 
  68   m_previousHandler 
= prev
; 
  69   m_handlerShape 
= shape
; 
  72 wxShapeEvtHandler::~wxShapeEvtHandler() 
  76 // Creates a copy of this event handler. 
  77 wxShapeEvtHandler
* wxShapeEvtHandler::CreateNewCopy() 
  79   wxShapeEvtHandler
* newObject 
= (wxShapeEvtHandler
*) GetClassInfo()->CreateObject(); 
  81   wxASSERT( (newObject 
!= NULL
) ); 
  82   wxASSERT( (newObject
->IsKindOf(CLASSINFO(wxShapeEvtHandler
))) ); 
  84   newObject
->m_previousHandler 
= newObject
; 
  92 void wxShapeEvtHandler::OnDelete() 
  94   if (this != GetShape()) 
  98 void wxShapeEvtHandler::OnDraw(wxDC
& dc
) 
 100   if (m_previousHandler
) 
 101     m_previousHandler
->OnDraw(dc
); 
 104 void wxShapeEvtHandler::OnMoveLinks(wxDC
& dc
) 
 106   if (m_previousHandler
) 
 107     m_previousHandler
->OnMoveLinks(dc
); 
 110 void wxShapeEvtHandler::OnMoveLink(wxDC
& dc
, bool moveControlPoints
) 
 112   if (m_previousHandler
) 
 113     m_previousHandler
->OnMoveLink(dc
, moveControlPoints
); 
 116 void wxShapeEvtHandler::OnDrawContents(wxDC
& dc
) 
 118   if (m_previousHandler
) 
 119     m_previousHandler
->OnDrawContents(dc
); 
 122 void wxShapeEvtHandler::OnDrawBranches(wxDC
& dc
, bool erase
) 
 124   if (m_previousHandler
) 
 125     m_previousHandler
->OnDrawBranches(dc
, erase
); 
 128 void wxShapeEvtHandler::OnSize(double x
, double y
) 
 130   if (m_previousHandler
) 
 131     m_previousHandler
->OnSize(x
, y
); 
 134 bool wxShapeEvtHandler::OnMovePre(wxDC
& dc
, double x
, double y
, double old_x
, double old_y
, bool display
) 
 136   if (m_previousHandler
) 
 137     return m_previousHandler
->OnMovePre(dc
, x
, y
, old_x
, old_y
, display
); 
 142 void wxShapeEvtHandler::OnMovePost(wxDC
& dc
, double x
, double y
, double old_x
, double old_y
, bool display
) 
 144   if (m_previousHandler
) 
 145     m_previousHandler
->OnMovePost(dc
, x
, y
, old_x
, old_y
, display
); 
 148 void wxShapeEvtHandler::OnErase(wxDC
& dc
) 
 150   if (m_previousHandler
) 
 151     m_previousHandler
->OnErase(dc
); 
 154 void wxShapeEvtHandler::OnEraseContents(wxDC
& dc
) 
 156   if (m_previousHandler
) 
 157     m_previousHandler
->OnEraseContents(dc
); 
 160 void wxShapeEvtHandler::OnHighlight(wxDC
& dc
) 
 162   if (m_previousHandler
) 
 163     m_previousHandler
->OnHighlight(dc
); 
 166 void wxShapeEvtHandler::OnLeftClick(double x
, double y
, int keys
, int attachment
) 
 168   if (m_previousHandler
) 
 169     m_previousHandler
->OnLeftClick(x
, y
, keys
, attachment
); 
 172 void wxShapeEvtHandler::OnLeftDoubleClick(double x
, double y
, int keys
, int attachment
) 
 174   if (m_previousHandler
) 
 175     m_previousHandler
->OnLeftDoubleClick(x
, y
, keys
, attachment
); 
 178 void wxShapeEvtHandler::OnRightClick(double x
, double y
, int keys
, int attachment
) 
 180   if (m_previousHandler
) 
 181     m_previousHandler
->OnRightClick(x
, y
, keys
, attachment
); 
 184 void wxShapeEvtHandler::OnDragLeft(bool draw
, double x
, double y
, int keys
, int attachment
) 
 186   if (m_previousHandler
) 
 187     m_previousHandler
->OnDragLeft(draw
, x
, y
, keys
, attachment
); 
 190 void wxShapeEvtHandler::OnBeginDragLeft(double x
, double y
, int keys
, int attachment
) 
 192   if (m_previousHandler
) 
 193     m_previousHandler
->OnBeginDragLeft(x
, y
, keys
, attachment
); 
 196 void wxShapeEvtHandler::OnEndDragLeft(double x
, double y
, int keys
, int attachment
) 
 198   if (m_previousHandler
) 
 199     m_previousHandler
->OnEndDragLeft(x
, y
, keys
, attachment
); 
 202 void wxShapeEvtHandler::OnDragRight(bool draw
, double x
, double y
, int keys
, int attachment
) 
 204   if (m_previousHandler
) 
 205     m_previousHandler
->OnDragRight(draw
, x
, y
, keys
, attachment
); 
 208 void wxShapeEvtHandler::OnBeginDragRight(double x
, double y
, int keys
, int attachment
) 
 210   if (m_previousHandler
) 
 211     m_previousHandler
->OnBeginDragRight(x
, y
, keys
, attachment
); 
 214 void wxShapeEvtHandler::OnEndDragRight(double x
, double y
, int keys
, int attachment
) 
 216   if (m_previousHandler
) 
 217     m_previousHandler
->OnEndDragRight(x
, y
, keys
, attachment
); 
 220 // Control points ('handles') redirect control to the actual shape, to make it easier 
 221 // to override sizing behaviour. 
 222 void wxShapeEvtHandler::OnSizingDragLeft(wxControlPoint
* pt
, bool draw
, double x
, double y
, int keys
, int attachment
) 
 224   if (m_previousHandler
) 
 225     m_previousHandler
->OnSizingDragLeft(pt
, draw
, x
, y
, keys
, attachment
); 
 228 void wxShapeEvtHandler::OnSizingBeginDragLeft(wxControlPoint
* pt
, double x
, double y
, int keys
, int attachment
) 
 230   if (m_previousHandler
) 
 231     m_previousHandler
->OnSizingBeginDragLeft(pt
, x
, y
, keys
, attachment
); 
 234 void wxShapeEvtHandler::OnSizingEndDragLeft(wxControlPoint
* pt
, double x
, double y
, int keys
, int attachment
) 
 236   if (m_previousHandler
) 
 237     m_previousHandler
->OnSizingEndDragLeft(pt
, x
, y
, keys
, attachment
); 
 240 void wxShapeEvtHandler::OnDrawOutline(wxDC
& dc
, double x
, double y
, double w
, double h
) 
 242   if (m_previousHandler
) 
 243     m_previousHandler
->OnDrawOutline(dc
, x
, y
, w
, h
); 
 246 void wxShapeEvtHandler::OnDrawControlPoints(wxDC
& dc
) 
 248   if (m_previousHandler
) 
 249     m_previousHandler
->OnDrawControlPoints(dc
); 
 252 void wxShapeEvtHandler::OnEraseControlPoints(wxDC
& dc
) 
 254   if (m_previousHandler
) 
 255     m_previousHandler
->OnEraseControlPoints(dc
); 
 258 // Can override this to prevent or intercept line reordering. 
 259 void wxShapeEvtHandler::OnChangeAttachment(int attachment
, wxLineShape
* line
, wxList
& ordering
) 
 261   if (m_previousHandler
) 
 262     m_previousHandler
->OnChangeAttachment(attachment
, line
, ordering
); 
 265 IMPLEMENT_ABSTRACT_CLASS(wxShape
, wxShapeEvtHandler
) 
 267 wxShape::wxShape(wxShapeCanvas 
*can
) 
 269   m_eventHandler 
= this; 
 274   m_xpos 
= 0.0; m_ypos 
= 0.0; 
 275   m_pen 
= g_oglBlackPen
; 
 276   m_brush 
= wxWHITE_BRUSH
; 
 277   m_font 
= g_oglNormalFont
; 
 278   m_textColour 
= wxT("BLACK"); 
 279   m_textColourName 
= wxT("BLACK"); 
 282   m_attachmentMode 
= ATTACHMENT_MODE_NONE
; 
 283   m_spaceAttachments 
= true; 
 284   m_disableLabel 
= false; 
 285   m_fixedWidth 
= false; 
 286   m_fixedHeight 
= false; 
 287   m_drawHandles 
= true; 
 288   m_sensitivity 
= OP_ALL
; 
 291   m_formatMode 
= FORMAT_CENTRE_HORIZ 
| FORMAT_CENTRE_VERT
; 
 292   m_shadowMode 
= SHADOW_NONE
; 
 295   m_shadowBrush 
= wxBLACK_BRUSH
; 
 298   m_regionName 
= wxT("0"); 
 299   m_centreResize 
= true; 
 300   m_maintainAspectRatio 
= false; 
 301   m_highlighted 
= false; 
 303   m_branchNeckLength 
= 10; 
 304   m_branchStemLength 
= 10; 
 305   m_branchSpacing 
= 10; 
 306   m_branchStyle 
= BRANCHING_ATTACHMENT_NORMAL
; 
 308   // Set up a default region. Much of the above will be put into 
 309   // the region eventually (the duplication is for compatibility) 
 310   wxShapeRegion 
*region 
= new wxShapeRegion
; 
 311   m_regions
.Append(region
); 
 312   region
->SetName(wxT("0")); 
 313   region
->SetFont(g_oglNormalFont
); 
 314   region
->SetFormatMode(FORMAT_CENTRE_HORIZ 
| FORMAT_CENTRE_VERT
); 
 315   region
->SetColour(wxT("BLACK")); 
 321     m_parent
->GetChildren().DeleteObject(this); 
 328     m_canvas
->RemoveShape(this); 
 330   GetEventHandler()->OnDelete(); 
 333 void wxShape::SetHighlight(bool hi
, bool recurse
) 
 338     wxNode 
*node 
= m_children
.GetFirst(); 
 341       wxShape 
*child 
= (wxShape 
*)node
->GetData(); 
 342       child
->SetHighlight(hi
, recurse
); 
 343       node 
= node
->GetNext(); 
 348 void wxShape::SetSensitivityFilter(int sens
, bool recursive
) 
 350   if (sens 
& OP_DRAG_LEFT
) 
 355   m_sensitivity 
= sens
; 
 358     wxNode 
*node 
= m_children
.GetFirst(); 
 361       wxShape 
*obj 
= (wxShape 
*)node
->GetData(); 
 362       obj
->SetSensitivityFilter(sens
, true); 
 363       node 
= node
->GetNext(); 
 368 void wxShape::SetDraggable(bool drag
, bool recursive
) 
 372     m_sensitivity 
|= OP_DRAG_LEFT
; 
 374     if (m_sensitivity 
& OP_DRAG_LEFT
) 
 375       m_sensitivity 
= m_sensitivity 
- OP_DRAG_LEFT
; 
 379     wxNode 
*node 
= m_children
.GetFirst(); 
 382       wxShape 
*obj 
= (wxShape 
*)node
->GetData(); 
 383       obj
->SetDraggable(drag
, true); 
 384       node 
= node
->GetNext(); 
 389 void wxShape::SetDrawHandles(bool drawH
) 
 391   m_drawHandles 
= drawH
; 
 392   wxNode 
*node 
= m_children
.GetFirst(); 
 395     wxShape 
*obj 
= (wxShape 
*)node
->GetData(); 
 396     obj
->SetDrawHandles(drawH
); 
 397     node 
= node
->GetNext(); 
 401 void wxShape::SetShadowMode(int mode
, bool redraw
) 
 403   if (redraw 
&& GetCanvas()) 
 405     wxClientDC 
dc(GetCanvas()); 
 406     GetCanvas()->PrepareDC(dc
); 
 419 void wxShape::SetCanvas(wxShapeCanvas 
*theCanvas
) 
 421   m_canvas 
= theCanvas
; 
 422   wxNode 
*node 
= m_children
.GetFirst(); 
 425     wxShape 
*child 
= (wxShape 
*)node
->GetData(); 
 426     child
->SetCanvas(theCanvas
); 
 427     node 
= node
->GetNext(); 
 431 void wxShape::AddToCanvas(wxShapeCanvas 
*theCanvas
, wxShape 
*addAfter
) 
 433   theCanvas
->AddShape(this, addAfter
); 
 434   wxNode 
*node 
= m_children
.GetFirst(); 
 435   wxShape 
*lastImage 
= this; 
 438     wxShape 
*object 
= (wxShape 
*)node
->GetData(); 
 439     object
->AddToCanvas(theCanvas
, lastImage
); 
 442     node 
= node
->GetNext(); 
 446 // Insert at front of canvas 
 447 void wxShape::InsertInCanvas(wxShapeCanvas 
*theCanvas
) 
 449   theCanvas
->InsertShape(this); 
 450   wxNode 
*node 
= m_children
.GetFirst(); 
 451   wxShape 
*lastImage 
= this; 
 454     wxShape 
*object 
= (wxShape 
*)node
->GetData(); 
 455     object
->AddToCanvas(theCanvas
, lastImage
); 
 458     node 
= node
->GetNext(); 
 462 void wxShape::RemoveFromCanvas(wxShapeCanvas 
*theCanvas
) 
 466   theCanvas
->RemoveShape(this); 
 467   wxNode 
*node 
= m_children
.GetFirst(); 
 470     wxShape 
*object 
= (wxShape 
*)node
->GetData(); 
 471     object
->RemoveFromCanvas(theCanvas
); 
 473     node 
= node
->GetNext(); 
 477 void wxShape::ClearAttachments() 
 479   wxNode 
*node 
= m_attachmentPoints
.GetFirst(); 
 482     wxAttachmentPoint 
*point 
= (wxAttachmentPoint 
*)node
->GetData(); 
 484     node 
= node
->GetNext(); 
 486   m_attachmentPoints
.Clear(); 
 489 void wxShape::ClearText(int regionId
) 
 493     m_text
.DeleteContents(true); 
 495     m_text
.DeleteContents(false); 
 497   wxNode 
*node 
= m_regions
.Item(regionId
); 
 500   wxShapeRegion 
*region 
= (wxShapeRegion 
*)node
->GetData(); 
 504 void wxShape::ClearRegions() 
 506   wxNode 
*node 
= m_regions
.GetFirst(); 
 509     wxShapeRegion 
*region 
= (wxShapeRegion 
*)node
->GetData(); 
 510     wxNode 
*next 
= node
->GetNext(); 
 517 void wxShape::AddRegion(wxShapeRegion 
*region
) 
 519   m_regions
.Append(region
); 
 522 void wxShape::SetDefaultRegionSize() 
 524   wxNode 
*node 
= m_regions
.GetFirst(); 
 526   wxShapeRegion 
*region 
= (wxShapeRegion 
*)node
->GetData(); 
 528   GetBoundingBoxMin(&w
, &h
); 
 529   region
->SetSize(w
, h
); 
 532 bool wxShape::HitTest(double x
, double y
, int *attachment
, double *distance
) 
 537   double width 
= 0.0, height 
= 0.0; 
 538   GetBoundingBoxMin(&width
, &height
); 
 539   if (fabs(width
) < 4.0) width 
= 4.0; 
 540   if (fabs(height
) < 4.0) height 
= 4.0; 
 542   width 
+= (double)4.0; height 
+= (double)4.0; // Allowance for inaccurate mousing 
 544   double left 
= (double)(m_xpos 
- (width
/2.0)); 
 545   double top 
= (double)(m_ypos 
- (height
/2.0)); 
 546   double right 
= (double)(m_xpos 
+ (width
/2.0)); 
 547   double bottom 
= (double)(m_ypos 
+ (height
/2.0)); 
 549   int nearest_attachment 
= 0; 
 551   // If within the bounding box, check the attachment points 
 552   // within the object. 
 554   if (x 
>= left 
&& x 
<= right 
&& y 
>= top 
&& y 
<= bottom
) 
 556     int n 
= GetNumberOfAttachments(); 
 557     double nearest 
= 999999.0; 
 559     // GetAttachmentPosition[Edge] takes a logical attachment position, 
 560     // i.e. if it's rotated through 90%, position 0 is East-facing. 
 562     for (int i 
= 0; i 
< n
; i
++) 
 565       if (GetAttachmentPositionEdge(i
, &xp
, &yp
)) 
 567         double l 
= (double)sqrt(((xp 
- x
) * (xp 
- x
)) + 
 568                    ((yp 
- y
) * (yp 
- y
))); 
 573           nearest_attachment 
= i
; 
 577     *attachment 
= nearest_attachment
; 
 584 // Format a text string according to the region size, adding 
 585 // strings with positions to region text list 
 587 static bool GraphicsInSizeToContents 
= false; // Infinite recursion elimination 
 588 void wxShape::FormatText(wxDC
& dc
, const wxString
& s
, int i
) 
 593   if (m_regions
.GetCount() < 1) 
 595   wxNode 
*node 
= m_regions
.Item(i
); 
 599   wxShapeRegion 
*region 
= (wxShapeRegion 
*)node
->GetData(); 
 600   // region->SetText(s);  // don't set the formatted text yet, it will be done below 
 601   region
->m_regionText 
= s
; 
 602   dc
.SetFont(* region
->GetFont()); 
 604   region
->GetSize(&w
, &h
); 
 606   wxStringList 
*stringList 
= oglFormatText(dc
, s
, (w
-2*m_textMarginX
), (h
-2*m_textMarginY
), region
->GetFormatMode()); 
 607   node 
= (wxNode
*)stringList
->GetFirst(); 
 610     wxChar 
*s 
= (wxChar 
*)node
->GetData(); 
 611     wxShapeTextLine 
*line 
= new wxShapeTextLine(0.0, 0.0, s
); 
 612     region
->GetFormattedText().Append((wxObject 
*)line
); 
 613     node 
= node
->GetNext(); 
 618   // Don't try to resize an object with more than one image (this case should be dealt 
 619   // with by overriden handlers) 
 620   if ((region
->GetFormatMode() & FORMAT_SIZE_TO_CONTENTS
) && 
 621       (region
->GetFormattedText().GetCount() > 0) && 
 622       (m_regions
.GetCount() == 1) && !GraphicsInSizeToContents
) 
 624     oglGetCentredTextExtent(dc
, &(region
->GetFormattedText()), m_xpos
, m_ypos
, w
, h
, &actualW
, &actualH
); 
 625     if ((actualW
+2*m_textMarginX 
!= w 
) || (actualH
+2*m_textMarginY 
!= h
)) 
 627       // If we are a descendant of a composite, must make sure the composite gets 
 629       wxShape 
*topAncestor 
= GetTopAncestor(); 
 631       if (topAncestor 
!= this) 
 633         // Make sure we don't recurse infinitely 
 634         GraphicsInSizeToContents 
= true; 
 636         wxCompositeShape 
*composite 
= (wxCompositeShape 
*)topAncestor
; 
 637         composite
->Erase(dc
); 
 638         SetSize(actualW
+2*m_textMarginX
, actualH
+2*m_textMarginY
); 
 639         Move(dc
, m_xpos
, m_ypos
); 
 640         composite
->CalculateSize(); 
 641         if (composite
->Selected()) 
 643           composite
->DeleteControlPoints(& dc
); 
 644           composite
->MakeControlPoints(); 
 645           composite
->MakeMandatoryControlPoints(); 
 647         // Where infinite recursion might happen if we didn't stop it 
 650         GraphicsInSizeToContents 
= false; 
 655         SetSize(actualW
+2*m_textMarginX
, actualH
+2*m_textMarginY
); 
 656         Move(dc
, m_xpos
, m_ypos
); 
 658       SetSize(actualW
+2*m_textMarginX
, actualH
+2*m_textMarginY
); 
 659       Move(dc
, m_xpos
, m_ypos
); 
 663   oglCentreText(dc
, &(region
->GetFormattedText()), m_xpos
, m_ypos
, actualW
-2*m_textMarginX
, actualH
-2*m_textMarginY
, region
->GetFormatMode()); 
 667 void wxShape::Recentre(wxDC
& dc
) 
 670   GetBoundingBoxMin(&w
, &h
); 
 672   int noRegions 
= m_regions
.GetCount(); 
 673   for (int i 
= 0; i 
< noRegions
; i
++) 
 675     wxNode 
*node 
= m_regions
.Item(i
); 
 678       wxShapeRegion 
*region 
= (wxShapeRegion 
*)node
->GetData(); 
 679       oglCentreText(dc
, &(region
->GetFormattedText()), m_xpos
, m_ypos
, w
-2*m_textMarginX
, h
-2*m_textMarginY
, region
->GetFormatMode()); 
 684 bool wxShape::GetPerimeterPoint(double WXUNUSED(x1
), double WXUNUSED(y1
), 
 685                                      double WXUNUSED(x2
), double WXUNUSED(y2
), 
 686                                      double *WXUNUSED(x3
), double *WXUNUSED(y3
)) 
 691 void wxShape::SetPen(wxPen 
*the_pen
) 
 696 void wxShape::SetBrush(wxBrush 
*the_brush
) 
 701 // Get the top-most (non-division) ancestor, or self 
 702 wxShape 
*wxShape::GetTopAncestor() 
 707   if (GetParent()->IsKindOf(CLASSINFO(wxDivisionShape
))) 
 709   else return GetParent()->GetTopAncestor(); 
 716 void wxShape::SetFont(wxFont 
*the_font
, int regionId
) 
 719   wxNode 
*node 
= m_regions
.Item(regionId
); 
 722   wxShapeRegion 
*region 
= (wxShapeRegion 
*)node
->GetData(); 
 723   region
->SetFont(the_font
); 
 726 wxFont 
*wxShape::GetFont(int n
) const 
 728   wxNode 
*node 
= m_regions
.Item(n
); 
 731   wxShapeRegion 
*region 
= (wxShapeRegion 
*)node
->GetData(); 
 732   return region
->GetFont(); 
 735 void wxShape::SetFormatMode(int mode
, int regionId
) 
 737   wxNode 
*node 
= m_regions
.Item(regionId
); 
 740   wxShapeRegion 
*region 
= (wxShapeRegion 
*)node
->GetData(); 
 741   region
->SetFormatMode(mode
); 
 744 int wxShape::GetFormatMode(int regionId
) const 
 746   wxNode 
*node 
= m_regions
.Item(regionId
); 
 749   wxShapeRegion 
*region 
= (wxShapeRegion 
*)node
->GetData(); 
 750   return region
->GetFormatMode(); 
 753 void wxShape::SetTextColour(const wxString
& the_colour
, int regionId
) 
 755   m_textColour 
= wxTheColourDatabase
->Find(the_colour
); 
 756   m_textColourName 
= the_colour
; 
 758   wxNode 
*node 
= m_regions
.Item(regionId
); 
 761   wxShapeRegion 
*region 
= (wxShapeRegion 
*)node
->GetData(); 
 762   region
->SetColour(the_colour
); 
 765 wxString 
wxShape::GetTextColour(int regionId
) const 
 767   wxNode 
*node 
= m_regions
.Item(regionId
); 
 769     return wxEmptyString
; 
 770   wxShapeRegion 
*region 
= (wxShapeRegion 
*)node
->GetData(); 
 771   return region
->GetColour(); 
 774 void wxShape::SetRegionName(const wxString
& name
, int regionId
) 
 776   wxNode 
*node 
= m_regions
.Item(regionId
); 
 779   wxShapeRegion 
*region 
= (wxShapeRegion 
*)node
->GetData(); 
 780   region
->SetName(name
); 
 783 wxString 
wxShape::GetRegionName(int regionId
) 
 785   wxNode 
*node 
= m_regions
.Item(regionId
); 
 787     return wxEmptyString
; 
 788   wxShapeRegion 
*region 
= (wxShapeRegion 
*)node
->GetData(); 
 789   return region
->GetName(); 
 792 int wxShape::GetRegionId(const wxString
& name
) 
 794   wxNode 
*node 
= m_regions
.GetFirst(); 
 798     wxShapeRegion 
*region 
= (wxShapeRegion 
*)node
->GetData(); 
 799     if (region
->GetName() == name
) 
 801     node 
= node
->GetNext(); 
 807 // Name all m_regions in all subimages recursively. 
 808 void wxShape::NameRegions(const wxString
& parentName
) 
 810   int n 
= GetNumberOfTextRegions(); 
 812   for (int i 
= 0; i 
< n
; i
++) 
 814     if (parentName
.Length() > 0) 
 815       buff 
<< parentName 
<< wxT(".") << i
; 
 818     SetRegionName(buff
, i
); 
 820   wxNode 
*node 
= m_children
.GetFirst(); 
 825     wxShape 
*child 
= (wxShape 
*)node
->GetData(); 
 826     if (parentName
.Length() > 0) 
 827       buff 
<< parentName 
<< wxT(".") << j
; 
 830     child
->NameRegions(buff
); 
 831     node 
= node
->GetNext(); 
 836 // Get a region by name, possibly looking recursively into composites. 
 837 wxShape 
*wxShape::FindRegion(const wxString
& name
, int *regionId
) 
 839   int id 
= GetRegionId(name
); 
 846   wxNode 
*node 
= m_children
.GetFirst(); 
 849     wxShape 
*child 
= (wxShape 
*)node
->GetData(); 
 850     wxShape 
*actualImage 
= child
->FindRegion(name
, regionId
); 
 853     node 
= node
->GetNext(); 
 858 // Finds all region names for this image (composite or simple). 
 859 // Supply empty string list. 
 860 void wxShape::FindRegionNames(wxStringList
& list
) 
 862   int n 
= GetNumberOfTextRegions(); 
 863   for (int i 
= 0; i 
< n
; i
++) 
 865     wxString 
name(GetRegionName(i
)); 
 869   wxNode 
*node 
= m_children
.GetFirst(); 
 872     wxShape 
*child 
= (wxShape 
*)node
->GetData(); 
 873     child
->FindRegionNames(list
); 
 874     node 
= node
->GetNext(); 
 878 void wxShape::AssignNewIds() 
 882   wxNode 
*node 
= m_children
.GetFirst(); 
 885     wxShape 
*child 
= (wxShape 
*)node
->GetData(); 
 886     child
->AssignNewIds(); 
 887     node 
= node
->GetNext(); 
 891 void wxShape::OnDraw(wxDC
& WXUNUSED(dc
)) 
 895 void wxShape::OnMoveLinks(wxDC
& dc
) 
 897   // Want to set the ends of all attached links 
 898   // to point to/from this object 
 900   wxNode 
*current 
= m_lines
.GetFirst(); 
 903     wxLineShape 
*line 
= (wxLineShape 
*)current
->GetData(); 
 904     line
->GetEventHandler()->OnMoveLink(dc
); 
 905     current 
= current
->GetNext(); 
 910 void wxShape::OnDrawContents(wxDC
& dc
) 
 912   double bound_x
, bound_y
; 
 913   GetBoundingBoxMin(&bound_x
, &bound_y
); 
 914     if (m_regions
.GetCount() < 1) return; 
 916     if (m_pen
) dc
.SetPen(* m_pen
); 
 918     wxShapeRegion 
*region 
= (wxShapeRegion 
*)m_regions
.GetFirst()->GetData(); 
 919     if (region
->GetFont()) dc
.SetFont(* region
->GetFont()); 
 921     dc
.SetTextForeground(region
->GetActualColourObject()); 
 922     dc
.SetBackgroundMode(wxTRANSPARENT
); 
 925       oglCentreText(dc
, &(region
->GetFormattedText()), m_xpos
, m_ypos
, bound_x
-2*m_textMarginX
, bound_y
-2*m_textMarginY
, region
->GetFormatMode()); 
 928     if (!GetDisableLabel()) 
 930       oglDrawFormattedText(dc
, &(region
->GetFormattedText()), m_xpos
, m_ypos
, bound_x
-2*m_textMarginX
, bound_y
-2*m_textMarginY
, region
->GetFormatMode()); 
 934 void wxShape::DrawContents(wxDC
& dc
) 
 936   GetEventHandler()->OnDrawContents(dc
); 
 939 void wxShape::OnSize(double WXUNUSED(x
), double WXUNUSED(y
)) 
 943 bool wxShape::OnMovePre(wxDC
& WXUNUSED(dc
), double WXUNUSED(x
), double WXUNUSED(y
), double WXUNUSED(old_x
), double WXUNUSED(old_y
), bool WXUNUSED(display
)) 
 948 void wxShape::OnMovePost(wxDC
& WXUNUSED(dc
), double WXUNUSED(x
), double WXUNUSED(y
), double WXUNUSED(old_x
), double WXUNUSED(old_y
), bool WXUNUSED(display
)) 
 952 void wxShape::OnErase(wxDC
& dc
) 
 958   wxNode 
*current 
= m_lines
.GetFirst(); 
 961     wxLineShape 
*line 
= (wxLineShape 
*)current
->GetData(); 
 962     line
->GetEventHandler()->OnErase(dc
); 
 963     current 
= current
->GetNext(); 
 965   GetEventHandler()->OnEraseContents(dc
); 
 968 void wxShape::OnEraseContents(wxDC
& dc
) 
 973   double maxX
, maxY
, minX
, minY
; 
 976   GetBoundingBoxMin(&minX
, &minY
); 
 977   GetBoundingBoxMax(&maxX
, &maxY
); 
 978   double topLeftX 
= (double)(xp 
- (maxX 
/ 2.0) - 2.0); 
 979   double topLeftY 
= (double)(yp 
- (maxY 
/ 2.0) - 2.0); 
 983       penWidth 
= m_pen
->GetWidth(); 
 985     dc
.SetPen(GetBackgroundPen()); 
 986     dc
.SetBrush(GetBackgroundBrush()); 
 988     dc
.DrawRectangle(WXROUND(topLeftX 
- penWidth
), WXROUND(topLeftY 
- penWidth
), 
 989                       WXROUND(maxX 
+ penWidth
*2.0 + 4.0), WXROUND(maxY 
+ penWidth
*2.0 + 4.0)); 
 992 void wxShape::EraseLinks(wxDC
& dc
, int attachment
, bool recurse
) 
 997   wxNode 
*current 
= m_lines
.GetFirst(); 
1000     wxLineShape 
*line 
= (wxLineShape 
*)current
->GetData(); 
1001     if (attachment 
== -1 || ((line
->GetTo() == this && line
->GetAttachmentTo() == attachment
) || 
1002                              (line
->GetFrom() == this && line
->GetAttachmentFrom() == attachment
))) 
1003       line
->GetEventHandler()->OnErase(dc
); 
1004     current 
= current
->GetNext(); 
1008     wxNode 
*node 
= m_children
.GetFirst(); 
1011       wxShape 
*child 
= (wxShape 
*)node
->GetData(); 
1012       child
->EraseLinks(dc
, attachment
, recurse
); 
1013       node 
= node
->GetNext(); 
1018 void wxShape::DrawLinks(wxDC
& dc
, int attachment
, bool recurse
) 
1023   wxNode 
*current 
= m_lines
.GetFirst(); 
1026     wxLineShape 
*line 
= (wxLineShape 
*)current
->GetData(); 
1027     if (attachment 
== -1 || 
1028         (line
->GetTo() == this && line
->GetAttachmentTo() == attachment
) || 
1029         (line
->GetFrom() == this && line
->GetAttachmentFrom() == attachment
)) 
1031     current 
= current
->GetNext(); 
1035     wxNode 
*node 
= m_children
.GetFirst(); 
1038       wxShape 
*child 
= (wxShape 
*)node
->GetData(); 
1039       child
->DrawLinks(dc
, attachment
, recurse
); 
1040       node 
= node
->GetNext(); 
1045 // Returns true if pt1 <= pt2 in the sense that one point comes before another on an 
1046 // edge of the shape. 
1047 // attachmentPoint is the attachment point (= side) in question. 
1049 // This is the default, rectangular implementation. 
1050 bool wxShape::AttachmentSortTest(int attachmentPoint
, const wxRealPoint
& pt1
, const wxRealPoint
& pt2
) 
1052     int physicalAttachment 
= LogicalToPhysicalAttachment(attachmentPoint
); 
1053     switch (physicalAttachment
) 
1058           return (pt1
.x 
<= pt2
.x
) ; 
1063           return (pt1
.y 
<= pt2
.y
) ; 
1070 bool wxShape::MoveLineToNewAttachment(wxDC
& dc
, wxLineShape 
*to_move
, 
1073   if (GetAttachmentMode() == ATTACHMENT_MODE_NONE
) 
1076   int newAttachment
, oldAttachment
; 
1079   // Is (x, y) on this object? If so, find the new attachment point 
1080   // the user has moved the point to 
1081   bool hit 
= HitTest(x
, y
, &newAttachment
, &distance
); 
1087   if (to_move
->GetTo() == this) 
1088     oldAttachment 
= to_move
->GetAttachmentTo(); 
1090     oldAttachment 
= to_move
->GetAttachmentFrom(); 
1092   // The links in a new ordering. 
1095   // First, add all links to the new list. 
1096   wxNode 
*node 
= m_lines
.GetFirst(); 
1099     newOrdering
.Append(node
->GetData()); 
1100     node 
= node
->GetNext(); 
1103   // Delete the line object from the list of links; we're going to move 
1104   // it to another position in the list 
1105   newOrdering
.DeleteObject(to_move
); 
1107   double old_x 
= (double) -99999.9; 
1108   double old_y 
= (double) -99999.9; 
1110   node 
= newOrdering
.GetFirst(); 
1113   while (!found 
&& node
) 
1115     wxLineShape 
*line 
= (wxLineShape 
*)node
->GetData(); 
1116     if ((line
->GetTo() == this && oldAttachment 
== line
->GetAttachmentTo()) || 
1117         (line
->GetFrom() == this && oldAttachment 
== line
->GetAttachmentFrom())) 
1119       double startX
, startY
, endX
, endY
; 
1121       line
->GetEnds(&startX
, &startY
, &endX
, &endY
); 
1122       if (line
->GetTo() == this) 
1132       wxRealPoint 
thisPoint(xp
, yp
); 
1133       wxRealPoint 
lastPoint(old_x
, old_y
); 
1134       wxRealPoint 
newPoint(x
, y
); 
1136       if (AttachmentSortTest(newAttachment
, newPoint
, thisPoint
) && AttachmentSortTest(newAttachment
, lastPoint
, newPoint
)) 
1139         newOrdering
.Insert(node
, to_move
); 
1145     node 
= node
->GetNext(); 
1149     newOrdering
.Append(to_move
); 
1151   GetEventHandler()->OnChangeAttachment(newAttachment
, to_move
, newOrdering
); 
1156 void wxShape::OnChangeAttachment(int attachment
, wxLineShape
* line
, wxList
& ordering
) 
1158     if (line
->GetTo() == this) 
1159         line
->SetAttachmentTo(attachment
); 
1161         line
->SetAttachmentFrom(attachment
); 
1163     ApplyAttachmentOrdering(ordering
); 
1165     wxClientDC 
dc(GetCanvas()); 
1166     GetCanvas()->PrepareDC(dc
); 
1170     if (!GetCanvas()->GetQuickEditMode()) GetCanvas()->Redraw(dc
); 
1173 // Reorders the lines according to the given list. 
1174 void wxShape::ApplyAttachmentOrdering(wxList
& linesToSort
) 
1176   // This is a temporary store of all the lines. 
1179   wxNode 
*node 
= m_lines
.GetFirst(); 
1182     wxLineShape 
*line 
= (wxLineShape 
*)node
->GetData(); 
1183     linesStore
.Append(line
); 
1184     node 
= node
->GetNext();; 
1189   node 
= linesToSort
.GetFirst(); 
1192     wxLineShape 
*line 
= (wxLineShape 
*)node
->GetData(); 
1193     if (linesStore
.Member(line
)) 
1196       linesStore
.DeleteObject(line
); 
1197       m_lines
.Append(line
); 
1199     node 
= node
->GetNext(); 
1202   // Now add any lines that haven't been listed in linesToSort. 
1203   node 
= linesStore
.GetFirst(); 
1206     wxLineShape 
*line 
= (wxLineShape 
*)node
->GetData(); 
1207     m_lines
.Append(line
); 
1208     node 
= node
->GetNext(); 
1212 // Reorders the lines coming into the node image at this attachment 
1213 // position, in the order in which they appear in linesToSort. 
1214 // Any remaining lines not in the list will be added to the end. 
1215 void wxShape::SortLines(int attachment
, wxList
& linesToSort
) 
1217   // This is a temporary store of all the lines at this attachment 
1218   // point. We'll tick them off as we've processed them. 
1219   wxList linesAtThisAttachment
; 
1221   wxNode 
*node 
= m_lines
.GetFirst(); 
1224     wxLineShape 
*line 
= (wxLineShape 
*)node
->GetData(); 
1225     wxNode 
*next 
= node
->GetNext(); 
1226     if ((line
->GetTo() == this && line
->GetAttachmentTo() == attachment
) || 
1227         (line
->GetFrom() == this && line
->GetAttachmentFrom() == attachment
)) 
1229       linesAtThisAttachment
.Append(line
); 
1233     else node 
= node
->GetNext(); 
1236   node 
= linesToSort
.GetFirst(); 
1239     wxLineShape 
*line 
= (wxLineShape 
*)node
->GetData(); 
1240     if (linesAtThisAttachment
.Member(line
)) 
1243       linesAtThisAttachment
.DeleteObject(line
); 
1244       m_lines
.Append(line
); 
1246     node 
= node
->GetNext(); 
1249   // Now add any lines that haven't been listed in linesToSort. 
1250   node 
= linesAtThisAttachment
.GetFirst(); 
1253     wxLineShape 
*line 
= (wxLineShape 
*)node
->GetData(); 
1254     m_lines
.Append(line
); 
1255     node 
= node
->GetNext(); 
1259 void wxShape::OnHighlight(wxDC
& WXUNUSED(dc
)) 
1263 void wxShape::OnLeftClick(double x
, double y
, int keys
, int attachment
) 
1265   if ((m_sensitivity 
& OP_CLICK_LEFT
) != OP_CLICK_LEFT
) 
1271       m_parent
->HitTest(x
, y
, &attachment
, &dist
); 
1272       m_parent
->GetEventHandler()->OnLeftClick(x
, y
, keys
, attachment
); 
1278 void wxShape::OnRightClick(double x
, double y
, int keys
, int attachment
) 
1280   if ((m_sensitivity 
& OP_CLICK_RIGHT
) != OP_CLICK_RIGHT
) 
1286       m_parent
->HitTest(x
, y
, &attachment
, &dist
); 
1287       m_parent
->GetEventHandler()->OnRightClick(x
, y
, keys
, attachment
); 
1293 double DragOffsetX 
= 0.0; 
1294 double DragOffsetY 
= 0.0; 
1296 void wxShape::OnDragLeft(bool draw
, double x
, double y
, int keys
, int attachment
) 
1298   if ((m_sensitivity 
& OP_DRAG_LEFT
) != OP_DRAG_LEFT
) 
1304       m_parent
->HitTest(x
, y
, &attachment
, &dist
); 
1305       m_parent
->GetEventHandler()->OnDragLeft(draw
, x
, y
, keys
, attachment
); 
1310   wxClientDC 
dc(GetCanvas()); 
1311   GetCanvas()->PrepareDC(dc
); 
1313   dc
.SetLogicalFunction(OGLRBLF
); 
1315   wxPen 
dottedPen(*wxBLACK
, 1, wxDOT
); 
1316   dc
.SetPen(dottedPen
); 
1317   dc
.SetBrush(* wxTRANSPARENT_BRUSH
); 
1320   xx 
= x 
+ DragOffsetX
; 
1321   yy 
= y 
+ DragOffsetY
; 
1323   m_canvas
->Snap(&xx
, &yy
); 
1324 //  m_xpos = xx; m_ypos = yy; 
1326   GetBoundingBoxMax(&w
, &h
); 
1327   GetEventHandler()->OnDrawOutline(dc
, xx
, yy
, w
, h
); 
1330 void wxShape::OnBeginDragLeft(double x
, double y
, int keys
, int attachment
) 
1332   if ((m_sensitivity 
& OP_DRAG_LEFT
) != OP_DRAG_LEFT
) 
1338       m_parent
->HitTest(x
, y
, &attachment
, &dist
); 
1339       m_parent
->GetEventHandler()->OnBeginDragLeft(x
, y
, keys
, attachment
); 
1344   DragOffsetX 
= m_xpos 
- x
; 
1345   DragOffsetY 
= m_ypos 
- y
; 
1347   wxClientDC 
dc(GetCanvas()); 
1348   GetCanvas()->PrepareDC(dc
); 
1350   // New policy: don't erase shape until end of drag. 
1354   xx 
= x 
+ DragOffsetX
; 
1355   yy 
= y 
+ DragOffsetY
; 
1356   m_canvas
->Snap(&xx
, &yy
); 
1357 //  m_xpos = xx; m_ypos = yy; 
1358   dc
.SetLogicalFunction(OGLRBLF
); 
1360   wxPen 
dottedPen(*wxBLACK
, 1, wxDOT
); 
1361   dc
.SetPen(dottedPen
); 
1362   dc
.SetBrush((* wxTRANSPARENT_BRUSH
)); 
1365   GetBoundingBoxMax(&w
, &h
); 
1366   GetEventHandler()->OnDrawOutline(dc
, xx
, yy
, w
, h
); 
1367   m_canvas
->CaptureMouse(); 
1370 void wxShape::OnEndDragLeft(double x
, double y
, int keys
, int attachment
) 
1372   m_canvas
->ReleaseMouse(); 
1373   if ((m_sensitivity 
& OP_DRAG_LEFT
) != OP_DRAG_LEFT
) 
1379       m_parent
->HitTest(x
, y
, &attachment
, &dist
); 
1380       m_parent
->GetEventHandler()->OnEndDragLeft(x
, y
, keys
, attachment
); 
1385   wxClientDC 
dc(GetCanvas()); 
1386   GetCanvas()->PrepareDC(dc
); 
1388   dc
.SetLogicalFunction(wxCOPY
); 
1390   double xx 
= x 
+ DragOffsetX
; 
1391   double yy 
= y 
+ DragOffsetY
; 
1392   m_canvas
->Snap(&xx
, &yy
); 
1393 //  canvas->Snap(&m_xpos, &m_ypos); 
1395   // New policy: erase shape at end of drag. 
1399   if (m_canvas 
&& !m_canvas
->GetQuickEditMode()) m_canvas
->Redraw(dc
); 
1402 void wxShape::OnDragRight(bool draw
, double x
, double y
, int keys
, int attachment
) 
1404   if ((m_sensitivity 
& OP_DRAG_RIGHT
) != OP_DRAG_RIGHT
) 
1410       m_parent
->HitTest(x
, y
, &attachment
, &dist
); 
1411       m_parent
->GetEventHandler()->OnDragRight(draw
, x
, y
, keys
, attachment
); 
1417 void wxShape::OnBeginDragRight(double x
, double y
, int keys
, int attachment
) 
1419   if ((m_sensitivity 
& OP_DRAG_RIGHT
) != OP_DRAG_RIGHT
) 
1425       m_parent
->HitTest(x
, y
, &attachment
, &dist
); 
1426       m_parent
->GetEventHandler()->OnBeginDragRight(x
, y
, keys
, attachment
); 
1432 void wxShape::OnEndDragRight(double x
, double y
, int keys
, int attachment
) 
1434   if ((m_sensitivity 
& OP_DRAG_RIGHT
) != OP_DRAG_RIGHT
) 
1440       m_parent
->HitTest(x
, y
, &attachment
, &dist
); 
1441       m_parent
->GetEventHandler()->OnEndDragRight(x
, y
, keys
, attachment
); 
1447 void wxShape::OnDrawOutline(wxDC
& dc
, double x
, double y
, double w
, double h
) 
1449   double top_left_x 
= (double)(x 
- w
/2.0); 
1450   double top_left_y 
= (double)(y 
- h
/2.0); 
1451   double top_right_x 
= (double)(top_left_x 
+ w
); 
1452   double top_right_y 
= (double)top_left_y
; 
1453   double bottom_left_x 
= (double)top_left_x
; 
1454   double bottom_left_y 
= (double)(top_left_y 
+ h
); 
1455   double bottom_right_x 
= (double)top_right_x
; 
1456   double bottom_right_y 
= (double)bottom_left_y
; 
1459   points
[0].x 
= WXROUND(top_left_x
); points
[0].y 
= WXROUND(top_left_y
); 
1460   points
[1].x 
= WXROUND(top_right_x
); points
[1].y 
= WXROUND(top_right_y
); 
1461   points
[2].x 
= WXROUND(bottom_right_x
); points
[2].y 
= WXROUND(bottom_right_y
); 
1462   points
[3].x 
= WXROUND(bottom_left_x
); points
[3].y 
= WXROUND(bottom_left_y
); 
1463   points
[4].x 
= WXROUND(top_left_x
); points
[4].y 
= WXROUND(top_left_y
); 
1465   dc
.DrawLines(5, points
); 
1468 void wxShape::Attach(wxShapeCanvas 
*can
) 
1473 void wxShape::Detach() 
1478 void wxShape::Move(wxDC
& dc
, double x
, double y
, bool display
) 
1480   double old_x 
= m_xpos
; 
1481   double old_y 
= m_ypos
; 
1483   if (!GetEventHandler()->OnMovePre(dc
, x
, y
, old_x
, old_y
, display
)) 
1490   m_xpos 
= x
; m_ypos 
= y
; 
1492   ResetControlPoints(); 
1499   GetEventHandler()->OnMovePost(dc
, x
, y
, old_x
, old_y
, display
); 
1502 void wxShape::MoveLinks(wxDC
& dc
) 
1504   GetEventHandler()->OnMoveLinks(dc
); 
1508 void wxShape::Draw(wxDC
& dc
) 
1512     GetEventHandler()->OnDraw(dc
); 
1513     GetEventHandler()->OnDrawContents(dc
); 
1514     GetEventHandler()->OnDrawControlPoints(dc
); 
1515     GetEventHandler()->OnDrawBranches(dc
); 
1519 void wxShape::Flash() 
1523         wxClientDC 
dc(GetCanvas()); 
1524         GetCanvas()->PrepareDC(dc
); 
1526         dc
.SetLogicalFunction(OGLRBLF
); 
1528         dc
.SetLogicalFunction(wxCOPY
); 
1533 void wxShape::Show(bool show
) 
1536   wxNode 
*node 
= m_children
.GetFirst(); 
1539     wxShape 
*image 
= (wxShape 
*)node
->GetData(); 
1541     node 
= node
->GetNext(); 
1545 void wxShape::Erase(wxDC
& dc
) 
1547   GetEventHandler()->OnErase(dc
); 
1548   GetEventHandler()->OnEraseControlPoints(dc
); 
1549   GetEventHandler()->OnDrawBranches(dc
, true); 
1552 void wxShape::EraseContents(wxDC
& dc
) 
1554   GetEventHandler()->OnEraseContents(dc
); 
1557 void wxShape::AddText(const wxString
& string
) 
1559   wxNode 
*node 
= m_regions
.GetFirst(); 
1562   wxShapeRegion 
*region 
= (wxShapeRegion 
*)node
->GetData(); 
1563   region
->ClearText(); 
1564   wxShapeTextLine 
*new_line 
= 
1565       new wxShapeTextLine(0.0, 0.0, string
); 
1566   region
->GetFormattedText().Append(new_line
); 
1568   m_formatted 
= false; 
1571 void wxShape::SetSize(double x
, double y
, bool WXUNUSED(recursive
)) 
1573   SetAttachmentSize(x
, y
); 
1574   SetDefaultRegionSize(); 
1577 void wxShape::SetAttachmentSize(double w
, double h
) 
1581   double width
, height
; 
1582   GetBoundingBoxMin(&width
, &height
); 
1585   else scaleX 
= w
/width
; 
1588   else scaleY 
= h
/height
; 
1590   wxNode 
*node 
= m_attachmentPoints
.GetFirst(); 
1593     wxAttachmentPoint 
*point 
= (wxAttachmentPoint 
*)node
->GetData(); 
1594     point
->m_x 
= (double)(point
->m_x 
* scaleX
); 
1595     point
->m_y 
= (double)(point
->m_y 
* scaleY
); 
1596     node 
= node
->GetNext(); 
1600 // Add line FROM this object 
1601 void wxShape::AddLine(wxLineShape 
*line
, wxShape 
*other
, 
1602                             int attachFrom
, int attachTo
, 
1603                             // The line ordering 
1604                             int positionFrom
, int positionTo
) 
1606     if (positionFrom 
== -1) 
1608         if (!m_lines
.Member(line
)) 
1609             m_lines
.Append(line
); 
1613         // Don't preserve old ordering if we have new ordering instructions 
1614         m_lines
.DeleteObject(line
); 
1615         if (positionFrom 
< (int) m_lines
.GetCount()) 
1617             wxNode
* node 
= m_lines
.Item(positionFrom
); 
1618             m_lines
.Insert(node
, line
); 
1621             m_lines
.Append(line
); 
1624     if (positionTo 
== -1) 
1626         if (!other
->m_lines
.Member(line
)) 
1627             other
->m_lines
.Append(line
); 
1631         // Don't preserve old ordering if we have new ordering instructions 
1632         other
->m_lines
.DeleteObject(line
); 
1633         if (positionTo 
< (int) other
->m_lines
.GetCount()) 
1635             wxNode
* node 
= other
->m_lines
.Item(positionTo
); 
1636             other
->m_lines
.Insert(node
, line
); 
1639             other
->m_lines
.Append(line
); 
1642     // Wrong: doesn't preserve ordering of shape already linked 
1643     m_lines
.DeleteObject(line
); 
1644     other
->m_lines
.DeleteObject(line
); 
1646     if (positionFrom 
== -1) 
1647         m_lines
.Append(line
); 
1650         if (positionFrom 
< m_lines
.GetCount()) 
1652             wxNode
* node 
= m_lines
.Item(positionFrom
); 
1653             m_lines
.Insert(node
, line
); 
1656             m_lines
.Append(line
); 
1659     if (positionTo 
== -1) 
1660         other
->m_lines
.Append(line
); 
1663         if (positionTo 
< other
->m_lines
.GetCount()) 
1665             wxNode
* node 
= other
->m_lines
.Item(positionTo
); 
1666             other
->m_lines
.Insert(node
, line
); 
1669             other
->m_lines
.Append(line
); 
1673     line
->SetFrom(this); 
1675     line
->SetAttachments(attachFrom
, attachTo
); 
1678 void wxShape::RemoveLine(wxLineShape 
*line
) 
1680   if (line
->GetFrom() == this) 
1681     line
->GetTo()->m_lines
.DeleteObject(line
); 
1683    line
->GetFrom()->m_lines
.DeleteObject(line
); 
1685   m_lines
.DeleteObject(line
); 
1689 void wxShape::WriteAttributes(wxExpr 
*clause
) 
1691   clause
->AddAttributeValueString(_T("type"), GetClassInfo()->GetClassName()); 
1692   clause
->AddAttributeValue(_T("id"), m_id
); 
1696     int penWidth 
= m_pen
->GetWidth(); 
1697     int penStyle 
= m_pen
->GetStyle(); 
1699       clause
->AddAttributeValue(_T("pen_width"), (long)penWidth
); 
1700     if (penStyle 
!= wxSOLID
) 
1701       clause
->AddAttributeValue(_T("pen_style"), (long)penStyle
); 
1703     wxString penColour 
= wxTheColourDatabase
->FindName(m_pen
->GetColour()); 
1704     if (penColour 
== wxEmptyString
) 
1706       wxString 
hex(oglColourToHex(m_pen
->GetColour())); 
1707       hex 
= wxString(_T("#")) + hex
; 
1708       clause
->AddAttributeValueString(_T("pen_colour"), hex
); 
1710     else if (penColour 
!= _T("BLACK")) 
1711       clause
->AddAttributeValueString(_T("pen_colour"), penColour
); 
1716     wxString brushColour 
= wxTheColourDatabase
->FindName(m_brush
->GetColour()); 
1718     if (brushColour 
== wxEmptyString
) 
1720       wxString 
hex(oglColourToHex(m_brush
->GetColour())); 
1721       hex 
= wxString(_T("#")) + hex
; 
1722       clause
->AddAttributeValueString(_T("brush_colour"), hex
); 
1724     else if (brushColour 
!= _T("WHITE")) 
1725       clause
->AddAttributeValueString(_T("brush_colour"), brushColour
); 
1727     if (m_brush
->GetStyle() != wxSOLID
) 
1728       clause
->AddAttributeValue(_T("brush_style"), (long)m_brush
->GetStyle()); 
1733   int n_lines 
= m_lines
.GetCount(); 
1736     wxExpr 
*list 
= new wxExpr(wxExprList
); 
1737     wxNode 
*node 
= m_lines
.GetFirst(); 
1740       wxShape 
*line 
= (wxShape 
*)node
->GetData(); 
1741       wxExpr 
*id_expr 
= new wxExpr(line
->GetId()); 
1742       list
->Append(id_expr
); 
1743       node 
= node
->GetNext(); 
1745     clause
->AddAttributeValue(_T("arcs"), list
); 
1748   // Miscellaneous members 
1749   if (m_attachmentMode 
!= 0) 
1750     clause
->AddAttributeValue(_T("use_attachments"), (long)m_attachmentMode
); 
1751   if (m_sensitivity 
!= OP_ALL
) 
1752     clause
->AddAttributeValue(_T("sensitivity"), (long)m_sensitivity
); 
1753   if (!m_spaceAttachments
) 
1754     clause
->AddAttributeValue(_T("space_attachments"), (long)m_spaceAttachments
); 
1756     clause
->AddAttributeValue(_T("fixed_width"), (long)m_fixedWidth
); 
1758     clause
->AddAttributeValue(_T("fixed_height"), (long)m_fixedHeight
); 
1759   if (m_shadowMode 
!= SHADOW_NONE
) 
1760     clause
->AddAttributeValue(_T("shadow_mode"), (long)m_shadowMode
); 
1761   if (m_centreResize 
!= true) 
1762     clause
->AddAttributeValue(_T("centre_resize"), (long)0); 
1763   clause
->AddAttributeValue(_T("maintain_aspect_ratio"), (long) m_maintainAspectRatio
); 
1764   if (m_highlighted 
!= false) 
1765     clause
->AddAttributeValue(_T("hilite"), (long)m_highlighted
); 
1767   if (m_parent
) // For composite objects 
1768     clause
->AddAttributeValue(_T("parent"), (long)m_parent
->GetId()); 
1770   if (m_rotation 
!= 0.0) 
1771     clause
->AddAttributeValue(_T("rotation"), m_rotation
); 
1773   if (!this->IsKindOf(CLASSINFO(wxLineShape
))) 
1775     clause
->AddAttributeValue(_T("neck_length"), (long) m_branchNeckLength
); 
1776     clause
->AddAttributeValue(_T("stem_length"), (long) m_branchStemLength
); 
1777     clause
->AddAttributeValue(_T("branch_spacing"), (long) m_branchSpacing
); 
1778     clause
->AddAttributeValue(_T("branch_style"), (long) m_branchStyle
); 
1781   // Write user-defined attachment points, if any 
1782   if (m_attachmentPoints
.GetCount() > 0) 
1784     wxExpr 
*attachmentList 
= new wxExpr(wxExprList
); 
1785     wxNode 
*node 
= m_attachmentPoints
.GetFirst(); 
1788       wxAttachmentPoint 
*point 
= (wxAttachmentPoint 
*)node
->GetData(); 
1789       wxExpr 
*pointExpr 
= new wxExpr(wxExprList
); 
1790       pointExpr
->Append(new wxExpr((long)point
->m_id
)); 
1791       pointExpr
->Append(new wxExpr(point
->m_x
)); 
1792       pointExpr
->Append(new wxExpr(point
->m_y
)); 
1793       attachmentList
->Append(pointExpr
); 
1794       node 
= node
->GetNext(); 
1796     clause
->AddAttributeValue(_T("user_attachments"), attachmentList
); 
1799   // Write text regions 
1800   WriteRegions(clause
); 
1803 void wxShape::WriteRegions(wxExpr 
*clause
) 
1805   // Output regions as region1 = (...), region2 = (...), etc 
1806   // and formatted text as text1 = (...), text2 = (...) etc. 
1808   wxChar regionNameBuf
[20]; 
1809   wxChar textNameBuf
[20]; 
1810   wxNode 
*node 
= m_regions
.GetFirst(); 
1813     wxShapeRegion 
*region 
= (wxShapeRegion 
*)node
->GetData(); 
1814     wxSprintf(regionNameBuf
, _T("region%d"), regionNo
); 
1815     wxSprintf(textNameBuf
, _T("text%d"), regionNo
); 
1817     // Original text and region attributes: 
1818     // region1 = (regionName regionText x y width height minWidth minHeight proportionX proportionY 
1819     //            formatMode fontSize fontFamily fontStyle fontWeight textColour) 
1820     wxExpr 
*regionExpr 
= new wxExpr(wxExprList
); 
1821     regionExpr
->Append(new wxExpr(wxExprString
, region
->m_regionName
)); 
1822     regionExpr
->Append(new wxExpr(wxExprString
, region
->m_regionText
)); 
1824     regionExpr
->Append(new wxExpr(region
->m_x
)); 
1825     regionExpr
->Append(new wxExpr(region
->m_y
)); 
1826     regionExpr
->Append(new wxExpr(region
->GetWidth())); 
1827     regionExpr
->Append(new wxExpr(region
->GetHeight())); 
1829     regionExpr
->Append(new wxExpr(region
->m_minWidth
)); 
1830     regionExpr
->Append(new wxExpr(region
->m_minHeight
)); 
1831     regionExpr
->Append(new wxExpr(region
->m_regionProportionX
)); 
1832     regionExpr
->Append(new wxExpr(region
->m_regionProportionY
)); 
1834     regionExpr
->Append(new wxExpr((long)region
->m_formatMode
)); 
1836     regionExpr
->Append(new wxExpr((long)(region
->m_font 
? region
->m_font
->GetPointSize() : 10))); 
1837     regionExpr
->Append(new wxExpr((long)(region
->m_font 
? region
->m_font
->GetFamily() : wxDEFAULT
))); 
1838     regionExpr
->Append(new wxExpr((long)(region
->m_font 
? region
->m_font
->GetStyle() : wxDEFAULT
))); 
1839     regionExpr
->Append(new wxExpr((long)(region
->m_font 
? region
->m_font
->GetWeight() : wxNORMAL
))); 
1840     regionExpr
->Append(new wxExpr(wxExprString
, region
->m_textColour
)); 
1842     // New members for pen colour/style 
1843     regionExpr
->Append(new wxExpr(wxExprString
, region
->m_penColour
)); 
1844     regionExpr
->Append(new wxExpr((long)region
->m_penStyle
)); 
1847     // text1 = ((x y string) (x y string) ...) 
1848     wxExpr 
*textExpr 
= new wxExpr(wxExprList
); 
1850     wxNode 
*textNode 
= region
->m_formattedText
.GetFirst(); 
1853       wxShapeTextLine 
*line 
= (wxShapeTextLine 
*)textNode
->GetData(); 
1854       wxExpr 
*list2 
= new wxExpr(wxExprList
); 
1855       list2
->Append(new wxExpr(line
->GetX())); 
1856       list2
->Append(new wxExpr(line
->GetY())); 
1857       list2
->Append(new wxExpr(wxExprString
, line
->GetText())); 
1858       textExpr
->Append(list2
); 
1859       textNode 
= textNode
->GetNext(); 
1862     // Now add both attributes to the clause 
1863     clause
->AddAttributeValue(regionNameBuf
, regionExpr
); 
1864     clause
->AddAttributeValue(textNameBuf
, textExpr
); 
1866     node 
= node
->GetNext(); 
1871 void wxShape::ReadAttributes(wxExpr 
*clause
) 
1873   clause
->GetAttributeValue(_T("id"), m_id
); 
1876   clause
->GetAttributeValue(_T("x"), m_xpos
); 
1877   clause
->GetAttributeValue(_T("y"), m_ypos
); 
1879   // Input text strings (FOR COMPATIBILITY WITH OLD FILES ONLY. SEE REGION CODE BELOW.) 
1881   wxExpr 
*strings 
= clause
->AttributeValue(_T("text")); 
1882   if (strings 
&& strings
->Type() == wxExprList
) 
1884     m_formatted 
= true;  // Assume text is formatted unless we prove otherwise 
1885     wxExpr 
*node 
= strings
->value
.first
; 
1888       wxExpr 
*string_expr 
= node
; 
1891       wxString the_string 
= wxEmptyString
; 
1893       // string_expr can either be a string, or a list of 
1894       // 3 elements: x, y, and string. 
1895       if (string_expr
->Type() == wxExprString
) 
1897         the_string 
= string_expr
->StringValue(); 
1898         m_formatted 
= false; 
1900       else if (string_expr
->Type() == wxExprList
) 
1902         wxExpr 
*first 
= string_expr
->value
.first
; 
1903         wxExpr 
*second 
= first 
? first
->next 
: (wxExpr
*) NULL
; 
1904         wxExpr 
*third 
= second 
? second
->next 
: (wxExpr
*) NULL
; 
1906         if (first 
&& second 
&& third 
&& 
1907             (first
->Type() == wxExprReal 
|| first
->Type() == wxExprInteger
) && 
1908             (second
->Type() == wxExprReal 
|| second
->Type() == wxExprInteger
) && 
1909             third
->Type() == wxExprString
) 
1911             if (first
->Type() == wxExprReal
) 
1912               the_x 
= first
->RealValue(); 
1913             else the_x 
= (double)first
->IntegerValue(); 
1915             if (second
->Type() == wxExprReal
) 
1916               the_y 
= second
->RealValue(); 
1917             else the_y 
= (double)second
->IntegerValue(); 
1919             the_string 
= third
->StringValue(); 
1922       wxShapeTextLine 
*line 
= 
1923             new wxShapeTextLine(the_x
, the_y
, the_string
); 
1924       m_text
.Append(line
); 
1930   wxString pen_string 
= wxEmptyString
; 
1931   wxString brush_string 
= wxEmptyString
; 
1933   int pen_style 
= wxSOLID
; 
1934   int brush_style 
= wxSOLID
; 
1935   m_attachmentMode 
= ATTACHMENT_MODE_NONE
; 
1937   clause
->GetAttributeValue(_T("pen_colour"), pen_string
); 
1938   clause
->GetAttributeValue(_T("text_colour"), m_textColourName
); 
1940   SetTextColour(m_textColourName
); 
1942   clause
->GetAttributeValue(_T("region_name"), m_regionName
); 
1944   clause
->GetAttributeValue(_T("brush_colour"), brush_string
); 
1945   clause
->GetAttributeValue(_T("pen_width"), pen_width
); 
1946   clause
->GetAttributeValue(_T("pen_style"), pen_style
); 
1947   clause
->GetAttributeValue(_T("brush_style"), brush_style
); 
1949   int iVal 
= (int) m_attachmentMode
; 
1950   clause
->GetAttributeValue(_T("use_attachments"), iVal
); 
1951   m_attachmentMode 
= iVal
; 
1953   clause
->GetAttributeValue(_T("sensitivity"), m_sensitivity
); 
1955   iVal 
= (int) m_spaceAttachments
; 
1956   clause
->GetAttributeValue(_T("space_attachments"), iVal
); 
1957   m_spaceAttachments 
= (iVal 
!= 0); 
1959   iVal 
= (int) m_fixedWidth
; 
1960   clause
->GetAttributeValue(_T("fixed_width"), iVal
); 
1961   m_fixedWidth 
= (iVal 
!= 0); 
1963   iVal 
= (int) m_fixedHeight
; 
1964   clause
->GetAttributeValue(_T("fixed_height"), iVal
); 
1965   m_fixedHeight 
= (iVal 
!= 0); 
1967   clause
->GetAttributeValue(_T("format_mode"), m_formatMode
); 
1968   clause
->GetAttributeValue(_T("shadow_mode"), m_shadowMode
); 
1970   iVal 
= m_branchNeckLength
; 
1971   clause
->GetAttributeValue(_T("neck_length"), iVal
); 
1972   m_branchNeckLength 
= iVal
; 
1974   iVal 
= m_branchStemLength
; 
1975   clause
->GetAttributeValue(_T("stem_length"), iVal
); 
1976   m_branchStemLength 
= iVal
; 
1978   iVal 
= m_branchSpacing
; 
1979   clause
->GetAttributeValue(_T("branch_spacing"), iVal
); 
1980   m_branchSpacing 
= iVal
; 
1982   clause
->GetAttributeValue(_T("branch_style"), m_branchStyle
); 
1984   iVal 
= (int) m_centreResize
; 
1985   clause
->GetAttributeValue(_T("centre_resize"), iVal
); 
1986   m_centreResize 
= (iVal 
!= 0); 
1988   iVal 
= (int) m_maintainAspectRatio
; 
1989   clause
->GetAttributeValue(_T("maintain_aspect_ratio"), iVal
); 
1990   m_maintainAspectRatio 
= (iVal 
!= 0); 
1992   iVal 
= (int) m_highlighted
; 
1993   clause
->GetAttributeValue(_T("hilite"), iVal
); 
1994   m_highlighted 
= (iVal 
!= 0); 
1996   clause
->GetAttributeValue(_T("rotation"), m_rotation
); 
1998   if (pen_string 
== wxEmptyString
) 
1999     pen_string 
= _T("BLACK"); 
2000   if (brush_string 
== wxEmptyString
) 
2001     brush_string 
= _T("WHITE"); 
2003   if (pen_string
.GetChar(0) == '#') 
2005     wxColour 
col(oglHexToColour(pen_string
.After('#'))); 
2006     m_pen 
= wxThePenList
->FindOrCreatePen(col
, pen_width
, pen_style
); 
2009     m_pen 
= wxThePenList
->FindOrCreatePen(pen_string
, pen_width
, pen_style
); 
2012     m_pen 
= wxBLACK_PEN
; 
2014   if (brush_string
.GetChar(0) == '#') 
2016     wxColour 
col(oglHexToColour(brush_string
.After('#'))); 
2017     m_brush 
= wxTheBrushList
->FindOrCreateBrush(col
, brush_style
); 
2020     m_brush 
= wxTheBrushList
->FindOrCreateBrush(brush_string
, brush_style
); 
2023     m_brush 
= wxWHITE_BRUSH
; 
2025   int point_size 
= 10; 
2026   clause
->GetAttributeValue(_T("point_size"), point_size
); 
2027   SetFont(oglMatchFont(point_size
)); 
2029   // Read user-defined attachment points, if any 
2030   wxExpr 
*attachmentList 
= clause
->AttributeValue(_T("user_attachments")); 
2033     wxExpr 
*pointExpr 
= attachmentList
->GetFirst(); 
2036       wxExpr 
*idExpr 
= pointExpr
->Nth(0); 
2037       wxExpr 
*xExpr 
= pointExpr
->Nth(1); 
2038       wxExpr 
*yExpr 
= pointExpr
->Nth(2); 
2039       if (idExpr 
&& xExpr 
&& yExpr
) 
2041         wxAttachmentPoint 
*point 
= new wxAttachmentPoint
; 
2042         point
->m_id 
= (int)idExpr
->IntegerValue(); 
2043         point
->m_x 
= xExpr
->RealValue(); 
2044         point
->m_y 
= yExpr
->RealValue(); 
2045         m_attachmentPoints
.Append((wxObject 
*)point
); 
2047       pointExpr 
= pointExpr
->GetNext(); 
2051   // Read text regions 
2052   ReadRegions(clause
); 
2055 void wxShape::ReadRegions(wxExpr 
*clause
) 
2059   // region1 = (regionName regionText x y width height minWidth minHeight proportionX proportionY 
2060   //            formatMode fontSize fontFamily fontStyle fontWeight textColour) 
2062   wxChar regionNameBuf
[20]; 
2063   wxChar textNameBuf
[20]; 
2066   wxExpr 
*textExpr 
= NULL
; 
2067   wxSprintf(regionNameBuf
, _T("region%d"), regionNo
); 
2068   wxSprintf(textNameBuf
, _T("text%d"), regionNo
); 
2070   m_formatted 
= true;  // Assume text is formatted unless we prove otherwise 
2072   while ((regionExpr 
= clause
->AttributeValue(regionNameBuf
)) != NULL
) 
2075      * Get the region information 
2079     wxString regionName 
= wxEmptyString
; 
2080     wxString regionText 
= wxEmptyString
; 
2084     double height 
= 0.0; 
2085     double minWidth 
= 5.0; 
2086     double minHeight 
= 5.0; 
2087     double m_regionProportionX 
= -1.0; 
2088     double m_regionProportionY 
= -1.0; 
2089     int formatMode 
= FORMAT_NONE
; 
2091     int fontFamily 
= wxSWISS
; 
2092     int fontStyle 
= wxNORMAL
; 
2093     int fontWeight 
= wxNORMAL
; 
2094     wxString regionTextColour 
= wxEmptyString
; 
2095     wxString penColour 
= wxEmptyString
; 
2096     int penStyle 
= wxSOLID
; 
2098     if (regionExpr
->Type() == wxExprList
) 
2100       wxExpr 
*nameExpr 
= regionExpr
->Nth(0); 
2101       wxExpr 
*textExpr 
= regionExpr
->Nth(1); 
2102       wxExpr 
*xExpr 
= regionExpr
->Nth(2); 
2103       wxExpr 
*yExpr 
= regionExpr
->Nth(3); 
2104       wxExpr 
*widthExpr 
= regionExpr
->Nth(4); 
2105       wxExpr 
*heightExpr 
= regionExpr
->Nth(5); 
2106       wxExpr 
*minWidthExpr 
= regionExpr
->Nth(6); 
2107       wxExpr 
*minHeightExpr 
= regionExpr
->Nth(7); 
2108       wxExpr 
*propXExpr 
= regionExpr
->Nth(8); 
2109       wxExpr 
*propYExpr 
= regionExpr
->Nth(9); 
2110       wxExpr 
*formatExpr 
= regionExpr
->Nth(10); 
2111       wxExpr 
*sizeExpr 
= regionExpr
->Nth(11); 
2112       wxExpr 
*familyExpr 
= regionExpr
->Nth(12); 
2113       wxExpr 
*styleExpr 
= regionExpr
->Nth(13); 
2114       wxExpr 
*weightExpr 
= regionExpr
->Nth(14); 
2115       wxExpr 
*colourExpr 
= regionExpr
->Nth(15); 
2116       wxExpr 
*penColourExpr 
= regionExpr
->Nth(16); 
2117       wxExpr 
*penStyleExpr 
= regionExpr
->Nth(17); 
2119       regionName 
= nameExpr
->StringValue(); 
2120       regionText 
= textExpr
->StringValue(); 
2122       x 
= xExpr
->RealValue(); 
2123       y 
= yExpr
->RealValue(); 
2125       width 
= widthExpr
->RealValue(); 
2126       height 
= heightExpr
->RealValue(); 
2128       minWidth 
= minWidthExpr
->RealValue(); 
2129       minHeight 
= minHeightExpr
->RealValue(); 
2131       m_regionProportionX 
= propXExpr
->RealValue(); 
2132       m_regionProportionY 
= propYExpr
->RealValue(); 
2134       formatMode 
= (int) formatExpr
->IntegerValue(); 
2135       fontSize 
= (int)sizeExpr
->IntegerValue(); 
2136       fontFamily 
= (int)familyExpr
->IntegerValue(); 
2137       fontStyle 
= (int)styleExpr
->IntegerValue(); 
2138       fontWeight 
= (int)weightExpr
->IntegerValue(); 
2142         regionTextColour 
= colourExpr
->StringValue(); 
2145         regionTextColour 
= _T("BLACK"); 
2148         penColour 
= penColourExpr
->StringValue(); 
2150         penStyle 
= (int)penStyleExpr
->IntegerValue(); 
2152     wxFont 
*font 
= wxTheFontList
->FindOrCreateFont(fontSize
, fontFamily
, fontStyle
, fontWeight
); 
2154     wxShapeRegion 
*region 
= new wxShapeRegion
; 
2155     region
->SetProportions(m_regionProportionX
, m_regionProportionY
); 
2156     region
->SetFont(font
); 
2157     region
->SetSize(width
, height
); 
2158     region
->SetPosition(x
, y
); 
2159     region
->SetMinSize(minWidth
, minHeight
); 
2160     region
->SetFormatMode(formatMode
); 
2161     region
->SetPenStyle(penStyle
); 
2162     if (penColour 
!= wxEmptyString
) 
2163       region
->SetPenColour(penColour
); 
2165     region
->m_textColour 
= regionTextColour
; 
2166     region
->m_regionText 
= regionText
; 
2167     region
->m_regionName 
= regionName
; 
2169     m_regions
.Append(region
); 
2172      * Get the formatted text strings 
2175     textExpr 
= clause
->AttributeValue(textNameBuf
); 
2176     if (textExpr 
&& (textExpr
->Type() == wxExprList
)) 
2178       wxExpr 
*node 
= textExpr
->value
.first
; 
2181         wxExpr 
*string_expr 
= node
; 
2184         wxString the_string 
= wxEmptyString
; 
2186         // string_expr can either be a string, or a list of 
2187         // 3 elements: x, y, and string. 
2188         if (string_expr
->Type() == wxExprString
) 
2190           the_string 
= string_expr
->StringValue(); 
2191           m_formatted 
= false; 
2193         else if (string_expr
->Type() == wxExprList
) 
2195           wxExpr 
*first 
= string_expr
->value
.first
; 
2196           wxExpr 
*second 
= first 
? first
->next 
: (wxExpr
*) NULL
; 
2197           wxExpr 
*third 
= second 
? second
->next 
: (wxExpr
*) NULL
; 
2199           if (first 
&& second 
&& third 
&& 
2200               (first
->Type() == wxExprReal 
|| first
->Type() == wxExprInteger
) && 
2201               (second
->Type() == wxExprReal 
|| second
->Type() == wxExprInteger
) && 
2202               third
->Type() == wxExprString
) 
2204             if (first
->Type() == wxExprReal
) 
2205               the_x 
= first
->RealValue(); 
2206             else the_x 
= (double)first
->IntegerValue(); 
2208             if (second
->Type() == wxExprReal
) 
2209               the_y 
= second
->RealValue(); 
2210             else the_y 
= (double)second
->IntegerValue(); 
2212             the_string 
= third
->StringValue(); 
2217           wxShapeTextLine 
*line 
= 
2218               new wxShapeTextLine(the_x
, the_y
, the_string
); 
2219           region
->m_formattedText
.Append(line
); 
2226     wxSprintf(regionNameBuf
, _T("region%d"), regionNo
); 
2227     wxSprintf(textNameBuf
, _T("text%d"), regionNo
); 
2230   // Compatibility: check for no regions (old file). 
2231   // Lines and divided rectangles must deal with this compatibility 
2232   // theirselves. Composites _may_ not have any regions anyway. 
2233   if ((m_regions
.GetCount() == 0) && 
2234       !this->IsKindOf(CLASSINFO(wxLineShape
)) && !this->IsKindOf(CLASSINFO(wxDividedShape
)) && 
2235       !this->IsKindOf(CLASSINFO(wxCompositeShape
))) 
2237     wxShapeRegion 
*newRegion 
= new wxShapeRegion
; 
2238     newRegion
->SetName(_T("0")); 
2239     m_regions
.Append((wxObject 
*)newRegion
); 
2240     if (m_text
.GetCount() > 0) 
2242       newRegion
->ClearText(); 
2243       wxNode 
*node 
= m_text
.GetFirst(); 
2246         wxShapeTextLine 
*textLine 
= (wxShapeTextLine 
*)node
->GetData(); 
2247         wxNode 
*next 
= node
->GetNext(); 
2248         newRegion
->GetFormattedText().Append((wxObject 
*)textLine
); 
2258 void wxShape::Copy(wxShape
& copy
) 
2261   copy
.m_xpos 
= m_xpos
; 
2262   copy
.m_ypos 
= m_ypos
; 
2264   copy
.m_brush 
= m_brush
; 
2265   copy
.m_textColour 
= m_textColour
; 
2266   copy
.m_centreResize 
= m_centreResize
; 
2267   copy
.m_maintainAspectRatio 
= m_maintainAspectRatio
; 
2268   copy
.m_attachmentMode 
= m_attachmentMode
; 
2269   copy
.m_spaceAttachments 
= m_spaceAttachments
; 
2270   copy
.m_highlighted 
= m_highlighted
; 
2271   copy
.m_rotation 
= m_rotation
; 
2272   copy
.m_textColourName 
= m_textColourName
; 
2273   copy
.m_regionName 
= m_regionName
; 
2275   copy
.m_sensitivity 
= m_sensitivity
; 
2276   copy
.m_draggable 
= m_draggable
; 
2277   copy
.m_fixedWidth 
= m_fixedWidth
; 
2278   copy
.m_fixedHeight 
= m_fixedHeight
; 
2279   copy
.m_formatMode 
= m_formatMode
; 
2280   copy
.m_drawHandles 
= m_drawHandles
; 
2282   copy
.m_visible 
= m_visible
; 
2283   copy
.m_shadowMode 
= m_shadowMode
; 
2284   copy
.m_shadowOffsetX 
= m_shadowOffsetX
; 
2285   copy
.m_shadowOffsetY 
= m_shadowOffsetY
; 
2286   copy
.m_shadowBrush 
= m_shadowBrush
; 
2288   copy
.m_branchNeckLength 
= m_branchNeckLength
; 
2289   copy
.m_branchStemLength 
= m_branchStemLength
; 
2290   copy
.m_branchSpacing 
= m_branchSpacing
; 
2292   // Copy text regions 
2293   copy
.ClearRegions(); 
2294   wxNode 
*node 
= m_regions
.GetFirst(); 
2297     wxShapeRegion 
*region 
= (wxShapeRegion 
*)node
->GetData(); 
2298     wxShapeRegion 
*newRegion 
= new wxShapeRegion(*region
); 
2299     copy
.m_regions
.Append(newRegion
); 
2300     node 
= node
->GetNext(); 
2304   copy
.ClearAttachments(); 
2305   node 
= m_attachmentPoints
.GetFirst(); 
2308     wxAttachmentPoint 
*point 
= (wxAttachmentPoint 
*)node
->GetData(); 
2309     wxAttachmentPoint 
*newPoint 
= new wxAttachmentPoint
; 
2310     newPoint
->m_id 
= point
->m_id
; 
2311     newPoint
->m_x 
= point
->m_x
; 
2312     newPoint
->m_y 
= point
->m_y
; 
2313     copy
.m_attachmentPoints
.Append((wxObject 
*)newPoint
); 
2314     node 
= node
->GetNext(); 
2318   copy
.m_lines
.Clear(); 
2319   node 
= m_lines
.GetFirst(); 
2322     wxLineShape
* line 
= (wxLineShape
*) node
->GetData(); 
2323     copy
.m_lines
.Append(line
); 
2324     node 
= node
->GetNext(); 
2328 // Create and return a new, fully copied object. 
2329 wxShape 
*wxShape::CreateNewCopy(bool resetMapping
, bool recompute
) 
2332     oglObjectCopyMapping
.Clear(); 
2334   wxShape
* newObject 
= (wxShape
*) GetClassInfo()->CreateObject(); 
2336   wxASSERT( (newObject 
!= NULL
) ); 
2337   wxASSERT( (newObject
->IsKindOf(CLASSINFO(wxShape
))) ); 
2341   if (GetEventHandler() != this) 
2343     wxShapeEvtHandler
* newHandler 
= GetEventHandler()->CreateNewCopy(); 
2344     newObject
->SetEventHandler(newHandler
); 
2345     newObject
->SetPreviousHandler(NULL
); 
2346     newHandler
->SetPreviousHandler(newObject
); 
2347     newHandler
->SetShape(newObject
); 
2351     newObject
->Recompute(); 
2355 // Does the copying for this object, including copying event 
2356 // handler data if any. Calls the virtual Copy function. 
2357 void wxShape::CopyWithHandler(wxShape
& copy
) 
2361     if (GetEventHandler() != this) 
2363         wxASSERT( copy
.GetEventHandler() != NULL 
); 
2364         wxASSERT( copy
.GetEventHandler() != (©
) ); 
2365         wxASSERT( GetEventHandler()->GetClassInfo() == copy
.GetEventHandler()->GetClassInfo() ); 
2366         GetEventHandler()->CopyData(* (copy
.GetEventHandler())); 
2371 // Default - make 6 control points 
2372 void wxShape::MakeControlPoints() 
2374   double maxX
, maxY
, minX
, minY
; 
2376   GetBoundingBoxMax(&maxX
, &maxY
); 
2377   GetBoundingBoxMin(&minX
, &minY
); 
2379   double widthMin 
= (double)(minX 
+ CONTROL_POINT_SIZE 
+ 2); 
2380   double heightMin 
= (double)(minY 
+ CONTROL_POINT_SIZE 
+ 2); 
2382   // Offsets from main object 
2383   double top 
= (double)(- (heightMin 
/ 2.0)); 
2384   double bottom 
= (double)(heightMin 
/ 2.0 + (maxY 
- minY
)); 
2385   double left 
= (double)(- (widthMin 
/ 2.0)); 
2386   double right 
= (double)(widthMin 
/ 2.0 + (maxX 
- minX
)); 
2388   wxControlPoint 
*control 
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, left
, top
, 
2389                                            CONTROL_POINT_DIAGONAL
); 
2390   m_canvas
->AddShape(control
); 
2391   m_controlPoints
.Append(control
); 
2393   control 
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, 0, top
, 
2394                                            CONTROL_POINT_VERTICAL
); 
2395   m_canvas
->AddShape(control
); 
2396   m_controlPoints
.Append(control
); 
2398   control 
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, right
, top
, 
2399                                            CONTROL_POINT_DIAGONAL
); 
2400   m_canvas
->AddShape(control
); 
2401   m_controlPoints
.Append(control
); 
2403   control 
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, right
, 0, 
2404                                            CONTROL_POINT_HORIZONTAL
); 
2405   m_canvas
->AddShape(control
); 
2406   m_controlPoints
.Append(control
); 
2408   control 
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, right
, bottom
, 
2409                                            CONTROL_POINT_DIAGONAL
); 
2410   m_canvas
->AddShape(control
); 
2411   m_controlPoints
.Append(control
); 
2413   control 
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, 0, bottom
, 
2414                                            CONTROL_POINT_VERTICAL
); 
2415   m_canvas
->AddShape(control
); 
2416   m_controlPoints
.Append(control
); 
2418   control 
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, left
, bottom
, 
2419                                            CONTROL_POINT_DIAGONAL
); 
2420   m_canvas
->AddShape(control
); 
2421   m_controlPoints
.Append(control
); 
2423   control 
= new wxControlPoint(m_canvas
, this, CONTROL_POINT_SIZE
, left
, 0, 
2424                                            CONTROL_POINT_HORIZONTAL
); 
2425   m_canvas
->AddShape(control
); 
2426   m_controlPoints
.Append(control
); 
2430 void wxShape::MakeMandatoryControlPoints() 
2432   wxNode 
*node 
= m_children
.GetFirst(); 
2435     wxShape 
*child 
= (wxShape 
*)node
->GetData(); 
2436     child
->MakeMandatoryControlPoints(); 
2437     node 
= node
->GetNext(); 
2441 void wxShape::ResetMandatoryControlPoints() 
2443   wxNode 
*node 
= m_children
.GetFirst(); 
2446     wxShape 
*child 
= (wxShape 
*)node
->GetData(); 
2447     child
->ResetMandatoryControlPoints(); 
2448     node 
= node
->GetNext(); 
2452 void wxShape::ResetControlPoints() 
2454   ResetMandatoryControlPoints(); 
2456   if (m_controlPoints
.GetCount() < 1) 
2459   double maxX
, maxY
, minX
, minY
; 
2461   GetBoundingBoxMax(&maxX
, &maxY
); 
2462   GetBoundingBoxMin(&minX
, &minY
); 
2464   double widthMin 
= (double)(minX 
+ CONTROL_POINT_SIZE 
+ 2); 
2465   double heightMin 
= (double)(minY 
+ CONTROL_POINT_SIZE 
+ 2); 
2467   // Offsets from main object 
2468   double top 
= (double)(- (heightMin 
/ 2.0)); 
2469   double bottom 
= (double)(heightMin 
/ 2.0 + (maxY 
- minY
)); 
2470   double left 
= (double)(- (widthMin 
/ 2.0)); 
2471   double right 
= (double)(widthMin 
/ 2.0 + (maxX 
- minX
)); 
2473   wxNode 
*node 
= m_controlPoints
.GetFirst(); 
2474   wxControlPoint 
*control 
= (wxControlPoint 
*)node
->GetData(); 
2475   control
->m_xoffset 
= left
; control
->m_yoffset 
= top
; 
2477   node 
= node
->GetNext(); control 
= (wxControlPoint 
*)node
->GetData(); 
2478   control
->m_xoffset 
= 0; control
->m_yoffset 
= top
; 
2480   node 
= node
->GetNext(); control 
= (wxControlPoint 
*)node
->GetData(); 
2481   control
->m_xoffset 
= right
; control
->m_yoffset 
= top
; 
2483   node 
= node
->GetNext(); control 
= (wxControlPoint 
*)node
->GetData(); 
2484   control
->m_xoffset 
= right
; control
->m_yoffset 
= 0; 
2486   node 
= node
->GetNext(); control 
= (wxControlPoint 
*)node
->GetData(); 
2487   control
->m_xoffset 
= right
; control
->m_yoffset 
= bottom
; 
2489   node 
= node
->GetNext(); control 
= (wxControlPoint 
*)node
->GetData(); 
2490   control
->m_xoffset 
= 0; control
->m_yoffset 
= bottom
; 
2492   node 
= node
->GetNext(); control 
= (wxControlPoint 
*)node
->GetData(); 
2493   control
->m_xoffset 
= left
; control
->m_yoffset 
= bottom
; 
2495   node 
= node
->GetNext(); control 
= (wxControlPoint 
*)node
->GetData(); 
2496   control
->m_xoffset 
= left
; control
->m_yoffset 
= 0; 
2499 void wxShape::DeleteControlPoints(wxDC 
*dc
) 
2501   wxNode 
*node 
= m_controlPoints
.GetFirst(); 
2504     wxControlPoint 
*control 
= (wxControlPoint 
*)node
->GetData(); 
2506         control
->GetEventHandler()->OnErase(*dc
); 
2507     m_canvas
->RemoveShape(control
); 
2510     node 
= m_controlPoints
.GetFirst(); 
2512   // Children of divisions are contained objects, 
2514   if (!IsKindOf(CLASSINFO(wxDivisionShape
))) 
2516     node 
= m_children
.GetFirst(); 
2519       wxShape 
*child 
= (wxShape 
*)node
->GetData(); 
2520       child
->DeleteControlPoints(dc
); 
2521       node 
= node
->GetNext(); 
2526 void wxShape::OnDrawControlPoints(wxDC
& dc
) 
2531   dc
.SetBrush(* wxBLACK_BRUSH
); 
2532   dc
.SetPen(* wxBLACK_PEN
); 
2534   wxNode 
*node 
= m_controlPoints
.GetFirst(); 
2537     wxControlPoint 
*control 
= (wxControlPoint 
*)node
->GetData(); 
2539     node 
= node
->GetNext(); 
2541   // Children of divisions are contained objects, 
2543   // This test bypasses the type facility for speed 
2544   // (critical when drawing) 
2545   if (!IsKindOf(CLASSINFO(wxDivisionShape
))) 
2547     node 
= m_children
.GetFirst(); 
2550       wxShape 
*child 
= (wxShape 
*)node
->GetData(); 
2551       child
->GetEventHandler()->OnDrawControlPoints(dc
); 
2552       node 
= node
->GetNext(); 
2557 void wxShape::OnEraseControlPoints(wxDC
& dc
) 
2559   wxNode 
*node 
= m_controlPoints
.GetFirst(); 
2562     wxControlPoint 
*control 
= (wxControlPoint 
*)node
->GetData(); 
2564     node 
= node
->GetNext(); 
2566   if (!IsKindOf(CLASSINFO(wxDivisionShape
))) 
2568     node 
= m_children
.GetFirst(); 
2571       wxShape 
*child 
= (wxShape 
*)node
->GetData(); 
2572       child
->GetEventHandler()->OnEraseControlPoints(dc
); 
2573       node 
= node
->GetNext(); 
2578 void wxShape::Select(bool select
, wxDC
* dc
) 
2580   m_selected 
= select
; 
2583     MakeControlPoints(); 
2584     // Children of divisions are contained objects, 
2586     if (!IsKindOf(CLASSINFO(wxDivisionShape
))) 
2588       wxNode 
*node 
= m_children
.GetFirst(); 
2591         wxShape 
*child 
= (wxShape 
*)node
->GetData(); 
2592         child
->MakeMandatoryControlPoints(); 
2593         node 
= node
->GetNext(); 
2597         GetEventHandler()->OnDrawControlPoints(*dc
); 
2601     DeleteControlPoints(dc
); 
2602     if (!IsKindOf(CLASSINFO(wxDivisionShape
))) 
2604       wxNode 
*node 
= m_children
.GetFirst(); 
2607         wxShape 
*child 
= (wxShape 
*)node
->GetData(); 
2608         child
->DeleteControlPoints(dc
); 
2609         node 
= node
->GetNext(); 
2615 bool wxShape::Selected() const 
2620 bool wxShape::AncestorSelected() const 
2622   if (m_selected
) return true; 
2626     return GetParent()->AncestorSelected(); 
2629 int wxShape::GetNumberOfAttachments() const 
2631   // Should return the MAXIMUM attachment point id here, 
2632   // so higher-level functions can iterate through all attachments, 
2633   // even if they're not contiguous. 
2634   if (m_attachmentPoints
.GetCount() == 0) 
2639     wxNode 
*node 
= m_attachmentPoints
.GetFirst(); 
2642       wxAttachmentPoint 
*point 
= (wxAttachmentPoint 
*)node
->GetData(); 
2643       if (point
->m_id 
> maxN
) 
2645       node 
= node
->GetNext(); 
2651 bool wxShape::AttachmentIsValid(int attachment
) const 
2653   if (m_attachmentPoints
.GetCount() == 0) 
2655     return ((attachment 
>= 0) && (attachment 
< 4)) ; 
2658   wxNode 
*node 
= m_attachmentPoints
.GetFirst(); 
2661     wxAttachmentPoint 
*point 
= (wxAttachmentPoint 
*)node
->GetData(); 
2662     if (point
->m_id 
== attachment
) 
2664     node 
= node
->GetNext(); 
2669 bool wxShape::GetAttachmentPosition(int attachment
, double *x
, double *y
, 
2670                                          int nth
, int no_arcs
, wxLineShape 
*line
) 
2672     if (m_attachmentMode 
== ATTACHMENT_MODE_NONE
) 
2674         *x 
= m_xpos
; *y 
= m_ypos
; 
2677     else if (m_attachmentMode 
== ATTACHMENT_MODE_BRANCHING
) 
2679         wxRealPoint pt
, stemPt
; 
2680         GetBranchingAttachmentPoint(attachment
, nth
, pt
, stemPt
); 
2685     else if (m_attachmentMode 
== ATTACHMENT_MODE_EDGE
) 
2687         if (m_attachmentPoints
.GetCount() > 0) 
2689             wxNode 
*node 
= m_attachmentPoints
.GetFirst(); 
2692                 wxAttachmentPoint 
*point 
= (wxAttachmentPoint 
*)node
->GetData(); 
2693                 if (point
->m_id 
== attachment
) 
2695                     *x 
= (double)(m_xpos 
+ point
->m_x
); 
2696                     *y 
= (double)(m_ypos 
+ point
->m_y
); 
2699                 node 
= node
->GetNext(); 
2701             *x 
= m_xpos
; *y 
= m_ypos
; 
2706             // Assume is rectangular 
2708             GetBoundingBoxMax(&w
, &h
); 
2709             double top 
= (double)(m_ypos 
+ h
/2.0); 
2710             double bottom 
= (double)(m_ypos 
- h
/2.0); 
2711             double left 
= (double)(m_xpos 
- w
/2.0); 
2712             double right 
= (double)(m_xpos 
+ w
/2.0); 
2715             /* 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 
= M_PI 
; 
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 
= M_PI 
; 
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 
= M_PI 
; 
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
;