summaryrefslogtreecommitdiffstats
path: root/src/itemlibrary.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/itemlibrary.cpp')
-rw-r--r--src/itemlibrary.cpp476
1 files changed, 476 insertions, 0 deletions
diff --git a/src/itemlibrary.cpp b/src/itemlibrary.cpp
new file mode 100644
index 0000000..d749f7f
--- /dev/null
+++ b/src/itemlibrary.cpp
@@ -0,0 +1,476 @@
+/***************************************************************************
+ * 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 "config.h"
+
+#include "cnitem.h"
+#include "canvasitemparts.h"
+#include "circuitdocument.h"
+#include "component.h"
+#include "ecsubcircuit.h"
+#include "ecnode.h"
+#include "itemlibrary.h"
+#include "node.h"
+#include "subcircuits.h"
+
+#ifdef MECHANICS
+#include "chassiscircular2.h"
+#endif
+
+#include "dptext.h"
+#include "dpline.h"
+#include "solidshape.h"
+
+#include "callsub.h"
+#include "count.h"
+#include "delay.h"
+#include "embed.h"
+#include "end.h"
+#include "inputbutton.h"
+#include "interrupt.h"
+#include "forloop.h"
+#include "keypad.h"
+#include "pulse.h"
+#include "readport.h"
+#include "repeat.h"
+#include "setpin.h"
+#include "sevenseg.h"
+#include "start.h"
+#include "sub.h"
+#include "testpin.h"
+#include "unary.h"
+#include "varassignment.h"
+#include "varcomparison.h"
+#include "while.h"
+#include "writeport.h"
+
+#include "addac.h"
+#include "bidirled.h"
+#include "binarycounter.h"
+#include "bussplitter.h"
+#include "demultiplexer.h"
+#include "dependentsource.h"
+#include "discretelogic.h"
+#include "externalconnection.h"
+#include "flipflop.h"
+#include "fulladder.h"
+#include "inductor.h"
+#include "magnitudecomparator.h"
+#include "matrixdisplay.h"
+#include "matrixdisplaydriver.h"
+#include "meter.h"
+#include "multiinputgate.h"
+#include "multiplexer.h"
+#include "parallelportcomponent.h"
+#include "piccomponent.h"
+#include "pushswitch.h"
+#include "probe.h"
+#include "ram.h"
+#include "resistordip.h"
+#include "rotoswitch.h"
+#include "serialportcomponent.h"
+#include "toggleswitch.h"
+
+#include "ec555.h"
+#include "ecbcdto7segment.h"
+#include "eccapacitor.h"
+#include "ecclockinput.h"
+#include "eccurrentsignal.h"
+#include "eccurrentsource.h"
+#include "ecdiode.h"
+#include "ecfixedvoltage.h"
+#include "ecground.h"
+#include "eckeypad.h"
+#include "ecled.h"
+#include "ecbjt.h"
+#include "ecopamp.h"
+#include "ecpotentiometer.h"
+#include "ecresistor.h"
+#include "ecsevensegment.h"
+#include "ecsignallamp.h"
+#include "ecvoltagesignal.h"
+#include "ecvoltagesource.h"
+
+#include "pinmapping.h"
+
+#include "libraryitem.h"
+
+#include "kdebug.h"
+#include <kiconloader.h>
+#include <qbitmap.h>
+#include <qimage.h>
+#include <qpainter.h>
+#include <qpixmap.h>
+#include <qpushbutton.h>
+#include <qregexp.h>
+
+#include <cassert>
+
+ItemLibrary::ItemLibrary()
+{
+ addFlowParts();
+ addComponents();
+ addMechanics();
+ addDrawParts();
+}
+
+
+ItemLibrary::~ItemLibrary()
+{
+ const LibraryItemList::iterator end = m_items.end();
+ for ( LibraryItemList::iterator it = m_items.begin(); it != end; ++it )
+ {
+ delete *it;
+ }
+ m_items.clear();
+}
+
+
+void ItemLibrary::addFlowParts()
+{
+ // Container loops
+ addLibraryItem( Repeat::libraryItem() );
+ addLibraryItem( While::libraryItem() );
+ addLibraryItem( ForLoop::libraryItem() );
+
+ // Variable operations
+ addLibraryItem( Unary::libraryItem() );
+ addLibraryItem( VarAssignment::libraryItem() );
+ addLibraryItem( VarComparison::libraryItem() );
+
+ // I/O
+ addLibraryItem( SetPin::libraryItem() );
+ addLibraryItem( TestPin::libraryItem() );
+ addLibraryItem( WritePort::libraryItem() );
+ addLibraryItem( ReadPort::libraryItem() );
+
+ // Functions
+ addLibraryItem( SevenSeg::libraryItem() );
+// addLibraryItem( Pulse::libraryItem() );
+ addLibraryItem( Keypad::libraryItem() );
+// addLibraryItem( Count::libraryItem() );
+// addLibraryItem( InputButton::libraryItem() );
+ addLibraryItem( Delay::libraryItem() );
+
+ // Common
+ addLibraryItem( Embed::libraryItem() );
+ addLibraryItem( CallSub::libraryItem() );
+// addLibraryItem( Interrupt::libraryItem() );
+ addLibraryItem( Sub::libraryItem() );
+ addLibraryItem( End::libraryItem() );
+ addLibraryItem( Start::libraryItem() );
+}
+
+
+void ItemLibrary::addComponents()
+{
+ // Integrated Circuits
+ addLibraryItem( ECBCDTo7Segment::libraryItem() );
+ addLibraryItem( MatrixDisplayDriver::libraryItem() );
+ addLibraryItem( BinaryCounter::libraryItem() );
+ addLibraryItem( DAC::libraryItem() );
+ addLibraryItem( ADC::libraryItem() );
+ addLibraryItem( ECOpAmp::libraryItem() );
+ addLibraryItem( MagnitudeComparator::libraryItem() );
+ addLibraryItem( Demultiplexer::libraryItem() );
+ addLibraryItem( Multiplexer::libraryItem() );
+ addLibraryItem( FullAdder::libraryItem() );
+ addLibraryItem( RAM::libraryItem() );
+ addLibraryItem( EC555::libraryItem() );
+ addLibraryItem( ECDFlipFlop::libraryItem() );
+ addLibraryItem( ECSRFlipFlop::libraryItem() );
+ addLibraryItem( ECJKFlipFlop::libraryItem() );
+#ifndef NO_GPSIM
+ addLibraryItem( PICComponent::libraryItem() );
+#endif
+
+ // Connections
+ addLibraryItem( ParallelPortComponent::libraryItem() );
+ addLibraryItem( SerialPortComponent::libraryItem() );
+ addLibraryItem( ExternalConnection::libraryItem() );
+ addLibraryItem( BusSplitter::libraryItem() );
+
+ // Logic
+ addLibraryItem( ECXnor::libraryItem() );
+ addLibraryItem( ECXor::libraryItem() );
+ addLibraryItem( ECNor::libraryItem() );
+ addLibraryItem( ECOr::libraryItem() );
+ addLibraryItem( ECNand::libraryItem() );
+ addLibraryItem( ECAnd::libraryItem() );
+ addLibraryItem( Inverter::libraryItem() );
+ addLibraryItem( Buffer::libraryItem() );
+ addLibraryItem( ECClockInput::libraryItem() );
+ addLibraryItem( ECLogicOutput::libraryItem() );
+ addLibraryItem( ECLogicInput::libraryItem() );
+
+
+ // Outputs
+// addLibraryItem( FrequencyMeter::libraryItem() );
+ addLibraryItem( CurrentProbe::libraryItem() );
+ addLibraryItem( VoltageProbe::libraryItem() );
+ addLibraryItem( LogicProbe::libraryItem() );
+ addLibraryItem( ECAmmeter::libraryItem() );
+ addLibraryItem( ECVoltMeter::libraryItem() );
+ addLibraryItem( MatrixDisplay::libraryItem() );
+ addLibraryItem( ECSevenSegment::libraryItem() );
+ addLibraryItem( BiDirLED::libraryItem() );
+ addLibraryItem( ECSignalLamp::libraryItem() );
+ addLibraryItem( ECLed::libraryItem() );
+
+ // Switches
+ addLibraryItem( ECRotoSwitch::libraryItem() );
+ addLibraryItem( ECDPDT::libraryItem() );
+ addLibraryItem( ECSPDT::libraryItem() );
+ addLibraryItem( ECDPST::libraryItem() );
+ addLibraryItem( ECSPST::libraryItem() );
+ addLibraryItem( ECKeyPad::libraryItem() );
+ addLibraryItem( ECPTBSwitch::libraryItem() );
+ addLibraryItem( ECPTMSwitch::libraryItem() );
+
+
+ // Discrete
+ addLibraryItem( ECPotentiometer::libraryItem() );
+ addLibraryItem( ResistorDIP::libraryItem() );
+ addLibraryItem( ECBJT::libraryItemPNP() );
+ addLibraryItem( ECBJT::libraryItemNPN() );
+ addLibraryItem( Inductor::libraryItem() );
+ addLibraryItem( ECDiode::libraryItem() );
+ addLibraryItem( ECCapacitor::libraryItem() );
+ addLibraryItem( ECResistor::libraryItem() );
+
+ // Dependent Sources
+ addLibraryItem( ECVCVS::libraryItem() );
+ addLibraryItem( ECVCCS::libraryItem() );
+ addLibraryItem( ECCCVS::libraryItem() );
+ addLibraryItem( ECCCCS::libraryItem() );
+
+ // Independent Sources
+ addLibraryItem( ECCurrentSignal::libraryItem() );
+ addLibraryItem( ECVoltageSignal::libraryItem() );
+ addLibraryItem( ECCurrentSource::libraryItem() );
+ addLibraryItem( ECGround::libraryItem() );
+ addLibraryItem( ECFixedVoltage::libraryItem() );
+ addLibraryItem( ECCell::libraryItem() );
+
+ // Other
+ addLibraryItem( ECSubcircuit::libraryItem() );
+ addLibraryItem( PIC_IC::libraryItem() );
+}
+
+
+void ItemLibrary::addDrawParts()
+{
+ addLibraryItem( DPText::libraryItem() );
+ addLibraryItem( DPLine::libraryItem() );
+ addLibraryItem( DPArrow::libraryItem() );
+ addLibraryItem( DPRectangle::libraryItem() );
+ addLibraryItem( DPEllipse::libraryItem() );
+}
+
+
+void ItemLibrary::addMechanics()
+{
+#ifdef MECHANICS
+ addLibraryItem( ChassisCircular2::libraryItem() );
+#endif
+}
+
+
+void ItemLibrary::addLibraryItem( LibraryItem *item )
+{
+ m_items.append(item);
+}
+
+
+Item *ItemLibrary::createItem( const QString &id, ItemDocument *itemDocument, bool newItem, const char *newId, bool finishCreation )
+{
+ Item * item = 0l;
+ if ( id.startsWith("sc/") )
+ {
+ // Is a subcircuit...
+
+ CircuitDocument * circuitDocument = dynamic_cast<CircuitDocument*>(itemDocument);
+ if (!circuitDocument)
+ {
+ kdWarning() << "Cannot create subcircuit without a circuit document" << endl;
+ return 0l;
+ }
+
+ QString temp = id;
+ int numId = temp.remove("sc/").toInt();
+
+ item = subcircuits()->createSubcircuit( numId, /*id,*/ circuitDocument, newItem, newId );
+ }
+
+ else
+ {
+ const LibraryItemList::iterator end = m_items.end();
+ LibraryItemList::iterator it = m_items.begin();
+ for ( ; it != end; ++it )
+ {
+ if ( (*it)->allIDs().contains(id) )
+ {
+ item = (*it)->createItemFnPtr()( itemDocument, newItem, newId );
+ item->m_type = (*it)->activeID();
+ break;
+ }
+ }
+
+ if ( it == end )
+ kdWarning() << "Could not find the item constructor for id " << id << endl;
+ }
+
+ if ( finishCreation && item )
+ item->finishedCreation();
+
+ return item;
+}
+
+
+QImage ItemLibrary::itemImage( Item *item, const uint maxSize )
+{
+ Component *component = dynamic_cast<Component*>(item);
+
+ QRect bound = item->boundingRect().normalize();
+ bound.setLeft( bound.left()-8 );
+ bound.setRight( bound.right()+8 );
+ bound.setTop( bound.top()-8 );
+ bound.setBottom( bound.bottom()+8 );
+
+ // We want a nice square bounding rect
+ const int dy = bound.width() - bound.height();
+ if ( dy > 0 )
+ {
+ bound.setTop( bound.top()-(dy/2) );
+ bound.setBottom( bound.bottom()+(dy/2) );
+ }
+ else if ( dy < 0 )
+ {
+ bound.setLeft( bound.left()+(dy/2) );
+ bound.setRight( bound.right()-(dy/2) );
+ }
+
+ const bool cache = ((bound.width()*bound.height()) > (int)maxSize);
+ QString type;
+ if ( cache && m_imageMap.contains(item->type()) )
+ return m_imageMap[item->type()];
+
+ // Create pixmap big enough to contain CNItem and surrounding nodes
+ // and copy the button grab to it
+
+ QPixmap pm( bound.size() );
+
+ QBitmap mask( bound.size() );
+ mask.fill( Qt::color0 );
+
+ QPainter maskPainter(&mask);
+ maskPainter.translate( -bound.x(), -bound.y() );
+ maskPainter.setPen( Qt::color1 );
+ maskPainter.setBrush( Qt::color1 );
+
+
+ QPainter p(&pm);
+ p.translate( -bound.x(), -bound.y() );
+ p.setPen( item->pen() );
+ p.setBrush( item->brush() );
+
+ // Now draw the shape :-)
+ const bool sel = item->isSelected();
+ if (sel)
+ {
+ // We block the signals as we end up in an infinite loop with cnitem emitting a selected signal
+ item->blockSignals(true);
+ item->setSelected(false);
+ item->blockSignals(false);
+ }
+ item->drawShape(p);
+ item->drawShape(maskPainter);
+ if (sel)
+ {
+ item->blockSignals(true);
+ item->setSelected(sel);
+ item->blockSignals(false);
+ }
+
+ maskPainter.setPen( Qt::color1 );
+ maskPainter.setBrush( Qt::color1 );
+
+ QWMatrix transMatrix; // Matrix to apply to the image
+
+ CNItem *cnItem = dynamic_cast<CNItem*>(item);
+ if (cnItem)
+ {
+ NodeMap nodes = cnItem->nodeMap();
+ const NodeMap::iterator nodesEnd = nodes.end();
+ for ( NodeMap::iterator it = nodes.begin(); it != nodesEnd; ++it )
+ {
+ Node *node = it.data().node;
+ const bool sel = node->isSelected();
+ if (sel)
+ node->setSelected(false);
+ if ( ECNode *ecnode = dynamic_cast<ECNode*>(node) )
+ {
+ const bool showVB = ecnode->showVoltageBars();
+ ecnode->setShowVoltageBars(false);
+ ecnode->drawShape(p);
+ ecnode->drawShape(maskPainter);
+ ecnode->setShowVoltageBars(showVB);
+ }
+ else
+ {
+ node->drawShape(p);
+ node->drawShape(maskPainter);
+ }
+ if (sel)
+ node->setSelected(sel);
+ }
+
+ p.setPen(Qt::black);
+ TextMap text = cnItem->textMap();
+ const TextMap::iterator textEnd = text.end();
+ for ( TextMap::iterator it = text.begin(); it != textEnd; ++it )
+ {
+ it.data()->drawShape(p);
+ it.data()->drawShape(maskPainter);
+ }
+
+// maskPainter.setPen( Qt::color1 );
+// maskPainter.setBrush( Qt::color1 );
+ cnItem->drawWidgets(p);
+// cnItem->drawWidgets(maskPainter);
+
+ transMatrix = Component::transMatrix( component->angleDegrees(), component->flipped(), bound.width()/2, bound.height()/2, true );
+ }
+
+ pm.setMask(mask);
+
+ // Now, rotate the image so that it's the right way up, and scale it to size
+ QImage im = pm.convertToImage();
+ im = im.xForm(transMatrix);
+ im = im.smoothScale( 50, 50, QImage::ScaleMin );
+
+ if (cache)
+ m_imageMap[item->type()] = im;
+
+ return im;
+}
+
+QPixmap ItemLibrary::itemIconFull( const QString &id )
+{
+ LibraryItemList::iterator end = m_items.end();
+ for ( LibraryItemList::iterator it = m_items.begin(); it != end; ++it )
+ {
+ if ( *it && (*it)->allIDs().contains(id) )
+ {
+ return (*it)->iconFull();
+ }
+ }
+ return QPixmap();
+}