/*************************************************************************** * 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. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #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 #include #include #include #include #include #include #include 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 TQString &id, ItemDocument *itemDocument, bool newItem, const char *newId, bool finishCreation ) { Item * item = 0l; if ( id.startsWith("sc/") ) { // Is a subcircuit... CircuitDocument * circuitDocument = dynamic_cast(itemDocument); if (!circuitDocument) { kdWarning() << "Cannot create subcircuit without a circuit document" << endl; return 0l; } TQString 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; } TQImage ItemLibrary::itemImage( Item *item, const uint maxSize ) { Component *component = dynamic_cast(item); TQRect 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); TQString 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 TQPixmap pm( bound.size() ); TQBitmap mask( bound.size() ); mask.fill( TQt::color0 ); TQPainter maskPainter(&mask); maskPainter.translate( -bound.x(), -bound.y() ); maskPainter.setPen( TQt::color1 ); maskPainter.setBrush( TQt::color1 ); TQPainter 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( TQt::color1 ); maskPainter.setBrush( TQt::color1 ); TQWMatrix transMatrix; // Matrix to apply to the image CNItem *cnItem = dynamic_cast(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(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(TQt::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( TQt::color1 ); // maskPainter.setBrush( TQt::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 TQImage im = pm.convertToImage(); im = im.xForm(transMatrix); im = im.smoothScale( 50, 50, TQ_ScaleMin ); if (cache) m_imageMap[item->type()] = im; return im; } TQPixmap ItemLibrary::itemIconFull( const TQString &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 TQPixmap(); }