📄 lines.cpp
字号:
lineShape->SetPen(old_pen);
lineShape->SetBrush(old_brush);
}
if (lpt->m_type == CONTROL_POINT_ENDPOINT_FROM || lpt->m_type == CONTROL_POINT_ENDPOINT_TO)
{
m_canvas->SetCursor(wxCursor(wxCURSOR_BULLSEYE));
lpt->m_oldCursor = wxSTANDARD_CURSOR;
}
}
void wxLineShape::OnSizingEndDragLeft(wxControlPoint* pt, double x, double y, int WXUNUSED(keys), int WXUNUSED(attachment))
{
wxLineControlPoint* lpt = (wxLineControlPoint*) pt;
wxClientDC dc(GetCanvas());
GetCanvas()->PrepareDC(dc);
this->SetDisableLabel(false);
wxLineShape *lineShape = (wxLineShape *)this;
if (lpt->m_type == CONTROL_POINT_LINE)
{
m_canvas->Snap(&x, &y);
wxRealPoint pt = wxRealPoint(x, y);
// Move the control point back to where it was;
// MoveControlPoint will move it to the new position
// if it decides it wants. We only moved the position
// during user feedback so we could redraw the line
// as it changed shape.
lpt->m_xpos = lpt->m_originalPos.x; lpt->m_ypos = lpt->m_originalPos.y;
lpt->m_point->x = lpt->m_originalPos.x; lpt->m_point->y = lpt->m_originalPos.y;
OnMoveMiddleControlPoint(dc, lpt, pt);
}
if (lpt->m_type == CONTROL_POINT_ENDPOINT_FROM)
{
if (lpt->m_oldCursor)
m_canvas->SetCursor(* lpt->m_oldCursor);
// this->Erase(dc);
// lpt->m_xpos = x; lpt->m_ypos = y;
if (lineShape->GetFrom())
{
lineShape->GetFrom()->MoveLineToNewAttachment(dc, lineShape, x, y);
}
}
if (lpt->m_type == CONTROL_POINT_ENDPOINT_TO)
{
if (lpt->m_oldCursor)
m_canvas->SetCursor(* lpt->m_oldCursor);
// lpt->m_xpos = x; lpt->m_ypos = y;
if (lineShape->GetTo())
{
lineShape->GetTo()->MoveLineToNewAttachment(dc, lineShape, x, y);
}
}
// Needed?
#if 0
int i = 0;
for (i = 0; i < lineShape->GetLineControlPoints()->GetCount(); i++)
if (((wxRealPoint *)(lineShape->GetLineControlPoints()->Item(i)->GetData())) == lpt->m_point)
break;
// N.B. in OnMoveControlPoint, an event handler in Hardy could have deselected
// the line and therefore deleted 'this'. -> GPF, intermittently.
// So assume at this point that we've been blown away.
lineShape->OnMoveControlPoint(i+1, x, y);
#endif
}
// This is called only when a non-end control point is moved.
bool wxLineShape::OnMoveMiddleControlPoint(wxDC& dc, wxLineControlPoint* lpt, const wxRealPoint& pt)
{
lpt->m_xpos = pt.x; lpt->m_ypos = pt.y;
lpt->m_point->x = pt.x; lpt->m_point->y = pt.y;
GetEventHandler()->OnMoveLink(dc);
return true;
}
// Implement movement of endpoint to a new attachment
// OBSOLETE: done by dragging with the left button.
#if 0
void wxLineControlPoint::OnDragRight(bool draw, double x, double y, int keys, int attachment)
{
if (m_type == CONTROL_POINT_ENDPOINT_FROM || m_type == CONTROL_POINT_ENDPOINT_TO)
{
m_xpos = x; m_ypos = y;
}
}
void wxLineControlPoint::OnBeginDragRight(double x, double y, int keys, int attachment)
{
wxClientDC dc(GetCanvas());
GetCanvas()->PrepareDC(dc);
wxLineShape *lineShape = (wxLineShape *)m_shape;
if (m_type == CONTROL_POINT_ENDPOINT_FROM || m_type == CONTROL_POINT_ENDPOINT_TO)
{
Erase(dc);
lineShape->GetEventHandler()->OnDraw(dc);
if (m_type == CONTROL_POINT_ENDPOINT_FROM)
{
lineShape->GetFrom()->GetEventHandler()->OnDraw(dc);
lineShape->GetFrom()->GetEventHandler()->OnDrawContents(dc);
}
else
{
lineShape->GetTo()->GetEventHandler()->OnDraw(dc);
lineShape->GetTo()->GetEventHandler()->OnDrawContents(dc);
}
m_canvas->SetCursor(wxCursor(wxCURSOR_BULLSEYE));
m_oldCursor = wxSTANDARD_CURSOR;
}
}
void wxLineControlPoint::OnEndDragRight(double x, double y, int keys, int attachment)
{
wxClientDC dc(GetCanvas());
GetCanvas()->PrepareDC(dc);
wxLineShape *lineShape = (wxLineShape *)m_shape;
if (m_type == CONTROL_POINT_ENDPOINT_FROM)
{
if (m_oldCursor)
m_canvas->SetCursor(m_oldCursor);
m_xpos = x; m_ypos = y;
if (lineShape->GetFrom())
{
lineShape->GetFrom()->EraseLinks(dc);
int new_attachment;
double distance;
if (lineShape->GetFrom()->HitTest(x, y, &new_attachment, &distance))
lineShape->SetAttachments(new_attachment, lineShape->GetAttachmentTo());
lineShape->GetFrom()->MoveLinks(dc);
}
}
if (m_type == CONTROL_POINT_ENDPOINT_TO)
{
if (m_oldCursor)
m_canvas->SetCursor(m_oldCursor);
m_shape->Erase(dc);
m_xpos = x; m_ypos = y;
if (lineShape->GetTo())
{
lineShape->GetTo()->EraseLinks(dc);
int new_attachment;
double distance;
if (lineShape->GetTo()->HitTest(x, y, &new_attachment, &distance))
lineShape->SetAttachments(lineShape->GetAttachmentFrom(), new_attachment);
lineShape->GetTo()->MoveLinks(dc);
}
}
int i = 0;
for (i = 0; i < lineShape->GetLineControlPoints()->GetCount(); i++)
if (((wxRealPoint *)(lineShape->GetLineControlPoints()->Item(i)->GetData())) == m_point)
break;
lineShape->OnMoveControlPoint(i+1, x, y);
if (!m_canvas->GetQuickEditMode()) m_canvas->Redraw(dc);
}
#endif
/*
* Get the point on the given line (x1, y1) (x2, y2)
* distance 'length' along from the end,
* returned values in x and y
*/
void GetPointOnLine(double x1, double y1, double x2, double y2,
double length, double *x, double *y)
{
double l = (double)sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1));
if (l < 0.01)
l = (double) 0.01;
double i_bar = (x2 - x1)/l;
double j_bar = (y2 - y1)/l;
*x = (- length*i_bar) + x2;
*y = (- length*j_bar) + y2;
}
wxArrowHead *wxLineShape::AddArrow(WXTYPE type, int end, double size, double xOffset,
const wxString& name, wxPseudoMetaFile *mf, long arrowId)
{
wxArrowHead *arrow = new wxArrowHead(type, end, size, xOffset, name, mf, arrowId);
m_arcArrows.Append(arrow);
return arrow;
}
/*
* Add arrowhead at a particular position in the arrowhead list.
*/
bool wxLineShape::AddArrowOrdered(wxArrowHead *arrow, wxList& referenceList, int end)
{
wxNode *refNode = referenceList.GetFirst();
wxNode *currNode = m_arcArrows.GetFirst();
wxString targetName(arrow->GetName());
if (!refNode) return false;
// First check whether we need to insert in front of list,
// because this arrowhead is the first in the reference
// list and should therefore be first in the current list.
wxArrowHead *refArrow = (wxArrowHead *)refNode->GetData();
if (refArrow->GetName() == targetName)
{
m_arcArrows.Insert(arrow);
return true;
}
wxArrowHead *currArrow = (wxArrowHead *)currNode->GetData();
while (refNode && currNode)
{
refArrow = (wxArrowHead *)refNode->GetData();
// Matching: advance current arrow pointer
if ((currArrow->GetArrowEnd() == end) &&
(currArrow->GetName() == refArrow->GetName()))
{
currNode = currNode->GetNext(); // Could be NULL now
if (currNode)
currArrow = (wxArrowHead *)currNode->GetData();
}
// Check if we're at the correct position in the
// reference list
if (targetName == refArrow->GetName())
{
if (currNode)
m_arcArrows.Insert(currNode, arrow);
else
m_arcArrows.Append(arrow);
return true;
}
refNode = refNode->GetNext();
}
m_arcArrows.Append(arrow);
return true;
}
void wxLineShape::ClearArrowsAtPosition(int end)
{
wxNode *node = m_arcArrows.GetFirst();
while (node)
{
wxArrowHead *arrow = (wxArrowHead *)node->GetData();
wxNode *next = node->GetNext();
switch (end)
{
case -1:
{
delete arrow;
delete node;
break;
}
case ARROW_POSITION_START:
{
if (arrow->GetArrowEnd() == ARROW_POSITION_START)
{
delete arrow;
delete node;
}
break;
}
case ARROW_POSITION_END:
{
if (arrow->GetArrowEnd() == ARROW_POSITION_END)
{
delete arrow;
delete node;
}
break;
}
case ARROW_POSITION_MIDDLE:
{
if (arrow->GetArrowEnd() == ARROW_POSITION_MIDDLE)
{
delete arrow;
delete node;
}
break;
}
}
node = next;
}
}
bool wxLineShape::ClearArrow(const wxString& name)
{
wxNode *node = m_arcArrows.GetFirst();
while (node)
{
wxArrowHead *arrow = (wxArrowHead *)node->GetData();
if (arrow->GetName() == name)
{
delete arrow;
delete node;
return true;
}
node = node->GetNext();
}
return false;
}
/*
* Finds an arrowhead at the given position (if -1, any position)
*
*/
wxArrowHead *wxLineShape::FindArrowHead(int position, const wxString& name)
{
wxNode *node = m_arcArrows.GetFirst();
while (node)
{
wxArrowHead *arrow = (wxArrowHead *)node->GetData();
if (((position == -1) || (position == arrow->GetArrowEnd())) &&
(arrow->GetName() == name))
return arrow;
node = node->GetNext();
}
return NULL;
}
wxArrowHead *wxLineShape::FindArrowHead(long arrowId)
{
wxNode *node = m_arcArrows.GetFirst();
while (node)
{
wxArrowHead *arrow = (wxArrowHead *)node->GetData();
if (arrowId == arrow->GetId())
return arrow;
node = node->GetNext();
}
return NULL;
}
/*
* Deletes an arrowhead at the given position (if -1, any position)
*
*/
bool wxLineShape::DeleteArrowHead(int position, const wxString& name)
{
wxNode *node = m_arcArrows.GetFirst();
while (node)
{
wxArrowHead *arrow = (wxArrowHead *)node->GetData();
if (((position == -1) || (position == arrow->GetArrowEnd())) &&
(arrow->GetName() == name))
{
delete arrow;
delete node;
return true;
}
node = node->GetNext();
}
return false;
}
// Overloaded DeleteArrowHead: pass arrowhead id.
bool wxLineShape::DeleteArrowHead(long id)
{
wxNode *node = m_arcArrows.GetFirst();
while (node)
{
wxArrowHead *arrow = (wxArrowHead *)node->GetData();
if (arrow->GetId() == id)
{
delete arrow;
delete node;
return true;
}
node = node->GetNext();
}
return false;
}
/*
* Calculate the minimum width a line
* occupies, for the purposes of drawing lines in tools.
*
*/
double wxLineShape::FindMinimumWidth()
{
double minWidth = 0.0;
wxNode *node = m_arcArrows.GetFirst();
while (node)
{
wxArrowHead *arrowHead = (wxArrowHead *)node->GetData();
minWidth += arrowHead->GetSize();
if (node->GetNext())
minWidth += arrowHead->GetSpacing();
node = node->GetNext();
}
// We have ABSOLUTE minimum now. So
// scale it to give it reasonable aesthetics
// when drawing with line.
if (minWidth > 0.0)
minWidth = (double)(minWidth * 1.4);
else
minWidth = 20.0;
SetEnds(0.0, 0.0, minWidth, 0.0);
Initialise();
return minWidth;
}
// Find which position we're talking about at this (x, y).
// Returns ARROW_POSITION_START, ARROW_POSITION_MIDDLE, ARROW_POSITION_END
int wxLineShape::FindLinePosition(double x, double y)
{
double startX, startY, endX, endY;
GetEnds(&startX, &startY, &endX, &endY);
// Find distances from centre, start and end. The smallest wins.
double centreDistance = (double)(sqrt((x - m_xpos)*(x - m_xpos) + (y - m_ypos)*(y - m_ypos)));
double startDistance = (double)(sqrt((x - startX)*(x - startX) + (y - startY)*(y - startY)));
double endDistance = (double)(sqrt((x - endX)*(x - endX) + (y - endY)*(y - endY)));
if (centreDistance < startDistance && centreDistance < endDistance)
return ARROW_POSITION_MIDDLE;
else if (startDistance < endDistance)
return ARROW_POSITION_START;
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -