📄 shapes.cpp
字号:
/////////////////////////////////////////////////////////////////////////////
// Name: contrib/samples/ogl/studio/shapes.cpp
// Purpose: Implements Studio shapes
// Author: Julian Smart
// Modified by:
// Created: 12/07/98
// RCS-ID: $Id: shapes.cpp,v 1.14 2006/02/10 11:59:48 ABX Exp $
// Copyright: (c) Julian Smart
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// 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/ogl/ogl.h" // base header of OGL, includes and adjusts wx/deprecated/setup.h
#include "studio.h"
#include "doc.h"
#include "shapes.h"
#include "view.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 WXUNUSED(x), double WXUNUSED(y), int keys, int WXUNUSED(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
{
#if wxUSE_STATUSBAR
((wxFrame*)wxGetApp().GetTopWindow())->SetStatusText(m_label);
#endif // wxUSE_STATUSBAR
}
}
void csEvtHandler::OnRightClick(double x, double y, int WXUNUSED(keys), int WXUNUSED(attachment))
{
// Have to convert back to physical coordinates from logical coordinates.
int viewStartX, viewStartY;
int unitX, unitY;
GetShape()->GetCanvas()->GetViewStart(& 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 WXUNUSED(keys), int attachment)
{
wxClientDC dc(GetShape()->GetCanvas());
GetShape()->GetCanvas()->PrepareDC(dc);
wxPen dottedPen(*wxBLACK, 1, wxDOT);
dc.SetLogicalFunction(OGLRBLF);
dc.SetPen(dottedPen);
double xp, yp;
GetShape()->GetAttachmentPositionEdge(attachment, &xp, &yp);
dc.DrawLine((wxCoord)xp, (wxCoord)yp, (wxCoord)x, (wxCoord)y);
GetShape()->GetCanvas()->CaptureMouse();
}
void csEvtHandler::OnDragRight(bool WXUNUSED(draw), double x, double y, int WXUNUSED(keys), int attachment)
{
wxClientDC dc(GetShape()->GetCanvas());
GetShape()->GetCanvas()->PrepareDC(dc);
wxPen dottedPen(*wxBLACK, 1, wxDOT);
dc.SetLogicalFunction(OGLRBLF);
dc.SetPen(dottedPen);
double xp, yp;
GetShape()->GetAttachmentPositionEdge(attachment, &xp, &yp);
dc.DrawLine((wxCoord)xp, (wxCoord)yp, (wxCoord)x, (wxCoord)y);
}
void csEvtHandler::OnEndDragRight(double x, double y, int WXUNUSED(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, wxEmptyString));
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, _T("Normal arrowhead"));
lineShape->SetFrom(GetShape());
lineShape->SetTo(otherShape);
lineShape->SetAttachments(attachment, new_attachment);
canvas->GetView()->GetDocument()->GetCommandProcessor()->Submit(
new csDiagramCommand(_T("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(*wxBLACK, 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
wxObjectList::compatibility_iterator node = GetShape()->GetCanvas()->GetDiagram()->GetShapeList()->GetFirst();
while (node)
{
wxShape* shape = (wxShape*) node->GetData();
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->GetNext();
}
}
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(*wxBLACK, 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
wxObjectList::compatibility_iterator node = GetShape()->GetCanvas()->GetDiagram()->GetShapeList()->GetFirst();
while (node)
{
wxShape* shape = (wxShape*) node->GetData();
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->GetNext();
}
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -