summaryrefslogtreecommitdiffstats
path: root/src/electronics/ecnode.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/electronics/ecnode.cpp')
-rw-r--r--src/electronics/ecnode.cpp239
1 files changed, 239 insertions, 0 deletions
diff --git a/src/electronics/ecnode.cpp b/src/electronics/ecnode.cpp
new file mode 100644
index 0000000..0fb2801
--- /dev/null
+++ b/src/electronics/ecnode.cpp
@@ -0,0 +1,239 @@
+/***************************************************************************
+ * 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 "src/core/ktlconfig.h"
+#include "component.h"
+#include "connector.h"
+#include "ecnode.h"
+#include "pin.h"
+
+#include <kdebug.h>
+#include <qpainter.h>
+
+#include <cmath>
+
+// The voltage at the middle of the voltage indicator
+const double vMidPoint = 5.;
+
+// The maximum length of the voltage indiactor
+const int vLength = 8;
+
+// The current at the middle of the current indicator
+const double iMidPoint = 0.03;
+
+// The maximum thicnkess of the current indicator
+const int iLength = 6;
+
+inline double calcVProp( const double v )
+{
+ return 1 - vMidPoint/(vMidPoint+std::abs(v));
+}
+
+inline double calcIProp( const double i )
+{
+ return 1 - iMidPoint/(iMidPoint+std::abs(i));
+}
+
+inline int calcThickness( const double prop )
+{
+ return (int)((iLength-2)*prop+2);
+}
+
+inline int calcLength( const double prop, const double v )
+{
+ return (v>0) ? -int(vLength*prop) : int(vLength*prop);
+}
+
+ECNode::ECNode( ICNDocument *icnDocument, Node::node_type _type, node_dir dir, const QPoint &pos, QString *_id )
+ : Node( icnDocument, _type, dir, pos, _id )
+{
+ m_prevV = 0;
+ m_prevI = 0;
+ m_pinPoint = 0l;
+ m_bShowVoltageBars = KTLConfig::showVoltageBars();
+
+ icnDocument->registerItem(this);
+
+ if ( type() == ec_pin )
+ {
+ m_pinPoint = new QCanvasRectangle( 0, 0, 3, 3, canvas() );
+ m_pinPoint->setBrush(Qt::black);
+ m_pinPoint->setPen(Qt::black);
+ }
+
+ m_pins.resize(1);
+ m_pins[0] = new Pin(this);
+}
+
+
+ECNode::~ECNode()
+{
+ if (m_pinPoint)
+ m_pinPoint->setCanvas(0l);
+ delete m_pinPoint;
+ m_pinPoint = 0l;
+
+ for ( unsigned i = 0; i < m_pins.size(); i++ )
+ delete m_pins[i];
+ m_pins.resize(0);
+}
+
+
+void ECNode::setNumPins( unsigned num )
+{
+ unsigned oldNum = m_pins.size();
+
+ if ( num == oldNum )
+ return;
+
+ if ( num > oldNum )
+ {
+ m_pins.resize(num);
+ for ( unsigned i = oldNum; i < num; i++ )
+ m_pins[i] = new Pin(this);
+ }
+ else
+ {
+ for ( unsigned i = num; i < oldNum; i++ )
+ delete m_pins[i];
+ m_pins.resize(num);
+ }
+
+ emit numPinsChanged(num);
+}
+
+
+void ECNode::setNodeChanged()
+{
+ if ( !canvas() || numPins() != 1 )
+ return;
+
+ Pin * pin = m_pins[0];
+
+ double v = pin->voltage();
+ double i = pin->current();
+
+ if ( v != m_prevV || i != m_prevI )
+ {
+ QRect r = boundingRect();
+ r.setCoords( r.left()+(r.width()/2)-1, r.top()+(r.height()/2)-1, r.right()-(r.width()/2)+1, r.bottom()-(r.height()/2)+1 );
+ canvas()->setChanged(r);
+ m_prevV = v;
+ m_prevI = i;
+ }
+}
+
+
+void ECNode::setParentItem( CNItem * parentItem )
+{
+ Node::setParentItem(parentItem);
+
+ if ( Component * component = dynamic_cast<Component*>(parentItem) )
+ {
+ connect( component, SIGNAL(elementDestroyed(Element* )), this, SLOT(removeElement(Element* )) );
+ connect( component, SIGNAL(switchDestroyed( Switch* )), this, SLOT(removeSwitch( Switch* )) );
+ }
+}
+
+
+void ECNode::removeElement( Element * e )
+{
+ for ( unsigned i = 0; i < m_pins.size(); i++ )
+ m_pins[i]->removeElement(e);
+}
+
+
+void ECNode::removeSwitch( Switch * sw )
+{
+ for ( unsigned i = 0; i < m_pins.size(); i++ )
+ m_pins[i]->removeSwitch( sw );
+}
+
+
+void ECNode::drawShape( QPainter &p )
+{
+ const int _x = int(x());
+ const int _y = int(y());
+
+ if ( type() == ec_junction )
+ {
+// p.drawRect( _x-2, _y-1, 5, 3 );
+// p.drawRect( _x-1, _y-2, 3, 5 );
+ p.drawRect( _x-1, _y-1, 3, 3 );
+ return;
+ }
+
+ if (m_pinPoint)
+ {
+ bool drawDivPoint;
+ QPoint divPoint = findConnectorDivergePoint(&drawDivPoint);
+ m_pinPoint->setVisible(drawDivPoint);
+ m_pinPoint->move( divPoint.x()-1, divPoint.y()-1 );
+ }
+
+ // Now to draw on our current/voltage bar indicators
+
+ if ( numPins() == 1 )
+ {
+ double v = pin()->voltage();
+ double vProp = calcVProp(v);
+ int length = calcLength( vProp, v );
+
+ if ( m_bShowVoltageBars && length != 0 )
+ {
+ // we can assume that v != 0 as length != 0
+
+ QPen oldPen = p.pen();
+
+ double i = pin()->current();
+ double iProp = calcIProp(i);
+ int thickness = calcThickness(iProp);
+
+ if ( v > 0 )
+ p.setPen( QPen( QColor( 255, 166, 0 ), thickness ) );
+
+ else
+ p.setPen( QPen( QColor( 0, 136, 255 ), thickness ) );
+
+ // The node line (drawn at the end of this function) will overdraw
+ // some of the voltage bar, so we need to adapt the length
+ if ( v > 0 && (m_dir == Node::dir_up || m_dir == Node::dir_down) )
+ length--;
+ else if ( v < 0 && (m_dir == Node::dir_left || m_dir == Node::dir_right) )
+ length++;
+
+ if ( m_dir == Node::dir_right )
+ p.drawLine( _x+3, _y, _x+3, _y+length );
+
+ else if ( m_dir == Node::dir_down )
+ p.drawLine( _x, _y+3, _x-length, _y+3 );
+
+ else if ( m_dir == Node::dir_left )
+ p.drawLine( _x-3, _y, _x-3, _y+length );
+
+ else if ( m_dir == Node::dir_up )
+ p.drawLine( _x, _y-3, _x-length, _y-3 );
+
+ p.setPen(oldPen);
+ }
+ }
+
+ QPen pen( p.pen() );
+ pen.setWidth( (numPins() > 1) ? 2 : 1 );
+ p.setPen(pen);
+
+ if ( m_dir == Node::dir_right ) p.drawLine( _x, _y, _x+8, _y );
+ else if ( m_dir == Node::dir_down ) p.drawLine( _x, _y, _x, _y+8 );
+ else if ( m_dir == Node::dir_left ) p.drawLine( _x, _y, _x-8, _y );
+ else if ( m_dir == Node::dir_up ) p.drawLine( _x, _y, _x, _y-8 );
+}
+
+#include "ecnode.moc"