|
|
|
/***************************************************************************
|
|
|
|
* Copyright (C) 2003-2005 by David Saxton *
|
|
|
|
* david@bluehaze.org *
|
|
|
|
* *
|
|
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
|
|
* it under the terms of the GNU General Public License as published by *
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
|
|
* (at your option) any later version. *
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
#include "circuitdocument.h"
|
|
|
|
#include "connector.h"
|
|
|
|
#include "conrouter.h"
|
|
|
|
#include "cnitem.h"
|
|
|
|
#include "ecnode.h"
|
|
|
|
#include "itemdocumentdata.h"
|
|
|
|
#include "wire.h"
|
|
|
|
|
|
|
|
#include <kdebug.h>
|
|
|
|
|
|
|
|
|
|
|
|
#include <cmath>
|
|
|
|
|
|
|
|
inline static int toCanvas( int pos )
|
|
|
|
{
|
|
|
|
return pos*8+4;
|
|
|
|
}
|
|
|
|
inline static int fromCanvas( int pos )
|
|
|
|
{
|
|
|
|
return (pos-4)/8;
|
|
|
|
// return (pos>0) ? int((pos-3)/8) : int((pos-5)/8);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline static TQPoint toCanvas( const TQPoint * const pos )
|
|
|
|
{
|
|
|
|
return TQPoint( toCanvas(pos->x()), toCanvas(pos->y()) );
|
|
|
|
}
|
|
|
|
inline static TQPoint fromCanvas( const TQPoint * const pos )
|
|
|
|
{
|
|
|
|
return TQPoint( fromCanvas(pos->x()), fromCanvas(pos->y()) );
|
|
|
|
}
|
|
|
|
|
|
|
|
inline static TQPoint toCanvas( const TQPoint &pos )
|
|
|
|
{
|
|
|
|
return TQPoint( toCanvas(pos.x()), toCanvas(pos.y()) );
|
|
|
|
}
|
|
|
|
inline static TQPoint fromCanvas( const TQPoint &pos )
|
|
|
|
{
|
|
|
|
return TQPoint( fromCanvas(pos.x()), fromCanvas(pos.y()) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//BEGIN class Connector
|
|
|
|
Connector::Connector( Node * startNode, Node * endNode, ICNDocument *icnDocument, TQString *id )
|
|
|
|
: TQObject(icnDocument),
|
|
|
|
TQCanvasPolygon( icnDocument->canvas() )
|
|
|
|
{
|
|
|
|
p_icnDocument = icnDocument;
|
|
|
|
m_conRouter = new ConRouter(p_icnDocument);
|
|
|
|
p_parentContainer = 0l;
|
|
|
|
m_startNode = startNode;
|
|
|
|
m_endNode = endNode;
|
|
|
|
p_nodeGroup = 0l;
|
|
|
|
b_semiHidden = false;
|
|
|
|
b_deleted = false;
|
|
|
|
b_pointsAdded = false;
|
|
|
|
b_manualPoints = false;
|
|
|
|
m_bIsSyncingWires = false;
|
|
|
|
|
|
|
|
if (id)
|
|
|
|
{
|
|
|
|
m_id = *id;
|
|
|
|
if ( !p_icnDocument->registerUID(*id) )
|
|
|
|
{
|
|
|
|
// kdDebug() << k_funcinfo << "KTechlab: Connector attempted to register given ID, but ID already in use"<<endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
m_id = p_icnDocument->generateUID("connector");
|
|
|
|
|
|
|
|
p_icnDocument->registerItem(this);
|
|
|
|
|
|
|
|
p_icnDocument->requestRerouteInvalidatedConnectors();
|
|
|
|
setVisible(true);
|
|
|
|
|
|
|
|
ECNode * startECNode = dynamic_cast<ECNode*>(startNode);
|
|
|
|
ECNode * endECNode = dynamic_cast<ECNode*>(endNode);
|
|
|
|
if ( startECNode && endECNode )
|
|
|
|
{
|
|
|
|
connect( startECNode, TQT_SIGNAL(numPinsChanged(unsigned)), this, TQT_SLOT(syncWiresWithNodes()) );
|
|
|
|
connect( endECNode, TQT_SIGNAL(numPinsChanged(unsigned)), this, TQT_SLOT(syncWiresWithNodes()) );
|
|
|
|
syncWiresWithNodes();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Connector::~Connector()
|
|
|
|
{
|
|
|
|
p_icnDocument->unregisterUID( id() );
|
|
|
|
|
|
|
|
delete m_conRouter;
|
|
|
|
m_conRouter = 0l;
|
|
|
|
|
|
|
|
for ( unsigned i = 0; i < m_wires.size(); i++ )
|
|
|
|
delete m_wires[i];
|
|
|
|
m_wires.resize(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Connector::rtti() const
|
|
|
|
{
|
|
|
|
return ItemDocument::RTTI::Connector;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Connector::syncWiresWithNodes()
|
|
|
|
{
|
|
|
|
ECNode * startECNode = dynamic_cast<ECNode*>((Node*)m_startNode);
|
|
|
|
ECNode * endECNode = dynamic_cast<ECNode*>((Node*)m_endNode);
|
|
|
|
|
|
|
|
if ( !startECNode || !endECNode )
|
|
|
|
return;
|
|
|
|
|
|
|
|
unsigned newNumWires = 0;
|
|
|
|
|
|
|
|
if ( startECNode->type() == Node::ec_junction ||
|
|
|
|
endECNode->type() == Node::ec_junction )
|
|
|
|
newNumWires = TQMAX( startECNode->numPins(), endECNode->numPins() );
|
|
|
|
|
|
|
|
else
|
|
|
|
newNumWires = TQMIN( startECNode->numPins(), endECNode->numPins() );
|
|
|
|
|
|
|
|
unsigned oldNumWires = m_wires.size();
|
|
|
|
|
|
|
|
if ( newNumWires == oldNumWires )
|
|
|
|
return;
|
|
|
|
|
|
|
|
m_bIsSyncingWires = true;
|
|
|
|
if ( startECNode->type() == Node::ec_junction )
|
|
|
|
startECNode->setNumPins(newNumWires);
|
|
|
|
if ( endECNode->type() == Node::ec_junction )
|
|
|
|
endECNode->setNumPins(newNumWires);
|
|
|
|
m_bIsSyncingWires = false;
|
|
|
|
|
|
|
|
if ( newNumWires > oldNumWires )
|
|
|
|
{
|
|
|
|
m_wires.resize(newNumWires);
|
|
|
|
for ( unsigned i = oldNumWires; i < newNumWires; i++ )
|
|
|
|
{
|
|
|
|
if ( startECNode->pin(i) && endECNode->pin(i) )
|
|
|
|
m_wires[i] = new Wire( startECNode->pin(i), endECNode->pin(i) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for ( unsigned i = newNumWires; i < oldNumWires; i++ )
|
|
|
|
delete m_wires[i];
|
|
|
|
m_wires.resize(newNumWires);
|
|
|
|
}
|
|
|
|
|
|
|
|
updateConnectorLines();
|
|
|
|
emit numWiresChanged(newNumWires);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Connector::setParentContainer( const TQString &cnItemId )
|
|
|
|
{
|
|
|
|
// // We only allow the node to be parented once
|
|
|
|
// if ( p_parentContainer || !ICNDocument->itemWithID(cnItemId) ) return;
|
|
|
|
p_parentContainer = p_icnDocument->cnItemWithID(cnItemId);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Connector::removeConnector( Node* )
|
|
|
|
{
|
|
|
|
if (b_deleted)
|
|
|
|
return;
|
|
|
|
b_deleted = true;
|
|
|
|
|
|
|
|
// Remove 'penalty' points for this connector from the ICNDocument
|
|
|
|
updateConnectorPoints(false);
|
|
|
|
|
|
|
|
emit selected(false);
|
|
|
|
emit removed(this);
|
|
|
|
if ( m_startNode )
|
|
|
|
m_startNode->removeConnector(this);
|
|
|
|
if ( m_endNode )
|
|
|
|
m_endNode->removeConnector(this);
|
|
|
|
p_icnDocument->appendDeleteList(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int getSlope( float x1, float y1, float x2, float y2 )
|
|
|
|
{
|
|
|
|
enum slope
|
|
|
|
{
|
|
|
|
s_n = 0,// .
|
|
|
|
s_v, // |
|
|
|
|
s_h, // -
|
|
|
|
s_s, // /
|
|
|
|
s_d // \ (backwards slash)
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
if ( x1 == x2 )
|
|
|
|
{
|
|
|
|
if ( y1 == y2 ) {
|
|
|
|
return s_n;
|
|
|
|
}
|
|
|
|
return s_v;
|
|
|
|
}
|
|
|
|
else if ( y1 == y2 ) {
|
|
|
|
return s_h;
|
|
|
|
}
|
|
|
|
else if ( (y2-y1)/(x2-x1) > 0 ) {
|
|
|
|
return s_s;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return s_d;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Connector::updateDrawList()
|
|
|
|
{
|
|
|
|
if ( !m_startNode || !m_endNode || !canvas() ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQPointList drawLineList;
|
|
|
|
|
|
|
|
int prevX = (*m_conRouter->cellPointList()->begin()).x();
|
|
|
|
int prevY = (*m_conRouter->cellPointList()->begin()).y();
|
|
|
|
|
|
|
|
int prevX_canvas = toCanvas(prevX);
|
|
|
|
int prevY_canvas = toCanvas(prevY);
|
|
|
|
|
|
|
|
Cells *cells = p_icnDocument->cells();
|
|
|
|
|
|
|
|
bool bumpNow = false;
|
|
|
|
const TQPointList::const_iterator cplEnd = m_conRouter->cellPointList()->end();
|
|
|
|
for ( TQPointList::const_iterator it = m_conRouter->cellPointList()->begin(); it != cplEnd; ++it )
|
|
|
|
{
|
|
|
|
const int x = (*it).x();
|
|
|
|
const int y = (*it).y();
|
|
|
|
const int numCon = p_icnDocument->isValidCellReference(x,y) ? (*cells)[x][y].numCon : 0;
|
|
|
|
|
|
|
|
const int y_canvas = toCanvas(y);
|
|
|
|
const int x_canvas = toCanvas(x);
|
|
|
|
|
|
|
|
const bool bumpNext = ( prevX == x &&
|
|
|
|
numCon > 1 &&
|
|
|
|
std::abs(y_canvas-m_startNode->y())>8 &&
|
|
|
|
std::abs(y_canvas-m_endNode->y())>8 );
|
|
|
|
|
|
|
|
int x0 = prevX_canvas;
|
|
|
|
int x2 = x_canvas;
|
|
|
|
int x1 = (x0+x2)/2;
|
|
|
|
|
|
|
|
int y0 = prevY_canvas;
|
|
|
|
int y3 = y_canvas;
|
|
|
|
int y1 = ( y0 == y3 ) ? y0 : ((y0<y3) ? y0+3 : y0-3);
|
|
|
|
int y2 = ( y0 == y3 ) ? y3 : ((y0<y3) ? y3-3 : y3+3);
|
|
|
|
|
|
|
|
if (bumpNow) x0 += 3;
|
|
|
|
if (bumpNext) x2 += 3;
|
|
|
|
|
|
|
|
if ( !bumpNow && !bumpNext )
|
|
|
|
{
|
|
|
|
drawLineList += TQPoint( x0, y0 );
|
|
|
|
drawLineList += TQPoint( x2, y3 );
|
|
|
|
}
|
|
|
|
else if (bumpNow)
|
|
|
|
{
|
|
|
|
drawLineList += TQPoint( x0, y0 );
|
|
|
|
drawLineList += TQPoint( x1, y1 );
|
|
|
|
drawLineList += TQPoint( x2, y3 );
|
|
|
|
}
|
|
|
|
else if (bumpNext)
|
|
|
|
{
|
|
|
|
drawLineList += TQPoint( x0, y0 );
|
|
|
|
drawLineList += TQPoint( x1, y2 );
|
|
|
|
drawLineList += TQPoint( x2, y3 );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
drawLineList += TQPoint( x0, y0 );
|
|
|
|
drawLineList += TQPoint( x1, y1 );
|
|
|
|
drawLineList += TQPoint( x1, y2 );
|
|
|
|
drawLineList += TQPoint( x2, y3 );
|
|
|
|
}
|
|
|
|
|
|
|
|
prevX = x;
|
|
|
|
prevY = y;
|
|
|
|
prevY_canvas = y_canvas;
|
|
|
|
prevX_canvas = x_canvas;
|
|
|
|
bumpNow = bumpNext;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now, remove redundant points (i.e. those that are either repeated or are
|
|
|
|
// in the same direction as the previous points)
|
|
|
|
|
|
|
|
if ( drawLineList.size() < 3 ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const TQPointList::iterator dllEnd = drawLineList.end();
|
|
|
|
|
|
|
|
TQPointList::iterator previous = drawLineList.begin();
|
|
|
|
|
|
|
|
TQPointList::iterator current = previous;
|
|
|
|
current++;
|
|
|
|
|
|
|
|
TQPointList::const_iterator next = current;
|
|
|
|
next++;
|
|
|
|
|
|
|
|
while ( previous != dllEnd && current != dllEnd && next != dllEnd )
|
|
|
|
{
|
|
|
|
const int slope1 = getSlope( (*previous).x(), (*previous).y(), (*current).x(), (*current).y() );
|
|
|
|
const int slope2 = getSlope( (*current).x(), (*current).y(), (*next).x(), (*next).y() );
|
|
|
|
|
|
|
|
if ( slope1 == slope2 || slope1 == 0 || slope2 == 0 )
|
|
|
|
{
|
|
|
|
*current = TQPoint( -1, -1 );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
previous = current;
|
|
|
|
}
|
|
|
|
|
|
|
|
current++;
|
|
|
|
next++;
|
|
|
|
}
|
|
|
|
|
|
|
|
drawLineList.remove( TQPoint( -1, -1 ) );
|
|
|
|
|
|
|
|
// Find the bounding rect
|
|
|
|
{
|
|
|
|
int x1=-1, y1=-1, x2=-1, y2=-1;
|
|
|
|
const TQPointList::iterator end = drawLineList.end();
|
|
|
|
for ( TQPointList::iterator it = drawLineList.begin(); it != end; ++it )
|
|
|
|
{
|
|
|
|
const TQPoint p = *it;
|
|
|
|
if ( p.x() < x1 || x1 == -1 ) {
|
|
|
|
x1 = p.x();
|
|
|
|
}
|
|
|
|
if ( p.x() > x2 || x2 == -1 ) {
|
|
|
|
x2 = p.x();
|
|
|
|
}
|
|
|
|
if ( p.y() < y1 || y1 == -1 ) {
|
|
|
|
y1 = p.y();
|
|
|
|
}
|
|
|
|
if ( p.y() > y2 || y2 == -1 ) {
|
|
|
|
y2 = p.y();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TQRect boundRect( x1, y1, x2-x1, y2-y1 );
|
|
|
|
if ( boundRect != m_oldBoundRect )
|
|
|
|
{
|
|
|
|
canvas()->setChanged( boundRect | m_oldBoundRect );
|
|
|
|
m_oldBoundRect = boundRect;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//BEGIN build up ConnectorLine list
|
|
|
|
const ConnectorLineList::iterator ConnectorLineEnd = m_connectorLineList.end();
|
|
|
|
for ( ConnectorLineList::iterator it = m_connectorLineList.begin(); it != ConnectorLineEnd; ++it )
|
|
|
|
delete *it;
|
|
|
|
m_connectorLineList.clear();
|
|
|
|
|
|
|
|
if ( drawLineList.size() > 1 )
|
|
|
|
{
|
|
|
|
TQPoint prev = drawLineList.first();
|
|
|
|
const TQPointList::iterator end = drawLineList.end();
|
|
|
|
for ( TQPointList::iterator it = ++drawLineList.begin(); it != end; ++it )
|
|
|
|
{
|
|
|
|
const TQPoint next = *it;
|
|
|
|
ConnectorLine *line = new ConnectorLine(this);
|
|
|
|
line->setPoints( prev.x(), prev.y(), next.x(), next.y() );
|
|
|
|
m_connectorLineList.append(line);
|
|
|
|
prev = next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
updateConnectorLines();
|
|
|
|
//END build up ConnectorPoint list
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Connector::setSemiHidden( bool semiHidden )
|
|
|
|
{
|
|
|
|
if ( !canvas() || semiHidden == b_semiHidden )
|
|
|
|
return;
|
|
|
|
|
|
|
|
b_semiHidden = semiHidden;
|
|
|
|
updateConnectorLines();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Connector::updateConnectorPoints( bool add )
|
|
|
|
{
|
|
|
|
if (!canvas()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( b_deleted || !isVisible() )
|
|
|
|
add = false;
|
|
|
|
|
|
|
|
// Check we haven't already added/removed the points...
|
|
|
|
if ( b_pointsAdded == add )
|
|
|
|
return;
|
|
|
|
|
|
|
|
b_pointsAdded = add;
|
|
|
|
|
|
|
|
// We don't include the end points in the mapping
|
|
|
|
if ( m_conRouter->cellPointList()->size() < 3 ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const int mult = (add)?1:-1;
|
|
|
|
const TQPointList::iterator end = --m_conRouter->cellPointList()->end();
|
|
|
|
for ( TQPointList::iterator it = ++m_conRouter->cellPointList()->begin(); it != end; ++it )
|
|
|
|
{
|
|
|
|
int x = (*it).x();
|
|
|
|
int y = (*it).y();
|
|
|
|
|
|
|
|
// Add the points of this connector to the cell array in the ICNDocument,
|
|
|
|
// so that other connectors still to calculate their points know to try
|
|
|
|
// and avoid this connector
|
|
|
|
|
|
|
|
p_icnDocument->addCPenalty( x, y-1, mult*ICNDocument::hs_connector/2 );
|
|
|
|
p_icnDocument->addCPenalty( x-1, y, mult*ICNDocument::hs_connector/2 );
|
|
|
|
p_icnDocument->addCPenalty( x, y, mult*ICNDocument::hs_connector );
|
|
|
|
p_icnDocument->addCPenalty( x+1, y, mult*ICNDocument::hs_connector/2 );
|
|
|
|
p_icnDocument->addCPenalty( x, y+1, mult*ICNDocument::hs_connector/2 );
|
|
|
|
|
|
|
|
if ( p_icnDocument->isValidCellReference( x, y ) ) {
|
|
|
|
(*p_icnDocument->cells())[x][y].numCon += mult;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// updateDrawList();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Connector::setRoutePoints( TQPointList pointList, bool setManual, bool checkEndPoints )
|
|
|
|
{
|
|
|
|
if (!canvas()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
updateConnectorPoints(false);
|
|
|
|
|
|
|
|
bool reversed = pointsAreReverse(pointList);
|
|
|
|
if (checkEndPoints)
|
|
|
|
{
|
|
|
|
if (reversed)
|
|
|
|
{
|
|
|
|
pointList.prepend( TQPoint( int(m_endNode->x()), int(m_endNode->y()) ) );
|
|
|
|
pointList.append( TQPoint( int(m_startNode->x()), int(m_startNode->y()) ) );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pointList.prepend( TQPoint( int(m_startNode->x()), int(m_startNode->y()) ) );
|
|
|
|
pointList.append( TQPoint( int(m_endNode->x()), int(m_endNode->y()) ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m_conRouter->setPoints( pointList, reversed );
|
|
|
|
b_manualPoints = setManual;
|
|
|
|
updateConnectorPoints(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Connector::pointsAreReverse( const TQPointList &pointList ) const
|
|
|
|
{
|
|
|
|
if ( !m_startNode || !m_endNode )
|
|
|
|
{
|
|
|
|
kdWarning() << k_funcinfo << "Cannot determine orientation as no start and end nodes" << endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( pointList.isEmpty() )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
int plsx = pointList.first().x();
|
|
|
|
int plsy = pointList.first().y();
|
|
|
|
int plex = pointList.last().x();
|
|
|
|
int pley = pointList.last().y();
|
|
|
|
|
|
|
|
double nsx = m_startNode->x();
|
|
|
|
double nsy = m_startNode->y();
|
|
|
|
double nex = m_endNode->x();
|
|
|
|
double ney = m_endNode->y();
|
|
|
|
|
|
|
|
double dist_normal = (nsx-plsx)*(nsx-plsx) + (nsy-plsy)*(nsy-plsy) + (nex-plex)*(nex-plex) + (ney-pley)*(ney-pley);
|
|
|
|
double dist_reverse = (nsx-plex)*(nsx-plex) + (nsy-pley)*(nsy-pley) + (nex-plsx)*(nex-plsx) + (ney-plsy)*(ney-plsy);
|
|
|
|
|
|
|
|
return dist_reverse < dist_normal;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Connector::rerouteConnector()
|
|
|
|
{
|
|
|
|
if (!isVisible())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if ( nodeGroup() )
|
|
|
|
{
|
|
|
|
kdWarning() << k_funcinfo << "Connector is controlled by a NodeGroup! Use that to reroute the connector" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !startNode() || !endNode() )
|
|
|
|
return;
|
|
|
|
|
|
|
|
updateConnectorPoints(false);
|
|
|
|
m_conRouter->mapRoute( int(startNode()->x()), int(startNode()->y()), int(endNode()->x()), int(endNode()->y()) );
|
|
|
|
b_manualPoints = false;
|
|
|
|
updateConnectorPoints(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Connector::translateRoute( int dx, int dy )
|
|
|
|
{
|
|
|
|
updateConnectorPoints(false);
|
|
|
|
m_conRouter->translateRoute( dx, dy );
|
|
|
|
updateConnectorPoints(true);
|
|
|
|
updateDrawList();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Connector::restoreFromConnectorData( const ConnectorData &connectorData )
|
|
|
|
{
|
|
|
|
updateConnectorPoints(false);
|
|
|
|
b_manualPoints = connectorData.manualRoute;
|
|
|
|
m_conRouter->setRoutePoints( connectorData.route );
|
|
|
|
updateConnectorPoints(true);
|
|
|
|
updateDrawList();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ConnectorData Connector::connectorData() const
|
|
|
|
{
|
|
|
|
ConnectorData connectorData;
|
|
|
|
if ( !m_startNode || !m_endNode )
|
|
|
|
{
|
|
|
|
kdDebug() << k_funcinfo << " m_startNode="<<m_startNode<<" m_endNode="<<m_endNode<<endl;
|
|
|
|
return connectorData;
|
|
|
|
}
|
|
|
|
|
|
|
|
connectorData.manualRoute = usesManualPoints();
|
|
|
|
connectorData.route = *m_conRouter->cellPointList();
|
|
|
|
|
|
|
|
if ( m_startNode->isChildNode() )
|
|
|
|
{
|
|
|
|
connectorData.startNodeIsChild = true;
|
|
|
|
connectorData.startNodeCId = m_startNode->childId();
|
|
|
|
connectorData.startNodeParent = m_startNode->parentItem()->id();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
connectorData.startNodeIsChild = false;
|
|
|
|
connectorData.startNodeId = m_startNode->id();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( m_endNode->isChildNode() )
|
|
|
|
{
|
|
|
|
connectorData.endNodeIsChild = true;
|
|
|
|
connectorData.endNodeCId = m_endNode->childId();
|
|
|
|
connectorData.endNodeParent = m_endNode->parentItem()->id();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
connectorData.endNodeIsChild = false;
|
|
|
|
connectorData.endNodeId = m_endNode->id();
|
|
|
|
}
|
|
|
|
|
|
|
|
return connectorData;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Connector::setVisible( bool yes )
|
|
|
|
{
|
|
|
|
if ( !canvas() || isVisible() == yes )
|
|
|
|
return;
|
|
|
|
|
|
|
|
TQCanvasPolygon::tqsetVisible(yes);
|
|
|
|
updateConnectorLines();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Connector::setSelected( bool yes )
|
|
|
|
{
|
|
|
|
if ( !canvas() || isSelected() == yes )
|
|
|
|
return;
|
|
|
|
|
|
|
|
TQCanvasPolygon::setSelected(yes);
|
|
|
|
updateConnectorLines();
|
|
|
|
emit selected(yes);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Connector::updateConnectorLines()
|
|
|
|
{
|
|
|
|
const TQColor color = b_semiHidden ? TQt::gray : (isSelected() ? TQColor( 101, 134, 192 ) : TQt::black);
|
|
|
|
// const TQColor color = b_semiHidden ? TQt::gray : (isSelected() ? TQColor( 0x7f, 0x7f, 0xff ) : TQt::black);
|
|
|
|
const int z = ICNDocument::Z::Connector + (isSelected() ? 5 : 0);
|
|
|
|
|
|
|
|
TQPen pen( color, (numWires() > 1) ? 2 : 1 );
|
|
|
|
|
|
|
|
const ConnectorLineList::iterator end = m_connectorLineList.end();
|
|
|
|
for ( ConnectorLineList::iterator it = m_connectorLineList.begin(); it != end; ++it )
|
|
|
|
{
|
|
|
|
TQCanvasPolygonalItem *item = static_cast<TQCanvasPolygonalItem*>(*it);
|
|
|
|
item->setZ(z);
|
|
|
|
item->setPen(pen);
|
|
|
|
item->setBrush(color);
|
|
|
|
item->tqsetVisible( isVisible() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQValueList<TQPointList> Connector::splitConnectorPoints( const TQPoint & pos ) const
|
|
|
|
{
|
|
|
|
return m_conRouter->splitPoints(pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQPointList Connector::connectorPoints( bool reverse ) const
|
|
|
|
{
|
|
|
|
bool doReverse = (reverse != pointsAreReverse( m_conRouter->pointList(false) ));
|
|
|
|
return m_conRouter->pointList(doReverse);
|
|
|
|
}
|
|
|
|
//END class Connector
|
|
|
|
|
|
|
|
|
|
|
|
//BEGIN class ConnectorLine
|
|
|
|
ConnectorLine::ConnectorLine( Connector *connector )
|
|
|
|
: TQObject(connector), TQCanvasLine( connector->canvas() )
|
|
|
|
{
|
|
|
|
p_connector = connector;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int ConnectorLine::rtti() const
|
|
|
|
{
|
|
|
|
return ICNDocument::RTTI::ConnectorLine;
|
|
|
|
}
|
|
|
|
//END class ConnectorLine
|
|
|
|
|
|
|
|
#include "connector.moc"
|