00001
00002
00003
00004
00005
00006
00007
00008
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
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
00107 if (b_doneInit)
00108 inStateChanged(!added);
00109
00110 updateAttachedPositioning();
00111 }
00112
00113
00114 void MultiInputGate::updateAttachedPositioning()
00115 {
00116
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
00136
00137
00138
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
00208
00209
00210
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
00278
00279
00280
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
00331 p.drawChord( _x-width(), _y, 2*width(), height(), -16*81, 16*162 );
00332
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
00349
00350
00351
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
00420
00421
00422
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
00474
00475
00476
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