From f93ce4dadc287261babbd21a29aae59a8efbed2b Mon Sep 17 00:00:00 2001
From: Julian Smart <julian@anthemion.co.uk>
Date: Wed, 16 Sep 1998 21:44:17 +0000
Subject: [PATCH] Misc OGL changes

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@739 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
---
 utils/ogl/distrib/ogl.rsp    |  74 +++---
 utils/ogl/distrib/zipogl.bat |  14 +-
 utils/ogl/docs/classes.tex   |  30 ++-
 utils/ogl/src/basic.cpp      | 202 +++++++++++++----
 utils/ogl/src/basic.h        |   9 +-
 utils/ogl/src/basic2.cpp     | 420 +++++++++++++----------------------
 utils/ogl/src/basicp.h       |  16 +-
 utils/ogl/src/composit.cpp   |  10 +-
 utils/ogl/src/composit.h     |   2 -
 utils/ogl/src/divided.h      |   1 -
 utils/ogl/src/drawn.cpp      |  28 +--
 utils/ogl/src/lines.cpp      |  10 +-
 utils/ogl/src/ogldiag.cpp    |  15 +-
 utils/ogl/src/ogldiag.h      |   5 +-
 14 files changed, 444 insertions(+), 392 deletions(-)

diff --git a/utils/ogl/distrib/ogl.rsp b/utils/ogl/distrib/ogl.rsp
index 74c26f53df..8da08f60a8 100644
--- a/utils/ogl/distrib/ogl.rsp
+++ b/utils/ogl/distrib/ogl.rsp
@@ -1,39 +1,43 @@
-src/*.cpp
-src/*.h
-src/*.rc
-src/*.def
-src/*.xbm
-src/*.xpm
-src/makefile*
-src/*.txt
-src/*.ico
-src/*.bmp
+utils/ogl/src/*.cpp
+utils/ogl/src/*.h
+utils/ogl/src/*.rc
+utils/ogl/src/*.def
+utils/ogl/src/*.xbm
+utils/ogl/src/*.xpm
+utils/ogl/src/makefile*
+utils/ogl/src/*.txt
+utils/ogl/src/*.ico
+utils/ogl/src/*.bmp
 
-samples/ogledit/*.cpp
-samples/ogledit/*.h
-samples/ogledit/*.rc
-samples/ogledit/*.def
-samples/ogledit/*.xbm
-samples/ogledit/makefile*
-samples/ogledit/*.txt
+utils/ogl/samples/ogledit/*.cpp
+utils/ogl/samples/ogledit/*.h
+utils/ogl/samples/ogledit/*.rc
+utils/ogl/samples/ogledit/*.def
+utils/ogl/samples/ogledit/*.xbm
+utils/ogl/samples/ogledit/makefile*
+utils/ogl/samples/ogledit/*.txt
 
-samples/ogledit/*.ico
-samples/ogledit/*.bmp
-samples/ogledit/bitmaps/*.bmp
-samples/ogledit/bitmaps/*.gif
-samples/ogledit/bitmaps/*.xbm
-samples/ogledit/bitmaps/*.xpm
+utils/ogl/samples/ogledit/*.ico
+utils/ogl/samples/ogledit/*.bmp
+utils/ogl/samples/ogledit/bitmaps/*.bmp
+utils/ogl/samples/ogledit/bitmaps/*.gif
+utils/ogl/samples/ogledit/bitmaps/*.xbm
+utils/ogl/samples/ogledit/bitmaps/*.xpm
 
-distrib/*.rsp
-distrib/*.bat
+utils/ogl/distrib/*.rsp
+utils/ogl/distrib/*.bat
+
+utils/ogl/docs/*.txt
+utils/ogl/docs/*.tex
+utils/ogl/docs/*.ini
+utils/ogl/docs/*.hpj
+utils/ogl/docs/*.ps
+utils/ogl/docs/*.eps
+utils/ogl/docs/*.bmp
+utils/ogl/docs/*.gif
+
+docs/html/ogl/*.*
+docs/winhelp/ogl.hlp
+docs/winhelp/ogl.cnt
+docs/pdf/ogl.pdf
 
-docs/*.txt
-docs/*.tex
-docs/*.ini
-docs/*.hpj
-docs/*.ps
-docs/*.eps
-docs/*.cnt
-docs/*.bmp
-docs/*.gif
-docs/*.hlp
diff --git a/utils/ogl/distrib/zipogl.bat b/utils/ogl/distrib/zipogl.bat
index 37f3e3bf94..51ee8b37fc 100755
--- a/utils/ogl/distrib/zipogl.bat
+++ b/utils/ogl/distrib/zipogl.bat
@@ -1,19 +1,21 @@
 @echo off
 rem Zip up an external distribution of OGL
-set src=d:\wx2\wxWindows\utils\ogl
-set dest=%src\deliver
+set src=d:\wx2\wxWindows
+set dest=%src\utils\ogl\deliver
 
 if "%src" == "" goto usage
 if "%dest" == "" goto usage
 echo About to archive an external OGL distribution:
 echo   From   %src
-echo   To     %dest\ogl.zip
+echo   To     %dest\ogl3.zip
 echo CTRL-C if this is not correct.
 inkey /W4 `Press any key to continue...` %%input
 
-erase %dest\ogl.zip
+erase %dest\ogl3.zip
 cd %src
-zip32 -@ %dest\ogl.zip < %src\distrib\ogl.rsp
+zip32 -@ %dest\ogl3.zip < %src\utils\ogl\distrib\ogl.rsp
+
+cd %dest
 
 echo OGL archived.
 goto end
@@ -21,7 +23,7 @@ goto end
 :usage
 echo DOS OGL distribution.
 echo Usage: zipogl source destination
-echo e.g. zipogl c:\wx\utils\ogl c:\wx\utils\ogl\deliver
+echo e.g. zipogl d:\wx2\wxWindows d:\wx2\wxWindows\utils\ogl\deliver
 
 :end
 
diff --git a/utils/ogl/docs/classes.tex b/utils/ogl/docs/classes.tex
index 7e15517577..768d28a0a2 100644
--- a/utils/ogl/docs/classes.tex
+++ b/utils/ogl/docs/classes.tex
@@ -225,12 +225,24 @@ Removes and deletes all shapes in the diagram.
 
 Draws an outline rectangle on the current device context.
 
+\membersection{wxDiagram::FindShape}\label{wxdiagramfindshape}
+
+\constfunc{wxShape*}{FindShape}{\param{long}{ id}}
+
+Returns the shape for the given identifier.
+
 \membersection{wxDiagram::GetCanvas}
 
 \constfunc{wxShapeCanvas*}{GetCanvas}{\void}
 
 Returns the shape canvas associated with this diagram.
 
+\membersection{wxDiagram::GetCount}\label{wxdiagramgetcount}
+
+\constfunc{int}{GetCount}{\void}
+
+Returns the number of shapes in the diagram.
+
 \membersection{wxDiagram::GetGridSpacing}
 
 \constfunc{double}{GetGridSpacing}{\void}
@@ -1474,7 +1486,7 @@ Destructor.
 
 \membersection{wxShape::AddLine}
 
-\func{void}{AddLine}{\param{wxLineShape *}{line}, \param{wxShape *}{other}, \param{int}{attachFrom = 0}, \param{int}{ attachTo = 0},
+\func{void}{AddLine}{\param{wxLineShape*}{ line}, \param{wxShape*}{ other}, \param{int}{ attachFrom = 0}, \param{int}{ attachTo = 0},
  \param{int}{ positionFrom = -1}, \param{int}{ positionTo = -1}}
 
 Adds a line between the specified canvas shapes, at the specified attachment points.
@@ -1847,6 +1859,13 @@ Gets the zero-based position of {\it line} in the list of lines for this shape.
 
 Returns a reference to the list of lines connected to this shape.
 
+\membersection{wxShape::GetMaintainAspectRatio}\label{wxshapegetmaintainaspectratio}
+
+\constfunc{bool}{GetMaintainAspectRatio}{\void}
+
+If returns TRUE, resizing the shape will not change the aspect ratio
+(width and height will be in the original proportion).
+
 \membersection{wxShape::GetNumberOfAttachments}\label{wxshapegetnumberofattachments}
 
 \constfunc{int}{GetNumberOfAttachments}{\void}
@@ -2197,6 +2216,13 @@ Sets the highlight for a shape. Shape highlighting is unimplemented.
 
 Set the integer identifier for this shape.
 
+\membersection{wxShape::SetMaintainAspectRatio}\label{wxshapesetmaintainaspectratio}
+
+\func{void}{SetMaintainAspectRatio}{\param{bool}{ flag}}
+
+If the argument is TRUE, tells the shape that resizes should not change the aspect ratio
+(width and height should be in the original proportion).
+
 \membersection{wxShape::SetPen}
 
 \func{void}{SetPen}{\param{wxPen *}{pen}}
@@ -2652,7 +2678,7 @@ image, and again to allow drawing at the new position.
 
 \membersection{wxShapeEvtHandler::OnDraw}
 
-\func{void}{OnDraw}{\void}
+\func{void}{OnDraw}{\param{wxDC\&}{ dc}}
 
 Defined for each class to draw the main graphic, but
 not the contents.
diff --git a/utils/ogl/src/basic.cpp b/utils/ogl/src/basic.cpp
index 1e366c9f33..5a8b417ee3 100644
--- a/utils/ogl/src/basic.cpp
+++ b/utils/ogl/src/basic.cpp
@@ -294,6 +294,7 @@ wxShape::wxShape(wxShapeCanvas *can)
   m_textMarginY = 5.0;
   m_regionName = "0";
   m_centreResize = TRUE;
+  m_maintainAspectRatio = FALSE;
   m_highlighted = FALSE;
   m_rotation = 0.0;
 
@@ -1590,6 +1591,43 @@ void wxShape::AddLine(wxLineShape *line, wxShape *other,
                             // The line ordering
                             int positionFrom, int positionTo)
 {
+    if (positionFrom == -1)
+    {
+        if (!m_lines.Member(line))
+            m_lines.Append(line);
+    }
+    else
+    {
+        // Don't preserve old ordering if we have new ordering instructions
+        m_lines.DeleteObject(line);
+        if (positionFrom < m_lines.Number())
+        {
+            wxNode* node = m_lines.Nth(positionFrom);
+            m_lines.Insert(node, line);
+        }
+        else
+            m_lines.Append(line);
+    }
+
+    if (positionTo == -1)
+    {
+        if (!other->m_lines.Member(line))
+            other->m_lines.Append(line);
+    }
+    else
+    {
+        // Don't preserve old ordering if we have new ordering instructions
+        other->m_lines.DeleteObject(line);
+        if (positionTo < other->m_lines.Number())
+        {
+            wxNode* node = other->m_lines.Nth(positionTo);
+            other->m_lines.Insert(node, line);
+        }
+        else
+            other->m_lines.Append(line);
+    }
+#if 0
+    // Wrong: doesn't preserve ordering of shape already linked
     m_lines.DeleteObject(line);
     other->m_lines.DeleteObject(line);
 
@@ -1618,6 +1656,7 @@ void wxShape::AddLine(wxLineShape *line, wxShape *other,
         else
             other->m_lines.Append(line);
     }
+#endif
 
     line->SetFrom(this);
     line->SetTo(other);
@@ -1682,7 +1721,7 @@ void wxShape::WriteAttributes(wxExpr *clause)
   int n_lines = m_lines.Number();
   if (n_lines > 0)
   {
-    wxExpr *list = new wxExpr(PrologList);
+    wxExpr *list = new wxExpr(wxExprList);
     wxNode *node = m_lines.First();
     while (node)
     {
@@ -1709,6 +1748,7 @@ void wxShape::WriteAttributes(wxExpr *clause)
     clause->AddAttributeValue("shadow_mode", (long)m_shadowMode);
   if (m_centreResize != TRUE)
     clause->AddAttributeValue("centre_resize", (long)0);
+  clause->AddAttributeValue("maintain_aspect_ratio", (long) m_maintainAspectRatio);
   if (m_highlighted != FALSE)
     clause->AddAttributeValue("hilite", (long)m_highlighted);
 
@@ -1721,12 +1761,12 @@ void wxShape::WriteAttributes(wxExpr *clause)
   // Write user-defined attachment points, if any
   if (m_attachmentPoints.Number() > 0)
   {
-    wxExpr *attachmentList = new wxExpr(PrologList);
+    wxExpr *attachmentList = new wxExpr(wxExprList);
     wxNode *node = m_attachmentPoints.First();
     while (node)
     {
       wxAttachmentPoint *point = (wxAttachmentPoint *)node->Data();
-      wxExpr *pointExpr = new wxExpr(PrologList);
+      wxExpr *pointExpr = new wxExpr(wxExprList);
       pointExpr->Append(new wxExpr((long)point->m_id));
       pointExpr->Append(new wxExpr(point->m_x));
       pointExpr->Append(new wxExpr(point->m_y));
@@ -1757,9 +1797,9 @@ void wxShape::WriteRegions(wxExpr *clause)
     // Original text and region attributes:
     // region1 = (regionName regionText x y width height minWidth minHeight proportionX proportionY
     //            formatMode fontSize fontFamily fontStyle fontWeight textColour)
-    wxExpr *regionExpr = new wxExpr(PrologList);
-    regionExpr->Append(new wxExpr(PrologString, (region->m_regionName ? region->m_regionName : "")));
-    regionExpr->Append(new wxExpr(PrologString, (region->m_regionText ? region->m_regionText : "")));
+    wxExpr *regionExpr = new wxExpr(wxExprList);
+    regionExpr->Append(new wxExpr(wxExprString, (region->m_regionName ? region->m_regionName : "")));
+    regionExpr->Append(new wxExpr(wxExprString, (region->m_regionText ? region->m_regionText : "")));
 
     regionExpr->Append(new wxExpr(region->m_x));
     regionExpr->Append(new wxExpr(region->m_y));
@@ -1777,24 +1817,24 @@ void wxShape::WriteRegions(wxExpr *clause)
     regionExpr->Append(new wxExpr((long)(region->m_font ? region->m_font->GetFamily() : wxDEFAULT)));
     regionExpr->Append(new wxExpr((long)(region->m_font ? region->m_font->GetStyle() : wxDEFAULT)));
     regionExpr->Append(new wxExpr((long)(region->m_font ? region->m_font->GetWeight() : wxNORMAL)));
-    regionExpr->Append(new wxExpr(PrologString, region->m_textColour ? region->m_textColour : "BLACK"));
+    regionExpr->Append(new wxExpr(wxExprString, region->m_textColour ? region->m_textColour : "BLACK"));
 
     // New members for pen colour/style
-    regionExpr->Append(new wxExpr(PrologString, region->m_penColour ? region->m_penColour : "BLACK"));
+    regionExpr->Append(new wxExpr(wxExprString, region->m_penColour ? region->m_penColour : "BLACK"));
     regionExpr->Append(new wxExpr((long)region->m_penStyle));
 
     // Formatted text:
     // text1 = ((x y string) (x y string) ...)
-    wxExpr *textExpr = new wxExpr(PrologList);
+    wxExpr *textExpr = new wxExpr(wxExprList);
 
     wxNode *textNode = region->m_formattedText.First();
     while (textNode)
     {
       wxShapeTextLine *line = (wxShapeTextLine *)textNode->Data();
-      wxExpr *list2 = new wxExpr(PrologList);
+      wxExpr *list2 = new wxExpr(wxExprList);
       list2->Append(new wxExpr(line->GetX()));
       list2->Append(new wxExpr(line->GetY()));
-      list2->Append(new wxExpr(PrologString, line->GetText()));
+      list2->Append(new wxExpr(wxExprString, line->GetText()));
       textExpr->Append(list2);
       textNode = textNode->Next();
     }
@@ -1819,7 +1859,7 @@ void wxShape::ReadAttributes(wxExpr *clause)
   // Input text strings (FOR COMPATIBILITY WITH OLD FILES ONLY. SEE REGION CODE BELOW.)
   ClearText();
   wxExpr *strings = clause->AttributeValue("text");
-  if (strings && strings->Type() == PrologList)
+  if (strings && strings->Type() == wxExprList)
   {
     m_formatted = TRUE;  // Assume text is formatted unless we prove otherwise
     wxExpr *node = strings->value.first;
@@ -1832,27 +1872,27 @@ void wxShape::ReadAttributes(wxExpr *clause)
 
       // string_expr can either be a string, or a list of
       // 3 elements: x, y, and string.
-      if (string_expr->Type() == PrologString)
+      if (string_expr->Type() == wxExprString)
       {
         the_string = string_expr->StringValue();
         m_formatted = FALSE;
       }
-      else if (string_expr->Type() == PrologList)
+      else if (string_expr->Type() == wxExprList)
       {
         wxExpr *first = string_expr->value.first;
         wxExpr *second = first ? first->next : NULL;
         wxExpr *third = second ? second->next : NULL;
 
         if (first && second && third &&
-            (first->Type() == PrologReal || first->Type() == PrologInteger) &&
-            (second->Type() == PrologReal || second->Type() == PrologInteger) &&
-            third->Type() == PrologString)
+            (first->Type() == wxExprReal || first->Type() == wxExprInteger) &&
+            (second->Type() == wxExprReal || second->Type() == wxExprInteger) &&
+            third->Type() == wxExprString)
           {
-            if (first->Type() == PrologReal)
+            if (first->Type() == wxExprReal)
               the_x = first->RealValue();
             else the_x = (double)first->IntegerValue();
 
-            if (second->Type() == PrologReal)
+            if (second->Type() == wxExprReal)
               the_y = second->RealValue();
             else the_y = (double)second->IntegerValue();
 
@@ -1911,6 +1951,10 @@ void wxShape::ReadAttributes(wxExpr *clause)
   clause->GetAttributeValue("centre_resize", iVal);
   m_centreResize = (iVal != 0);
 
+  iVal = (int) m_maintainAspectRatio;
+  clause->GetAttributeValue("maintain_aspect_ratio", iVal);
+  m_maintainAspectRatio = (iVal != 0);
+
   iVal = (int) m_highlighted;
   clause->GetAttributeValue("hilite", iVal);
   m_highlighted = (iVal != 0);
@@ -2017,7 +2061,7 @@ void wxShape::ReadRegions(wxExpr *clause)
     wxString penColour("");
     int penStyle = wxSOLID;
 
-    if (regionExpr->Type() == PrologList)
+    if (regionExpr->Type() == wxExprList)
     {
       wxExpr *nameExpr = regionExpr->Nth(0);
       wxExpr *textExpr = regionExpr->Nth(1);
@@ -2095,7 +2139,7 @@ void wxShape::ReadRegions(wxExpr *clause)
      *
      */
     textExpr = clause->AttributeValue(textNameBuf);
-    if (textExpr && (textExpr->Type() == PrologList))
+    if (textExpr && (textExpr->Type() == wxExprList))
     {
       wxExpr *node = textExpr->value.first;
       while (node)
@@ -2107,27 +2151,27 @@ void wxShape::ReadRegions(wxExpr *clause)
 
         // string_expr can either be a string, or a list of
         // 3 elements: x, y, and string.
-        if (string_expr->Type() == PrologString)
+        if (string_expr->Type() == wxExprString)
         {
           the_string = string_expr->StringValue();
           m_formatted = FALSE;
         }
-        else if (string_expr->Type() == PrologList)
+        else if (string_expr->Type() == wxExprList)
         {
           wxExpr *first = string_expr->value.first;
           wxExpr *second = first ? first->next : NULL;
           wxExpr *third = second ? second->next : NULL;
 
           if (first && second && third &&
-              (first->Type() == PrologReal || first->Type() == PrologInteger) &&
-              (second->Type() == PrologReal || second->Type() == PrologInteger) &&
-              third->Type() == PrologString)
+              (first->Type() == wxExprReal || first->Type() == wxExprInteger) &&
+              (second->Type() == wxExprReal || second->Type() == wxExprInteger) &&
+              third->Type() == wxExprString)
           {
-            if (first->Type() == PrologReal)
+            if (first->Type() == wxExprReal)
               the_x = first->RealValue();
             else the_x = (double)first->IntegerValue();
 
-            if (second->Type() == PrologReal)
+            if (second->Type() == wxExprReal)
               the_y = second->RealValue();
             else the_y = (double)second->IntegerValue();
 
@@ -2186,6 +2230,7 @@ void wxShape::Copy(wxShape& copy)
   copy.m_brush = m_brush;
   copy.m_textColour = m_textColour;
   copy.m_centreResize = m_centreResize;
+  copy.m_maintainAspectRatio = m_maintainAspectRatio;
   copy.m_attachmentMode = m_attachmentMode;
   copy.m_spaceAttachments = m_spaceAttachments;
   copy.m_highlighted = m_highlighted;
@@ -2567,8 +2612,10 @@ int wxShape::GetNumberOfAttachments() const
 
 bool wxShape::AttachmentIsValid(int attachment) const
 {
-  if ((attachment >= 0) && (attachment < 4))
-    return TRUE;
+  if (m_attachmentPoints.Number() == 0)
+  {
+    return ((attachment >= 0) && (attachment < 4)) ;
+  }
 
   wxNode *node = m_attachmentPoints.First();
   while (node)
@@ -2584,28 +2631,87 @@ bool wxShape::AttachmentIsValid(int attachment) const
 bool wxShape::GetAttachmentPosition(int attachment, double *x, double *y, 
                                          int nth, int no_arcs, wxLineShape *line)
 {
-  if (!m_attachmentMode)
-  {
-    *x = m_xpos; *y = m_ypos;
-    return TRUE;
-  }
-  else
-  {
-    wxNode *node = m_attachmentPoints.First();
-    while (node)
+    if (!m_attachmentMode)
     {
-      wxAttachmentPoint *point = (wxAttachmentPoint *)node->Data();
-      if (point->m_id == attachment)
-      {
-        *x = (double)(m_xpos + point->m_x);
-        *y = (double)(m_ypos + point->m_y);
+        *x = m_xpos; *y = m_ypos;
         return TRUE;
-      }
-      node = node->Next();
     }
-    *x = m_xpos; *y = m_ypos;
+    else
+    {
+        if (m_attachmentPoints.Number() > 0)
+        {
+            wxNode *node = m_attachmentPoints.First();
+            while (node)
+            {
+                wxAttachmentPoint *point = (wxAttachmentPoint *)node->Data();
+                if (point->m_id == attachment)
+                {
+                    *x = (double)(m_xpos + point->m_x);
+                    *y = (double)(m_ypos + point->m_y);
+                    return TRUE;
+                }
+                node = node->Next();
+            }
+            *x = m_xpos; *y = m_ypos;
+            return FALSE;
+        }
+        else
+        {
+            // Assume is rectangular
+            double w, h;
+            GetBoundingBoxMax(&w, &h);
+            double top = (double)(m_ypos + h/2.0);
+            double bottom = (double)(m_ypos - h/2.0);
+            double left = (double)(m_xpos - w/2.0);
+            double right = (double)(m_xpos + w/2.0);
+
+            bool isEnd = (line && line->IsEnd(this));
+
+            // Simplified code
+            switch (attachment)
+            {
+                case 0:
+                {
+                    wxRealPoint pt = CalcSimpleAttachment(wxRealPoint(left, bottom), wxRealPoint(right, bottom),
+                            nth, no_arcs, line);
+
+                    *x = pt.x; *y = pt.y;
+                    break;
+                }
+                case 1:
+                {
+                    wxRealPoint pt = CalcSimpleAttachment(wxRealPoint(right, bottom), wxRealPoint(right, top),
+                            nth, no_arcs, line);
+
+                    *x = pt.x; *y = pt.y;
+                    break;
+                }
+                case 2:
+                {
+                    wxRealPoint pt = CalcSimpleAttachment(wxRealPoint(left, top), wxRealPoint(right, top),
+                            nth, no_arcs, line);
+
+                    *x = pt.x; *y = pt.y;
+                    break;
+                }
+                case 3:
+                {
+                    wxRealPoint pt = CalcSimpleAttachment(wxRealPoint(left, bottom), wxRealPoint(left, top),
+                            nth, no_arcs, line);
+
+                    *x = pt.x; *y = pt.y;
+                    break;
+                }
+                default:
+                {
+                    return wxShape::GetAttachmentPosition(attachment, x, y, nth, no_arcs, line);
+                    break;
+                }
+            }
+            return TRUE;
+        }
+    }
     return FALSE;
-  }
 }
 
 void wxShape::GetBoundingBoxMax(double *w, double *h)
diff --git a/utils/ogl/src/basic.h b/utils/ogl/src/basic.h
index 4a2aff1095..52b78d16ed 100644
--- a/utils/ogl/src/basic.h
+++ b/utils/ogl/src/basic.h
@@ -269,6 +269,8 @@ class wxShape: public wxShapeEvtHandler
   virtual bool HitTest(double x, double y, int *attachment, double *distance);
   inline void SetCentreResize(bool cr) { m_centreResize = cr; }
   inline bool GetCentreResize() const { return m_centreResize; }
+  inline void SetMaintainAspectRatio(bool ar) { m_maintainAspectRatio = ar; }
+  inline bool GetMaintainAspectRatio() const { return m_maintainAspectRatio; }
   inline wxList& GetLines() const { return (wxList&) m_lines; }
   inline void SetDisableLabel(bool flag) { m_disableLabel = flag; }
   inline bool GetDisableLabel() const { return m_disableLabel; }
@@ -482,6 +484,7 @@ class wxShape: public wxShapeEvtHandler
   int                   m_textMarginX;    // Gap between text and border
   int                   m_textMarginY;
   wxString              m_regionName;
+  bool                  m_maintainAspectRatio;
 };
 
 class wxPolygonShape: public wxShape
@@ -532,7 +535,6 @@ class wxPolygonShape: public wxShape
   virtual void CalculatePolygonCentre();
 
 #ifdef PROLOGIO
-  // Prolog database stuff
   void WriteAttributes(wxExpr *clause);
   void ReadAttributes(wxExpr *clause);
 #endif
@@ -546,6 +548,9 @@ class wxPolygonShape: public wxShape
 
   inline wxList *GetPoints() { return m_points; }
 
+  // Rotate about the given axis by the given amount in radians
+  virtual void Rotate(double x, double y, double theta);
+
  private:
   wxList*       m_points;
   wxList*       m_originalPoints;
@@ -569,7 +574,6 @@ class wxRectangleShape: public wxShape
   void SetCornerRadius(double rad); // If > 0, rounded corners
 
 #ifdef PROLOGIO
-  // Prolog database stuff
   void WriteAttributes(wxExpr *clause);
   void ReadAttributes(wxExpr *clause);
 #endif
@@ -622,7 +626,6 @@ class wxEllipseShape: public wxShape
   void SetSize(double x, double y, bool recursive = TRUE);
 
 #ifdef PROLOGIO
-  // Prolog database stuff
   void WriteAttributes(wxExpr *clause);
   void ReadAttributes(wxExpr *clause);
 #endif
diff --git a/utils/ogl/src/basic2.cpp b/utils/ogl/src/basic2.cpp
index 99800cf4fe..d959c5e5c1 100644
--- a/utils/ogl/src/basic2.cpp
+++ b/utils/ogl/src/basic2.cpp
@@ -557,62 +557,6 @@ void wxPolygonShape::MakeControlPoints()
     m_controlPoints.Append(control);
     node = node->Next();
   }
-
-/*
-  double maxX, maxY, minX, minY;
-
-  GetBoundingBoxMax(&maxX, &maxY);
-  GetBoundingBoxMin(&minX, &minY);
-
-  double widthMin = (double)(minX + CONTROL_POINT_SIZE + 2);
-  double heightMin = (double)(minY + CONTROL_POINT_SIZE + 2);
-
-  // Offsets from main object
-  double top = (double)(- (heightMin / 2.0));
-  double bottom = (double)(heightMin / 2.0 + (maxY - minY));
-  double left = (double)(- (widthMin / 2.0));
-  double right = (double)(widthMin / 2.0 + (maxX - minX));
-
-  wxControlPoint *control = new wxControlPoint(m_canvas, this, CONTROL_POINT_SIZE, left, top, 
-                                           CONTROL_POINT_DIAGONAL);
-  m_canvas->AddShape(control);
-  m_controlPoints.Append(control);
-
-  control = new wxControlPoint(m_canvas, this, CONTROL_POINT_SIZE, 0, top, 
-                                           CONTROL_POINT_VERTICAL);
-  m_canvas->AddShape(control);
-  m_controlPoints.Append(control);
-
-  control = new wxControlPoint(m_canvas, this, CONTROL_POINT_SIZE, right, top, 
-                                           CONTROL_POINT_DIAGONAL);
-  m_canvas->AddShape(control);
-  m_controlPoints.Append(control);
-
-  control = new wxControlPoint(m_canvas, this, CONTROL_POINT_SIZE, right, 0, 
-                                           CONTROL_POINT_HORIZONTAL);
-  m_canvas->AddShape(control);
-  m_controlPoints.Append(control);
-
-  control = new wxControlPoint(m_canvas, this, CONTROL_POINT_SIZE, right, bottom, 
-                                           CONTROL_POINT_DIAGONAL);
-  m_canvas->AddShape(control);
-  m_controlPoints.Append(control);
-
-  control = new wxControlPoint(m_canvas, this, CONTROL_POINT_SIZE, 0, bottom, 
-                                           CONTROL_POINT_VERTICAL);
-  m_canvas->AddShape(control);
-  m_controlPoints.Append(control);
-
-  control = new wxControlPoint(m_canvas, this, CONTROL_POINT_SIZE, left, bottom, 
-                                           CONTROL_POINT_DIAGONAL);
-  m_canvas->AddShape(control);
-  m_controlPoints.Append(control);
-
-  control = new wxControlPoint(m_canvas, this, CONTROL_POINT_SIZE, left, 0, 
-                                           CONTROL_POINT_HORIZONTAL);
-  m_canvas->AddShape(control);
-  m_controlPoints.Append(control);
-*/
 }
 
 void wxPolygonShape::ResetControlPoints()
@@ -631,50 +575,6 @@ void wxPolygonShape::ResetControlPoints()
     node = node->Next();
     controlPointNode = controlPointNode->Next();
   }
-/*
-
-  if (m_controlPoints.Number() < 1)
-    return;
-
-  double maxX, maxY, minX, minY;
-
-  GetBoundingBoxMax(&maxX, &maxY);
-  GetBoundingBoxMin(&minX, &minY);
-
-  double widthMin = (double)(minX + CONTROL_POINT_SIZE + 2);
-  double heightMin = (double)(minY + CONTROL_POINT_SIZE + 2);
-
-  // Offsets from main object
-  double top = (double)(- (heightMin / 2.0));
-  double bottom = (double)(heightMin / 2.0 + (maxY - minY));
-  double left = (double)(- (widthMin / 2.0));
-  double right = (double)(widthMin / 2.0 + (maxX - minX));
-
-  wxNode *node = m_controlPoints.First();
-  wxControlPoint *control = (wxControlPoint *)node->Data();
-  control->xoffset = left; control->yoffset = top;
-
-  node = node->Next(); control = (wxControlPoint *)node->Data();
-  control->xoffset = 0; control->yoffset = top;
-
-  node = node->Next(); control = (wxControlPoint *)node->Data();
-  control->xoffset = right; control->yoffset = top;
-
-  node = node->Next(); control = (wxControlPoint *)node->Data();
-  control->xoffset = right; control->yoffset = 0;
-
-  node = node->Next(); control = (wxControlPoint *)node->Data();
-  control->xoffset = right; control->yoffset = bottom;
-
-  node = node->Next(); control = (wxControlPoint *)node->Data();
-  control->xoffset = 0; control->yoffset = bottom;
-
-  node = node->Next(); control = (wxControlPoint *)node->Data();
-  control->xoffset = left; control->yoffset = bottom;
-
-  node = node->Next(); control = (wxControlPoint *)node->Data();
-  control->xoffset = left; control->yoffset = 0;
-*/
 }
 
 
@@ -687,12 +587,12 @@ void wxPolygonShape::WriteAttributes(wxExpr *clause)
   clause->AddAttributeValue("y", m_ypos);
 
   // Make a list of lists for the coordinates
-  wxExpr *list = new wxExpr(PrologList);
+  wxExpr *list = new wxExpr(wxExprList);
   wxNode *node = m_points->First();
   while (node)
   {
     wxRealPoint *point = (wxRealPoint *)node->Data();
-    wxExpr *point_list = new wxExpr(PrologList);
+    wxExpr *point_list = new wxExpr(wxExprList);
     wxExpr *x_expr = new wxExpr((double)point->x);
     wxExpr *y_expr = new wxExpr((double)point->y);
 
@@ -705,12 +605,12 @@ void wxPolygonShape::WriteAttributes(wxExpr *clause)
   clause->AddAttributeValue("points", list);
 
   // Save the original (unscaled) points
-  list = new wxExpr(PrologList);
+  list = new wxExpr(wxExprList);
   node = m_originalPoints->First();
   while (node)
   {
     wxRealPoint *point = (wxRealPoint *)node->Data();
-    wxExpr *point_list = new wxExpr(PrologList);
+    wxExpr *point_list = new wxExpr(wxExprList);
     wxExpr *x_expr = new wxExpr((double) point->x);
     wxExpr *y_expr = new wxExpr((double) point->y);
     point_list->Append(x_expr);
@@ -915,6 +815,53 @@ bool wxPolygonShape::AttachmentIsValid(int attachment)
   return FALSE;
 }
 
+// Rotate about the given axis by the given amount in radians
+void wxPolygonShape::Rotate(double x, double y, double theta)
+{
+    double actualTheta = theta-m_rotation;
+
+    // Rotate attachment points
+    double sinTheta = (double)sin(actualTheta);
+    double cosTheta = (double)cos(actualTheta);
+    wxNode *node = m_attachmentPoints.First();
+    while (node)
+    {
+        wxAttachmentPoint *point = (wxAttachmentPoint *)node->Data();
+        double x1 = point->m_x;
+        double y1 = point->m_y;
+        point->m_x = x1*cosTheta - y1*sinTheta + x*(1.0 - cosTheta) + y*sinTheta;
+        point->m_y = x1*sinTheta + y1*cosTheta + y*(1.0 - cosTheta) + x*sinTheta;
+        node = node->Next();
+    }
+
+    node = m_points->First();
+    while (node)
+    {
+        wxRealPoint *point = (wxRealPoint *)node->Data();
+        double x1 = point->x;
+        double y1 = point->y;
+        point->x = x1*cosTheta - y1*sinTheta + x*(1.0 - cosTheta) + y*sinTheta;
+        point->y = x1*sinTheta + y1*cosTheta + y*(1.0 - cosTheta) + x*sinTheta;
+        node = node->Next();
+    }
+    node = m_originalPoints->First();
+    while (node)
+    {
+        wxRealPoint *point = (wxRealPoint *)node->Data();
+        double x1 = point->x;
+        double y1 = point->y;
+        point->x = x1*cosTheta - y1*sinTheta + x*(1.0 - cosTheta) + y*sinTheta;
+        point->y = x1*sinTheta + y1*cosTheta + y*(1.0 - cosTheta) + x*sinTheta;
+        node = node->Next();
+    }
+
+    m_rotation = theta;
+
+    CalculatePolygonCentre();
+    CalculateBoundingBox();
+    ResetControlPoints();
+}
+
 // Rectangle object
 
 IMPLEMENT_DYNAMIC_CLASS(wxRectangleShape, wxShape)
@@ -1093,106 +1040,6 @@ bool wxRectangleShape::GetAttachmentPosition(int attachment, double *x, double *
       }
     }
 
-    // Old code
-#if 0
-    switch (attachment)
-    {
-      case 0:
-      {
-        if (m_spaceAttachments)
-        {
-          if (line && (line->GetAlignmentType(isEnd) == LINE_ALIGNMENT_TO_NEXT_HANDLE))
-          {
-            // Align line according to the next handle along
-            wxRealPoint *point = line->GetNextControlPoint(this);
-            if (point->x < left)
-              *x = left;
-            else if (point->x > right)
-              *x = right;
-            else
-              *x = point->x;
-          }
-          else
-            *x = left + (nth + 1)*m_width/(no_arcs + 1);
-        }
-        else *x = m_xpos;
-
-        *y = bottom;
-        break;
-      }
-      case 1:
-      {
-        *x = right;
-        if (m_spaceAttachments)
-        {
-          if (line && (line->GetAlignmentType(isEnd) == LINE_ALIGNMENT_TO_NEXT_HANDLE))
-          {
-            // Align line according to the next handle along
-            wxRealPoint *point = line->GetNextControlPoint(this);
-            if (point->y < bottom)
-              *y = bottom;
-            else if (point->y > top)
-              *y = top;
-            else
-              *y = point->y;
-          }
-          else
-            *y = bottom + (nth + 1)*m_height/(no_arcs + 1);
-        }
-        else *y = m_ypos;
-        break;
-      }
-      case 2:
-      {
-        if (m_spaceAttachments)
-        {
-          if (line && (line->GetAlignmentType(isEnd) == LINE_ALIGNMENT_TO_NEXT_HANDLE))
-          {
-            // Align line according to the next handle along
-            wxRealPoint *point = line->GetNextControlPoint(this);
-            if (point->x < left)
-              *x = left;
-            else if (point->x > right)
-              *x = right;
-            else
-              *x = point->x;
-          }
-          else
-            *x = left + (nth + 1)*m_width/(no_arcs + 1);
-        }
-        else *x = m_xpos;
-        *y = top;
-        break;
-      }
-      case 3:
-      {
-        *x = left;
-        if (m_spaceAttachments)
-        {
-          if (line && (line->GetAlignmentType(isEnd) == LINE_ALIGNMENT_TO_NEXT_HANDLE))
-          {
-            // Align line according to the next handle along
-            wxRealPoint *point = line->GetNextControlPoint(this);
-            if (point->y < bottom)
-              *y = bottom;
-            else if (point->y > top)
-              *y = top;
-            else
-              *y = point->y;
-          }
-          else
-            *y = bottom + (nth + 1)*m_height/(no_arcs + 1);
-        }
-        else *y = m_ypos;
-        break;
-      }
-      default:
-      {
-        return wxShape::GetAttachmentPosition(attachment, x, y, nth, no_arcs, line);
-        break;
-      }
-    }
-#endif
     return TRUE;
   }
   else
@@ -1397,6 +1244,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxCircleShape, wxEllipseShape)
 
 wxCircleShape::wxCircleShape(double diameter):wxEllipseShape(diameter, diameter)
 {
+    SetMaintainAspectRatio(TRUE);
 }
 
 void wxCircleShape::Copy(wxShape& copy)
@@ -1418,14 +1266,14 @@ bool wxCircleShape::GetPerimeterPoint(double x1, double y1,
 
 // Control points
 
-double wxControlPoint::controlPointDragStartX = 0.0;
-double wxControlPoint::controlPointDragStartY = 0.0;
-double wxControlPoint::controlPointDragStartWidth = 0.0;
-double wxControlPoint::controlPointDragStartHeight = 0.0;
-double wxControlPoint::controlPointDragEndWidth = 0.0;
-double wxControlPoint::controlPointDragEndHeight = 0.0;
-double wxControlPoint::controlPointDragPosX = 0.0;
-double wxControlPoint::controlPointDragPosY = 0.0;
+double wxControlPoint::sm_controlPointDragStartX = 0.0;
+double wxControlPoint::sm_controlPointDragStartY = 0.0;
+double wxControlPoint::sm_controlPointDragStartWidth = 0.0;
+double wxControlPoint::sm_controlPointDragStartHeight = 0.0;
+double wxControlPoint::sm_controlPointDragEndWidth = 0.0;
+double wxControlPoint::sm_controlPointDragEndHeight = 0.0;
+double wxControlPoint::sm_controlPointDragPosX = 0.0;
+double wxControlPoint::sm_controlPointDragPosY = 0.0;
 
 IMPLEMENT_DYNAMIC_CLASS(wxControlPoint, wxRectangleShape)
 
@@ -1517,9 +1365,23 @@ void wxShape::OnSizingDragLeft(wxControlPoint* pt, bool draw, double x, double y
 
     // Constrain sizing according to what control point you're dragging
     if (pt->m_type == CONTROL_POINT_HORIZONTAL)
-      new_height = bound_y;
+    {
+        if (GetMaintainAspectRatio())
+        {
+            new_height = bound_y*(new_width/bound_x);
+        }
+        else
+            new_height = bound_y;
+    }
     else if (pt->m_type == CONTROL_POINT_VERTICAL)
-      new_width = bound_x;
+    {
+        if (GetMaintainAspectRatio())
+        {
+            new_width = bound_x*(new_height/bound_y);
+        }
+        else
+            new_width = bound_x;
+    }
     else if (pt->m_type == CONTROL_POINT_DIAGONAL && (keys & KEY_SHIFT))
       new_height = bound_y*(new_width/bound_x);
 
@@ -1529,8 +1391,8 @@ void wxShape::OnSizingDragLeft(wxControlPoint* pt, bool draw, double x, double y
     if (this->GetFixedHeight())
       new_height = bound_y;
 
-    pt->controlPointDragEndWidth = new_width;
-    pt->controlPointDragEndHeight = new_height;
+    pt->sm_controlPointDragEndWidth = new_width;
+    pt->sm_controlPointDragEndHeight = new_height;
 
     this->GetEventHandler()->OnDrawOutline(dc, this->GetX(), this->GetY(),
                                 new_width, new_height);
@@ -1538,24 +1400,24 @@ void wxShape::OnSizingDragLeft(wxControlPoint* pt, bool draw, double x, double y
   else
   {
     // Don't maintain the same centre point!
-    double newX1 = wxMin(pt->controlPointDragStartX, x);
-    double newY1 = wxMin(pt->controlPointDragStartY, y);
-    double newX2 = wxMax(pt->controlPointDragStartX, x);
-    double newY2 = wxMax(pt->controlPointDragStartY, y);
+    double newX1 = wxMin(pt->sm_controlPointDragStartX, x);
+    double newY1 = wxMin(pt->sm_controlPointDragStartY, y);
+    double newX2 = wxMax(pt->sm_controlPointDragStartX, x);
+    double newY2 = wxMax(pt->sm_controlPointDragStartY, y);
     if (pt->m_type == CONTROL_POINT_HORIZONTAL)
     {
-      newY1 = pt->controlPointDragStartY;
-      newY2 = newY1 + pt->controlPointDragStartHeight;
+      newY1 = pt->sm_controlPointDragStartY;
+      newY2 = newY1 + pt->sm_controlPointDragStartHeight;
     }
     else if (pt->m_type == CONTROL_POINT_VERTICAL)
     {
-      newX1 = pt->controlPointDragStartX;
-      newX2 = newX1 + pt->controlPointDragStartWidth;
+      newX1 = pt->sm_controlPointDragStartX;
+      newX2 = newX1 + pt->sm_controlPointDragStartWidth;
     }
-    else if (pt->m_type == CONTROL_POINT_DIAGONAL && (keys & KEY_SHIFT))
+    else if (pt->m_type == CONTROL_POINT_DIAGONAL && ((keys & KEY_SHIFT) || GetMaintainAspectRatio()))
     {
-      double newH = (double)((newX2 - newX1)*(pt->controlPointDragStartHeight/pt->controlPointDragStartWidth));
-      if (GetY() > pt->controlPointDragStartY)
+      double newH = (double)((newX2 - newX1)*(pt->sm_controlPointDragStartHeight/pt->sm_controlPointDragStartWidth));
+      if (GetY() > pt->sm_controlPointDragStartY)
         newY2 = (double)(newY1 + newH);
       else
         newY1 = (double)(newY2 - newH);
@@ -1563,17 +1425,27 @@ void wxShape::OnSizingDragLeft(wxControlPoint* pt, bool draw, double x, double y
     double newWidth = (double)(newX2 - newX1);
     double newHeight = (double)(newY2 - newY1);
 
-    pt->controlPointDragPosX = (double)(newX1 + (newWidth/2.0));
-    pt->controlPointDragPosY = (double)(newY1 + (newHeight/2.0));
+    if (pt->m_type == CONTROL_POINT_VERTICAL && GetMaintainAspectRatio())
+    {
+        newWidth = bound_x * (newHeight/bound_y) ;
+    }
+
+    if (pt->m_type == CONTROL_POINT_HORIZONTAL && GetMaintainAspectRatio())
+    {
+        newHeight = bound_y * (newWidth/bound_x) ;
+    }
+
+    pt->sm_controlPointDragPosX = (double)(newX1 + (newWidth/2.0));
+    pt->sm_controlPointDragPosY = (double)(newY1 + (newHeight/2.0));
     if (this->GetFixedWidth())
       newWidth = bound_x;
      
     if (this->GetFixedHeight())
       newHeight = bound_y;
 
-    pt->controlPointDragEndWidth = newWidth;
-    pt->controlPointDragEndHeight = newHeight;
-    this->GetEventHandler()->OnDrawOutline(dc, pt->controlPointDragPosX, pt->controlPointDragPosY, newWidth, newHeight);
+    pt->sm_controlPointDragEndWidth = newWidth;
+    pt->sm_controlPointDragEndHeight = newHeight;
+    this->GetEventHandler()->OnDrawOutline(dc, pt->sm_controlPointDragPosX, pt->sm_controlPointDragPosY, newWidth, newHeight);
   }
 }
 
@@ -1597,23 +1469,23 @@ void wxShape::OnSizingBeginDragLeft(wxControlPoint* pt, double x, double y, int
   // Choose the 'opposite corner' of the object as the stationary
   // point in case this is non-centring resizing.
   if (pt->GetX() < this->GetX())
-    pt->controlPointDragStartX = (double)(this->GetX() + (bound_x/2.0));
+    pt->sm_controlPointDragStartX = (double)(this->GetX() + (bound_x/2.0));
   else
-    pt->controlPointDragStartX = (double)(this->GetX() - (bound_x/2.0));
+    pt->sm_controlPointDragStartX = (double)(this->GetX() - (bound_x/2.0));
 
   if (pt->GetY() < this->GetY())
-    pt->controlPointDragStartY = (double)(this->GetY() + (bound_y/2.0));
+    pt->sm_controlPointDragStartY = (double)(this->GetY() + (bound_y/2.0));
   else
-    pt->controlPointDragStartY = (double)(this->GetY() - (bound_y/2.0));
+    pt->sm_controlPointDragStartY = (double)(this->GetY() - (bound_y/2.0));
 
   if (pt->m_type == CONTROL_POINT_HORIZONTAL)
-    pt->controlPointDragStartY = (double)(this->GetY() - (bound_y/2.0));
+    pt->sm_controlPointDragStartY = (double)(this->GetY() - (bound_y/2.0));
   else if (pt->m_type == CONTROL_POINT_VERTICAL)
-    pt->controlPointDragStartX = (double)(this->GetX() - (bound_x/2.0));
+    pt->sm_controlPointDragStartX = (double)(this->GetX() - (bound_x/2.0));
 
   // We may require the old width and height.
-  pt->controlPointDragStartWidth = bound_x;
-  pt->controlPointDragStartHeight = bound_y;
+  pt->sm_controlPointDragStartWidth = bound_x;
+  pt->sm_controlPointDragStartHeight = bound_y;
 
   wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
   dc.SetPen(dottedPen);
@@ -1626,9 +1498,23 @@ void wxShape::OnSizingBeginDragLeft(wxControlPoint* pt, double x, double y, int
 
     // Constrain sizing according to what control point you're dragging
     if (pt->m_type == CONTROL_POINT_HORIZONTAL)
-      new_height = bound_y;
+    {
+        if (GetMaintainAspectRatio())
+        {
+            new_height = bound_y*(new_width/bound_x);
+        }
+        else
+            new_height = bound_y;
+    }
     else if (pt->m_type == CONTROL_POINT_VERTICAL)
-      new_width = bound_x;
+    {
+        if (GetMaintainAspectRatio())
+        {
+            new_width = bound_x*(new_height/bound_y);
+        }
+        else
+            new_width = bound_x;
+    }
     else if (pt->m_type == CONTROL_POINT_DIAGONAL && (keys & KEY_SHIFT))
       new_height = bound_y*(new_width/bound_x);
 
@@ -1638,32 +1524,32 @@ void wxShape::OnSizingBeginDragLeft(wxControlPoint* pt, double x, double y, int
     if (this->GetFixedHeight())
       new_height = bound_y;
 
-    pt->controlPointDragEndWidth = new_width;
-    pt->controlPointDragEndHeight = new_height;
+    pt->sm_controlPointDragEndWidth = new_width;
+    pt->sm_controlPointDragEndHeight = new_height;
     this->GetEventHandler()->OnDrawOutline(dc, this->GetX(), this->GetY(),
                                 new_width, new_height);
   }
   else
   {
     // Don't maintain the same centre point!
-    double newX1 = wxMin(pt->controlPointDragStartX, x);
-    double newY1 = wxMin(pt->controlPointDragStartY, y);
-    double newX2 = wxMax(pt->controlPointDragStartX, x);
-    double newY2 = wxMax(pt->controlPointDragStartY, y);
+    double newX1 = wxMin(pt->sm_controlPointDragStartX, x);
+    double newY1 = wxMin(pt->sm_controlPointDragStartY, y);
+    double newX2 = wxMax(pt->sm_controlPointDragStartX, x);
+    double newY2 = wxMax(pt->sm_controlPointDragStartY, y);
     if (pt->m_type == CONTROL_POINT_HORIZONTAL)
     {
-      newY1 = pt->controlPointDragStartY;
-      newY2 = newY1 + pt->controlPointDragStartHeight;
+      newY1 = pt->sm_controlPointDragStartY;
+      newY2 = newY1 + pt->sm_controlPointDragStartHeight;
     }
     else if (pt->m_type == CONTROL_POINT_VERTICAL)
     {
-      newX1 = pt->controlPointDragStartX;
-      newX2 = newX1 + pt->controlPointDragStartWidth;
+      newX1 = pt->sm_controlPointDragStartX;
+      newX2 = newX1 + pt->sm_controlPointDragStartWidth;
     }
-    else if (pt->m_type == CONTROL_POINT_DIAGONAL && (keys & KEY_SHIFT))
+    else if (pt->m_type == CONTROL_POINT_DIAGONAL && ((keys & KEY_SHIFT) || GetMaintainAspectRatio()))
     {
-      double newH = (double)((newX2 - newX1)*(pt->controlPointDragStartHeight/pt->controlPointDragStartWidth));
-      if (pt->GetY() > pt->controlPointDragStartY)
+      double newH = (double)((newX2 - newX1)*(pt->sm_controlPointDragStartHeight/pt->sm_controlPointDragStartWidth));
+      if (pt->GetY() > pt->sm_controlPointDragStartY)
         newY2 = (double)(newY1 + newH);
       else
         newY1 = (double)(newY2 - newH);
@@ -1671,17 +1557,27 @@ void wxShape::OnSizingBeginDragLeft(wxControlPoint* pt, double x, double y, int
     double newWidth = (double)(newX2 - newX1);
     double newHeight = (double)(newY2 - newY1);
 
-    pt->controlPointDragPosX = (double)(newX1 + (newWidth/2.0));
-    pt->controlPointDragPosY = (double)(newY1 + (newHeight/2.0));
+    if (pt->m_type == CONTROL_POINT_VERTICAL && GetMaintainAspectRatio())
+    {
+        newWidth = bound_x * (newHeight/bound_y) ;
+    }
+
+    if (pt->m_type == CONTROL_POINT_HORIZONTAL && GetMaintainAspectRatio())
+    {
+        newHeight = bound_y * (newWidth/bound_x) ;
+    }
+
+    pt->sm_controlPointDragPosX = (double)(newX1 + (newWidth/2.0));
+    pt->sm_controlPointDragPosY = (double)(newY1 + (newHeight/2.0));
     if (this->GetFixedWidth())
       newWidth = bound_x;
 
     if (this->GetFixedHeight())
       newHeight = bound_y;
 
-    pt->controlPointDragEndWidth = newWidth;
-    pt->controlPointDragEndHeight = newHeight;
-    this->GetEventHandler()->OnDrawOutline(dc, pt->controlPointDragPosX, pt->controlPointDragPosY, newWidth, newHeight);
+    pt->sm_controlPointDragEndWidth = newWidth;
+    pt->sm_controlPointDragEndHeight = newHeight;
+    this->GetEventHandler()->OnDrawOutline(dc, pt->sm_controlPointDragPosX, pt->sm_controlPointDragPosY, newWidth, newHeight);
   }
 }
 
@@ -1701,7 +1597,7 @@ void wxShape::OnSizingEndDragLeft(wxControlPoint* pt, double x, double y, int ke
     this->Show(FALSE);
 */
 
-  this->SetSize(pt->controlPointDragEndWidth, pt->controlPointDragEndHeight);
+  this->SetSize(pt->sm_controlPointDragEndWidth, pt->sm_controlPointDragEndHeight);
 
   // The next operation could destroy this control point (it does for label objects,
   // via formatting the text), so save all values we're going to use, or
@@ -1713,7 +1609,7 @@ void wxShape::OnSizingEndDragLeft(wxControlPoint* pt, double x, double y, int ke
   if (theObject->GetCentreResize())
     theObject->Move(dc, theObject->GetX(), theObject->GetY());
   else
-    theObject->Move(dc, pt->controlPointDragPosX, pt->controlPointDragPosY);
+    theObject->Move(dc, pt->sm_controlPointDragPosX, pt->sm_controlPointDragPosY);
 
 /*
   if (!eraseIt)
diff --git a/utils/ogl/src/basicp.h b/utils/ogl/src/basicp.h
index 6b5cbd94a0..aa1067764f 100644
--- a/utils/ogl/src/basicp.h
+++ b/utils/ogl/src/basicp.h
@@ -78,14 +78,14 @@ public:
  * Store original top-left, bottom-right coordinates
  * in case we're doing non-vertical resizing.
  */
-  static double controlPointDragStartX;
-  static double controlPointDragStartY;
-  static double controlPointDragStartWidth;
-  static double controlPointDragStartHeight;
-  static double controlPointDragEndWidth;
-  static double controlPointDragEndHeight;
-  static double controlPointDragPosX;
-  static double controlPointDragPosY;
+  static double sm_controlPointDragStartX;
+  static double sm_controlPointDragStartY;
+  static double sm_controlPointDragStartWidth;
+  static double sm_controlPointDragStartHeight;
+  static double sm_controlPointDragEndWidth;
+  static double sm_controlPointDragEndHeight;
+  static double sm_controlPointDragPosX;
+  static double sm_controlPointDragPosY;
 };
 
 class wxPolygonShape;
diff --git a/utils/ogl/src/composit.cpp b/utils/ogl/src/composit.cpp
index 198f4b0ff9..8d1e60add6 100644
--- a/utils/ogl/src/composit.cpp
+++ b/utils/ogl/src/composit.cpp
@@ -620,15 +620,15 @@ void wxCompositeShape::WriteAttributes(wxExpr *clause)
 
     // Each constraint is stored in the form
     // (type name id xspacing yspacing m_constrainingObjectId constrainedObjectIdList)
-    wxExpr *constraintExpr = new wxExpr(PrologList);
+    wxExpr *constraintExpr = new wxExpr(wxExprList);
     constraintExpr->Append(new wxExpr((long)constraint->m_constraintType));
-    constraintExpr->Append(new wxExpr(PrologString, constraint->m_constraintName));
+    constraintExpr->Append(new wxExpr(wxExprString, constraint->m_constraintName));
     constraintExpr->Append(new wxExpr(constraint->m_constraintId));
     constraintExpr->Append(new wxExpr(constraint->m_xSpacing));
     constraintExpr->Append(new wxExpr(constraint->m_ySpacing));
     constraintExpr->Append(new wxExpr(constraint->m_constrainingObject->GetId()));
 
-    wxExpr *objectList = new wxExpr(PrologList);
+    wxExpr *objectList = new wxExpr(wxExprList);
     wxNode *node1 = constraint->m_constrainedObjects.First();
     while (node1)
     {
@@ -645,7 +645,7 @@ void wxCompositeShape::WriteAttributes(wxExpr *clause)
   }
 
   // Write the ids of all the child images
-  wxExpr *childrenExpr = new wxExpr(PrologList);
+  wxExpr *childrenExpr = new wxExpr(wxExprList);
   node = m_children.First();
   while (node)
   {
@@ -658,7 +658,7 @@ void wxCompositeShape::WriteAttributes(wxExpr *clause)
   // Write the ids of all the division images
   if (m_divisions.Number() > 0)
   {
-    wxExpr *divisionsExpr = new wxExpr(PrologList);
+    wxExpr *divisionsExpr = new wxExpr(wxExprList);
     node = m_divisions.First();
     while (node)
     {
diff --git a/utils/ogl/src/composit.h b/utils/ogl/src/composit.h
index c667e38d87..505667c2bd 100644
--- a/utils/ogl/src/composit.h
+++ b/utils/ogl/src/composit.h
@@ -78,7 +78,6 @@ public:
   void CalculateSize();
 
 #ifdef PROLOGIO
-  // Prolog database stuff
   void WriteAttributes(wxExpr *clause);
   void ReadAttributes(wxExpr *clause);
   // In case the object has constraints it needs to read in in a different pass
@@ -154,7 +153,6 @@ class wxDivisionShape: public wxCompositeShape
   void ResetMandatoryControlPoints();
 
 #ifdef PROLOGIO
-  // Prolog database stuff
   void WriteAttributes(wxExpr *clause);
   void ReadAttributes(wxExpr *clause);
 #endif
diff --git a/utils/ogl/src/divided.h b/utils/ogl/src/divided.h
index 9d7093913e..f8404637df 100644
--- a/utils/ogl/src/divided.h
+++ b/utils/ogl/src/divided.h
@@ -47,7 +47,6 @@ class wxDividedShape: public wxRectangleShape
   void ResetMandatoryControlPoints();
 
 #ifdef PROLOGIO
-  // Prolog database stuff
   void WriteAttributes(wxExpr *clause);
   void ReadAttributes(wxExpr *clause);
 #endif
diff --git a/utils/ogl/src/drawn.cpp b/utils/ogl/src/drawn.cpp
index 178dcfaf9a..f6d8f33a98 100644
--- a/utils/ogl/src/drawn.cpp
+++ b/utils/ogl/src/drawn.cpp
@@ -240,6 +240,7 @@ void wxDrawnShape::WriteAttributes(wxExpr *clause)
 {
   wxRectangleShape::WriteAttributes(clause);
 
+  clause->AddAttributeValue("current_angle", (long)m_currentAngle);
   clause->AddAttributeValue("save_metafile", (long)m_saveToFile);
   if (m_saveToFile)
   {
@@ -257,7 +258,8 @@ void wxDrawnShape::ReadAttributes(wxExpr *clause)
   wxRectangleShape::ReadAttributes(clause);
 
   int iVal = (int) m_saveToFile;
-  clause->AssignAttributeValue("save_metafile", &iVal);
+  clause->GetAttributeValue("save_metafile", iVal);
+  clause->GetAttributeValue("current_angle", m_currentAngle);
   m_saveToFile = (iVal != 0);
 
   if (m_saveToFile)
@@ -521,7 +523,7 @@ wxDrawOp *wxOpSetGDI::Copy(wxPseudoMetaFile *newImage)
 
 wxExpr *wxOpSetGDI::WriteExpr(wxPseudoMetaFile *image)
 {
-  wxExpr *expr = new wxExpr(PrologList);
+  wxExpr *expr = new wxExpr(wxExprList);
   expr->Append(new wxExpr((long)m_op));
   switch (m_op)
   {
@@ -635,7 +637,7 @@ void wxOpSetClipping::Translate(double x, double y)
 
 wxExpr *wxOpSetClipping::WriteExpr(wxPseudoMetaFile *image)
 {
-  wxExpr *expr = new wxExpr(PrologList);
+  wxExpr *expr = new wxExpr(wxExprList);
   expr->Append(new wxExpr((long)m_op));
   switch (m_op)
   {
@@ -879,7 +881,7 @@ void wxOpDraw::Rotate(double x, double y, double theta, double sinTheta, double
 
 wxExpr *wxOpDraw::WriteExpr(wxPseudoMetaFile *image)
 {
-  wxExpr *expr = new wxExpr(PrologList);
+  wxExpr *expr = new wxExpr(wxExprList);
   expr->Append(new wxExpr((long)m_op));
   switch (m_op)
   {
@@ -912,7 +914,7 @@ wxExpr *wxOpDraw::WriteExpr(wxPseudoMetaFile *image)
     {
       expr->Append(new wxExpr(m_x1));
       expr->Append(new wxExpr(m_y1));
-      expr->Append(new wxExpr(PrologString, m_textString));
+      expr->Append(new wxExpr(wxExprString, m_textString));
       break;
     }
     case DRAWOP_DRAW_ARC:
@@ -1103,7 +1105,7 @@ void wxOpPolyDraw::Rotate(double x, double y, double theta, double sinTheta, dou
 
 wxExpr *wxOpPolyDraw::WriteExpr(wxPseudoMetaFile *image)
 {
-  wxExpr *expr = new wxExpr(PrologList);
+  wxExpr *expr = new wxExpr(wxExprList);
   expr->Append(new wxExpr((long)m_op));
   expr->Append(new wxExpr((long)m_noPoints));
 
@@ -1140,7 +1142,7 @@ wxExpr *wxOpPolyDraw::WriteExpr(wxPseudoMetaFile *image)
       strcat(oglBuffer, buf3);
     }
   }
-  expr->Append(new wxExpr(PrologString, oglBuffer));
+  expr->Append(new wxExpr(wxExprString, oglBuffer));
   return expr;
 }
 
@@ -1480,7 +1482,7 @@ void wxPseudoMetaFile::WriteAttributes(wxExpr *clause, int whichAngle)
       if (obj->IsKindOf(CLASSINFO(wxPen)))
       {
         wxPen *thePen = (wxPen *)obj;
-        expr = new wxExpr(PrologList);
+        expr = new wxExpr(wxExprList);
         expr->Append(new wxExpr((long)gyTYPE_PEN));
         expr->Append(new wxExpr((long)thePen->GetWidth()));
         expr->Append(new wxExpr((long)thePen->GetStyle()));
@@ -1491,7 +1493,7 @@ void wxPseudoMetaFile::WriteAttributes(wxExpr *clause, int whichAngle)
       else if (obj->IsKindOf(CLASSINFO(wxBrush)))
       {
         wxBrush *theBrush = (wxBrush *)obj;
-        expr = new wxExpr(PrologList);
+        expr = new wxExpr(wxExprList);
         expr->Append(new wxExpr((long)gyTYPE_BRUSH));
         expr->Append(new wxExpr((long)theBrush->GetStyle()));
         expr->Append(new wxExpr((long)theBrush->GetColour().Red()));
@@ -1501,7 +1503,7 @@ void wxPseudoMetaFile::WriteAttributes(wxExpr *clause, int whichAngle)
       else if (obj->IsKindOf(CLASSINFO(wxFont)))
       {
         wxFont *theFont = (wxFont *)obj;
-        expr = new wxExpr(PrologList);
+        expr = new wxExpr(wxExprList);
         expr->Append(new wxExpr((long)gyTYPE_FONT));
         expr->Append(new wxExpr((long)theFont->GetPointSize()));
         expr->Append(new wxExpr((long)theFont->GetFamily()));
@@ -1513,7 +1515,7 @@ void wxPseudoMetaFile::WriteAttributes(wxExpr *clause, int whichAngle)
     else
     {
       // If no recognised GDI object, append a place holder anyway.
-      expr = new wxExpr(PrologList);
+      expr = new wxExpr(wxExprList);
       expr->Append(new wxExpr((long)0));
     }
 
@@ -1544,7 +1546,7 @@ void wxPseudoMetaFile::WriteAttributes(wxExpr *clause, int whichAngle)
   // Write outline and fill GDI op lists (if any)
   if (m_outlineColours.Number() > 0)
   {
-    wxExpr *outlineExpr = new wxExpr(PrologList);
+    wxExpr *outlineExpr = new wxExpr(wxExprList);
     node = m_outlineColours.First();
     while (node)
     {
@@ -1558,7 +1560,7 @@ void wxPseudoMetaFile::WriteAttributes(wxExpr *clause, int whichAngle)
   }
   if (m_fillColours.Number() > 0)
   {
-    wxExpr *fillExpr = new wxExpr(PrologList);
+    wxExpr *fillExpr = new wxExpr(wxExprList);
     node = m_fillColours.First();
     while (node)
     {
diff --git a/utils/ogl/src/lines.cpp b/utils/ogl/src/lines.cpp
index a3e1222bfe..90a524d118 100644
--- a/utils/ogl/src/lines.cpp
+++ b/utils/ogl/src/lines.cpp
@@ -1393,12 +1393,12 @@ void wxLineShape::WriteAttributes(wxExpr *clause)
     clause->AddAttributeValue("keep_lines_straight", (long)m_maintainStraightLines);
 
   // Make a list of lists for the (sp)line controls
-  wxExpr *list = new wxExpr(PrologList);
+  wxExpr *list = new wxExpr(wxExprList);
   wxNode *node = m_lineControlPoints->First();
   while (node)
   {
     wxRealPoint *point = (wxRealPoint *)node->Data();
-    wxExpr *point_list = new wxExpr(PrologList);
+    wxExpr *point_list = new wxExpr(wxExprList);
     wxExpr *x_expr = new wxExpr((double) point->x);
     wxExpr *y_expr = new wxExpr((double) point->y);
     point_list->Append(x_expr);
@@ -1414,17 +1414,17 @@ void wxLineShape::WriteAttributes(wxExpr *clause)
   // (arrowType arrowEnd xOffset arrowSize)
   if (m_arcArrows.Number() > 0)
   {
-    wxExpr *arrow_list = new wxExpr(PrologList);
+    wxExpr *arrow_list = new wxExpr(wxExprList);
     node = m_arcArrows.First();
     while (node)
     {
       wxArrowHead *head = (wxArrowHead *)node->Data();
-      wxExpr *head_list = new wxExpr(PrologList);
+      wxExpr *head_list = new wxExpr(wxExprList);
       head_list->Append(new wxExpr((long)head->_GetType()));
       head_list->Append(new wxExpr((long)head->GetArrowEnd()));
       head_list->Append(new wxExpr(head->GetXOffset()));
       head_list->Append(new wxExpr(head->GetArrowSize()));
-      head_list->Append(new wxExpr(PrologString, (head->GetName() ? head->GetName() : "")));
+      head_list->Append(new wxExpr(wxExprString, (head->GetName() ? head->GetName() : "")));
       head_list->Append(new wxExpr(head->GetId()));
 
       // New members of wxArrowHead
diff --git a/utils/ogl/src/ogldiag.cpp b/utils/ogl/src/ogldiag.cpp
index ed50ec51f5..35deb671dd 100644
--- a/utils/ogl/src/ogldiag.cpp
+++ b/utils/ogl/src/ogldiag.cpp
@@ -300,7 +300,7 @@ bool wxDiagram::LoadFile(const wxString& filename)
 {
   wxBeginBusyCursor();
   
-  wxExprDatabase database(PrologInteger, "id");
+  wxExprDatabase database(wxExprInteger, "id");
   if (!database.Read(filename))
   {
     wxEndBusyCursor();
@@ -578,4 +578,17 @@ void wxDiagram::SetCanvas(wxShapeCanvas *can)
   m_diagramCanvas = can;
 }
 
+// Find a shape by its id
+wxShape* wxDiagram::FindShape(long id) const
+{
+    wxNode* node = GetShapeList()->First();
+    while (node)
+    {
+        wxShape* shape = (wxShape*) node->Data();
+        if (shape->GetId() == id)
+            return shape;
+        node = node->Next();
+    }
+    return NULL;
+}
 
diff --git a/utils/ogl/src/ogldiag.h b/utils/ogl/src/ogldiag.h
index 1654831f8e..485857e440 100644
--- a/utils/ogl/src/ogldiag.h
+++ b/utils/ogl/src/ogldiag.h
@@ -56,15 +56,18 @@ public:
   virtual void DeleteAllShapes();
   virtual void ShowAll(bool show);
 
+  // Find a shape by its id
+  wxShape* FindShape(long id) const;
+
   inline void SetMouseTolerance(int tol) { m_mouseTolerance = tol; }
   inline int GetMouseTolerance() const { return m_mouseTolerance; }
   inline wxList *GetShapeList() const { return m_shapeList; }
+  inline int GetCount() const { return m_shapeList->Number(); }
 
   // Make sure all text that should be centred, is centred.
   void RecentreAll(wxDC& dc);
 
 #ifdef PROLOGIO
-  // Prolog database stuff
   virtual bool SaveFile(const wxString& filename);
   virtual bool LoadFile(const wxString& filename);
 
-- 
2.50.0

