Added OGL to contrib
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@6407 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
13
contrib/src/ogl/Makefile.in
Normal file
13
contrib/src/ogl/Makefile.in
Normal file
@@ -0,0 +1,13 @@
|
||||
#
|
||||
|
||||
top_builddir = ../..
|
||||
|
||||
VPATH= $(top_srcdir)/ogl
|
||||
|
||||
LIBTARGET=$(top_builddir)/lib/libogl
|
||||
|
||||
OBJECTS=basic.o bmpshape.o composit.o divided.o lines.o misc.o \
|
||||
basic2.o canvas.o constrnt.o drawn.o mfutils.o ogldiag.o
|
||||
|
||||
|
||||
include $(top_builddir)/src/makelib.env
|
||||
3274
contrib/src/ogl/basic.cpp
Normal file
3274
contrib/src/ogl/basic.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1902
contrib/src/ogl/basic2.cpp
Normal file
1902
contrib/src/ogl/basic2.cpp
Normal file
File diff suppressed because it is too large
Load Diff
115
contrib/src/ogl/bmpshape.cpp
Normal file
115
contrib/src/ogl/bmpshape.cpp
Normal file
@@ -0,0 +1,115 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: bmpshape.cpp
|
||||
// Purpose: Bitmap shape class
|
||||
// Author: Julian Smart
|
||||
// Modified by:
|
||||
// Created: 12/07/98
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) Julian Smart
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "bmpshape.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>
|
||||
|
||||
#include <wx/ogl/basic.h>
|
||||
#include <wx/ogl/basicp.h>
|
||||
#include <wx/ogl/canvas.h>
|
||||
#include <wx/ogl/bmpshape.h>
|
||||
#include <wx/ogl/misc.h>
|
||||
|
||||
/*
|
||||
* Bitmap object
|
||||
*
|
||||
*/
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxBitmapShape, wxShape)
|
||||
|
||||
wxBitmapShape::wxBitmapShape():wxRectangleShape(100.0, 50.0)
|
||||
{
|
||||
m_filename = "";
|
||||
}
|
||||
|
||||
wxBitmapShape::~wxBitmapShape()
|
||||
{
|
||||
}
|
||||
|
||||
void wxBitmapShape::OnDraw(wxDC& dc)
|
||||
{
|
||||
if (!m_bitmap.Ok())
|
||||
return;
|
||||
|
||||
wxMemoryDC tempDC;
|
||||
tempDC.SelectObject(m_bitmap);
|
||||
double x, y;
|
||||
x = WXROUND(m_xpos - m_bitmap.GetWidth() / 2.0);
|
||||
y = WXROUND(m_ypos - m_bitmap.GetHeight() / 2.0);
|
||||
dc.Blit((long) x, (long) y, m_bitmap.GetWidth(), m_bitmap.GetHeight(), &tempDC, 0, 0);
|
||||
}
|
||||
|
||||
void wxBitmapShape::SetSize(double w, double h, bool recursive)
|
||||
{
|
||||
if (m_bitmap.Ok())
|
||||
{
|
||||
w = m_bitmap.GetWidth();
|
||||
h = m_bitmap.GetHeight();
|
||||
}
|
||||
|
||||
SetAttachmentSize(w, h);
|
||||
|
||||
m_width = w;
|
||||
m_height = h;
|
||||
SetDefaultRegionSize();
|
||||
}
|
||||
|
||||
#ifdef PROLOGIO
|
||||
void wxBitmapShape::WriteAttributes(wxExpr *clause)
|
||||
{
|
||||
// Can't really save the bitmap; so instantiate the bitmap
|
||||
// at a higher level in the application, from a symbol library.
|
||||
wxRectangleShape::WriteAttributes(clause);
|
||||
clause->AddAttributeValueString("filename", m_filename);
|
||||
}
|
||||
|
||||
void wxBitmapShape::ReadAttributes(wxExpr *clause)
|
||||
{
|
||||
wxRectangleShape::ReadAttributes(clause);
|
||||
clause->GetAttributeValue("filename", m_filename);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Does the copying for this object
|
||||
void wxBitmapShape::Copy(wxShape& copy)
|
||||
{
|
||||
wxRectangleShape::Copy(copy);
|
||||
|
||||
wxASSERT( copy.IsKindOf(CLASSINFO(wxBitmapShape)) ) ;
|
||||
|
||||
wxBitmapShape& bitmapCopy = (wxBitmapShape&) copy;
|
||||
|
||||
bitmapCopy.m_bitmap = m_bitmap;
|
||||
bitmapCopy.SetFilename(m_filename);
|
||||
}
|
||||
|
||||
void wxBitmapShape::SetBitmap(const wxBitmap& bm)
|
||||
{
|
||||
m_bitmap = bm;
|
||||
if (m_bitmap.Ok())
|
||||
SetSize(m_bitmap.GetWidth(), m_bitmap.GetHeight());
|
||||
}
|
||||
|
||||
|
||||
516
contrib/src/ogl/canvas.cpp
Normal file
516
contrib/src/ogl/canvas.cpp
Normal file
@@ -0,0 +1,516 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: canvas.cpp
|
||||
// Purpose: Shape canvas class
|
||||
// Author: Julian Smart
|
||||
// Modified by:
|
||||
// Created: 12/07/98
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) Julian Smart
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "canvas.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>
|
||||
|
||||
#if wxUSE_IOSTREAMH
|
||||
#include <iostream.h>
|
||||
#else
|
||||
#include <iostream>
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <wx/ogl/basic.h>
|
||||
#include <wx/ogl/basicp.h>
|
||||
#include <wx/ogl/canvas.h>
|
||||
#include <wx/ogl/ogldiag.h>
|
||||
#include <wx/ogl/misc.h>
|
||||
#include <wx/ogl/lines.h>
|
||||
#include <wx/ogl/composit.h>
|
||||
|
||||
#define CONTROL_POINT_SIZE 6
|
||||
|
||||
// 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
|
||||
|
||||
extern wxCursor *g_oglBullseyeCursor;
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxShapeCanvas, wxScrolledWindow)
|
||||
|
||||
BEGIN_EVENT_TABLE(wxShapeCanvas, wxScrolledWindow)
|
||||
EVT_PAINT(wxShapeCanvas::OnPaint)
|
||||
EVT_MOUSE_EVENTS(wxShapeCanvas::OnMouseEvent)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
// Object canvas
|
||||
wxShapeCanvas::wxShapeCanvas(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style):
|
||||
wxScrolledWindow(parent, id, pos, size, style)
|
||||
{
|
||||
m_shapeDiagram = NULL;
|
||||
m_dragState = NoDragging;
|
||||
m_draggedShape = NULL;
|
||||
m_oldDragX = 0;
|
||||
m_oldDragY = 0;
|
||||
m_firstDragX = 0;
|
||||
m_firstDragY = 0;
|
||||
m_checkTolerance = TRUE;
|
||||
}
|
||||
|
||||
wxShapeCanvas::~wxShapeCanvas()
|
||||
{
|
||||
}
|
||||
|
||||
void wxShapeCanvas::OnPaint(wxPaintEvent& event)
|
||||
{
|
||||
wxPaintDC dc(this);
|
||||
|
||||
PrepareDC(dc);
|
||||
|
||||
dc.Clear();
|
||||
|
||||
if (GetDiagram())
|
||||
GetDiagram()->Redraw(dc);
|
||||
}
|
||||
|
||||
void wxShapeCanvas::OnMouseEvent(wxMouseEvent& event)
|
||||
{
|
||||
wxClientDC dc(this);
|
||||
PrepareDC(dc);
|
||||
|
||||
wxPoint logPos(event.GetLogicalPosition(dc));
|
||||
|
||||
double x, y;
|
||||
x = (double) logPos.x;
|
||||
y = (double) logPos.y;
|
||||
|
||||
int keys = 0;
|
||||
if (event.ShiftDown())
|
||||
keys = keys | KEY_SHIFT;
|
||||
if (event.ControlDown())
|
||||
keys = keys | KEY_CTRL;
|
||||
|
||||
bool dragging = event.Dragging();
|
||||
|
||||
// Check if we're within the tolerance for mouse movements.
|
||||
// If we're very close to the position we started dragging
|
||||
// from, this may not be an intentional drag at all.
|
||||
if (dragging)
|
||||
{
|
||||
int dx = abs(dc.LogicalToDeviceX((long) (x - m_firstDragX)));
|
||||
int dy = abs(dc.LogicalToDeviceY((long) (y - m_firstDragY)));
|
||||
if (m_checkTolerance && (dx <= GetDiagram()->GetMouseTolerance()) && (dy <= GetDiagram()->GetMouseTolerance()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
// If we've ignored the tolerance once, then ALWAYS ignore
|
||||
// tolerance in this drag, even if we come back within
|
||||
// the tolerance range.
|
||||
m_checkTolerance = FALSE;
|
||||
}
|
||||
|
||||
// Dragging - note that the effect of dragging is left entirely up
|
||||
// to the object, so no movement is done unless explicitly done by
|
||||
// object.
|
||||
if (dragging && m_draggedShape && m_dragState == StartDraggingLeft)
|
||||
{
|
||||
m_dragState = ContinueDraggingLeft;
|
||||
|
||||
// If the object isn't m_draggable, transfer message to canvas
|
||||
if (m_draggedShape->Draggable())
|
||||
m_draggedShape->GetEventHandler()->OnBeginDragLeft((double)x, (double)y, keys, m_draggedAttachment);
|
||||
else
|
||||
{
|
||||
m_draggedShape = NULL;
|
||||
OnBeginDragLeft((double)x, (double)y, keys);
|
||||
}
|
||||
|
||||
m_oldDragX = x; m_oldDragY = y;
|
||||
}
|
||||
else if (dragging && m_draggedShape && m_dragState == ContinueDraggingLeft)
|
||||
{
|
||||
// Continue dragging
|
||||
m_draggedShape->GetEventHandler()->OnDragLeft(FALSE, m_oldDragX, m_oldDragY, keys, m_draggedAttachment);
|
||||
m_draggedShape->GetEventHandler()->OnDragLeft(TRUE, (double)x, (double)y, keys, m_draggedAttachment);
|
||||
m_oldDragX = x; m_oldDragY = y;
|
||||
}
|
||||
else if (event.LeftUp() && m_draggedShape && m_dragState == ContinueDraggingLeft)
|
||||
{
|
||||
m_dragState = NoDragging;
|
||||
m_checkTolerance = TRUE;
|
||||
|
||||
m_draggedShape->GetEventHandler()->OnDragLeft(FALSE, m_oldDragX, m_oldDragY, keys, m_draggedAttachment);
|
||||
|
||||
m_draggedShape->GetEventHandler()->OnEndDragLeft((double)x, (double)y, keys, m_draggedAttachment);
|
||||
m_draggedShape = NULL;
|
||||
}
|
||||
else if (dragging && m_draggedShape && m_dragState == StartDraggingRight)
|
||||
{
|
||||
m_dragState = ContinueDraggingRight;
|
||||
|
||||
if (m_draggedShape->Draggable())
|
||||
m_draggedShape->GetEventHandler()->OnBeginDragRight((double)x, (double)y, keys, m_draggedAttachment);
|
||||
else
|
||||
{
|
||||
m_draggedShape = NULL;
|
||||
OnBeginDragRight((double)x, (double)y, keys);
|
||||
}
|
||||
m_oldDragX = x; m_oldDragY = y;
|
||||
}
|
||||
else if (dragging && m_draggedShape && m_dragState == ContinueDraggingRight)
|
||||
{
|
||||
// Continue dragging
|
||||
m_draggedShape->GetEventHandler()->OnDragRight(FALSE, m_oldDragX, m_oldDragY, keys, m_draggedAttachment);
|
||||
m_draggedShape->GetEventHandler()->OnDragRight(TRUE, (double)x, (double)y, keys, m_draggedAttachment);
|
||||
m_oldDragX = x; m_oldDragY = y;
|
||||
}
|
||||
else if (event.RightUp() && m_draggedShape && m_dragState == ContinueDraggingRight)
|
||||
{
|
||||
m_dragState = NoDragging;
|
||||
m_checkTolerance = TRUE;
|
||||
|
||||
m_draggedShape->GetEventHandler()->OnDragRight(FALSE, m_oldDragX, m_oldDragY, keys, m_draggedAttachment);
|
||||
|
||||
m_draggedShape->GetEventHandler()->OnEndDragRight((double)x, (double)y, keys, m_draggedAttachment);
|
||||
m_draggedShape = NULL;
|
||||
}
|
||||
|
||||
// All following events sent to canvas, not object
|
||||
else if (dragging && !m_draggedShape && m_dragState == StartDraggingLeft)
|
||||
{
|
||||
m_dragState = ContinueDraggingLeft;
|
||||
OnBeginDragLeft((double)x, (double)y, keys);
|
||||
m_oldDragX = x; m_oldDragY = y;
|
||||
}
|
||||
else if (dragging && !m_draggedShape && m_dragState == ContinueDraggingLeft)
|
||||
{
|
||||
// Continue dragging
|
||||
OnDragLeft(FALSE, m_oldDragX, m_oldDragY, keys);
|
||||
OnDragLeft(TRUE, (double)x, (double)y, keys);
|
||||
m_oldDragX = x; m_oldDragY = y;
|
||||
}
|
||||
else if (event.LeftUp() && !m_draggedShape && m_dragState == ContinueDraggingLeft)
|
||||
{
|
||||
m_dragState = NoDragging;
|
||||
m_checkTolerance = TRUE;
|
||||
|
||||
OnDragLeft(FALSE, m_oldDragX, m_oldDragY, keys);
|
||||
OnEndDragLeft((double)x, (double)y, keys);
|
||||
m_draggedShape = NULL;
|
||||
}
|
||||
else if (dragging && !m_draggedShape && m_dragState == StartDraggingRight)
|
||||
{
|
||||
m_dragState = ContinueDraggingRight;
|
||||
OnBeginDragRight((double)x, (double)y, keys);
|
||||
m_oldDragX = x; m_oldDragY = y;
|
||||
}
|
||||
else if (dragging && !m_draggedShape && m_dragState == ContinueDraggingRight)
|
||||
{
|
||||
// Continue dragging
|
||||
OnDragRight(FALSE, m_oldDragX, m_oldDragY, keys);
|
||||
OnDragRight(TRUE, (double)x, (double)y, keys);
|
||||
m_oldDragX = x; m_oldDragY = y;
|
||||
}
|
||||
else if (event.RightUp() && !m_draggedShape && m_dragState == ContinueDraggingRight)
|
||||
{
|
||||
m_dragState = NoDragging;
|
||||
m_checkTolerance = TRUE;
|
||||
|
||||
OnDragRight(FALSE, m_oldDragX, m_oldDragY, keys);
|
||||
OnEndDragRight((double)x, (double)y, keys);
|
||||
m_draggedShape = NULL;
|
||||
}
|
||||
|
||||
// Non-dragging events
|
||||
else if (event.IsButton())
|
||||
{
|
||||
m_checkTolerance = TRUE;
|
||||
|
||||
// Find the nearest object
|
||||
int attachment = 0;
|
||||
wxShape *nearest_object = FindShape(x, y, &attachment);
|
||||
if (nearest_object) // Object event
|
||||
{
|
||||
if (event.LeftDown())
|
||||
{
|
||||
m_draggedShape = nearest_object;
|
||||
m_draggedAttachment = attachment;
|
||||
m_dragState = StartDraggingLeft;
|
||||
m_firstDragX = x;
|
||||
m_firstDragY = y;
|
||||
}
|
||||
else if (event.LeftUp())
|
||||
{
|
||||
// N.B. Only register a click if the same object was
|
||||
// identified for down *and* up.
|
||||
if (nearest_object == m_draggedShape)
|
||||
nearest_object->GetEventHandler()->OnLeftClick((double)x, (double)y, keys, attachment);
|
||||
|
||||
m_draggedShape = NULL;
|
||||
m_dragState = NoDragging;
|
||||
}
|
||||
else if (event.LeftDClick())
|
||||
{
|
||||
nearest_object->GetEventHandler()->OnLeftDoubleClick((double)x, (double)y, keys, attachment);
|
||||
|
||||
m_draggedShape = NULL;
|
||||
m_dragState = NoDragging;
|
||||
}
|
||||
else if (event.RightDown())
|
||||
{
|
||||
m_draggedShape = nearest_object;
|
||||
m_draggedAttachment = attachment;
|
||||
m_dragState = StartDraggingRight;
|
||||
m_firstDragX = x;
|
||||
m_firstDragY = y;
|
||||
}
|
||||
else if (event.RightUp())
|
||||
{
|
||||
if (nearest_object == m_draggedShape)
|
||||
nearest_object->GetEventHandler()->OnRightClick((double)x, (double)y, keys, attachment);
|
||||
|
||||
m_draggedShape = NULL;
|
||||
m_dragState = NoDragging;
|
||||
}
|
||||
}
|
||||
else // Canvas event (no nearest object)
|
||||
{
|
||||
if (event.LeftDown())
|
||||
{
|
||||
m_draggedShape = NULL;
|
||||
m_dragState = StartDraggingLeft;
|
||||
m_firstDragX = x;
|
||||
m_firstDragY = y;
|
||||
}
|
||||
else if (event.LeftUp())
|
||||
{
|
||||
OnLeftClick((double)x, (double)y, keys);
|
||||
|
||||
m_draggedShape = NULL;
|
||||
m_dragState = NoDragging;
|
||||
}
|
||||
else if (event.RightDown())
|
||||
{
|
||||
m_draggedShape = NULL;
|
||||
m_dragState = StartDraggingRight;
|
||||
m_firstDragX = x;
|
||||
m_firstDragY = y;
|
||||
}
|
||||
else if (event.RightUp())
|
||||
{
|
||||
OnRightClick((double)x, (double)y, keys);
|
||||
|
||||
m_draggedShape = NULL;
|
||||
m_dragState = NoDragging;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to find a sensitive object, working up the hierarchy of composites.
|
||||
*
|
||||
*/
|
||||
wxShape *wxShapeCanvas::FindFirstSensitiveShape(double x, double y, int *new_attachment, int op)
|
||||
{
|
||||
wxShape *image = FindShape(x, y, new_attachment);
|
||||
if (!image) return NULL;
|
||||
|
||||
wxShape *actualImage = FindFirstSensitiveShape1(image, op);
|
||||
if (actualImage)
|
||||
{
|
||||
double dist;
|
||||
// Find actual attachment
|
||||
actualImage->HitTest(x, y, new_attachment, &dist);
|
||||
}
|
||||
return actualImage;
|
||||
}
|
||||
|
||||
wxShape *wxShapeCanvas::FindFirstSensitiveShape1(wxShape *image, int op)
|
||||
{
|
||||
if (image->GetSensitivityFilter() & op)
|
||||
return image;
|
||||
if (image->GetParent())
|
||||
return FindFirstSensitiveShape1(image->GetParent(), op);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Helper function: TRUE if 'contains' wholly contains 'contained'.
|
||||
static bool WhollyContains(wxShape *contains, wxShape *contained)
|
||||
{
|
||||
double xp1, yp1, xp2, yp2;
|
||||
double w1, h1, w2, h2;
|
||||
double left1, top1, right1, bottom1, left2, top2, right2, bottom2;
|
||||
|
||||
xp1 = contains->GetX(); yp1 = contains->GetY(); xp2 = contained->GetX(); yp2 = contained->GetY();
|
||||
contains->GetBoundingBoxMax(&w1, &h1);
|
||||
contained->GetBoundingBoxMax(&w2, &h2);
|
||||
|
||||
left1 = (double)(xp1 - (w1 / 2.0));
|
||||
top1 = (double)(yp1 - (h1 / 2.0));
|
||||
right1 = (double)(xp1 + (w1 / 2.0));
|
||||
bottom1 = (double)(yp1 + (h1 / 2.0));
|
||||
|
||||
left2 = (double)(xp2 - (w2 / 2.0));
|
||||
top2 = (double)(yp2 - (h2 / 2.0));
|
||||
right2 = (double)(xp2 + (w2 / 2.0));
|
||||
bottom2 = (double)(yp2 + (h2 / 2.0));
|
||||
|
||||
return ((left1 <= left2) && (top1 <= top2) && (right1 >= right2) && (bottom1 >= bottom2));
|
||||
}
|
||||
|
||||
wxShape *wxShapeCanvas::FindShape(double x, double y, int *attachment, wxClassInfo *info, wxShape *notObject)
|
||||
{
|
||||
double nearest = 100000.0;
|
||||
int nearest_attachment = 0;
|
||||
wxShape *nearest_object = NULL;
|
||||
|
||||
// Go backward through the object list, since we want:
|
||||
// (a) to have the control points drawn LAST to overlay
|
||||
// the other objects
|
||||
// (b) to find the control points FIRST if they exist
|
||||
|
||||
wxNode *current = GetDiagram()->GetShapeList()->Last();
|
||||
while (current)
|
||||
{
|
||||
wxShape *object = (wxShape *)current->Data();
|
||||
|
||||
double dist;
|
||||
int temp_attachment;
|
||||
|
||||
// First pass for lines, which might be inside a container, so we
|
||||
// want lines to take priority over containers. This first loop
|
||||
// could fail if we clickout side a line, so then we'll
|
||||
// try other shapes.
|
||||
if (object->IsShown() &&
|
||||
object->IsKindOf(CLASSINFO(wxLineShape)) &&
|
||||
object->HitTest(x, y, &temp_attachment, &dist) &&
|
||||
((info == NULL) || object->IsKindOf(info)) &&
|
||||
(!notObject || !notObject->HasDescendant(object)))
|
||||
{
|
||||
// A line is trickier to spot than a normal object.
|
||||
// For a line, since it's the diagonal of the box
|
||||
// we use for the hit test, we may have several
|
||||
// lines in the box and therefore we need to be able
|
||||
// to specify the nearest point to the centre of the line
|
||||
// as our hit criterion, to give the user some room for
|
||||
// manouevre.
|
||||
if (dist < nearest)
|
||||
{
|
||||
nearest = dist;
|
||||
nearest_object = object;
|
||||
nearest_attachment = temp_attachment;
|
||||
}
|
||||
}
|
||||
if (current)
|
||||
current = current->Previous();
|
||||
}
|
||||
|
||||
current = GetDiagram()->GetShapeList()->Last();
|
||||
while (current)
|
||||
{
|
||||
wxShape *object = (wxShape *)current->Data();
|
||||
double dist;
|
||||
int temp_attachment;
|
||||
|
||||
// On second pass, only ever consider non-composites or divisions. If children want to pass
|
||||
// up control to the composite, that's up to them.
|
||||
if (object->IsShown() && (object->IsKindOf(CLASSINFO(wxDivisionShape)) || !object->IsKindOf(CLASSINFO(wxCompositeShape)))
|
||||
&& object->HitTest(x, y, &temp_attachment, &dist) && ((info == NULL) || object->IsKindOf(info)) &&
|
||||
(!notObject || !notObject->HasDescendant(object)))
|
||||
{
|
||||
if (!object->IsKindOf(CLASSINFO(wxLineShape)))
|
||||
{
|
||||
// If we've hit a container, and we have already found a line in the
|
||||
// first pass, then ignore the container in case the line is in the container.
|
||||
// Check for division in case line straddles divisions (i.e. is not wholly contained).
|
||||
if (!nearest_object || !(object->IsKindOf(CLASSINFO(wxDivisionShape)) || WhollyContains(object, nearest_object)))
|
||||
{
|
||||
nearest = dist;
|
||||
nearest_object = object;
|
||||
nearest_attachment = temp_attachment;
|
||||
current = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (current)
|
||||
current = current->Previous();
|
||||
}
|
||||
|
||||
*attachment = nearest_attachment;
|
||||
return nearest_object;
|
||||
}
|
||||
|
||||
/*
|
||||
* Higher-level events called by OnEvent
|
||||
*
|
||||
*/
|
||||
|
||||
void wxShapeCanvas::OnLeftClick(double x, double y, int keys)
|
||||
{
|
||||
}
|
||||
|
||||
void wxShapeCanvas::OnRightClick(double x, double y, int keys)
|
||||
{
|
||||
}
|
||||
|
||||
void wxShapeCanvas::OnDragLeft(bool draw, double x, double y, int keys)
|
||||
{
|
||||
}
|
||||
|
||||
void wxShapeCanvas::OnBeginDragLeft(double x, double y, int keys)
|
||||
{
|
||||
}
|
||||
|
||||
void wxShapeCanvas::OnEndDragLeft(double x, double y, int keys)
|
||||
{
|
||||
}
|
||||
|
||||
void wxShapeCanvas::OnDragRight(bool draw, double x, double y, int keys)
|
||||
{
|
||||
}
|
||||
|
||||
void wxShapeCanvas::OnBeginDragRight(double x, double y, int keys)
|
||||
{
|
||||
}
|
||||
|
||||
void wxShapeCanvas::OnEndDragRight(double x, double y, int keys)
|
||||
{
|
||||
}
|
||||
|
||||
void wxShapeCanvas::AddShape(wxShape *object, wxShape *addAfter)
|
||||
{ GetDiagram()->AddShape(object, addAfter); }
|
||||
void wxShapeCanvas::InsertShape(wxShape *object)
|
||||
{ GetDiagram()->InsertShape(object); }
|
||||
void wxShapeCanvas::RemoveShape(wxShape *object)
|
||||
{ GetDiagram()->RemoveShape(object); }
|
||||
bool wxShapeCanvas::GetQuickEditMode()
|
||||
{ return GetDiagram()->GetQuickEditMode(); }
|
||||
void wxShapeCanvas::Redraw(wxDC& dc)
|
||||
{ GetDiagram()->Redraw(dc); }
|
||||
void wxShapeCanvas::Snap(double *x, double *y)
|
||||
{ GetDiagram()->Snap(x, y); }
|
||||
1784
contrib/src/ogl/composit.cpp
Normal file
1784
contrib/src/ogl/composit.cpp
Normal file
File diff suppressed because it is too large
Load Diff
619
contrib/src/ogl/constrnt.cpp
Normal file
619
contrib/src/ogl/constrnt.cpp
Normal file
@@ -0,0 +1,619 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: constrnt.cpp
|
||||
// Purpose: OGL Constraint classes
|
||||
// Author: Julian Smart
|
||||
// Modified by:
|
||||
// Created: 12/07/98
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) Julian Smart
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "constrnt.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>
|
||||
|
||||
#include <wx/ogl/basic.h>
|
||||
#include <wx/ogl/constrnt.h>
|
||||
#include <wx/ogl/canvas.h>
|
||||
|
||||
wxList *wxOGLConstraintTypes = NULL;
|
||||
|
||||
/*
|
||||
* Constraint type
|
||||
*
|
||||
*/
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxOGLConstraintType, wxObject)
|
||||
|
||||
wxOGLConstraintType::wxOGLConstraintType(int theType, const wxString& theName, const wxString& thePhrase)
|
||||
{
|
||||
m_type = theType;
|
||||
m_name = theName;
|
||||
m_phrase = thePhrase;
|
||||
}
|
||||
|
||||
wxOGLConstraintType::~wxOGLConstraintType()
|
||||
{
|
||||
}
|
||||
|
||||
void OGLInitializeConstraintTypes()
|
||||
{
|
||||
if (!wxOGLConstraintTypes)
|
||||
return;
|
||||
|
||||
wxOGLConstraintTypes = new wxList(wxKEY_INTEGER);
|
||||
|
||||
wxOGLConstraintTypes->Append(gyCONSTRAINT_CENTRED_VERTICALLY,
|
||||
new wxOGLConstraintType(gyCONSTRAINT_CENTRED_VERTICALLY, "Centre vertically", "centred vertically w.r.t."));
|
||||
|
||||
wxOGLConstraintTypes->Append(gyCONSTRAINT_CENTRED_HORIZONTALLY,
|
||||
new wxOGLConstraintType(gyCONSTRAINT_CENTRED_HORIZONTALLY, "Centre horizontally", "centred horizontally w.r.t."));
|
||||
|
||||
wxOGLConstraintTypes->Append(gyCONSTRAINT_CENTRED_BOTH,
|
||||
new wxOGLConstraintType(gyCONSTRAINT_CENTRED_BOTH, "Centre", "centred w.r.t."));
|
||||
|
||||
wxOGLConstraintTypes->Append(gyCONSTRAINT_LEFT_OF,
|
||||
new wxOGLConstraintType(gyCONSTRAINT_LEFT_OF, "Left of", "left of"));
|
||||
|
||||
wxOGLConstraintTypes->Append(gyCONSTRAINT_RIGHT_OF,
|
||||
new wxOGLConstraintType(gyCONSTRAINT_RIGHT_OF, "Right of", "right of"));
|
||||
|
||||
wxOGLConstraintTypes->Append(gyCONSTRAINT_ABOVE,
|
||||
new wxOGLConstraintType(gyCONSTRAINT_ABOVE, "Above", "above"));
|
||||
|
||||
wxOGLConstraintTypes->Append(gyCONSTRAINT_BELOW,
|
||||
new wxOGLConstraintType(gyCONSTRAINT_BELOW, "Below", "below"));
|
||||
|
||||
// Alignment
|
||||
wxOGLConstraintTypes->Append(gyCONSTRAINT_ALIGNED_TOP,
|
||||
new wxOGLConstraintType(gyCONSTRAINT_ALIGNED_TOP, "Top-aligned", "aligned to the top of"));
|
||||
|
||||
wxOGLConstraintTypes->Append(gyCONSTRAINT_ALIGNED_BOTTOM,
|
||||
new wxOGLConstraintType(gyCONSTRAINT_ALIGNED_BOTTOM, "Bottom-aligned", "aligned to the bottom of"));
|
||||
|
||||
wxOGLConstraintTypes->Append(gyCONSTRAINT_ALIGNED_LEFT,
|
||||
new wxOGLConstraintType(gyCONSTRAINT_ALIGNED_LEFT, "Left-aligned", "aligned to the left of"));
|
||||
|
||||
wxOGLConstraintTypes->Append(gyCONSTRAINT_ALIGNED_RIGHT,
|
||||
new wxOGLConstraintType(gyCONSTRAINT_ALIGNED_RIGHT, "Right-aligned", "aligned to the right of"));
|
||||
|
||||
// Mid-alignment
|
||||
wxOGLConstraintTypes->Append(gyCONSTRAINT_MIDALIGNED_TOP,
|
||||
new wxOGLConstraintType(gyCONSTRAINT_MIDALIGNED_TOP, "Top-midaligned", "centred on the top of"));
|
||||
|
||||
wxOGLConstraintTypes->Append(gyCONSTRAINT_MIDALIGNED_BOTTOM,
|
||||
new wxOGLConstraintType(gyCONSTRAINT_MIDALIGNED_BOTTOM, "Bottom-midaligned", "centred on the bottom of"));
|
||||
|
||||
wxOGLConstraintTypes->Append(gyCONSTRAINT_MIDALIGNED_LEFT,
|
||||
new wxOGLConstraintType(gyCONSTRAINT_MIDALIGNED_LEFT, "Left-midaligned", "centred on the left of"));
|
||||
|
||||
wxOGLConstraintTypes->Append(gyCONSTRAINT_MIDALIGNED_RIGHT,
|
||||
new wxOGLConstraintType(gyCONSTRAINT_MIDALIGNED_RIGHT, "Right-midaligned", "centred on the right of"));
|
||||
}
|
||||
|
||||
void OGLCleanUpConstraintTypes()
|
||||
{
|
||||
if (!wxOGLConstraintTypes)
|
||||
return;
|
||||
|
||||
wxNode* node = wxOGLConstraintTypes->First();
|
||||
while (node)
|
||||
{
|
||||
wxOGLConstraintType* ct = (wxOGLConstraintType*) node->Data();
|
||||
delete ct;
|
||||
node = node->Next();
|
||||
}
|
||||
delete wxOGLConstraintTypes;
|
||||
wxOGLConstraintTypes = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Constraint Stuff
|
||||
*
|
||||
*/
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxOGLConstraint, wxObject)
|
||||
|
||||
wxOGLConstraint::wxOGLConstraint(int type, wxShape *constraining, wxList& constrained)
|
||||
{
|
||||
m_xSpacing = 0.0;
|
||||
m_ySpacing = 0.0;
|
||||
|
||||
m_constraintType = type;
|
||||
m_constrainingObject = constraining;
|
||||
|
||||
m_constraintId = 0;
|
||||
m_constraintName = "noname";
|
||||
|
||||
wxNode *node = constrained.First();
|
||||
while (node)
|
||||
{
|
||||
m_constrainedObjects.Append(node->Data());
|
||||
node = node->Next();
|
||||
}
|
||||
}
|
||||
|
||||
wxOGLConstraint::~wxOGLConstraint()
|
||||
{
|
||||
}
|
||||
|
||||
bool wxOGLConstraint::Equals(double a, double b)
|
||||
{
|
||||
double marg = 0.5;
|
||||
|
||||
bool eq = ((b <= a + marg) && (b >= a - marg));
|
||||
return eq;
|
||||
}
|
||||
|
||||
// Return TRUE if anything changed
|
||||
bool wxOGLConstraint::Evaluate()
|
||||
{
|
||||
double maxWidth, maxHeight, minWidth, minHeight, x, y;
|
||||
m_constrainingObject->GetBoundingBoxMax(&maxWidth, &maxHeight);
|
||||
m_constrainingObject->GetBoundingBoxMin(&minWidth, &minHeight);
|
||||
x = m_constrainingObject->GetX();
|
||||
y = m_constrainingObject->GetY();
|
||||
|
||||
wxClientDC dc(m_constrainingObject->GetCanvas());
|
||||
m_constrainingObject->GetCanvas()->PrepareDC(dc);
|
||||
|
||||
switch (m_constraintType)
|
||||
{
|
||||
case gyCONSTRAINT_CENTRED_VERTICALLY:
|
||||
{
|
||||
int n = m_constrainedObjects.Number();
|
||||
double totalObjectHeight = 0.0;
|
||||
wxNode *node = m_constrainedObjects.First();
|
||||
while (node)
|
||||
{
|
||||
wxShape *constrainedObject = (wxShape *)node->Data();
|
||||
|
||||
double width2, height2;
|
||||
constrainedObject->GetBoundingBoxMax(&width2, &height2);
|
||||
totalObjectHeight += height2;
|
||||
node = node->Next();
|
||||
}
|
||||
double startY;
|
||||
double spacingY;
|
||||
// Check if within the constraining object...
|
||||
if ((totalObjectHeight + (n + 1)*m_ySpacing) <= minHeight)
|
||||
{
|
||||
spacingY = (double)((minHeight - totalObjectHeight)/(n + 1));
|
||||
startY = (double)(y - (minHeight/2.0));
|
||||
}
|
||||
// Otherwise, use default spacing
|
||||
else
|
||||
{
|
||||
spacingY = m_ySpacing;
|
||||
startY = (double)(y - ((totalObjectHeight + (n+1)*spacingY)/2.0));
|
||||
}
|
||||
|
||||
// Now position the objects
|
||||
bool changed = FALSE;
|
||||
node = m_constrainedObjects.First();
|
||||
while (node)
|
||||
{
|
||||
wxShape *constrainedObject = (wxShape *)node->Data();
|
||||
double width2, height2;
|
||||
constrainedObject->GetBoundingBoxMax(&width2, &height2);
|
||||
startY += (double)(spacingY + (height2/2.0));
|
||||
if (!Equals(startY, constrainedObject->GetY()))
|
||||
{
|
||||
constrainedObject->Move(dc, constrainedObject->GetX(), startY, FALSE);
|
||||
changed = TRUE;
|
||||
}
|
||||
startY += (double)(height2/2.0);
|
||||
node = node->Next();
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
case gyCONSTRAINT_CENTRED_HORIZONTALLY:
|
||||
{
|
||||
int n = m_constrainedObjects.Number();
|
||||
double totalObjectWidth = 0.0;
|
||||
wxNode *node = m_constrainedObjects.First();
|
||||
while (node)
|
||||
{
|
||||
wxShape *constrainedObject = (wxShape *)node->Data();
|
||||
|
||||
double width2, height2;
|
||||
constrainedObject->GetBoundingBoxMax(&width2, &height2);
|
||||
totalObjectWidth += width2;
|
||||
node = node->Next();
|
||||
}
|
||||
double startX;
|
||||
double spacingX;
|
||||
// Check if within the constraining object...
|
||||
if ((totalObjectWidth + (n + 1)*m_xSpacing) <= minWidth)
|
||||
{
|
||||
spacingX = (double)((minWidth - totalObjectWidth)/(n + 1));
|
||||
startX = (double)(x - (minWidth/2.0));
|
||||
}
|
||||
// Otherwise, use default spacing
|
||||
else
|
||||
{
|
||||
spacingX = m_xSpacing;
|
||||
startX = (double)(x - ((totalObjectWidth + (n+1)*spacingX)/2.0));
|
||||
}
|
||||
|
||||
// Now position the objects
|
||||
bool changed = FALSE;
|
||||
node = m_constrainedObjects.First();
|
||||
while (node)
|
||||
{
|
||||
wxShape *constrainedObject = (wxShape *)node->Data();
|
||||
double width2, height2;
|
||||
constrainedObject->GetBoundingBoxMax(&width2, &height2);
|
||||
startX += (double)(spacingX + (width2/2.0));
|
||||
if (!Equals(startX, constrainedObject->GetX()))
|
||||
{
|
||||
constrainedObject->Move(dc, startX, constrainedObject->GetY(), FALSE);
|
||||
changed = TRUE;
|
||||
}
|
||||
startX += (double)(width2/2.0);
|
||||
node = node->Next();
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
case gyCONSTRAINT_CENTRED_BOTH:
|
||||
{
|
||||
int n = m_constrainedObjects.Number();
|
||||
double totalObjectWidth = 0.0;
|
||||
double totalObjectHeight = 0.0;
|
||||
wxNode *node = m_constrainedObjects.First();
|
||||
while (node)
|
||||
{
|
||||
wxShape *constrainedObject = (wxShape *)node->Data();
|
||||
|
||||
double width2, height2;
|
||||
constrainedObject->GetBoundingBoxMax(&width2, &height2);
|
||||
totalObjectWidth += width2;
|
||||
totalObjectHeight += height2;
|
||||
node = node->Next();
|
||||
}
|
||||
double startX;
|
||||
double spacingX;
|
||||
double startY;
|
||||
double spacingY;
|
||||
|
||||
// Check if within the constraining object...
|
||||
if ((totalObjectWidth + (n + 1)*m_xSpacing) <= minWidth)
|
||||
{
|
||||
spacingX = (double)((minWidth - totalObjectWidth)/(n + 1));
|
||||
startX = (double)(x - (minWidth/2.0));
|
||||
}
|
||||
// Otherwise, use default spacing
|
||||
else
|
||||
{
|
||||
spacingX = m_xSpacing;
|
||||
startX = (double)(x - ((totalObjectWidth + (n+1)*spacingX)/2.0));
|
||||
}
|
||||
|
||||
// Check if within the constraining object...
|
||||
if ((totalObjectHeight + (n + 1)*m_ySpacing) <= minHeight)
|
||||
{
|
||||
spacingY = (double)((minHeight - totalObjectHeight)/(n + 1));
|
||||
startY = (double)(y - (minHeight/2.0));
|
||||
}
|
||||
// Otherwise, use default spacing
|
||||
else
|
||||
{
|
||||
spacingY = m_ySpacing;
|
||||
startY = (double)(y - ((totalObjectHeight + (n+1)*spacingY)/2.0));
|
||||
}
|
||||
|
||||
// Now position the objects
|
||||
bool changed = FALSE;
|
||||
node = m_constrainedObjects.First();
|
||||
while (node)
|
||||
{
|
||||
wxShape *constrainedObject = (wxShape *)node->Data();
|
||||
double width2, height2;
|
||||
constrainedObject->GetBoundingBoxMax(&width2, &height2);
|
||||
startX += (double)(spacingX + (width2/2.0));
|
||||
startY += (double)(spacingY + (height2/2.0));
|
||||
|
||||
if ((!Equals(startX, constrainedObject->GetX())) || (!Equals(startY, constrainedObject->GetY())))
|
||||
{
|
||||
constrainedObject->Move(dc, startX, startY, FALSE);
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
startX += (double)(width2/2.0);
|
||||
startY += (double)(height2/2.0);
|
||||
|
||||
node = node->Next();
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
case gyCONSTRAINT_LEFT_OF:
|
||||
{
|
||||
bool changed = FALSE;
|
||||
|
||||
wxNode *node = m_constrainedObjects.First();
|
||||
while (node)
|
||||
{
|
||||
wxShape *constrainedObject = (wxShape *)node->Data();
|
||||
|
||||
double width2, height2;
|
||||
constrainedObject->GetBoundingBoxMax(&width2, &height2);
|
||||
|
||||
double x3 = (double)(x - (minWidth/2.0) - (width2/2.0) - m_xSpacing);
|
||||
if (!Equals(x3, constrainedObject->GetX()))
|
||||
{
|
||||
changed = TRUE;
|
||||
constrainedObject->Move(dc, x3, constrainedObject->GetY(), FALSE);
|
||||
}
|
||||
|
||||
node = node->Next();
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
case gyCONSTRAINT_RIGHT_OF:
|
||||
{
|
||||
bool changed = FALSE;
|
||||
|
||||
wxNode *node = m_constrainedObjects.First();
|
||||
while (node)
|
||||
{
|
||||
wxShape *constrainedObject = (wxShape *)node->Data();
|
||||
|
||||
double width2, height2;
|
||||
constrainedObject->GetBoundingBoxMax(&width2, &height2);
|
||||
|
||||
double x3 = (double)(x + (minWidth/2.0) + (width2/2.0) + m_xSpacing);
|
||||
if (!Equals(x3, constrainedObject->GetX()))
|
||||
{
|
||||
changed = TRUE;
|
||||
constrainedObject->Move(dc, x3, constrainedObject->GetY(), FALSE);
|
||||
}
|
||||
|
||||
node = node->Next();
|
||||
}
|
||||
return changed;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
case gyCONSTRAINT_ABOVE:
|
||||
{
|
||||
bool changed = FALSE;
|
||||
|
||||
wxNode *node = m_constrainedObjects.First();
|
||||
while (node)
|
||||
{
|
||||
wxShape *constrainedObject = (wxShape *)node->Data();
|
||||
|
||||
double width2, height2;
|
||||
constrainedObject->GetBoundingBoxMax(&width2, &height2);
|
||||
|
||||
double y3 = (double)(y - (minHeight/2.0) - (height2/2.0) - m_ySpacing);
|
||||
if (!Equals(y3, constrainedObject->GetY()))
|
||||
{
|
||||
changed = TRUE;
|
||||
constrainedObject->Move(dc, constrainedObject->GetX(), y3, FALSE);
|
||||
}
|
||||
|
||||
node = node->Next();
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
case gyCONSTRAINT_BELOW:
|
||||
{
|
||||
bool changed = FALSE;
|
||||
|
||||
wxNode *node = m_constrainedObjects.First();
|
||||
while (node)
|
||||
{
|
||||
wxShape *constrainedObject = (wxShape *)node->Data();
|
||||
|
||||
double width2, height2;
|
||||
constrainedObject->GetBoundingBoxMax(&width2, &height2);
|
||||
|
||||
double y3 = (double)(y + (minHeight/2.0) + (height2/2.0) + m_ySpacing);
|
||||
if (!Equals(y3, constrainedObject->GetY()))
|
||||
{
|
||||
changed = TRUE;
|
||||
constrainedObject->Move(dc, constrainedObject->GetX(), y3, FALSE);
|
||||
}
|
||||
|
||||
node = node->Next();
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
case gyCONSTRAINT_ALIGNED_LEFT:
|
||||
{
|
||||
bool changed = FALSE;
|
||||
|
||||
wxNode *node = m_constrainedObjects.First();
|
||||
while (node)
|
||||
{
|
||||
wxShape *constrainedObject = (wxShape *)node->Data();
|
||||
|
||||
double width2, height2;
|
||||
constrainedObject->GetBoundingBoxMax(&width2, &height2);
|
||||
|
||||
double x3 = (double)(x - (minWidth/2.0) + (width2/2.0) + m_xSpacing);
|
||||
if (!Equals(x3, constrainedObject->GetX()))
|
||||
{
|
||||
changed = TRUE;
|
||||
constrainedObject->Move(dc, x3, constrainedObject->GetY(), FALSE);
|
||||
}
|
||||
|
||||
node = node->Next();
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
case gyCONSTRAINT_ALIGNED_RIGHT:
|
||||
{
|
||||
bool changed = FALSE;
|
||||
|
||||
wxNode *node = m_constrainedObjects.First();
|
||||
while (node)
|
||||
{
|
||||
wxShape *constrainedObject = (wxShape *)node->Data();
|
||||
|
||||
double width2, height2;
|
||||
constrainedObject->GetBoundingBoxMax(&width2, &height2);
|
||||
|
||||
double x3 = (double)(x + (minWidth/2.0) - (width2/2.0) - m_xSpacing);
|
||||
if (!Equals(x3, constrainedObject->GetX()))
|
||||
{
|
||||
changed = TRUE;
|
||||
constrainedObject->Move(dc, x3, constrainedObject->GetY(), FALSE);
|
||||
}
|
||||
|
||||
node = node->Next();
|
||||
}
|
||||
return changed;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
case gyCONSTRAINT_ALIGNED_TOP:
|
||||
{
|
||||
bool changed = FALSE;
|
||||
|
||||
wxNode *node = m_constrainedObjects.First();
|
||||
while (node)
|
||||
{
|
||||
wxShape *constrainedObject = (wxShape *)node->Data();
|
||||
|
||||
double width2, height2;
|
||||
constrainedObject->GetBoundingBoxMax(&width2, &height2);
|
||||
|
||||
double y3 = (double)(y - (minHeight/2.0) + (height2/2.0) + m_ySpacing);
|
||||
if (!Equals(y3, constrainedObject->GetY()))
|
||||
{
|
||||
changed = TRUE;
|
||||
constrainedObject->Move(dc, constrainedObject->GetX(), y3, FALSE);
|
||||
}
|
||||
|
||||
node = node->Next();
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
case gyCONSTRAINT_ALIGNED_BOTTOM:
|
||||
{
|
||||
bool changed = FALSE;
|
||||
|
||||
wxNode *node = m_constrainedObjects.First();
|
||||
while (node)
|
||||
{
|
||||
wxShape *constrainedObject = (wxShape *)node->Data();
|
||||
|
||||
double width2, height2;
|
||||
constrainedObject->GetBoundingBoxMax(&width2, &height2);
|
||||
|
||||
double y3 = (double)(y + (minHeight/2.0) - (height2/2.0) - m_ySpacing);
|
||||
if (!Equals(y3, constrainedObject->GetY()))
|
||||
{
|
||||
changed = TRUE;
|
||||
constrainedObject->Move(dc, constrainedObject->GetX(), y3, FALSE);
|
||||
}
|
||||
|
||||
node = node->Next();
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
case gyCONSTRAINT_MIDALIGNED_LEFT:
|
||||
{
|
||||
bool changed = FALSE;
|
||||
|
||||
wxNode *node = m_constrainedObjects.First();
|
||||
while (node)
|
||||
{
|
||||
wxShape *constrainedObject = (wxShape *)node->Data();
|
||||
|
||||
double x3 = (double)(x - (minWidth/2.0));
|
||||
if (!Equals(x3, constrainedObject->GetX()))
|
||||
{
|
||||
changed = TRUE;
|
||||
constrainedObject->Move(dc, x3, constrainedObject->GetY(), FALSE);
|
||||
}
|
||||
|
||||
node = node->Next();
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
case gyCONSTRAINT_MIDALIGNED_RIGHT:
|
||||
{
|
||||
bool changed = FALSE;
|
||||
|
||||
wxNode *node = m_constrainedObjects.First();
|
||||
while (node)
|
||||
{
|
||||
wxShape *constrainedObject = (wxShape *)node->Data();
|
||||
|
||||
double x3 = (double)(x + (minWidth/2.0));
|
||||
if (!Equals(x3, constrainedObject->GetX()))
|
||||
{
|
||||
changed = TRUE;
|
||||
constrainedObject->Move(dc, x3, constrainedObject->GetY(), FALSE);
|
||||
}
|
||||
|
||||
node = node->Next();
|
||||
}
|
||||
return changed;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
case gyCONSTRAINT_MIDALIGNED_TOP:
|
||||
{
|
||||
bool changed = FALSE;
|
||||
|
||||
wxNode *node = m_constrainedObjects.First();
|
||||
while (node)
|
||||
{
|
||||
wxShape *constrainedObject = (wxShape *)node->Data();
|
||||
|
||||
double y3 = (double)(y - (minHeight/2.0));
|
||||
if (!Equals(y3, constrainedObject->GetY()))
|
||||
{
|
||||
changed = TRUE;
|
||||
constrainedObject->Move(dc, constrainedObject->GetX(), y3, FALSE);
|
||||
}
|
||||
|
||||
node = node->Next();
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
case gyCONSTRAINT_MIDALIGNED_BOTTOM:
|
||||
{
|
||||
bool changed = FALSE;
|
||||
|
||||
wxNode *node = m_constrainedObjects.First();
|
||||
while (node)
|
||||
{
|
||||
wxShape *constrainedObject = (wxShape *)node->Data();
|
||||
|
||||
double y3 = (double)(y + (minHeight/2.0));
|
||||
if (!Equals(y3, constrainedObject->GetY()))
|
||||
{
|
||||
changed = TRUE;
|
||||
constrainedObject->Move(dc, constrainedObject->GetX(), y3, FALSE);
|
||||
}
|
||||
|
||||
node = node->Next();
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
720
contrib/src/ogl/divided.cpp
Normal file
720
contrib/src/ogl/divided.cpp
Normal file
@@ -0,0 +1,720 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: divided.cpp
|
||||
// Purpose: wxDividedShape class
|
||||
// Author: Julian Smart
|
||||
// Modified by:
|
||||
// Created: 12/07/98
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) Julian Smart
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "divided.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>
|
||||
|
||||
#include <wx/ogl/basic.h>
|
||||
#include <wx/ogl/basicp.h>
|
||||
#include <wx/ogl/canvas.h>
|
||||
#include <wx/ogl/divided.h>
|
||||
#include <wx/ogl/lines.h>
|
||||
#include <wx/ogl/misc.h>
|
||||
|
||||
class wxDividedShapeControlPoint: public wxControlPoint
|
||||
{
|
||||
DECLARE_DYNAMIC_CLASS(wxDividedShapeControlPoint)
|
||||
private:
|
||||
int regionId;
|
||||
public:
|
||||
wxDividedShapeControlPoint() { regionId = 0; }
|
||||
wxDividedShapeControlPoint(wxShapeCanvas *the_canvas, wxShape *object, int region,
|
||||
double size, double the_xoffset, double the_yoffset, int the_type);
|
||||
~wxDividedShapeControlPoint();
|
||||
|
||||
void OnDragLeft(bool draw, double x, double y, int keys=0, int attachment = 0);
|
||||
void OnBeginDragLeft(double x, double y, int keys=0, int attachment = 0);
|
||||
void OnEndDragLeft(double x, double y, int keys=0, int attachment = 0);
|
||||
};
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxDividedShapeControlPoint, wxControlPoint)
|
||||
|
||||
/*
|
||||
* Divided object
|
||||
*
|
||||
*/
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxDividedShape, wxRectangleShape)
|
||||
|
||||
wxDividedShape::wxDividedShape(double w, double h): wxRectangleShape(w, h)
|
||||
{
|
||||
ClearRegions();
|
||||
}
|
||||
|
||||
wxDividedShape::~wxDividedShape()
|
||||
{
|
||||
}
|
||||
|
||||
void wxDividedShape::OnDraw(wxDC& dc)
|
||||
{
|
||||
wxRectangleShape::OnDraw(dc);
|
||||
}
|
||||
|
||||
void wxDividedShape::OnDrawContents(wxDC& dc)
|
||||
{
|
||||
double defaultProportion = (double)(GetRegions().Number() > 0 ? (1.0/((double)(GetRegions().Number()))) : 0.0);
|
||||
double currentY = (double)(m_ypos - (m_height / 2.0));
|
||||
double maxY = (double)(m_ypos + (m_height / 2.0));
|
||||
|
||||
double leftX = (double)(m_xpos - (m_width / 2.0));
|
||||
double rightX = (double)(m_xpos + (m_width / 2.0));
|
||||
|
||||
if (m_pen) dc.SetPen(* m_pen);
|
||||
|
||||
if (m_textColour) dc.SetTextForeground(* m_textColour);
|
||||
|
||||
#ifdef __WXMSW__
|
||||
// For efficiency, don't do this under X - doesn't make
|
||||
// any visible difference for our purposes.
|
||||
if (m_brush)
|
||||
dc.SetTextBackground(m_brush->GetColour());
|
||||
#endif
|
||||
/*
|
||||
if (!formatted)
|
||||
{
|
||||
FormatRegionText();
|
||||
formatted = TRUE;
|
||||
}
|
||||
*/
|
||||
if (GetDisableLabel()) return;
|
||||
|
||||
double xMargin = 2;
|
||||
double yMargin = 2;
|
||||
dc.SetBackgroundMode(wxTRANSPARENT);
|
||||
|
||||
wxNode *node = GetRegions().First();
|
||||
while (node)
|
||||
{
|
||||
wxShapeRegion *region = (wxShapeRegion *)node->Data();
|
||||
dc.SetFont(* region->GetFont());
|
||||
dc.SetTextForeground(* region->GetActualColourObject());
|
||||
|
||||
double proportion =
|
||||
region->m_regionProportionY < 0.0 ? defaultProportion : region->m_regionProportionY;
|
||||
|
||||
double y = currentY + m_height*proportion;
|
||||
double actualY = maxY < y ? maxY : y;
|
||||
|
||||
double centreX = m_xpos;
|
||||
double centreY = (double)(currentY + (actualY - currentY)/2.0);
|
||||
|
||||
oglDrawFormattedText(dc, ®ion->m_formattedText,
|
||||
(double)(centreX), (double)(centreY), (double)(m_width-2*xMargin), (double)(actualY - currentY - 2*yMargin),
|
||||
region->m_formatMode);
|
||||
if ((y <= maxY) && (node->Next()))
|
||||
{
|
||||
wxPen *regionPen = region->GetActualPen();
|
||||
if (regionPen)
|
||||
{
|
||||
dc.SetPen(* regionPen);
|
||||
dc.DrawLine(WXROUND(leftX), WXROUND(y), WXROUND(rightX), WXROUND(y));
|
||||
}
|
||||
}
|
||||
|
||||
currentY = actualY;
|
||||
|
||||
node = node->Next();
|
||||
}
|
||||
}
|
||||
|
||||
void wxDividedShape::SetSize(double w, double h, bool recursive)
|
||||
{
|
||||
SetAttachmentSize(w, h);
|
||||
m_width = w;
|
||||
m_height = h;
|
||||
SetRegionSizes();
|
||||
}
|
||||
|
||||
void wxDividedShape::SetRegionSizes()
|
||||
{
|
||||
if (GetRegions().Number() == 0)
|
||||
return;
|
||||
|
||||
double defaultProportion = (double)(GetRegions().Number() > 0 ? (1.0/((double)(GetRegions().Number()))) : 0.0);
|
||||
double currentY = (double)(m_ypos - (m_height / 2.0));
|
||||
double maxY = (double)(m_ypos + (m_height / 2.0));
|
||||
|
||||
// double leftX = (double)(m_xpos - (m_width / 2.0));
|
||||
// double rightX = (double)(m_xpos + (m_width / 2.0));
|
||||
|
||||
wxNode *node = GetRegions().First();
|
||||
while (node)
|
||||
{
|
||||
wxShapeRegion *region = (wxShapeRegion *)node->Data();
|
||||
double proportion =
|
||||
region->m_regionProportionY <= 0.0 ? defaultProportion : region->m_regionProportionY;
|
||||
|
||||
double sizeY = (double)proportion*m_height;
|
||||
double y = currentY + sizeY;
|
||||
double actualY = maxY < y ? maxY : y;
|
||||
|
||||
double centreY = (double)(currentY + (actualY - currentY)/2.0);
|
||||
|
||||
region->SetSize(m_width, sizeY);
|
||||
region->SetPosition(0.0, (double)(centreY - m_ypos));
|
||||
currentY = actualY;
|
||||
node = node->Next();
|
||||
}
|
||||
}
|
||||
|
||||
// Attachment points correspond to regions in the divided box
|
||||
bool wxDividedShape::GetAttachmentPosition(int attachment, double *x, double *y, int nth, int no_arcs,
|
||||
wxLineShape *line)
|
||||
{
|
||||
int totalNumberAttachments = (GetRegions().Number() * 2) + 2;
|
||||
if ((GetAttachmentMode() == ATTACHMENT_MODE_NONE) || (attachment >= totalNumberAttachments))
|
||||
{
|
||||
return wxShape::GetAttachmentPosition(attachment, x, y, nth, no_arcs);
|
||||
}
|
||||
|
||||
int n = GetRegions().Number();
|
||||
bool isEnd = (line && line->IsEnd(this));
|
||||
|
||||
double left = (double)(m_xpos - m_width/2.0);
|
||||
double right = (double)(m_xpos + m_width/2.0);
|
||||
double top = (double)(m_ypos - m_height/2.0);
|
||||
double bottom = (double)(m_ypos + m_height/2.0);
|
||||
|
||||
// Zero is top, n+1 is bottom.
|
||||
if (attachment == 0)
|
||||
{
|
||||
*y = top;
|
||||
if (m_spaceAttachments)
|
||||
{
|
||||
if (line && (line->GetAlignmentType(isEnd) == LINE_ALIGNMENT_TO_NEXT_HANDLE))
|
||||
{
|
||||
// Align line according to the next handle along
|
||||
wxRealPoint *point = line->GetNextControlPoint(this);
|
||||
if (point->x < left)
|
||||
*x = left;
|
||||
else if (point->x > right)
|
||||
*x = right;
|
||||
else
|
||||
*x = point->x;
|
||||
}
|
||||
else
|
||||
*x = left + (nth + 1)*m_width/(no_arcs + 1);
|
||||
}
|
||||
else
|
||||
*x = m_xpos;
|
||||
}
|
||||
else if (attachment == (n+1))
|
||||
{
|
||||
*y = bottom;
|
||||
if (m_spaceAttachments)
|
||||
{
|
||||
if (line && (line->GetAlignmentType(isEnd) == LINE_ALIGNMENT_TO_NEXT_HANDLE))
|
||||
{
|
||||
// Align line according to the next handle along
|
||||
wxRealPoint *point = line->GetNextControlPoint(this);
|
||||
if (point->x < left)
|
||||
*x = left;
|
||||
else if (point->x > right)
|
||||
*x = right;
|
||||
else
|
||||
*x = point->x;
|
||||
}
|
||||
else
|
||||
*x = left + (nth + 1)*m_width/(no_arcs + 1);
|
||||
}
|
||||
else
|
||||
*x = m_xpos;
|
||||
}
|
||||
// Left or right.
|
||||
else
|
||||
{
|
||||
int i = 0;
|
||||
bool isLeft = FALSE;
|
||||
if (attachment < (n+1))
|
||||
{
|
||||
i = attachment-1;
|
||||
isLeft = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
i = (totalNumberAttachments - attachment - 1);
|
||||
isLeft = TRUE;
|
||||
}
|
||||
wxNode *node = GetRegions().Nth(i);
|
||||
if (node)
|
||||
{
|
||||
wxShapeRegion *region = (wxShapeRegion *)node->Data();
|
||||
|
||||
if (isLeft)
|
||||
*x = left;
|
||||
else
|
||||
*x = right;
|
||||
|
||||
// Calculate top and bottom of region
|
||||
top = (double)((m_ypos + region->m_y) - (region->m_height/2.0));
|
||||
bottom = (double)((m_ypos + region->m_y) + (region->m_height/2.0));
|
||||
|
||||
// Assuming we can trust the absolute size and
|
||||
// position of these regions...
|
||||
if (m_spaceAttachments)
|
||||
{
|
||||
if (line && (line->GetAlignmentType(isEnd) == LINE_ALIGNMENT_TO_NEXT_HANDLE))
|
||||
{
|
||||
// Align line according to the next handle along
|
||||
wxRealPoint *point = line->GetNextControlPoint(this);
|
||||
if (point->y < bottom)
|
||||
*y = bottom;
|
||||
else if (point->y > top)
|
||||
*y = top;
|
||||
else
|
||||
*y = point->y;
|
||||
}
|
||||
else
|
||||
// *y = (double)(((m_ypos + region->m_y) - (region->m_height/2.0)) + (nth + 1)*region->m_height/(no_arcs+1));
|
||||
*y = (double)(top + (nth + 1)*region->m_height/(no_arcs+1));
|
||||
}
|
||||
else
|
||||
*y = (double)(m_ypos + region->m_y);
|
||||
}
|
||||
else
|
||||
{
|
||||
*x = m_xpos;
|
||||
*y = m_ypos;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int wxDividedShape::GetNumberOfAttachments() const
|
||||
{
|
||||
// There are two attachments for each region (left and right),
|
||||
// plus one on the top and one on the bottom.
|
||||
int n = (GetRegions().Number() * 2) + 2;
|
||||
|
||||
int maxN = n - 1;
|
||||
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 wxDividedShape::AttachmentIsValid(int attachment)
|
||||
{
|
||||
int totalNumberAttachments = (GetRegions().Number() * 2) + 2;
|
||||
if (attachment >= totalNumberAttachments)
|
||||
{
|
||||
return wxShape::AttachmentIsValid(attachment);
|
||||
}
|
||||
else if (attachment >= 0)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void wxDividedShape::Copy(wxShape& copy)
|
||||
{
|
||||
wxRectangleShape::Copy(copy);
|
||||
}
|
||||
|
||||
// Region operations
|
||||
|
||||
void wxDividedShape::MakeControlPoints()
|
||||
{
|
||||
wxRectangleShape::MakeControlPoints();
|
||||
|
||||
MakeMandatoryControlPoints();
|
||||
}
|
||||
|
||||
void wxDividedShape::MakeMandatoryControlPoints()
|
||||
{
|
||||
double currentY = (double)(GetY() - (m_height / 2.0));
|
||||
double maxY = (double)(GetY() + (m_height / 2.0));
|
||||
|
||||
wxNode *node = GetRegions().First();
|
||||
int i = 0;
|
||||
while (node)
|
||||
{
|
||||
wxShapeRegion *region = (wxShapeRegion *)node->Data();
|
||||
|
||||
double proportion = region->m_regionProportionY;
|
||||
|
||||
double y = currentY + m_height*proportion;
|
||||
double actualY = (double)(maxY < y ? maxY : y);
|
||||
|
||||
if (node->Next())
|
||||
{
|
||||
wxDividedShapeControlPoint *controlPoint =
|
||||
new wxDividedShapeControlPoint(m_canvas, this, i, CONTROL_POINT_SIZE, 0.0, (double)(actualY - GetY()), 0);
|
||||
m_canvas->AddShape(controlPoint);
|
||||
m_controlPoints.Append(controlPoint);
|
||||
}
|
||||
currentY = actualY;
|
||||
i ++;
|
||||
node = node->Next();
|
||||
}
|
||||
}
|
||||
|
||||
void wxDividedShape::ResetControlPoints()
|
||||
{
|
||||
// May only have the region handles, (n - 1) of them.
|
||||
if (m_controlPoints.Number() > (GetRegions().Number() - 1))
|
||||
wxRectangleShape::ResetControlPoints();
|
||||
|
||||
ResetMandatoryControlPoints();
|
||||
}
|
||||
|
||||
void wxDividedShape::ResetMandatoryControlPoints()
|
||||
{
|
||||
double currentY = (double)(GetY() - (m_height / 2.0));
|
||||
double maxY = (double)(GetY() + (m_height / 2.0));
|
||||
|
||||
wxNode *node = m_controlPoints.First();
|
||||
int i = 0;
|
||||
while (node)
|
||||
{
|
||||
wxControlPoint *controlPoint = (wxControlPoint *)node->Data();
|
||||
if (controlPoint->IsKindOf(CLASSINFO(wxDividedShapeControlPoint)))
|
||||
{
|
||||
wxNode *node1 = GetRegions().Nth(i);
|
||||
wxShapeRegion *region = (wxShapeRegion *)node1->Data();
|
||||
|
||||
double proportion = region->m_regionProportionY;
|
||||
|
||||
double y = currentY + m_height*proportion;
|
||||
double actualY = (double)(maxY < y ? maxY : y);
|
||||
|
||||
controlPoint->m_xoffset = 0.0;
|
||||
controlPoint->m_yoffset = (double)(actualY - GetY());
|
||||
currentY = actualY;
|
||||
i ++;
|
||||
}
|
||||
node = node->Next();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PROLOGIO
|
||||
void wxDividedShape::WriteAttributes(wxExpr *clause)
|
||||
{
|
||||
wxRectangleShape::WriteAttributes(clause);
|
||||
}
|
||||
|
||||
void wxDividedShape::ReadAttributes(wxExpr *clause)
|
||||
{
|
||||
wxRectangleShape::ReadAttributes(clause);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Edit the division colour/style
|
||||
*
|
||||
*/
|
||||
|
||||
void wxDividedShape::EditRegions()
|
||||
{
|
||||
wxMessageBox("EditRegions() is unimplemented.", "OGL", wxOK);
|
||||
|
||||
// TODO
|
||||
#if 0
|
||||
if (GetRegions().Number() < 2)
|
||||
return;
|
||||
|
||||
wxBeginBusyCursor();
|
||||
|
||||
GraphicsForm *form = new GraphicsForm("Divided nodes");
|
||||
// Need an array to store all the style strings,
|
||||
// since they need to be converted to integers
|
||||
char **styleStrings = new char *[GetRegions().Number()];
|
||||
for (int j = 0; j < GetRegions().Number(); j++)
|
||||
styleStrings[j] = NULL;
|
||||
|
||||
int i = 0;
|
||||
wxNode *node = GetRegions().First();
|
||||
while (node && node->Next())
|
||||
{
|
||||
wxShapeRegion *region = (wxShapeRegion *)node->Data();
|
||||
char buf[50];
|
||||
sprintf(buf, "Region %d", (i+1));
|
||||
form->Add(wxMakeFormMessage(buf));
|
||||
form->Add(wxMakeFormNewLine());
|
||||
|
||||
form->Add(wxMakeFormString("Colour", ®ion->penColour, wxFORM_CHOICE,
|
||||
new wxList(wxMakeConstraintStrings(
|
||||
"Invisible" ,
|
||||
"BLACK" ,
|
||||
"BLUE" ,
|
||||
"BROWN" ,
|
||||
"CORAL" ,
|
||||
"CYAN" ,
|
||||
"DARK GREY" ,
|
||||
"DARK GREEN" ,
|
||||
"DIM GREY" ,
|
||||
"GREY" ,
|
||||
"GREEN" ,
|
||||
"LIGHT BLUE" ,
|
||||
"LIGHT GREY" ,
|
||||
"MAGENTA" ,
|
||||
"MAROON" ,
|
||||
"NAVY" ,
|
||||
"ORANGE" ,
|
||||
"PURPLE" ,
|
||||
"RED" ,
|
||||
"TURQUOISE" ,
|
||||
"VIOLET" ,
|
||||
"WHITE" ,
|
||||
"YELLOW" ,
|
||||
NULL),
|
||||
NULL), NULL, wxVERTICAL, 150));
|
||||
|
||||
char *styleString = NULL;
|
||||
switch (region->penStyle)
|
||||
{
|
||||
case wxSHORT_DASH:
|
||||
styleString = "Short Dash";
|
||||
break;
|
||||
case wxLONG_DASH:
|
||||
styleString = "Long Dash";
|
||||
break;
|
||||
case wxDOT:
|
||||
styleString = "Dot";
|
||||
break;
|
||||
case wxDOT_DASH:
|
||||
styleString = "Dot Dash";
|
||||
break;
|
||||
case wxSOLID:
|
||||
default:
|
||||
styleString = "Solid";
|
||||
break;
|
||||
}
|
||||
styleStrings[i] = copystring(styleString);
|
||||
form->Add(wxMakeFormString("Style", &(styleStrings[i]), wxFORM_CHOICE,
|
||||
new wxList(wxMakeConstraintStrings(
|
||||
"Solid" ,
|
||||
"Short Dash" ,
|
||||
"Long Dash" ,
|
||||
"Dot" ,
|
||||
"Dot Dash" ,
|
||||
NULL),
|
||||
NULL), NULL, wxVERTICAL, 100));
|
||||
node = node->Next();
|
||||
i ++;
|
||||
if (node && node->Next())
|
||||
form->Add(wxMakeFormNewLine());
|
||||
}
|
||||
wxDialogBox *dialog = new wxDialogBox(m_canvas->GetParent(), "Divided object properties", 10, 10, 500, 500);
|
||||
if (GraphicsLabelFont)
|
||||
dialog->SetLabelFont(GraphicsLabelFont);
|
||||
if (GraphicsButtonFont)
|
||||
dialog->SetButtonFont(GraphicsButtonFont);
|
||||
form->AssociatePanel(dialog);
|
||||
form->dialog = dialog;
|
||||
|
||||
dialog->Fit();
|
||||
dialog->Centre(wxBOTH);
|
||||
|
||||
wxEndBusyCursor();
|
||||
|
||||
dialog->Show(TRUE);
|
||||
|
||||
node = GetRegions().First();
|
||||
i = 0;
|
||||
while (node)
|
||||
{
|
||||
wxShapeRegion *region = (wxShapeRegion *)node->Data();
|
||||
|
||||
if (styleStrings[i])
|
||||
{
|
||||
if (strcmp(styleStrings[i], "Solid") == 0)
|
||||
region->penStyle = wxSOLID;
|
||||
else if (strcmp(styleStrings[i], "Dot") == 0)
|
||||
region->penStyle = wxDOT;
|
||||
else if (strcmp(styleStrings[i], "Short Dash") == 0)
|
||||
region->penStyle = wxSHORT_DASH;
|
||||
else if (strcmp(styleStrings[i], "Long Dash") == 0)
|
||||
region->penStyle = wxLONG_DASH;
|
||||
else if (strcmp(styleStrings[i], "Dot Dash") == 0)
|
||||
region->penStyle = wxDOT_DASH;
|
||||
delete[] styleStrings[i];
|
||||
}
|
||||
region->m_actualPenObject = NULL;
|
||||
node = node->Next();
|
||||
i ++;
|
||||
}
|
||||
delete[] styleStrings;
|
||||
Draw(dc);
|
||||
#endif
|
||||
}
|
||||
|
||||
void wxDividedShape::OnRightClick(double x, double y, int keys, int attachment)
|
||||
{
|
||||
if (keys & KEY_CTRL)
|
||||
{
|
||||
EditRegions();
|
||||
}
|
||||
else
|
||||
{
|
||||
wxRectangleShape::OnRightClick(x, y, keys, attachment);
|
||||
}
|
||||
}
|
||||
|
||||
wxDividedShapeControlPoint::wxDividedShapeControlPoint(wxShapeCanvas *the_canvas, wxShape *object,
|
||||
int region, double size, double the_m_xoffset, double the_m_yoffset, int the_type):
|
||||
wxControlPoint(the_canvas, object, size, the_m_xoffset, the_m_yoffset, the_type)
|
||||
{
|
||||
regionId = region;
|
||||
}
|
||||
|
||||
wxDividedShapeControlPoint::~wxDividedShapeControlPoint()
|
||||
{
|
||||
}
|
||||
|
||||
// Implement resizing of divided object division
|
||||
void wxDividedShapeControlPoint::OnDragLeft(bool draw, double x, double y, int keys, int attachment)
|
||||
{
|
||||
wxClientDC dc(GetCanvas());
|
||||
GetCanvas()->PrepareDC(dc);
|
||||
|
||||
dc.SetLogicalFunction(OGLRBLF);
|
||||
wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
|
||||
dc.SetPen(dottedPen);
|
||||
dc.SetBrush((* wxTRANSPARENT_BRUSH));
|
||||
|
||||
wxDividedShape *dividedObject = (wxDividedShape *)m_shape;
|
||||
double x1 = (double)(dividedObject->GetX() - (dividedObject->GetWidth()/2.0));
|
||||
double y1 = y;
|
||||
double x2 = (double)(dividedObject->GetX() + (dividedObject->GetWidth()/2.0));
|
||||
double y2 = y;
|
||||
dc.DrawLine(WXROUND(x1), WXROUND(y1), WXROUND(x2), WXROUND(y2));
|
||||
}
|
||||
|
||||
void wxDividedShapeControlPoint::OnBeginDragLeft(double x, double y, int keys, int attachment)
|
||||
{
|
||||
wxClientDC dc(GetCanvas());
|
||||
GetCanvas()->PrepareDC(dc);
|
||||
|
||||
wxDividedShape *dividedObject = (wxDividedShape *)m_shape;
|
||||
dc.SetLogicalFunction(OGLRBLF);
|
||||
wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
|
||||
dc.SetPen(dottedPen);
|
||||
dc.SetBrush((* wxTRANSPARENT_BRUSH));
|
||||
|
||||
double x1 = (double)(dividedObject->GetX() - (dividedObject->GetWidth()/2.0));
|
||||
double y1 = y;
|
||||
double x2 = (double)(dividedObject->GetX() + (dividedObject->GetWidth()/2.0));
|
||||
double y2 = y;
|
||||
dc.DrawLine(WXROUND(x1), WXROUND(y1), WXROUND(x2), WXROUND(y2));
|
||||
m_canvas->CaptureMouse();
|
||||
}
|
||||
|
||||
void wxDividedShapeControlPoint::OnEndDragLeft(double x, double y, int keys, int attachment)
|
||||
{
|
||||
wxClientDC dc(GetCanvas());
|
||||
GetCanvas()->PrepareDC(dc);
|
||||
|
||||
wxDividedShape *dividedObject = (wxDividedShape *)m_shape;
|
||||
wxNode *node = dividedObject->GetRegions().Nth(regionId);
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
wxShapeRegion *thisRegion = (wxShapeRegion *)node->Data();
|
||||
wxShapeRegion *nextRegion = NULL; // Region below this one
|
||||
|
||||
dc.SetLogicalFunction(wxCOPY);
|
||||
|
||||
m_canvas->ReleaseMouse();
|
||||
|
||||
// Find the old top and bottom of this region,
|
||||
// and calculate the new proportion for this region
|
||||
// if legal.
|
||||
|
||||
double currentY = (double)(dividedObject->GetY() - (dividedObject->GetHeight() / 2.0));
|
||||
double maxY = (double)(dividedObject->GetY() + (dividedObject->GetHeight() / 2.0));
|
||||
|
||||
// Save values
|
||||
double thisRegionTop = 0.0;
|
||||
double thisRegionBottom = 0.0;
|
||||
double nextRegionBottom = 0.0;
|
||||
|
||||
node = dividedObject->GetRegions().First();
|
||||
while (node)
|
||||
{
|
||||
wxShapeRegion *region = (wxShapeRegion *)node->Data();
|
||||
|
||||
double proportion = region->m_regionProportionY;
|
||||
double yy = currentY + (dividedObject->GetHeight()*proportion);
|
||||
double actualY = (double)(maxY < yy ? maxY : yy);
|
||||
|
||||
if (region == thisRegion)
|
||||
{
|
||||
thisRegionTop = currentY;
|
||||
thisRegionBottom = actualY;
|
||||
if (node->Next())
|
||||
nextRegion = (wxShapeRegion *)node->Next()->Data();
|
||||
}
|
||||
if (region == nextRegion)
|
||||
{
|
||||
nextRegionBottom = actualY;
|
||||
}
|
||||
|
||||
currentY = actualY;
|
||||
node = node->Next();
|
||||
}
|
||||
if (!nextRegion)
|
||||
return;
|
||||
|
||||
// Check that we haven't gone above this region or below
|
||||
// next region.
|
||||
if ((y <= thisRegionTop) || (y >= nextRegionBottom))
|
||||
return;
|
||||
|
||||
dividedObject->EraseLinks(dc);
|
||||
|
||||
// Now calculate the new proportions of this region and the next region.
|
||||
double thisProportion = (double)((y - thisRegionTop)/dividedObject->GetHeight());
|
||||
double nextProportion = (double)((nextRegionBottom - y)/dividedObject->GetHeight());
|
||||
thisRegion->SetProportions(0.0, thisProportion);
|
||||
nextRegion->SetProportions(0.0, nextProportion);
|
||||
m_yoffset = (double)(y - dividedObject->GetY());
|
||||
|
||||
// Now reformat text
|
||||
int i = 0;
|
||||
node = dividedObject->GetRegions().First();
|
||||
while (node)
|
||||
{
|
||||
wxShapeRegion *region = (wxShapeRegion *)node->Data();
|
||||
if (region->GetText())
|
||||
{
|
||||
char *s = copystring(region->GetText());
|
||||
dividedObject->FormatText(dc, s, i);
|
||||
delete[] s;
|
||||
}
|
||||
node = node->Next();
|
||||
i++;
|
||||
}
|
||||
dividedObject->SetRegionSizes();
|
||||
dividedObject->Draw(dc);
|
||||
dividedObject->GetEventHandler()->OnMoveLinks(dc);
|
||||
}
|
||||
|
||||
2489
contrib/src/ogl/drawn.cpp
Normal file
2489
contrib/src/ogl/drawn.cpp
Normal file
File diff suppressed because it is too large
Load Diff
2515
contrib/src/ogl/lines.cpp
Normal file
2515
contrib/src/ogl/lines.cpp
Normal file
File diff suppressed because it is too large
Load Diff
18
contrib/src/ogl/makefile.b32
Normal file
18
contrib/src/ogl/makefile.b32
Normal file
@@ -0,0 +1,18 @@
|
||||
#
|
||||
# File: makefile.b32
|
||||
# Author: Julian Smart
|
||||
# Created: 1999
|
||||
# Updated:
|
||||
# Copyright:
|
||||
#
|
||||
# Makefile : Builds OGL library for 32-bit BC++
|
||||
|
||||
WXDIR = $(WXWIN)
|
||||
|
||||
LIBTARGET=$(WXDIR)\contrib\lib\ogl.lib
|
||||
|
||||
OBJECTS = basic.obj basic2.obj canvas.obj ogldiag.obj lines.obj misc.obj divided.obj constrnt.obj\
|
||||
composit.obj drawn.obj bmpshape.obj mfutils.obj
|
||||
|
||||
!include $(WXDIR)\src\makelib.b32
|
||||
|
||||
21
contrib/src/ogl/makefile.bcc
Normal file
21
contrib/src/ogl/makefile.bcc
Normal file
@@ -0,0 +1,21 @@
|
||||
#
|
||||
# File: makefile.bcc
|
||||
# Author: Julian Smart
|
||||
# Created: 1998
|
||||
# Updated:
|
||||
#
|
||||
# Builds OGL library for BC++, 16-bit
|
||||
|
||||
!if "$(WXWIN)" == ""
|
||||
!error You must define the WXWIN variable in autoexec.bat, e.g. WXWIN=c:\wx
|
||||
!endif
|
||||
|
||||
WXDIR = $(WXWIN)
|
||||
|
||||
LIBTARGET=$(WXDIR)\contrib\lib\ogl.lib
|
||||
|
||||
OBJECTS = basic.obj basic2.obj canvas.obj ogldiag.obj lines.obj misc.obj divided.obj constrnt.obj\
|
||||
composit.obj drawn.obj bmpshape.obj mfutils.obj
|
||||
|
||||
!include $(WXDIR)\src\makelib.bcc
|
||||
|
||||
159
contrib/src/ogl/makefile.dos
Normal file
159
contrib/src/ogl/makefile.dos
Normal file
@@ -0,0 +1,159 @@
|
||||
#
|
||||
# File: makefile.dos
|
||||
# Author: Julian Smart
|
||||
# Created: 1993
|
||||
# Updated:
|
||||
# Copyright: (c) 1993, AIAI, University of Edinburgh
|
||||
#
|
||||
# "%W% %G%"
|
||||
#
|
||||
# Makefile: Builds object graphics library (DOS).
|
||||
# Use FINAL=1 argument to nmake to build final version with no debugging
|
||||
# info
|
||||
|
||||
# Set WXDIR for your system
|
||||
WXDIR = $(WXWIN)
|
||||
|
||||
!include $(WXDIR)\src\makemsc.env
|
||||
|
||||
OGLDIR = $(WXDIR)\contrib\src\ogl
|
||||
THISDIR = $(OGLDIR)
|
||||
DOCDIR = $(WXDIR)\docs\latex\ogl
|
||||
|
||||
GRAPHICSLIB = $(WXDIR)\contrib\lib\ogl.lib
|
||||
INC = /I$(WXDIR)\include /I$(WXDIR)\contrib\include
|
||||
|
||||
# Normally set OPTIONS =
|
||||
# to disable PROLOGIO-dependent code
|
||||
OPTIONS = -DPROLOGIO
|
||||
|
||||
OBJECTS = basic.obj basic2.obj canvas.obj ogldiag.obj lines.obj misc.obj divided.obj constrnt.obj\
|
||||
composit.obj drawn.obj bitmap.obj mfutils.obj
|
||||
|
||||
all: $(GRAPHICSLIB)
|
||||
|
||||
wx:
|
||||
cd $(WXDIR)\src\msw
|
||||
nmake -f makefile.dos $(WXLIB) FINAL=$(FINAL)
|
||||
cd $(THISDIR)
|
||||
|
||||
$(GRAPHICSLIB): $(OBJECTS)
|
||||
erase $(GRAPHICSLIB)
|
||||
lib /PAGESIZE:128 @<<
|
||||
$(GRAPHICSLIB)
|
||||
y
|
||||
$(OBJECTS)
|
||||
nul
|
||||
;
|
||||
<<
|
||||
|
||||
# NOTE: This causes a floating point stack error when optimized,
|
||||
# so DON'T optimize!
|
||||
|
||||
basic.obj: basic.$(SRCSUFF) basic.h lines.h misc.h canvas.h
|
||||
cl @<<
|
||||
$(CPPFLAGS) /Od /c /Tp $*.$(SRCSUFF)
|
||||
<<
|
||||
|
||||
basic2.obj: basic2.$(SRCSUFF) basic.h lines.h misc.h canvas.h
|
||||
cl @<<
|
||||
$(CPPFLAGS) /Od /c /Tp $*.$(SRCSUFF)
|
||||
<<
|
||||
|
||||
canvas.obj: canvas.$(SRCSUFF) basic.h misc.h canvas.h
|
||||
cl @<<
|
||||
$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
|
||||
<<
|
||||
|
||||
ogldiag.obj: ogldiag.$(SRCSUFF) ogldiag.h canvas.h basic.h
|
||||
cl @<<
|
||||
$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
|
||||
<<
|
||||
|
||||
lines.obj: lines.$(SRCSUFF) basic.h misc.h canvas.h lines.h basicp.h linesp.h
|
||||
cl @<<
|
||||
$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
|
||||
<<
|
||||
|
||||
misc.obj: misc.$(SRCSUFF) basic.h misc.h constrnt.h basicp.h
|
||||
cl @<<
|
||||
$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
|
||||
<<
|
||||
|
||||
divided.obj: divided.$(SRCSUFF) basic.h misc.h canvas.h divided.h basicp.h
|
||||
cl @<<
|
||||
$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
|
||||
<<
|
||||
|
||||
constrnt.obj: constrnt.$(SRCSUFF) basic.h constrnt.h
|
||||
cl @<<
|
||||
$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
|
||||
<<
|
||||
|
||||
composit.obj: composit.$(SRCSUFF) basic.h misc.h canvas.h constrnt.h composit.h basicp.h
|
||||
cl @<<
|
||||
$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
|
||||
<<
|
||||
|
||||
drawn.obj: drawn.$(SRCSUFF) basic.h misc.h canvas.h drawn.h drawnp.h basicp.h
|
||||
cl @<<
|
||||
$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
|
||||
<<
|
||||
|
||||
bitmap.obj: bitmap.$(SRCSUFF) basic.h misc.h canvas.h bitmap.h
|
||||
cl @<<
|
||||
$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
|
||||
<<
|
||||
|
||||
mfutils.obj: mfutils.$(SRCSUFF) mfutils.h
|
||||
cl @<<
|
||||
$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
|
||||
<<
|
||||
|
||||
# Making documents
|
||||
docs: hlp
|
||||
hlp: $(DOCDIR)/ogl.hlp
|
||||
hlp32: $(DOCDIR)/hlp32/ogl.hlp
|
||||
rtf: $(DOCDIR)/ogl.rtf
|
||||
|
||||
$(DOCDIR)/ogl.hlp: $(DOCDIR)/ogl.rtf $(DOCDIR)/ogl.hpj
|
||||
cd $(DOCDIR)
|
||||
-erase ogl.ph
|
||||
hc ogl
|
||||
cd $(THISDIR)
|
||||
|
||||
$(DOCDIR)/hlp32/ogl.hlp: $(DOCDIR)/hlp32/ogl.rtf $(DOCDIR)/hlp32/ogl.hpj
|
||||
cd $(DOCDIR)/hlp32
|
||||
-erase ogl.ph
|
||||
start /w hcw /c /e ogl.hpj
|
||||
cd $(THISDIR)
|
||||
|
||||
$(DOCDIR)/ogl.rtf: $(DOCDIR)/classes.tex $(DOCDIR)/intro.tex $(DOCDIR)/ogl.tex
|
||||
cd $(DOCDIR)
|
||||
start /w tex2rtf $(DOCDIR)/ogl.tex $(DOCDIR)/ogl.rtf -twice -winhelp
|
||||
cd $(THISDIR)
|
||||
|
||||
$(DOCDIR)/hlp32/ogl.rtf: $(DOCDIR)/classes.tex $(DOCDIR)/intro.tex $(DOCDIR)/ogl.tex
|
||||
cd $(DOCDIR)
|
||||
start /w tex2rtf $(DOCDIR)/ogl.tex $(DOCDIR)/hlp32/ogl.rtf -twice -winhelp -macros $(DOCDIR)/t2rtf32.ini
|
||||
cd $(THISDIR)
|
||||
|
||||
wordrtf:
|
||||
cd $(DOCDIR)
|
||||
-wx /W tex2rtf $(DOCDIR)/ogl.tex $(DOCDIR)/ogl.rtf -twice -rtf
|
||||
cd $(THISDIR)
|
||||
|
||||
clean:
|
||||
-erase *.obj
|
||||
-erase *.sbr
|
||||
-erase *.exe
|
||||
-erase *.res
|
||||
-erase *.map
|
||||
-erase *.pdb
|
||||
-erase *.lib
|
||||
-erase ..\lib\*.lib
|
||||
|
||||
wxclean:
|
||||
cd $(WXDIR)\src\msw
|
||||
nmake -f makefile.dos clean
|
||||
cd $(THISDIR)
|
||||
17
contrib/src/ogl/makefile.g95
Normal file
17
contrib/src/ogl/makefile.g95
Normal file
@@ -0,0 +1,17 @@
|
||||
#
|
||||
# File: makefile.g95
|
||||
# Author: Julian Smart
|
||||
# Created: 1999
|
||||
# Updated:
|
||||
# Copyright: (c) Julian Smart, 1999
|
||||
#
|
||||
# Makefile for wxWindows OGL library Cygwin/Mingw32).
|
||||
|
||||
WXDIR = ../..
|
||||
|
||||
LIBTARGET=$(WXDIR)/lib/libogl.a
|
||||
OBJECTS = basic.o basic2.o canvas.o ogldiag.o lines.o misc.o divided.o constrnt.o\
|
||||
composit.o drawn.o bmpshape.o mfutils.o
|
||||
|
||||
include $(WXDIR)/src/makelib.g95
|
||||
|
||||
42
contrib/src/ogl/makefile.unx
Normal file
42
contrib/src/ogl/makefile.unx
Normal file
@@ -0,0 +1,42 @@
|
||||
#
|
||||
# File: makefile.unx
|
||||
# Author: Julian Smart
|
||||
# Created: 1998
|
||||
# Updated:
|
||||
# Copyright: (c) 1998
|
||||
#
|
||||
#
|
||||
# Makefile for OGL library, Unix
|
||||
|
||||
include ../../src/make.env
|
||||
|
||||
OGLLIB=$(WXDIR)/lib/libogl$(GUISUFFIX).a
|
||||
|
||||
LIB_CPP_SRC=\
|
||||
\
|
||||
basic.o\
|
||||
basic2.o\
|
||||
canvas.o\
|
||||
ogldiag.o\
|
||||
lines.o\
|
||||
misc.o\
|
||||
divided.o\
|
||||
constrnt.o\
|
||||
composit.o\
|
||||
drawn.o\
|
||||
bmpshape.o\
|
||||
mfutils.o
|
||||
|
||||
all: $(OGLLIB)
|
||||
|
||||
# Define library objects
|
||||
OBJECTS=\
|
||||
$(LIB_CPP_SRC:.cpp=.o)
|
||||
|
||||
$(OGLLIB) : $(OBJECTS)
|
||||
ar $(AROPTIONS) $@ $(OBJECTS)
|
||||
$(RANLIB) $@
|
||||
|
||||
clean:
|
||||
rm -f $(OBJECTS) $(OGLLIB)
|
||||
|
||||
196
contrib/src/ogl/makefile.vc
Normal file
196
contrib/src/ogl/makefile.vc
Normal file
@@ -0,0 +1,196 @@
|
||||
|
||||
# File: makefile.vc
|
||||
# Author: Julian Smart
|
||||
# Created: 1993
|
||||
# Updated:
|
||||
# Copyright: (c) 1993, AIAI, University of Edinburgh
|
||||
#
|
||||
# "%W% %G%"
|
||||
#
|
||||
# Makefile : Builds OGL classes library (MS VC++).
|
||||
# Use FINAL=1 argument to nmake to build final version with no debugging
|
||||
# info
|
||||
|
||||
|
||||
# Set WXDIR for your system
|
||||
WXDIR = $(WXWIN)
|
||||
OGLDIR = $(WXDIR)\src\ogl
|
||||
OGLINC = $(WXDIR)\contrib\include\wx\ogl
|
||||
THISDIR = $(WXDIR)\src\ogl
|
||||
EXTRAFLAGS=/DPROLOGIO=1
|
||||
DOCDIR=$(WXDIR)\docs
|
||||
LOCALDOCDIR=$(WXDIR)\docs\latex\ogl
|
||||
|
||||
!include $(WXDIR)\src\makevc.env
|
||||
|
||||
PROGRAM=test
|
||||
|
||||
OBJECTS = $(D)\basic.obj $(D)\basic2.obj $(D)\canvas.obj $(D)\ogldiag.obj $(D)\lines.obj $(D)\misc.obj $(D)\divided.obj $(D)\constrnt.obj\
|
||||
$(D)\composit.obj $(D)\drawn.obj $(D)\bmpshape.obj $(D)\mfutils.obj
|
||||
|
||||
LIBTARGET=$(WXDIR)\contrib\lib\ogl$(LIBEXT).lib
|
||||
|
||||
all: $(D) $(LIBTARGET)
|
||||
|
||||
$(PROGRAM): $(PROGRAM).exe
|
||||
|
||||
$(D) :
|
||||
mkdir $(D)
|
||||
|
||||
wx:
|
||||
cd $(WXDIR)\src\msw
|
||||
nmake -f makefile.vc FINAL=$(FINAL)
|
||||
cd $(THISDIR)
|
||||
|
||||
wxclean:
|
||||
cd $(WXDIR)\src\msw
|
||||
nmake -f makefile.vc clean
|
||||
cd $(THISDIR)
|
||||
|
||||
$(LIBTARGET): $(OBJECTS)
|
||||
-erase $(LIBTARGET)
|
||||
$(implib) @<<
|
||||
-out:$(LIBTARGET)
|
||||
-machine:$(CPU)
|
||||
$(OBJECTS)
|
||||
<<
|
||||
|
||||
# NOTE: This causes a floating point stack error when optimized,
|
||||
# so DON'T optimize!
|
||||
$(D)\basic.obj: basic.$(SRCSUFF) $(OGLINC)/basic.h $(OGLINC)/lines.h $(OGLINC)/misc.h $(OGLINC)/canvas.h
|
||||
cl @<<
|
||||
$(CPPFLAGS) /Od /c /Fo$@ /Tp $(*B).$(SRCSUFF)
|
||||
<<
|
||||
|
||||
$(D)\basic2.obj: basic2.$(SRCSUFF) $(OGLINC)/basic.h $(OGLINC)/lines.h $(OGLINC)/misc.h $(OGLINC)/canvas.h
|
||||
cl @<<
|
||||
$(CPPFLAGS) /Od /c /Fo$@ /Tp $(*B).$(SRCSUFF)
|
||||
<<
|
||||
|
||||
$(D)\canvas.obj: canvas.$(SRCSUFF) $(OGLINC)/basic.h $(OGLINC)/misc.h $(OGLINC)/canvas.h
|
||||
cl @<<
|
||||
$(CPPFLAGS) /c /Fo$@ /Tp $(*B).$(SRCSUFF)
|
||||
<<
|
||||
|
||||
$(D)\ogldiag.obj: ogldiag.$(SRCSUFF) $(OGLINC)/ogldiag.h $(OGLINC)/canvas.h $(OGLINC)/basic.h
|
||||
cl @<<
|
||||
$(CPPFLAGS) /c /Fo$@ /Tp $(*B).$(SRCSUFF)
|
||||
<<
|
||||
|
||||
$(D)\lines.obj: lines.$(SRCSUFF) $(OGLINC)/basic.h $(OGLINC)/misc.h $(OGLINC)/canvas.h $(OGLINC)/lines.h $(OGLINC)/basicp.h $(OGLINC)/linesp.h
|
||||
cl @<<
|
||||
$(CPPFLAGS) /c /Fo$@ /Tp $(*B).$(SRCSUFF)
|
||||
<<
|
||||
|
||||
$(D)\misc.obj: misc.$(SRCSUFF) $(OGLINC)/basic.h $(OGLINC)/misc.h $(OGLINC)/constrnt.h $(OGLINC)/basicp.h
|
||||
cl @<<
|
||||
$(CPPFLAGS) /c /Fo$@ /Tp $(*B).$(SRCSUFF)
|
||||
<<
|
||||
|
||||
$(D)\divided.obj: divided.$(SRCSUFF) $(OGLINC)/basic.h $(OGLINC)/misc.h $(OGLINC)/canvas.h $(OGLINC)/divided.h $(OGLINC)/basicp.h
|
||||
cl @<<
|
||||
$(CPPFLAGS) /c /Fo$@ /Tp $(*B).$(SRCSUFF)
|
||||
<<
|
||||
|
||||
$(D)\constrnt.obj: constrnt.$(SRCSUFF) $(OGLINC)/basic.h $(OGLINC)/constrnt.h
|
||||
cl @<<
|
||||
$(CPPFLAGS) /c /Fo$@ /Tp $(*B).$(SRCSUFF)
|
||||
<<
|
||||
|
||||
$(D)\composit.obj: composit.$(SRCSUFF) $(OGLINC)/basic.h $(OGLINC)/misc.h $(OGLINC)/canvas.h $(OGLINC)/constrnt.h $(OGLINC)/composit.h $(OGLINC)/basicp.h
|
||||
cl @<<
|
||||
$(CPPFLAGS) /c /Fo$@ /Tp $(*B).$(SRCSUFF)
|
||||
<<
|
||||
|
||||
$(D)\drawn.obj: drawn.$(SRCSUFF) $(OGLINC)/basic.h $(OGLINC)/misc.h $(OGLINC)/canvas.h $(OGLINC)/drawn.h $(OGLINC)/drawnp.h $(OGLINC)/basicp.h
|
||||
cl @<<
|
||||
$(CPPFLAGS) /c /Fo$@ /Tp $(*B).$(SRCSUFF)
|
||||
<<
|
||||
|
||||
$(D)\bmpshape.obj: bmpshape.$(SRCSUFF) $(OGLINC)/basic.h $(OGLINC)/misc.h $(OGLINC)/canvas.h $(OGLINC)/bmpshape.h
|
||||
cl @<<
|
||||
$(CPPFLAGS) /c /Fo$@ /Tp $(*B).$(SRCSUFF)
|
||||
<<
|
||||
|
||||
$(D)\mfutils.obj: mfutils.$(SRCSUFF) $(OGLINC)/mfutils.h
|
||||
cl @<<
|
||||
$(CPPFLAGS) /c /Fo$@ /Tp $(*B).$(SRCSUFF)
|
||||
<<
|
||||
|
||||
clean:
|
||||
-erase $(D)\*.obj
|
||||
-erase *.sbr
|
||||
-erase *.exe
|
||||
-erase *.res
|
||||
-erase *.map
|
||||
-erase *.pdb
|
||||
-erase $(LIBTARGET)
|
||||
|
||||
DOCSOURCES=$(LOCALDOCDIR)\ogl.tex \
|
||||
$(LOCALDOCDIR)\bugs.tex $(LOCALDOCDIR)\changes.tex\
|
||||
$(LOCALDOCDIR)\classes.tex $(LOCALDOCDIR)\intro.tex\
|
||||
$(LOCALDOCDIR)\topics.tex $(LOCALDOCDIR)\sample.tex
|
||||
|
||||
html: $(DOCDIR)\html\ogl\ogl.htm
|
||||
htmlhelp: $(DOCDIR)\html\ogl\ogl.chm
|
||||
hlp: $(DOCDIR)\winhelp\ogl.hlp
|
||||
pdfrtf: $(DOCDIR)\pdf\ogl.rtf
|
||||
ps: $(DOCDIR)\ps\ogl.ps
|
||||
|
||||
touchmanual:
|
||||
touch $(LOCALDOCDIR)\ogl.tex
|
||||
|
||||
|
||||
$(DOCDIR)\winhelp\ogl.hlp: $(LOCALDOCDIR)\ogl.rtf $(LOCALDOCDIR)\ogl.hpj
|
||||
cd $(LOCALDOCDIR)
|
||||
-erase ogl.ph
|
||||
hc ogl
|
||||
move ogl.hlp $(DOCDIR)\winhelp\ogl.hlp
|
||||
move ogl.cnt $(DOCDIR)\winhelp\ogl.cnt
|
||||
cd $(THISDIR)
|
||||
|
||||
$(LOCALDOCDIR)\ogl.rtf: $(DOCSOURCES)
|
||||
cd $(LOCALDOCDIR)
|
||||
-start $(WAITFLAG) tex2rtf $(LOCALDOCDIR)\ogl.tex $(LOCALDOCDIR)\ogl.rtf -twice -winhelp
|
||||
cd $(THISDIR)
|
||||
|
||||
$(DOCDIR)\pdf\ogl.rtf: $(DOCSOURCES)
|
||||
cd $(LOCALDOCDIR)
|
||||
-copy *.bmp $(DOCDIR)\pdf
|
||||
-start $(WAITFLAG) tex2rtf $(LOCALDOCDIR)\ogl.tex $(DOCDIR)\pdf\ogl.rtf -twice -rtf
|
||||
cd $(THISDIR)
|
||||
|
||||
$(DOCDIR)\html\ogl\ogl.htm: $(DOCSOURCES)
|
||||
cd $(LOCALDOCDIR)
|
||||
-mkdir $(DOCDIR)\html\ogl
|
||||
copy *.gif $(DOCDIR)\html\ogl
|
||||
-start $(WAITFLAG) tex2rtf $(LOCALDOCDIR)\ogl.tex $(DOCDIR)\html\ogl\ogl.htm -twice -html
|
||||
-erase $(DOCDIR)\html\ogl\*.con
|
||||
-erase *.con
|
||||
-erase $(DOCDIR)\html\ogl\*.ref
|
||||
cd $(THISDIR)
|
||||
|
||||
|
||||
$(DOCDIR)\html\ogl\ogl.chm: $(DOCDIR)\html\ogl\ogl.htm $(DOCDIR)\html\ogl\ogl.hhp
|
||||
cd $(DOCDIR)\html\ogl
|
||||
-hhc ogl.hhp
|
||||
cd $(THISDIR)
|
||||
|
||||
|
||||
$(LOCALDOCDIR)\ogl.dvi: $(DOCSOURCES)
|
||||
cd $(LOCALDOCDIR)
|
||||
-latex ogl
|
||||
-latex ogl
|
||||
-makeindx ogl
|
||||
-bibtex ogl
|
||||
-latex ogl
|
||||
-latex ogl
|
||||
cd $(THISDIR)
|
||||
|
||||
$(WXDIR)\docs\ps\ogl.ps: $(LOCALDOCDIR)\ogl.dvi
|
||||
cd $(LOCALDOCDIR)
|
||||
-dvips32 -o ogl.ps ogl
|
||||
move ogl.ps $(WXDIR)\docs\ps\ogl.ps
|
||||
cd $(THISDIR)
|
||||
|
||||
|
||||
25
contrib/src/ogl/makefile.wat
Normal file
25
contrib/src/ogl/makefile.wat
Normal file
@@ -0,0 +1,25 @@
|
||||
# Objects makefile
|
||||
|
||||
WXDIR = ..\..\..
|
||||
|
||||
!include $(WXDIR)\src\makewat.env
|
||||
|
||||
EXTRACPPFLAGS=/DPROLOGIO
|
||||
|
||||
OGLLIB = $(WXDIR)\contrib\lib\ogl.lib
|
||||
THISDIR = $(WXDIR)\src\ogl
|
||||
|
||||
NAME = ogl
|
||||
LNK = $(name).lnk
|
||||
|
||||
OBJECTS = basic.obj basic2.obj canvas.obj lines.obj divided.obj constrnt.obj &
|
||||
composit.obj drawn.obj bmpshape.obj mfutils.obj ogldiag.obj oglmisc.obj
|
||||
|
||||
all: $(OGLLIB)
|
||||
|
||||
$(OGLLIB): $(OBJECTS)
|
||||
*wlib /b /c /n /P=256 $(OGLLIB) $(OBJECTS)
|
||||
|
||||
clean: .SYMBOLIC
|
||||
-erase *.obj *.bak *.err *.pch $(OGLLIB) *.lbc
|
||||
|
||||
1085
contrib/src/ogl/mfutils.cpp
Normal file
1085
contrib/src/ogl/mfutils.cpp
Normal file
File diff suppressed because it is too large
Load Diff
894
contrib/src/ogl/misc.cpp
Normal file
894
contrib/src/ogl/misc.cpp
Normal file
@@ -0,0 +1,894 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: misc.cpp
|
||||
// Purpose: Miscellaneous OGL support functions
|
||||
// Author: Julian Smart
|
||||
// Modified by:
|
||||
// Created: 12/07/98
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) Julian Smart
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "misc.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>
|
||||
|
||||
#include <wx/types.h>
|
||||
|
||||
#if wxUSE_IOSTREAMH
|
||||
#include <iostream.h>
|
||||
#else
|
||||
#include <iostream>
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <wx/ogl/basic.h>
|
||||
#include <wx/ogl/basicp.h>
|
||||
#include <wx/ogl/misc.h>
|
||||
#include <wx/ogl/constrnt.h>
|
||||
#include <wx/ogl/composit.h>
|
||||
|
||||
wxFont* g_oglNormalFont;
|
||||
wxPen* g_oglBlackPen;
|
||||
wxPen* g_oglWhiteBackgroundPen;
|
||||
wxPen* g_oglTransparentPen;
|
||||
wxBrush* g_oglWhiteBackgroundBrush;
|
||||
wxPen* g_oglBlackForegroundPen;
|
||||
wxCursor* g_oglBullseyeCursor = NULL;
|
||||
|
||||
char* oglBuffer = NULL;
|
||||
|
||||
wxList oglObjectCopyMapping(wxKEY_INTEGER);
|
||||
|
||||
|
||||
|
||||
void wxOGLInitialize()
|
||||
{
|
||||
g_oglBullseyeCursor = new wxCursor(wxCURSOR_BULLSEYE);
|
||||
|
||||
g_oglNormalFont = new wxFont(10, wxSWISS, wxNORMAL, wxNORMAL);
|
||||
|
||||
g_oglBlackPen = new wxPen("BLACK", 1, wxSOLID);
|
||||
|
||||
g_oglWhiteBackgroundPen = new wxPen("WHITE", 1, wxSOLID);
|
||||
g_oglTransparentPen = new wxPen("WHITE", 1, wxTRANSPARENT);
|
||||
g_oglWhiteBackgroundBrush = new wxBrush("WHITE", wxSOLID);
|
||||
g_oglBlackForegroundPen = new wxPen("BLACK", 1, wxSOLID);
|
||||
|
||||
OGLInitializeConstraintTypes();
|
||||
|
||||
// Initialize big buffer used when writing images
|
||||
oglBuffer = new char[3000];
|
||||
|
||||
}
|
||||
|
||||
void wxOGLCleanUp()
|
||||
{
|
||||
if (oglBuffer)
|
||||
{
|
||||
delete[] oglBuffer;
|
||||
oglBuffer = NULL;
|
||||
}
|
||||
oglBuffer = NULL;
|
||||
if (g_oglBullseyeCursor)
|
||||
{
|
||||
delete g_oglBullseyeCursor;
|
||||
g_oglBullseyeCursor = NULL;
|
||||
}
|
||||
|
||||
if (g_oglNormalFont)
|
||||
{
|
||||
delete g_oglNormalFont;
|
||||
g_oglNormalFont = NULL;
|
||||
}
|
||||
if (g_oglBlackPen)
|
||||
{
|
||||
delete g_oglBlackPen;
|
||||
g_oglBlackPen = NULL;
|
||||
}
|
||||
if (g_oglWhiteBackgroundPen)
|
||||
{
|
||||
delete g_oglWhiteBackgroundPen;
|
||||
g_oglWhiteBackgroundPen = NULL;
|
||||
}
|
||||
if (g_oglTransparentPen)
|
||||
{
|
||||
delete g_oglTransparentPen;
|
||||
g_oglTransparentPen = NULL;
|
||||
}
|
||||
if (g_oglWhiteBackgroundBrush)
|
||||
{
|
||||
delete g_oglWhiteBackgroundBrush;
|
||||
g_oglWhiteBackgroundBrush = NULL;
|
||||
}
|
||||
if (g_oglBlackForegroundPen)
|
||||
{
|
||||
delete g_oglBlackForegroundPen;
|
||||
g_oglBlackForegroundPen = NULL;
|
||||
}
|
||||
|
||||
OGLCleanUpConstraintTypes();
|
||||
}
|
||||
|
||||
wxFont *oglMatchFont(int point_size)
|
||||
{
|
||||
wxFont *font = wxTheFontList->FindOrCreateFont(point_size, wxSWISS, wxNORMAL, wxNORMAL);
|
||||
#if 0
|
||||
switch (point_size)
|
||||
{
|
||||
case 4:
|
||||
font = swiss_font_4;
|
||||
break;
|
||||
case 6:
|
||||
font = swiss_font_6;
|
||||
break;
|
||||
case 8:
|
||||
font = swiss_font_8;
|
||||
break;
|
||||
case 12:
|
||||
font = swiss_font_12;
|
||||
break;
|
||||
case 14:
|
||||
font = swiss_font_14;
|
||||
break;
|
||||
case 18:
|
||||
font = swiss_font_18;
|
||||
break;
|
||||
case 24:
|
||||
font = swiss_font_24;
|
||||
break;
|
||||
default:
|
||||
case 10:
|
||||
font = swiss_font_10;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
return font;
|
||||
}
|
||||
|
||||
int FontSizeDialog(wxFrame *parent, int old_size)
|
||||
{
|
||||
if (old_size <= 0)
|
||||
old_size = 10;
|
||||
char buf[40];
|
||||
sprintf(buf, "%d", old_size);
|
||||
wxString ans = wxGetTextFromUser("Enter point size", "Font size", buf, parent);
|
||||
if (ans == "")
|
||||
return 0;
|
||||
|
||||
int new_size = atoi(ans);
|
||||
if ((new_size <= 0) || (new_size > 40))
|
||||
{
|
||||
wxMessageBox("Invalid point size!", "Error", wxOK);
|
||||
return 0;
|
||||
}
|
||||
return new_size;
|
||||
/*
|
||||
char *strings[8];
|
||||
strings[0] = "4";
|
||||
strings[1] = "6";
|
||||
strings[2] = "8";
|
||||
strings[3] = "10";
|
||||
strings[4] = "12";
|
||||
strings[5] = "14";
|
||||
strings[6] = "18";
|
||||
strings[7] = "24";
|
||||
char *ans = wxGetSingleChoice("Choose", "Choose a font size", 8, strings, parent);
|
||||
if (ans)
|
||||
{
|
||||
int size;
|
||||
sscanf(ans, "%d", &size);
|
||||
return oglMatchFont(size);
|
||||
}
|
||||
else return NULL;
|
||||
*/
|
||||
}
|
||||
|
||||
// Centre a list of strings in the given box. xOffset and yOffset are the
|
||||
// the positions that these lines should be relative to, and this might be
|
||||
// the same as m_xpos, m_ypos, but might be zero if formatting from left-justifying.
|
||||
void oglCentreText(wxDC& dc, wxList *text_list,
|
||||
double m_xpos, double m_ypos, double width, double height,
|
||||
int formatMode)
|
||||
{
|
||||
int n = text_list->Number();
|
||||
|
||||
if (!text_list || (n == 0))
|
||||
return;
|
||||
|
||||
// First, get maximum dimensions of box enclosing text
|
||||
|
||||
long char_height = 0;
|
||||
long max_width = 0;
|
||||
long current_width = 0;
|
||||
|
||||
// Store text extents for speed
|
||||
double *widths = new double[n];
|
||||
|
||||
wxNode *current = text_list->First();
|
||||
int i = 0;
|
||||
while (current)
|
||||
{
|
||||
wxShapeTextLine *line = (wxShapeTextLine *)current->Data();
|
||||
dc.GetTextExtent(line->GetText(), ¤t_width, &char_height);
|
||||
widths[i] = current_width;
|
||||
|
||||
if (current_width > max_width)
|
||||
max_width = current_width;
|
||||
current = current->Next();
|
||||
i ++;
|
||||
}
|
||||
|
||||
double max_height = n*char_height;
|
||||
|
||||
double xoffset, yoffset, xOffset, yOffset;
|
||||
|
||||
if (formatMode & FORMAT_CENTRE_VERT)
|
||||
{
|
||||
if (max_height < height)
|
||||
yoffset = (double)(m_ypos - (height/2.0) + (height - max_height)/2.0);
|
||||
else
|
||||
yoffset = (double)(m_ypos - (height/2.0));
|
||||
yOffset = m_ypos;
|
||||
}
|
||||
else
|
||||
{
|
||||
yoffset = 0.0;
|
||||
yOffset = 0.0;
|
||||
}
|
||||
|
||||
if (formatMode & FORMAT_CENTRE_HORIZ)
|
||||
{
|
||||
xoffset = (double)(m_xpos - width/2.0);
|
||||
xOffset = m_xpos;
|
||||
}
|
||||
else
|
||||
{
|
||||
xoffset = 0.0;
|
||||
xOffset = 0.0;
|
||||
}
|
||||
|
||||
current = text_list->First();
|
||||
i = 0;
|
||||
|
||||
while (current)
|
||||
{
|
||||
wxShapeTextLine *line = (wxShapeTextLine *)current->Data();
|
||||
|
||||
double x;
|
||||
if ((formatMode & FORMAT_CENTRE_HORIZ) && (widths[i] < width))
|
||||
x = (double)((width - widths[i])/2.0 + xoffset);
|
||||
else
|
||||
x = xoffset;
|
||||
double y = (double)(i*char_height + yoffset);
|
||||
|
||||
line->SetX( x - xOffset ); line->SetY( y - yOffset );
|
||||
current = current->Next();
|
||||
i ++;
|
||||
}
|
||||
|
||||
delete widths;
|
||||
}
|
||||
|
||||
// Centre a list of strings in the given box
|
||||
void oglCentreTextNoClipping(wxDC& dc, wxList *text_list,
|
||||
double m_xpos, double m_ypos, double width, double height)
|
||||
{
|
||||
int n = text_list->Number();
|
||||
|
||||
if (!text_list || (n == 0))
|
||||
return;
|
||||
|
||||
// First, get maximum dimensions of box enclosing text
|
||||
|
||||
long char_height = 0;
|
||||
long max_width = 0;
|
||||
long current_width = 0;
|
||||
|
||||
// Store text extents for speed
|
||||
double *widths = new double[n];
|
||||
|
||||
wxNode *current = text_list->First();
|
||||
int i = 0;
|
||||
while (current)
|
||||
{
|
||||
wxShapeTextLine *line = (wxShapeTextLine *)current->Data();
|
||||
dc.GetTextExtent(line->GetText(), ¤t_width, &char_height);
|
||||
widths[i] = current_width;
|
||||
|
||||
if (current_width > max_width)
|
||||
max_width = current_width;
|
||||
current = current->Next();
|
||||
i ++;
|
||||
}
|
||||
|
||||
double max_height = n*char_height;
|
||||
|
||||
double yoffset = (double)(m_ypos - (height/2.0) + (height - max_height)/2.0);
|
||||
|
||||
double xoffset = (double)(m_xpos - width/2.0);
|
||||
|
||||
current = text_list->First();
|
||||
i = 0;
|
||||
|
||||
while (current)
|
||||
{
|
||||
wxShapeTextLine *line = (wxShapeTextLine *)current->Data();
|
||||
|
||||
double x = (double)((width - widths[i])/2.0 + xoffset);
|
||||
double y = (double)(i*char_height + yoffset);
|
||||
|
||||
line->SetX( x - m_xpos ); line->SetY( y - m_ypos );
|
||||
current = current->Next();
|
||||
i ++;
|
||||
}
|
||||
delete widths;
|
||||
}
|
||||
|
||||
void oglGetCentredTextExtent(wxDC& dc, wxList *text_list,
|
||||
double m_xpos, double m_ypos, double width, double height,
|
||||
double *actual_width, double *actual_height)
|
||||
{
|
||||
int n = text_list->Number();
|
||||
|
||||
if (!text_list || (n == 0))
|
||||
{
|
||||
*actual_width = 0;
|
||||
*actual_height = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// First, get maximum dimensions of box enclosing text
|
||||
|
||||
long char_height = 0;
|
||||
long max_width = 0;
|
||||
long current_width = 0;
|
||||
|
||||
wxNode *current = text_list->First();
|
||||
int i = 0;
|
||||
while (current)
|
||||
{
|
||||
wxShapeTextLine *line = (wxShapeTextLine *)current->Data();
|
||||
dc.GetTextExtent(line->GetText(), ¤t_width, &char_height);
|
||||
|
||||
if (current_width > max_width)
|
||||
max_width = current_width;
|
||||
current = current->Next();
|
||||
i ++;
|
||||
}
|
||||
|
||||
*actual_height = n*char_height;
|
||||
*actual_width = max_width;
|
||||
}
|
||||
|
||||
// Format a string to a list of strings that fit in the given box.
|
||||
// Interpret %n and 10 or 13 as a new line.
|
||||
wxStringList *oglFormatText(wxDC& dc, const wxString& text, double width, double height, int formatMode)
|
||||
{
|
||||
// First, parse the string into a list of words
|
||||
wxStringList word_list;
|
||||
|
||||
// Make new lines into NULL strings at this point
|
||||
int i = 0; int j = 0; int len = strlen(text);
|
||||
char word[200]; word[0] = 0;
|
||||
bool end_word = FALSE; bool new_line = FALSE;
|
||||
while (i < len)
|
||||
{
|
||||
switch (text[i])
|
||||
{
|
||||
case '%':
|
||||
{
|
||||
i ++;
|
||||
if (i == len)
|
||||
{ word[j] = '%'; j ++; }
|
||||
else
|
||||
{
|
||||
if (text[i] == 'n')
|
||||
{ new_line = TRUE; end_word = TRUE; i++; }
|
||||
else
|
||||
{ word[j] = '%'; j ++; word[j] = text[i]; j ++; i ++; }
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 10:
|
||||
{
|
||||
new_line = TRUE; end_word = TRUE; i++;
|
||||
break;
|
||||
}
|
||||
case 13:
|
||||
{
|
||||
new_line = TRUE; end_word = TRUE; i++;
|
||||
}
|
||||
case ' ':
|
||||
{
|
||||
end_word = TRUE;
|
||||
i ++;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
word[j] = text[i];
|
||||
j ++; i ++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == len) end_word = TRUE;
|
||||
if (end_word)
|
||||
{
|
||||
word[j] = 0;
|
||||
j = 0;
|
||||
word_list.Add(word);
|
||||
end_word = FALSE;
|
||||
}
|
||||
if (new_line)
|
||||
{
|
||||
word_list.Append(NULL);
|
||||
new_line = FALSE;
|
||||
}
|
||||
}
|
||||
// Now, make a list of strings which can fit in the box
|
||||
wxStringList *string_list = new wxStringList;
|
||||
|
||||
char buffer[400];
|
||||
buffer[0] = 0;
|
||||
wxNode *node = word_list.First();
|
||||
long x, y;
|
||||
|
||||
while (node)
|
||||
{
|
||||
wxString oldBuffer(buffer);
|
||||
|
||||
char *s = (char *)node->Data();
|
||||
if (!s)
|
||||
{
|
||||
// FORCE NEW LINE
|
||||
if (strlen(buffer) > 0)
|
||||
string_list->Add(buffer);
|
||||
|
||||
buffer[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (buffer[0] != 0)
|
||||
strcat(buffer, " ");
|
||||
|
||||
strcat(buffer, s);
|
||||
dc.GetTextExtent(buffer, &x, &y);
|
||||
|
||||
// Don't fit within the bounding box if we're fitting shape to contents
|
||||
if ((x > width) && !(formatMode & FORMAT_SIZE_TO_CONTENTS))
|
||||
{
|
||||
// Deal with first word being wider than box
|
||||
if (oldBuffer.Length() > 0)
|
||||
string_list->Add(oldBuffer);
|
||||
|
||||
buffer[0] = 0;
|
||||
strcat(buffer, s);
|
||||
}
|
||||
}
|
||||
|
||||
node = node->Next();
|
||||
}
|
||||
if (buffer[0] != 0)
|
||||
string_list->Add(buffer);
|
||||
|
||||
return string_list;
|
||||
}
|
||||
|
||||
void oglDrawFormattedText(wxDC& dc, wxList *text_list,
|
||||
double m_xpos, double m_ypos, double width, double height,
|
||||
int formatMode)
|
||||
{
|
||||
double xoffset, yoffset;
|
||||
if (formatMode & FORMAT_CENTRE_HORIZ)
|
||||
xoffset = m_xpos;
|
||||
else
|
||||
xoffset = (double)(m_xpos - (width / 2.0));
|
||||
|
||||
if (formatMode & FORMAT_CENTRE_VERT)
|
||||
yoffset = m_ypos;
|
||||
else
|
||||
yoffset = (double)(m_ypos - (height / 2.0));
|
||||
|
||||
dc.SetClippingRegion(
|
||||
(long)(m_xpos - width/2.0), (long)(m_ypos - height/2.0),
|
||||
(long)width, (long)height);
|
||||
|
||||
wxNode *current = text_list->First();
|
||||
while (current)
|
||||
{
|
||||
wxShapeTextLine *line = (wxShapeTextLine *)current->Data();
|
||||
|
||||
dc.DrawText(line->GetText(), WXROUND(xoffset + line->GetX()), WXROUND(yoffset + line->GetY()));
|
||||
current = current->Next();
|
||||
}
|
||||
|
||||
dc.DestroyClippingRegion();
|
||||
}
|
||||
|
||||
/*
|
||||
* Find centroid given list of points comprising polyline
|
||||
*
|
||||
*/
|
||||
|
||||
void oglFindPolylineCentroid(wxList *points, double *x, double *y)
|
||||
{
|
||||
double xcount = 0;
|
||||
double ycount = 0;
|
||||
|
||||
wxNode *node = points->First();
|
||||
while (node)
|
||||
{
|
||||
wxRealPoint *point = (wxRealPoint *)node->Data();
|
||||
xcount += point->x;
|
||||
ycount += point->y;
|
||||
node = node->Next();
|
||||
}
|
||||
|
||||
*x = (xcount/points->Number());
|
||||
*y = (ycount/points->Number());
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that (x1, y1) -> (x2, y2) hits (x3, y3) -> (x4, y4).
|
||||
* If so, ratio1 gives the proportion along the first line
|
||||
* that the intersection occurs (or something like that).
|
||||
* Used by functions below.
|
||||
*
|
||||
*/
|
||||
void oglCheckLineIntersection(double x1, double y1, double x2, double y2,
|
||||
double x3, double y3, double x4, double y4,
|
||||
double *ratio1, double *ratio2)
|
||||
{
|
||||
double denominator_term = (y4 - y3)*(x2 - x1) - (y2 - y1)*(x4 - x3);
|
||||
double numerator_term = (x3 - x1)*(y4 - y3) + (x4 - x3)*(y1 - y3);
|
||||
|
||||
double line_constant;
|
||||
double length_ratio = 1.0;
|
||||
double k_line = 1.0;
|
||||
|
||||
// Check for parallel lines
|
||||
if ((denominator_term < 0.005) && (denominator_term > -0.005))
|
||||
line_constant = -1.0;
|
||||
else
|
||||
line_constant = numerator_term/denominator_term;
|
||||
|
||||
// Check for intersection
|
||||
if ((line_constant < 1.0) && (line_constant > 0.0))
|
||||
{
|
||||
// Now must check that other line hits
|
||||
if (((y4 - y3) < 0.005) && ((y4 - y3) > -0.005))
|
||||
k_line = ((x1 - x3) + line_constant*(x2 - x1))/(x4 - x3);
|
||||
else
|
||||
k_line = ((y1 - y3) + line_constant*(y2 - y1))/(y4 - y3);
|
||||
|
||||
if ((k_line >= 0.0) && (k_line < 1.0))
|
||||
length_ratio = line_constant;
|
||||
else
|
||||
k_line = 1.0;
|
||||
}
|
||||
*ratio1 = length_ratio;
|
||||
*ratio2 = k_line;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find where (x1, y1) -> (x2, y2) hits one of the lines in xvec, yvec.
|
||||
* (*x3, *y3) is the point where it hits.
|
||||
*
|
||||
*/
|
||||
void oglFindEndForPolyline(double n, double xvec[], double yvec[],
|
||||
double x1, double y1, double x2, double y2, double *x3, double *y3)
|
||||
{
|
||||
int i;
|
||||
double lastx = xvec[0];
|
||||
double lasty = yvec[0];
|
||||
|
||||
double min_ratio = 1.0;
|
||||
double line_ratio;
|
||||
double other_ratio;
|
||||
|
||||
for (i = 1; i < n; i++)
|
||||
{
|
||||
oglCheckLineIntersection(x1, y1, x2, y2, lastx, lasty, xvec[i], yvec[i],
|
||||
&line_ratio, &other_ratio);
|
||||
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 < min_ratio)
|
||||
min_ratio = line_ratio;
|
||||
}
|
||||
|
||||
*x3 = (x1 + (x2 - x1)*min_ratio);
|
||||
*y3 = (y1 + (y2 - y1)*min_ratio);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Find where the line hits the box.
|
||||
*
|
||||
*/
|
||||
|
||||
void oglFindEndForBox(double width, double height,
|
||||
double x1, double y1, // Centre of box (possibly)
|
||||
double x2, double y2, // other end of line
|
||||
double *x3, double *y3) // End on box edge
|
||||
{
|
||||
double xvec[5];
|
||||
double yvec[5];
|
||||
|
||||
xvec[0] = (double)(x1 - width/2.0);
|
||||
yvec[0] = (double)(y1 - height/2.0);
|
||||
xvec[1] = (double)(x1 - width/2.0);
|
||||
yvec[1] = (double)(y1 + height/2.0);
|
||||
xvec[2] = (double)(x1 + width/2.0);
|
||||
yvec[2] = (double)(y1 + height/2.0);
|
||||
xvec[3] = (double)(x1 + width/2.0);
|
||||
yvec[3] = (double)(y1 - height/2.0);
|
||||
xvec[4] = (double)(x1 - width/2.0);
|
||||
yvec[4] = (double)(y1 - height/2.0);
|
||||
|
||||
oglFindEndForPolyline(5, xvec, yvec, x2, y2, x1, y1, x3, y3);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find where the line hits the circle.
|
||||
*
|
||||
*/
|
||||
|
||||
void oglFindEndForCircle(double radius,
|
||||
double x1, double y1, // Centre of circle
|
||||
double x2, double y2, // Other end of line
|
||||
double *x3, double *y3)
|
||||
{
|
||||
double H = (double)sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1));
|
||||
|
||||
if (H == 0.0)
|
||||
{
|
||||
*x3 = x1;
|
||||
*y3 = y1;
|
||||
}
|
||||
else
|
||||
{
|
||||
*y3 = radius * (y2 - y1)/H + y1;
|
||||
*x3 = radius * (x2 - x1)/H + x1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Given the line (x1, y1) -> (x2, y2), and an arrow size of given length and width,
|
||||
* return the position of the tip of the arrow and the left and right vertices of the arrow.
|
||||
*
|
||||
*/
|
||||
|
||||
void oglGetArrowPoints(double x1, double y1, double x2, double y2,
|
||||
double length, double width,
|
||||
double *tip_x, double *tip_y,
|
||||
double *side1_x, double *side1_y,
|
||||
double *side2_x, double *side2_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;
|
||||
|
||||
double x3 = (- length*i_bar) + x2;
|
||||
double y3 = (- length*j_bar) + y2;
|
||||
|
||||
*side1_x = width*(-j_bar) + x3;
|
||||
*side1_y = width*i_bar + y3;
|
||||
|
||||
*side2_x = -width*(-j_bar) + x3;
|
||||
*side2_y = -width*i_bar + y3;
|
||||
|
||||
*tip_x = x2; *tip_y = y2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given an ellipse and endpoints of a line, returns the point at which
|
||||
* the line touches the ellipse in values x4, y4.
|
||||
* This function assumes that the centre of the ellipse is at x1, y1, and the
|
||||
* ellipse has a width of width1 and a height of height1. It also assumes you are
|
||||
* wanting to draw an arc FROM point x2, y2 TOWARDS point x3, y3.
|
||||
* This function calculates the x,y coordinates of the intersection point of
|
||||
* the arc with the ellipse.
|
||||
* Author: Ian Harrison
|
||||
*/
|
||||
|
||||
void oglDrawArcToEllipse(double x1, double y1, double width1, double height1, double x2, double y2, double x3, double y3,
|
||||
double *x4, double *y4)
|
||||
{
|
||||
double a1 = (double)(width1/2.0);
|
||||
double b1 = (double)(height1/2.0);
|
||||
|
||||
// These are required to give top left x and y coordinates for DrawEllipse
|
||||
// double top_left_x1 = (double)(x1 - a1);
|
||||
// double top_left_y1 = (double)(y1 - b1);
|
||||
/*
|
||||
// Check for vertical line
|
||||
if (fabs(x2 - x3) < 0.05)
|
||||
{
|
||||
*x4 = x3;
|
||||
if (y2 < y3)
|
||||
*y4 = (double)(y1 - b1);
|
||||
else
|
||||
*y4 = (double)(y1 + b1);
|
||||
return;
|
||||
}
|
||||
*/
|
||||
// Check that x2 != x3
|
||||
if (fabs(x2 - x3) < 0.05)
|
||||
{
|
||||
*x4 = x2;
|
||||
if (y3 > y2)
|
||||
*y4 = (double)(y1 - sqrt((b1*b1 - (((x2-x1)*(x2-x1))*(b1*b1)/(a1*a1)))));
|
||||
else
|
||||
*y4 = (double)(y1 + sqrt((b1*b1 - (((x2-x1)*(x2-x1))*(b1*b1)/(a1*a1)))));
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate the x and y coordinates of the point where arc intersects ellipse
|
||||
|
||||
double A, B, C, D, E, F, G, H, K;
|
||||
double ellipse1_x, ellipse1_y;
|
||||
|
||||
A = (double)(1/(a1 * a1));
|
||||
B = (double)((y3 - y2) * (y3 - y2)) / ((x3 - x2) * (x3 - x2) * b1 * b1);
|
||||
C = (double)(2 * (y3 - y2) * (y2 - y1)) / ((x3 - x2) * b1 * b1);
|
||||
D = (double)((y2 - y1) * (y2 - y1)) / (b1 * b1);
|
||||
E = (double)(A + B);
|
||||
F = (double)(C - (2 * A * x1) - (2 * B * x2));
|
||||
G = (double)((A * x1 * x1) + (B * x2 * x2) - (C * x2) + D - 1);
|
||||
H = (double)((y3 - y2) / (x3 - x2));
|
||||
K = (double)((F * F) - (4 * E * G));
|
||||
|
||||
if (K >= 0)
|
||||
// In this case the line intersects the ellipse, so calculate intersection
|
||||
{
|
||||
if(x2 >= x1)
|
||||
{
|
||||
ellipse1_x = (double)(((F * -1) + sqrt(K)) / (2 * E));
|
||||
ellipse1_y = (double)((H * (ellipse1_x - x2)) + y2);
|
||||
}
|
||||
else
|
||||
{
|
||||
ellipse1_x = (double)(((F * -1) - sqrt(K)) / (2 * E));
|
||||
ellipse1_y = (double)((H * (ellipse1_x - x2)) + y2);
|
||||
}
|
||||
}
|
||||
else
|
||||
// in this case, arc does not intersect ellipse, so just draw arc
|
||||
{
|
||||
ellipse1_x = x3;
|
||||
ellipse1_y = y3;
|
||||
}
|
||||
*x4 = ellipse1_x;
|
||||
*y4 = ellipse1_y;
|
||||
|
||||
/*
|
||||
// Draw a little circle (radius = 2) at the end of the arc where it hits
|
||||
// the ellipse .
|
||||
|
||||
double circle_x = ellipse1_x - 2.0;
|
||||
double circle_y = ellipse1_y - 2.0;
|
||||
m_canvas->DrawEllipse(circle_x, circle_y, 4.0, 4.0);
|
||||
*/
|
||||
}
|
||||
|
||||
// Update a list item from a list of strings
|
||||
void UpdateListBox(wxListBox *item, wxList *list)
|
||||
{
|
||||
item->Clear();
|
||||
if (!list)
|
||||
return;
|
||||
|
||||
wxNode *node = list->First();
|
||||
while (node)
|
||||
{
|
||||
char *s = (char *)node->Data();
|
||||
item->Append(s);
|
||||
node = node->Next();
|
||||
}
|
||||
}
|
||||
|
||||
bool oglRoughlyEqual(double val1, double val2, double tol)
|
||||
{
|
||||
return ( (val1 < (val2 + tol)) && (val1 > (val2 - tol)) &&
|
||||
(val2 < (val1 + tol)) && (val2 > (val1 - tol)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Hex<->Dec conversion
|
||||
*/
|
||||
|
||||
// Array used in DecToHex conversion routine.
|
||||
static char sg_HexArray[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',
|
||||
'C', 'D', 'E', 'F' };
|
||||
|
||||
// Convert 2-digit hex number to decimal
|
||||
unsigned int oglHexToDec(char* buf)
|
||||
{
|
||||
int firstDigit, secondDigit;
|
||||
|
||||
if (buf[0] >= 'A')
|
||||
firstDigit = buf[0] - 'A' + 10;
|
||||
else
|
||||
firstDigit = buf[0] - '0';
|
||||
|
||||
if (buf[1] >= 'A')
|
||||
secondDigit = buf[1] - 'A' + 10;
|
||||
else
|
||||
secondDigit = buf[1] - '0';
|
||||
|
||||
return firstDigit * 16 + secondDigit;
|
||||
}
|
||||
|
||||
// Convert decimal integer to 2-character hex string
|
||||
void oglDecToHex(unsigned int dec, char *buf)
|
||||
{
|
||||
int firstDigit = (int)(dec/16.0);
|
||||
int secondDigit = (int)(dec - (firstDigit*16.0));
|
||||
buf[0] = sg_HexArray[firstDigit];
|
||||
buf[1] = sg_HexArray[secondDigit];
|
||||
buf[2] = 0;
|
||||
}
|
||||
|
||||
// 3-digit hex to wxColour
|
||||
wxColour oglHexToColour(const wxString& hex)
|
||||
{
|
||||
if (hex.Length() == 6)
|
||||
{
|
||||
char buf[7];
|
||||
strncpy(buf, hex, 7);
|
||||
unsigned int r = oglHexToDec((char *)buf);
|
||||
unsigned int g = oglHexToDec((char *)(buf+2));
|
||||
unsigned int b = oglHexToDec((char *)(buf+4));
|
||||
return wxColour(r, g, b);
|
||||
}
|
||||
else
|
||||
return wxColour(0,0,0);
|
||||
}
|
||||
|
||||
// RGB to 3-digit hex
|
||||
wxString oglColourToHex(const wxColour& colour)
|
||||
{
|
||||
char buf[7];
|
||||
unsigned int red = colour.Red();
|
||||
unsigned int green = colour.Green();
|
||||
unsigned int blue = colour.Blue();
|
||||
|
||||
oglDecToHex(red, buf);
|
||||
oglDecToHex(green, buf+2);
|
||||
oglDecToHex(blue, buf+4);
|
||||
|
||||
return wxString(buf);
|
||||
}
|
||||
|
||||
|
||||
756
contrib/src/ogl/ogldiag.cpp
Normal file
756
contrib/src/ogl/ogldiag.cpp
Normal file
@@ -0,0 +1,756 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: ogldiag.cpp
|
||||
// Purpose: wxDiagram
|
||||
// Author: Julian Smart
|
||||
// Modified by:
|
||||
// Created: 12/07/98
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) Julian Smart
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "ogldiag.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>
|
||||
|
||||
#if wxUSE_IOSTREAMH
|
||||
#include <iostream.h>
|
||||
#include <fstream.h>
|
||||
#else
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#ifdef _MSC_VER
|
||||
using namespace std;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <wx/ogl/basic.h>
|
||||
#include <wx/ogl/basicp.h>
|
||||
#include <wx/ogl/canvas.h>
|
||||
#include <wx/ogl/ogldiag.h>
|
||||
#include <wx/ogl/lines.h>
|
||||
#include <wx/ogl/composit.h>
|
||||
#include <wx/ogl/misc.h>
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxDiagram, wxObject)
|
||||
|
||||
// Object canvas
|
||||
wxDiagram::wxDiagram()
|
||||
{
|
||||
m_diagramCanvas = NULL;
|
||||
m_quickEditMode = FALSE;
|
||||
m_snapToGrid = TRUE;
|
||||
m_gridSpacing = 5.0;
|
||||
m_shapeList = new wxList;
|
||||
m_mouseTolerance = DEFAULT_MOUSE_TOLERANCE;
|
||||
}
|
||||
|
||||
wxDiagram::~wxDiagram()
|
||||
{
|
||||
if (m_shapeList)
|
||||
delete m_shapeList;
|
||||
}
|
||||
|
||||
void wxDiagram::SetSnapToGrid(bool snap)
|
||||
{
|
||||
m_snapToGrid = snap;
|
||||
}
|
||||
|
||||
void wxDiagram::SetGridSpacing(double spacing)
|
||||
{
|
||||
m_gridSpacing = spacing;
|
||||
}
|
||||
|
||||
void wxDiagram::Snap(double *x, double *y)
|
||||
{
|
||||
if (m_snapToGrid)
|
||||
{
|
||||
*x = m_gridSpacing * ((int)(*x/m_gridSpacing + 0.5));
|
||||
*y = m_gridSpacing * ((int)(*y/m_gridSpacing + 0.5));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void wxDiagram::Redraw(wxDC& dc)
|
||||
{
|
||||
if (m_shapeList)
|
||||
{
|
||||
if (GetCanvas())
|
||||
GetCanvas()->SetCursor(* wxHOURGLASS_CURSOR);
|
||||
wxNode *current = m_shapeList->First();
|
||||
|
||||
while (current)
|
||||
{
|
||||
wxShape *object = (wxShape *)current->Data();
|
||||
if (!object->GetParent())
|
||||
object->Draw(dc);
|
||||
|
||||
current = current->Next();
|
||||
}
|
||||
if (GetCanvas())
|
||||
GetCanvas()->SetCursor(* wxSTANDARD_CURSOR);
|
||||
}
|
||||
}
|
||||
|
||||
void wxDiagram::Clear(wxDC& dc)
|
||||
{
|
||||
dc.Clear();
|
||||
}
|
||||
|
||||
// Insert object after addAfter, or at end of list.
|
||||
void wxDiagram::AddShape(wxShape *object, wxShape *addAfter)
|
||||
{
|
||||
wxNode *nodeAfter = NULL;
|
||||
if (addAfter)
|
||||
nodeAfter = m_shapeList->Member(addAfter);
|
||||
|
||||
if (!m_shapeList->Member(object))
|
||||
{
|
||||
if (nodeAfter)
|
||||
{
|
||||
if (nodeAfter->Next())
|
||||
m_shapeList->Insert(nodeAfter->Next(), object);
|
||||
else
|
||||
m_shapeList->Append(object);
|
||||
}
|
||||
else
|
||||
m_shapeList->Append(object);
|
||||
object->SetCanvas(GetCanvas());
|
||||
}
|
||||
}
|
||||
|
||||
void wxDiagram::InsertShape(wxShape *object)
|
||||
{
|
||||
m_shapeList->Insert(object);
|
||||
object->SetCanvas(GetCanvas());
|
||||
}
|
||||
|
||||
void wxDiagram::RemoveShape(wxShape *object)
|
||||
{
|
||||
m_shapeList->DeleteObject(object);
|
||||
}
|
||||
|
||||
// Should this delete the actual objects too? I think not.
|
||||
void wxDiagram::RemoveAllShapes()
|
||||
{
|
||||
m_shapeList->Clear();
|
||||
}
|
||||
|
||||
void wxDiagram::DeleteAllShapes()
|
||||
{
|
||||
wxNode *node = m_shapeList->First();
|
||||
while (node)
|
||||
{
|
||||
wxShape *shape = (wxShape *)node->Data();
|
||||
if (!shape->GetParent())
|
||||
{
|
||||
RemoveShape(shape);
|
||||
delete shape;
|
||||
node = m_shapeList->First();
|
||||
}
|
||||
else
|
||||
node = node->Next();
|
||||
}
|
||||
}
|
||||
|
||||
void wxDiagram::ShowAll(bool show)
|
||||
{
|
||||
wxNode *current = m_shapeList->First();
|
||||
|
||||
while (current)
|
||||
{
|
||||
wxShape *object = (wxShape *)current->Data();
|
||||
object->Show(show);
|
||||
|
||||
current = current->Next();
|
||||
}
|
||||
}
|
||||
|
||||
void wxDiagram::DrawOutline(wxDC& dc, double x1, double y1, double x2, double y2)
|
||||
{
|
||||
wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
|
||||
dc.SetPen(dottedPen);
|
||||
dc.SetBrush((* wxTRANSPARENT_BRUSH));
|
||||
|
||||
wxPoint points[5];
|
||||
|
||||
points[0].x = (int) x1;
|
||||
points[0].y = (int) y1;
|
||||
|
||||
points[1].x = (int) x2;
|
||||
points[1].y = (int) y1;
|
||||
|
||||
points[2].x = (int) x2;
|
||||
points[2].y = (int) y2;
|
||||
|
||||
points[3].x = (int) x1;
|
||||
points[3].y = (int) y2;
|
||||
|
||||
points[4].x = (int) x1;
|
||||
points[4].y = (int) y1;
|
||||
dc.DrawLines(5, points);
|
||||
}
|
||||
|
||||
// Make sure all text that should be centred, is centred.
|
||||
void wxDiagram::RecentreAll(wxDC& dc)
|
||||
{
|
||||
wxNode *object_node = m_shapeList->First();
|
||||
while (object_node)
|
||||
{
|
||||
wxShape *obj = (wxShape *)object_node->Data();
|
||||
obj->Recentre(dc);
|
||||
object_node = object_node->Next();
|
||||
}
|
||||
}
|
||||
|
||||
// Input/output
|
||||
#ifdef PROLOGIO
|
||||
bool wxDiagram::SaveFile(const wxString& filename)
|
||||
{
|
||||
wxBeginBusyCursor();
|
||||
|
||||
wxExprDatabase *database = new wxExprDatabase;
|
||||
|
||||
// First write the diagram type
|
||||
wxExpr *header = new wxExpr("diagram");
|
||||
OnHeaderSave(*database, *header);
|
||||
|
||||
database->Append(header);
|
||||
|
||||
wxNode *node = m_shapeList->First();
|
||||
while (node)
|
||||
{
|
||||
wxShape *shape = (wxShape *)node->Data();
|
||||
|
||||
if (!shape->IsKindOf(CLASSINFO(wxControlPoint)))
|
||||
{
|
||||
wxExpr *expr = NULL;
|
||||
if (shape->IsKindOf(CLASSINFO(wxLineShape)))
|
||||
expr = new wxExpr("line");
|
||||
else
|
||||
expr = new wxExpr("shape");
|
||||
|
||||
OnShapeSave(*database, *shape, *expr);
|
||||
}
|
||||
node = node->Next();
|
||||
}
|
||||
OnDatabaseSave(*database);
|
||||
|
||||
char tempFile[400];
|
||||
wxGetTempFileName("diag", tempFile);
|
||||
FILE* file = fopen(tempFile, "w");
|
||||
if (! file)
|
||||
{
|
||||
wxEndBusyCursor();
|
||||
delete database;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
database->Write(file);
|
||||
fclose(file);
|
||||
delete database;
|
||||
|
||||
/*
|
||||
// Save backup
|
||||
if (FileExists(filename))
|
||||
{
|
||||
char buf[400];
|
||||
#ifdef __X__
|
||||
sprintf(buf, "%s.bak", filename);
|
||||
#endif
|
||||
#ifdef __WXMSW__
|
||||
sprintf(buf, "_diagram.bak");
|
||||
#endif
|
||||
if (FileExists(buf)) wxRemoveFile(buf);
|
||||
if (!wxRenameFile(filename, buf))
|
||||
{
|
||||
wxCopyFile(filename, buf);
|
||||
wxRemoveFile(filename);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Copy the temporary file to the correct filename
|
||||
if (!wxRenameFile(tempFile, filename))
|
||||
{
|
||||
wxCopyFile(tempFile, filename);
|
||||
wxRemoveFile(tempFile);
|
||||
}
|
||||
|
||||
wxEndBusyCursor();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool wxDiagram::LoadFile(const wxString& filename)
|
||||
{
|
||||
wxBeginBusyCursor();
|
||||
|
||||
wxExprDatabase database(wxExprInteger, "id");
|
||||
if (!database.Read(filename))
|
||||
{
|
||||
wxEndBusyCursor();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DeleteAllShapes();
|
||||
|
||||
database.BeginFind();
|
||||
wxExpr *header = database.FindClauseByFunctor("diagram");
|
||||
|
||||
if (header)
|
||||
OnHeaderLoad(database, *header);
|
||||
|
||||
// Scan through all clauses and register the ids
|
||||
wxNode *node = database.First();
|
||||
while (node)
|
||||
{
|
||||
wxExpr *clause = (wxExpr *)node->Data();
|
||||
long id = -1;
|
||||
clause->GetAttributeValue("id", id);
|
||||
wxRegisterId(id);
|
||||
node = node->Next();
|
||||
}
|
||||
|
||||
ReadNodes(database);
|
||||
ReadContainerGeometry(database);
|
||||
ReadLines(database);
|
||||
|
||||
OnDatabaseLoad(database);
|
||||
|
||||
wxEndBusyCursor();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void wxDiagram::ReadNodes(wxExprDatabase& database)
|
||||
{
|
||||
// Find and create the node images
|
||||
database.BeginFind();
|
||||
wxExpr *clause = database.FindClauseByFunctor("shape");
|
||||
while (clause)
|
||||
{
|
||||
char *type = NULL;
|
||||
long parentId = -1;
|
||||
|
||||
clause->AssignAttributeValue("type", &type);
|
||||
clause->AssignAttributeValue("parent", &parentId);
|
||||
wxClassInfo *classInfo = wxClassInfo::FindClass(type);
|
||||
if (classInfo)
|
||||
{
|
||||
wxShape *shape = (wxShape *)classInfo->CreateObject();
|
||||
OnShapeLoad(database, *shape, *clause);
|
||||
|
||||
shape->SetCanvas(GetCanvas());
|
||||
shape->Show(TRUE);
|
||||
|
||||
m_shapeList->Append(shape);
|
||||
|
||||
// If child of composite, link up
|
||||
if (parentId > -1)
|
||||
{
|
||||
wxExpr *parentExpr = database.HashFind("shape", parentId);
|
||||
if (parentExpr && parentExpr->GetClientData())
|
||||
{
|
||||
wxShape *parent = (wxShape *)parentExpr->GetClientData();
|
||||
shape->SetParent(parent);
|
||||
parent->GetChildren().Append(shape);
|
||||
}
|
||||
}
|
||||
|
||||
clause->SetClientData(shape);
|
||||
}
|
||||
if (type)
|
||||
delete[] type;
|
||||
|
||||
clause = database.FindClauseByFunctor("shape");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void wxDiagram::ReadLines(wxExprDatabase& database)
|
||||
{
|
||||
database.BeginFind();
|
||||
wxExpr *clause = database.FindClauseByFunctor("line");
|
||||
while (clause)
|
||||
{
|
||||
wxString type("");
|
||||
long parentId = -1;
|
||||
|
||||
clause->GetAttributeValue("type", type);
|
||||
clause->GetAttributeValue("parent", parentId);
|
||||
wxClassInfo *classInfo = wxClassInfo::FindClass((char*) (const char*) type);
|
||||
if (classInfo)
|
||||
{
|
||||
wxLineShape *shape = (wxLineShape *)classInfo->CreateObject();
|
||||
shape->Show(TRUE);
|
||||
|
||||
OnShapeLoad(database, *shape, *clause);
|
||||
shape->SetCanvas(GetCanvas());
|
||||
|
||||
long image_to = -1; long image_from = -1;
|
||||
clause->GetAttributeValue("to", image_to);
|
||||
clause->GetAttributeValue("from", image_from);
|
||||
|
||||
wxExpr *image_to_expr = database.HashFind("shape", image_to);
|
||||
|
||||
if (!image_to_expr)
|
||||
{
|
||||
// Error
|
||||
}
|
||||
wxExpr *image_from_expr = database.HashFind("shape", image_from);
|
||||
|
||||
if (!image_from_expr)
|
||||
{
|
||||
// Error
|
||||
}
|
||||
|
||||
if (image_to_expr && image_from_expr)
|
||||
{
|
||||
wxShape *image_to_object = (wxShape *)image_to_expr->GetClientData();
|
||||
wxShape *image_from_object = (wxShape *)image_from_expr->GetClientData();
|
||||
|
||||
if (image_to_object && image_from_object)
|
||||
{
|
||||
image_from_object->AddLine(shape, image_to_object, shape->GetAttachmentFrom(), shape->GetAttachmentTo());
|
||||
}
|
||||
}
|
||||
clause->SetClientData(shape);
|
||||
|
||||
m_shapeList->Append(shape);
|
||||
}
|
||||
|
||||
clause = database.FindClauseByFunctor("line");
|
||||
}
|
||||
}
|
||||
|
||||
// Containers have divisions that reference adjoining divisions,
|
||||
// so we need a separate pass to link everything up.
|
||||
// Also used by Symbol Library.
|
||||
void wxDiagram::ReadContainerGeometry(wxExprDatabase& database)
|
||||
{
|
||||
database.BeginFind();
|
||||
wxExpr *clause = database.FindClauseByFunctor("shape");
|
||||
while (clause)
|
||||
{
|
||||
wxShape *image = (wxShape *)clause->GetClientData();
|
||||
if (image && image->IsKindOf(CLASSINFO(wxCompositeShape)))
|
||||
{
|
||||
wxCompositeShape *composite = (wxCompositeShape *)image;
|
||||
wxExpr *divisionExpr = NULL;
|
||||
|
||||
// Find the list of divisions in the composite
|
||||
clause->GetAttributeValue("divisions", &divisionExpr);
|
||||
if (divisionExpr)
|
||||
{
|
||||
int i = 0;
|
||||
wxExpr *idExpr = divisionExpr->Nth(i);
|
||||
while (idExpr)
|
||||
{
|
||||
long divisionId = idExpr->IntegerValue();
|
||||
wxExpr *childExpr = database.HashFind("shape", divisionId);
|
||||
if (childExpr && childExpr->GetClientData())
|
||||
{
|
||||
wxDivisionShape *child = (wxDivisionShape *)childExpr->GetClientData();
|
||||
composite->GetDivisions().Append(child);
|
||||
|
||||
// Find the adjoining shapes
|
||||
long leftSideId = -1;
|
||||
long topSideId = -1;
|
||||
long rightSideId = -1;
|
||||
long bottomSideId = -1;
|
||||
childExpr->GetAttributeValue("left_side", leftSideId);
|
||||
childExpr->GetAttributeValue("top_side", topSideId);
|
||||
childExpr->GetAttributeValue("right_side", rightSideId);
|
||||
childExpr->GetAttributeValue("bottom_side", bottomSideId);
|
||||
if (leftSideId > -1)
|
||||
{
|
||||
wxExpr *leftExpr = database.HashFind("shape", leftSideId);
|
||||
if (leftExpr && leftExpr->GetClientData())
|
||||
{
|
||||
wxDivisionShape *leftSide = (wxDivisionShape *)leftExpr->GetClientData();
|
||||
child->SetLeftSide(leftSide);
|
||||
}
|
||||
}
|
||||
if (topSideId > -1)
|
||||
{
|
||||
wxExpr *topExpr = database.HashFind("shape", topSideId);
|
||||
if (topExpr && topExpr->GetClientData())
|
||||
{
|
||||
wxDivisionShape *topSide = (wxDivisionShape *)topExpr->GetClientData();
|
||||
child->SetTopSide(topSide);
|
||||
}
|
||||
}
|
||||
if (rightSideId > -1)
|
||||
{
|
||||
wxExpr *rightExpr = database.HashFind("shape", rightSideId);
|
||||
if (rightExpr && rightExpr->GetClientData())
|
||||
{
|
||||
wxDivisionShape *rightSide = (wxDivisionShape *)rightExpr->GetClientData();
|
||||
child->SetRightSide(rightSide);
|
||||
}
|
||||
}
|
||||
if (bottomSideId > -1)
|
||||
{
|
||||
wxExpr *bottomExpr = database.HashFind("shape", bottomSideId);
|
||||
if (bottomExpr && bottomExpr->GetClientData())
|
||||
{
|
||||
wxDivisionShape *bottomSide = (wxDivisionShape *)bottomExpr->GetClientData();
|
||||
child->SetBottomSide(bottomSide);
|
||||
}
|
||||
}
|
||||
}
|
||||
i ++;
|
||||
idExpr = divisionExpr->Nth(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clause = database.FindClauseByFunctor("shape");
|
||||
}
|
||||
}
|
||||
|
||||
// Allow for modifying file
|
||||
bool wxDiagram::OnDatabaseLoad(wxExprDatabase& db)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool wxDiagram::OnDatabaseSave(wxExprDatabase& db)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool wxDiagram::OnShapeSave(wxExprDatabase& db, wxShape& shape, wxExpr& expr)
|
||||
{
|
||||
shape.WriteAttributes(&expr);
|
||||
db.Append(&expr);
|
||||
|
||||
if (shape.IsKindOf(CLASSINFO(wxCompositeShape)))
|
||||
{
|
||||
wxNode *node = shape.GetChildren().First();
|
||||
while (node)
|
||||
{
|
||||
wxShape *childShape = (wxShape *)node->Data();
|
||||
wxExpr *childExpr = new wxExpr("shape");
|
||||
OnShapeSave(db, *childShape, *childExpr);
|
||||
node = node->Next();
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool wxDiagram::OnShapeLoad(wxExprDatabase& db, wxShape& shape, wxExpr& expr)
|
||||
{
|
||||
shape.ReadAttributes(&expr);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool wxDiagram::OnHeaderSave(wxExprDatabase& db, wxExpr& expr)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool wxDiagram::OnHeaderLoad(wxExprDatabase& db, wxExpr& expr)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void wxDiagram::SetCanvas(wxShapeCanvas *can)
|
||||
{
|
||||
m_diagramCanvas = can;
|
||||
}
|
||||
|
||||
// Find a shape by its id
|
||||
wxShape* wxDiagram::FindShape(long id) const
|
||||
{
|
||||
wxNode* node = GetShapeList()->First();
|
||||
while (node)
|
||||
{
|
||||
wxShape* shape = (wxShape*) node->Data();
|
||||
if (shape->GetId() == id)
|
||||
return shape;
|
||||
node = node->Next();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//// Crossings classes
|
||||
|
||||
wxLineCrossings::wxLineCrossings()
|
||||
{
|
||||
}
|
||||
|
||||
wxLineCrossings::~wxLineCrossings()
|
||||
{
|
||||
ClearCrossings();
|
||||
}
|
||||
|
||||
void wxLineCrossings::FindCrossings(wxDiagram& diagram)
|
||||
{
|
||||
ClearCrossings();
|
||||
wxNode* node1 = diagram.GetShapeList()->First();
|
||||
while (node1)
|
||||
{
|
||||
wxShape* shape1 = (wxShape*) node1->Data();
|
||||
if (shape1->IsKindOf(CLASSINFO(wxLineShape)))
|
||||
{
|
||||
wxLineShape* lineShape1 = (wxLineShape*) shape1;
|
||||
// Iterate through the segments
|
||||
wxList* pts1 = lineShape1->GetLineControlPoints();
|
||||
int i;
|
||||
for (i = 0; i < (pts1->Number() - 1); i++)
|
||||
{
|
||||
wxRealPoint* pt1_a = (wxRealPoint*) (pts1->Nth(i)->Data());
|
||||
wxRealPoint* pt1_b = (wxRealPoint*) (pts1->Nth(i+1)->Data());
|
||||
|
||||
// Now we iterate through the segments again
|
||||
|
||||
wxNode* node2 = diagram.GetShapeList()->First();
|
||||
while (node2)
|
||||
{
|
||||
wxShape* shape2 = (wxShape*) node2->Data();
|
||||
|
||||
// Assume that the same line doesn't cross itself
|
||||
if (shape2->IsKindOf(CLASSINFO(wxLineShape)) && (shape1 != shape2))
|
||||
{
|
||||
wxLineShape* lineShape2 = (wxLineShape*) shape2;
|
||||
// Iterate through the segments
|
||||
wxList* pts2 = lineShape2->GetLineControlPoints();
|
||||
int j;
|
||||
for (j = 0; j < (pts2->Number() - 1); j++)
|
||||
{
|
||||
wxRealPoint* pt2_a = (wxRealPoint*) (pts2->Nth(j)->Data());
|
||||
wxRealPoint* pt2_b = (wxRealPoint*) (pts2->Nth(j+1)->Data());
|
||||
|
||||
// Now let's see if these two segments cross.
|
||||
double ratio1, ratio2;
|
||||
oglCheckLineIntersection(pt1_a->x, pt1_a->y, pt1_b->x, pt1_b->y,
|
||||
pt2_a->x, pt2_a->y, pt2_b->x, pt2_b->y,
|
||||
& ratio1, & ratio2);
|
||||
|
||||
if ((ratio1 < 1.0) && (ratio1 > -1.0))
|
||||
{
|
||||
// Intersection!
|
||||
wxLineCrossing* crossing = new wxLineCrossing;
|
||||
crossing->m_intersect.x = (pt1_a->x + (pt1_b->x - pt1_a->x)*ratio1);
|
||||
crossing->m_intersect.y = (pt1_a->y + (pt1_b->y - pt1_a->y)*ratio1);
|
||||
|
||||
crossing->m_pt1 = * pt1_a;
|
||||
crossing->m_pt2 = * pt1_b;
|
||||
crossing->m_pt3 = * pt2_a;
|
||||
crossing->m_pt4 = * pt2_b;
|
||||
|
||||
crossing->m_lineShape1 = lineShape1;
|
||||
crossing->m_lineShape2 = lineShape2;
|
||||
|
||||
m_crossings.Append(crossing);
|
||||
}
|
||||
}
|
||||
}
|
||||
node2 = node2->Next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
node1 = node1->Next();
|
||||
}
|
||||
}
|
||||
|
||||
void wxLineCrossings::DrawCrossings(wxDiagram& diagram, wxDC& dc)
|
||||
{
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
|
||||
long arcWidth = 8;
|
||||
|
||||
wxNode* node = m_crossings.First();
|
||||
while (node)
|
||||
{
|
||||
wxLineCrossing* crossing = (wxLineCrossing*) node->Data();
|
||||
// dc.DrawEllipse((long) (crossing->m_intersect.x - (arcWidth/2.0) + 0.5), (long) (crossing->m_intersect.y - (arcWidth/2.0) + 0.5),
|
||||
// arcWidth, arcWidth);
|
||||
|
||||
|
||||
// Let's do some geometry to find the points on either end of the arc.
|
||||
/*
|
||||
|
||||
(x1, y1)
|
||||
|\
|
||||
| \
|
||||
| \
|
||||
| \
|
||||
| \
|
||||
| |\ c c1
|
||||
| a | \
|
||||
| \
|
||||
| - x <-- centre of arc
|
||||
a1 | b |\
|
||||
| | \ c2
|
||||
| a2 | \
|
||||
| - \
|
||||
| b2 \
|
||||
| \
|
||||
|_______________\ (x2, y2)
|
||||
b1
|
||||
|
||||
*/
|
||||
|
||||
double a1 = wxMax(crossing->m_pt1.y, crossing->m_pt2.y) - wxMin(crossing->m_pt1.y, crossing->m_pt2.y) ;
|
||||
double b1 = wxMax(crossing->m_pt1.x, crossing->m_pt2.x) - wxMin(crossing->m_pt1.x, crossing->m_pt2.x) ;
|
||||
double c1 = sqrt( (a1*a1) + (b1*b1) );
|
||||
|
||||
double c = arcWidth / 2.0;
|
||||
double a = c * a1/c1 ;
|
||||
double b = c * b1/c1 ;
|
||||
|
||||
// I'm not sure this is right, since we don't know which direction we should be going in - need
|
||||
// to know which way the line slopes and choose the sign appropriately.
|
||||
double arcX1 = crossing->m_intersect.x - b;
|
||||
double arcY1 = crossing->m_intersect.y - a;
|
||||
|
||||
double arcX2 = crossing->m_intersect.x + b;
|
||||
double arcY2 = crossing->m_intersect.y + a;
|
||||
|
||||
dc.SetPen(*wxBLACK_PEN);
|
||||
dc.DrawArc( (long) arcX1, (long) arcY1, (long) arcX2, (long) arcY2,
|
||||
(long) crossing->m_intersect.x, (long) crossing->m_intersect.y);
|
||||
|
||||
dc.SetPen(*wxWHITE_PEN);
|
||||
dc.DrawLine( (long) arcX1, (long) arcY1, (long) arcX2, (long) arcY2 );
|
||||
|
||||
node = node->Next();
|
||||
}
|
||||
}
|
||||
|
||||
void wxLineCrossings::ClearCrossings()
|
||||
{
|
||||
wxNode* node = m_crossings.First();
|
||||
while (node)
|
||||
{
|
||||
wxLineCrossing* crossing = (wxLineCrossing*) node->Data();
|
||||
delete crossing;
|
||||
node = node->Next();
|
||||
}
|
||||
m_crossings.Clear();
|
||||
}
|
||||
|
||||
894
contrib/src/ogl/oglmisc.cpp
Normal file
894
contrib/src/ogl/oglmisc.cpp
Normal file
@@ -0,0 +1,894 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: misc.cpp
|
||||
// Purpose: Miscellaneous OGL support functions
|
||||
// Author: Julian Smart
|
||||
// Modified by:
|
||||
// Created: 12/07/98
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) Julian Smart
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "misc.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>
|
||||
|
||||
#include <wx/types.h>
|
||||
|
||||
#if wxUSE_IOSTREAMH
|
||||
#include <iostream.h>
|
||||
#else
|
||||
#include <iostream>
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <wx/ogl/basic.h>
|
||||
#include <wx/ogl/basicp.h>
|
||||
#include <wx/ogl/misc.h>
|
||||
#include <wx/ogl/constrnt.h>
|
||||
#include <wx/ogl/composit.h>
|
||||
|
||||
wxFont* g_oglNormalFont;
|
||||
wxPen* g_oglBlackPen;
|
||||
wxPen* g_oglWhiteBackgroundPen;
|
||||
wxPen* g_oglTransparentPen;
|
||||
wxBrush* g_oglWhiteBackgroundBrush;
|
||||
wxPen* g_oglBlackForegroundPen;
|
||||
wxCursor* g_oglBullseyeCursor = NULL;
|
||||
|
||||
char* oglBuffer = NULL;
|
||||
|
||||
wxList oglObjectCopyMapping(wxKEY_INTEGER);
|
||||
|
||||
|
||||
|
||||
void wxOGLInitialize()
|
||||
{
|
||||
g_oglBullseyeCursor = new wxCursor(wxCURSOR_BULLSEYE);
|
||||
|
||||
g_oglNormalFont = new wxFont(10, wxSWISS, wxNORMAL, wxNORMAL);
|
||||
|
||||
g_oglBlackPen = new wxPen("BLACK", 1, wxSOLID);
|
||||
|
||||
g_oglWhiteBackgroundPen = new wxPen("WHITE", 1, wxSOLID);
|
||||
g_oglTransparentPen = new wxPen("WHITE", 1, wxTRANSPARENT);
|
||||
g_oglWhiteBackgroundBrush = new wxBrush("WHITE", wxSOLID);
|
||||
g_oglBlackForegroundPen = new wxPen("BLACK", 1, wxSOLID);
|
||||
|
||||
OGLInitializeConstraintTypes();
|
||||
|
||||
// Initialize big buffer used when writing images
|
||||
oglBuffer = new char[3000];
|
||||
|
||||
}
|
||||
|
||||
void wxOGLCleanUp()
|
||||
{
|
||||
if (oglBuffer)
|
||||
{
|
||||
delete[] oglBuffer;
|
||||
oglBuffer = NULL;
|
||||
}
|
||||
oglBuffer = NULL;
|
||||
if (g_oglBullseyeCursor)
|
||||
{
|
||||
delete g_oglBullseyeCursor;
|
||||
g_oglBullseyeCursor = NULL;
|
||||
}
|
||||
|
||||
if (g_oglNormalFont)
|
||||
{
|
||||
delete g_oglNormalFont;
|
||||
g_oglNormalFont = NULL;
|
||||
}
|
||||
if (g_oglBlackPen)
|
||||
{
|
||||
delete g_oglBlackPen;
|
||||
g_oglBlackPen = NULL;
|
||||
}
|
||||
if (g_oglWhiteBackgroundPen)
|
||||
{
|
||||
delete g_oglWhiteBackgroundPen;
|
||||
g_oglWhiteBackgroundPen = NULL;
|
||||
}
|
||||
if (g_oglTransparentPen)
|
||||
{
|
||||
delete g_oglTransparentPen;
|
||||
g_oglTransparentPen = NULL;
|
||||
}
|
||||
if (g_oglWhiteBackgroundBrush)
|
||||
{
|
||||
delete g_oglWhiteBackgroundBrush;
|
||||
g_oglWhiteBackgroundBrush = NULL;
|
||||
}
|
||||
if (g_oglBlackForegroundPen)
|
||||
{
|
||||
delete g_oglBlackForegroundPen;
|
||||
g_oglBlackForegroundPen = NULL;
|
||||
}
|
||||
|
||||
OGLCleanUpConstraintTypes();
|
||||
}
|
||||
|
||||
wxFont *oglMatchFont(int point_size)
|
||||
{
|
||||
wxFont *font = wxTheFontList->FindOrCreateFont(point_size, wxSWISS, wxNORMAL, wxNORMAL);
|
||||
#if 0
|
||||
switch (point_size)
|
||||
{
|
||||
case 4:
|
||||
font = swiss_font_4;
|
||||
break;
|
||||
case 6:
|
||||
font = swiss_font_6;
|
||||
break;
|
||||
case 8:
|
||||
font = swiss_font_8;
|
||||
break;
|
||||
case 12:
|
||||
font = swiss_font_12;
|
||||
break;
|
||||
case 14:
|
||||
font = swiss_font_14;
|
||||
break;
|
||||
case 18:
|
||||
font = swiss_font_18;
|
||||
break;
|
||||
case 24:
|
||||
font = swiss_font_24;
|
||||
break;
|
||||
default:
|
||||
case 10:
|
||||
font = swiss_font_10;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
return font;
|
||||
}
|
||||
|
||||
int FontSizeDialog(wxFrame *parent, int old_size)
|
||||
{
|
||||
if (old_size <= 0)
|
||||
old_size = 10;
|
||||
char buf[40];
|
||||
sprintf(buf, "%d", old_size);
|
||||
wxString ans = wxGetTextFromUser("Enter point size", "Font size", buf, parent);
|
||||
if (ans == "")
|
||||
return 0;
|
||||
|
||||
int new_size = atoi(ans);
|
||||
if ((new_size <= 0) || (new_size > 40))
|
||||
{
|
||||
wxMessageBox("Invalid point size!", "Error", wxOK);
|
||||
return 0;
|
||||
}
|
||||
return new_size;
|
||||
/*
|
||||
char *strings[8];
|
||||
strings[0] = "4";
|
||||
strings[1] = "6";
|
||||
strings[2] = "8";
|
||||
strings[3] = "10";
|
||||
strings[4] = "12";
|
||||
strings[5] = "14";
|
||||
strings[6] = "18";
|
||||
strings[7] = "24";
|
||||
char *ans = wxGetSingleChoice("Choose", "Choose a font size", 8, strings, parent);
|
||||
if (ans)
|
||||
{
|
||||
int size;
|
||||
sscanf(ans, "%d", &size);
|
||||
return oglMatchFont(size);
|
||||
}
|
||||
else return NULL;
|
||||
*/
|
||||
}
|
||||
|
||||
// Centre a list of strings in the given box. xOffset and yOffset are the
|
||||
// the positions that these lines should be relative to, and this might be
|
||||
// the same as m_xpos, m_ypos, but might be zero if formatting from left-justifying.
|
||||
void oglCentreText(wxDC& dc, wxList *text_list,
|
||||
double m_xpos, double m_ypos, double width, double height,
|
||||
int formatMode)
|
||||
{
|
||||
int n = text_list->Number();
|
||||
|
||||
if (!text_list || (n == 0))
|
||||
return;
|
||||
|
||||
// First, get maximum dimensions of box enclosing text
|
||||
|
||||
long char_height = 0;
|
||||
long max_width = 0;
|
||||
long current_width = 0;
|
||||
|
||||
// Store text extents for speed
|
||||
double *widths = new double[n];
|
||||
|
||||
wxNode *current = text_list->First();
|
||||
int i = 0;
|
||||
while (current)
|
||||
{
|
||||
wxShapeTextLine *line = (wxShapeTextLine *)current->Data();
|
||||
dc.GetTextExtent(line->GetText(), ¤t_width, &char_height);
|
||||
widths[i] = current_width;
|
||||
|
||||
if (current_width > max_width)
|
||||
max_width = current_width;
|
||||
current = current->Next();
|
||||
i ++;
|
||||
}
|
||||
|
||||
double max_height = n*char_height;
|
||||
|
||||
double xoffset, yoffset, xOffset, yOffset;
|
||||
|
||||
if (formatMode & FORMAT_CENTRE_VERT)
|
||||
{
|
||||
if (max_height < height)
|
||||
yoffset = (double)(m_ypos - (height/2.0) + (height - max_height)/2.0);
|
||||
else
|
||||
yoffset = (double)(m_ypos - (height/2.0));
|
||||
yOffset = m_ypos;
|
||||
}
|
||||
else
|
||||
{
|
||||
yoffset = 0.0;
|
||||
yOffset = 0.0;
|
||||
}
|
||||
|
||||
if (formatMode & FORMAT_CENTRE_HORIZ)
|
||||
{
|
||||
xoffset = (double)(m_xpos - width/2.0);
|
||||
xOffset = m_xpos;
|
||||
}
|
||||
else
|
||||
{
|
||||
xoffset = 0.0;
|
||||
xOffset = 0.0;
|
||||
}
|
||||
|
||||
current = text_list->First();
|
||||
i = 0;
|
||||
|
||||
while (current)
|
||||
{
|
||||
wxShapeTextLine *line = (wxShapeTextLine *)current->Data();
|
||||
|
||||
double x;
|
||||
if ((formatMode & FORMAT_CENTRE_HORIZ) && (widths[i] < width))
|
||||
x = (double)((width - widths[i])/2.0 + xoffset);
|
||||
else
|
||||
x = xoffset;
|
||||
double y = (double)(i*char_height + yoffset);
|
||||
|
||||
line->SetX( x - xOffset ); line->SetY( y - yOffset );
|
||||
current = current->Next();
|
||||
i ++;
|
||||
}
|
||||
|
||||
delete widths;
|
||||
}
|
||||
|
||||
// Centre a list of strings in the given box
|
||||
void oglCentreTextNoClipping(wxDC& dc, wxList *text_list,
|
||||
double m_xpos, double m_ypos, double width, double height)
|
||||
{
|
||||
int n = text_list->Number();
|
||||
|
||||
if (!text_list || (n == 0))
|
||||
return;
|
||||
|
||||
// First, get maximum dimensions of box enclosing text
|
||||
|
||||
long char_height = 0;
|
||||
long max_width = 0;
|
||||
long current_width = 0;
|
||||
|
||||
// Store text extents for speed
|
||||
double *widths = new double[n];
|
||||
|
||||
wxNode *current = text_list->First();
|
||||
int i = 0;
|
||||
while (current)
|
||||
{
|
||||
wxShapeTextLine *line = (wxShapeTextLine *)current->Data();
|
||||
dc.GetTextExtent(line->GetText(), ¤t_width, &char_height);
|
||||
widths[i] = current_width;
|
||||
|
||||
if (current_width > max_width)
|
||||
max_width = current_width;
|
||||
current = current->Next();
|
||||
i ++;
|
||||
}
|
||||
|
||||
double max_height = n*char_height;
|
||||
|
||||
double yoffset = (double)(m_ypos - (height/2.0) + (height - max_height)/2.0);
|
||||
|
||||
double xoffset = (double)(m_xpos - width/2.0);
|
||||
|
||||
current = text_list->First();
|
||||
i = 0;
|
||||
|
||||
while (current)
|
||||
{
|
||||
wxShapeTextLine *line = (wxShapeTextLine *)current->Data();
|
||||
|
||||
double x = (double)((width - widths[i])/2.0 + xoffset);
|
||||
double y = (double)(i*char_height + yoffset);
|
||||
|
||||
line->SetX( x - m_xpos ); line->SetY( y - m_ypos );
|
||||
current = current->Next();
|
||||
i ++;
|
||||
}
|
||||
delete widths;
|
||||
}
|
||||
|
||||
void oglGetCentredTextExtent(wxDC& dc, wxList *text_list,
|
||||
double m_xpos, double m_ypos, double width, double height,
|
||||
double *actual_width, double *actual_height)
|
||||
{
|
||||
int n = text_list->Number();
|
||||
|
||||
if (!text_list || (n == 0))
|
||||
{
|
||||
*actual_width = 0;
|
||||
*actual_height = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// First, get maximum dimensions of box enclosing text
|
||||
|
||||
long char_height = 0;
|
||||
long max_width = 0;
|
||||
long current_width = 0;
|
||||
|
||||
wxNode *current = text_list->First();
|
||||
int i = 0;
|
||||
while (current)
|
||||
{
|
||||
wxShapeTextLine *line = (wxShapeTextLine *)current->Data();
|
||||
dc.GetTextExtent(line->GetText(), ¤t_width, &char_height);
|
||||
|
||||
if (current_width > max_width)
|
||||
max_width = current_width;
|
||||
current = current->Next();
|
||||
i ++;
|
||||
}
|
||||
|
||||
*actual_height = n*char_height;
|
||||
*actual_width = max_width;
|
||||
}
|
||||
|
||||
// Format a string to a list of strings that fit in the given box.
|
||||
// Interpret %n and 10 or 13 as a new line.
|
||||
wxStringList *oglFormatText(wxDC& dc, const wxString& text, double width, double height, int formatMode)
|
||||
{
|
||||
// First, parse the string into a list of words
|
||||
wxStringList word_list;
|
||||
|
||||
// Make new lines into NULL strings at this point
|
||||
int i = 0; int j = 0; int len = strlen(text);
|
||||
char word[200]; word[0] = 0;
|
||||
bool end_word = FALSE; bool new_line = FALSE;
|
||||
while (i < len)
|
||||
{
|
||||
switch (text[i])
|
||||
{
|
||||
case '%':
|
||||
{
|
||||
i ++;
|
||||
if (i == len)
|
||||
{ word[j] = '%'; j ++; }
|
||||
else
|
||||
{
|
||||
if (text[i] == 'n')
|
||||
{ new_line = TRUE; end_word = TRUE; i++; }
|
||||
else
|
||||
{ word[j] = '%'; j ++; word[j] = text[i]; j ++; i ++; }
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 10:
|
||||
{
|
||||
new_line = TRUE; end_word = TRUE; i++;
|
||||
break;
|
||||
}
|
||||
case 13:
|
||||
{
|
||||
new_line = TRUE; end_word = TRUE; i++;
|
||||
}
|
||||
case ' ':
|
||||
{
|
||||
end_word = TRUE;
|
||||
i ++;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
word[j] = text[i];
|
||||
j ++; i ++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == len) end_word = TRUE;
|
||||
if (end_word)
|
||||
{
|
||||
word[j] = 0;
|
||||
j = 0;
|
||||
word_list.Add(word);
|
||||
end_word = FALSE;
|
||||
}
|
||||
if (new_line)
|
||||
{
|
||||
word_list.Append(NULL);
|
||||
new_line = FALSE;
|
||||
}
|
||||
}
|
||||
// Now, make a list of strings which can fit in the box
|
||||
wxStringList *string_list = new wxStringList;
|
||||
|
||||
char buffer[400];
|
||||
buffer[0] = 0;
|
||||
wxNode *node = word_list.First();
|
||||
long x, y;
|
||||
|
||||
while (node)
|
||||
{
|
||||
wxString oldBuffer(buffer);
|
||||
|
||||
char *s = (char *)node->Data();
|
||||
if (!s)
|
||||
{
|
||||
// FORCE NEW LINE
|
||||
if (strlen(buffer) > 0)
|
||||
string_list->Add(buffer);
|
||||
|
||||
buffer[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (buffer[0] != 0)
|
||||
strcat(buffer, " ");
|
||||
|
||||
strcat(buffer, s);
|
||||
dc.GetTextExtent(buffer, &x, &y);
|
||||
|
||||
// Don't fit within the bounding box if we're fitting shape to contents
|
||||
if ((x > width) && !(formatMode & FORMAT_SIZE_TO_CONTENTS))
|
||||
{
|
||||
// Deal with first word being wider than box
|
||||
if (oldBuffer.Length() > 0)
|
||||
string_list->Add(oldBuffer);
|
||||
|
||||
buffer[0] = 0;
|
||||
strcat(buffer, s);
|
||||
}
|
||||
}
|
||||
|
||||
node = node->Next();
|
||||
}
|
||||
if (buffer[0] != 0)
|
||||
string_list->Add(buffer);
|
||||
|
||||
return string_list;
|
||||
}
|
||||
|
||||
void oglDrawFormattedText(wxDC& dc, wxList *text_list,
|
||||
double m_xpos, double m_ypos, double width, double height,
|
||||
int formatMode)
|
||||
{
|
||||
double xoffset, yoffset;
|
||||
if (formatMode & FORMAT_CENTRE_HORIZ)
|
||||
xoffset = m_xpos;
|
||||
else
|
||||
xoffset = (double)(m_xpos - (width / 2.0));
|
||||
|
||||
if (formatMode & FORMAT_CENTRE_VERT)
|
||||
yoffset = m_ypos;
|
||||
else
|
||||
yoffset = (double)(m_ypos - (height / 2.0));
|
||||
|
||||
dc.SetClippingRegion(
|
||||
(long)(m_xpos - width/2.0), (long)(m_ypos - height/2.0),
|
||||
(long)width, (long)height);
|
||||
|
||||
wxNode *current = text_list->First();
|
||||
while (current)
|
||||
{
|
||||
wxShapeTextLine *line = (wxShapeTextLine *)current->Data();
|
||||
|
||||
dc.DrawText(line->GetText(), WXROUND(xoffset + line->GetX()), WXROUND(yoffset + line->GetY()));
|
||||
current = current->Next();
|
||||
}
|
||||
|
||||
dc.DestroyClippingRegion();
|
||||
}
|
||||
|
||||
/*
|
||||
* Find centroid given list of points comprising polyline
|
||||
*
|
||||
*/
|
||||
|
||||
void oglFindPolylineCentroid(wxList *points, double *x, double *y)
|
||||
{
|
||||
double xcount = 0;
|
||||
double ycount = 0;
|
||||
|
||||
wxNode *node = points->First();
|
||||
while (node)
|
||||
{
|
||||
wxRealPoint *point = (wxRealPoint *)node->Data();
|
||||
xcount += point->x;
|
||||
ycount += point->y;
|
||||
node = node->Next();
|
||||
}
|
||||
|
||||
*x = (xcount/points->Number());
|
||||
*y = (ycount/points->Number());
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that (x1, y1) -> (x2, y2) hits (x3, y3) -> (x4, y4).
|
||||
* If so, ratio1 gives the proportion along the first line
|
||||
* that the intersection occurs (or something like that).
|
||||
* Used by functions below.
|
||||
*
|
||||
*/
|
||||
void oglCheckLineIntersection(double x1, double y1, double x2, double y2,
|
||||
double x3, double y3, double x4, double y4,
|
||||
double *ratio1, double *ratio2)
|
||||
{
|
||||
double denominator_term = (y4 - y3)*(x2 - x1) - (y2 - y1)*(x4 - x3);
|
||||
double numerator_term = (x3 - x1)*(y4 - y3) + (x4 - x3)*(y1 - y3);
|
||||
|
||||
double line_constant;
|
||||
double length_ratio = 1.0;
|
||||
double k_line = 1.0;
|
||||
|
||||
// Check for parallel lines
|
||||
if ((denominator_term < 0.005) && (denominator_term > -0.005))
|
||||
line_constant = -1.0;
|
||||
else
|
||||
line_constant = numerator_term/denominator_term;
|
||||
|
||||
// Check for intersection
|
||||
if ((line_constant < 1.0) && (line_constant > 0.0))
|
||||
{
|
||||
// Now must check that other line hits
|
||||
if (((y4 - y3) < 0.005) && ((y4 - y3) > -0.005))
|
||||
k_line = ((x1 - x3) + line_constant*(x2 - x1))/(x4 - x3);
|
||||
else
|
||||
k_line = ((y1 - y3) + line_constant*(y2 - y1))/(y4 - y3);
|
||||
|
||||
if ((k_line >= 0.0) && (k_line < 1.0))
|
||||
length_ratio = line_constant;
|
||||
else
|
||||
k_line = 1.0;
|
||||
}
|
||||
*ratio1 = length_ratio;
|
||||
*ratio2 = k_line;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find where (x1, y1) -> (x2, y2) hits one of the lines in xvec, yvec.
|
||||
* (*x3, *y3) is the point where it hits.
|
||||
*
|
||||
*/
|
||||
void oglFindEndForPolyline(double n, double xvec[], double yvec[],
|
||||
double x1, double y1, double x2, double y2, double *x3, double *y3)
|
||||
{
|
||||
int i;
|
||||
double lastx = xvec[0];
|
||||
double lasty = yvec[0];
|
||||
|
||||
double min_ratio = 1.0;
|
||||
double line_ratio;
|
||||
double other_ratio;
|
||||
|
||||
for (i = 1; i < n; i++)
|
||||
{
|
||||
oglCheckLineIntersection(x1, y1, x2, y2, lastx, lasty, xvec[i], yvec[i],
|
||||
&line_ratio, &other_ratio);
|
||||
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 < min_ratio)
|
||||
min_ratio = line_ratio;
|
||||
}
|
||||
|
||||
*x3 = (x1 + (x2 - x1)*min_ratio);
|
||||
*y3 = (y1 + (y2 - y1)*min_ratio);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Find where the line hits the box.
|
||||
*
|
||||
*/
|
||||
|
||||
void oglFindEndForBox(double width, double height,
|
||||
double x1, double y1, // Centre of box (possibly)
|
||||
double x2, double y2, // other end of line
|
||||
double *x3, double *y3) // End on box edge
|
||||
{
|
||||
double xvec[5];
|
||||
double yvec[5];
|
||||
|
||||
xvec[0] = (double)(x1 - width/2.0);
|
||||
yvec[0] = (double)(y1 - height/2.0);
|
||||
xvec[1] = (double)(x1 - width/2.0);
|
||||
yvec[1] = (double)(y1 + height/2.0);
|
||||
xvec[2] = (double)(x1 + width/2.0);
|
||||
yvec[2] = (double)(y1 + height/2.0);
|
||||
xvec[3] = (double)(x1 + width/2.0);
|
||||
yvec[3] = (double)(y1 - height/2.0);
|
||||
xvec[4] = (double)(x1 - width/2.0);
|
||||
yvec[4] = (double)(y1 - height/2.0);
|
||||
|
||||
oglFindEndForPolyline(5, xvec, yvec, x2, y2, x1, y1, x3, y3);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find where the line hits the circle.
|
||||
*
|
||||
*/
|
||||
|
||||
void oglFindEndForCircle(double radius,
|
||||
double x1, double y1, // Centre of circle
|
||||
double x2, double y2, // Other end of line
|
||||
double *x3, double *y3)
|
||||
{
|
||||
double H = (double)sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1));
|
||||
|
||||
if (H == 0.0)
|
||||
{
|
||||
*x3 = x1;
|
||||
*y3 = y1;
|
||||
}
|
||||
else
|
||||
{
|
||||
*y3 = radius * (y2 - y1)/H + y1;
|
||||
*x3 = radius * (x2 - x1)/H + x1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Given the line (x1, y1) -> (x2, y2), and an arrow size of given length and width,
|
||||
* return the position of the tip of the arrow and the left and right vertices of the arrow.
|
||||
*
|
||||
*/
|
||||
|
||||
void oglGetArrowPoints(double x1, double y1, double x2, double y2,
|
||||
double length, double width,
|
||||
double *tip_x, double *tip_y,
|
||||
double *side1_x, double *side1_y,
|
||||
double *side2_x, double *side2_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;
|
||||
|
||||
double x3 = (- length*i_bar) + x2;
|
||||
double y3 = (- length*j_bar) + y2;
|
||||
|
||||
*side1_x = width*(-j_bar) + x3;
|
||||
*side1_y = width*i_bar + y3;
|
||||
|
||||
*side2_x = -width*(-j_bar) + x3;
|
||||
*side2_y = -width*i_bar + y3;
|
||||
|
||||
*tip_x = x2; *tip_y = y2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given an ellipse and endpoints of a line, returns the point at which
|
||||
* the line touches the ellipse in values x4, y4.
|
||||
* This function assumes that the centre of the ellipse is at x1, y1, and the
|
||||
* ellipse has a width of width1 and a height of height1. It also assumes you are
|
||||
* wanting to draw an arc FROM point x2, y2 TOWARDS point x3, y3.
|
||||
* This function calculates the x,y coordinates of the intersection point of
|
||||
* the arc with the ellipse.
|
||||
* Author: Ian Harrison
|
||||
*/
|
||||
|
||||
void oglDrawArcToEllipse(double x1, double y1, double width1, double height1, double x2, double y2, double x3, double y3,
|
||||
double *x4, double *y4)
|
||||
{
|
||||
double a1 = (double)(width1/2.0);
|
||||
double b1 = (double)(height1/2.0);
|
||||
|
||||
// These are required to give top left x and y coordinates for DrawEllipse
|
||||
// double top_left_x1 = (double)(x1 - a1);
|
||||
// double top_left_y1 = (double)(y1 - b1);
|
||||
/*
|
||||
// Check for vertical line
|
||||
if (fabs(x2 - x3) < 0.05)
|
||||
{
|
||||
*x4 = x3;
|
||||
if (y2 < y3)
|
||||
*y4 = (double)(y1 - b1);
|
||||
else
|
||||
*y4 = (double)(y1 + b1);
|
||||
return;
|
||||
}
|
||||
*/
|
||||
// Check that x2 != x3
|
||||
if (fabs(x2 - x3) < 0.05)
|
||||
{
|
||||
*x4 = x2;
|
||||
if (y3 > y2)
|
||||
*y4 = (double)(y1 - sqrt((b1*b1 - (((x2-x1)*(x2-x1))*(b1*b1)/(a1*a1)))));
|
||||
else
|
||||
*y4 = (double)(y1 + sqrt((b1*b1 - (((x2-x1)*(x2-x1))*(b1*b1)/(a1*a1)))));
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate the x and y coordinates of the point where arc intersects ellipse
|
||||
|
||||
double A, B, C, D, E, F, G, H, K;
|
||||
double ellipse1_x, ellipse1_y;
|
||||
|
||||
A = (double)(1/(a1 * a1));
|
||||
B = (double)((y3 - y2) * (y3 - y2)) / ((x3 - x2) * (x3 - x2) * b1 * b1);
|
||||
C = (double)(2 * (y3 - y2) * (y2 - y1)) / ((x3 - x2) * b1 * b1);
|
||||
D = (double)((y2 - y1) * (y2 - y1)) / (b1 * b1);
|
||||
E = (double)(A + B);
|
||||
F = (double)(C - (2 * A * x1) - (2 * B * x2));
|
||||
G = (double)((A * x1 * x1) + (B * x2 * x2) - (C * x2) + D - 1);
|
||||
H = (double)((y3 - y2) / (x3 - x2));
|
||||
K = (double)((F * F) - (4 * E * G));
|
||||
|
||||
if (K >= 0)
|
||||
// In this case the line intersects the ellipse, so calculate intersection
|
||||
{
|
||||
if(x2 >= x1)
|
||||
{
|
||||
ellipse1_x = (double)(((F * -1) + sqrt(K)) / (2 * E));
|
||||
ellipse1_y = (double)((H * (ellipse1_x - x2)) + y2);
|
||||
}
|
||||
else
|
||||
{
|
||||
ellipse1_x = (double)(((F * -1) - sqrt(K)) / (2 * E));
|
||||
ellipse1_y = (double)((H * (ellipse1_x - x2)) + y2);
|
||||
}
|
||||
}
|
||||
else
|
||||
// in this case, arc does not intersect ellipse, so just draw arc
|
||||
{
|
||||
ellipse1_x = x3;
|
||||
ellipse1_y = y3;
|
||||
}
|
||||
*x4 = ellipse1_x;
|
||||
*y4 = ellipse1_y;
|
||||
|
||||
/*
|
||||
// Draw a little circle (radius = 2) at the end of the arc where it hits
|
||||
// the ellipse .
|
||||
|
||||
double circle_x = ellipse1_x - 2.0;
|
||||
double circle_y = ellipse1_y - 2.0;
|
||||
m_canvas->DrawEllipse(circle_x, circle_y, 4.0, 4.0);
|
||||
*/
|
||||
}
|
||||
|
||||
// Update a list item from a list of strings
|
||||
void UpdateListBox(wxListBox *item, wxList *list)
|
||||
{
|
||||
item->Clear();
|
||||
if (!list)
|
||||
return;
|
||||
|
||||
wxNode *node = list->First();
|
||||
while (node)
|
||||
{
|
||||
char *s = (char *)node->Data();
|
||||
item->Append(s);
|
||||
node = node->Next();
|
||||
}
|
||||
}
|
||||
|
||||
bool oglRoughlyEqual(double val1, double val2, double tol)
|
||||
{
|
||||
return ( (val1 < (val2 + tol)) && (val1 > (val2 - tol)) &&
|
||||
(val2 < (val1 + tol)) && (val2 > (val1 - tol)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Hex<->Dec conversion
|
||||
*/
|
||||
|
||||
// Array used in DecToHex conversion routine.
|
||||
static char sg_HexArray[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',
|
||||
'C', 'D', 'E', 'F' };
|
||||
|
||||
// Convert 2-digit hex number to decimal
|
||||
unsigned int oglHexToDec(char* buf)
|
||||
{
|
||||
int firstDigit, secondDigit;
|
||||
|
||||
if (buf[0] >= 'A')
|
||||
firstDigit = buf[0] - 'A' + 10;
|
||||
else
|
||||
firstDigit = buf[0] - '0';
|
||||
|
||||
if (buf[1] >= 'A')
|
||||
secondDigit = buf[1] - 'A' + 10;
|
||||
else
|
||||
secondDigit = buf[1] - '0';
|
||||
|
||||
return firstDigit * 16 + secondDigit;
|
||||
}
|
||||
|
||||
// Convert decimal integer to 2-character hex string
|
||||
void oglDecToHex(unsigned int dec, char *buf)
|
||||
{
|
||||
int firstDigit = (int)(dec/16.0);
|
||||
int secondDigit = (int)(dec - (firstDigit*16.0));
|
||||
buf[0] = sg_HexArray[firstDigit];
|
||||
buf[1] = sg_HexArray[secondDigit];
|
||||
buf[2] = 0;
|
||||
}
|
||||
|
||||
// 3-digit hex to wxColour
|
||||
wxColour oglHexToColour(const wxString& hex)
|
||||
{
|
||||
if (hex.Length() == 6)
|
||||
{
|
||||
char buf[7];
|
||||
strncpy(buf, hex, 7);
|
||||
unsigned int r = oglHexToDec((char *)buf);
|
||||
unsigned int g = oglHexToDec((char *)(buf+2));
|
||||
unsigned int b = oglHexToDec((char *)(buf+4));
|
||||
return wxColour(r, g, b);
|
||||
}
|
||||
else
|
||||
return wxColour(0,0,0);
|
||||
}
|
||||
|
||||
// RGB to 3-digit hex
|
||||
wxString oglColourToHex(const wxColour& colour)
|
||||
{
|
||||
char buf[7];
|
||||
unsigned int red = colour.Red();
|
||||
unsigned int green = colour.Green();
|
||||
unsigned int blue = colour.Blue();
|
||||
|
||||
oglDecToHex(red, buf);
|
||||
oglDecToHex(green, buf+2);
|
||||
oglDecToHex(blue, buf+4);
|
||||
|
||||
return wxString(buf);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user