#include <wx/wx.h>
#endif
-#ifdef PROLOGIO
#include <wx/wxexpr.h>
-#endif
-#if USE_IOSTREAMH
+#if wxUSE_IOSTREAMH
#include <iostream.h>
#else
#include <iostream>
IMPLEMENT_DYNAMIC_CLASS(wxShapeTextLine, wxObject)
IMPLEMENT_DYNAMIC_CLASS(wxAttachmentPoint, wxObject)
-wxShapeTextLine::wxShapeTextLine(float the_x, float the_y, const wxString& the_line)
+wxShapeTextLine::wxShapeTextLine(double the_x, double the_y, const wxString& the_line)
{
m_x = the_x; m_y = the_y; m_line = the_line;
}
{
}
+// Creates a copy of this event handler.
+wxShapeEvtHandler* wxShapeEvtHandler::CreateNewCopy()
+{
+ wxShapeEvtHandler* newObject = (wxShapeEvtHandler*) GetClassInfo()->CreateObject();
+
+ wxASSERT( (newObject != NULL) );
+ wxASSERT( (newObject->IsKindOf(CLASSINFO(wxShapeEvtHandler))) );
+
+ newObject->m_previousHandler = newObject;
+
+ CopyData(*newObject);
+
+ return newObject;
+}
+
+
void wxShapeEvtHandler::OnDelete()
{
if (this != GetShape())
m_previousHandler->OnDrawContents(dc);
}
-void wxShapeEvtHandler::OnSize(float x, float y)
+void wxShapeEvtHandler::OnDrawBranches(wxDC& dc, bool erase)
+{
+ if (m_previousHandler)
+ m_previousHandler->OnDrawBranches(dc, erase);
+}
+
+void wxShapeEvtHandler::OnSize(double x, double y)
{
if (m_previousHandler)
m_previousHandler->OnSize(x, y);
}
-bool wxShapeEvtHandler::OnMovePre(wxDC& dc, float x, float y, float old_x, float old_y, bool display)
+bool wxShapeEvtHandler::OnMovePre(wxDC& dc, double x, double y, double old_x, double old_y, bool display)
{
if (m_previousHandler)
return m_previousHandler->OnMovePre(dc, x, y, old_x, old_y, display);
return TRUE;
}
-void wxShapeEvtHandler::OnMovePost(wxDC& dc, float x, float y, float old_x, float old_y, bool display)
+void wxShapeEvtHandler::OnMovePost(wxDC& dc, double x, double y, double old_x, double old_y, bool display)
{
if (m_previousHandler)
m_previousHandler->OnMovePost(dc, x, y, old_x, old_y, display);
m_previousHandler->OnHighlight(dc);
}
-void wxShapeEvtHandler::OnLeftClick(float x, float y, int keys, int attachment)
+void wxShapeEvtHandler::OnLeftClick(double x, double y, int keys, int attachment)
{
if (m_previousHandler)
m_previousHandler->OnLeftClick(x, y, keys, attachment);
}
-void wxShapeEvtHandler::OnRightClick(float x, float y, int keys, int attachment)
+void wxShapeEvtHandler::OnLeftDoubleClick(double x, double y, int keys, int attachment)
+{
+ if (m_previousHandler)
+ m_previousHandler->OnLeftDoubleClick(x, y, keys, attachment);
+}
+
+void wxShapeEvtHandler::OnRightClick(double x, double y, int keys, int attachment)
{
if (m_previousHandler)
m_previousHandler->OnRightClick(x, y, keys, attachment);
}
-void wxShapeEvtHandler::OnDragLeft(bool draw, float x, float y, int keys, int attachment)
+void wxShapeEvtHandler::OnDragLeft(bool draw, double x, double y, int keys, int attachment)
{
if (m_previousHandler)
m_previousHandler->OnDragLeft(draw, x, y, keys, attachment);
}
-void wxShapeEvtHandler::OnBeginDragLeft(float x, float y, int keys, int attachment)
+void wxShapeEvtHandler::OnBeginDragLeft(double x, double y, int keys, int attachment)
{
if (m_previousHandler)
m_previousHandler->OnBeginDragLeft(x, y, keys, attachment);
}
-void wxShapeEvtHandler::OnEndDragLeft(float x, float y, int keys, int attachment)
+void wxShapeEvtHandler::OnEndDragLeft(double x, double y, int keys, int attachment)
{
if (m_previousHandler)
m_previousHandler->OnEndDragLeft(x, y, keys, attachment);
}
-void wxShapeEvtHandler::OnDragRight(bool draw, float x, float y, int keys, int attachment)
+void wxShapeEvtHandler::OnDragRight(bool draw, double x, double y, int keys, int attachment)
{
if (m_previousHandler)
m_previousHandler->OnDragRight(draw, x, y, keys, attachment);
}
-void wxShapeEvtHandler::OnBeginDragRight(float x, float y, int keys, int attachment)
+void wxShapeEvtHandler::OnBeginDragRight(double x, double y, int keys, int attachment)
{
if (m_previousHandler)
m_previousHandler->OnBeginDragRight(x, y, keys, attachment);
}
-void wxShapeEvtHandler::OnEndDragRight(float x, float y, int keys, int attachment)
+void wxShapeEvtHandler::OnEndDragRight(double x, double y, int keys, int attachment)
{
if (m_previousHandler)
m_previousHandler->OnEndDragRight(x, y, keys, attachment);
}
-void wxShapeEvtHandler::OnDrawOutline(wxDC& dc, float x, float y, float w, float h)
+// Control points ('handles') redirect control to the actual shape, to make it easier
+// to override sizing behaviour.
+void wxShapeEvtHandler::OnSizingDragLeft(wxControlPoint* pt, bool draw, double x, double y, int keys, int attachment)
+{
+ if (m_previousHandler)
+ m_previousHandler->OnSizingDragLeft(pt, draw, x, y, keys, attachment);
+}
+
+void wxShapeEvtHandler::OnSizingBeginDragLeft(wxControlPoint* pt, double x, double y, int keys, int attachment)
+{
+ if (m_previousHandler)
+ m_previousHandler->OnSizingBeginDragLeft(pt, x, y, keys, attachment);
+}
+
+void wxShapeEvtHandler::OnSizingEndDragLeft(wxControlPoint* pt, double x, double y, int keys, int attachment)
+{
+ if (m_previousHandler)
+ m_previousHandler->OnSizingEndDragLeft(pt, x, y, keys, attachment);
+}
+
+void wxShapeEvtHandler::OnDrawOutline(wxDC& dc, double x, double y, double w, double h)
{
if (m_previousHandler)
m_previousHandler->OnDrawOutline(dc, x, y, w, h);
m_previousHandler->OnEraseControlPoints(dc);
}
+// Can override this to prevent or intercept line reordering.
+void wxShapeEvtHandler::OnChangeAttachment(int attachment, wxLineShape* line, wxList& ordering)
+{
+ if (m_previousHandler)
+ m_previousHandler->OnChangeAttachment(attachment, line, ordering);
+}
+
IMPLEMENT_ABSTRACT_CLASS(wxShape, wxShapeEvtHandler)
wxShape::wxShape(wxShapeCanvas *can)
{
m_eventHandler = this;
- SetHandlerShape(this);
+ SetShape(this);
m_id = 0;
m_formatted = FALSE;
m_canvas = can;
m_xpos = 0.0; m_ypos = 0.0;
- m_pen = black_pen;
+ m_pen = g_oglBlackPen;
m_brush = wxWHITE_BRUSH;
m_font = g_oglNormalFont;
m_textColour = wxBLACK;
m_visible = FALSE;
m_clientData = NULL;
m_selected = FALSE;
- m_attachmentMode = FALSE;
+ m_attachmentMode = ATTACHMENT_MODE_NONE;
m_spaceAttachments = TRUE;
m_disableLabel = FALSE;
m_fixedWidth = FALSE;
m_textMarginY = 5.0;
m_regionName = "0";
m_centreResize = TRUE;
+ m_maintainAspectRatio = FALSE;
m_highlighted = FALSE;
m_rotation = 0.0;
+ m_branchNeckLength = 10;
+ m_branchStemLength = 10;
+ m_branchSpacing = 10;
+ m_branchStyle = BRANCHING_ATTACHMENT_NORMAL;
// Set up a default region. Much of the above will be put into
// the region eventually (the duplication is for compatibility)
wxNode *node = m_regions.First();
if (!node) return;
wxShapeRegion *region = (wxShapeRegion *)node->Data();
- float w, h;
+ double w, h;
GetBoundingBoxMin(&w, &h);
region->SetSize(w, h);
}
-bool wxShape::HitTest(float x, float y, int *attachment, float *distance)
+bool wxShape::HitTest(double x, double y, int *attachment, double *distance)
{
// if (!sensitive)
// return FALSE;
- float width = 0.0, height = 0.0;
+ double width = 0.0, height = 0.0;
GetBoundingBoxMin(&width, &height);
if (fabs(width) < 4.0) width = 4.0;
if (fabs(height) < 4.0) height = 4.0;
- width += (float)4.0; height += (float)4.0; // Allowance for inaccurate mousing
+ width += (double)4.0; height += (double)4.0; // Allowance for inaccurate mousing
- float left = (float)(m_xpos - (width/2.0));
- float top = (float)(m_ypos - (height/2.0));
- float right = (float)(m_xpos + (width/2.0));
- float bottom = (float)(m_ypos + (height/2.0));
+ double left = (double)(m_xpos - (width/2.0));
+ double top = (double)(m_ypos - (height/2.0));
+ double right = (double)(m_xpos + (width/2.0));
+ double bottom = (double)(m_ypos + (height/2.0));
int nearest_attachment = 0;
-
// If within the bounding box, check the attachment points
// within the object.
if (x >= left && x <= right && y >= top && y <= bottom)
{
int n = GetNumberOfAttachments();
- float nearest = 999999.0;
+ double nearest = 999999.0;
+
+ // GetAttachmentPosition[Edge] takes a logical attachment position,
+ // i.e. if it's rotated through 90%, position 0 is East-facing.
for (int i = 0; i < n; i++)
{
- float xp, yp;
- if (GetAttachmentPosition(i, &xp, &yp))
+ double xp, yp;
+ if (GetAttachmentPositionEdge(i, &xp, &yp))
{
- float l = (float)sqrt(((xp - x) * (xp - x)) +
+ double l = (double)sqrt(((xp - x) * (xp - x)) +
((yp - y) * (yp - y)));
if (l < nearest)
static bool GraphicsInSizeToContents = FALSE; // Infinite recursion elimination
void wxShape::FormatText(wxDC& dc, const wxString& s, int i)
{
- float w, h;
+ double w, h;
ClearText(i);
if (m_regions.Number() < 1)
region->GetSize(&w, &h);
- wxList *string_list = ::FormatText(dc, s, (w-5), (h-5), region->GetFormatMode());
- node = string_list->First();
+ wxStringList *stringList = oglFormatText(dc, s, (w-5), (h-5), region->GetFormatMode());
+ node = stringList->First();
while (node)
{
char *s = (char *)node->Data();
wxShapeTextLine *line = new wxShapeTextLine(0.0, 0.0, s);
region->GetFormattedText().Append((wxObject *)line);
- delete node;
- node = string_list->First();
+ node = node->Next();
}
- delete string_list;
- float actualW = w;
- float actualH = h;
+ delete stringList;
+ double actualW = w;
+ double actualH = h;
// Don't try to resize an object with more than one image (this case should be dealt
// with by overriden handlers)
if ((region->GetFormatMode() & FORMAT_SIZE_TO_CONTENTS) &&
(region->GetFormattedText().Number() > 0) &&
(m_regions.Number() == 1) && !GraphicsInSizeToContents)
{
- GetCentredTextExtent(dc, &(region->GetFormattedText()), m_xpos, m_ypos, w, h, &actualW, &actualH);
+ oglGetCentredTextExtent(dc, &(region->GetFormattedText()), m_xpos, m_ypos, w, h, &actualW, &actualH);
if ((actualW+m_textMarginX != w ) || (actualH+m_textMarginY != h))
{
// If we are a descendant of a composite, must make sure the composite gets
EraseContents(dc);
}
}
- CentreText(dc, &(region->GetFormattedText()), m_xpos, m_ypos, actualW, actualH, region->GetFormatMode());
+ oglCentreText(dc, &(region->GetFormattedText()), m_xpos, m_ypos, actualW, actualH, region->GetFormatMode());
m_formatted = TRUE;
}
void wxShape::Recentre(wxDC& dc)
{
- float w, h;
+ double w, h;
GetBoundingBoxMin(&w, &h);
int noRegions = m_regions.Number();
if (node)
{
wxShapeRegion *region = (wxShapeRegion *)node->Data();
- CentreText(dc, &(region->GetFormattedText()), m_xpos, m_ypos, w, h, region->GetFormatMode());
+ oglCentreText(dc, &(region->GetFormattedText()), m_xpos, m_ypos, w, h, region->GetFormatMode());
}
}
}
-bool wxShape::GetPerimeterPoint(float x1, float y1,
- float x2, float y2,
- float *x3, float *y3)
+bool wxShape::GetPerimeterPoint(double x1, double y1,
+ double x2, double y2,
+ double *x3, double *y3)
{
return FALSE;
}
void wxShape::AssignNewIds()
{
- if (m_id == 0)
- m_id = NewId();
+// if (m_id == 0)
+ m_id = NewId();
wxNode *node = m_children.First();
while (node)
{
void wxShape::OnDrawContents(wxDC& dc)
{
- float bound_x, bound_y;
+ double bound_x, bound_y;
GetBoundingBoxMin(&bound_x, &bound_y);
if (m_regions.Number() < 1) return;
dc.SetBackgroundMode(wxTRANSPARENT);
if (!m_formatted)
{
- CentreText(dc, &(region->GetFormattedText()), m_xpos, m_ypos, bound_x, bound_y, region->GetFormatMode());
+ oglCentreText(dc, &(region->GetFormattedText()), m_xpos, m_ypos, bound_x, bound_y, region->GetFormatMode());
m_formatted = TRUE;
}
if (!GetDisableLabel())
{
- DrawFormattedText(dc, &(region->GetFormattedText()), m_xpos, m_ypos, bound_x, bound_y, region->GetFormatMode());
+ oglDrawFormattedText(dc, &(region->GetFormattedText()), m_xpos, m_ypos, bound_x, bound_y, region->GetFormatMode());
}
}
GetEventHandler()->OnDrawContents(dc);
}
-void wxShape::OnSize(float x, float y)
+void wxShape::OnSize(double x, double y)
{
}
-bool wxShape::OnMovePre(wxDC& dc, float x, float y, float old_x, float old_y, bool display)
+bool wxShape::OnMovePre(wxDC& dc, double x, double y, double old_x, double old_y, bool display)
{
return TRUE;
}
-void wxShape::OnMovePost(wxDC& dc, float x, float y, float old_x, float old_y, bool display)
+void wxShape::OnMovePost(wxDC& dc, double x, double y, double old_x, double old_y, bool display)
{
}
if (!m_visible)
return;
- float maxX, maxY, minX, minY;
- float xp = GetX();
- float yp = GetY();
+ double maxX, maxY, minX, minY;
+ double xp = GetX();
+ double yp = GetY();
GetBoundingBoxMin(&minX, &minY);
GetBoundingBoxMax(&maxX, &maxY);
- float topLeftX = (float)(xp - (maxX / 2.0) - 2.0);
- float topLeftY = (float)(yp - (maxY / 2.0) - 2.0);
+ double topLeftX = (double)(xp - (maxX / 2.0) - 2.0);
+ double topLeftY = (double)(yp - (maxY / 2.0) - 2.0);
int penWidth = 0;
if (m_pen)
penWidth = m_pen->GetWidth();
- dc.SetPen(white_background_pen);
- dc.SetBrush(white_background_brush);
- dc.DrawRectangle((float)(topLeftX - penWidth), (float)(topLeftY - penWidth),
- (float)(maxX + penWidth*2.0 + 4.0), (float)(maxY + penWidth*2.0 + 4.0));
+ dc.SetPen(g_oglWhiteBackgroundPen);
+ dc.SetBrush(g_oglWhiteBackgroundBrush);
+ dc.DrawRectangle(WXROUND(topLeftX - penWidth), WXROUND(topLeftY - penWidth),
+ WXROUND(maxX + penWidth*2.0 + 4.0), WXROUND(maxY + penWidth*2.0 + 4.0));
}
void wxShape::EraseLinks(wxDC& dc, int attachment, bool recurse)
}
}
-void wxShape::MoveLineToNewAttachment(wxDC& dc, wxLineShape *to_move,
- float x, float y)
+// Returns TRUE if pt1 <= pt2 in the sense that one point comes before another on an
+// edge of the shape.
+// attachmentPoint is the attachment point (= side) in question.
+
+// This is the default, rectangular implementation.
+bool wxShape::AttachmentSortTest(int attachmentPoint, const wxRealPoint& pt1, const wxRealPoint& pt2)
+{
+ int physicalAttachment = LogicalToPhysicalAttachment(attachmentPoint);
+ switch (physicalAttachment)
+ {
+ case 0:
+ case 2:
+ {
+ return (pt1.x <= pt2.x) ;
+ break;
+ }
+ case 1:
+ case 3:
+ {
+ return (pt1.y <= pt2.y) ;
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+bool wxShape::MoveLineToNewAttachment(wxDC& dc, wxLineShape *to_move,
+ double x, double y)
{
- int new_point;
- float distance;
+ if (GetAttachmentMode() == ATTACHMENT_MODE_NONE)
+ return FALSE;
+
+ int newAttachment, oldAttachment;
+ double distance;
// Is (x, y) on this object? If so, find the new attachment point
// the user has moved the point to
- bool hit = HitTest(x, y, &new_point, &distance);
+ bool hit = HitTest(x, y, &newAttachment, &distance);
if (!hit)
- return;
+ return FALSE;
EraseLinks(dc);
- int old_attachment;
if (to_move->GetTo() == this)
- old_attachment = to_move->GetAttachmentTo();
+ oldAttachment = to_move->GetAttachmentTo();
else
- old_attachment = to_move->GetAttachmentFrom();
+ oldAttachment = to_move->GetAttachmentFrom();
+
+ // The links in a new ordering.
+ wxList newOrdering;
+
+ // First, add all links to the new list.
+ wxNode *node = m_lines.First();
+ while (node)
+ {
+ newOrdering.Append(node->Data());
+ node = node->Next();
+ }
// Delete the line object from the list of links; we're going to move
// it to another position in the list
- m_lines.DeleteObject(to_move);
+ newOrdering.DeleteObject(to_move);
- float old_x = (float) -9999.9;
- float old_y = (float) -9999.9;
+ double old_x = (double) -99999.9;
+ double old_y = (double) -99999.9;
- wxNode *node = m_lines.First();
+ node = newOrdering.First();
bool found = FALSE;
- while (node && !found)
+ while (!found && node)
{
wxLineShape *line = (wxLineShape *)node->Data();
- if ((line->GetTo() == this && old_attachment == line->GetAttachmentTo()) ||
- (line->GetFrom() == this && old_attachment == line->GetAttachmentFrom()))
+ if ((line->GetTo() == this && oldAttachment == line->GetAttachmentTo()) ||
+ (line->GetFrom() == this && oldAttachment == line->GetAttachmentFrom()))
{
- float startX, startY, endX, endY;
- float xp, yp;
+ double startX, startY, endX, endY;
+ double xp, yp;
line->GetEnds(&startX, &startY, &endX, &endY);
if (line->GetTo() == this)
{
-// xp = line->m_xpos2 + line->m_xpos;
-// yp = line->m_ypos2 + line->m_ypos;
- xp = startX;
- yp = startY;
- } else
- {
-// xp = line->m_xpos1 + line->m_xpos;
-// yp = line->m_ypos1 + line->m_ypos;
xp = endX;
yp = endY;
+ } else
+ {
+ xp = startX;
+ yp = startY;
}
- switch (old_attachment)
+ wxRealPoint thisPoint(xp, yp);
+ wxRealPoint lastPoint(old_x, old_y);
+ wxRealPoint newPoint(x, y);
+
+ if (AttachmentSortTest(newAttachment, newPoint, thisPoint) && AttachmentSortTest(newAttachment, lastPoint, newPoint))
{
- case 0:
- case 2:
- {
- if (x > old_x && x <= xp)
- {
- found = TRUE;
- m_lines.Insert(node, to_move);
- }
- break;
- }
- case 1:
- case 3:
- {
- if (y > old_y && y <= yp)
- {
- found = TRUE;
- m_lines.Insert(node, to_move);
- }
- break;
- }
+ found = TRUE;
+ newOrdering.Insert(node, to_move);
}
+
old_x = xp;
old_y = yp;
}
node = node->Next();
}
+
if (!found)
- m_lines.Append(to_move);
+ newOrdering.Append(to_move);
+
+ GetEventHandler()->OnChangeAttachment(newAttachment, to_move, newOrdering);
+
+ return TRUE;
+}
+
+void wxShape::OnChangeAttachment(int attachment, wxLineShape* line, wxList& ordering)
+{
+ if (line->GetTo() == this)
+ line->SetAttachmentTo(attachment);
+ else
+ line->SetAttachmentFrom(attachment);
+
+ ApplyAttachmentOrdering(ordering);
+
+ wxClientDC dc(GetCanvas());
+ GetCanvas()->PrepareDC(dc);
+
+ MoveLinks(dc);
+
+ if (!GetCanvas()->GetQuickEditMode()) GetCanvas()->Redraw(dc);
+}
+
+// Reorders the lines according to the given list.
+void wxShape::ApplyAttachmentOrdering(wxList& linesToSort)
+{
+ // This is a temporary store of all the lines.
+ wxList linesStore;
+
+ wxNode *node = m_lines.First();
+ while (node)
+ {
+ wxLineShape *line = (wxLineShape *)node->Data();
+ linesStore.Append(line);
+ node = node->Next();;
+ }
+
+ m_lines.Clear();
+
+ node = linesToSort.First();
+ while (node)
+ {
+ wxLineShape *line = (wxLineShape *)node->Data();
+ if (linesStore.Member(line))
+ {
+ // Done this one
+ linesStore.DeleteObject(line);
+ m_lines.Append(line);
+ }
+ node = node->Next();
+ }
+
+ // Now add any lines that haven't been listed in linesToSort.
+ node = linesStore.First();
+ while (node)
+ {
+ wxLineShape *line = (wxLineShape *)node->Data();
+ m_lines.Append(line);
+ node = node->Next();
+ }
}
// Reorders the lines coming into the node image at this attachment
{
}
-void wxShape::OnLeftClick(float x, float y, int keys, int attachment)
+void wxShape::OnLeftClick(double x, double y, int keys, int attachment)
{
if ((m_sensitivity & OP_CLICK_LEFT) != OP_CLICK_LEFT)
{
attachment = 0;
- float dist;
+ double dist;
if (m_parent)
{
m_parent->HitTest(x, y, &attachment, &dist);
}
}
-void wxShape::OnRightClick(float x, float y, int keys, int attachment)
+void wxShape::OnRightClick(double x, double y, int keys, int attachment)
{
if ((m_sensitivity & OP_CLICK_RIGHT) != OP_CLICK_RIGHT)
{
attachment = 0;
- float dist;
+ double dist;
if (m_parent)
{
m_parent->HitTest(x, y, &attachment, &dist);
}
}
-float DragOffsetX = 0.0;
-float DragOffsetY = 0.0;
+double DragOffsetX = 0.0;
+double DragOffsetY = 0.0;
-void wxShape::OnDragLeft(bool draw, float x, float y, int keys, int attachment)
+void wxShape::OnDragLeft(bool draw, double x, double y, int keys, int attachment)
{
if ((m_sensitivity & OP_DRAG_LEFT) != OP_DRAG_LEFT)
{
attachment = 0;
- float dist;
+ double dist;
if (m_parent)
{
m_parent->HitTest(x, y, &attachment, &dist);
dc.SetPen(dottedPen);
dc.SetBrush(* wxTRANSPARENT_BRUSH);
- float xx, yy;
+ double xx, yy;
xx = x + DragOffsetX;
yy = y + DragOffsetY;
m_canvas->Snap(&xx, &yy);
// m_xpos = xx; m_ypos = yy;
- float w, h;
+ double w, h;
GetBoundingBoxMax(&w, &h);
GetEventHandler()->OnDrawOutline(dc, xx, yy, w, h);
}
-void wxShape::OnBeginDragLeft(float x, float y, int keys, int attachment)
+void wxShape::OnBeginDragLeft(double x, double y, int keys, int attachment)
{
if ((m_sensitivity & OP_DRAG_LEFT) != OP_DRAG_LEFT)
{
attachment = 0;
- float dist;
+ double dist;
if (m_parent)
{
m_parent->HitTest(x, y, &attachment, &dist);
wxClientDC dc(GetCanvas());
GetCanvas()->PrepareDC(dc);
- Erase(dc);
- float xx, yy;
+ // New policy: don't erase shape until end of drag.
+// Erase(dc);
+
+ double xx, yy;
xx = x + DragOffsetX;
yy = y + DragOffsetY;
m_canvas->Snap(&xx, &yy);
dc.SetPen(dottedPen);
dc.SetBrush((* wxTRANSPARENT_BRUSH));
- float w, h;
+ double w, h;
GetBoundingBoxMax(&w, &h);
GetEventHandler()->OnDrawOutline(dc, xx, yy, w, h);
m_canvas->CaptureMouse();
}
-void wxShape::OnEndDragLeft(float x, float y, int keys, int attachment)
+void wxShape::OnEndDragLeft(double x, double y, int keys, int attachment)
{
m_canvas->ReleaseMouse();
if ((m_sensitivity & OP_DRAG_LEFT) != OP_DRAG_LEFT)
{
attachment = 0;
- float dist;
+ double dist;
if (m_parent)
{
m_parent->HitTest(x, y, &attachment, &dist);
dc.SetLogicalFunction(wxCOPY);
- float xx = x + DragOffsetX;
- float yy = y + DragOffsetY;
+ double xx = x + DragOffsetX;
+ double yy = y + DragOffsetY;
m_canvas->Snap(&xx, &yy);
// canvas->Snap(&m_xpos, &m_ypos);
+
+ // New policy: erase shape at end of drag.
+ Erase(dc);
+
Move(dc, xx, yy);
if (m_canvas && !m_canvas->GetQuickEditMode()) m_canvas->Redraw(dc);
}
-void wxShape::OnDragRight(bool draw, float x, float y, int keys, int attachment)
+void wxShape::OnDragRight(bool draw, double x, double y, int keys, int attachment)
{
if ((m_sensitivity & OP_DRAG_RIGHT) != OP_DRAG_RIGHT)
{
attachment = 0;
- float dist;
+ double dist;
if (m_parent)
{
m_parent->HitTest(x, y, &attachment, &dist);
}
}
-void wxShape::OnBeginDragRight(float x, float y, int keys, int attachment)
+void wxShape::OnBeginDragRight(double x, double y, int keys, int attachment)
{
if ((m_sensitivity & OP_DRAG_RIGHT) != OP_DRAG_RIGHT)
{
attachment = 0;
- float dist;
+ double dist;
if (m_parent)
{
m_parent->HitTest(x, y, &attachment, &dist);
}
}
-void wxShape::OnEndDragRight(float x, float y, int keys, int attachment)
+void wxShape::OnEndDragRight(double x, double y, int keys, int attachment)
{
if ((m_sensitivity & OP_DRAG_RIGHT) != OP_DRAG_RIGHT)
{
attachment = 0;
- float dist;
+ double dist;
if (m_parent)
{
m_parent->HitTest(x, y, &attachment, &dist);
}
}
-void wxShape::OnDrawOutline(wxDC& dc, float x, float y, float w, float h)
+void wxShape::OnDrawOutline(wxDC& dc, double x, double y, double w, double h)
{
- float top_left_x = (float)(x - w/2.0);
- float top_left_y = (float)(y - h/2.0);
- float top_right_x = (float)(top_left_x + w);
- float top_right_y = (float)top_left_y;
- float bottom_left_x = (float)top_left_x;
- float bottom_left_y = (float)(top_left_y + h);
- float bottom_right_x = (float)top_right_x;
- float bottom_right_y = (float)bottom_left_y;
+ double top_left_x = (double)(x - w/2.0);
+ double top_left_y = (double)(y - h/2.0);
+ double top_right_x = (double)(top_left_x + w);
+ double top_right_y = (double)top_left_y;
+ double bottom_left_x = (double)top_left_x;
+ double bottom_left_y = (double)(top_left_y + h);
+ double bottom_right_x = (double)top_right_x;
+ double bottom_right_y = (double)bottom_left_y;
wxPoint points[5];
- points[0].x = top_left_x; points[0].y = top_left_y;
- points[1].x = top_right_x; points[1].y = top_right_y;
- points[2].x = bottom_right_x; points[2].y = bottom_right_y;
- points[3].x = bottom_left_x; points[3].y = bottom_left_y;
- points[4].x = top_left_x; points[4].y = top_left_y;
+ points[0].x = WXROUND(top_left_x); points[0].y = WXROUND(top_left_y);
+ points[1].x = WXROUND(top_right_x); points[1].y = WXROUND(top_right_y);
+ points[2].x = WXROUND(bottom_right_x); points[2].y = WXROUND(bottom_right_y);
+ points[3].x = WXROUND(bottom_left_x); points[3].y = WXROUND(bottom_left_y);
+ points[4].x = WXROUND(top_left_x); points[4].y = WXROUND(top_left_y);
dc.DrawLines(5, points);
}
m_canvas = NULL;
}
-void wxShape::Move(wxDC& dc, float x, float y, bool display)
+void wxShape::Move(wxDC& dc, double x, double y, bool display)
{
- float old_x = m_xpos;
- float old_y = m_ypos;
-
- m_xpos = x; m_ypos = y;
+ double old_x = m_xpos;
+ double old_y = m_ypos;
if (!GetEventHandler()->OnMovePre(dc, x, y, old_x, old_y, display))
{
- m_xpos = old_x;
- m_ypos = old_y;
+// m_xpos = old_x;
+// m_ypos = old_y;
return;
}
+ m_xpos = x; m_ypos = y;
+
ResetControlPoints();
if (display)
GetEventHandler()->OnDraw(dc);
GetEventHandler()->OnDrawContents(dc);
GetEventHandler()->OnDrawControlPoints(dc);
+ GetEventHandler()->OnDrawBranches(dc);
}
}
{
GetEventHandler()->OnErase(dc);
GetEventHandler()->OnEraseControlPoints(dc);
+ GetEventHandler()->OnDrawBranches(dc, TRUE);
}
void wxShape::EraseContents(wxDC& dc)
m_formatted = FALSE;
}
-void wxShape::SetSize(float x, float y, bool recursive)
+void wxShape::SetSize(double x, double y, bool recursive)
{
SetAttachmentSize(x, y);
SetDefaultRegionSize();
}
-void wxShape::SetAttachmentSize(float w, float h)
+void wxShape::SetAttachmentSize(double w, double h)
{
- float scaleX;
- float scaleY;
- float width, height;
+ double scaleX;
+ double scaleY;
+ double width, height;
GetBoundingBoxMin(&width, &height);
if (width == 0.0)
scaleX = 1.0;
while (node)
{
wxAttachmentPoint *point = (wxAttachmentPoint *)node->Data();
- point->m_x = (float)(point->m_x * scaleX);
- point->m_y = (float)(point->m_y * scaleY);
+ point->m_x = (double)(point->m_x * scaleX);
+ point->m_y = (double)(point->m_y * scaleY);
node = node->Next();
}
}
// Add line FROM this object
void wxShape::AddLine(wxLineShape *line, wxShape *other,
- int attachFrom, int attachTo)
+ int attachFrom, int attachTo,
+ // The line ordering
+ int positionFrom, int positionTo)
{
- if (!m_lines.Member(line))
- m_lines.Append(line);
+ 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);
+
+ if (positionFrom == -1)
+ m_lines.Append(line);
+ else
+ {
+ if (positionFrom < m_lines.Number())
+ {
+ wxNode* node = m_lines.Nth(positionFrom);
+ m_lines.Insert(node, line);
+ }
+ else
+ m_lines.Append(line);
+ }
- if (!other->m_lines.Member(line))
- other->m_lines.Append(line);
+ if (positionTo == -1)
+ other->m_lines.Append(line);
+ else
+ {
+ 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);
+ }
+#endif
- line->SetFrom(this);
- line->SetTo(other);
- line->SetAttachments(attachFrom, attachTo);
+ line->SetFrom(this);
+ line->SetTo(other);
+ line->SetAttachments(attachFrom, attachTo);
}
void wxShape::RemoveLine(wxLineShape *line)
}
#ifdef PROLOGIO
-char *wxShape::GetFunctor()
-{
- return "node_image";
-}
-
-void wxShape::WritePrologAttributes(wxExpr *clause)
+void wxShape::WriteAttributes(wxExpr *clause)
{
clause->AddAttributeValueString("type", GetClassInfo()->GetClassName());
clause->AddAttributeValue("id", m_id);
clause->AddAttributeValue("pen_style", (long)penStyle);
wxString penColour = wxTheColourDatabase->FindName(m_pen->GetColour());
- if ((penColour != "") && (penColour != "BLACK"))
+ if (penColour == "")
+ {
+ wxString hex(oglColourToHex(m_pen->GetColour()));
+ hex = wxString("#") + hex;
+ clause->AddAttributeValueString("pen_colour", hex);
+ }
+ else if (penColour != "BLACK")
clause->AddAttributeValueString("pen_colour", penColour);
}
{
wxString brushColour = wxTheColourDatabase->FindName(m_brush->GetColour());
- if ((brushColour != "") && (brushColour != "WHITE"))
+ if (brushColour == "")
+ {
+ wxString hex(oglColourToHex(m_brush->GetColour()));
+ hex = wxString("#") + hex;
+ clause->AddAttributeValueString("brush_colour", hex);
+ }
+ else if (brushColour != "WHITE")
clause->AddAttributeValueString("brush_colour", brushColour);
if (m_brush->GetStyle() != wxSOLID)
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)
{
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);
if (m_rotation != 0.0)
clause->AddAttributeValue("rotation", m_rotation);
+ if (!this->IsKindOf(CLASSINFO(wxLineShape)))
+ {
+ clause->AddAttributeValue("neck_length", (long) m_branchNeckLength);
+ clause->AddAttributeValue("stem_length", (long) m_branchStemLength);
+ clause->AddAttributeValue("branch_spacing", (long) m_branchSpacing);
+ clause->AddAttributeValue("branch_style", (long) m_branchStyle);
+ }
+
// 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));
// 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));
+ regionExpr->Append(new wxExpr(wxExprString, region->m_regionText));
regionExpr->Append(new wxExpr(region->m_x));
regionExpr->Append(new wxExpr(region->m_y));
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));
// 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));
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();
}
}
}
-void wxShape::ReadPrologAttributes(wxExpr *clause)
+void wxShape::ReadAttributes(wxExpr *clause)
{
clause->GetAttributeValue("id", m_id);
RegisterId(m_id);
// 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;
while (node)
{
wxExpr *string_expr = node;
- float the_x = 0.0;
- float the_y = 0.0;
+ double the_x = 0.0;
+ double the_y = 0.0;
wxString the_string("");
// 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 = (float)first->IntegerValue();
+ else the_x = (double)first->IntegerValue();
- if (second->Type() == PrologReal)
+ if (second->Type() == wxExprReal)
the_y = second->RealValue();
- else the_y = (float)second->IntegerValue();
+ else the_y = (double)second->IntegerValue();
the_string = third->StringValue();
}
int pen_width = 1;
int pen_style = wxSOLID;
int brush_style = wxSOLID;
- m_attachmentMode = FALSE;
+ m_attachmentMode = ATTACHMENT_MODE_NONE;
clause->GetAttributeValue("pen_colour", pen_string);
clause->GetAttributeValue("text_colour", m_textColourName);
int iVal = (int) m_attachmentMode;
clause->GetAttributeValue("use_attachments", iVal);
- m_attachmentMode = (iVal != 0);
+ m_attachmentMode = iVal;
clause->GetAttributeValue("sensitivity", m_sensitivity);
clause->GetAttributeValue("format_mode", m_formatMode);
clause->GetAttributeValue("shadow_mode", m_shadowMode);
+ iVal = m_branchNeckLength;
+ clause->GetAttributeValue("neck_length", iVal);
+ m_branchNeckLength = iVal;
+
+ iVal = m_branchStemLength;
+ clause->GetAttributeValue("stem_length", iVal);
+ m_branchStemLength = iVal;
+
+ iVal = m_branchSpacing;
+ clause->GetAttributeValue("branch_spacing", iVal);
+ m_branchSpacing = iVal;
+
+ clause->GetAttributeValue("branch_style", m_branchStyle);
+
iVal = (int) m_centreResize;
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);
if (brush_string == "")
brush_string = "WHITE";
- m_pen = wxThePenList->FindOrCreatePen(pen_string, pen_width, pen_style);
+ if (pen_string[0] == '#')
+ {
+ wxColour col(oglHexToColour(pen_string.After('#')));
+ m_pen = wxThePenList->FindOrCreatePen(col, pen_width, pen_style);
+ }
+ else
+ m_pen = wxThePenList->FindOrCreatePen(pen_string, pen_width, pen_style);
+
if (!m_pen)
m_pen = wxBLACK_PEN;
- m_brush = wxTheBrushList->FindOrCreateBrush(brush_string, brush_style);
+ if (brush_string[0] == '#')
+ {
+ wxColour col(oglHexToColour(brush_string.After('#')));
+ m_brush = wxTheBrushList->FindOrCreateBrush(col, brush_style);
+ }
+ else
+ m_brush = wxTheBrushList->FindOrCreateBrush(brush_string, brush_style);
+
if (!m_brush)
m_brush = wxWHITE_BRUSH;
int point_size = 10;
clause->GetAttributeValue("point_size", point_size);
- SetFont(MatchFont(point_size));
+ SetFont(oglMatchFont(point_size));
// Read user-defined attachment points, if any
wxExpr *attachmentList = clause->AttributeValue("user_attachments");
wxString regionName("");
wxString regionText("");
- float x = 0.0;
- float y = 0.0;
- float width = 0.0;
- float height = 0.0;
- float minWidth = 5.0;
- float minHeight = 5.0;
- float m_regionProportionX = -1.0;
- float m_regionProportionY = -1.0;
+ double x = 0.0;
+ double y = 0.0;
+ double width = 0.0;
+ double height = 0.0;
+ double minWidth = 5.0;
+ double minHeight = 5.0;
+ double m_regionProportionX = -1.0;
+ double m_regionProportionY = -1.0;
int formatMode = FORMAT_NONE;
int fontSize = 10;
int fontFamily = wxSWISS;
wxString penColour("");
int penStyle = wxSOLID;
- if (regionExpr->Type() == PrologList)
+ if (regionExpr->Type() == wxExprList)
{
wxExpr *nameExpr = regionExpr->Nth(0);
wxExpr *textExpr = regionExpr->Nth(1);
m_regionProportionX = propXExpr->RealValue();
m_regionProportionY = propYExpr->RealValue();
- formatMode = (formatExpr->IntegerValue() != 0);
+ formatMode = (int) formatExpr->IntegerValue();
fontSize = (int)sizeExpr->IntegerValue();
fontFamily = (int)familyExpr->IntegerValue();
fontStyle = (int)styleExpr->IntegerValue();
*
*/
textExpr = clause->AttributeValue(textNameBuf);
- if (textExpr && (textExpr->Type() == PrologList))
+ if (textExpr && (textExpr->Type() == wxExprList))
{
wxExpr *node = textExpr->value.first;
while (node)
{
wxExpr *string_expr = node;
- float the_x = 0.0;
- float the_y = 0.0;
+ double the_x = 0.0;
+ double the_y = 0.0;
wxString the_string("");
// 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 = (float)first->IntegerValue();
+ else the_x = (double)first->IntegerValue();
- if (second->Type() == PrologReal)
+ if (second->Type() == wxExprReal)
the_y = second->RealValue();
- else the_y = (float)second->IntegerValue();
+ else the_y = (double)second->IntegerValue();
the_string = third->StringValue();
}
void wxShape::Copy(wxShape& copy)
{
+ copy.m_id = m_id;
copy.m_xpos = m_xpos;
copy.m_ypos = m_ypos;
copy.m_pen = m_pen;
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;
copy.m_shadowOffsetY = m_shadowOffsetY;
copy.m_shadowBrush = m_shadowBrush;
+ copy.m_branchNeckLength = m_branchNeckLength;
+ copy.m_branchStemLength = m_branchStemLength;
+ copy.m_branchSpacing = m_branchSpacing;
+
// Copy text regions
copy.ClearRegions();
wxNode *node = m_regions.First();
copy.m_attachmentPoints.Append((wxObject *)newPoint);
node = node->Next();
}
+
+ // Copy lines
+ copy.m_lines.Clear();
+ node = m_lines.First();
+ while (node)
+ {
+ wxLineShape* line = (wxLineShape*) node->Data();
+ copy.m_lines.Append(line);
+ node = node->Next();
+ }
}
// Create and return a new, fully copied object.
-wxShape *wxShape::CreateNewCopy(wxShapeCanvas *theCanvas)
+wxShape *wxShape::CreateNewCopy(bool resetMapping, bool recompute)
{
- wxObjectCopyMapping.Clear();
- wxShape *newObject = PrivateCopy();
- if (theCanvas)
- newObject->AddToCanvas(theCanvas);
- newObject->Recompute();
+ if (resetMapping)
+ oglObjectCopyMapping.Clear();
+
+ wxShape* newObject = (wxShape*) GetClassInfo()->CreateObject();
+
+ wxASSERT( (newObject != NULL) );
+ wxASSERT( (newObject->IsKindOf(CLASSINFO(wxShape))) );
+
+ Copy(*newObject);
+
+ if (GetEventHandler() != this)
+ {
+ wxShapeEvtHandler* newHandler = GetEventHandler()->CreateNewCopy();
+ newObject->SetEventHandler(newHandler);
+ newObject->SetPreviousHandler(NULL);
+ newHandler->SetPreviousHandler(newObject);
+ newHandler->SetShape(newObject);
+ }
+
+ if (recompute)
+ newObject->Recompute();
return newObject;
}
+// Does the copying for this object, including copying event
+// handler data if any. Calls the virtual Copy function.
+void wxShape::CopyWithHandler(wxShape& copy)
+{
+ Copy(copy);
+
+ if (GetEventHandler() != this)
+ {
+ wxASSERT( copy.GetEventHandler() != NULL );
+ wxASSERT( copy.GetEventHandler() != (©) );
+ wxASSERT( GetEventHandler()->GetClassInfo() == copy.GetEventHandler()->GetClassInfo() );
+ GetEventHandler()->CopyData(* (copy.GetEventHandler()));
+ }
+}
+
+
// Default - make 6 control points
void wxShape::MakeControlPoints()
{
- float maxX, maxY, minX, minY;
+ double maxX, maxY, minX, minY;
GetBoundingBoxMax(&maxX, &maxY);
GetBoundingBoxMin(&minX, &minY);
- float widthMin = (float)(minX + CONTROL_POINT_SIZE + 2);
- float heightMin = (float)(minY + CONTROL_POINT_SIZE + 2);
+ double widthMin = (double)(minX + CONTROL_POINT_SIZE + 2);
+ double heightMin = (double)(minY + CONTROL_POINT_SIZE + 2);
// Offsets from main object
- float top = (float)(- (heightMin / 2.0));
- float bottom = (float)(heightMin / 2.0 + (maxY - minY));
- float left = (float)(- (widthMin / 2.0));
- float right = (float)(widthMin / 2.0 + (maxX - minX));
+ 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);
if (m_controlPoints.Number() < 1)
return;
- float maxX, maxY, minX, minY;
+ double maxX, maxY, minX, minY;
GetBoundingBoxMax(&maxX, &maxY);
GetBoundingBoxMin(&minX, &minY);
- float widthMin = (float)(minX + CONTROL_POINT_SIZE + 2);
- float heightMin = (float)(minY + CONTROL_POINT_SIZE + 2);
+ double widthMin = (double)(minX + CONTROL_POINT_SIZE + 2);
+ double heightMin = (double)(minY + CONTROL_POINT_SIZE + 2);
// Offsets from main object
- float top = (float)(- (heightMin / 2.0));
- float bottom = (float)(heightMin / 2.0 + (maxY - minY));
- float left = (float)(- (widthMin / 2.0));
- float right = (float)(widthMin / 2.0 + (maxX - minX));
+ 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();
return GetParent()->AncestorSelected();
}
-int wxShape::GetNumberOfAttachments()
+int wxShape::GetNumberOfAttachments() const
{
// Should return the MAXIMUM attachment point id here,
// so higher-level functions can iterate through all attachments,
}
}
-bool wxShape::AttachmentIsValid(int attachment)
+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)
return FALSE;
}
-bool wxShape::GetAttachmentPosition(int attachment, float *x, float *y,
+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 == ATTACHMENT_MODE_NONE)
{
- wxAttachmentPoint *point = (wxAttachmentPoint *)node->Data();
- if (point->m_id == attachment)
- {
- *x = (float)(m_xpos + point->m_x);
- *y = (float)(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_attachmentMode == ATTACHMENT_MODE_BRANCHING)
+ {
+ wxRealPoint pt, stemPt;
+ GetBranchingAttachmentPoint(attachment, nth, pt, stemPt);
+ *x = pt.x;
+ *y = pt.y;
+ return TRUE;
+ }
+ else if (m_attachmentMode == ATTACHMENT_MODE_EDGE)
+ {
+ 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));
+
+ int physicalAttachment = LogicalToPhysicalAttachment(attachment);
+
+ // Simplified code
+ switch (physicalAttachment)
+ {
+ 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 FALSE;
+ break;
+ }
+ }
+ return TRUE;
+ }
+ }
return FALSE;
- }
}
-void wxShape::GetBoundingBoxMax(float *w, float *h)
+void wxShape::GetBoundingBoxMax(double *w, double *h)
{
- float ww, hh;
+ double ww, hh;
GetBoundingBoxMin(&ww, &hh);
if (m_shadowMode != SHADOW_NONE)
{
list.Clear();
}
+// Assuming the attachment lies along a vertical or horizontal line,
+// calculate the position on that point.
+wxRealPoint wxShape::CalcSimpleAttachment(const wxRealPoint& pt1, const wxRealPoint& pt2,
+ int nth, int noArcs, wxLineShape* line)
+{
+ bool isEnd = (line && line->IsEnd(this));
+
+ // Are we horizontal or vertical?
+ bool isHorizontal = (oglRoughlyEqual(pt1.y, pt2.y) == TRUE);
+
+ double x, y;
+
+ if (isHorizontal)
+ {
+ wxRealPoint firstPoint, secondPoint;
+ if (pt1.x > pt2.x)
+ {
+ firstPoint = pt2;
+ secondPoint = pt1;
+ }
+ else
+ {
+ firstPoint = pt1;
+ secondPoint = pt2;
+ }
+
+ 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 < firstPoint.x)
+ x = firstPoint.x;
+ else if (point->x > secondPoint.x)
+ x = secondPoint.x;
+ else
+ x = point->x;
+ }
+ else
+ x = firstPoint.x + (nth + 1)*(secondPoint.x - firstPoint.x)/(noArcs + 1);
+ }
+ else x = (secondPoint.x - firstPoint.x)/2.0; // Midpoint
+
+ y = pt1.y;
+ }
+ else
+ {
+ wxASSERT( oglRoughlyEqual(pt1.x, pt2.x) == TRUE );
+
+ wxRealPoint firstPoint, secondPoint;
+ if (pt1.y > pt2.y)
+ {
+ firstPoint = pt2;
+ secondPoint = pt1;
+ }
+ else
+ {
+ firstPoint = pt1;
+ secondPoint = pt2;
+ }
+
+ 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 < firstPoint.y)
+ y = firstPoint.y;
+ else if (point->y > secondPoint.y)
+ y = secondPoint.y;
+ else
+ y = point->y;
+ }
+ else
+ y = firstPoint.y + (nth + 1)*(secondPoint.y - firstPoint.y)/(noArcs + 1);
+ }
+ else y = (secondPoint.y - firstPoint.y)/2.0; // Midpoint
+
+ x = pt1.x;
+ }
+
+ return wxRealPoint(x, y);
+}
+
+// Return the zero-based position in m_lines of line.
+int wxShape::GetLinePosition(wxLineShape* line)
+{
+ int i = 0;
+ for (i = 0; i < m_lines.Number(); i++)
+ if ((wxLineShape*) (m_lines.Nth(i)->Data()) == line)
+ return i;
+
+ return 0;
+}
+
+//
+// |________|
+// | <- root
+// | <- neck
+// shoulder1 ->---------<- shoulder2
+// | | | | |
+// <- branching attachment point N-1
+
+// This function gets information about where branching connections go.
+// Returns FALSE if there are no lines at this attachment.
+bool wxShape::GetBranchingAttachmentInfo(int attachment, wxRealPoint& root, wxRealPoint& neck,
+ wxRealPoint& shoulder1, wxRealPoint& shoulder2)
+{
+ int physicalAttachment = LogicalToPhysicalAttachment(attachment);
+
+ // Number of lines at this attachment.
+ int lineCount = GetAttachmentLineCount(attachment);
+
+ if (lineCount == 0)
+ return FALSE;
+
+ int totalBranchLength = m_branchSpacing * (lineCount - 1);
+
+ root = GetBranchingAttachmentRoot(attachment);
+
+ // Assume that we have attachment points 0 to 3: top, right, bottom, left.
+ switch (physicalAttachment)
+ {
+ case 0:
+ {
+ neck.x = GetX();
+ neck.y = root.y - m_branchNeckLength;
+
+ shoulder1.x = root.x - (totalBranchLength/2.0) ;
+ shoulder2.x = root.x + (totalBranchLength/2.0) ;
+
+ shoulder1.y = neck.y;
+ shoulder2.y = neck.y;
+ break;
+ }
+ case 1:
+ {
+ neck.x = root.x + m_branchNeckLength;
+ neck.y = root.y;
+
+ shoulder1.x = neck.x ;
+ shoulder2.x = neck.x ;
+
+ shoulder1.y = neck.y - (totalBranchLength/2.0) ;
+ shoulder2.y = neck.y + (totalBranchLength/2.0) ;
+ break;
+ }
+ case 2:
+ {
+ neck.x = GetX();
+ neck.y = root.y + m_branchNeckLength;
+
+ shoulder1.x = root.x - (totalBranchLength/2.0) ;
+ shoulder2.x = root.x + (totalBranchLength/2.0) ;
+
+ shoulder1.y = neck.y;
+ shoulder2.y = neck.y;
+ break;
+ }
+ case 3:
+ {
+ neck.x = root.x - m_branchNeckLength;
+ neck.y = root.y ;
+
+ shoulder1.x = neck.x ;
+ shoulder2.x = neck.x ;
+
+ shoulder1.y = neck.y - (totalBranchLength/2.0) ;
+ shoulder2.y = neck.y + (totalBranchLength/2.0) ;
+ break;
+ }
+ default:
+ {
+ wxFAIL_MSG( "Unrecognised attachment point in GetBranchingAttachmentInfo." );
+ break;
+ }
+ }
+ return TRUE;
+}
+
+// n is the number of the adjoining line, from 0 to N-1 where N is the number of lines
+// at this attachment point.
+// Get the attachment point where the arc joins the stem, and also the point where the
+// the stem meets the shoulder.
+bool wxShape::GetBranchingAttachmentPoint(int attachment, int n, wxRealPoint& pt, wxRealPoint& stemPt)
+{
+ int physicalAttachment = LogicalToPhysicalAttachment(attachment);
+
+ wxRealPoint root, neck, shoulder1, shoulder2;
+ GetBranchingAttachmentInfo(attachment, root, neck, shoulder1, shoulder2);
+
+ // Assume that we have attachment points 0 to 3: top, right, bottom, left.
+ switch (physicalAttachment)
+ {
+ case 0:
+ {
+ pt.y = neck.y - m_branchStemLength;
+ pt.x = shoulder1.x + n*m_branchSpacing;
+
+ stemPt.x = pt.x;
+ stemPt.y = neck.y;
+ break;
+ }
+ case 2:
+ {
+ pt.y = neck.y + m_branchStemLength;
+ pt.x = shoulder1.x + n*m_branchSpacing;
+
+ stemPt.x = pt.x;
+ stemPt.y = neck.y;
+ break;
+ }
+ case 1:
+ {
+ pt.x = neck.x + m_branchStemLength;
+ pt.y = shoulder1.y + n*m_branchSpacing;
+
+ stemPt.x = neck.x;
+ stemPt.y = pt.y;
+ break;
+ }
+ case 3:
+ {
+ pt.x = neck.x - m_branchStemLength;
+ pt.y = shoulder1.y + n*m_branchSpacing;
+
+ stemPt.x = neck.x;
+ stemPt.y = pt.y;
+ break;
+ }
+ default:
+ {
+ wxFAIL_MSG( "Unrecognised attachment point in GetBranchingAttachmentPoint." );
+ break;
+ }
+ }
+
+ return TRUE;
+}
+
+// Get the number of lines at this attachment position.
+int wxShape::GetAttachmentLineCount(int attachment) const
+{
+ int count = 0;
+ wxNode* node = m_lines.First();
+ while (node)
+ {
+ wxLineShape* lineShape = (wxLineShape*) node->Data();
+ if ((lineShape->GetFrom() == this) && (lineShape->GetAttachmentFrom() == attachment))
+ count ++;
+ else if ((lineShape->GetTo() == this) && (lineShape->GetAttachmentTo() == attachment))
+ count ++;
+
+ node = node->Next();
+ }
+ return count;
+}
+
+// This function gets the root point at the given attachment.
+wxRealPoint wxShape::GetBranchingAttachmentRoot(int attachment)
+{
+ int physicalAttachment = LogicalToPhysicalAttachment(attachment);
+
+ wxRealPoint root;
+
+ double width, height;
+ GetBoundingBoxMax(& width, & height);
+
+ // Assume that we have attachment points 0 to 3: top, right, bottom, left.
+ switch (physicalAttachment)
+ {
+ case 0:
+ {
+ root.x = GetX() ;
+ root.y = GetY() - height/2.0;
+ break;
+ }
+ case 1:
+ {
+ root.x = GetX() + width/2.0;
+ root.y = GetY() ;
+ break;
+ }
+ case 2:
+ {
+ root.x = GetX() ;
+ root.y = GetY() + height/2.0;
+ break;
+ }
+ case 3:
+ {
+ root.x = GetX() - width/2.0;
+ root.y = GetY() ;
+ break;
+ }
+ default:
+ {
+ wxFAIL_MSG( "Unrecognised attachment point in GetBranchingAttachmentRoot." );
+ break;
+ }
+ }
+ return root;
+}
+
+// Draw or erase the branches (not the actual arcs though)
+void wxShape::OnDrawBranches(wxDC& dc, int attachment, bool erase)
+{
+ int count = GetAttachmentLineCount(attachment);
+ if (count == 0)
+ return;
+
+ wxRealPoint root, neck, shoulder1, shoulder2;
+ GetBranchingAttachmentInfo(attachment, root, neck, shoulder1, shoulder2);
+
+ if (erase)
+ {
+ dc.SetPen(*wxWHITE_PEN);
+ dc.SetBrush(*wxWHITE_BRUSH);
+ }
+ else
+ {
+ dc.SetPen(*wxBLACK_PEN);
+ dc.SetBrush(*wxBLACK_BRUSH);
+ }
+
+ // Draw neck
+ dc.DrawLine((long) root.x, (long) root.y, (long) neck.x, (long) neck.y);
+
+ if (count > 1)
+ {
+ // Draw shoulder-to-shoulder line
+ dc.DrawLine((long) shoulder1.x, (long) shoulder1.y, (long) shoulder2.x, (long) shoulder2.y);
+ }
+ // Draw all the little branches
+ int i;
+ for (i = 0; i < count; i++)
+ {
+ wxRealPoint pt, stemPt;
+ GetBranchingAttachmentPoint(attachment, i, pt, stemPt);
+ dc.DrawLine((long) stemPt.x, (long) stemPt.y, (long) pt.x, (long) pt.y);
+
+ if ((GetBranchStyle() & BRANCHING_ATTACHMENT_BLOB) && (count > 1))
+ {
+ long blobSize=6;
+// dc.DrawEllipse((long) (stemPt.x + 0.5 - (blobSize/2.0)), (long) (stemPt.y + 0.5 - (blobSize/2.0)), blobSize, blobSize);
+ dc.DrawEllipse((long) (stemPt.x - (blobSize/2.0)), (long) (stemPt.y - (blobSize/2.0)), blobSize, blobSize);
+ }
+ }
+}
+
+// Draw or erase the branches (not the actual arcs though)
+void wxShape::OnDrawBranches(wxDC& dc, bool erase)
+{
+ if (m_attachmentMode != ATTACHMENT_MODE_BRANCHING)
+ return;
+
+ int count = GetNumberOfAttachments();
+ int i;
+ for (i = 0; i < count; i++)
+ OnDrawBranches(dc, i, erase);
+}
+
+// Only get the attachment position at the _edge_ of the shape, ignoring
+// branching mode. This is used e.g. to indicate the edge of interest, not the point
+// on the attachment branch.
+bool wxShape::GetAttachmentPositionEdge(int attachment, double *x, double *y,
+ int nth, int no_arcs, wxLineShape *line)
+{
+ int oldMode = m_attachmentMode;
+
+ // Calculate as if to edge, not branch
+ if (m_attachmentMode == ATTACHMENT_MODE_BRANCHING)
+ m_attachmentMode = ATTACHMENT_MODE_EDGE;
+ bool success = GetAttachmentPosition(attachment, x, y, nth, no_arcs, line);
+ m_attachmentMode = oldMode;
+
+ return success;
+}
+
+// Rotate the standard attachment point from physical (0 is always North)
+// to logical (0 -> 1 if rotated by 90 degrees)
+int wxShape::PhysicalToLogicalAttachment(int physicalAttachment) const
+{
+ const double pi = 3.1415926535897932384626433832795 ;
+ int i;
+ if (oglRoughlyEqual(GetRotation(), 0.0))
+ {
+ i = physicalAttachment;
+ }
+ else if (oglRoughlyEqual(GetRotation(), (pi/2.0)))
+ {
+ i = physicalAttachment - 1;
+ }
+ else if (oglRoughlyEqual(GetRotation(), pi))
+ {
+ i = physicalAttachment - 2;
+ }
+ else if (oglRoughlyEqual(GetRotation(), (3.0*pi/2.0)))
+ {
+ i = physicalAttachment - 3;
+ }
+ else
+ // Can't handle -- assume the same.
+ return physicalAttachment;
+
+ if (i < 0)
+ i += 4;
+
+ return i;
+}
+
+// Rotate the standard attachment point from logical
+// to physical (0 is always North)
+int wxShape::LogicalToPhysicalAttachment(int logicalAttachment) const
+{
+ const double pi = 3.1415926535897932384626433832795 ;
+ int i;
+ if (oglRoughlyEqual(GetRotation(), 0.0))
+ {
+ i = logicalAttachment;
+ }
+ else if (oglRoughlyEqual(GetRotation(), (pi/2.0)))
+ {
+ i = logicalAttachment + 1;
+ }
+ else if (oglRoughlyEqual(GetRotation(), pi))
+ {
+ i = logicalAttachment + 2;
+ }
+ else if (oglRoughlyEqual(GetRotation(), (3.0*pi/2.0)))
+ {
+ i = logicalAttachment + 3;
+ }
+ else
+ // Can't handle -- assume the same.
+ return logicalAttachment;
+
+ if (i > 3)
+ i -= 4;
+
+ return i;
+}
+
+void wxShape::Rotate(double WXUNUSED(x), double WXUNUSED(y), double theta)
+{
+ const double pi = 3.1415926535897932384626433832795 ;
+ m_rotation = theta;
+ if (m_rotation < 0.0)
+ {
+ m_rotation += 2*pi;
+ }
+ else if (m_rotation > 2*pi)
+ {
+ m_rotation -= 2*pi;
+ }
+}
+