diff options
author | Karel Kočí <cynerd@email.cz> | 2018-01-17 21:35:51 +0100 |
---|---|---|
committer | Karel Kočí <cynerd@email.cz> | 2018-01-17 21:35:51 +0100 |
commit | 6ed6360bfde189191bd976d8969c2834b33ec64e (patch) | |
tree | 0038b3c3a2fba84204647ac3113519b8255ab164 /qtmips_gui/coreview | |
parent | 4a9975f012e74022247c3e9e1c143d2b0ea21925 (diff) | |
download | qtmips-6ed6360bfde189191bd976d8969c2834b33ec64e.tar.gz qtmips-6ed6360bfde189191bd976d8969c2834b33ec64e.tar.bz2 qtmips-6ed6360bfde189191bd976d8969c2834b33ec64e.zip |
Add logicblock and Control Unit to scheme
Diffstat (limited to 'qtmips_gui/coreview')
-rw-r--r-- | qtmips_gui/coreview/logicblock.cpp | 99 | ||||
-rw-r--r-- | qtmips_gui/coreview/logicblock.h | 44 |
2 files changed, 143 insertions, 0 deletions
diff --git a/qtmips_gui/coreview/logicblock.cpp b/qtmips_gui/coreview/logicblock.cpp new file mode 100644 index 0000000..6b5769a --- /dev/null +++ b/qtmips_gui/coreview/logicblock.cpp @@ -0,0 +1,99 @@ +#include "logicblock.h" +#include <cmath> + +using namespace coreview; + +////////////////////// +#define GAP 3 +#define RADIUS GAP +#define LINE_OFFSET 1 +#define PENW 1 +////////////////////// + +LogicBlock::LogicBlock(QString name) { + LogicBlock({name}); +} + +LogicBlock::LogicBlock(QVector<QString> name) : QGraphicsItem(nullptr) { + QFont font; + font.setPointSize(7); + + qreal h = 0, w = 0; + for (int i = 0; i < name.size(); i++) { + QGraphicsSimpleTextItem *t = new QGraphicsSimpleTextItem(name[i], this); + t->setFont(font); + text.append(t); + QRectF t_box = t->boundingRect(); + t->setPos(-t_box.width()/2, h + LINE_OFFSET); + h += t_box.height() + LINE_OFFSET; + if (w < t_box.width()) + w = t_box.width(); + } + + box = QRectF(-w/2 - GAP, -GAP, w + (2*GAP), h + (2*GAP)); +} + +LogicBlock::~LogicBlock() { + for (int i = 0; i < connectors.size(); i++) + delete connectors[i].con; + for (int i = 0; i < text.size(); i++) + delete text[i]; +} + +QRectF LogicBlock::boundingRect() const { + return QRectF(box.x() - PENW/2, box.y() - PENW/2, box.width() + PENW, box.height() + PENW); +} + +void LogicBlock::paint(QPainter *painter, const QStyleOptionGraphicsItem *option __attribute__((unused)), QWidget *widget __attribute__((unused))) { + painter->drawRoundedRect(box, RADIUS, RADIUS); +} + +void LogicBlock::setPos(qreal x, qreal y) { + QGraphicsItem::setPos(x, y); + for (int i = 0; i < connectors.size(); i++) { + struct Con &c = connectors[i]; + c.con->setPos(x + c.p.x(), y + c.p.y()); + } +} + +void LogicBlock::setSize(qreal width, qreal height) { + box.setX(-width/2 - GAP); + box.setWidth(width + (2*GAP)); + box.setHeight(height + (2*GAP)); + for (int i = 0; i < connectors.size(); i++) { // Update point for all connectors + struct Con &c = connectors[i]; + c.p = con_pos(c.x, c.y); + } + setPos(x(), y()); +} + +static qreal sign(qreal v) { + // This intentionally doesn't return 0 on v == 0 + return (0 <= v) - (0 > v); +} + +const Connector *LogicBlock::new_connector(qreal x, qreal y) { + // stick to closest edge + if (fabs(x) > fabs(y)) + x = sign(x); + else + y = sign(y); + + // Note: we are using here that 0 and M_PI is same angle but different orientation (but we ignore orientation for now) + Connector *c = new Connector(fabs(x) > fabs(y) ? 0 : M_PI_2); + connectors.append({ + .con = c, + .x = x, + .y = y, + .p = con_pos(x, y) + }); + setPos(this->x(), this->y()); // Update connector position + return c; +} + +QPointF LogicBlock::con_pos(qreal x, qreal y) { + qreal px, py; + px = (box.right() - GAP) * x + (GAP * sign(x)); + py = (box.bottom()/2 - GAP) * (y + 1) + (GAP * sign(y)); + return QPointF(px, py); +} diff --git a/qtmips_gui/coreview/logicblock.h b/qtmips_gui/coreview/logicblock.h new file mode 100644 index 0000000..4c1310c --- /dev/null +++ b/qtmips_gui/coreview/logicblock.h @@ -0,0 +1,44 @@ +#ifndef LOGICBLOCK_H +#define LOGICBLOCK_H + +#include <QGraphicsItem> +#include <QPainter> +#include <QGraphicsSimpleTextItem> +#include <QVector> +#include "connection.h" + +namespace coreview { + +class LogicBlock : public QGraphicsItem { +public: + LogicBlock(QString name); + LogicBlock(QVector<QString> name); + ~LogicBlock(); + + QRectF boundingRect() const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + + void setPos(qreal x, qreal y); + void setSize(qreal width, qreal height); + + // This creates new connector + // Position is determined by x and y in 0 to 1 range and is mapped to real size of this block + // Using x=y and x=-y coordinates is not supported + const Connector *new_connector(qreal x, qreal y); + +private: + QVector<QGraphicsSimpleTextItem*> text; + QRectF box; + + struct Con { + Connector *con; + qreal x, y; + QPointF p; + }; + QVector<struct Con> connectors; + QPointF con_pos(qreal x, qreal y); +}; + +} + +#endif // LOGICBLOCK_H |