|
|
|
/***************************************************************************
|
|
|
|
* 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 <tqbitmap.h>
|
|
|
|
#include <tqimage.h>
|
|
|
|
#include <tqpainter.h>
|
|
|
|
#include <tqpixmap.h>
|
|
|
|
#include <tqpushbutton.h>
|
|
|
|
#include <tqregexp.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 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<CircuitDocument*>(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<Component*>(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 tqmask( bound.size() );
|
|
|
|
tqmask.fill( TQt::color0 );
|
|
|
|
|
|
|
|
TQPainter maskPainter(&tqmask);
|
|
|
|
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 tqshape :-)
|
|
|
|
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<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(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(tqmask);
|
|
|
|
|
|
|
|
// 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();
|
|
|
|
}
|