⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lines.cpp

📁 Wxpython Implemented on Windows CE, Source code
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/////////////////////////////////////////////////////////////////////////////
// Name:        lines.cpp
// Purpose:     wxLineShape
// Author:      Julian Smart
// Modified by:
// Created:     12/07/98
// RCS-ID:      $Id: lines.cpp,v 1.27 2006/04/18 22:26:26 PC Exp $
// Copyright:   (c) Julian Smart
// Licence:     wxWindows licence
/////////////////////////////////////////////////////////////////////////////

// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
#pragma hdrstop
#endif

#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif

#if wxUSE_PROLOGIO
#include "wx/deprecated/wxexpr.h"
#endif

#ifdef new
#undef new
#endif

#include <ctype.h>

#include "wx/ogl/ogl.h"


// Line shape
IMPLEMENT_DYNAMIC_CLASS(wxLineShape, wxShape)

wxLineShape::wxLineShape()
{
  m_sensitivity = OP_CLICK_LEFT | OP_CLICK_RIGHT;
  m_draggable = false;
  m_attachmentTo = 0;
  m_attachmentFrom = 0;
/*
  m_actualTextWidth = 0.0;
  m_actualTextHeight = 0.0;
*/
  m_from = NULL;
  m_to = NULL;
  m_erasing = false;
  m_arrowSpacing = 5.0; // For the moment, don't bother saving this to file.
  m_ignoreArrowOffsets = false;
  m_isSpline = false;
  m_maintainStraightLines = false;
  m_alignmentStart = 0;
  m_alignmentEnd = 0;

  m_lineControlPoints = NULL;

  // Clear any existing regions (created in an earlier constructor)
  // and make the three line regions.
  ClearRegions();
  wxShapeRegion *newRegion = new wxShapeRegion;
  newRegion->SetName(wxT("Middle"));
  newRegion->SetSize(150, 50);
  m_regions.Append((wxObject *)newRegion);

  newRegion = new wxShapeRegion;
  newRegion->SetName(wxT("Start"));
  newRegion->SetSize(150, 50);
  m_regions.Append((wxObject *)newRegion);

  newRegion = new wxShapeRegion;
  newRegion->SetName(wxT("End"));
  newRegion->SetSize(150, 50);
  m_regions.Append((wxObject *)newRegion);

  for (int i = 0; i < 3; i++)
    m_labelObjects[i] = NULL;
}

wxLineShape::~wxLineShape()
{
  if (m_lineControlPoints)
  {
    ClearPointList(*m_lineControlPoints);
    delete m_lineControlPoints;
  }
  for (int i = 0; i < 3; i++)
  {
    if (m_labelObjects[i])
    {
      m_labelObjects[i]->Select(false);
      m_labelObjects[i]->RemoveFromCanvas(m_canvas);
      delete m_labelObjects[i];
      m_labelObjects[i] = NULL;
    }
  }
  ClearArrowsAtPosition(-1);
}

void wxLineShape::MakeLineControlPoints(int n)
{
  if (m_lineControlPoints)
  {
    ClearPointList(*m_lineControlPoints);
    delete m_lineControlPoints;
  }
  m_lineControlPoints = new wxList;

  for (int i = 0; i < n; i++)
  {
    wxRealPoint *point = new wxRealPoint(-999, -999);
    m_lineControlPoints->Append((wxObject*) point);
  }
}

wxNode *wxLineShape::InsertLineControlPoint(wxDC* dc)
{
    if (dc)
        Erase(*dc);

  wxNode *last = m_lineControlPoints->GetLast();
  wxNode *second_last = last->GetPrevious();
  wxRealPoint *last_point = (wxRealPoint *)last->GetData();
  wxRealPoint *second_last_point = (wxRealPoint *)second_last->GetData();

  // Choose a point half way between the last and penultimate points
  double line_x = ((last_point->x + second_last_point->x)/2);
  double line_y = ((last_point->y + second_last_point->y)/2);

  wxRealPoint *point = new wxRealPoint(line_x, line_y);
  wxNode *node = m_lineControlPoints->Insert(last, (wxObject*) point);
  return node;
}

bool wxLineShape::DeleteLineControlPoint()
{
  if (m_lineControlPoints->GetCount() < 3)
    return false;

  wxNode *last = m_lineControlPoints->GetLast();
  wxNode *second_last = last->GetPrevious();

  wxRealPoint *second_last_point = (wxRealPoint *)second_last->GetData();
  delete second_last_point;
  delete second_last;

  return true;
}

void wxLineShape::Initialise()
{
  if (m_lineControlPoints)
  {
    // Just move the first and last control points
    wxNode *first = m_lineControlPoints->GetFirst();
    wxRealPoint *first_point = (wxRealPoint *)first->GetData();

    wxNode *last = m_lineControlPoints->GetLast();
    wxRealPoint *last_point = (wxRealPoint *)last->GetData();

    // If any of the line points are at -999, we must
    // initialize them by placing them half way between the first
    // and the last.
    wxNode *node = first->GetNext();
    while (node)
    {
      wxRealPoint *point = (wxRealPoint *)node->GetData();
      if (point->x == -999)
      {
        double x1, y1, x2, y2;
        if (first_point->x < last_point->x)
          { x1 = first_point->x; x2 = last_point->x; }
        else
          { x2 = first_point->x; x1 = last_point->x; }

        if (first_point->y < last_point->y)
          { y1 = first_point->y; y2 = last_point->y; }
        else
          { y2 = first_point->y; y1 = last_point->y; }

        point->x = ((x2 - x1)/2 + x1);
        point->y = ((y2 - y1)/2 + y1);
      }
      node = node->GetNext();
    }
  }
}

// Format a text string according to the region size, adding
// strings with positions to region text list
void wxLineShape::FormatText(wxDC& dc, const wxString& s, int i)
{
  double w, h;
  ClearText(i);

  if (m_regions.GetCount() < 1)
    return;
  wxNode *node = m_regions.Item(i);
  if (!node)
    return;

  wxShapeRegion *region = (wxShapeRegion *)node->GetData();
  region->SetText(s);
  dc.SetFont(* region->GetFont());

  region->GetSize(&w, &h);
  // Initialize the size if zero
  if (((w == 0) || (h == 0)) && (s.Length() > 0))
  {
    w = 100; h = 50;
    region->SetSize(w, h);
  }

  wxStringList *string_list = oglFormatText(dc, s, (w-5), (h-5), region->GetFormatMode());
  node = (wxNode*)string_list->GetFirst();
  while (node)
  {
    wxChar *s = (wxChar *)node->GetData();
    wxShapeTextLine *line = new wxShapeTextLine(0.0, 0.0, s);
    region->GetFormattedText().Append((wxObject *)line);
    node = node->GetNext();
  }
  delete string_list;
  double actualW = w;
  double actualH = h;
  if (region->GetFormatMode() & FORMAT_SIZE_TO_CONTENTS)
  {
    oglGetCentredTextExtent(dc, &(region->GetFormattedText()), m_xpos, m_ypos, w, h, &actualW, &actualH);
    if ((actualW != w ) || (actualH != h))
    {
      double xx, yy;
      GetLabelPosition(i, &xx, &yy);
      EraseRegion(dc, region, xx, yy);
      if (m_labelObjects[i])
      {
        m_labelObjects[i]->Select(false, &dc);
        m_labelObjects[i]->Erase(dc);
        m_labelObjects[i]->SetSize(actualW, actualH);
      }

      region->SetSize(actualW, actualH);

      if (m_labelObjects[i])
      {
        m_labelObjects[i]->Select(true, & dc);
        m_labelObjects[i]->Draw(dc);
      }
    }
  }
  oglCentreText(dc, &(region->GetFormattedText()), m_xpos, m_ypos, actualW, actualH, region->GetFormatMode());
  m_formatted = true;
}

void wxLineShape::DrawRegion(wxDC& dc, wxShapeRegion *region, double x, double y)
{
  if (GetDisableLabel())
    return;

  double w, h;
  double xx, yy;
  region->GetSize(&w, &h);

  // Get offset from x, y
  region->GetPosition(&xx, &yy);

  double xp = xx + x;
  double yp = yy + y;

  // First, clear a rectangle for the text IF there is any
  if (region->GetFormattedText().GetCount() > 0)
  {
      dc.SetPen(GetBackgroundPen());
      dc.SetBrush(GetBackgroundBrush());

      // Now draw the text
      if (region->GetFont()) dc.SetFont(* region->GetFont());

      dc.DrawRectangle((long)(xp - w/2.0), (long)(yp - h/2.0), (long)w, (long)h);

      if (m_pen) dc.SetPen(* m_pen);
      dc.SetTextForeground(region->GetActualColourObject());

#ifdef __WXMSW__
      dc.SetTextBackground(GetBackgroundBrush().GetColour());
#endif

      oglDrawFormattedText(dc, &(region->GetFormattedText()), xp, yp, w, h, region->GetFormatMode());
  }
}

void wxLineShape::EraseRegion(wxDC& dc, wxShapeRegion *region, double x, double y)
{
  if (GetDisableLabel())
    return;

  double w, h;
  double xx, yy;
  region->GetSize(&w, &h);

  // Get offset from x, y
  region->GetPosition(&xx, &yy);

  double xp = xx + x;
  double yp = yy + y;

  if (region->GetFormattedText().GetCount() > 0)
  {
      dc.SetPen(GetBackgroundPen());
      dc.SetBrush(GetBackgroundBrush());

      dc.DrawRectangle((long)(xp - w/2.0), (long)(yp - h/2.0), (long)w, (long)h);
  }
}

// Get the reference point for a label. Region x and y
// are offsets from this.
// position is 0, 1, 2
void wxLineShape::GetLabelPosition(int position, double *x, double *y)
{
  switch (position)
  {
    case 0:
    {
      // Want to take the middle section for the label
      int n = m_lineControlPoints->GetCount();
      int half_way = (int)(n/2);

      // Find middle of this line
      wxNode *node = m_lineControlPoints->Item(half_way - 1);
      wxRealPoint *point = (wxRealPoint *)node->GetData();
      wxNode *next_node = node->GetNext();
      wxRealPoint *next_point = (wxRealPoint *)next_node->GetData();

      double dx = (next_point->x - point->x);
      double dy = (next_point->y - point->y);
      *x = (double)(point->x + dx/2.0);
      *y = (double)(point->y + dy/2.0);
      break;
    }
    case 1:
    {
      wxNode *node = m_lineControlPoints->GetFirst();
      *x = ((wxRealPoint *)node->GetData())->x;
      *y = ((wxRealPoint *)node->GetData())->y;
      break;
    }
    case 2:
    {
      wxNode *node = m_lineControlPoints->GetLast();
      *x = ((wxRealPoint *)node->GetData())->x;
      *y = ((wxRealPoint *)node->GetData())->y;
      break;
    }
    default:
      break;
  }
}

/*
 * Find whether line is supposed to be vertical or horizontal and
 * make it so.
 *
 */
void GraphicsStraightenLine(wxRealPoint *point1, wxRealPoint *point2)
{
  double dx = point2->x - point1->x;
  double dy = point2->y - point1->y;

  if (dx == 0.0)
    return;
  else if (fabs(dy/dx) > 1.0)
  {
    point2->x = point1->x;
  }
  else point2->y = point1->y;
}

void wxLineShape::Straighten(wxDC *dc)
{
  if (!m_lineControlPoints || m_lineControlPoints->GetCount() < 3)
    return;

  if (dc)
    Erase(* dc);

  wxNode *first_point_node = m_lineControlPoints->GetFirst();
  wxNode *last_point_node = m_lineControlPoints->GetLast();
  wxNode *second_last_point_node = last_point_node->GetPrevious();

  wxRealPoint *last_point = (wxRealPoint *)last_point_node->GetData();
  wxRealPoint *second_last_point = (wxRealPoint *)second_last_point_node->GetData();

  GraphicsStraightenLine(last_point, second_last_point);

  wxNode *node = first_point_node;
  while (node && (node != second_last_point_node))
  {
    wxRealPoint *point = (wxRealPoint *)node->GetData();
    wxRealPoint *next_point = (wxRealPoint *)(node->GetNext()->GetData());

    GraphicsStraightenLine(point, next_point);
    node = node->GetNext();
  }

  if (dc)
    Draw(* dc);
}


void wxLineShape::Unlink()
{
  if (m_to)
    m_to->GetLines().DeleteObject(this);
  if (m_from)
    m_from->GetLines().DeleteObject(this);
  m_to = NULL;
  m_from = NULL;
}

void wxLineShape::SetEnds(double x1, double y1, double x2, double y2)
{
  // Find centre point
  wxNode *first_point_node = m_lineControlPoints->GetFirst();
  wxNode *last_point_node = m_lineControlPoints->GetLast();
  wxRealPoint *first_point = (wxRealPoint *)first_point_node->GetData();
  wxRealPoint *last_point = (wxRealPoint *)last_point_node->GetData();

  first_point->x = x1;
  first_point->y = y1;
  last_point->x = x2;
  last_point->y = y2;

  m_xpos = (double)((x1 + x2)/2.0);
  m_ypos = (double)((y1 + y2)/2.0);
}

// Get absolute positions of ends
void wxLineShape::GetEnds(double *x1, double *y1, double *x2, double *y2)
{
  wxNode *first_point_node = m_lineControlPoints->GetFirst();
  wxNode *last_point_node = m_lineControlPoints->GetLast();
  wxRealPoint *first_point = (wxRealPoint *)first_point_node->GetData();
  wxRealPoint *last_point = (wxRealPoint *)last_point_node->GetData();

  *x1 = first_point->x; *y1 = first_point->y;
  *x2 = last_point->x; *y2 = last_point->y;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -