multiinputgate.cpp

00001 /***************************************************************************
00002  *   Copyright (C) 2004-2005 by David Saxton                               *
00003  *   david@bluehaze.org                                                    *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  ***************************************************************************/
00010 
00011 #include "ecnode.h"
00012 #include "icndocument.h"
00013 #include "libraryitem.h"
00014 #include "multiinputgate.h"
00015 #include "logic.h"
00016 
00017 #include <cmath>
00018 #include <klocale.h>
00019 #include <qpainter.h>
00020 
00021 //BEGIN class MultiInputGate
00022 MultiInputGate::MultiInputGate( ICNDocument *icnDocument, bool newItem, const char *id, int baseWidth )
00023         : Component( icnDocument, newItem, id )
00024 {
00025         b_doneInit = false;
00026         m_numInputs = 0;
00027         if ( baseWidth == -1 ) {
00028                 baseWidth = 32;
00029         }
00030         m_baseWidth = baseWidth;
00031         
00032         for ( int i=0; i<maxGateInput; ++i )
00033         {
00034                 inLogic[i] = 0;
00035                 inNode[i] = 0;
00036         }
00037         
00038         updateInputs(2);
00039         
00040         init1PinRight(16);
00041         m_pOut = createLogicOut( m_pPNode[0], false );
00042         
00043         
00044         createProperty( "numInput", Variant::Type::Int );
00045         property("numInput")->setCaption( i18n("Number Inputs") );
00046         property("numInput")->setMinValue(2);
00047         property("numInput")->setMaxValue(maxGateInput);
00048         property("numInput")->setValue(2);
00049         
00050         b_doneInit = true;
00051 }
00052 
00053 
00054 MultiInputGate::~MultiInputGate()
00055 {
00056 }
00057 
00058 
00059 void MultiInputGate::dataChanged()
00060 {
00061         updateInputs( QMIN( maxGateInput, dataInt("numInput") ) );
00062 }
00063 
00064 
00065 void MultiInputGate::updateInputs( int newNum )
00066 {
00067         if ( newNum == m_numInputs ) {
00068                 return;
00069         }
00070         
00071         if ( newNum < 2 ) {
00072                 newNum = 2;
00073         }
00074         else if ( newNum > maxGateInput ) {
00075                 newNum = maxGateInput;
00076         }
00077         
00078         const int newWidth = m_baseWidth;
00079         
00080         setSize( -newWidth/2, -8*newNum, newWidth, 16*newNum, true );
00081         
00082         const bool added = ( newNum > m_numInputs );
00083         if (added)
00084         {
00085                 for ( int i = m_numInputs; i<newNum; ++i )
00086                 {
00087                         ECNode *node = createPin( 0, 0, 0, "in"+QString::number(i) );
00088                         inNode[i] = node;
00089                         inLogic[i] = createLogicIn(node);
00090                         inLogic[i]->setCallback( this, (CallbackPtr)(&MultiInputGate::inStateChanged) );
00091                 }
00092         }
00093         else
00094         {
00095                 for ( int i=newNum; i<m_numInputs; ++i )
00096                 {
00097                         removeNode("in"+QString::number(i));
00098                         removeElement( inLogic[i], false );
00099                         inNode[i] = 0;
00100                         inLogic[i] = 0;
00101                 }
00102         }
00103         
00104         m_numInputs = newNum;
00105         
00106         // We can't call a pure-virtual function if we haven't finished our constructor yet...
00107         if (b_doneInit)
00108                 inStateChanged(!added);
00109         
00110         updateAttachedPositioning();
00111 }
00112 
00113 
00114 void MultiInputGate::updateAttachedPositioning()
00115 {
00116         // Check that our ndoes have been created before we attempt to use them
00117         if ( !m_nodeMap.contains("p1") || !m_nodeMap.contains("in"+QString::number(m_numInputs-1)) )
00118                 return;
00119         
00120         int _x = offsetX()+8;
00121         int _y = offsetY()+8;
00122         
00123         m_nodeMap["p1"].x = m_baseWidth/2 + 8;
00124         m_nodeMap["p1"].y = 0;
00125         
00126         for ( int i=0; i< m_numInputs; ++i )
00127         {
00128                 m_nodeMap["in"+QString::number(i)].x = _x - 16;
00129                 m_nodeMap["in"+QString::number(i)].y = _y + 16*i;
00130         }
00131         
00132         if (b_doneInit)
00133                 Component::updateAttachedPositioning();
00134 }
00135 //END class MultiInputGate
00136 
00137 
00138 //BEGIN class ECXNor
00139 Item* ECXnor::construct( ItemDocument *itemDocument, bool newItem, const char *id )
00140 {
00141         return new ECXnor( (ICNDocument*)itemDocument, newItem, id );
00142 }
00143 
00144 LibraryItem* ECXnor::libraryItem()
00145 {
00146         return new LibraryItem(
00147                 QString::QString("ec/xnor"),
00148                 i18n("XNOR gate"),
00149                 i18n("Logic"),
00150                 "xnor.png",
00151                 LibraryItem::lit_component,
00152                 ECXnor::construct );
00153 }
00154 
00155 ECXnor::ECXnor( ICNDocument *icnDocument, bool newItem, const char *id )
00156         : MultiInputGate( icnDocument, newItem, (id) ? id : "xnor", 48 )
00157 {
00158         m_name = i18n("XNOR gate");
00159         m_desc = i18n("Exclusive NOR gate. Output is low when exactly one input is high.");
00160         
00161         inStateChanged(false);
00162 }
00163 
00164 ECXnor::~ECXnor()
00165 {
00166 }
00167 
00168 void ECXnor::inStateChanged(bool)
00169 {
00170         int highCount = 0;
00171         for ( int i=0; i<m_numInputs; ++i )
00172         {
00173                 if ( inLogic[i]->isHigh() )
00174                         highCount++;
00175         }
00176         
00177         m_pOut->setHigh( highCount != 1 );
00178 }
00179 
00180 void ECXnor::drawShape( QPainter &p )
00181 {
00182         initPainter(p);
00183         int _x = (int)x()+offsetX();
00184         int _y = (int)y()+offsetY();
00185         
00186         p.save();
00187         p.setPen( Qt::NoPen );
00188         p.drawChord( _x-width()+22, _y, 2*width()-28, height(), -16*81, 16*162 );
00189         p.restore();
00190         
00191         p.drawArc( _x-width()+22, _y, 2*width()-28, height(), -16*90, 16*180 );
00192         p.drawArc( _x-8, _y, 16, height(), -16*90, 16*180 );
00193         p.drawArc( _x, _y, 16, height(), -16*90, 16*180 );
00194         
00195         p.drawEllipse( _x+width()-6, _y+(height()/2)-3, 6, 6 );
00196         
00197         const int n = m_numInputs;
00198         for ( int i=0; i<n; ++i )
00199         {
00200                 p.setPen( inNode[i]->isSelected() ? m_selectedCol : Qt::black );
00201                 int pin_x = (int)std::sqrt((double)(64*n*n - (8*n-8-16*i)*(8*n-8-16*i)))/n;
00202                 p.drawLine( _x, _y+16*i+8, _x+pin_x, _y+16*i+8 );
00203         }
00204         
00205         deinitPainter(p);
00206 }
00207 //END class ECXnor
00208 
00209 
00210 //BEGIN class ECXor
00211 Item* ECXor::construct( ItemDocument *itemDocument, bool newItem, const char *id )
00212 {
00213         return new ECXor( (ICNDocument*)itemDocument, newItem, id );
00214 }
00215 
00216 LibraryItem* ECXor::libraryItem()
00217 {
00218         return new LibraryItem(
00219                 QString::QString("ec/xor"),
00220                 i18n("XOR gate"),
00221                 i18n("Logic"),
00222                 "xor.png",
00223                 LibraryItem::lit_component,
00224                 ECXor::construct );
00225 }
00226 
00227 ECXor::ECXor( ICNDocument *icnDocument, bool newItem, const char *id )
00228         : MultiInputGate( icnDocument, newItem, (id) ? id : "xor", 48 )
00229 {
00230         m_name = i18n("XOR gate");
00231         m_desc = i18n("Exclusive OR gate. Output is high when exactly one input is high.");
00232         
00233         inStateChanged(false);
00234 }
00235 
00236 ECXor::~ECXor()
00237 {
00238 }
00239 
00240 void ECXor::inStateChanged(bool)
00241 {
00242         int highCount = 0;
00243         for ( int i=0; i<m_numInputs; ++i )
00244         {
00245                 if ( inLogic[i]->isHigh() )
00246                         highCount++;
00247         }
00248         
00249         m_pOut->setHigh( highCount == 1 );
00250 }
00251 
00252 void ECXor::drawShape( QPainter &p )
00253 {
00254         initPainter(p);
00255         int _x = (int)x()+offsetX();
00256         int _y = (int)y()+offsetY();
00257         
00258         p.save();
00259         p.setPen( Qt::NoPen );
00260         p.drawChord( _x-width()+16, _y, 2*width()-16, height(), -16*81, 16*162 );
00261         p.restore();
00262         
00263         p.drawArc( _x-width()+16, _y, 2*width()-16, height(), -16*90, 16*180 );
00264         p.drawArc( _x-8, _y, 16, height(), -16*90, 16*180 );
00265         p.drawArc( _x, _y, 16, height(), -16*90, 16*180 );
00266         
00267         const int n = m_numInputs;
00268         for ( int i=0; i<n; ++i )
00269         {
00270                 p.setPen( inNode[i]->isSelected() ? m_selectedCol : Qt::black );
00271                 int pin_x = (int)std::sqrt((double)(64*n*n - (8*n-8-16*i)*(8*n-8-16*i)))/n;
00272                 p.drawLine( _x, _y+16*i+8, _x+pin_x, _y+16*i+8 );
00273         }
00274         
00275         deinitPainter(p);
00276 }
00277 //END class ECXor
00278 
00279 
00280 //BEGIN class EXOr
00281 Item* ECOr::construct( ItemDocument *itemDocument, bool newItem, const char *id )
00282 {
00283         return new ECOr( (ICNDocument*)itemDocument, newItem, id );
00284 }
00285 
00286 LibraryItem* ECOr::libraryItem()
00287 {
00288         return new LibraryItem(
00289                 QString::QString("ec/or"),
00290                 i18n("OR gate"),
00291                 i18n("Logic"),
00292                 "or.png",
00293                 LibraryItem::lit_component,
00294                 ECOr::construct );
00295 }
00296 
00297 ECOr::ECOr( ICNDocument *icnDocument, bool newItem, const char *id )
00298         : MultiInputGate( icnDocument, newItem, (id) ? id : "or", 48 )
00299 {
00300         m_name = i18n("OR gate");
00301         m_desc = i18n("The output is high when at least one of the inputs is high; or low when all of the inputs are off");
00302         
00303         inStateChanged(false);
00304 }
00305 
00306 ECOr::~ECOr()
00307 {
00308 }
00309 
00310 void ECOr::inStateChanged(bool)
00311 {
00312         bool allLow = true;
00313         for ( int i=0; i<m_numInputs && allLow; ++i )
00314         {
00315                 if ( inLogic[i]->isHigh() )
00316                         allLow = false;
00317         }
00318         
00319         m_pOut->setHigh(!allLow);
00320 }
00321 
00322 void ECOr::drawShape( QPainter &p )
00323 {
00324         initPainter(p);
00325         int _x = (int)x()+offsetX();
00326         int _y = (int)y()+offsetY();
00327         
00328         p.save();
00329         p.setPen( Qt::NoPen );
00330 //      p.setBrush( Qt::red );
00331         p.drawChord( _x-width(), _y, 2*width(), height(), -16*81, 16*162 );
00332 //      p.drawPie( _x-width()+16, _y, 2*width()-16, height(), -16*100, 16*200 );
00333         p.restore();
00334         
00335         p.drawArc( _x-width(), _y, 2*width(), height(), -16*90, 16*180 );
00336         p.drawArc( _x-8, _y, 16, height(), -16*90, 16*180 );
00337         
00338         const int n = m_numInputs;
00339         for ( int i=0; i<n; ++i )
00340         {
00341                 p.setPen( inNode[i]->isSelected() ? m_selectedCol : Qt::black );
00342                 int pin_x = (int)std::sqrt((double)(64*n*n - (8*n-8-16*i)*(8*n-8-16*i)))/n;
00343                 p.drawLine( _x, _y+16*i+8, _x+pin_x, _y+16*i+8 );
00344         }
00345         
00346         deinitPainter(p);
00347 }
00348 //END class ECOr
00349 
00350 
00351 //BEGIN class ECNor
00352 Item* ECNor::construct( ItemDocument *itemDocument, bool newItem, const char *id )
00353 {
00354         return new ECNor( (ICNDocument*)itemDocument, newItem, id );
00355 }
00356 
00357 LibraryItem* ECNor::libraryItem()
00358 {
00359         return new LibraryItem(
00360                 QString::QString("ec/nor"),
00361                 i18n("NOR gate"),
00362                 i18n("Logic"),
00363                 "nor.png",
00364                 LibraryItem::lit_component,
00365                 ECNor::construct );
00366 }
00367 
00368 ECNor::ECNor( ICNDocument *icnDocument, bool newItem, const char *id )
00369         : MultiInputGate( icnDocument, newItem, (id) ? id : "nor", 48 )
00370 {
00371         m_name = i18n("NOR Gate");
00372         m_desc = i18n("The output is high when all inputs are low.");
00373         
00374         inStateChanged(false);
00375 }
00376 
00377 ECNor::~ECNor()
00378 {
00379 }
00380 
00381 void ECNor::inStateChanged(bool)
00382 {
00383         bool allLow = true;
00384         for ( int i=0; i<m_numInputs && allLow; ++i )
00385         {
00386                 if ( inLogic[i]->isHigh() )
00387                         allLow = false;
00388         }
00389         
00390         m_pOut->setHigh(allLow);
00391 }
00392 
00393 void ECNor::drawShape( QPainter &p )
00394 {
00395         initPainter(p);
00396         int _x = (int)x()+offsetX();
00397         int _y = (int)y()+offsetY();
00398         
00399         p.save();
00400         p.setPen( Qt::NoPen );
00401         p.drawChord( _x-width()+6, _y, 2*width()-12, height(), -16*81, 16*162 );
00402         p.restore();
00403         
00404         p.drawArc( _x-width()+6, _y, 2*width()-12, height(), -16*90, 16*180 );
00405         p.drawArc( _x-8, _y, 16, height(), -16*90, 16*180 );
00406         
00407         p.drawEllipse( _x+width()-6, _y+(height()/2)-3, 6, 6 );
00408         
00409         const int n = m_numInputs;
00410         for ( int i=0; i<n; ++i )
00411         {
00412                 p.setPen( inNode[i]->isSelected() ? m_selectedCol : Qt::black );
00413                 int pin_x = (int)std::sqrt((double)(64*n*n - (8*n-8-16*i)*(8*n-8-16*i)))/n;
00414                 p.drawLine( _x, _y+16*i+8, _x+pin_x, _y+16*i+8 );
00415         }
00416         
00417         deinitPainter(p);
00418 }
00419 //END class ECNor
00420 
00421 
00422 //BEGIN class ECNand
00423 Item* ECNand::construct( ItemDocument *itemDocument, bool newItem, const char *id )
00424 {
00425         return new ECNand( (ICNDocument*)itemDocument, newItem, id );
00426 }
00427 
00428 LibraryItem* ECNand::libraryItem()
00429 {
00430         return new LibraryItem(
00431                 QString::QString("ec/nand"),
00432                 i18n("NAND gate"),
00433                 i18n("Logic"),
00434                 "nand.png",
00435                 LibraryItem::lit_component,
00436                 ECNand::construct );
00437 }
00438 
00439 ECNand::ECNand( ICNDocument *icnDocument, bool newItem, const char *id )
00440         : MultiInputGate( icnDocument, newItem, id ? id : "nand" )
00441 {
00442         m_name = i18n("NAND Gate");
00443         m_desc = i18n("The output is low only when all of the inputs are high.");
00444         
00445         inStateChanged(false);
00446 }
00447 
00448 ECNand::~ECNand()
00449 {
00450 }
00451 
00452 void ECNand::inStateChanged(bool)
00453 {
00454         bool allHigh = true;
00455         for ( int i=0; i<m_numInputs && allHigh; ++i )
00456         {
00457                 if ( !inLogic[i]->isHigh() )
00458                         allHigh = false;
00459         }
00460         
00461         m_pOut->setHigh(!allHigh);
00462 }
00463 
00464 void ECNand::drawShape( QPainter &p )
00465 {
00466         initPainter(p);
00467         int _x = (int)x()+offsetX();
00468         int _y = (int)y()+offsetY();
00469         p.drawChord( _x-width()+6, _y, 2*width()-12, height(), -16*90, 16*180 );
00470         p.drawEllipse( _x+width()-6, _y+(height()/2)-3, 6, 6 );
00471         deinitPainter(p);
00472 }
00473 //END class ECNand
00474 
00475 
00476 //BEGIN class ECAnd
00477 Item* ECAnd::construct( ItemDocument *itemDocument, bool newItem, const char *id )
00478 {
00479         return new ECAnd( (ICNDocument*)itemDocument, newItem, id );
00480 }
00481 
00482 LibraryItem* ECAnd::libraryItem()
00483 {
00484         QStringList idList;
00485         idList << "ec/and" << "ec/and_2";
00486         return new LibraryItem(
00487                 idList,
00488                 i18n("AND gate"),
00489                 i18n("Logic"),
00490                 "and.png",
00491                 LibraryItem::lit_component,
00492                 ECAnd::construct );
00493 }
00494 
00495 ECAnd::ECAnd( ICNDocument *icnDocument, bool newItem, const char *id )
00496         : MultiInputGate( icnDocument, newItem, id ? id : "and" )
00497 {
00498         m_name = i18n("AND Gate");
00499         m_desc = i18n("The output is high if and only if all of the inputs are high.");
00500         
00501         inStateChanged(false);
00502 }
00503 
00504 ECAnd::~ECAnd()
00505 {
00506 }
00507 
00508 void ECAnd::inStateChanged(bool)
00509 {
00510         bool allHigh = true;
00511         for ( int i=0; i<m_numInputs && allHigh; ++i )
00512         {
00513                 if ( !inLogic[i]->isHigh() )
00514                         allHigh = false;
00515         }
00516         
00517         m_pOut->setHigh(allHigh);
00518 }
00519 
00520 void ECAnd::drawShape( QPainter &p )
00521 {
00522         initPainter(p);
00523         
00524         int _x = (int)x()+offsetX();
00525         int _y = (int)y()+offsetY();
00526         p.drawChord( _x-width(), _y, 2*width(), height(), -16*90, 16*180 );
00527         
00528         deinitPainter(p);
00529 }
00530 //END class ECAnd

Generated on Tue May 8 17:05:31 2007 for KTechLab by  doxygen 1.5.1