📄 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 shapeIMPLEMENT_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 listvoid 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, 2void 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 endsvoid 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;}void wxLineShape::SetAttachments(int from_attach, int to_attach){ m_attachmentFrom = from_attach; m_attachmentTo = to_attach;}bool wxLineShape::HitTest(double x, double y, int *attachment, double *distance){ if (!m_lineControlPoints) return false; // Look at label regions in case mouse is over a label bool inLabelRegion = false;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -