+++ /dev/null
-/////////////////////////////////////////////////////////////////////////////
-// Name: shapes.cpp
-// Purpose: Implements Studio shapes
-// Author: Julian Smart
-// Modified by:
-// Created: 12/07/98
-// RCS-ID: $Id$
-// Copyright: (c) Julian Smart
-// Licence: wxWindows licence
-/////////////////////////////////////////////////////////////////////////////
-
-#ifdef __GNUG__
-// #pragma implementation
-#endif
-
-// For compilers that support precompilation, includes "wx.h".
-#include <wx/wxprec.h>
-
-#ifdef __BORLANDC__
-#pragma hdrstop
-#endif
-
-#ifndef WX_PRECOMP
-#include <wx/wx.h>
-#endif
-
-#if !wxUSE_DOC_VIEW_ARCHITECTURE
-#error You must set wxUSE_DOC_VIEW_ARCHITECTURE to 1 in wx_setup.h!
-#endif
-
-#include <wx/wxexpr.h>
-
-#include "studio.h"
-#include "doc.h"
-#include "shapes.h"
-#include "view.h"
-#include "basicp.h"
-#include "linesp.h"
-#include "cspalette.h"
-#include "dialogs.h"
-
-#define csSTANDARD_SHAPE_WIDTH 100
-
-IMPLEMENT_CLASS(csDiagram, wxDiagram)
-
-csDiagram::~csDiagram()
-{
- DeleteAllShapes();
-}
-
-void csDiagram::Redraw(wxDC& dc)
-{
- wxDiagram::Redraw(dc);
-
- // Draw line crossings
- wxLineCrossings lineCrossings;
- lineCrossings.FindCrossings(*this);
- lineCrossings.DrawCrossings(*this, dc);
-}
-
-/*
- * csEvtHandler: an event handler class for all shapes
- */
-
-IMPLEMENT_DYNAMIC_CLASS(csEvtHandler, wxShapeEvtHandler)
-
-csEvtHandler::csEvtHandler(wxShapeEvtHandler *prev, wxShape *shape, const wxString& lab):
- wxShapeEvtHandler(prev, shape)
-{
- m_label = lab;
-}
-
-csEvtHandler::~csEvtHandler()
-{
-}
-
-// Copy any event handler data
-void csEvtHandler::CopyData(wxShapeEvtHandler& copy)
-{
- wxShapeEvtHandler::CopyData(copy);
-
- csEvtHandler& csCopy = (csEvtHandler&) copy;
- csCopy.m_label = m_label;
-}
-
-void csEvtHandler::OnLeftClick(double x, double y, int keys, int attachment)
-{
- wxClientDC dc(GetShape()->GetCanvas());
- GetShape()->GetCanvas()->PrepareDC(dc);
-
- csDiagramView* view = ((csCanvas*)GetShape()->GetCanvas())->GetView();
- view->ReflectPointSize(GetShape()->GetFont()->GetPointSize());
-
- if (GetShape()->IsKindOf(CLASSINFO(wxLineShape)))
- view->ReflectArrowState((wxLineShape*) GetShape());
-
- csEditorToolPalette *palette = wxGetApp().GetDiagramPalette();
- if (palette->GetSelection() == PALETTE_TEXT_TOOL)
- {
- view->ReflectPointSize(GetShape()->GetFont()->GetPointSize());
-
- EditProperties();
-#if 0
- csLabelEditingDialog* dialog = new csLabelEditingDialog(GetShape()->GetCanvas()->GetParent());
- dialog->SetShapeLabel(m_label);
- if (dialog->ShowModal() == wxID_CANCEL)
- {
- dialog->Destroy();
- return;
- }
-
- wxString newLabel = dialog->GetShapeLabel();
- dialog->Destroy();
-
- wxShape* newShape = GetShape()->CreateNewCopy();
-
- csEvtHandler* handler = (csEvtHandler *)newShape->GetEventHandler();
- handler->m_label = newLabel;
-
- view->GetDocument()->GetCommandProcessor()->Submit(new csDiagramCommand("Edit label", (csDiagramDocument*) view->GetDocument(),
- new csCommandState(ID_CS_EDIT_PROPERTIES, newShape, GetShape())));
-#endif
- return;
- }
-
- if (keys == 0)
- {
- // If no shift key, then everything is deselected.
- // If the shape was selected, deselect it and vice versa.
- bool selected = GetShape()->Selected();
-
- view->SelectAll(FALSE);
-
- selected = !selected;
-
- GetShape()->Select(selected, &dc);
- GetShape()->GetCanvas()->Redraw(dc); // Redraw because bits of objects will be missing
-
- view->SelectShape(GetShape(), selected);
- }
- else if (keys & KEY_SHIFT)
- {
- if (GetShape()->Selected())
- {
- GetShape()->Select(FALSE, &dc);
- view->SelectShape(GetShape(), FALSE);
- }
- else
- {
- GetShape()->Select(TRUE, &dc);
- view->SelectShape(GetShape(), TRUE);
- }
- GetShape()->GetCanvas()->Redraw(dc); // Redraw because bits of objects will be missing
- }
- else if (keys & KEY_CTRL)
- {
- // Do something for CONTROL
- }
- else
- {
- ((wxFrame*)wxGetApp().GetTopWindow())->SetStatusText(m_label);
- }
-}
-
-void csEvtHandler::OnRightClick(double x, double y, int keys, int attachment)
-{
- // Have to convert back to physical coordinates from logical coordinates.
-
- int viewStartX, viewStartY;
- int unitX, unitY;
- GetShape()->GetCanvas()->ViewStart(& viewStartX, & viewStartY);
- GetShape()->GetCanvas()->GetScrollPixelsPerUnit(& unitX, & unitY);
-
- int x1 = (int)(x * GetShape()->GetCanvas()->GetScaleX());
- int y1 = (int)(y * GetShape()->GetCanvas()->GetScaleY());
-
- int menuX = (int) (x1 - (viewStartX * unitX)) ;
- int menuY = (int) (y1 - (viewStartY * unitY));
-
- wxGetApp().GetShapeEditMenu()->SetClientData((char*) GetShape());
- wxGetApp().GetShapeEditMenu()->Enable(ID_CS_ROTATE_CLOCKWISE, !GetShape()->IsKindOf(CLASSINFO(wxLineShape)));
- wxGetApp().GetShapeEditMenu()->Enable(ID_CS_ROTATE_ANTICLOCKWISE, !GetShape()->IsKindOf(CLASSINFO(wxLineShape)));
-
- GetShape()->GetCanvas()->PopupMenu(wxGetApp().GetShapeEditMenu(), menuX, menuY);
-}
-
-/*
- * Implement connection of two shapes by right-dragging between them.
- */
-
-void csEvtHandler::OnBeginDragRight(double x, double y, int keys, int attachment)
-{
- wxClientDC dc(GetShape()->GetCanvas());
- GetShape()->GetCanvas()->PrepareDC(dc);
-
- wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
- dc.SetLogicalFunction(OGLRBLF);
- dc.SetPen(dottedPen);
- double xp, yp;
- GetShape()->GetAttachmentPositionEdge(attachment, &xp, &yp);
- dc.DrawLine(xp, yp, x, y);
- GetShape()->GetCanvas()->CaptureMouse();
-}
-
-void csEvtHandler::OnDragRight(bool draw, double x, double y, int keys, int attachment)
-{
- wxClientDC dc(GetShape()->GetCanvas());
- GetShape()->GetCanvas()->PrepareDC(dc);
-
- wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
- dc.SetLogicalFunction(OGLRBLF);
- dc.SetPen(dottedPen);
- double xp, yp;
- GetShape()->GetAttachmentPositionEdge(attachment, &xp, &yp);
- dc.DrawLine(xp, yp, x, y);
-}
-
-void csEvtHandler::OnEndDragRight(double x, double y, int keys, int attachment)
-{
- GetShape()->GetCanvas()->ReleaseMouse();
- csCanvas *canvas = (csCanvas *)GetShape()->GetCanvas();
-
- // Check if we're on an object
- int new_attachment;
- wxShape *otherShape = canvas->FindFirstSensitiveShape(x, y, &new_attachment, OP_DRAG_RIGHT);
-
- if (otherShape && !otherShape->IsKindOf(CLASSINFO(wxLineShape)))
- {
- wxLineShape* theShape = new csLineShape;
-
- theShape->AssignNewIds();
- theShape->SetEventHandler(new csEvtHandler(theShape, theShape, wxString("")));
- theShape->SetPen(wxBLACK_PEN);
- theShape->SetBrush(wxRED_BRUSH);
-
- wxToolBar* toolbar = wxGetApp().GetDiagramToolBar();
- bool haveArrow = toolbar->GetToolState(DIAGRAM_TOOLBAR_LINE_ARROW);
-
- wxLineShape *lineShape = (wxLineShape *)theShape;
-
- // Yes, you can have more than 2 control points, in which case
- // it becomes a multi-segment line.
- lineShape->MakeLineControlPoints(2);
-
- if (haveArrow)
- lineShape->AddArrow(ARROW_ARROW, ARROW_POSITION_MIDDLE, 10.0, 0.0, "Normal arrowhead");
-
- lineShape->SetFrom(GetShape());
- lineShape->SetTo(otherShape);
- lineShape->SetAttachments(attachment, new_attachment);
-
- canvas->GetView()->GetDocument()->GetCommandProcessor()->Submit(
- new csDiagramCommand("Line", (csDiagramDocument *)canvas->GetView()->GetDocument(),
- new csCommandState(ID_CS_ADD_LINE, lineShape, NULL)));
- }
-}
-
-static double g_DragOffsetX = 0.0;
-static double g_DragOffsetY = 0.0;
-static double g_DragStartX = 0.0;
-static double g_DragStartY = 0.0;
-
-void csEvtHandler::OnDragLeft(bool draw, double x, double y, int keys, int attachment)
-{
- if ((GetShape()->GetSensitivityFilter() & OP_DRAG_LEFT) != OP_DRAG_LEFT)
- {
- attachment = 0;
- double dist;
- if (GetShape()->GetParent())
- {
- GetShape()->GetParent()->HitTest(x, y, &attachment, &dist);
- GetShape()->GetParent()->GetEventHandler()->OnDragLeft(draw, x, y, keys, attachment);
- }
- return;
- }
-
- wxClientDC dc(GetShape()->GetCanvas());
- GetShape()->GetCanvas()->PrepareDC(dc);
-
- dc.SetLogicalFunction(OGLRBLF);
-
- wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
- dc.SetPen(dottedPen);
- dc.SetBrush(* wxTRANSPARENT_BRUSH);
-
- double xx, yy;
- xx = x + g_DragOffsetX;
- yy = y + g_DragOffsetY;
-
- GetShape()->GetCanvas()->Snap(&xx, &yy);
-
- double offsetX = xx - g_DragStartX;
- double offsetY = yy - g_DragStartY;
-
-// m_xpos = xx; m_ypos = yy;
- double w, h;
- GetShape()->GetBoundingBoxMax(&w, &h);
- GetShape()->GetEventHandler()->OnDrawOutline(dc, xx, yy, w, h);
-
- // Draw bounding box for other selected shapes
- wxNode* node = GetShape()->GetCanvas()->GetDiagram()->GetShapeList()->First();
- while (node)
- {
- wxShape* shape = (wxShape*) node->Data();
- if (shape->Selected() && !shape->IsKindOf(CLASSINFO(wxLineShape)) && (shape != GetShape()))
- {
- shape->GetBoundingBoxMax(&w, &h);
- shape->OnDrawOutline(dc, shape->GetX() + offsetX, shape->GetY() + offsetY, w, h);
- }
- node = node->Next();
- }
-}
-
-void csEvtHandler::OnBeginDragLeft(double x, double y, int keys, int attachment)
-{
- if ((GetShape()->GetSensitivityFilter() & OP_DRAG_LEFT) != OP_DRAG_LEFT)
- {
- attachment = 0;
- double dist;
- if (GetShape()->GetParent())
- {
- GetShape()->GetParent()->HitTest(x, y, &attachment, &dist);
- GetShape()->GetParent()->GetEventHandler()->OnBeginDragLeft(x, y, keys, attachment);
- }
- return;
- }
-
- wxClientDC dc(GetShape()->GetCanvas());
- GetShape()->GetCanvas()->PrepareDC(dc);
-
- // New policy: don't erase shape until end of drag.
-// Erase(dc);
-
- g_DragOffsetX = GetShape()->GetX() - x;
- g_DragOffsetY = GetShape()->GetY() - y;
-
- double xx, yy;
- xx = x + g_DragOffsetX;
- yy = y + g_DragOffsetY;
-
- GetShape()->GetCanvas()->Snap(&xx, &yy);
-
- g_DragStartX = GetShape()->GetX();
- g_DragStartY = GetShape()->GetY();
-
- double offsetX = xx - g_DragStartX;
- double offsetY = yy - g_DragStartY;
-
- dc.SetLogicalFunction(OGLRBLF);
-
- wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
- dc.SetPen(dottedPen);
- dc.SetBrush((* wxTRANSPARENT_BRUSH));
-
- double w, h;
- GetShape()->GetBoundingBoxMax(&w, &h);
- GetShape()->GetEventHandler()->OnDrawOutline(dc, xx, yy, w, h);
-
- // Draw bounding box for other selected shapes
- wxNode* node = GetShape()->GetCanvas()->GetDiagram()->GetShapeList()->First();
- while (node)
- {
- wxShape* shape = (wxShape*) node->Data();
- if (shape->Selected() && !shape->IsKindOf(CLASSINFO(wxLineShape)) && (shape != GetShape()))
- {
- shape->GetBoundingBoxMax(&w, &h);
- shape->OnDrawOutline(dc, shape->GetX() + offsetX, shape->GetY() + offsetY, w, h);
- }
- node = node->Next();
- }
-
- GetShape()->GetCanvas()->CaptureMouse();
-}
-
-
-void csEvtHandler::OnEndDragLeft(double x, double y, int keys, int attachment)
-{
- csCanvas *canvas = (csCanvas *)GetShape()->GetCanvas();
-
- canvas->ReleaseMouse();
- if ((GetShape()->GetSensitivityFilter() & OP_DRAG_LEFT) != OP_DRAG_LEFT)
- {
- attachment = 0;
- double dist;
- if (GetShape()->GetParent())
- {
- GetShape()->GetParent()->HitTest(x, y, &attachment, &dist);
- GetShape()->GetParent()->GetEventHandler()->OnEndDragLeft(x, y, keys, attachment);
- }
- return;
- }
-
- wxClientDC dc(canvas);
- canvas->PrepareDC(dc);
-
- dc.SetLogicalFunction(wxCOPY);
-
- double xx = x + g_DragOffsetX;
- double yy = y + g_DragOffsetY;
-
- canvas->Snap(&xx, &yy);
-
- double offsetX = xx - g_DragStartX;
- double offsetY = yy - g_DragStartY;
-
- wxShape* newShape = GetShape()->CreateNewCopy();
-
- newShape->SetX(xx);
- newShape->SetY(yy);
-
- csDiagramCommand* cmd = new csDiagramCommand("Move", (csDiagramDocument*)canvas->GetView()->GetDocument(),
- new csCommandState(ID_CS_MOVE, newShape, GetShape()));
-
- // Move line points
- wxNode* node = GetShape()->GetCanvas()->GetDiagram()->GetShapeList()->First();
- while (node)
- {
- wxShape* shape = (wxShape*) node->Data();
- // Only move the line point(s) if both ends move too
- if (shape->IsKindOf(CLASSINFO(wxLineShape)) &&
- ((wxLineShape*)shape)->GetTo()->Selected() && ((wxLineShape*)shape)->GetFrom()->Selected())
- {
- wxLineShape* lineShape = (wxLineShape*) shape;
-
- if (lineShape->GetLineControlPoints()->Number() > 2)
- {
- wxLineShape* newLineShape = (wxLineShape*) lineShape->CreateNewCopy();
-
- wxNode *node1 = newLineShape->GetLineControlPoints()->First();
- while (node1)
- {
- wxRealPoint *point = (wxRealPoint *)node1->Data();
- point->x += offsetX;
- point->y += offsetY;
- node1 = node1->Next();
- }
- cmd->AddState(new csCommandState(ID_CS_MOVE_LINE_POINT, newLineShape, lineShape));
- lineShape->Erase(dc);
- }
- }
- node = node->Next();
- }
-
- // Add other selected node shapes, if any
- node = GetShape()->GetCanvas()->GetDiagram()->GetShapeList()->First();
- while (node)
- {
- wxShape* shape = (wxShape*) node->Data();
- if (shape->Selected() && !shape->IsKindOf(CLASSINFO(wxLineShape)) && (shape != GetShape()))
- {
- wxShape* newShape2 = shape->CreateNewCopy();
- newShape2->SetX(shape->GetX() + offsetX);
- newShape2->SetY(shape->GetY() + offsetY);
- cmd->AddState(new csCommandState(ID_CS_MOVE, newShape2, shape));
- }
- node = node->Next();
- }
-
- canvas->GetView()->GetDocument()->GetCommandProcessor()->Submit(cmd);
-}
-
-void csEvtHandler::OnSizingEndDragLeft(wxControlPoint* pt, double x, double y, int keys, int attachment)
-{
- wxShape* shape = GetShape();
- csCanvas *canvas = (csCanvas *)GetShape()->GetCanvas();
-
- if (shape->IsKindOf(CLASSINFO(wxLineShape)))
- {
- // TODO: Do/Undo support for line operations
- ((wxLineShape*)shape)->wxLineShape::OnSizingEndDragLeft(pt, x, y, keys, attachment);
-#if 0
- wxLineShape* lineShape = (wxLineShape*) shape;
-
- wxLineControlPoint* lpt = (wxLineControlPoint*) pt;
-
- wxClientDC dc(canvas);
- canvas->PrepareDC(dc);
-
- shape->SetDisableLabel(FALSE);
-
- if (lpt->m_type == CONTROL_POINT_LINE)
- {
- canvas->Snap(&x, &y);
-
- dc.SetLogicalFunction(wxCOPY);
- lpt->SetX(x); lpt->SetY(y);
- lpt->m_point->x = x; lpt->m_point->y = y;
-
- this->OnMoveLink(dc);
- }
- if (lpt->m_type == CONTROL_POINT_ENDPOINT_FROM)
- {
- if (lpt->m_oldCursor)
- canvas->SetCursor(lpt->m_oldCursor);
- lineShape->Erase(dc);
-
- lpt->SetX(x); lpt->SetY(y);
-
- if (lineShape->GetFrom())
- {
- lineShape->GetFrom()->MoveLineToNewAttachment(dc, lineShape, x, y);
- }
- }
- if (lpt->m_type == CONTROL_POINT_ENDPOINT_TO)
- {
- if (lpt->m_oldCursor)
- canvas->SetCursor(lpt->m_oldCursor);
-
- lpt->SetX(x); lpt->SetY(y);
-
- if (lineShape->GetTo())
- {
- lineShape->GetTo()->MoveLineToNewAttachment(dc, lineShape, x, y);
- }
- }
-#endif
- return;
- }
-
- wxClientDC dc(canvas);
- canvas->PrepareDC(dc);
-
- canvas->ReleaseMouse();
- dc.SetLogicalFunction(wxCOPY);
-
-// shape->Erase(dc);
-/*
- shape->Recompute();
- shape->ResetControlPoints();
- if (!pt->m_eraseObject)
- shape->Show(FALSE);
-*/
-
- wxShape* newShape = shape->CreateNewCopy();
-
- if (newShape->IsKindOf(CLASSINFO(wxPolygonShape)))
- {
- wxPolygonControlPoint* ppt = (wxPolygonControlPoint*) pt;
- newShape->SetSize(ppt->GetNewSize().x, ppt->GetNewSize().y);
-
- ((wxPolygonShape *)newShape)->CalculateBoundingBox();
- ((wxPolygonShape *)newShape)->CalculatePolygonCentre();
- newShape->ResetControlPoints();
- }
- else
- {
- newShape->SetSize(pt->sm_controlPointDragEndWidth, pt->sm_controlPointDragEndHeight);
- if (shape->GetCentreResize())
- {
- // Old position is fine
- }
- else
- {
- newShape->SetX(pt->sm_controlPointDragPosX);
- newShape->SetY(pt->sm_controlPointDragPosY);
- }
- }
-
- csDiagramCommand* cmd = new csDiagramCommand("Size", (csDiagramDocument*)canvas->GetView()->GetDocument(),
- new csCommandState(ID_CS_SIZE, newShape, shape));
-
- canvas->GetView()->GetDocument()->GetCommandProcessor()->Submit(cmd);
-
-}
-
-void csEvtHandler::OnEndSize(double x, double y)
-{
- wxClientDC dc(GetShape()->GetCanvas());
- GetShape()->GetCanvas()->PrepareDC(dc);
-
- GetShape()->FormatText(dc, m_label);
-}
-
-void csEvtHandler::OnChangeAttachment(int attachment, wxLineShape* line, wxList& ordering)
-{
- csCanvas *canvas = (csCanvas *)GetShape()->GetCanvas();
-
- // We actually submit two different states: one to change the ordering, and another
- // to change the attachment for the line.
- // Problem. If we refresh after the attachment change, we'll get a flicker.
- // We really want to do both in a oner.
-
- csDiagramCommand* cmd = new csDiagramCommand("Change attachment", (csDiagramDocument*)canvas->GetView()->GetDocument());
-
- wxLineShape* newLine = (wxLineShape*) line->CreateNewCopy();
- if (line->GetTo() == GetShape())
- newLine->SetAttachmentTo(attachment);
- else
- newLine->SetAttachmentFrom(attachment);
-
- cmd->AddState(new csCommandState(ID_CS_CHANGE_LINE_ATTACHMENT, newLine, line));
-
- // Change ordering
- wxShape* newShape = GetShape()->CreateNewCopy();
- newShape->ApplyAttachmentOrdering(ordering);
-
- cmd->AddState(new csCommandState(ID_CS_CHANGE_LINE_ORDERING, newShape, GetShape()));
-
- canvas->GetView()->GetDocument()->GetCommandProcessor()->Submit(cmd);
-}
-
-void csEvtHandler::OnLeftDoubleClick(double x, double y, int keys, int attachment)
-{
- EditProperties();
-}
-
-// Popup up a property dialog
-bool csEvtHandler::EditProperties()
-{
- wxShape* shape = GetShape();
-
- // For now, no line property editing
- if (shape->IsKindOf(CLASSINFO(wxLineShape)))
- return FALSE;
-
- csDiagramView* view = ((csCanvas*)shape->GetCanvas())->GetView();
-
- wxPanel* attributeDialog;
- wxString attributeDialogName;
- wxString title;
-
- if (shape->IsKindOf(CLASSINFO(csThinRectangleShape)))
- {
- attributeDialog = new csThinRectangleDialog;
- attributeDialogName = "thin_rectangle";
- title = "Thin Rectangle Properties";
- }
- else if (shape->IsKindOf(CLASSINFO(csWideRectangleShape)))
- {
- attributeDialog = new csWideRectangleDialog;
- attributeDialogName = "wide_rectangle";
- title = "Wide Rectangle Properties";
- }
- else if (shape->IsKindOf(CLASSINFO(csTriangleShape)))
- {
- attributeDialog = new csTriangleDialog;
- attributeDialogName = "triangle";
- title = "Triangle Properties";
- }
- else if (shape->IsKindOf(CLASSINFO(csSemiCircleShape)))
- {
- attributeDialog = new csSemiCircleDialog;
- attributeDialogName = "semi_circle";
- title = "Semicircle Properties";
- }
- else if (shape->IsKindOf(CLASSINFO(csCircleShape)))
- {
- attributeDialog = new csCircleDialog;
- attributeDialogName = "circle";
- title = "Circle Properties";
- }
- else if (shape->IsKindOf(CLASSINFO(csCircleShadowShape)))
- {
- attributeDialog = new csCircleShadowDialog;
- attributeDialogName = "circle_shadow";
- title = "Circle Shadow Properties";
- }
- else if (shape->IsKindOf(CLASSINFO(csTextBoxShape)))
- {
- attributeDialog = new csTextBoxDialog;
- attributeDialogName = "text_box";
- title = "Text Box Properties";
- }
- else if (shape->IsKindOf(CLASSINFO(csGroupShape)))
- {
- attributeDialog = new csGroupDialog;
- attributeDialogName = "group";
- title = "Group Properties";
- }
- else if (shape->IsKindOf(CLASSINFO(csOctagonShape)))
- {
- attributeDialog = new csOctagonDialog;
- attributeDialogName = "octagon";
- title = "Octagon Properties";
- }
- else
- {
- wxMessageBox("Unrecognised shape.", "Studio", wxICON_EXCLAMATION);
- return FALSE;
- }
-
- csShapePropertiesDialog* dialog = new csShapePropertiesDialog(shape->GetCanvas()->GetParent(), title, attributeDialog, attributeDialogName);
- dialog->GetGeneralPropertiesDialog()->SetShapeLabel(m_label);
- if (dialog->ShowModal() == wxID_CANCEL)
- {
- dialog->Destroy();
- return FALSE;
- }
-
- wxString newLabel = dialog->GetGeneralPropertiesDialog()->GetShapeLabel();
- dialog->Destroy();
-
- wxShape* newShape = shape->CreateNewCopy();
-
- csEvtHandler* handler2 = (csEvtHandler *)newShape->GetEventHandler();
- handler2->m_label = newLabel;
-
- view->GetDocument()->GetCommandProcessor()->Submit(new csDiagramCommand("Edit properties", (csDiagramDocument*) view->GetDocument(),
- new csCommandState(ID_CS_EDIT_PROPERTIES, newShape, shape)));
-
- return TRUE;
-}
-
-/*
- * Diagram
- */
-
-bool csDiagram::OnShapeSave(wxExprDatabase& db, wxShape& shape, wxExpr& expr)
-{
- wxDiagram::OnShapeSave(db, shape, expr);
- csEvtHandler *handler = (csEvtHandler *)shape.GetEventHandler();
- expr.AddAttributeValueString("label", handler->m_label);
- return TRUE;
-}
-
-bool csDiagram::OnShapeLoad(wxExprDatabase& db, wxShape& shape, wxExpr& expr)
-{
- wxDiagram::OnShapeLoad(db, shape, expr);
- wxString label("");
- expr.GetAttributeValue("label", label);
- csEvtHandler *handler = new csEvtHandler(&shape, &shape, label);
- shape.SetEventHandler(handler);
-
- return TRUE;
-}
-
-IMPLEMENT_DYNAMIC_CLASS(csThinRectangleShape, wxDrawnShape)
-
-csThinRectangleShape::csThinRectangleShape()
-{
- SetDrawnPen(wxBLACK_PEN);
- wxBrush* brush = wxTheBrushList->FindOrCreateBrush(wxColour(220, 220, 220), wxSOLID);
- SetDrawnBrush(brush);
-
- double w = csSTANDARD_SHAPE_WIDTH/2;
- double h = csSTANDARD_SHAPE_WIDTH;
-
- DrawRectangle(wxRect(- w/2, - h/2, w, h));
- CalculateSize();
-
- SetAttachmentMode(ATTACHMENT_MODE_BRANCHING);
- SetBranchStyle(BRANCHING_ATTACHMENT_NORMAL|BRANCHING_ATTACHMENT_BLOB);
- SetCentreResize(FALSE);
-}
-
-IMPLEMENT_DYNAMIC_CLASS(csWideRectangleShape, wxDrawnShape)
-
-csWideRectangleShape::csWideRectangleShape()
-{
- SetDrawnPen(wxBLACK_PEN);
- wxBrush* brush = wxTheBrushList->FindOrCreateBrush(wxColour(220, 220, 220), wxSOLID);
- SetDrawnBrush(brush);
-
- double w = csSTANDARD_SHAPE_WIDTH;
- double h = w/2.0;
-
- DrawRoundedRectangle(wxRect(- w/2, - h/2, w, h), -0.3);
- CalculateSize();
-
- SetAttachmentMode(ATTACHMENT_MODE_BRANCHING);
- SetBranchStyle(BRANCHING_ATTACHMENT_NORMAL|BRANCHING_ATTACHMENT_BLOB);
- SetCentreResize(FALSE);
-}
-
-IMPLEMENT_DYNAMIC_CLASS(csTriangleShape, wxDrawnShape)
-
-csTriangleShape::csTriangleShape()
-{
- SetDrawnPen(wxBLACK_PEN);
- wxBrush* brush = wxTheBrushList->FindOrCreateBrush(wxColour(220, 220, 220), wxSOLID);
- SetDrawnBrush(brush);
-
- double w = csSTANDARD_SHAPE_WIDTH;
- double h = (csSTANDARD_SHAPE_WIDTH*2.0)/3.0;
-
- // Triangle, from top vertex
- wxPoint* points = new wxPoint[3];
-
-
- points[0] = wxPoint( 0 , - h / 2 );
- points[1] = wxPoint( w / 2 , h / 2 );
- points[2] = wxPoint( -w / 2, h / 2 );
-
- DrawPolygon(3, points, oglMETAFLAGS_OUTLINE);
-
- delete[] points;
-
- // Add another triangle at the top for the black bit
- SetDrawnBrush(wxBLACK_BRUSH);
-
- points = new wxPoint[3];
-
- // Calculate where the new points will be, using the proportions
- // of the triangle.
- double h1 = 8; // Height of little triangle.
-
- /*
- Formula: ((w/2) / h) = w1 / h1
- w1 = ((w/2) / h) * h1;
- */
- double ratio = ((w/2.0) / h) ;
- double w1 = ratio * h1;
-
- points[0] = wxPoint(0 , (int) (- h / 2 ));
- points[1] = wxPoint( (int) w1, (int) (- h / 2 + h1));
- points[2] = wxPoint( (int) -w1, (int) (- h / 2 + h1));
-
- DrawPolygon(3, points);
-
- delete[] points;
-
- CalculateSize();
-
- SetAttachmentMode(ATTACHMENT_MODE_BRANCHING);
- SetBranchStyle(BRANCHING_ATTACHMENT_NORMAL|BRANCHING_ATTACHMENT_BLOB);
- SetCentreResize(FALSE);
-}
-
-IMPLEMENT_DYNAMIC_CLASS(csSemiCircleShape, wxDrawnShape)
-
-csSemiCircleShape::csSemiCircleShape()
-{
- // Zero degrees
- DrawAtAngle(oglDRAWN_ANGLE_0);
-
- double w = csSTANDARD_SHAPE_WIDTH;
- double h = w/2.0;
-
- SetDrawnPen(wxTRANSPARENT_PEN);
- SetDrawnBrush(wxTRANSPARENT_BRUSH);
-
- // Draw a dummy rectangle that will be used for calculating the
- // bounding box, since we can't calculate the bounding box for
- // an arbitrary arc (not implemented)
-
- DrawRectangle(wxRect(-w/2.0, -h/2.0, w, h));
-
- SetDrawnPen(wxBLACK_PEN);
- wxBrush* brush = wxTheBrushList->FindOrCreateBrush(wxColour(220, 220, 220), wxSOLID);
- SetDrawnBrush(brush);
-
- DrawEllipticArc(wxRect(-w/2, -h/2, w, 2*h), 0.0, 180.0);
- DrawLine(wxPoint(-w/2, h/2), wxPoint(w/2, h/2));
-
- CalculateSize();
-
- /// 90 degrees
-
- w = csSTANDARD_SHAPE_WIDTH/2;
- h = csSTANDARD_SHAPE_WIDTH;
-
- DrawAtAngle(oglDRAWN_ANGLE_90);
-
- SetDrawnPen(wxTRANSPARENT_PEN);
- SetDrawnBrush(wxTRANSPARENT_BRUSH);
-
- DrawRectangle(wxRect(-w/2, -h/2, w, h));
-
- SetDrawnPen(wxBLACK_PEN);
- SetDrawnBrush(brush);
-
- DrawEllipticArc(wxRect(-w/2 - w, -h/2, 2*w, h), 270.0, 90.0);
- DrawLine(wxPoint(-w/2, -h/2), wxPoint(-w/2, h/2));
-
- CalculateSize();
-
- /// 180 degrees
-
- DrawAtAngle(oglDRAWN_ANGLE_180);
-
- w = csSTANDARD_SHAPE_WIDTH;
- h = csSTANDARD_SHAPE_WIDTH/2;
-
- SetDrawnPen(wxTRANSPARENT_PEN);
- SetDrawnBrush(wxTRANSPARENT_BRUSH);
-
- DrawRectangle(wxRect(-w/2, -h/2, w, h));
-
- SetDrawnPen(wxBLACK_PEN);
- SetDrawnBrush(brush);
-
- DrawEllipticArc(wxRect(-w/2, -h/2 - h, w, 2*h), 180.0, 0.0);
- DrawLine(wxPoint(-w/2, -h/2), wxPoint(w/2, -h/2));
-
- CalculateSize();
-
- /// 270 degrees
-
- DrawAtAngle(oglDRAWN_ANGLE_270);
-
- w = csSTANDARD_SHAPE_WIDTH/2;
- h = csSTANDARD_SHAPE_WIDTH;
-
- SetDrawnPen(wxTRANSPARENT_PEN);
- SetDrawnBrush(wxTRANSPARENT_BRUSH);
-
- DrawRectangle(wxRect(-w/2, -h/2, w, h));
-
- SetDrawnPen(wxBLACK_PEN);
- SetDrawnBrush(brush);
-
- DrawEllipticArc(wxRect(-w/2, -h/2, 2*w, h), 90.0, 270.0);
- DrawLine(wxPoint(w/2, -h/2), wxPoint(w/2, h/2));
-
- CalculateSize();
-
- // Reset to zero
- DrawAtAngle(oglDRAWN_ANGLE_0);
- CalculateSize();
-
- SetAttachmentMode(ATTACHMENT_MODE_BRANCHING);
- SetBranchStyle(BRANCHING_ATTACHMENT_NORMAL|BRANCHING_ATTACHMENT_BLOB);
- SetCentreResize(FALSE);
-}
-
-IMPLEMENT_DYNAMIC_CLASS(csCircleShape, wxCircleShape)
-
-csCircleShape::csCircleShape()
-{
- SetPen(wxBLACK_PEN);
- wxBrush* brush = wxTheBrushList->FindOrCreateBrush(wxColour(220, 220, 220), wxSOLID);
- SetBrush(brush);
-
- SetSize(csSTANDARD_SHAPE_WIDTH*0.6, csSTANDARD_SHAPE_WIDTH*0.6);
-
- SetAttachmentMode(ATTACHMENT_MODE_BRANCHING);
- SetBranchStyle(BRANCHING_ATTACHMENT_NORMAL|BRANCHING_ATTACHMENT_BLOB);
- SetCentreResize(FALSE);
-}
-
-IMPLEMENT_DYNAMIC_CLASS(csCircleShadowShape, wxCircleShape)
-
-csCircleShadowShape::csCircleShadowShape()
-{
- SetPen(wxBLACK_PEN);
- wxBrush* brush = wxTheBrushList->FindOrCreateBrush(wxColour(220, 220, 220), wxSOLID);
- SetBrush(brush);
-
- SetSize(csSTANDARD_SHAPE_WIDTH*0.6, csSTANDARD_SHAPE_WIDTH*0.6);
-
- SetAttachmentMode(ATTACHMENT_MODE_BRANCHING);
- SetBranchStyle(BRANCHING_ATTACHMENT_NORMAL|BRANCHING_ATTACHMENT_BLOB);
- SetCentreResize(FALSE);
- SetShadowMode(SHADOW_RIGHT);
-}
-
-IMPLEMENT_DYNAMIC_CLASS(csOctagonShape, wxPolygonShape)
-
-csOctagonShape::csOctagonShape()
-{
- SetPen(wxBLACK_PEN);
- SetBrush(wxTheBrushList->FindOrCreateBrush(wxColour(220, 220, 220), wxSOLID));
-
- double w = csSTANDARD_SHAPE_WIDTH*0.5;
- double h = csSTANDARD_SHAPE_WIDTH*0.5;
-
- double prop = h/3.0;
-
- wxList* points = new wxList;
- points->Append((wxObject*) new wxRealPoint(-w/2.0 + prop, -h/2.0));
- points->Append((wxObject*) new wxRealPoint(w/2.0 - prop, -h/2.0));
- points->Append((wxObject*) new wxRealPoint(w/2.0, -h/2.0 + prop));
- points->Append((wxObject*) new wxRealPoint(w/2.0, h/2.0 - prop));
- points->Append((wxObject*) new wxRealPoint(w/2.0 - prop, h/2.0));
- points->Append((wxObject*) new wxRealPoint(-w/2.0 + prop, h/2.0));
- points->Append((wxObject*) new wxRealPoint(-w/2.0, h/2.0 - prop));
- points->Append((wxObject*) new wxRealPoint(-w/2.0, -h/2.0 + prop));
-
- Create(points);
-
- SetAttachmentMode(ATTACHMENT_MODE_BRANCHING);
- SetBranchStyle(BRANCHING_ATTACHMENT_NORMAL|BRANCHING_ATTACHMENT_BLOB);
- SetCentreResize(FALSE);
-}
-
-// This is a transparent shape for drawing around other shapes.
-IMPLEMENT_DYNAMIC_CLASS(csGroupShape, wxRectangleShape)
-
-csGroupShape::csGroupShape()
-{
- SetPen(wxThePenList->FindOrCreatePen("BLACK", 1, wxDOT));
- SetBrush(wxTRANSPARENT_BRUSH);
-
- SetSize(csSTANDARD_SHAPE_WIDTH, csSTANDARD_SHAPE_WIDTH);
- SetCentreResize(FALSE);
-}
-
-void csGroupShape::OnDraw(wxDC& dc)
-{
- wxRectangleShape::OnDraw(dc);
-}
-
-// Must modify the hit-test so it doesn't obscure shapes that are inside.
-bool csGroupShape::HitTest(double x, double y, int* attachment, double* distance)
-{
- *attachment = 0;
- *distance = 0.0;
-
- double width = 0.0, height = 0.0;
- GetBoundingBoxMin(&width, &height);
-
- double x1 = GetX() - (width/2.0);
- double y1 = GetY() - (height/2.0);
- double x2 = GetX() + (width/2.0);
- double y2 = GetY() + (height/2.0);
-
- double edgeTolerance = 4.0;
-
- // Test each edge in turn
-
- // Top/bottom edges
- if (x >= x1 && x <= x2)
- {
- if ((y >= y1 - edgeTolerance) && (y <= y1 + edgeTolerance))
- return TRUE;
- if ((y <= y2 + edgeTolerance) && (y >= y2 - edgeTolerance))
- return TRUE;
- }
- // Left/right edges
- if (y >= y1 && y <= y2)
- {
- if ((x >= x1 - edgeTolerance) && (x <= x1 + edgeTolerance))
- return TRUE;
- if ((x <= x2 + edgeTolerance) && (x >= x2 - edgeTolerance))
- return TRUE;
- }
-
- return FALSE;
-}
-
-IMPLEMENT_DYNAMIC_CLASS(csTextBoxShape, wxRectangleShape)
-
-csTextBoxShape::csTextBoxShape()
-{
- SetPen(wxTRANSPARENT_PEN);
- SetBrush(wxTRANSPARENT_BRUSH);
-
- SetSize(csSTANDARD_SHAPE_WIDTH, csSTANDARD_SHAPE_WIDTH/2.0);
-
- SetAttachmentMode(ATTACHMENT_MODE_NONE);
- SetBranchStyle(BRANCHING_ATTACHMENT_NORMAL|BRANCHING_ATTACHMENT_BLOB);
- SetCentreResize(FALSE);
-}
-
-IMPLEMENT_DYNAMIC_CLASS(csLineShape, wxLineShape)
-
-csLineShape::csLineShape()
-{
-}
-
-bool csLineShape::OnMoveMiddleControlPoint(wxDC& dc, wxLineControlPoint* lpt, const wxRealPoint& pt)
-{
- csDiagramView* view = ((csCanvas*)GetCanvas())->GetView();
-
- // Temporarily set the new shape properties so we can copy it
- lpt->SetX(pt.x); lpt->SetY(pt.y);
- lpt->m_point->x = pt.x; lpt->m_point->y = pt.y;
-
- wxLineShape* newShape = (wxLineShape*) this->CreateNewCopy();
-
- // Now set them back again
- lpt->SetX(lpt->m_originalPos.x); lpt->SetY(lpt->m_originalPos.y);
- lpt->m_point->x = lpt->m_originalPos.x; lpt->m_point->y = lpt->m_originalPos.y;
-
- view->GetDocument()->GetCommandProcessor()->Submit(new csDiagramCommand("Move line point", (csDiagramDocument*) view->GetDocument(),
- new csCommandState(ID_CS_MOVE_LINE_POINT, newShape, this)));
-
- return TRUE;
-}
-
-wxLabelShape* csLineShape::OnCreateLabelShape(wxLineShape *parent, wxShapeRegion *region, double w, double h)
-{
- return new csLabelShape(parent, region, w, h);
-}
-
-#if 0
-bool csLineShape::OnLabelMovePre(wxDC& dc, wxLabelShape* labelShape, double x, double y, double old_x, double old_y, bool display)
-{
- csDiagramView* view = ((csCanvas*)GetCanvas())->GetView();
-
- wxLineShape* newShape = (wxLineShape*) this->CreateNewCopy();
-
- wxLineShape::OnLabelMovePre(dc, labelShape, x, y, old_x, old_y, display);
-
- view->GetDocument()->GetCommandProcessor()->Submit(new csDiagramCommand("Move label", (csDiagramDocument*) view->GetDocument(),
- new csCommandState(ID_CS_MOVE_LABEL, newShape, this)));
- return TRUE;
-}
-#endif
-
-IMPLEMENT_DYNAMIC_CLASS(csLabelShape, wxLabelShape)
-
-csLabelShape::csLabelShape(wxLineShape *parent, wxShapeRegion *region, double w, double h):
- wxLabelShape(parent, region, w, h)
-{
-}
-
-// TODO: not sure how intercept normal behaviour (OnMovePre) to make
-// label movement undo-able.
-void csLabelShape::OnEndDragLeft(double x, double y, int keys, int attachment)
-{
- wxLabelShape::OnEndDragLeft(x, y, keys, attachment);
-}
-
-
-// Menu for editing shapes
-void studioShapeEditProc(wxMenu& menu, wxCommandEvent& event)
-{
- wxShape* shape = (wxShape*) menu.GetClientData();
- csDiagramView* view = ((csCanvas*)shape->GetCanvas())->GetView();
-
- switch (event.GetId())
- {
- case ID_CS_EDIT_PROPERTIES:
- {
- csEvtHandler* handler1 = (csEvtHandler *)shape->GetEventHandler();
- handler1->EditProperties();
-#if 0
- csEvtHandler* handler1 = (csEvtHandler *)shape->GetEventHandler();
- csLabelEditingDialog* dialog = new csLabelEditingDialog(shape->GetCanvas()->GetParent());
- dialog->SetShapeLabel(handler1->m_label);
- if (dialog->ShowModal() == wxID_CANCEL)
- {
- dialog->Destroy();
- return;
- }
-
- wxString newLabel = dialog->GetShapeLabel();
- dialog->Destroy();
-
- wxShape* newShape = shape->CreateNewCopy();
-
- csEvtHandler* handler2 = (csEvtHandler *)newShape->GetEventHandler();
- handler2->m_label = newLabel;
-
- view->GetDocument()->GetCommandProcessor()->Submit(new csDiagramCommand("Edit label", (csDiagramDocument*) view->GetDocument(),
- new csCommandState(ID_CS_EDIT_LABEL, newShape, shape)));
-#endif
- break;
- }
- case wxID_CUT:
- {
- wxList list;
- list.Append(shape);
- view->DoCut(list);
- break;
- }
- case ID_CS_ROTATE_CLOCKWISE:
- case ID_CS_ROTATE_ANTICLOCKWISE:
- {
- if (shape->IsKindOf(CLASSINFO(wxLineShape)))
- break;
-
- double theta = shape->GetRotation();
- const double myPi = 3.1415926535897932384626433832795 ;
- double ninetyDegrees = myPi/2.0;
-
- wxString opStr;
- if (event.GetId() == ID_CS_ROTATE_CLOCKWISE)
- {
- theta += ninetyDegrees;
- opStr = "Rotate clockwise";
- }
- else
- {
- theta -= ninetyDegrees;
- opStr = "Rotate anticlockwise";
- }
-
- if (theta >= 2.0*myPi || theta < 0.0)
- theta = 0.0;
- wxShape* newShape = shape->CreateNewCopy();
- newShape->Rotate(0.0, 0.0, theta);
- wxList newShapes;
- wxList oldShapes;
- newShapes.Append(newShape);
- oldShapes.Append(shape);
- view->DoCmd(newShapes, oldShapes, event.GetId(), opStr);
- break;
- }
- default:
- break;
- }
-}
-
-BEGIN_EVENT_TABLE(ShapeEditMenu, wxMenu)
- EVT_COMMAND_RANGE(1, 65000, wxEVT_COMMAND_MENU_SELECTED, ShapeEditMenu::OnCommand)
-END_EVENT_TABLE()
-
-void ShapeEditMenu::OnCommand(wxCommandEvent& event)
-{
- studioShapeEditProc(*this, event);
-}
-