File indexing completed on 2024-05-05 05:46:03

0001 /***************************************************************************
0002  *   Copyright (C) 2005 by David Saxton                                    *
0003  *   david@bluehaze.org                                                    *
0004  *                                                                         *
0005  *   This program is free software; you can redistribute it and/or modify  *
0006  *   it under the terms of the GNU General Public License as published by  *
0007  *   the Free Software Foundation; either version 2 of the License, or     *
0008  *   (at your option) any later version.                                   *
0009  ***************************************************************************/
0010 
0011 #include "discretelogic.h"
0012 #include "canvasitemparts.h"
0013 #include "ecnode.h"
0014 #include "libraryitem.h"
0015 #include "logic.h"
0016 #include "simulator.h"
0017 
0018 #include <KLocalizedString>
0019 #include <QPainter>
0020 
0021 // BEGIN class Inverter
0022 Item *Inverter::construct(ItemDocument *itemDocument, bool newItem, const char *id)
0023 {
0024     return new Inverter(static_cast<ICNDocument *>(itemDocument), newItem, id);
0025 }
0026 
0027 LibraryItem *Inverter::libraryItem()
0028 {
0029     QStringList ids;
0030     ids << "ec/inverter"
0031         << "ec/not";
0032     return new LibraryItem(ids, i18n("Inverter"), i18n("Logic"), "not.png", LibraryItem::lit_component, Inverter::construct);
0033 }
0034 
0035 void Inverter_inStateChanged(void *objV, bool newState) {
0036     Inverter *objT = static_cast<Inverter*>(objV);
0037     objT->inStateChanged(newState);
0038 }
0039 
0040 Inverter::Inverter(ICNDocument *icnDocument, bool newItem, const char *id)
0041     : Component(icnDocument, newItem, id ? id : "not")
0042 {
0043     m_name = i18n("Inverter");
0044     setSize(-8, -8, 16, 16);
0045 
0046     init1PinLeft();
0047     init1PinRight();
0048 
0049     m_pIn = createLogicIn(m_pNNode[0]);
0050     m_pOut = createLogicOut(m_pPNode[0], true);
0051 
0052     //m_pIn->setCallback(this, (CallbackPtr)(&Inverter::inStateChanged));
0053     m_pIn->setCallback2(Inverter_inStateChanged, this);
0054     inStateChanged(false);
0055 }
0056 
0057 Inverter::~Inverter()
0058 {
0059 }
0060 
0061 void Inverter::inStateChanged(bool newState)
0062 {
0063     m_pOut->setHigh(!newState);
0064 }
0065 
0066 void Inverter::drawShape(QPainter &p)
0067 {
0068     initPainter(p);
0069     int _x = int(x()) - 8;
0070     int _y = int(y()) - 8;
0071     QPolygon pa(3);
0072     pa[0] = QPoint(_x, _y);
0073     pa[1] = QPoint(_x + width() - 6, _y + (height() / 2));
0074     pa[2] = QPoint(_x, _y + height());
0075     p.drawPolygon(pa);
0076     p.drawPolyline(pa);
0077     p.drawEllipse(_x + width() - 6, _y + (height() / 2) - 3, 7, 7);
0078     deinitPainter(p);
0079 }
0080 // END class Inverter
0081 
0082 // BEGIN class Buffer
0083 Item *Buffer::construct(ItemDocument *itemDocument, bool newItem, const char *id)
0084 {
0085     return new Buffer(static_cast<ICNDocument *>(itemDocument), newItem, id);
0086 }
0087 
0088 LibraryItem *Buffer::libraryItem()
0089 {
0090     return new LibraryItem(QStringList(QString("ec/buffer")), i18n("Buffer"), i18n("Logic"), "buffer.png", LibraryItem::lit_component, Buffer::construct);
0091 }
0092 
0093 void Buffer_inStateChanged(void *objV, bool newState) {
0094     Buffer *objT = static_cast<Buffer*>(objV);
0095     objT->inStateChanged(newState);
0096 }
0097 
0098 Buffer::Buffer(ICNDocument *icnDocument, bool newItem, const char *id)
0099     : Component(icnDocument, newItem, id ? id : "buffer")
0100 {
0101     m_name = i18n("Buffer");
0102     setSize(-8, -8, 16, 16);
0103 
0104     init1PinLeft();
0105     init1PinRight();
0106 
0107     m_pIn = createLogicIn(m_pNNode[0]);
0108     m_pOut = createLogicOut(m_pPNode[0], true);
0109 
0110     //m_pIn->setCallback(this, (CallbackPtr)(&Buffer::inStateChanged));
0111     m_pIn->setCallback2(Buffer_inStateChanged, this);
0112     inStateChanged(false);
0113 }
0114 
0115 Buffer::~Buffer()
0116 {
0117 }
0118 
0119 void Buffer::inStateChanged(bool newState)
0120 {
0121     m_pOut->setHigh(newState);
0122 }
0123 
0124 void Buffer::drawShape(QPainter &p)
0125 {
0126     initPainter(p);
0127     int _x = int(x()) - 8;
0128     int _y = int(y()) - 8;
0129     QPolygon pa(3);
0130     pa[0] = QPoint(_x, _y);
0131     pa[1] = QPoint(_x + width(), _y + (height() / 2));
0132     pa[2] = QPoint(_x, _y + height());
0133     p.drawPolygon(pa);
0134     p.drawPolyline(pa);
0135     deinitPainter(p);
0136 }
0137 // END class Buffer
0138 
0139 // BEGIN class ECLogicInput
0140 Item *ECLogicInput::construct(ItemDocument *itemDocument, bool newItem, const char *id)
0141 {
0142     return new ECLogicInput(static_cast<ICNDocument *>(itemDocument), newItem, id);
0143 }
0144 
0145 LibraryItem *ECLogicInput::libraryItem()
0146 {
0147     return new LibraryItem(QStringList(QString("ec/logic_input")), i18n("Logic Input"), i18n("Logic"), "logic_input.png", LibraryItem::lit_component, ECLogicInput::construct);
0148 }
0149 
0150 ECLogicInput::ECLogicInput(ICNDocument *icnDocument, bool newItem, const char *id)
0151     : Component(icnDocument, newItem, (id) ? id : "logic_input")
0152 {
0153     m_name = i18n("Logic Input");
0154     setSize(-8, -8, 16, 16);
0155 
0156     b_state = false;
0157     addButton("button", QRect(-24, -8, 16, 16), "", true);
0158 
0159     createProperty("useToggle", Variant::Type::Bool);
0160     property("useToggle")->setCaption(i18n("Use Toggle"));
0161     property("useToggle")->setValue(true);
0162 
0163     init1PinRight();
0164 
0165     m_pOut = createLogicOut(m_pPNode[0], false);
0166 }
0167 
0168 ECLogicInput::~ECLogicInput()
0169 {
0170 }
0171 
0172 void ECLogicInput::dataChanged()
0173 {
0174     button("button")->setToggle(dataBool("useToggle"));
0175 }
0176 
0177 void ECLogicInput::drawShape(QPainter &p)
0178 {
0179     initPainter(p);
0180     if (b_state)
0181         p.setBrush(QColor(255, 166, 0));
0182     else
0183         p.setBrush(Qt::white);
0184     p.drawEllipse(int(x()) - 4, int(y()) - 6, 12, 12);
0185     deinitPainter(p);
0186 }
0187 
0188 void ECLogicInput::buttonStateChanged(const QString &, bool state)
0189 {
0190     b_state = state;
0191     m_pOut->setHigh(b_state);
0192 }
0193 // END class ECLogicInput
0194 
0195 // BEGIN class ECLogicOutput
0196 Item *ECLogicOutput::construct(ItemDocument *itemDocument, bool newItem, const char *id)
0197 {
0198     return new ECLogicOutput(static_cast<ICNDocument *>(itemDocument), newItem, id);
0199 }
0200 
0201 LibraryItem *ECLogicOutput::libraryItem()
0202 {
0203     return new LibraryItem(QStringList(QString("ec/logic_output")), i18n("Logic Output"), i18n("Logic"), "logic_output.png", LibraryItem::lit_component, ECLogicOutput::construct);
0204 }
0205 
0206 void ECLogicOutput_inStateChanged(void * objV, bool newState) {
0207     ECLogicOutput *objT = static_cast<ECLogicOutput*>(objV);
0208     objT->inStateChanged(newState);
0209 }
0210 
0211 ECLogicOutput::ECLogicOutput(ICNDocument *icnDocument, bool newItem, const char *id)
0212     : Component(icnDocument, newItem, id ? id : "logic_output")
0213 {
0214     m_name = i18n("Logic Output");
0215     setSize(-8, -8, 16, 16);
0216 
0217     init1PinLeft();
0218     m_pIn = createLogicIn(m_pNNode[0]);
0219 
0220     m_pSimulator = Simulator::self();
0221 
0222     m_lastDrawState = 0.0;
0223     m_lastSwitchTime = m_lastDrawTime = m_pSimulator->time();
0224     m_highTime = 0;
0225     m_bLastState = false;
0226     m_bDynamicContent = true;
0227 
0228     //m_pIn->setCallback(this, (CallbackPtr)(&ECLogicOutput::inStateChanged));
0229     m_pIn->setCallback2(ECLogicOutput_inStateChanged, this);
0230 }
0231 
0232 ECLogicOutput::~ECLogicOutput()
0233 {
0234 }
0235 
0236 void ECLogicOutput::inStateChanged(bool newState)
0237 {
0238     if (m_bLastState == newState)
0239         return;
0240 
0241     unsigned long long newTime = m_pSimulator->time();
0242     unsigned long long dt = newTime - m_lastSwitchTime;
0243 
0244     m_lastSwitchTime = newTime;
0245 
0246     m_bLastState = newState;
0247     if (!newState) {
0248         // Gone from high to low
0249         m_highTime += dt;
0250     }
0251 }
0252 
0253 void ECLogicOutput::drawShape(QPainter &p)
0254 {
0255     unsigned long long newTime = m_pSimulator->time();
0256     unsigned long long runTime = newTime - m_lastDrawTime;
0257     m_lastDrawTime = newTime;
0258 
0259     if (m_bLastState) {
0260         // Logic in is currently high
0261         m_highTime += newTime - m_lastSwitchTime;
0262     }
0263 
0264     double state;
0265 
0266     if (runTime == 0)
0267         state = m_lastDrawState;
0268 
0269     else
0270         state = m_lastDrawState = double(m_highTime) / double(runTime);
0271 
0272     initPainter(p);
0273     p.setBrush(QColor(255, uint(255 - state * (255 - 166)), uint((1 - state) * 255)));
0274     p.drawEllipse(int(x() - 8), int(y() - 8), width(), height());
0275     deinitPainter(p);
0276 
0277     m_lastSwitchTime = newTime;
0278     m_highTime = 0;
0279 }
0280 // END class ECLogicOutput