git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_4_BRANCH@18317 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
1907 lines
51 KiB
C++
1907 lines
51 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: basic2.cpp
|
|
// Purpose: Basic OGL classes (2)
|
|
// Author: Julian Smart
|
|
// Modified by:
|
|
// Created: 12/07/98
|
|
// RCS-ID: $Id$
|
|
// Copyright: (c) Julian Smart
|
|
// Licence: wxWindows licence
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifdef __GNUG__
|
|
#pragma implementation "basicp.h"
|
|
#endif
|
|
|
|
// 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
|
|
|
|
#include <wx/wxexpr.h>
|
|
|
|
#ifdef new
|
|
#undef new
|
|
#endif
|
|
|
|
#if wxUSE_IOSTREAMH
|
|
#include <iostream.h>
|
|
#else
|
|
#include <iostream>
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include <math.h>
|
|
|
|
#include <wx/ogl/basic.h>
|
|
#include <wx/ogl/basicp.h>
|
|
#include <wx/ogl/composit.h>
|
|
#include <wx/ogl/lines.h>
|
|
#include <wx/ogl/canvas.h>
|
|
#include <wx/ogl/divided.h>
|
|
#include <wx/ogl/misc.h>
|
|
|
|
// Control point types
|
|
// Rectangle and most other shapes
|
|
#define CONTROL_POINT_VERTICAL 1
|
|
#define CONTROL_POINT_HORIZONTAL 2
|
|
#define CONTROL_POINT_DIAGONAL 3
|
|
|
|
// Line
|
|
#define CONTROL_POINT_ENDPOINT_TO 4
|
|
#define CONTROL_POINT_ENDPOINT_FROM 5
|
|
#define CONTROL_POINT_LINE 6
|
|
|
|
// Two stage construction: need to call Create
|
|
IMPLEMENT_DYNAMIC_CLASS(wxPolygonShape, wxShape)
|
|
|
|
wxPolygonShape::wxPolygonShape()
|
|
{
|
|
m_points = NULL;
|
|
m_originalPoints = NULL;
|
|
}
|
|
|
|
void wxPolygonShape::Create(wxList *the_points)
|
|
{
|
|
ClearPoints();
|
|
|
|
m_originalPoints = the_points;
|
|
|
|
// Duplicate the list of points
|
|
m_points = new wxList;
|
|
|
|
wxNode *node = the_points->First();
|
|
while (node)
|
|
{
|
|
wxRealPoint *point = (wxRealPoint *)node->Data();
|
|
wxRealPoint *new_point = new wxRealPoint(point->x, point->y);
|
|
m_points->Append((wxObject*) new_point);
|
|
node = node->Next();
|
|
}
|
|
CalculateBoundingBox();
|
|
m_originalWidth = m_boundWidth;
|
|
m_originalHeight = m_boundHeight;
|
|
SetDefaultRegionSize();
|
|
}
|
|
|
|
wxPolygonShape::~wxPolygonShape()
|
|
{
|
|
ClearPoints();
|
|
}
|
|
|
|
void wxPolygonShape::ClearPoints()
|
|
{
|
|
if (m_points)
|
|
{
|
|
wxNode *node = m_points->First();
|
|
while (node)
|
|
{
|
|
wxRealPoint *point = (wxRealPoint *)node->Data();
|
|
delete point;
|
|
delete node;
|
|
node = m_points->First();
|
|
}
|
|
delete m_points;
|
|
m_points = NULL;
|
|
}
|
|
if (m_originalPoints)
|
|
{
|
|
wxNode *node = m_originalPoints->First();
|
|
while (node)
|
|
{
|
|
wxRealPoint *point = (wxRealPoint *)node->Data();
|
|
delete point;
|
|
delete node;
|
|
node = m_originalPoints->First();
|
|
}
|
|
delete m_originalPoints;
|
|
m_originalPoints = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
// Width and height. Centre of object is centre of box.
|
|
void wxPolygonShape::GetBoundingBoxMin(double *width, double *height)
|
|
{
|
|
*width = m_boundWidth;
|
|
*height = m_boundHeight;
|
|
}
|
|
|
|
void wxPolygonShape::CalculateBoundingBox()
|
|
{
|
|
// Calculate bounding box at construction (and presumably resize) time
|
|
double left = 10000;
|
|
double right = -10000;
|
|
double top = 10000;
|
|
double bottom = -10000;
|
|
|
|
wxNode *node = m_points->First();
|
|
while (node)
|
|
{
|
|
wxRealPoint *point = (wxRealPoint *)node->Data();
|
|
if (point->x < left) left = point->x;
|
|
if (point->x > right) right = point->x;
|
|
|
|
if (point->y < top) top = point->y;
|
|
if (point->y > bottom) bottom = point->y;
|
|
|
|
node = node->Next();
|
|
}
|
|
m_boundWidth = right - left;
|
|
m_boundHeight = bottom - top;
|
|
}
|
|
|
|
// Recalculates the centre of the polygon, and
|
|
// readjusts the point offsets accordingly.
|
|
// Necessary since the centre of the polygon
|
|
// is expected to be the real centre of the bounding
|
|
// box.
|
|
void wxPolygonShape::CalculatePolygonCentre()
|
|
{
|
|
double left = 10000;
|
|
double right = -10000;
|
|
double top = 10000;
|
|
double bottom = -10000;
|
|
|
|
wxNode *node = m_points->First();
|
|
while (node)
|
|
{
|
|
wxRealPoint *point = (wxRealPoint *)node->Data();
|
|
if (point->x < left) left = point->x;
|
|
if (point->x > right) right = point->x;
|
|
|
|
if (point->y < top) top = point->y;
|
|
if (point->y > bottom) bottom = point->y;
|
|
|
|
node = node->Next();
|
|
}
|
|
double bwidth = right - left;
|
|
double bheight = bottom - top;
|
|
|
|
double newCentreX = (double)(left + (bwidth/2.0));
|
|
double newCentreY = (double)(top + (bheight/2.0));
|
|
|
|
node = m_points->First();
|
|
while (node)
|
|
{
|
|
wxRealPoint *point = (wxRealPoint *)node->Data();
|
|
point->x -= newCentreX;
|
|
point->y -= newCentreY;
|
|
node = node->Next();
|
|
}
|
|
m_xpos += newCentreX;
|
|
m_ypos += newCentreY;
|
|
}
|
|
|
|
bool PolylineHitTest(double n, double xvec[], double yvec[],
|
|
double x1, double y1, double x2, double y2)
|
|
{
|
|
bool isAHit = FALSE;
|
|
int i;
|
|
double lastx = xvec[0];
|
|
double lasty = yvec[0];
|
|
|
|
double min_ratio = 1.0;
|
|
double line_ratio;
|
|
double other_ratio;
|
|
|
|
// char buf[300];
|
|
for (i = 1; i < n; i++)
|
|
{
|
|
oglCheckLineIntersection(x1, y1, x2, y2, lastx, lasty, xvec[i], yvec[i],
|
|
&line_ratio, &other_ratio);
|
|
if (line_ratio != 1.0)
|
|
isAHit = TRUE;
|
|
// sprintf(buf, "Line ratio = %.2f, other ratio = %.2f\n", line_ratio, other_ratio);
|
|
// ClipsErrorFunction(buf);
|
|
lastx = xvec[i];
|
|
lasty = yvec[i];
|
|
|
|
if (line_ratio < min_ratio)
|
|
min_ratio = line_ratio;
|
|
}
|
|
|
|
// Do last (implicit) line if last and first doubles are not identical
|
|
if (!(xvec[0] == lastx && yvec[0] == lasty))
|
|
{
|
|
oglCheckLineIntersection(x1, y1, x2, y2, lastx, lasty, xvec[0], yvec[0],
|
|
&line_ratio, &other_ratio);
|
|
if (line_ratio != 1.0)
|
|
isAHit = TRUE;
|
|
// sprintf(buf, "Line ratio = %.2f, other ratio = %.2f\n", line_ratio, other_ratio);
|
|
// ClipsErrorFunction(buf);
|
|
|
|
if (line_ratio < min_ratio)
|
|
min_ratio = line_ratio;
|
|
}
|
|
// ClipsErrorFunction("\n");
|
|
return isAHit;
|
|
}
|
|
|
|
bool wxPolygonShape::HitTest(double x, double y, int *attachment, double *distance)
|
|
{
|
|
// Imagine four lines radiating from this point. If all of these lines hit the polygon,
|
|
// we're inside it, otherwise we're not. Obviously we'd need more radiating lines
|
|
// to be sure of correct results for very strange (concave) shapes.
|
|
double endPointsX[4];
|
|
double endPointsY[4];
|
|
// North
|
|
endPointsX[0] = x;
|
|
endPointsY[0] = (double)(y - 1000.0);
|
|
// East
|
|
endPointsX[1] = (double)(x + 1000.0);
|
|
endPointsY[1] = y;
|
|
// South
|
|
endPointsX[2] = x;
|
|
endPointsY[2] = (double)(y + 1000.0);
|
|
// West
|
|
endPointsX[3] = (double)(x - 1000.0);
|
|
endPointsY[3] = y;
|
|
|
|
// Store polygon points in an array
|
|
int np = m_points->Number();
|
|
double *xpoints = new double[np];
|
|
double *ypoints = new double[np];
|
|
wxNode *node = m_points->First();
|
|
int i = 0;
|
|
while (node)
|
|
{
|
|
wxRealPoint *point = (wxRealPoint *)node->Data();
|
|
xpoints[i] = point->x + m_xpos;
|
|
ypoints[i] = point->y + m_ypos;
|
|
node = node->Next();
|
|
i ++;
|
|
}
|
|
|
|
// We assume it's inside the polygon UNLESS one or more
|
|
// lines don't hit the outline.
|
|
bool isContained = TRUE;
|
|
|
|
int noPoints = 4;
|
|
for (i = 0; i < noPoints; i++)
|
|
{
|
|
if (!PolylineHitTest(np, xpoints, ypoints, x, y, endPointsX[i], endPointsY[i]))
|
|
isContained = FALSE;
|
|
}
|
|
/*
|
|
if (isContained)
|
|
ClipsErrorFunction("It's a hit!\n");
|
|
else
|
|
ClipsErrorFunction("No hit.\n");
|
|
*/
|
|
delete[] xpoints;
|
|
delete[] ypoints;
|
|
|
|
if (!isContained)
|
|
return FALSE;
|
|
|
|
int nearest_attachment = 0;
|
|
|
|
// If a hit, check the attachment points within the object.
|
|
int n = GetNumberOfAttachments();
|
|
double nearest = 999999.0;
|
|
|
|
for (i = 0; i < n; i++)
|
|
{
|
|
double xp, yp;
|
|
if (GetAttachmentPositionEdge(i, &xp, &yp))
|
|
{
|
|
double l = (double)sqrt(((xp - x) * (xp - x)) +
|
|
((yp - y) * (yp - y)));
|
|
if (l < nearest)
|
|
{
|
|
nearest = l;
|
|
nearest_attachment = i;
|
|
}
|
|
}
|
|
}
|
|
*attachment = nearest_attachment;
|
|
*distance = nearest;
|
|
return TRUE;
|
|
}
|
|
|
|
// Really need to be able to reset the shape! Otherwise, if the
|
|
// points ever go to zero, we've lost it, and can't resize.
|
|
void wxPolygonShape::SetSize(double new_width, double new_height, bool recursive)
|
|
{
|
|
SetAttachmentSize(new_width, new_height);
|
|
|
|
// Multiply all points by proportion of new size to old size
|
|
double x_proportion = (double)(fabs(new_width/m_originalWidth));
|
|
double y_proportion = (double)(fabs(new_height/m_originalHeight));
|
|
|
|
wxNode *node = m_points->First();
|
|
wxNode *original_node = m_originalPoints->First();
|
|
while (node && original_node)
|
|
{
|
|
wxRealPoint *point = (wxRealPoint *)node->Data();
|
|
wxRealPoint *original_point = (wxRealPoint *)original_node->Data();
|
|
|
|
point->x = (original_point->x * x_proportion);
|
|
point->y = (original_point->y * y_proportion);
|
|
|
|
node = node->Next();
|
|
original_node = original_node->Next();
|
|
}
|
|
|
|
// CalculateBoundingBox();
|
|
m_boundWidth = (double)fabs(new_width);
|
|
m_boundHeight = (double)fabs(new_height);
|
|
SetDefaultRegionSize();
|
|
}
|
|
|
|
// Make the original points the same as the working points
|
|
void wxPolygonShape::UpdateOriginalPoints()
|
|
{
|
|
if (!m_originalPoints) m_originalPoints = new wxList;
|
|
wxNode *original_node = m_originalPoints->First();
|
|
while (original_node)
|
|
{
|
|
wxNode *next_node = original_node->Next();
|
|
wxRealPoint *original_point = (wxRealPoint *)original_node->Data();
|
|
delete original_point;
|
|
delete original_node;
|
|
|
|
original_node = next_node;
|
|
}
|
|
|
|
wxNode *node = m_points->First();
|
|
while (node)
|
|
{
|
|
wxRealPoint *point = (wxRealPoint *)node->Data();
|
|
wxRealPoint *original_point = new wxRealPoint(point->x, point->y);
|
|
m_originalPoints->Append((wxObject*) original_point);
|
|
|
|
node = node->Next();
|
|
}
|
|
CalculateBoundingBox();
|
|
m_originalWidth = m_boundWidth;
|
|
m_originalHeight = m_boundHeight;
|
|
}
|
|
|
|
void wxPolygonShape::AddPolygonPoint(int pos)
|
|
{
|
|
wxNode *node = m_points->Nth(pos);
|
|
if (!node) node = m_points->First();
|
|
wxRealPoint *firstPoint = (wxRealPoint *)node->Data();
|
|
|
|
wxNode *node2 = m_points->Nth(pos + 1);
|
|
if (!node2) node2 = m_points->First();
|
|
wxRealPoint *secondPoint = (wxRealPoint *)node2->Data();
|
|
|
|
double x = (double)((secondPoint->x - firstPoint->x)/2.0 + firstPoint->x);
|
|
double y = (double)((secondPoint->y - firstPoint->y)/2.0 + firstPoint->y);
|
|
wxRealPoint *point = new wxRealPoint(x, y);
|
|
|
|
if (pos >= (m_points->Number() - 1))
|
|
m_points->Append((wxObject*) point);
|
|
else
|
|
m_points->Insert(node2, (wxObject*) point);
|
|
|
|
UpdateOriginalPoints();
|
|
|
|
if (m_selected)
|
|
{
|
|
DeleteControlPoints();
|
|
MakeControlPoints();
|
|
}
|
|
}
|
|
|
|
void wxPolygonShape::DeletePolygonPoint(int pos)
|
|
{
|
|
wxNode *node = m_points->Nth(pos);
|
|
if (node)
|
|
{
|
|
wxRealPoint *point = (wxRealPoint *)node->Data();
|
|
delete point;
|
|
delete node;
|
|
UpdateOriginalPoints();
|
|
if (m_selected)
|
|
{
|
|
DeleteControlPoints();
|
|
MakeControlPoints();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Assume (x1, y1) is centre of box (most generally, line end at box)
|
|
bool wxPolygonShape::GetPerimeterPoint(double x1, double y1,
|
|
double x2, double y2,
|
|
double *x3, double *y3)
|
|
{
|
|
int n = m_points->Number();
|
|
|
|
// First check for situation where the line is vertical,
|
|
// and we would want to connect to a point on that vertical --
|
|
// oglFindEndForPolyline can't cope with this (the arrow
|
|
// gets drawn to the wrong place).
|
|
if ((m_attachmentMode == ATTACHMENT_MODE_NONE) && (x1 == x2))
|
|
{
|
|
// Look for the point we'd be connecting to. This is
|
|
// a heuristic...
|
|
wxNode *node = m_points->First();
|
|
while (node)
|
|
{
|
|
wxRealPoint *point = (wxRealPoint *)node->Data();
|
|
if (point->x == 0.0)
|
|
{
|
|
if ((y2 > y1) && (point->y > 0.0))
|
|
{
|
|
*x3 = point->x + m_xpos;
|
|
*y3 = point->y + m_ypos;
|
|
return TRUE;
|
|
}
|
|
else if ((y2 < y1) && (point->y < 0.0))
|
|
{
|
|
*x3 = point->x + m_xpos;
|
|
*y3 = point->y + m_ypos;
|
|
return TRUE;
|
|
}
|
|
}
|
|
node = node->Next();
|
|
}
|
|
}
|
|
|
|
double *xpoints = new double[n];
|
|
double *ypoints = new double[n];
|
|
|
|
wxNode *node = m_points->First();
|
|
int i = 0;
|
|
while (node)
|
|
{
|
|
wxRealPoint *point = (wxRealPoint *)node->Data();
|
|
xpoints[i] = point->x + m_xpos;
|
|
ypoints[i] = point->y + m_ypos;
|
|
node = node->Next();
|
|
i ++;
|
|
}
|
|
|
|
oglFindEndForPolyline(n, xpoints, ypoints,
|
|
x1, y1, x2, y2, x3, y3);
|
|
|
|
delete[] xpoints;
|
|
delete[] ypoints;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void wxPolygonShape::OnDraw(wxDC& dc)
|
|
{
|
|
int n = m_points->Number();
|
|
wxPoint *intPoints = new wxPoint[n];
|
|
int i;
|
|
for (i = 0; i < n; i++)
|
|
{
|
|
wxRealPoint* point = (wxRealPoint*) m_points->Nth(i)->Data();
|
|
intPoints[i].x = WXROUND(point->x);
|
|
intPoints[i].y = WXROUND(point->y);
|
|
}
|
|
|
|
if (m_shadowMode != SHADOW_NONE)
|
|
{
|
|
if (m_shadowBrush)
|
|
dc.SetBrush(* m_shadowBrush);
|
|
dc.SetPen(* g_oglTransparentPen);
|
|
|
|
dc.DrawPolygon(n, intPoints, WXROUND(m_xpos + m_shadowOffsetX), WXROUND(m_ypos + m_shadowOffsetY));
|
|
}
|
|
|
|
if (m_pen)
|
|
{
|
|
if (m_pen->GetWidth() == 0)
|
|
dc.SetPen(* g_oglTransparentPen);
|
|
else
|
|
dc.SetPen(* m_pen);
|
|
}
|
|
if (m_brush)
|
|
dc.SetBrush(* m_brush);
|
|
dc.DrawPolygon(n, intPoints, WXROUND(m_xpos), WXROUND(m_ypos));
|
|
|
|
delete[] intPoints;
|
|
}
|
|
|
|
void wxPolygonShape::OnDrawOutline(wxDC& dc, double x, double y, double w, double h)
|
|
{
|
|
dc.SetBrush(* wxTRANSPARENT_BRUSH);
|
|
// Multiply all points by proportion of new size to old size
|
|
double x_proportion = (double)(fabs(w/m_originalWidth));
|
|
double y_proportion = (double)(fabs(h/m_originalHeight));
|
|
|
|
int n = m_originalPoints->Number();
|
|
wxPoint *intPoints = new wxPoint[n];
|
|
int i;
|
|
for (i = 0; i < n; i++)
|
|
{
|
|
wxRealPoint* point = (wxRealPoint*) m_originalPoints->Nth(i)->Data();
|
|
intPoints[i].x = WXROUND(x_proportion * point->x);
|
|
intPoints[i].y = WXROUND(y_proportion * point->y);
|
|
}
|
|
dc.DrawPolygon(n, intPoints, WXROUND(x), WXROUND(y));
|
|
delete[] intPoints;
|
|
}
|
|
|
|
// Make as many control points as there are vertices.
|
|
void wxPolygonShape::MakeControlPoints()
|
|
{
|
|
wxNode *node = m_points->First();
|
|
while (node)
|
|
{
|
|
wxRealPoint *point = (wxRealPoint *)node->Data();
|
|
wxPolygonControlPoint *control = new wxPolygonControlPoint(m_canvas, this, CONTROL_POINT_SIZE,
|
|
point, point->x, point->y);
|
|
m_canvas->AddShape(control);
|
|
m_controlPoints.Append(control);
|
|
node = node->Next();
|
|
}
|
|
}
|
|
|
|
void wxPolygonShape::ResetControlPoints()
|
|
{
|
|
wxNode *node = m_points->First();
|
|
wxNode *controlPointNode = m_controlPoints.First();
|
|
while (node && controlPointNode)
|
|
{
|
|
wxRealPoint *point = (wxRealPoint *)node->Data();
|
|
wxPolygonControlPoint *controlPoint = (wxPolygonControlPoint *)controlPointNode->Data();
|
|
|
|
controlPoint->m_xoffset = point->x;
|
|
controlPoint->m_yoffset = point->y;
|
|
controlPoint->m_polygonVertex = point;
|
|
|
|
node = node->Next();
|
|
controlPointNode = controlPointNode->Next();
|
|
}
|
|
}
|
|
|
|
|
|
#if wxUSE_PROLOGIO
|
|
void wxPolygonShape::WriteAttributes(wxExpr *clause)
|
|
{
|
|
wxShape::WriteAttributes(clause);
|
|
|
|
clause->AddAttributeValue(wxT("x"), m_xpos);
|
|
clause->AddAttributeValue(wxT("y"), m_ypos);
|
|
|
|
// Make a list of lists for the coordinates
|
|
wxExpr *list = new wxExpr(wxExprList);
|
|
wxNode *node = m_points->First();
|
|
while (node)
|
|
{
|
|
wxRealPoint *point = (wxRealPoint *)node->Data();
|
|
wxExpr *point_list = new wxExpr(wxExprList);
|
|
wxExpr *x_expr = new wxExpr((double)point->x);
|
|
wxExpr *y_expr = new wxExpr((double)point->y);
|
|
|
|
point_list->Append(x_expr);
|
|
point_list->Append(y_expr);
|
|
list->Append(point_list);
|
|
|
|
node = node->Next();
|
|
}
|
|
clause->AddAttributeValue(wxT("points"), list);
|
|
|
|
// Save the original (unscaled) points
|
|
list = new wxExpr(wxExprList);
|
|
node = m_originalPoints->First();
|
|
while (node)
|
|
{
|
|
wxRealPoint *point = (wxRealPoint *)node->Data();
|
|
wxExpr *point_list = new wxExpr(wxExprList);
|
|
wxExpr *x_expr = new wxExpr((double) point->x);
|
|
wxExpr *y_expr = new wxExpr((double) point->y);
|
|
point_list->Append(x_expr);
|
|
point_list->Append(y_expr);
|
|
list->Append(point_list);
|
|
|
|
node = node->Next();
|
|
}
|
|
clause->AddAttributeValue(wxT("m_originalPoints"), list);
|
|
}
|
|
|
|
void wxPolygonShape::ReadAttributes(wxExpr *clause)
|
|
{
|
|
wxShape::ReadAttributes(clause);
|
|
|
|
// Read a list of lists
|
|
m_points = new wxList;
|
|
m_originalPoints = new wxList;
|
|
|
|
wxExpr *points_list = NULL;
|
|
clause->AssignAttributeValue(wxT("points"), &points_list);
|
|
|
|
// If no points_list, don't crash!! Assume a diamond instead.
|
|
double the_height = 100.0;
|
|
double the_width = 100.0;
|
|
if (!points_list)
|
|
{
|
|
wxRealPoint *point = new wxRealPoint(0.0, (-the_height/2));
|
|
m_points->Append((wxObject*) point);
|
|
|
|
point = new wxRealPoint((the_width/2), 0.0);
|
|
m_points->Append((wxObject*) point);
|
|
|
|
point = new wxRealPoint(0.0, (the_height/2));
|
|
m_points->Append((wxObject*) point);
|
|
|
|
point = new wxRealPoint((-the_width/2), 0.0);
|
|
m_points->Append((wxObject*) point);
|
|
|
|
point = new wxRealPoint(0.0, (-the_height/2));
|
|
m_points->Append((wxObject*) point);
|
|
}
|
|
else
|
|
{
|
|
wxExpr *node = points_list->value.first;
|
|
|
|
while (node)
|
|
{
|
|
wxExpr *xexpr = node->value.first;
|
|
long x = xexpr->IntegerValue();
|
|
|
|
wxExpr *yexpr = xexpr->next;
|
|
long y = yexpr->IntegerValue();
|
|
|
|
wxRealPoint *point = new wxRealPoint((double)x, (double)y);
|
|
m_points->Append((wxObject*) point);
|
|
|
|
node = node->next;
|
|
}
|
|
}
|
|
|
|
points_list = NULL;
|
|
clause->AssignAttributeValue(wxT("m_originalPoints"), &points_list);
|
|
|
|
// If no points_list, don't crash!! Assume a diamond instead.
|
|
if (!points_list)
|
|
{
|
|
wxRealPoint *point = new wxRealPoint(0.0, (-the_height/2));
|
|
m_originalPoints->Append((wxObject*) point);
|
|
|
|
point = new wxRealPoint((the_width/2), 0.0);
|
|
m_originalPoints->Append((wxObject*) point);
|
|
|
|
point = new wxRealPoint(0.0, (the_height/2));
|
|
m_originalPoints->Append((wxObject*) point);
|
|
|
|
point = new wxRealPoint((-the_width/2), 0.0);
|
|
m_originalPoints->Append((wxObject*) point);
|
|
|
|
point = new wxRealPoint(0.0, (-the_height/2));
|
|
m_originalPoints->Append((wxObject*) point);
|
|
|
|
m_originalWidth = the_width;
|
|
m_originalHeight = the_height;
|
|
}
|
|
else
|
|
{
|
|
wxExpr *node = points_list->value.first;
|
|
double min_x = 1000;
|
|
double min_y = 1000;
|
|
double max_x = -1000;
|
|
double max_y = -1000;
|
|
while (node)
|
|
{
|
|
wxExpr *xexpr = node->value.first;
|
|
long x = xexpr->IntegerValue();
|
|
|
|
wxExpr *yexpr = xexpr->next;
|
|
long y = yexpr->IntegerValue();
|
|
|
|
wxRealPoint *point = new wxRealPoint((double)x, (double)y);
|
|
m_originalPoints->Append((wxObject*) point);
|
|
|
|
if (x < min_x)
|
|
min_x = (double)x;
|
|
if (y < min_y)
|
|
min_y = (double)y;
|
|
if (x > max_x)
|
|
max_x = (double)x;
|
|
if (y > max_y)
|
|
max_y = (double)y;
|
|
|
|
node = node->next;
|
|
}
|
|
m_originalWidth = max_x - min_x;
|
|
m_originalHeight = max_y - min_y;
|
|
}
|
|
|
|
CalculateBoundingBox();
|
|
}
|
|
#endif
|
|
|
|
void wxPolygonShape::Copy(wxShape& copy)
|
|
{
|
|
wxShape::Copy(copy);
|
|
|
|
wxASSERT( copy.IsKindOf(CLASSINFO(wxPolygonShape)) );
|
|
|
|
wxPolygonShape& polyCopy = (wxPolygonShape&) copy;
|
|
|
|
polyCopy.ClearPoints();
|
|
|
|
polyCopy.m_points = new wxList;
|
|
polyCopy.m_originalPoints = new wxList;
|
|
|
|
wxNode *node = m_points->First();
|
|
while (node)
|
|
{
|
|
wxRealPoint *point = (wxRealPoint *)node->Data();
|
|
wxRealPoint *new_point = new wxRealPoint(point->x, point->y);
|
|
polyCopy.m_points->Append((wxObject*) new_point);
|
|
node = node->Next();
|
|
}
|
|
node = m_originalPoints->First();
|
|
while (node)
|
|
{
|
|
wxRealPoint *point = (wxRealPoint *)node->Data();
|
|
wxRealPoint *new_point = new wxRealPoint(point->x, point->y);
|
|
polyCopy.m_originalPoints->Append((wxObject*) new_point);
|
|
node = node->Next();
|
|
}
|
|
polyCopy.m_boundWidth = m_boundWidth;
|
|
polyCopy.m_boundHeight = m_boundHeight;
|
|
polyCopy.m_originalWidth = m_originalWidth;
|
|
polyCopy.m_originalHeight = m_originalHeight;
|
|
}
|
|
|
|
int wxPolygonShape::GetNumberOfAttachments() const
|
|
{
|
|
int maxN = (m_points ? (m_points->Number() - 1) : 0);
|
|
wxNode *node = m_attachmentPoints.First();
|
|
while (node)
|
|
{
|
|
wxAttachmentPoint *point = (wxAttachmentPoint *)node->Data();
|
|
if (point->m_id > maxN)
|
|
maxN = point->m_id;
|
|
node = node->Next();
|
|
}
|
|
return maxN+1;;
|
|
}
|
|
|
|
bool wxPolygonShape::GetAttachmentPosition(int attachment, double *x, double *y,
|
|
int nth, int no_arcs, wxLineShape *line)
|
|
{
|
|
if ((m_attachmentMode == ATTACHMENT_MODE_EDGE) && m_points && attachment < m_points->Number())
|
|
{
|
|
wxRealPoint *point = (wxRealPoint *)m_points->Nth(attachment)->Data();
|
|
*x = point->x + m_xpos;
|
|
*y = point->y + m_ypos;
|
|
return TRUE;
|
|
}
|
|
else
|
|
{ return wxShape::GetAttachmentPosition(attachment, x, y, nth, no_arcs, line); }
|
|
}
|
|
|
|
bool wxPolygonShape::AttachmentIsValid(int attachment)
|
|
{
|
|
if (!m_points)
|
|
return FALSE;
|
|
|
|
if ((attachment >= 0) && (attachment < m_points->Number()))
|
|
return TRUE;
|
|
|
|
wxNode *node = m_attachmentPoints.First();
|
|
while (node)
|
|
{
|
|
wxAttachmentPoint *point = (wxAttachmentPoint *)node->Data();
|
|
if (point->m_id == attachment)
|
|
return TRUE;
|
|
node = node->Next();
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
// Rotate about the given axis by the given amount in radians
|
|
void wxPolygonShape::Rotate(double x, double y, double theta)
|
|
{
|
|
double actualTheta = theta-m_rotation;
|
|
|
|
// Rotate attachment points
|
|
double sinTheta = (double)sin(actualTheta);
|
|
double cosTheta = (double)cos(actualTheta);
|
|
wxNode *node = m_attachmentPoints.First();
|
|
while (node)
|
|
{
|
|
wxAttachmentPoint *point = (wxAttachmentPoint *)node->Data();
|
|
double x1 = point->m_x;
|
|
double y1 = point->m_y;
|
|
point->m_x = x1*cosTheta - y1*sinTheta + x*(1.0 - cosTheta) + y*sinTheta;
|
|
point->m_y = x1*sinTheta + y1*cosTheta + y*(1.0 - cosTheta) + x*sinTheta;
|
|
node = node->Next();
|
|
}
|
|
|
|
node = m_points->First();
|
|
while (node)
|
|
{
|
|
wxRealPoint *point = (wxRealPoint *)node->Data();
|
|
double x1 = point->x;
|
|
double y1 = point->y;
|
|
point->x = x1*cosTheta - y1*sinTheta + x*(1.0 - cosTheta) + y*sinTheta;
|
|
point->y = x1*sinTheta + y1*cosTheta + y*(1.0 - cosTheta) + x*sinTheta;
|
|
node = node->Next();
|
|
}
|
|
node = m_originalPoints->First();
|
|
while (node)
|
|
{
|
|
wxRealPoint *point = (wxRealPoint *)node->Data();
|
|
double x1 = point->x;
|
|
double y1 = point->y;
|
|
point->x = x1*cosTheta - y1*sinTheta + x*(1.0 - cosTheta) + y*sinTheta;
|
|
point->y = x1*sinTheta + y1*cosTheta + y*(1.0 - cosTheta) + x*sinTheta;
|
|
node = node->Next();
|
|
}
|
|
|
|
m_rotation = theta;
|
|
|
|
CalculatePolygonCentre();
|
|
CalculateBoundingBox();
|
|
ResetControlPoints();
|
|
}
|
|
|
|
// Rectangle object
|
|
|
|
IMPLEMENT_DYNAMIC_CLASS(wxRectangleShape, wxShape)
|
|
|
|
wxRectangleShape::wxRectangleShape(double w, double h)
|
|
{
|
|
m_width = w; m_height = h; m_cornerRadius = 0.0;
|
|
SetDefaultRegionSize();
|
|
}
|
|
|
|
void wxRectangleShape::OnDraw(wxDC& dc)
|
|
{
|
|
double x1 = (double)(m_xpos - m_width/2.0);
|
|
double y1 = (double)(m_ypos - m_height/2.0);
|
|
|
|
if (m_shadowMode != SHADOW_NONE)
|
|
{
|
|
if (m_shadowBrush)
|
|
dc.SetBrush(* m_shadowBrush);
|
|
dc.SetPen(* g_oglTransparentPen);
|
|
|
|
if (m_cornerRadius != 0.0)
|
|
dc.DrawRoundedRectangle(WXROUND(x1 + m_shadowOffsetX), WXROUND(y1 + m_shadowOffsetY),
|
|
WXROUND(m_width), WXROUND(m_height), m_cornerRadius);
|
|
else
|
|
dc.DrawRectangle(WXROUND(x1 + m_shadowOffsetX), WXROUND(y1 + m_shadowOffsetY), WXROUND(m_width), WXROUND(m_height));
|
|
}
|
|
|
|
if (m_pen)
|
|
{
|
|
if (m_pen->GetWidth() == 0)
|
|
dc.SetPen(* g_oglTransparentPen);
|
|
else
|
|
dc.SetPen(* m_pen);
|
|
}
|
|
if (m_brush)
|
|
dc.SetBrush(* m_brush);
|
|
|
|
if (m_cornerRadius != 0.0)
|
|
dc.DrawRoundedRectangle(WXROUND(x1), WXROUND(y1), WXROUND(m_width), WXROUND(m_height), m_cornerRadius);
|
|
else
|
|
dc.DrawRectangle(WXROUND(x1), WXROUND(y1), WXROUND(m_width), WXROUND(m_height));
|
|
}
|
|
|
|
void wxRectangleShape::GetBoundingBoxMin(double *the_width, double *the_height)
|
|
{
|
|
*the_width = m_width;
|
|
*the_height = m_height;
|
|
}
|
|
|
|
void wxRectangleShape::SetSize(double x, double y, bool recursive)
|
|
{
|
|
SetAttachmentSize(x, y);
|
|
m_width = (double)wxMax(x, 1.0);
|
|
m_height = (double)wxMax(y, 1.0);
|
|
SetDefaultRegionSize();
|
|
}
|
|
|
|
void wxRectangleShape::SetCornerRadius(double rad)
|
|
{
|
|
m_cornerRadius = rad;
|
|
}
|
|
|
|
// Assume (x1, y1) is centre of box (most generally, line end at box)
|
|
bool wxRectangleShape::GetPerimeterPoint(double x1, double y1,
|
|
double x2, double y2,
|
|
double *x3, double *y3)
|
|
{
|
|
double bound_x, bound_y;
|
|
GetBoundingBoxMax(&bound_x, &bound_y);
|
|
oglFindEndForBox(bound_x, bound_y, m_xpos, m_ypos, x2, y2, x3, y3);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#if wxUSE_PROLOGIO
|
|
void wxRectangleShape::WriteAttributes(wxExpr *clause)
|
|
{
|
|
wxShape::WriteAttributes(clause);
|
|
clause->AddAttributeValue(wxT("x"), m_xpos);
|
|
clause->AddAttributeValue(wxT("y"), m_ypos);
|
|
|
|
clause->AddAttributeValue(wxT("width"), m_width);
|
|
clause->AddAttributeValue(wxT("height"), m_height);
|
|
if (m_cornerRadius != 0.0)
|
|
clause->AddAttributeValue(wxT("corner"), m_cornerRadius);
|
|
}
|
|
|
|
void wxRectangleShape::ReadAttributes(wxExpr *clause)
|
|
{
|
|
wxShape::ReadAttributes(clause);
|
|
clause->AssignAttributeValue(wxT("width"), &m_width);
|
|
clause->AssignAttributeValue(wxT("height"), &m_height);
|
|
clause->AssignAttributeValue(wxT("corner"), &m_cornerRadius);
|
|
|
|
// In case we're reading an old file, set the region's size
|
|
if (m_regions.Number() == 1)
|
|
{
|
|
wxShapeRegion *region = (wxShapeRegion *)m_regions.First()->Data();
|
|
region->SetSize(m_width, m_height);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void wxRectangleShape::Copy(wxShape& copy)
|
|
{
|
|
wxShape::Copy(copy);
|
|
|
|
wxASSERT( copy.IsKindOf(CLASSINFO(wxRectangleShape)) );
|
|
|
|
wxRectangleShape& rectCopy = (wxRectangleShape&) copy;
|
|
rectCopy.m_width = m_width;
|
|
rectCopy.m_height = m_height;
|
|
rectCopy.m_cornerRadius = m_cornerRadius;
|
|
}
|
|
|
|
int wxRectangleShape::GetNumberOfAttachments() const
|
|
{
|
|
return wxShape::GetNumberOfAttachments();
|
|
}
|
|
|
|
|
|
// There are 4 attachment points on a rectangle - 0 = top, 1 = right, 2 = bottom,
|
|
// 3 = left.
|
|
bool wxRectangleShape::GetAttachmentPosition(int attachment, double *x, double *y,
|
|
int nth, int no_arcs, wxLineShape *line)
|
|
{
|
|
return wxShape::GetAttachmentPosition(attachment, x, y, nth, no_arcs, line);
|
|
}
|
|
|
|
// Text object (no box)
|
|
|
|
IMPLEMENT_DYNAMIC_CLASS(wxTextShape, wxRectangleShape)
|
|
|
|
wxTextShape::wxTextShape(double width, double height):
|
|
wxRectangleShape(width, height)
|
|
{
|
|
}
|
|
|
|
void wxTextShape::OnDraw(wxDC& dc)
|
|
{
|
|
}
|
|
|
|
void wxTextShape::Copy(wxShape& copy)
|
|
{
|
|
wxRectangleShape::Copy(copy);
|
|
}
|
|
|
|
#if wxUSE_PROLOGIO
|
|
void wxTextShape::WriteAttributes(wxExpr *clause)
|
|
{
|
|
wxRectangleShape::WriteAttributes(clause);
|
|
}
|
|
#endif
|
|
|
|
// Ellipse object
|
|
|
|
IMPLEMENT_DYNAMIC_CLASS(wxEllipseShape, wxShape)
|
|
|
|
wxEllipseShape::wxEllipseShape(double w, double h)
|
|
{
|
|
m_width = w; m_height = h;
|
|
SetDefaultRegionSize();
|
|
}
|
|
|
|
void wxEllipseShape::GetBoundingBoxMin(double *w, double *h)
|
|
{
|
|
*w = m_width; *h = m_height;
|
|
}
|
|
|
|
bool wxEllipseShape::GetPerimeterPoint(double x1, double y1,
|
|
double x2, double y2,
|
|
double *x3, double *y3)
|
|
{
|
|
double bound_x, bound_y;
|
|
GetBoundingBoxMax(&bound_x, &bound_y);
|
|
|
|
// oglFindEndForBox(bound_x, bound_y, m_xpos, m_ypos, x2, y2, x3, y3);
|
|
oglDrawArcToEllipse(m_xpos, m_ypos, bound_x, bound_y, x2, y2, x1, y1, x3, y3);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void wxEllipseShape::OnDraw(wxDC& dc)
|
|
{
|
|
if (m_shadowMode != SHADOW_NONE)
|
|
{
|
|
if (m_shadowBrush)
|
|
dc.SetBrush(* m_shadowBrush);
|
|
dc.SetPen(* g_oglTransparentPen);
|
|
dc.DrawEllipse((long) ((m_xpos - GetWidth()/2) + m_shadowOffsetX),
|
|
(long) ((m_ypos - GetHeight()/2) + m_shadowOffsetY),
|
|
(long) GetWidth(), (long) GetHeight());
|
|
}
|
|
|
|
if (m_pen)
|
|
{
|
|
if (m_pen->GetWidth() == 0)
|
|
dc.SetPen(* g_oglTransparentPen);
|
|
else
|
|
dc.SetPen(* m_pen);
|
|
}
|
|
if (m_brush)
|
|
dc.SetBrush(* m_brush);
|
|
dc.DrawEllipse((long) (m_xpos - GetWidth()/2), (long) (m_ypos - GetHeight()/2), (long) GetWidth(), (long) GetHeight());
|
|
}
|
|
|
|
void wxEllipseShape::SetSize(double x, double y, bool recursive)
|
|
{
|
|
SetAttachmentSize(x, y);
|
|
m_width = x;
|
|
m_height = y;
|
|
SetDefaultRegionSize();
|
|
}
|
|
|
|
#if wxUSE_PROLOGIO
|
|
void wxEllipseShape::WriteAttributes(wxExpr *clause)
|
|
{
|
|
wxShape::WriteAttributes(clause);
|
|
clause->AddAttributeValue(wxT("x"), m_xpos);
|
|
clause->AddAttributeValue(wxT("y"), m_ypos);
|
|
|
|
clause->AddAttributeValue(wxT("width"), m_width);
|
|
clause->AddAttributeValue(wxT("height"), m_height);
|
|
}
|
|
|
|
void wxEllipseShape::ReadAttributes(wxExpr *clause)
|
|
{
|
|
wxShape::ReadAttributes(clause);
|
|
clause->AssignAttributeValue(wxT("width"), &m_width);
|
|
clause->AssignAttributeValue(wxT("height"), &m_height);
|
|
|
|
// In case we're reading an old file, set the region's size
|
|
if (m_regions.Number() == 1)
|
|
{
|
|
wxShapeRegion *region = (wxShapeRegion *)m_regions.First()->Data();
|
|
region->SetSize(m_width, m_height);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void wxEllipseShape::Copy(wxShape& copy)
|
|
{
|
|
wxShape::Copy(copy);
|
|
|
|
wxASSERT( copy.IsKindOf(CLASSINFO(wxEllipseShape)) );
|
|
|
|
wxEllipseShape& ellipseCopy = (wxEllipseShape&) copy;
|
|
|
|
ellipseCopy.m_width = m_width;
|
|
ellipseCopy.m_height = m_height;
|
|
}
|
|
|
|
int wxEllipseShape::GetNumberOfAttachments() const
|
|
{
|
|
return wxShape::GetNumberOfAttachments();
|
|
}
|
|
|
|
// There are 4 attachment points on an ellipse - 0 = top, 1 = right, 2 = bottom,
|
|
// 3 = left.
|
|
bool wxEllipseShape::GetAttachmentPosition(int attachment, double *x, double *y,
|
|
int nth, int no_arcs, wxLineShape *line)
|
|
{
|
|
if (m_attachmentMode == ATTACHMENT_MODE_BRANCHING)
|
|
return wxShape::GetAttachmentPosition(attachment, x, y, nth, no_arcs, line);
|
|
|
|
if (m_attachmentMode != ATTACHMENT_MODE_NONE)
|
|
{
|
|
double top = (double)(m_ypos + m_height/2.0);
|
|
double bottom = (double)(m_ypos - m_height/2.0);
|
|
double left = (double)(m_xpos - m_width/2.0);
|
|
double right = (double)(m_xpos + m_width/2.0);
|
|
|
|
int physicalAttachment = LogicalToPhysicalAttachment(attachment);
|
|
|
|
switch (physicalAttachment)
|
|
{
|
|
case 0:
|
|
{
|
|
if (m_spaceAttachments)
|
|
*x = left + (nth + 1)*m_width/(no_arcs + 1);
|
|
else *x = m_xpos;
|
|
*y = top;
|
|
// We now have the point on the bounding box: but get the point on the ellipse
|
|
// by imagining a vertical line from (*x, m_ypos - m_height- 500) to (*x, m_ypos) intersecting
|
|
// the ellipse.
|
|
oglDrawArcToEllipse(m_xpos, m_ypos, m_width, m_height, *x, (double)(m_ypos-m_height-500), *x, m_ypos, x, y);
|
|
break;
|
|
}
|
|
case 1:
|
|
{
|
|
*x = right;
|
|
if (m_spaceAttachments)
|
|
*y = bottom + (nth + 1)*m_height/(no_arcs + 1);
|
|
else *y = m_ypos;
|
|
oglDrawArcToEllipse(m_xpos, m_ypos, m_width, m_height, (double)(m_xpos+m_width+500), *y, m_xpos, *y, x, y);
|
|
break;
|
|
}
|
|
case 2:
|
|
{
|
|
if (m_spaceAttachments)
|
|
*x = left + (nth + 1)*m_width/(no_arcs + 1);
|
|
else *x = m_xpos;
|
|
*y = bottom;
|
|
oglDrawArcToEllipse(m_xpos, m_ypos, m_width, m_height, *x, (double)(m_ypos+m_height+500), *x, m_ypos, x, y);
|
|
break;
|
|
}
|
|
case 3:
|
|
{
|
|
*x = left;
|
|
if (m_spaceAttachments)
|
|
*y = bottom + (nth + 1)*m_height/(no_arcs + 1);
|
|
else *y = m_ypos;
|
|
oglDrawArcToEllipse(m_xpos, m_ypos, m_width, m_height, (double)(m_xpos-m_width-500), *y, m_xpos, *y, x, y);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
return wxShape::GetAttachmentPosition(attachment, x, y, nth, no_arcs, line);
|
|
break;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
else
|
|
{ *x = m_xpos; *y = m_ypos; return TRUE; }
|
|
}
|
|
|
|
|
|
// Circle object
|
|
IMPLEMENT_DYNAMIC_CLASS(wxCircleShape, wxEllipseShape)
|
|
|
|
wxCircleShape::wxCircleShape(double diameter):wxEllipseShape(diameter, diameter)
|
|
{
|
|
SetMaintainAspectRatio(TRUE);
|
|
}
|
|
|
|
void wxCircleShape::Copy(wxShape& copy)
|
|
{
|
|
wxEllipseShape::Copy(copy);
|
|
}
|
|
|
|
bool wxCircleShape::GetPerimeterPoint(double x1, double y1,
|
|
double x2, double y2,
|
|
double *x3, double *y3)
|
|
{
|
|
oglFindEndForCircle(m_width/2,
|
|
m_xpos, m_ypos, // Centre of circle
|
|
x2, y2, // Other end of line
|
|
x3, y3);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// Control points
|
|
|
|
double wxControlPoint::sm_controlPointDragStartX = 0.0;
|
|
double wxControlPoint::sm_controlPointDragStartY = 0.0;
|
|
double wxControlPoint::sm_controlPointDragStartWidth = 0.0;
|
|
double wxControlPoint::sm_controlPointDragStartHeight = 0.0;
|
|
double wxControlPoint::sm_controlPointDragEndWidth = 0.0;
|
|
double wxControlPoint::sm_controlPointDragEndHeight = 0.0;
|
|
double wxControlPoint::sm_controlPointDragPosX = 0.0;
|
|
double wxControlPoint::sm_controlPointDragPosY = 0.0;
|
|
|
|
IMPLEMENT_DYNAMIC_CLASS(wxControlPoint, wxRectangleShape)
|
|
|
|
wxControlPoint::wxControlPoint(wxShapeCanvas *theCanvas, wxShape *object, double size, double the_xoffset, double the_yoffset, int the_type):wxRectangleShape(size, size)
|
|
{
|
|
m_canvas = theCanvas;
|
|
m_shape = object;
|
|
m_xoffset = the_xoffset;
|
|
m_yoffset = the_yoffset;
|
|
m_type = the_type;
|
|
SetPen(g_oglBlackForegroundPen);
|
|
SetBrush(wxBLACK_BRUSH);
|
|
m_oldCursor = NULL;
|
|
m_visible = TRUE;
|
|
m_eraseObject = TRUE;
|
|
}
|
|
|
|
wxControlPoint::~wxControlPoint()
|
|
{
|
|
}
|
|
|
|
// Don't even attempt to draw any text - waste of time!
|
|
void wxControlPoint::OnDrawContents(wxDC& dc)
|
|
{
|
|
}
|
|
|
|
void wxControlPoint::OnDraw(wxDC& dc)
|
|
{
|
|
m_xpos = m_shape->GetX() + m_xoffset;
|
|
m_ypos = m_shape->GetY() + m_yoffset;
|
|
wxRectangleShape::OnDraw(dc);
|
|
}
|
|
|
|
void wxControlPoint::OnErase(wxDC& dc)
|
|
{
|
|
wxRectangleShape::OnErase(dc);
|
|
}
|
|
|
|
// Implement resizing of canvas object
|
|
void wxControlPoint::OnDragLeft(bool draw, double x, double y, int keys, int attachment)
|
|
{
|
|
m_shape->GetEventHandler()->OnSizingDragLeft(this, draw, x, y, keys, attachment);
|
|
}
|
|
|
|
void wxControlPoint::OnBeginDragLeft(double x, double y, int keys, int attachment)
|
|
{
|
|
m_shape->GetEventHandler()->OnSizingBeginDragLeft(this, x, y, keys, attachment);
|
|
}
|
|
|
|
void wxControlPoint::OnEndDragLeft(double x, double y, int keys, int attachment)
|
|
{
|
|
m_shape->GetEventHandler()->OnSizingEndDragLeft(this, x, y, keys, attachment);
|
|
}
|
|
|
|
int wxControlPoint::GetNumberOfAttachments() const
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
bool wxControlPoint::GetAttachmentPosition(int attachment, double *x, double *y,
|
|
int nth, int no_arcs, wxLineShape *line)
|
|
{
|
|
*x = m_xpos; *y = m_ypos;
|
|
return TRUE;
|
|
}
|
|
|
|
// Control points ('handles') redirect control to the actual shape, to make it easier
|
|
// to override sizing behaviour.
|
|
void wxShape::OnSizingDragLeft(wxControlPoint* pt, bool draw, double x, double y, int keys, int attachment)
|
|
{
|
|
double bound_x;
|
|
double bound_y;
|
|
this->GetBoundingBoxMin(&bound_x, &bound_y);
|
|
|
|
wxClientDC dc(GetCanvas());
|
|
GetCanvas()->PrepareDC(dc);
|
|
|
|
dc.SetLogicalFunction(OGLRBLF);
|
|
|
|
wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
|
|
dc.SetPen(dottedPen);
|
|
dc.SetBrush((* wxTRANSPARENT_BRUSH));
|
|
|
|
if (this->GetCentreResize())
|
|
{
|
|
// Maintain the same centre point.
|
|
double new_width = (double)(2.0*fabs(x - this->GetX()));
|
|
double new_height = (double)(2.0*fabs(y - this->GetY()));
|
|
|
|
// Constrain sizing according to what control point you're dragging
|
|
if (pt->m_type == CONTROL_POINT_HORIZONTAL)
|
|
{
|
|
if (GetMaintainAspectRatio())
|
|
{
|
|
new_height = bound_y*(new_width/bound_x);
|
|
}
|
|
else
|
|
new_height = bound_y;
|
|
}
|
|
else if (pt->m_type == CONTROL_POINT_VERTICAL)
|
|
{
|
|
if (GetMaintainAspectRatio())
|
|
{
|
|
new_width = bound_x*(new_height/bound_y);
|
|
}
|
|
else
|
|
new_width = bound_x;
|
|
}
|
|
else if (pt->m_type == CONTROL_POINT_DIAGONAL && (keys & KEY_SHIFT))
|
|
new_height = bound_y*(new_width/bound_x);
|
|
|
|
if (this->GetFixedWidth())
|
|
new_width = bound_x;
|
|
|
|
if (this->GetFixedHeight())
|
|
new_height = bound_y;
|
|
|
|
pt->sm_controlPointDragEndWidth = new_width;
|
|
pt->sm_controlPointDragEndHeight = new_height;
|
|
|
|
this->GetEventHandler()->OnDrawOutline(dc, this->GetX(), this->GetY(),
|
|
new_width, new_height);
|
|
}
|
|
else
|
|
{
|
|
// Don't maintain the same centre point!
|
|
double newX1 = wxMin(pt->sm_controlPointDragStartX, x);
|
|
double newY1 = wxMin(pt->sm_controlPointDragStartY, y);
|
|
double newX2 = wxMax(pt->sm_controlPointDragStartX, x);
|
|
double newY2 = wxMax(pt->sm_controlPointDragStartY, y);
|
|
if (pt->m_type == CONTROL_POINT_HORIZONTAL)
|
|
{
|
|
newY1 = pt->sm_controlPointDragStartY;
|
|
newY2 = newY1 + pt->sm_controlPointDragStartHeight;
|
|
}
|
|
else if (pt->m_type == CONTROL_POINT_VERTICAL)
|
|
{
|
|
newX1 = pt->sm_controlPointDragStartX;
|
|
newX2 = newX1 + pt->sm_controlPointDragStartWidth;
|
|
}
|
|
else if (pt->m_type == CONTROL_POINT_DIAGONAL && ((keys & KEY_SHIFT) || GetMaintainAspectRatio()))
|
|
{
|
|
double newH = (double)((newX2 - newX1)*(pt->sm_controlPointDragStartHeight/pt->sm_controlPointDragStartWidth));
|
|
if (GetY() > pt->sm_controlPointDragStartY)
|
|
newY2 = (double)(newY1 + newH);
|
|
else
|
|
newY1 = (double)(newY2 - newH);
|
|
}
|
|
double newWidth = (double)(newX2 - newX1);
|
|
double newHeight = (double)(newY2 - newY1);
|
|
|
|
if (pt->m_type == CONTROL_POINT_VERTICAL && GetMaintainAspectRatio())
|
|
{
|
|
newWidth = bound_x * (newHeight/bound_y) ;
|
|
}
|
|
|
|
if (pt->m_type == CONTROL_POINT_HORIZONTAL && GetMaintainAspectRatio())
|
|
{
|
|
newHeight = bound_y * (newWidth/bound_x) ;
|
|
}
|
|
|
|
pt->sm_controlPointDragPosX = (double)(newX1 + (newWidth/2.0));
|
|
pt->sm_controlPointDragPosY = (double)(newY1 + (newHeight/2.0));
|
|
if (this->GetFixedWidth())
|
|
newWidth = bound_x;
|
|
|
|
if (this->GetFixedHeight())
|
|
newHeight = bound_y;
|
|
|
|
pt->sm_controlPointDragEndWidth = newWidth;
|
|
pt->sm_controlPointDragEndHeight = newHeight;
|
|
this->GetEventHandler()->OnDrawOutline(dc, pt->sm_controlPointDragPosX, pt->sm_controlPointDragPosY, newWidth, newHeight);
|
|
}
|
|
}
|
|
|
|
void wxShape::OnSizingBeginDragLeft(wxControlPoint* pt, double x, double y, int keys, int attachment)
|
|
{
|
|
m_canvas->CaptureMouse();
|
|
|
|
wxClientDC dc(GetCanvas());
|
|
GetCanvas()->PrepareDC(dc);
|
|
/*
|
|
if (pt->m_eraseObject)
|
|
this->Erase(dc);
|
|
*/
|
|
|
|
dc.SetLogicalFunction(OGLRBLF);
|
|
|
|
double bound_x;
|
|
double bound_y;
|
|
this->GetBoundingBoxMin(&bound_x, &bound_y);
|
|
|
|
// Choose the 'opposite corner' of the object as the stationary
|
|
// point in case this is non-centring resizing.
|
|
if (pt->GetX() < this->GetX())
|
|
pt->sm_controlPointDragStartX = (double)(this->GetX() + (bound_x/2.0));
|
|
else
|
|
pt->sm_controlPointDragStartX = (double)(this->GetX() - (bound_x/2.0));
|
|
|
|
if (pt->GetY() < this->GetY())
|
|
pt->sm_controlPointDragStartY = (double)(this->GetY() + (bound_y/2.0));
|
|
else
|
|
pt->sm_controlPointDragStartY = (double)(this->GetY() - (bound_y/2.0));
|
|
|
|
if (pt->m_type == CONTROL_POINT_HORIZONTAL)
|
|
pt->sm_controlPointDragStartY = (double)(this->GetY() - (bound_y/2.0));
|
|
else if (pt->m_type == CONTROL_POINT_VERTICAL)
|
|
pt->sm_controlPointDragStartX = (double)(this->GetX() - (bound_x/2.0));
|
|
|
|
// We may require the old width and height.
|
|
pt->sm_controlPointDragStartWidth = bound_x;
|
|
pt->sm_controlPointDragStartHeight = bound_y;
|
|
|
|
wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
|
|
dc.SetPen(dottedPen);
|
|
dc.SetBrush((* wxTRANSPARENT_BRUSH));
|
|
|
|
if (this->GetCentreResize())
|
|
{
|
|
double new_width = (double)(2.0*fabs(x - this->GetX()));
|
|
double new_height = (double)(2.0*fabs(y - this->GetY()));
|
|
|
|
// Constrain sizing according to what control point you're dragging
|
|
if (pt->m_type == CONTROL_POINT_HORIZONTAL)
|
|
{
|
|
if (GetMaintainAspectRatio())
|
|
{
|
|
new_height = bound_y*(new_width/bound_x);
|
|
}
|
|
else
|
|
new_height = bound_y;
|
|
}
|
|
else if (pt->m_type == CONTROL_POINT_VERTICAL)
|
|
{
|
|
if (GetMaintainAspectRatio())
|
|
{
|
|
new_width = bound_x*(new_height/bound_y);
|
|
}
|
|
else
|
|
new_width = bound_x;
|
|
}
|
|
else if (pt->m_type == CONTROL_POINT_DIAGONAL && (keys & KEY_SHIFT))
|
|
new_height = bound_y*(new_width/bound_x);
|
|
|
|
if (this->GetFixedWidth())
|
|
new_width = bound_x;
|
|
|
|
if (this->GetFixedHeight())
|
|
new_height = bound_y;
|
|
|
|
pt->sm_controlPointDragEndWidth = new_width;
|
|
pt->sm_controlPointDragEndHeight = new_height;
|
|
this->GetEventHandler()->OnDrawOutline(dc, this->GetX(), this->GetY(),
|
|
new_width, new_height);
|
|
}
|
|
else
|
|
{
|
|
// Don't maintain the same centre point!
|
|
double newX1 = wxMin(pt->sm_controlPointDragStartX, x);
|
|
double newY1 = wxMin(pt->sm_controlPointDragStartY, y);
|
|
double newX2 = wxMax(pt->sm_controlPointDragStartX, x);
|
|
double newY2 = wxMax(pt->sm_controlPointDragStartY, y);
|
|
if (pt->m_type == CONTROL_POINT_HORIZONTAL)
|
|
{
|
|
newY1 = pt->sm_controlPointDragStartY;
|
|
newY2 = newY1 + pt->sm_controlPointDragStartHeight;
|
|
}
|
|
else if (pt->m_type == CONTROL_POINT_VERTICAL)
|
|
{
|
|
newX1 = pt->sm_controlPointDragStartX;
|
|
newX2 = newX1 + pt->sm_controlPointDragStartWidth;
|
|
}
|
|
else if (pt->m_type == CONTROL_POINT_DIAGONAL && ((keys & KEY_SHIFT) || GetMaintainAspectRatio()))
|
|
{
|
|
double newH = (double)((newX2 - newX1)*(pt->sm_controlPointDragStartHeight/pt->sm_controlPointDragStartWidth));
|
|
if (pt->GetY() > pt->sm_controlPointDragStartY)
|
|
newY2 = (double)(newY1 + newH);
|
|
else
|
|
newY1 = (double)(newY2 - newH);
|
|
}
|
|
double newWidth = (double)(newX2 - newX1);
|
|
double newHeight = (double)(newY2 - newY1);
|
|
|
|
if (pt->m_type == CONTROL_POINT_VERTICAL && GetMaintainAspectRatio())
|
|
{
|
|
newWidth = bound_x * (newHeight/bound_y) ;
|
|
}
|
|
|
|
if (pt->m_type == CONTROL_POINT_HORIZONTAL && GetMaintainAspectRatio())
|
|
{
|
|
newHeight = bound_y * (newWidth/bound_x) ;
|
|
}
|
|
|
|
pt->sm_controlPointDragPosX = (double)(newX1 + (newWidth/2.0));
|
|
pt->sm_controlPointDragPosY = (double)(newY1 + (newHeight/2.0));
|
|
if (this->GetFixedWidth())
|
|
newWidth = bound_x;
|
|
|
|
if (this->GetFixedHeight())
|
|
newHeight = bound_y;
|
|
|
|
pt->sm_controlPointDragEndWidth = newWidth;
|
|
pt->sm_controlPointDragEndHeight = newHeight;
|
|
this->GetEventHandler()->OnDrawOutline(dc, pt->sm_controlPointDragPosX, pt->sm_controlPointDragPosY, newWidth, newHeight);
|
|
}
|
|
}
|
|
|
|
void wxShape::OnSizingEndDragLeft(wxControlPoint* pt, double x, double y, int keys, int attachment)
|
|
{
|
|
wxClientDC dc(GetCanvas());
|
|
GetCanvas()->PrepareDC(dc);
|
|
|
|
m_canvas->ReleaseMouse();
|
|
dc.SetLogicalFunction(wxCOPY);
|
|
this->Recompute();
|
|
this->ResetControlPoints();
|
|
|
|
this->Erase(dc);
|
|
/*
|
|
if (!pt->m_eraseObject)
|
|
this->Show(FALSE);
|
|
*/
|
|
|
|
this->SetSize(pt->sm_controlPointDragEndWidth, pt->sm_controlPointDragEndHeight);
|
|
|
|
// The next operation could destroy this control point (it does for label objects,
|
|
// via formatting the text), so save all values we're going to use, or
|
|
// we'll be accessing garbage.
|
|
wxShape *theObject = this;
|
|
wxShapeCanvas *theCanvas = m_canvas;
|
|
bool eraseIt = pt->m_eraseObject;
|
|
|
|
if (theObject->GetCentreResize())
|
|
theObject->Move(dc, theObject->GetX(), theObject->GetY());
|
|
else
|
|
theObject->Move(dc, pt->sm_controlPointDragPosX, pt->sm_controlPointDragPosY);
|
|
|
|
/*
|
|
if (!eraseIt)
|
|
theObject->Show(TRUE);
|
|
*/
|
|
|
|
// Recursively redraw links if we have a composite.
|
|
if (theObject->GetChildren().Number() > 0)
|
|
theObject->DrawLinks(dc, -1, TRUE);
|
|
|
|
double width, height;
|
|
theObject->GetBoundingBoxMax(&width, &height);
|
|
theObject->GetEventHandler()->OnEndSize(width, height);
|
|
|
|
if (!theCanvas->GetQuickEditMode() && eraseIt) theCanvas->Redraw(dc);
|
|
}
|
|
|
|
|
|
|
|
// Polygon control points
|
|
|
|
IMPLEMENT_DYNAMIC_CLASS(wxPolygonControlPoint, wxControlPoint)
|
|
|
|
wxPolygonControlPoint::wxPolygonControlPoint(wxShapeCanvas *theCanvas, wxShape *object, double size,
|
|
wxRealPoint *vertex, double the_xoffset, double the_yoffset):
|
|
wxControlPoint(theCanvas, object, size, the_xoffset, the_yoffset, 0)
|
|
{
|
|
m_polygonVertex = vertex;
|
|
m_originalDistance = 0.0;
|
|
}
|
|
|
|
wxPolygonControlPoint::~wxPolygonControlPoint()
|
|
{
|
|
}
|
|
|
|
// Calculate what new size would be, at end of resize
|
|
void wxPolygonControlPoint::CalculateNewSize(double x, double y)
|
|
{
|
|
double bound_x;
|
|
double bound_y;
|
|
GetShape()->GetBoundingBoxMin(&bound_x, &bound_y);
|
|
|
|
double dist = (double)sqrt((x - m_shape->GetX())*(x - m_shape->GetX()) +
|
|
(y - m_shape->GetY())*(y - m_shape->GetY()));
|
|
|
|
m_newSize.x = (double)(dist/this->m_originalDistance)*this->m_originalSize.x;
|
|
m_newSize.y = (double)(dist/this->m_originalDistance)*this->m_originalSize.y;
|
|
}
|
|
|
|
|
|
// Implement resizing polygon or moving the vertex.
|
|
void wxPolygonControlPoint::OnDragLeft(bool draw, double x, double y, int keys, int attachment)
|
|
{
|
|
m_shape->GetEventHandler()->OnSizingDragLeft(this, draw, x, y, keys, attachment);
|
|
}
|
|
|
|
void wxPolygonControlPoint::OnBeginDragLeft(double x, double y, int keys, int attachment)
|
|
{
|
|
m_shape->GetEventHandler()->OnSizingBeginDragLeft(this, x, y, keys, attachment);
|
|
}
|
|
|
|
void wxPolygonControlPoint::OnEndDragLeft(double x, double y, int keys, int attachment)
|
|
{
|
|
m_shape->GetEventHandler()->OnSizingEndDragLeft(this, x, y, keys, attachment);
|
|
}
|
|
|
|
// Control points ('handles') redirect control to the actual shape, to make it easier
|
|
// to override sizing behaviour.
|
|
void wxPolygonShape::OnSizingDragLeft(wxControlPoint* pt, bool draw, double x, double y, int keys, int attachment)
|
|
{
|
|
wxPolygonControlPoint* ppt = (wxPolygonControlPoint*) pt;
|
|
|
|
wxClientDC dc(GetCanvas());
|
|
GetCanvas()->PrepareDC(dc);
|
|
|
|
dc.SetLogicalFunction(OGLRBLF);
|
|
|
|
wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
|
|
dc.SetPen(dottedPen);
|
|
dc.SetBrush((* wxTRANSPARENT_BRUSH));
|
|
|
|
if (0) // keys & KEY_CTRL)
|
|
{
|
|
// TODO: mend this code. Currently we rely on altering the
|
|
// actual points, but we should assume we're not, as per
|
|
// the normal sizing case.
|
|
m_canvas->Snap(&x, &y);
|
|
|
|
// Move point
|
|
ppt->m_polygonVertex->x = x - this->GetX();
|
|
ppt->m_polygonVertex->y = y - this->GetY();
|
|
ppt->SetX(x);
|
|
ppt->SetY(y);
|
|
((wxPolygonShape *)this)->CalculateBoundingBox();
|
|
((wxPolygonShape *)this)->CalculatePolygonCentre();
|
|
}
|
|
else
|
|
{
|
|
ppt->CalculateNewSize(x, y);
|
|
}
|
|
|
|
this->GetEventHandler()->OnDrawOutline(dc, this->GetX(), this->GetY(),
|
|
ppt->GetNewSize().x, ppt->GetNewSize().y);
|
|
}
|
|
|
|
void wxPolygonShape::OnSizingBeginDragLeft(wxControlPoint* pt, double x, double y, int keys, int attachment)
|
|
{
|
|
wxPolygonControlPoint* ppt = (wxPolygonControlPoint*) pt;
|
|
|
|
wxClientDC dc(GetCanvas());
|
|
GetCanvas()->PrepareDC(dc);
|
|
|
|
this->Erase(dc);
|
|
|
|
dc.SetLogicalFunction(OGLRBLF);
|
|
|
|
double bound_x;
|
|
double bound_y;
|
|
this->GetBoundingBoxMin(&bound_x, &bound_y);
|
|
|
|
double dist = (double)sqrt((x - this->GetX())*(x - this->GetX()) +
|
|
(y - this->GetY())*(y - this->GetY()));
|
|
ppt->m_originalDistance = dist;
|
|
ppt->m_originalSize.x = bound_x;
|
|
ppt->m_originalSize.y = bound_y;
|
|
|
|
if (ppt->m_originalDistance == 0.0) ppt->m_originalDistance = (double) 0.0001;
|
|
|
|
wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
|
|
dc.SetPen(dottedPen);
|
|
dc.SetBrush((* wxTRANSPARENT_BRUSH));
|
|
|
|
if (0) // keys & KEY_CTRL)
|
|
{
|
|
// TODO: mend this code. Currently we rely on altering the
|
|
// actual points, but we should assume we're not, as per
|
|
// the normal sizing case.
|
|
m_canvas->Snap(&x, &y);
|
|
|
|
// Move point
|
|
ppt->m_polygonVertex->x = x - this->GetX();
|
|
ppt->m_polygonVertex->y = y - this->GetY();
|
|
ppt->SetX(x);
|
|
ppt->SetY(y);
|
|
((wxPolygonShape *)this)->CalculateBoundingBox();
|
|
((wxPolygonShape *)this)->CalculatePolygonCentre();
|
|
}
|
|
else
|
|
{
|
|
ppt->CalculateNewSize(x, y);
|
|
}
|
|
|
|
this->GetEventHandler()->OnDrawOutline(dc, this->GetX(), this->GetY(),
|
|
ppt->GetNewSize().x, ppt->GetNewSize().y);
|
|
|
|
m_canvas->CaptureMouse();
|
|
}
|
|
|
|
void wxPolygonShape::OnSizingEndDragLeft(wxControlPoint* pt, double x, double y, int keys, int attachment)
|
|
{
|
|
wxPolygonControlPoint* ppt = (wxPolygonControlPoint*) pt;
|
|
|
|
wxClientDC dc(GetCanvas());
|
|
GetCanvas()->PrepareDC(dc);
|
|
|
|
m_canvas->ReleaseMouse();
|
|
dc.SetLogicalFunction(wxCOPY);
|
|
|
|
// If we're changing shape, must reset the original points
|
|
if (keys & KEY_CTRL)
|
|
{
|
|
((wxPolygonShape *)this)->CalculateBoundingBox();
|
|
((wxPolygonShape *)this)->UpdateOriginalPoints();
|
|
}
|
|
else
|
|
{
|
|
SetSize(ppt->GetNewSize().x, ppt->GetNewSize().y);
|
|
}
|
|
|
|
((wxPolygonShape *)this)->CalculateBoundingBox();
|
|
((wxPolygonShape *)this)->CalculatePolygonCentre();
|
|
|
|
this->Recompute();
|
|
this->ResetControlPoints();
|
|
this->Move(dc, this->GetX(), this->GetY());
|
|
if (!m_canvas->GetQuickEditMode()) m_canvas->Redraw(dc);
|
|
}
|
|
|
|
/*
|
|
* Object region
|
|
*
|
|
*/
|
|
IMPLEMENT_DYNAMIC_CLASS(wxShapeRegion, wxObject)
|
|
|
|
wxShapeRegion::wxShapeRegion()
|
|
{
|
|
m_regionText = wxEmptyString;
|
|
m_font = g_oglNormalFont;
|
|
m_minHeight = 5.0;
|
|
m_minWidth = 5.0;
|
|
m_width = 0.0;
|
|
m_height = 0.0;
|
|
m_x = 0.0;
|
|
m_y = 0.0;
|
|
|
|
m_regionProportionX = -1.0;
|
|
m_regionProportionY = -1.0;
|
|
m_formatMode = FORMAT_CENTRE_HORIZ | FORMAT_CENTRE_VERT;
|
|
m_regionName = wxEmptyString;
|
|
m_textColour = wxT("BLACK");
|
|
m_penColour = wxT("BLACK");
|
|
m_penStyle = wxSOLID;
|
|
m_actualColourObject = NULL;
|
|
m_actualPenObject = NULL;
|
|
}
|
|
|
|
wxShapeRegion::wxShapeRegion(wxShapeRegion& region)
|
|
{
|
|
m_regionText = region.m_regionText;
|
|
m_regionName = region.m_regionName;
|
|
m_textColour = region.m_textColour;
|
|
|
|
m_font = region.m_font;
|
|
m_minHeight = region.m_minHeight;
|
|
m_minWidth = region.m_minWidth;
|
|
m_width = region.m_width;
|
|
m_height = region.m_height;
|
|
m_x = region.m_x;
|
|
m_y = region.m_y;
|
|
|
|
m_regionProportionX = region.m_regionProportionX;
|
|
m_regionProportionY = region.m_regionProportionY;
|
|
m_formatMode = region.m_formatMode;
|
|
m_actualColourObject = NULL;
|
|
m_actualPenObject = NULL;
|
|
m_penStyle = region.m_penStyle;
|
|
m_penColour = region.m_penColour;
|
|
|
|
ClearText();
|
|
wxNode *node = region.m_formattedText.First();
|
|
while (node)
|
|
{
|
|
wxShapeTextLine *line = (wxShapeTextLine *)node->Data();
|
|
wxShapeTextLine *new_line =
|
|
new wxShapeTextLine(line->GetX(), line->GetY(), line->GetText());
|
|
m_formattedText.Append(new_line);
|
|
node = node->Next();
|
|
}
|
|
}
|
|
|
|
wxShapeRegion::~wxShapeRegion()
|
|
{
|
|
ClearText();
|
|
}
|
|
|
|
void wxShapeRegion::ClearText()
|
|
{
|
|
wxNode *node = m_formattedText.First();
|
|
while (node)
|
|
{
|
|
wxShapeTextLine *line = (wxShapeTextLine *)node->Data();
|
|
wxNode *next = node->Next();
|
|
delete line;
|
|
delete node;
|
|
node = next;
|
|
}
|
|
}
|
|
|
|
void wxShapeRegion::SetFont(wxFont *f)
|
|
{
|
|
m_font = f;
|
|
}
|
|
|
|
void wxShapeRegion::SetMinSize(double w, double h)
|
|
{
|
|
m_minWidth = w;
|
|
m_minHeight = h;
|
|
}
|
|
|
|
void wxShapeRegion::SetSize(double w, double h)
|
|
{
|
|
m_width = w;
|
|
m_height = h;
|
|
}
|
|
|
|
void wxShapeRegion::SetPosition(double xp, double yp)
|
|
{
|
|
m_x = xp;
|
|
m_y = yp;
|
|
}
|
|
|
|
void wxShapeRegion::SetProportions(double xp, double yp)
|
|
{
|
|
m_regionProportionX = xp;
|
|
m_regionProportionY = yp;
|
|
}
|
|
|
|
void wxShapeRegion::SetFormatMode(int mode)
|
|
{
|
|
m_formatMode = mode;
|
|
}
|
|
|
|
void wxShapeRegion::SetColour(const wxString& col)
|
|
{
|
|
m_textColour = col;
|
|
m_actualColourObject = NULL;
|
|
}
|
|
|
|
wxColour *wxShapeRegion::GetActualColourObject()
|
|
{
|
|
if (!m_actualColourObject)
|
|
m_actualColourObject = wxTheColourDatabase->FindColour(GetColour());
|
|
if (!m_actualColourObject)
|
|
m_actualColourObject = wxBLACK;
|
|
return m_actualColourObject;
|
|
}
|
|
|
|
void wxShapeRegion::SetPenColour(const wxString& col)
|
|
{
|
|
m_penColour = col;
|
|
m_actualPenObject = NULL;
|
|
}
|
|
|
|
// Returns NULL if the pen is invisible
|
|
// (different to pen being transparent; indicates that
|
|
// region boundary should not be drawn.)
|
|
wxPen *wxShapeRegion::GetActualPen()
|
|
{
|
|
if (m_actualPenObject)
|
|
return m_actualPenObject;
|
|
|
|
if (!m_penColour) return NULL;
|
|
if (m_penColour == wxT("Invisible"))
|
|
return NULL;
|
|
m_actualPenObject = wxThePenList->FindOrCreatePen(m_penColour, 1, m_penStyle);
|
|
return m_actualPenObject;
|
|
}
|
|
|
|
|