📄 shapes.cpp
字号:
/*
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((int)(-w/2.0), (int)(-h/2.0), (int)(w), (int)(h)));
SetDrawnPen(wxBLACK_PEN);
wxBrush* brush = wxTheBrushList->FindOrCreateBrush(wxColour(220, 220, 220), wxSOLID);
SetDrawnBrush(brush);
DrawEllipticArc(wxRect((int)(-w/2), (int)(-h/2), (int)(w), (int)(2*h)), 0.0, 180.0);
DrawLine(wxPoint((int)(-w/2), (int)(h/2)), wxPoint((int)(w/2), (int)(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((int)(-w/2), (int)(-h/2), (int)(w), (int)(h)));
SetDrawnPen(wxBLACK_PEN);
SetDrawnBrush(brush);
DrawEllipticArc(wxRect((int)(-w/2 - w), (int)(-h/2), (int)(2*w), (int)(h)), 270.0, 90.0);
DrawLine(wxPoint((int)(-w/2), (int)(-h/2)), wxPoint((int)(-w/2), (int)(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((int)(-w/2), (int)(-h/2), (int)(w), (int)(h)));
SetDrawnPen(wxBLACK_PEN);
SetDrawnBrush(brush);
DrawEllipticArc(wxRect((int)(-w/2), (int)(-h/2 - h), (int)(w), (int)(2*h)), 180.0, 0.0);
DrawLine(wxPoint((int)(-w/2), (int)(-h/2)), wxPoint((int)(w/2), (int)(-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((int)(-w/2), (int)(-h/2), (int)(w), (int)(h)));
SetDrawnPen(wxBLACK_PEN);
SetDrawnBrush(brush);
DrawEllipticArc(wxRect((int)(-w/2), (int)(-h/2), (int)(2*w), (int)(h)), 90.0, 270.0);
DrawLine(wxPoint((int)(w/2),(int)(-h/2)), wxPoint((int)(w/2), (int)(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(_T("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& WXUNUSED(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(_T("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 = M_PI;
double ninetyDegrees = myPi/2.0;
wxString opStr;
if (event.GetId() == ID_CS_ROTATE_CLOCKWISE)
{
theta += ninetyDegrees;
opStr = _T("Rotate clockwise");
}
else
{
theta -= ninetyDegrees;
opStr = _T("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);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -