📄 lines.cpp
字号:
/////////////////////////////////////////////////////////////////////////////
// Name: lines.cpp
// Purpose: wxLineShape
// Author: Julian Smart
// Modified by:
// Created: 12/07/98
// RCS-ID: $Id: lines.cpp,v 1.27 2006/04/18 22:26:26 PC 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_PROLOGIO
#include "wx/deprecated/wxexpr.h"
#endif
#ifdef new
#undef new
#endif
#include <ctype.h>
#include "wx/ogl/ogl.h"
// Line shape
IMPLEMENT_DYNAMIC_CLASS(wxLineShape, wxShape)
wxLineShape::wxLineShape()
{
m_sensitivity = OP_CLICK_LEFT | OP_CLICK_RIGHT;
m_draggable = false;
m_attachmentTo = 0;
m_attachmentFrom = 0;
/*
m_actualTextWidth = 0.0;
m_actualTextHeight = 0.0;
*/
m_from = NULL;
m_to = NULL;
m_erasing = false;
m_arrowSpacing = 5.0; // For the moment, don't bother saving this to file.
m_ignoreArrowOffsets = false;
m_isSpline = false;
m_maintainStraightLines = false;
m_alignmentStart = 0;
m_alignmentEnd = 0;
m_lineControlPoints = NULL;
// Clear any existing regions (created in an earlier constructor)
// and make the three line regions.
ClearRegions();
wxShapeRegion *newRegion = new wxShapeRegion;
newRegion->SetName(wxT("Middle"));
newRegion->SetSize(150, 50);
m_regions.Append((wxObject *)newRegion);
newRegion = new wxShapeRegion;
newRegion->SetName(wxT("Start"));
newRegion->SetSize(150, 50);
m_regions.Append((wxObject *)newRegion);
newRegion = new wxShapeRegion;
newRegion->SetName(wxT("End"));
newRegion->SetSize(150, 50);
m_regions.Append((wxObject *)newRegion);
for (int i = 0; i < 3; i++)
m_labelObjects[i] = NULL;
}
wxLineShape::~wxLineShape()
{
if (m_lineControlPoints)
{
ClearPointList(*m_lineControlPoints);
delete m_lineControlPoints;
}
for (int i = 0; i < 3; i++)
{
if (m_labelObjects[i])
{
m_labelObjects[i]->Select(false);
m_labelObjects[i]->RemoveFromCanvas(m_canvas);
delete m_labelObjects[i];
m_labelObjects[i] = NULL;
}
}
ClearArrowsAtPosition(-1);
}
void wxLineShape::MakeLineControlPoints(int n)
{
if (m_lineControlPoints)
{
ClearPointList(*m_lineControlPoints);
delete m_lineControlPoints;
}
m_lineControlPoints = new wxList;
for (int i = 0; i < n; i++)
{
wxRealPoint *point = new wxRealPoint(-999, -999);
m_lineControlPoints->Append((wxObject*) point);
}
}
wxNode *wxLineShape::InsertLineControlPoint(wxDC* dc)
{
if (dc)
Erase(*dc);
wxNode *last = m_lineControlPoints->GetLast();
wxNode *second_last = last->GetPrevious();
wxRealPoint *last_point = (wxRealPoint *)last->GetData();
wxRealPoint *second_last_point = (wxRealPoint *)second_last->GetData();
// Choose a point half way between the last and penultimate points
double line_x = ((last_point->x + second_last_point->x)/2);
double line_y = ((last_point->y + second_last_point->y)/2);
wxRealPoint *point = new wxRealPoint(line_x, line_y);
wxNode *node = m_lineControlPoints->Insert(last, (wxObject*) point);
return node;
}
bool wxLineShape::DeleteLineControlPoint()
{
if (m_lineControlPoints->GetCount() < 3)
return false;
wxNode *last = m_lineControlPoints->GetLast();
wxNode *second_last = last->GetPrevious();
wxRealPoint *second_last_point = (wxRealPoint *)second_last->GetData();
delete second_last_point;
delete second_last;
return true;
}
void wxLineShape::Initialise()
{
if (m_lineControlPoints)
{
// Just move the first and last control points
wxNode *first = m_lineControlPoints->GetFirst();
wxRealPoint *first_point = (wxRealPoint *)first->GetData();
wxNode *last = m_lineControlPoints->GetLast();
wxRealPoint *last_point = (wxRealPoint *)last->GetData();
// If any of the line points are at -999, we must
// initialize them by placing them half way between the first
// and the last.
wxNode *node = first->GetNext();
while (node)
{
wxRealPoint *point = (wxRealPoint *)node->GetData();
if (point->x == -999)
{
double x1, y1, x2, y2;
if (first_point->x < last_point->x)
{ x1 = first_point->x; x2 = last_point->x; }
else
{ x2 = first_point->x; x1 = last_point->x; }
if (first_point->y < last_point->y)
{ y1 = first_point->y; y2 = last_point->y; }
else
{ y2 = first_point->y; y1 = last_point->y; }
point->x = ((x2 - x1)/2 + x1);
point->y = ((y2 - y1)/2 + y1);
}
node = node->GetNext();
}
}
}
// Format a text string according to the region size, adding
// strings with positions to region text list
void wxLineShape::FormatText(wxDC& dc, const wxString& s, int i)
{
double w, h;
ClearText(i);
if (m_regions.GetCount() < 1)
return;
wxNode *node = m_regions.Item(i);
if (!node)
return;
wxShapeRegion *region = (wxShapeRegion *)node->GetData();
region->SetText(s);
dc.SetFont(* region->GetFont());
region->GetSize(&w, &h);
// Initialize the size if zero
if (((w == 0) || (h == 0)) && (s.Length() > 0))
{
w = 100; h = 50;
region->SetSize(w, h);
}
wxStringList *string_list = oglFormatText(dc, s, (w-5), (h-5), region->GetFormatMode());
node = (wxNode*)string_list->GetFirst();
while (node)
{
wxChar *s = (wxChar *)node->GetData();
wxShapeTextLine *line = new wxShapeTextLine(0.0, 0.0, s);
region->GetFormattedText().Append((wxObject *)line);
node = node->GetNext();
}
delete string_list;
double actualW = w;
double actualH = h;
if (region->GetFormatMode() & FORMAT_SIZE_TO_CONTENTS)
{
oglGetCentredTextExtent(dc, &(region->GetFormattedText()), m_xpos, m_ypos, w, h, &actualW, &actualH);
if ((actualW != w ) || (actualH != h))
{
double xx, yy;
GetLabelPosition(i, &xx, &yy);
EraseRegion(dc, region, xx, yy);
if (m_labelObjects[i])
{
m_labelObjects[i]->Select(false, &dc);
m_labelObjects[i]->Erase(dc);
m_labelObjects[i]->SetSize(actualW, actualH);
}
region->SetSize(actualW, actualH);
if (m_labelObjects[i])
{
m_labelObjects[i]->Select(true, & dc);
m_labelObjects[i]->Draw(dc);
}
}
}
oglCentreText(dc, &(region->GetFormattedText()), m_xpos, m_ypos, actualW, actualH, region->GetFormatMode());
m_formatted = true;
}
void wxLineShape::DrawRegion(wxDC& dc, wxShapeRegion *region, double x, double y)
{
if (GetDisableLabel())
return;
double w, h;
double xx, yy;
region->GetSize(&w, &h);
// Get offset from x, y
region->GetPosition(&xx, &yy);
double xp = xx + x;
double yp = yy + y;
// First, clear a rectangle for the text IF there is any
if (region->GetFormattedText().GetCount() > 0)
{
dc.SetPen(GetBackgroundPen());
dc.SetBrush(GetBackgroundBrush());
// Now draw the text
if (region->GetFont()) dc.SetFont(* region->GetFont());
dc.DrawRectangle((long)(xp - w/2.0), (long)(yp - h/2.0), (long)w, (long)h);
if (m_pen) dc.SetPen(* m_pen);
dc.SetTextForeground(region->GetActualColourObject());
#ifdef __WXMSW__
dc.SetTextBackground(GetBackgroundBrush().GetColour());
#endif
oglDrawFormattedText(dc, &(region->GetFormattedText()), xp, yp, w, h, region->GetFormatMode());
}
}
void wxLineShape::EraseRegion(wxDC& dc, wxShapeRegion *region, double x, double y)
{
if (GetDisableLabel())
return;
double w, h;
double xx, yy;
region->GetSize(&w, &h);
// Get offset from x, y
region->GetPosition(&xx, &yy);
double xp = xx + x;
double yp = yy + y;
if (region->GetFormattedText().GetCount() > 0)
{
dc.SetPen(GetBackgroundPen());
dc.SetBrush(GetBackgroundBrush());
dc.DrawRectangle((long)(xp - w/2.0), (long)(yp - h/2.0), (long)w, (long)h);
}
}
// Get the reference point for a label. Region x and y
// are offsets from this.
// position is 0, 1, 2
void wxLineShape::GetLabelPosition(int position, double *x, double *y)
{
switch (position)
{
case 0:
{
// Want to take the middle section for the label
int n = m_lineControlPoints->GetCount();
int half_way = (int)(n/2);
// Find middle of this line
wxNode *node = m_lineControlPoints->Item(half_way - 1);
wxRealPoint *point = (wxRealPoint *)node->GetData();
wxNode *next_node = node->GetNext();
wxRealPoint *next_point = (wxRealPoint *)next_node->GetData();
double dx = (next_point->x - point->x);
double dy = (next_point->y - point->y);
*x = (double)(point->x + dx/2.0);
*y = (double)(point->y + dy/2.0);
break;
}
case 1:
{
wxNode *node = m_lineControlPoints->GetFirst();
*x = ((wxRealPoint *)node->GetData())->x;
*y = ((wxRealPoint *)node->GetData())->y;
break;
}
case 2:
{
wxNode *node = m_lineControlPoints->GetLast();
*x = ((wxRealPoint *)node->GetData())->x;
*y = ((wxRealPoint *)node->GetData())->y;
break;
}
default:
break;
}
}
/*
* Find whether line is supposed to be vertical or horizontal and
* make it so.
*
*/
void GraphicsStraightenLine(wxRealPoint *point1, wxRealPoint *point2)
{
double dx = point2->x - point1->x;
double dy = point2->y - point1->y;
if (dx == 0.0)
return;
else if (fabs(dy/dx) > 1.0)
{
point2->x = point1->x;
}
else point2->y = point1->y;
}
void wxLineShape::Straighten(wxDC *dc)
{
if (!m_lineControlPoints || m_lineControlPoints->GetCount() < 3)
return;
if (dc)
Erase(* dc);
wxNode *first_point_node = m_lineControlPoints->GetFirst();
wxNode *last_point_node = m_lineControlPoints->GetLast();
wxNode *second_last_point_node = last_point_node->GetPrevious();
wxRealPoint *last_point = (wxRealPoint *)last_point_node->GetData();
wxRealPoint *second_last_point = (wxRealPoint *)second_last_point_node->GetData();
GraphicsStraightenLine(last_point, second_last_point);
wxNode *node = first_point_node;
while (node && (node != second_last_point_node))
{
wxRealPoint *point = (wxRealPoint *)node->GetData();
wxRealPoint *next_point = (wxRealPoint *)(node->GetNext()->GetData());
GraphicsStraightenLine(point, next_point);
node = node->GetNext();
}
if (dc)
Draw(* dc);
}
void wxLineShape::Unlink()
{
if (m_to)
m_to->GetLines().DeleteObject(this);
if (m_from)
m_from->GetLines().DeleteObject(this);
m_to = NULL;
m_from = NULL;
}
void wxLineShape::SetEnds(double x1, double y1, double x2, double y2)
{
// Find centre point
wxNode *first_point_node = m_lineControlPoints->GetFirst();
wxNode *last_point_node = m_lineControlPoints->GetLast();
wxRealPoint *first_point = (wxRealPoint *)first_point_node->GetData();
wxRealPoint *last_point = (wxRealPoint *)last_point_node->GetData();
first_point->x = x1;
first_point->y = y1;
last_point->x = x2;
last_point->y = y2;
m_xpos = (double)((x1 + x2)/2.0);
m_ypos = (double)((y1 + y2)/2.0);
}
// Get absolute positions of ends
void wxLineShape::GetEnds(double *x1, double *y1, double *x2, double *y2)
{
wxNode *first_point_node = m_lineControlPoints->GetFirst();
wxNode *last_point_node = m_lineControlPoints->GetLast();
wxRealPoint *first_point = (wxRealPoint *)first_point_node->GetData();
wxRealPoint *last_point = (wxRealPoint *)last_point_node->GetData();
*x1 = first_point->x; *y1 = first_point->y;
*x2 = last_point->x; *y2 = last_point->y;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -