From a33fa1d2749971a07fac6f541227a9e57f8ef499 Mon Sep 17 00:00:00 2001
From: Martin Hanzik <martin@hanzik.com>
Date: Sat, 31 Mar 2018 16:06:47 +0200
Subject: [PATCH] Major refactoring of Graphics/Model boxes

---
 agui2/CMakeLists.txt                          |  32 ++-
 agui2/ConnectionHelper.cpp                    |  37 ----
 agui2/ConnectionHelper.h                      |  17 --
 .../Graphics/{ => Connection}/Connection.cpp  |  28 ++-
 agui2/Graphics/{ => Connection}/Connection.h  |  11 +-
 .../{ => Connection}/ConnectionBox.cpp        |  44 ++--
 .../Graphics/{ => Connection}/ConnectionBox.h |  22 +-
 .../Connection/InputConnectionBox.cpp         |  17 ++
 .../Graphics/Connection/InputConnectionBox.h  |  21 ++
 .../Connection/OutputConnectionBox.cpp        |  16 ++
 .../Graphics/Connection/OutputConnectionBox.h |  19 ++
 agui2/Graphics/GraphicsBox.cpp                | 204 +++---------------
 agui2/Graphics/GraphicsBox.h                  |  62 ++----
 agui2/Graphics/GraphicsConnection.cpp         | 136 ------------
 agui2/Graphics/GraphicsConnection.h           |  37 ----
 agui2/Graphics/GraphicsScene.cpp              |  15 +-
 agui2/Graphics/GraphicsScene.h                |   1 -
 agui2/Graphics/InputGraphicsBox.cpp           |  62 ++----
 agui2/Graphics/InputGraphicsBox.h             |  17 +-
 agui2/Graphics/OutputGraphicsBox.cpp          |  29 ---
 agui2/Graphics/OutputGraphicsBox.h            |  14 --
 agui2/MainWindow.cpp                          | 113 +++++-----
 agui2/MainWindow.h                            |   7 +-
 agui2/Models/AlgorithmModelBox.cpp            |  71 ++++++
 agui2/Models/AlgorithmModelBox.h              |  14 ++
 agui2/Models/DoubleModelBox.cpp               |  82 -------
 agui2/Models/DoubleModelBox.h                 |  25 ---
 agui2/Models/InputModelBox.cpp                |  37 +---
 agui2/Models/InputModelBox.h                  |  36 ++--
 agui2/Models/ModelBox.cpp                     |  30 ++-
 agui2/Models/ModelBox.h                       |  59 +++--
 agui2/Models/OutputModelBox.cpp               | 195 +----------------
 agui2/Models/OutputModelBox.h                 |  40 +---
 agui2/Models/SingleModelBox.cpp               |  52 -----
 agui2/Models/SingleModelBox.h                 |  25 ---
 agui2/WrapperBox.cpp                          |  72 -------
 agui2/WrapperBox.h                            |  27 ---
 agui2/WrapperFactory.cpp                      | 113 +++++-----
 agui2/WrapperFactory.h                        |   7 +-
 39 files changed, 537 insertions(+), 1309 deletions(-)
 delete mode 100644 agui2/ConnectionHelper.cpp
 delete mode 100644 agui2/ConnectionHelper.h
 rename agui2/Graphics/{ => Connection}/Connection.cpp (63%)
 rename agui2/Graphics/{ => Connection}/Connection.h (55%)
 rename agui2/Graphics/{ => Connection}/ConnectionBox.cpp (70%)
 rename agui2/Graphics/{ => Connection}/ConnectionBox.h (66%)
 create mode 100644 agui2/Graphics/Connection/InputConnectionBox.cpp
 create mode 100644 agui2/Graphics/Connection/InputConnectionBox.h
 create mode 100644 agui2/Graphics/Connection/OutputConnectionBox.cpp
 create mode 100644 agui2/Graphics/Connection/OutputConnectionBox.h
 delete mode 100644 agui2/Graphics/GraphicsConnection.cpp
 delete mode 100644 agui2/Graphics/GraphicsConnection.h
 delete mode 100644 agui2/Graphics/OutputGraphicsBox.cpp
 delete mode 100644 agui2/Graphics/OutputGraphicsBox.h
 create mode 100644 agui2/Models/AlgorithmModelBox.cpp
 create mode 100644 agui2/Models/AlgorithmModelBox.h
 delete mode 100644 agui2/Models/DoubleModelBox.cpp
 delete mode 100644 agui2/Models/DoubleModelBox.h
 delete mode 100644 agui2/Models/SingleModelBox.cpp
 delete mode 100644 agui2/Models/SingleModelBox.h
 delete mode 100644 agui2/WrapperBox.cpp
 delete mode 100644 agui2/WrapperBox.h

diff --git a/agui2/CMakeLists.txt b/agui2/CMakeLists.txt
index 0bd4c60051..857dd699ba 100644
--- a/agui2/CMakeLists.txt
+++ b/agui2/CMakeLists.txt
@@ -39,51 +39,45 @@ link_directories(${ALIB_PATH}/bin-debug)
 add_executable(${PROJECT_NAME}
         AlibExceptionHandler.cpp
         AlibExceptionHandler.h
-        ConnectionHelper.cpp
-        ConnectionHelper.h
         Converter.cpp
         Converter.h
-        Graphics/Connection.cpp
-        Graphics/Connection.h
-        Graphics/ConnectionBox.cpp
-        Graphics/ConnectionBox.h
+        Graphics/Connection/Connection.cpp
+        Graphics/Connection/Connection.h
+        Graphics/Connection/ConnectionBox.cpp
+        Graphics/Connection/ConnectionBox.h
+        Graphics/Connection/InputConnectionBox.cpp
+        Graphics/Connection/InputConnectionBox.h
+        Graphics/Connection/OutputConnectionBox.cpp
+        Graphics/Connection/OutputConnectionBox.h
         Graphics/Dialogs/InputDialog.cpp
         Graphics/Dialogs/InputDialog.h
         Graphics/Dialogs/OutputDialog.cpp
         Graphics/Dialogs/OutputDialog.h
         Graphics/Dialogs/ResultDialog.cpp
         Graphics/Dialogs/ResultDialog.h
-        Graphics/GraphicsBox.cpp
-        Graphics/GraphicsBox.h
-        Graphics/GraphicsConnection.cpp
-        Graphics/GraphicsConnection.h
         Graphics/GraphicsScene.cpp
         Graphics/GraphicsScene.h
+        Graphics/GraphicsBox.cpp
+        Graphics/GraphicsBox.h
         Graphics/InputGraphicsBox.cpp
         Graphics/InputGraphicsBox.h
-        Graphics/OutputGraphicsBox.cpp
-        Graphics/OutputGraphicsBox.h
         GraphvizIntegrator.cpp
         GraphvizIntegrator.h
         main.cpp
         MainWindow.cpp
         MainWindow.h
-        Models/DoubleModelBox.cpp
-        Models/DoubleModelBox.h
+        Models/InputSettings.h
+        Models/AlgorithmModelBox.cpp
+        Models/AlgorithmModelBox.h
         Models/InputModelBox.cpp
         Models/InputModelBox.h
-        Models/InputSettings.h
         Models/ModelBox.cpp
         Models/ModelBox.h
         Models/OutputModelBox.cpp
         Models/OutputModelBox.h
         Models/OutputSettings.h
-        Models/SingleModelBox.cpp
-        Models/SingleModelBox.h
         Utils.cpp
         Utils.h
-        WrapperBox.cpp
-        WrapperBox.h
         WrapperFactory.cpp
         WrapperFactory.h
         )
diff --git a/agui2/ConnectionHelper.cpp b/agui2/ConnectionHelper.cpp
deleted file mode 100644
index 6ca08a63eb..0000000000
--- a/agui2/ConnectionHelper.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-#include <ConnectionHelper.h>
-
-#include <QGraphicsScene>
-
-#include <WrapperBox.h>
-
-ConnectionHelper &ConnectionHelper::getInstance()
-{
-    static ConnectionHelper instance;
-    return instance;
-}
-
-void ConnectionHelper::startConnection(WrapperBox *origin)
-{
-    m_origin = origin;
-    m_origin->disconnectOutput();
-}
-
-void ConnectionHelper::completeConnection(WrapperBox *target)
-{
-    if( target == nullptr || m_origin == nullptr || m_origin == target )
-    {
-        m_origin = nullptr;
-        return;
-    }
-    if( target->getModel()->acceptInput() )
-    {
-        target->getAvailableInput();
-        m_Connection = new GraphicsConnection( m_origin, target);
-    }
-    m_origin = nullptr;
-}
-
-ConnectionHelper::ConnectionHelper()
-{
-    m_Connection = nullptr;
-}
diff --git a/agui2/ConnectionHelper.h b/agui2/ConnectionHelper.h
deleted file mode 100644
index 7290597d38..0000000000
--- a/agui2/ConnectionHelper.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#pragma once
-class GraphicsConnection;
-class WrapperBox;
-
-class ConnectionHelper
-{
-public:
-    static ConnectionHelper& getInstance();
-    void startConnection(WrapperBox* origin );
-    void completeConnection(WrapperBox* target);
-private:
-    GraphicsConnection* m_Connection;
-    WrapperBox* m_origin;
-    ConnectionHelper();
-};
-
-
diff --git a/agui2/Graphics/Connection.cpp b/agui2/Graphics/Connection/Connection.cpp
similarity index 63%
rename from agui2/Graphics/Connection.cpp
rename to agui2/Graphics/Connection/Connection.cpp
index 94197631e7..b313fadf95 100644
--- a/agui2/Graphics/Connection.cpp
+++ b/agui2/Graphics/Connection/Connection.cpp
@@ -1,27 +1,29 @@
-#include <Graphics/Connection.h>
+#include <Graphics/Connection/Connection.h>
 
 #include <QGraphicsScene>
 #include <QPainter>
 
-#include <Graphics/ConnectionBox.h>
+#include <Graphics/Connection/ConnectionBox.h>
+#include <Graphics/Connection/InputConnectionBox.h>
+#include <Graphics/Connection/OutputConnectionBox.h>
 #include <Graphics/GraphicsBox.h>
 #include <Utils.h>
-#include <WrapperBox.h>
 
-Connection::Connection(ConnectionBox* origin, ConnectionBox* target)
+Connection::Connection(OutputConnectionBox* origin, InputConnectionBox* target)
     : originConnectionBox(origin)
     , targetConnectionBox(target)
 {
-    Q_ASSERT(origin->getType() == ConnectionBox::Type::Output);
-    Q_ASSERT(target->getType() == ConnectionBox::Type::Input);
     this->setZValue(2);
     this->boundRect = Utils::pointsToRect(origin->pos(), target->pos());
     this->boundRect.adjust(-1, -1, 1, 1);
     origin->scene()->addItem(this);
     origin->scene()->update();
 
-    origin->getWrapperBox()->addOutput(target->getWrapperBox(), nullptr);
-    target->getWrapperBox()->addInput(origin->getWrapperBox(), nullptr);
+    auto* originModel = origin->getParent()->getModelBox();
+    auto* targetModel = target->getParent()->getModelBox();
+
+    originModel->addOutput(targetModel, target->getSlot());
+    targetModel->setInput(target->getSlot(), originModel);
 }
 
 QRectF Connection::boundingRect() const {
@@ -52,3 +54,13 @@ void Connection::recalculateBoundingRect(const QPointF& a, const QPointF& b) {
     this->boundRect = Utils::pointsToRect(a, b);
     this->boundRect.adjust(-1, -1, 1, 1);
 }
+
+void Connection::destroy() {
+    auto& conns = this->originConnectionBox->connections;
+    conns.erase(std::remove(conns.begin(), conns.end(), this), conns.end());
+
+    Q_ASSERT(this->targetConnectionBox->connection == this);
+    this->targetConnectionBox->connection = nullptr;
+
+    delete this;
+}
diff --git a/agui2/Graphics/Connection.h b/agui2/Graphics/Connection/Connection.h
similarity index 55%
rename from agui2/Graphics/Connection.h
rename to agui2/Graphics/Connection/Connection.h
index d5aceb1425..54a530e784 100644
--- a/agui2/Graphics/Connection.h
+++ b/agui2/Graphics/Connection/Connection.h
@@ -3,25 +3,26 @@
 #include <QtWidgets/QGraphicsItem>
 
 class ConnectionBox;
+class InputConnectionBox;
+class OutputConnectionBox;
 
 class Connection : public QGraphicsItem {
 public:
-    Connection(ConnectionBox* origin, ConnectionBox* target);
+    Connection(OutputConnectionBox* origin, InputConnectionBox* target);
 
     QRectF boundingRect() const override;
 
     void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) override;
 
-    ConnectionBox* getOriginConnectionBox() const { return this->originConnectionBox; }
-    ConnectionBox* getTargetConnectionBox() const { return this->targetConnectionBox; }
+    void destroy();
 
 private:
     void recalculateBoundingRect(const QPointF& topLeft, const QPointF& bottomRight);
 
     QRectF boundRect;
 
-    ConnectionBox* originConnectionBox;
-    ConnectionBox* targetConnectionBox;
+    OutputConnectionBox* originConnectionBox;
+    InputConnectionBox* targetConnectionBox;
 };
 
 
diff --git a/agui2/Graphics/ConnectionBox.cpp b/agui2/Graphics/Connection/ConnectionBox.cpp
similarity index 70%
rename from agui2/Graphics/ConnectionBox.cpp
rename to agui2/Graphics/Connection/ConnectionBox.cpp
index b404c4475b..d7303d25a2 100644
--- a/agui2/Graphics/ConnectionBox.cpp
+++ b/agui2/Graphics/Connection/ConnectionBox.cpp
@@ -1,19 +1,21 @@
-#include <Graphics/ConnectionBox.h>
+#include <Graphics/Connection/ConnectionBox.h>
 
 #include <utility>
 
 #include <QtGui/QDrag>
 #include <QtWidgets/QApplication>
 
+#include <Graphics/Connection/InputConnectionBox.h>
+#include <Graphics/Connection/OutputConnectionBox.h>
 #include <Graphics/GraphicsBox.h>
 #include <Graphics/GraphicsScene.h>
-#include <WrapperBox.h>
+#include <QtWidgets/QMenu>
 
 const QColor ConnectionBox::defaultColor = Qt::white;
 
 ConnectionBox::ConnectionBox(GraphicsBox* parent, Type type)
     : QGraphicsRectItem(-8, -8, 16, 16, parent)
-    , _type(type)
+    , type(type)
 
 {
     this->setBrush(ConnectionBox::defaultColor);
@@ -68,18 +70,20 @@ void ConnectionBox::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) {
     {
         this->setColor(ConnectionBox::defaultColor);
         other->setColor(ConnectionBox::defaultColor);
-        ConnectionBox::connect(this, other);
+
+        auto* origin = this;
+        auto* target = other;
+        if (origin->getType() != ConnectionBox::Type::Output)
+            std::swap(origin, target);
+
+        ConnectionBox::connect(dynamic_cast<OutputConnectionBox*>(origin), dynamic_cast<InputConnectionBox*>(target));
     }
 }
 
-void ConnectionBox::connect(ConnectionBox* a, ConnectionBox* b) {
-    Q_ASSERT(a->getType() != b->getType());
-    auto* origin = a;
-    auto* target = b;
-    if (origin->getType() == ConnectionBox::Type::Input)
-        std::swap(origin, target);
-
-    origin->connection = target->connection = std::make_shared<Connection>(origin, target);
+void ConnectionBox::connect(gsl::not_null<OutputConnectionBox*> origin, gsl::not_null<InputConnectionBox*> target) {
+    auto connection = new Connection(origin, target);
+    origin->addConnection(connection);
+    target->setConnection(connection);
 }
 
 void ConnectionBox::contextMenuEvent(QGraphicsSceneContextMenuEvent* event) {
@@ -90,22 +94,14 @@ void ConnectionBox::contextMenuEvent(QGraphicsSceneContextMenuEvent* event) {
     event->accept();
 }
 
-void ConnectionBox::on_Disconnect() {
-    auto* origin = this->connection->getOriginConnectionBox();
-    auto* target = this->connection->getTargetConnectionBox();
-    origin->getWrapperBox()->removeOutput();
-    target->getWrapperBox()->removeInput(origin->getWrapperBox(), nullptr);
-
-    origin->connection.reset();
-    target->connection.reset();
-}
-
 void ConnectionBox::setColor(QColor color) {
     QBrush brush = this->brush();
     brush.setColor(color);
     this->setBrush(brush);
 }
 
-WrapperBox* ConnectionBox::getWrapperBox() const {
-    return dynamic_cast<GraphicsBox*>(this->parentObject())->getWrapperBox();
+GraphicsBox* ConnectionBox::getParent() const {
+    auto* parent = dynamic_cast<GraphicsBox*>(this->parentObject());
+    Q_ASSERT(parent);
+    return parent;
 }
diff --git a/agui2/Graphics/ConnectionBox.h b/agui2/Graphics/Connection/ConnectionBox.h
similarity index 66%
rename from agui2/Graphics/ConnectionBox.h
rename to agui2/Graphics/Connection/ConnectionBox.h
index c560aae739..b7fb98f786 100644
--- a/agui2/Graphics/ConnectionBox.h
+++ b/agui2/Graphics/Connection/ConnectionBox.h
@@ -3,10 +3,13 @@
 
 #include <QtWidgets/QGraphicsRectItem>
 
-#include <Graphics/Connection.h>
+#include <gsl/pointers>
 
+#include <Graphics/Connection/Connection.h>
+
+class InputConnectionBox;
 class GraphicsBox;
-class WrapperBox;
+class OutputConnectionBox;
 
 class ConnectionBox : public QObject, public QGraphicsRectItem {
     Q_OBJECT
@@ -18,31 +21,30 @@ public:
         Output
     };
 
-    ConnectionBox(GraphicsBox* parent, Type type);
-
     static const QColor defaultColor;
 
-    Type getType() const { return this->_type; }
-    WrapperBox* getWrapperBox() const;
+    Type getType() const { return this->type; }
+    GraphicsBox* getParent() const;
 
 protected:
+    ConnectionBox(GraphicsBox* parent, Type type);
+
     void mousePressEvent(QGraphicsSceneMouseEvent* event) override;
     void mouseMoveEvent(QGraphicsSceneMouseEvent* event) override;
     void mouseReleaseEvent(QGraphicsSceneMouseEvent* event) override;
 
     void contextMenuEvent(QGraphicsSceneContextMenuEvent* event) override;
 
-    static void connect(ConnectionBox* a, ConnectionBox* b);
+    static void connect(gsl::not_null<OutputConnectionBox*> origin, gsl::not_null<InputConnectionBox*> target);
 
 private:
     void setColor(QColor color);
 
-    std::shared_ptr<Connection> connection;
     QGraphicsLineItem* tempLine = nullptr;
-    Type _type;
+    Type type;
 
 private slots:
-    void on_Disconnect();
+    virtual void on_Disconnect() = 0;
 };
 
 
diff --git a/agui2/Graphics/Connection/InputConnectionBox.cpp b/agui2/Graphics/Connection/InputConnectionBox.cpp
new file mode 100644
index 0000000000..99222ff246
--- /dev/null
+++ b/agui2/Graphics/Connection/InputConnectionBox.cpp
@@ -0,0 +1,17 @@
+#include <Graphics/Connection/InputConnectionBox.h>
+
+InputConnectionBox::InputConnectionBox(GraphicsBox* parent, uint8_t slot)
+    : ConnectionBox(parent, ConnectionBox::Type::Input)
+    , slot(slot)
+{}
+
+void InputConnectionBox::setConnection(Connection* connection) {
+    Q_ASSERT(!this->connection);
+    this->connection = connection;
+}
+
+void InputConnectionBox::on_Disconnect() {
+    Q_ASSERT(this->connection);
+    this->connection->destroy();
+    Q_ASSERT(!this->connection);
+}
diff --git a/agui2/Graphics/Connection/InputConnectionBox.h b/agui2/Graphics/Connection/InputConnectionBox.h
new file mode 100644
index 0000000000..e27a8d10b6
--- /dev/null
+++ b/agui2/Graphics/Connection/InputConnectionBox.h
@@ -0,0 +1,21 @@
+#pragma once
+#include <Graphics/Connection/ConnectionBox.h>
+
+class InputConnectionBox : public ConnectionBox {
+    friend class Connection;
+
+public:
+    explicit InputConnectionBox(GraphicsBox* parent, uint8_t slot);
+
+    void setConnection(Connection* connection);
+    uint8_t getSlot() const { return this->slot; }
+
+private:
+    void on_Disconnect() override;
+
+protected:
+    Connection* connection = nullptr;
+    uint8_t slot;
+};
+
+
diff --git a/agui2/Graphics/Connection/OutputConnectionBox.cpp b/agui2/Graphics/Connection/OutputConnectionBox.cpp
new file mode 100644
index 0000000000..97d4ba784f
--- /dev/null
+++ b/agui2/Graphics/Connection/OutputConnectionBox.cpp
@@ -0,0 +1,16 @@
+#include <Graphics/Connection/OutputConnectionBox.h>
+
+OutputConnectionBox::OutputConnectionBox(GraphicsBox* parent)
+    : ConnectionBox(parent, ConnectionBox::Type::Output)
+{}
+
+void OutputConnectionBox::addConnection(Connection* connection) {
+    this->connections.push_back(connection);
+}
+
+void OutputConnectionBox::on_Disconnect() {
+    Q_ASSERT(!this->connections.empty());
+    for (auto* connection: this->connections)
+        connection->destroy();
+    Q_ASSERT(this->connections.empty());
+}
diff --git a/agui2/Graphics/Connection/OutputConnectionBox.h b/agui2/Graphics/Connection/OutputConnectionBox.h
new file mode 100644
index 0000000000..5f228e1c01
--- /dev/null
+++ b/agui2/Graphics/Connection/OutputConnectionBox.h
@@ -0,0 +1,19 @@
+#pragma once
+#include <Graphics/Connection/ConnectionBox.h>
+
+class OutputConnectionBox : public ConnectionBox {
+    friend class Connection;
+
+public:
+    explicit OutputConnectionBox(GraphicsBox* parent);
+
+    void addConnection(Connection* connection);
+
+private:
+    void on_Disconnect() override;
+
+protected:
+    std::vector<Connection*> connections;
+};
+
+
diff --git a/agui2/Graphics/GraphicsBox.cpp b/agui2/Graphics/GraphicsBox.cpp
index 8805ca9ced..9406e3a153 100644
--- a/agui2/Graphics/GraphicsBox.cpp
+++ b/agui2/Graphics/GraphicsBox.cpp
@@ -2,195 +2,55 @@
 
 #include <utility>
 
-#include <QDialog>
-#include <QGraphicsScene>
-#include <QGraphicsSceneContextMenuEvent>
+#include <QtCore/QRectF>
+#include <QtGui/QPainter>
+#include <QtWidgets/QStyleOptionGraphicsItem>
 
-#include <ConnectionHelper.h>
-#include <Graphics/ConnectionBox.h>
-#include <Graphics/GraphicsConnection.h>
-#include <Graphics/GraphicsScene.h>
-#include <WrapperBox.h>
+#include <Graphics/Connection/InputConnectionBox.h>
+#include <Graphics/Connection/OutputConnectionBox.h>
 
-GraphicsBox::GraphicsBox(QString text, qreal x, qreal y, uint8_t inputs, uint8_t outputs)
-    : m_text(std::move(text))
-    , m_color(Qt::blue)
+GraphicsBox::GraphicsBox(std::unique_ptr<ModelBox> modelBox, QString text, QPointF pos)
+    : color(Qt::blue)
+    , text(std::move(text))
+    , modelBox(std::move(modelBox))
 {
-    m_font.setBold(true);
-    m_font.setPixelSize(18);
+    this->font.setBold(true);
+    this->font.setPixelSize(18);
 
-    setPos(x, y);
-    setFlags(ItemIsMovable);
-    setZValue(1);
+    this->setPos(pos);
+    this->setFlags(ItemIsMovable);
+    this->setZValue(1);
+    this->setBoundingRectangle();
 
-    setBoundingRectangle();
-
-    this->inConnections.fill(nullptr);
-
-    this->inputConnections.reserve(inputs);
-    for (uint8_t i = 0; i < inputs; ++i)
+    uint8_t maxInputCount = this->modelBox->getMaxInputCount();
+    for (uint8_t i = 0; i < maxInputCount; ++i)
     {
-        auto* box = new ConnectionBox(this, ConnectionBox::Type::Input);
-        box->setPos(this->m_boundRect.left(), this->m_boundRect.top() + ((i + 1) * this->m_boundRect.height()) / float(inputs + 1));
-        this->inputConnections.push_back(box);
+        auto* box = new InputConnectionBox(this, i);
+        box->setPos(this->boundRect.left(), this->boundRect.top() + ((i + 1) * this->boundRect.height()) / float(maxInputCount + 1));
+        this->inputConnectionBoxes.push_back(box);
     }
 
-    this->outputConnections.reserve(outputs);
-    for (uint8_t i = 0; i < outputs; ++i)
-    {
-        auto* box = new ConnectionBox(this, ConnectionBox::Type::Output);
-        box->setPos(this->m_boundRect.right(), this->m_boundRect.top() + ((i + 1) * this->m_boundRect.height()) / float(outputs + 1));
-        this->outputConnections.push_back(box);
+    if (this->modelBox->canHaveOutput()) {
+        this->outputConnectionBox = new OutputConnectionBox(this);
+        this->outputConnectionBox->setPos(this->boundRect.right(), this->boundRect.top() + this->boundRect.height() / 2.0);
     }
 }
 
-GraphicsBox::~GraphicsBox()
-{
-    for (auto* conn: this->inConnections)
-        if (conn)
-            conn->on_Disconnect();
-    if(m_OutConnection)
-        m_OutConnection->on_Disconnect();
-}
-
 void GraphicsBox::setBoundingRectangle()
 {
-    m_boundRect = QFontMetrics(m_font).boundingRect(m_text);
-    m_boundRect.adjust(-BOX_MARGIN, -BOX_MARGIN, BOX_MARGIN, BOX_MARGIN);
+    this->boundRect = QFontMetrics(this->font).boundingRect(this->text);
+    this->boundRect.adjust(-20, -20, 20, 20);
 }
 
-QRectF GraphicsBox::boundingRect() const
-{
-    return m_boundRect;
+QRectF GraphicsBox::boundingRect() const {
+    return this->boundRect;
 }
 
-void GraphicsBox::paint(QPainter *painter, const QStyleOptionGraphicsItem *options __attribute__((unused)), QWidget *widget __attribute__((unused)))
-{
-    painter->setFont(m_font);
+void GraphicsBox::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) {
+    painter->setFont(this->font);
     painter->setPen(Qt::white);
-    painter->fillRect(m_boundRect,m_color);
+    painter->fillRect(this->boundRect, this->color);
     prepareGeometryChange();
-    painter->drawText(m_boundRect, Qt::AlignCenter, m_text, &m_boundRect );
-    m_boundRect.adjust(-BOX_MARGIN, -BOX_MARGIN, BOX_MARGIN, BOX_MARGIN);
-}
-
-void GraphicsBox::addOutput(GraphicsConnection *connection)
-{
-    m_OutConnection = connection;
-}
-
-void GraphicsBox::addInput(GraphicsConnection* connection)
-{
-    if (this->inputConnections.size() == 1) {
-        this->inConnections[0] = connection;
-    }
-    else {
-        if (this->inConnections[0] == nullptr) {
-            this->inConnections[0] = connection;
-        }
-        else {
-            Q_ASSERT(this->inputConnections.size() > 1);
-            this->inConnections[1] = connection;
-        }
-    }
-}
-
-void GraphicsBox::removeOutput()
-{
-    m_OutConnection = nullptr;
-}
-
-void GraphicsBox::removeInput(GraphicsConnection *connection __attribute__((unused)))
-{
-    if (this->inputConnections.size() == 1) {
-        this->inConnections[0] = nullptr;
-    }
-    else {
-        if (this->inConnections[0] == connection) {
-            this->inConnections[0] = nullptr;
-        } else if (this->inConnections[1] == connection) {
-            Q_ASSERT(this->inputConnections.size() > 1);
-            this->inConnections[1] = nullptr;
-        }
-    }
+    painter->drawText(this->boundRect, Qt::AlignCenter, this->text, &this->boundRect);
+    this->boundRect.adjust(-20, -20, 20, 20);
 }
-
-QPointF GraphicsBox::getConnectionOrigin()
-{
-    return {m_boundRect.right(), m_boundRect.center().y()};
-}
-
-QPointF GraphicsBox::getConnectionTarget(GraphicsConnection *connection __attribute__((unused)))
-{
-    if (this->inputConnections.size() == 1)
-        return {m_boundRect.left(), m_boundRect.center().y()};
-
-    QPointF topPoint (m_boundRect.left(), m_boundRect.y() + (m_boundRect.height() / 3.0));
-    QPointF bottomPoint (m_boundRect.left(), m_boundRect.y() + (2.0 * m_boundRect.height() / 3.0));
-
-    if (this->inConnections[0] && this->inConnections[1]) {
-        if (this->inConnections[0] == connection)
-        {
-            if (this->inConnections[0]->getOriginPoint().y() < this->inConnections[1]->getOriginPoint().y())
-                return topPoint;
-            else
-                return bottomPoint;
-        }
-        else {
-            if (this->inConnections[0]->getOriginPoint().y() < this->inConnections[1]->getOriginPoint().y())
-                return bottomPoint;
-            else
-                return topPoint;
-        }
-    }
-    else {
-        if (connection->getOriginPoint().y() < m_boundRect.center().y())
-            return topPoint;
-        else
-            return bottomPoint;
-    }
-}
-
-void GraphicsBox::setWrapper(WrapperBox *wrapper)
-{
-    m_wrapper = wrapper;
-}
-
-void GraphicsBox::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
-{
-    if( event->button() == Qt::LeftButton )
-    {
-        event->accept();
-        ConnectionHelper::getInstance().completeConnection( m_wrapper );
-    }
-    QGraphicsObject::mouseReleaseEvent(event);
-}
-
-void GraphicsBox::finishMenu(QMenu *menu)
-{
-    QAction * a;
-    a = menu->addAction( m_wrapper->getModel()->isOutputSet() ? "Re&connect" : "&Connect");
-    QObject::connect(a,SIGNAL(triggered()), this, SLOT(on_Connect()));
-    a = menu->addAction("&Delete");
-    QObject::connect(a,SIGNAL(triggered()), this, SLOT(on_Delete()));
-}
-
-void GraphicsBox::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
-{
-    QMenu menu;
-    finishMenu(&menu);
-    menu.exec(event->screenPos());
-    ungrabMouse();
-    event->accept();
-}
-
-void GraphicsBox::on_Connect()
-{
-    ConnectionHelper::getInstance().startConnection( m_wrapper );
-}
-
-void GraphicsBox::on_Delete()
-{
-    delete m_wrapper;
-}
-
diff --git a/agui2/Graphics/GraphicsBox.h b/agui2/Graphics/GraphicsBox.h
index 5fdcbcc1ed..1d23bd97e9 100644
--- a/agui2/Graphics/GraphicsBox.h
+++ b/agui2/Graphics/GraphicsBox.h
@@ -1,56 +1,38 @@
 #pragma once
-#include <QAction>
-#include <QBrush>
-#include <QPainter>
-#include <QGraphicsItem>
-#include <QFont>
-#include <QMenu>
 
-#include <Graphics/GraphicsConnection.h>
+#include <QtGui/QFont>
+#include <QtWidgets/QGraphicsObject>
 
-#define BOX_MARGIN 20
+#include <gsl/pointers>
+
+#include <Models/ModelBox.h>
 
 class ConnectionBox;
-class GraphicsConnection;
-class WrapperBox;
 
-class GraphicsBox : public QGraphicsObject
-{
+class GraphicsBox : public QGraphicsObject {
     Q_OBJECT
 public:
-    friend class WrapperBox;
+    GraphicsBox(std::unique_ptr<ModelBox> modelBox, QString text, QPointF pos);
 
-    explicit GraphicsBox(QString text, qreal x = 0, qreal y = 0, uint8_t inputs = 1, uint8_t outputs = 1);
-    ~GraphicsBox() override;
+    void setBoundingRectangle();
 
-    void paint(QPainter *painter, const QStyleOptionGraphicsItem *options, QWidget *widget) override;
-    void addOutput( GraphicsConnection* connection );
-    virtual void addInput( GraphicsConnection* connection );
-    void removeOutput();
-    virtual void removeInput( GraphicsConnection* connection );
     QRectF boundingRect() const override;
-    QPointF getConnectionOrigin();
-    virtual QPointF getConnectionTarget( GraphicsConnection* connection );
-    WrapperBox* getWrapperBox() const { return this->m_wrapper; }
+    void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) override;
+
+    ModelBox* getModelBox() const { return this->modelBox.get(); }
+
 protected:
-    QFont m_font;
-    QColor m_color;
-    QString m_text;
-    QRectF m_boundRect;
-    GraphicsConnection* m_OutConnection = nullptr;
-    std::array<GraphicsConnection*, 2> inConnections;
-    WrapperBox* m_wrapper;
-    std::vector<ConnectionBox*> inputConnections;
-    std::vector<ConnectionBox*> outputConnections;
-    void finishMenu( QMenu * menu );
-    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override ;
-    void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;
+    QColor color;
+
 private:
-    void setWrapper( WrapperBox* wrapper );
-    void setBoundingRectangle();
-private slots:
-    void on_Connect();
-    void on_Delete();
+    QRectF boundRect;
+    QString text;
+    QFont font;
+
+    std::unique_ptr<ModelBox> modelBox;
+
+    std::vector<ConnectionBox*> inputConnectionBoxes;
+    ConnectionBox* outputConnectionBox;
 };
 
 
diff --git a/agui2/Graphics/GraphicsConnection.cpp b/agui2/Graphics/GraphicsConnection.cpp
deleted file mode 100644
index 1fea9259e5..0000000000
--- a/agui2/Graphics/GraphicsConnection.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-#include <Graphics/GraphicsConnection.h>
-
-#include <QAction>
-#include <QGraphicsScene>
-#include <QMenu>
-#include <QPainter>
-
-#include <ConnectionHelper.h>
-#include <WrapperBox.h>
-
-#define SHORTEST_LINE 20.0
-
-GraphicsConnection::GraphicsConnection(WrapperBox * origin, WrapperBox * target)
-    : m_origin(origin)
-    , m_target(target)
-    , m_originGraphics(origin->getGraphics())
-    , m_targetGraphics(target->getGraphics())
-    , m_boundRect(getOriginPoint(), getTargetPoint())
-{
-    setPos(0, 0);
-    setZValue(0.5);
-
-    origin->addOutput( target, this );
-    target->addInput( m_origin, this );
-
-    m_originGraphics->scene()->addItem(this);
-    m_originGraphics->scene()->update();
-}
-
-QRectF GraphicsConnection::boundingRect() const
-{
-    return m_boundRect;
-}
-
-void GraphicsConnection::paint(QPainter *painter, const QStyleOptionGraphicsItem *options __attribute__((unused)), QWidget *widget __attribute__((unused)))
-{
-
-    QPointF originPoint = getOriginPoint();
-    QPointF targetPoint = getTargetPoint();
-    recalculateBoundingRect( originPoint, targetPoint );
-
-    painter->setPen(QPen(Qt::black,1));
-    if( (targetPoint.x() - originPoint.x()) > SHORTEST_LINE )
-        drawDirectConnection( painter, originPoint, targetPoint );
-    else
-        drawAroundConnection( painter, originPoint, targetPoint );
-}
-
-// Local coordinates
-QPointF GraphicsConnection::getOriginPoint()
-{
-    return mapFromItem(m_originGraphics, m_originGraphics->getConnectionOrigin());
-}
-
-// Local coordinates
-QPointF GraphicsConnection::getTargetPoint()
-{
-    return mapFromItem(m_targetGraphics, m_targetGraphics->getConnectionTarget( this ));
-}
-
-void GraphicsConnection::mousePressEvent(QGraphicsSceneMouseEvent *event)
-{
-    if( event->button() == Qt::LeftButton )
-    {
-        ConnectionHelper::getInstance().completeConnection(nullptr);
-    }
-    this->QGraphicsItem::mouseReleaseEvent(event);
-}
-
-void GraphicsConnection::recalculateBoundingRect(const QPointF & topLeft , const QPointF & bottomRight)
-{
-    prepareGeometryChange();
-    m_boundRect.setTopLeft( topLeft );
-    m_boundRect.setBottomRight( bottomRight );
-    m_boundRect.adjust( -1, -1, 1, 1 );
-}
-
-void GraphicsConnection::drawDirectConnection(QPainter * painter, const QPointF &originPoint, const QPointF &targetPoint)
-{
-    qreal midWidth = originPoint.x() + qAbs( originPoint.x() - targetPoint.x() )/2.0;
-    painter->drawLine(originPoint.x(), originPoint.y(),
-                      midWidth, originPoint.y());
-    painter->drawLine(midWidth, originPoint.y(),
-                      midWidth, targetPoint.y());
-    painter->drawLine(midWidth, targetPoint.y(),
-                      targetPoint.x(), targetPoint.y());
-    if( originPoint.y() < targetPoint.y() )
-        recalculateBoundingRect( originPoint, targetPoint );
-    else
-    {
-        QPointF topLeft( originPoint.x(), targetPoint.y() );
-        QPointF bottomRight( targetPoint.x(), originPoint.y() );
-        recalculateBoundingRect( topLeft, bottomRight );
-    }
-}
-
-void GraphicsConnection::drawAroundConnection(QPainter *painter, const QPointF &originPoint, const QPointF &targetPoint)
-{
-    qreal midHeight;
-    QPointF topLeft;
-    QPointF bottomRight;
-
-    if( originPoint.y() < targetPoint.y() )
-    {
-        midHeight = originPoint.y() + qAbs( originPoint.y() - targetPoint.y() )/2.0;
-        topLeft = QPointF( targetPoint.x() - SHORTEST_LINE, originPoint.y() );
-        bottomRight = QPointF( originPoint.x() + SHORTEST_LINE, targetPoint.y() );
-    }
-    else
-    {
-        midHeight = targetPoint.y() + qAbs( originPoint.y() - targetPoint.y() )/2.0;
-        topLeft = QPointF( targetPoint.x() - SHORTEST_LINE, targetPoint.y() );
-        bottomRight = QPointF( originPoint.x() + SHORTEST_LINE, originPoint.y() );
-    }
-
-    painter->drawLine(originPoint.x(), originPoint.y(),
-                      bottomRight.x(), originPoint.y());
-    painter->drawLine(bottomRight.x(), originPoint.y(),
-                      bottomRight.x(), midHeight);
-    painter->drawLine(bottomRight.x(), midHeight,
-                      topLeft.x(), midHeight);
-    painter->drawLine(topLeft.x(), midHeight,
-                      topLeft.x(), targetPoint.y());
-    painter->drawLine(topLeft.x(), targetPoint.y(),
-                      targetPoint.x(), targetPoint.y());
-    recalculateBoundingRect( topLeft, bottomRight );
-}
-
-void GraphicsConnection::on_Disconnect()
-{
-    m_origin->removeOutput();
-    m_target->removeInput( m_origin, this );
-    delete this;
-}
-
-
diff --git a/agui2/Graphics/GraphicsConnection.h b/agui2/Graphics/GraphicsConnection.h
deleted file mode 100644
index 5735d65e1c..0000000000
--- a/agui2/Graphics/GraphicsConnection.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#pragma once
-#include <tuple>
-
-#include <QGraphicsItem>
-#include <QGraphicsSceneMouseEvent>
-
-#include <Graphics/GraphicsBox.h>
-
-class GraphicsBox;
-class WrapperBox;
-
-class GraphicsConnection : public QGraphicsObject
-{
-    Q_OBJECT
-public:
-    GraphicsConnection(WrapperBox * origin, WrapperBox * target);
-    ~GraphicsConnection() override = default;
-    QRectF boundingRect() const override;
-    void paint(QPainter *painter, const QStyleOptionGraphicsItem *options, QWidget *widget) override;
-    QPointF getOriginPoint();
-    QPointF getTargetPoint();
-protected:
-    void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
-private:
-    void recalculateBoundingRect(const QPointF &topLeft, const QPointF &bottomRight);
-    void drawDirectConnection(QPainter * painter, const QPointF &originPoint, const QPointF &targetPoint);
-    void drawAroundConnection(QPainter * painter, const QPointF &originPoint, const QPointF &targetPoint);
-    GraphicsBox * m_targetGraphics;
-    GraphicsBox * m_originGraphics;
-    WrapperBox * m_target;
-    WrapperBox * m_origin;
-    QRectF m_boundRect;
-public slots:
-    void on_Disconnect();
-};
-
-
diff --git a/agui2/Graphics/GraphicsScene.cpp b/agui2/Graphics/GraphicsScene.cpp
index 405284d7d1..abdccd3423 100644
--- a/agui2/Graphics/GraphicsScene.cpp
+++ b/agui2/Graphics/GraphicsScene.cpp
@@ -2,8 +2,6 @@
 
 #include <QGraphicsView>
 
-#include <ConnectionHelper.h>
-
 GraphicsScene::GraphicsScene(QObject *parent)
         : QGraphicsScene(parent)
 {}
@@ -17,15 +15,4 @@ void GraphicsScene::wheelEvent(QGraphicsSceneWheelEvent *event)
     if( factor > 1.0 )
         view->centerOn(event->scenePos());
     event->accept();
-}
-
-void GraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
-{
-    if( event->button() == Qt::LeftButton )
-    {
-        QGraphicsItem* item = itemAt(event->scenePos(), views().first()->transform());
-        if( item == nullptr )
-            ConnectionHelper::getInstance().completeConnection(nullptr);
-    }
-    QGraphicsScene::mousePressEvent(event);
-}
+}
\ No newline at end of file
diff --git a/agui2/Graphics/GraphicsScene.h b/agui2/Graphics/GraphicsScene.h
index 7153b336a6..942ea9c904 100644
--- a/agui2/Graphics/GraphicsScene.h
+++ b/agui2/Graphics/GraphicsScene.h
@@ -11,7 +11,6 @@ public:
 
 protected:
     void wheelEvent(QGraphicsSceneWheelEvent *event) override;
-    void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
 };
 
 
diff --git a/agui2/Graphics/InputGraphicsBox.cpp b/agui2/Graphics/InputGraphicsBox.cpp
index 19fc1bec3b..9d8cdb2023 100644
--- a/agui2/Graphics/InputGraphicsBox.cpp
+++ b/agui2/Graphics/InputGraphicsBox.cpp
@@ -1,59 +1,43 @@
 #include <Graphics/InputGraphicsBox.h>
 
-#include <QMenu>
-#include <QAction>
-#include <QObject>
+#include <memory>
 
-#include <ConnectionHelper.h>
-#include <Graphics/Dialogs/InputDialog.h>
-#include <Models/InputModelBox.h>
-#include <WrapperBox.h>
+#include <QtCore/QString>
+#include <QtCore/QPointF>
+#include <QGraphicsSceneContextMenuEvent>
+#include <QtWidgets/QMenu>
 
-class ModelBox;
+#include <Graphics/Dialogs/InputDialog.h>
 
-void InputGraphicsBox::paint(QPainter *painter, const QStyleOptionGraphicsItem *options, QWidget *widget)
+InputGraphicsBox::InputGraphicsBox(std::unique_ptr<InputModelBox> modelBox,
+                                         const QString& text,
+                                         const QPointF& pos)
+    : GraphicsBox(std::move(modelBox), text, pos)
 {
-    if(dynamic_cast<InputModelBox*>(m_wrapper->getModel())->isInputEmpty() )
-        m_color = Qt::red;
-    else
-        m_color = Qt::blue;
-    GraphicsBox::paint( painter, options, widget );
+    this->color = Qt::red;
 }
 
 void InputGraphicsBox::on_SetInput()
 {
-    auto * model = dynamic_cast<InputModelBox*>(m_wrapper->getModel());
-    auto * inputDialog =  new InputDialog();
+    auto* model = dynamic_cast<InputModelBox*>(this->getModelBox());
+    Q_ASSERT(model);
+    auto inputDialog = std::make_unique<InputDialog>();
 
-    inputDialog->setSettings( model->getSettings() );
-    inputDialog->setAutomaton( model->getAutomaton() );
+    inputDialog->setSettings(model->getSettings());
+    inputDialog->setAutomaton(model->getAutomaton());
 
-    if(inputDialog->exec())
-    {
-        model->setAutomaton( inputDialog->getAutomaton() );
-        model->setSettings( inputDialog->getSettings() );
+    if (inputDialog->exec()) {
+        model->setAutomaton(inputDialog->getAutomaton());
+        model->setSettings(inputDialog->getSettings());
     }
-    delete inputDialog;
-}
-
-void InputGraphicsBox::on_Connect()
-{
-    ConnectionHelper::getInstance().startConnection( m_wrapper );
-}
 
-void InputGraphicsBox::on_Delete()
-{
-    delete m_wrapper;
+    this->color = model->getAutomaton() ? Qt::blue : Qt::red;
 }
 
-void InputGraphicsBox::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
-{
+void InputGraphicsBox::contextMenuEvent(QGraphicsSceneContextMenuEvent* event) {
     QMenu menu;
-    QAction * a;
-    a = menu.addAction("&Set Input");
-    QObject::connect(a,SIGNAL(triggered()), this, SLOT(on_SetInput()));
-    menu.addSeparator();
-    finishMenu(&menu);
+    auto* a = menu.addAction("&Set input");
+    QObject::connect(a, SIGNAL(triggered()), this, SLOT(on_SetInput()));
     menu.exec(event->screenPos());
     ungrabMouse();
     event->accept();
diff --git a/agui2/Graphics/InputGraphicsBox.h b/agui2/Graphics/InputGraphicsBox.h
index e6dafb753b..2d844074ae 100644
--- a/agui2/Graphics/InputGraphicsBox.h
+++ b/agui2/Graphics/InputGraphicsBox.h
@@ -1,19 +1,18 @@
 #pragma once
 #include <Graphics/GraphicsBox.h>
 
-class InputGraphicsBox : public GraphicsBox
-{
+#include <Models/InputModelBox.h>
+
+class InputGraphicsBox : public GraphicsBox {
     Q_OBJECT
 public:
-    InputGraphicsBox(qreal x = 0, qreal y = 0): GraphicsBox("Input", x, y, 0, 1) {}
-    virtual ~InputGraphicsBox() {}
-    virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *options, QWidget *widget);
+    InputGraphicsBox(std::unique_ptr<InputModelBox> modelBox, const QString& text, const QPointF& pos);
+
+protected:
+    void contextMenuEvent(QGraphicsSceneContextMenuEvent* event) override;
+
 private slots:
     void on_SetInput();
-    void on_Connect();
-    void on_Delete();
-protected:
-    void contextMenuEvent(QGraphicsSceneContextMenuEvent *event);
 };
 
 
diff --git a/agui2/Graphics/OutputGraphicsBox.cpp b/agui2/Graphics/OutputGraphicsBox.cpp
deleted file mode 100644
index 849c997c8c..0000000000
--- a/agui2/Graphics/OutputGraphicsBox.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-#include <Graphics/OutputGraphicsBox.h>
-
-#include <QMenu>
-#include <QAction>
-
-#include <Graphics/Dialogs/OutputDialog.h>
-#include <Models/OutputModelBox.h>
-#include <WrapperBox.h>
-
-void OutputGraphicsBox::on_SetOutput()
-{
-    auto * model = dynamic_cast<OutputModelBox*>(m_wrapper->getModel());
-    auto * outputDialog = new OutputDialog();
-    outputDialog->setSettings( model->getSettings() );
-    if( outputDialog->exec() )
-        model->setSettings( outputDialog->getSettings() );
-    delete outputDialog;
-}
-
-void OutputGraphicsBox::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
-{
-    QMenu menu;
-    QAction * a;
-    a = menu.addAction("&Set Output");
-    QObject::connect(a,SIGNAL(triggered()), this, SLOT(on_SetOutput()));
-    menu.exec(event->screenPos());
-    ungrabMouse();
-    event->accept();
-}
diff --git a/agui2/Graphics/OutputGraphicsBox.h b/agui2/Graphics/OutputGraphicsBox.h
deleted file mode 100644
index d4673ce3c0..0000000000
--- a/agui2/Graphics/OutputGraphicsBox.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#pragma once
-#include <Graphics/GraphicsBox.h>
-
-class OutputGraphicsBox : public GraphicsBox
-{
-    Q_OBJECT
-public:
-    OutputGraphicsBox( qreal x = 0, qreal y = 0 ): GraphicsBox( "Output", x, y, 1, 0 ) {}
-    virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *event);
-private slots:
-    void on_SetOutput();
-};
-
-
diff --git a/agui2/MainWindow.cpp b/agui2/MainWindow.cpp
index 3426f74459..d23916a1a3 100644
--- a/agui2/MainWindow.cpp
+++ b/agui2/MainWindow.cpp
@@ -5,12 +5,16 @@
 #include <QFileDialog>
 #include <QGraphicsItem>
 
-#include <ConnectionHelper.h>
+#include <AlibExceptionHandler.h>
 #include <Graphics/Dialogs/InputDialog.h>
 #include <Graphics/InputGraphicsBox.h>
-#include <Graphics/OutputGraphicsBox.h>
+#include <Graphics/GraphicsBox.h>
+#include <Models/InputModelBox.h>
 #include <ui_MainWindow.h>
 #include <WrapperFactory.h>
+#include <QtWidgets/QMessageBox>
+#include <Graphics/Dialogs/ResultDialog.h>
+#include "Converter.h"
 
 MainWindow::MainWindow()
     : ui(new Ui::MainWindow)
@@ -19,40 +23,50 @@ MainWindow::MainWindow()
     ui->setupUi(this);
     ui->graphicsView->setScene(this->scene.get());
 
-    WrapperBox * inputBox = WrapperFactory::create( WrapperFactory::INPUT, 0, 0 );
-    scene->addItem(inputBox->getGraphics());
-    WrapperBox * outputBox = WrapperFactory::create( WrapperFactory::OUTPUT, 400, 0 );
-    scene->addItem(outputBox->getGraphics());
-    m_output = outputBox;
+    this->scene->addItem(WrapperFactory::createNew(WrapperFactory::INPUT, 0, 200));
+    outputBox = WrapperFactory::createNew(WrapperFactory::OUTPUT, 400, 200);
+    this->scene->addItem(outputBox);
+}
+
+void MainWindow::displayError(const QString& text) const {
+    QMessageBox::critical(this->ui->graphicsView, "Error", text, QMessageBox::Close);
 }
 
 void MainWindow::on_RunBtn_clicked()
 {
-    m_output->getModel()->run();
+    AlibExceptionHandler::getInstance().reset();
+    auto result = this->outputBox->getModelBox()->run();
+    if (!result) {
+        if (AlibExceptionHandler::getInstance().isActive())
+            this->displayError(AlibExceptionHandler::getInstance().getMessage());
+        else
+            this->displayError("Nothing was outputted.");
+    }
+    else {
+        auto* resultDlg = new ResultDialog();
+        resultDlg->setImageContent(Converter::automatonToPNG(result));
+        resultDlg->exec();
+    }
 }
 
 void MainWindow::on_DeterminizeBtn_clicked()
 {
-    WrapperBox * box = WrapperFactory::create( WrapperFactory::DETERMINIZE, 200, 50 );
-    scene->addItem(box->getGraphics());
+    this->scene->addItem(WrapperFactory::createNew(WrapperFactory::DETERMINIZE, 200, 50));
 }
 
 void MainWindow::on_TotalBtn_clicked()
 {
-    WrapperBox * box = WrapperFactory::create( WrapperFactory::TOTAL, 300, 50 );
-    scene->addItem(box->getGraphics());
+    this->scene->addItem(WrapperFactory::createNew(WrapperFactory::TOTAL, 300, 50));
 }
 
 void MainWindow::on_CompactBtn_clicked()
 {
-    WrapperBox * box = WrapperFactory::create( WrapperFactory::COMPACT, 200, -50 );
-    scene->addItem(box->getGraphics());
+    this->scene->addItem(WrapperFactory::createNew(WrapperFactory::COMPACT, 200, -50));
 }
 
 void MainWindow::on_SingleInitialBtn_clicked()
 {
-    WrapperBox * box = WrapperFactory::create( WrapperFactory::SINGLE_INITIAL, 200, 30 );
-    scene->addItem(box->getGraphics());
+    this->scene->addItem(WrapperFactory::createNew(WrapperFactory::SINGLE_INITIAL, 200, 30));
 }
 
 void MainWindow::on_EpsilonRemoveBtn_clicked()
@@ -63,62 +77,53 @@ void MainWindow::on_EpsilonRemoveBtn_clicked()
     QObject::connect(a,SIGNAL(triggered()), this, SLOT(on_EpsilonRemoveIncoming()));
     a = menu.addAction("&Outgoing");
     QObject::connect(a,SIGNAL(triggered()), this, SLOT(on_EpsilonRemoveOutgoing()));
-    QPoint point = ui->EpsilonRemoveBtn->mapToGlobal( ui->EpsilonRemoveBtn->rect().topRight() );
-    menu.exec( point );
+    QPoint point = ui->EpsilonRemoveBtn->mapToGlobal(ui->EpsilonRemoveBtn->rect().topRight());
+    menu.exec(point);
 }
 
 void MainWindow::on_MinimizeBtn_clicked()
 {
-    WrapperBox * box = WrapperFactory::create( WrapperFactory::MINIMIZE, 200, 100 );
-    scene->addItem(box->getGraphics());
+    this->scene->addItem(WrapperFactory::createNew(WrapperFactory::MINIMIZE, 200, 100));
 }
 
 void MainWindow::on_NormilizeBtn_clicked()
 {
-    WrapperBox * box = WrapperFactory::create( WrapperFactory::NORMALIZE, 200, 100 );
-    scene->addItem(box->getGraphics());
+    this->scene->addItem(WrapperFactory::createNew(WrapperFactory::NORMALIZE, 200, 100));
 }
 
 void MainWindow::on_EpsilonRemoveIncoming()
 {
-    WrapperBox * box = WrapperFactory::create( WrapperFactory::EPSILON_REMOVE_IN, 200, 30 );
-    scene->addItem(box->getGraphics());
+    this->scene->addItem(WrapperFactory::createNew(WrapperFactory::EPSILON_REMOVE_IN, 200, 30));
 }
 
 void MainWindow::on_EpsilonRemoveOutgoing()
 {
-    WrapperBox * box = WrapperFactory::create( WrapperFactory::EPSILON_REMOVE_OUT, 200, 30 );
-    scene->addItem(box->getGraphics());
+    this->scene->addItem(WrapperFactory::createNew(WrapperFactory::EPSILON_REMOVE_OUT, 200, 30));
 }
 
 void MainWindow::on_RenameBtn_clicked()
 {
-    WrapperBox * box = WrapperFactory::create( WrapperFactory::RENAME, 200, 30 );
-    scene->addItem(box->getGraphics());
+    this->scene->addItem(WrapperFactory::createNew(WrapperFactory::RENAME, 200, 30));
 }
 
 void MainWindow::on_TrimBtn_clicked()
 {
-    WrapperBox * box = WrapperFactory::create( WrapperFactory::TRIM, 200, 30 );
-    scene->addItem(box->getGraphics());
+    this->scene->addItem(WrapperFactory::createNew(WrapperFactory::TRIM, 200, 30));
 }
 
 void MainWindow::on_RemoveUselessBtn_clicked()
 {
-    WrapperBox * box = WrapperFactory::create( WrapperFactory::REMOVE_USELES, 200, 30 );
-    scene->addItem(box->getGraphics());
+    this->scene->addItem(WrapperFactory::createNew(WrapperFactory::REMOVE_USELES, 200, 30));
 }
 
 void MainWindow::on_RemoveUnreachableBtn_clicked()
 {
-    WrapperBox * box = WrapperFactory::create( WrapperFactory::REMOVE_UNREACHABLE, 200, 30 );
-    scene->addItem(box->getGraphics());
+    this->scene->addItem(WrapperFactory::createNew(WrapperFactory::REMOVE_UNREACHABLE, 200, 30));
 }
 
 void MainWindow::on_ReverseBtn_clicked()
 {
-    WrapperBox * box = WrapperFactory::create( WrapperFactory::REVERSE, 200, 30 );
-    scene->addItem(box->getGraphics());
+    this->scene->addItem(WrapperFactory::createNew(WrapperFactory::REVERSE, 200, 30));
 }
 
 void MainWindow::on_IterateBtn_clicked()
@@ -129,20 +134,18 @@ void MainWindow::on_IterateBtn_clicked()
     QObject::connect(a,SIGNAL(triggered()), this, SLOT(on_Iterate()));
     a = menu.addAction("&Epsilon transitions");
     QObject::connect(a,SIGNAL(triggered()), this, SLOT(on_IterateEpsilon()));
-    QPoint point = ui->IterateBtn->mapToGlobal( ui->IterateBtn->rect().topRight() );
-    menu.exec( point );
+    QPoint point = ui->IterateBtn->mapToGlobal(ui->IterateBtn->rect().topRight());
+    menu.exec(point);
 }
 
 void MainWindow::on_Iterate()
 {
-    WrapperBox * box = WrapperFactory::create( WrapperFactory::ITERATE, 200, 30 );
-    scene->addItem(box->getGraphics());
+    this->scene->addItem(WrapperFactory::createNew(WrapperFactory::ITERATE, 200, 30));
 }
 
 void MainWindow::on_IterateEpsilon()
 {
-    WrapperBox * box = WrapperFactory::create( WrapperFactory::ITERATE_EPSILON, 200, 30 );
-    scene->addItem(box->getGraphics());
+    this->scene->addItem(WrapperFactory::createNew(WrapperFactory::ITERATE_EPSILON, 200, 30));
 }
 
 void MainWindow::on_ConcatenateBtn_clicked()
@@ -153,20 +156,18 @@ void MainWindow::on_ConcatenateBtn_clicked()
     QObject::connect(a,SIGNAL(triggered()), this, SLOT(on_Concatenate()));
     a = menu.addAction("&Epsilon transitions");
     QObject::connect(a,SIGNAL(triggered()), this, SLOT(on_ConcatenateEpsilon()));
-    QPoint point = ui->ConcatenateBtn->mapToGlobal( ui->ConcatenateBtn->rect().topRight() );
-    menu.exec( point );
+    QPoint point = ui->ConcatenateBtn->mapToGlobal(ui->ConcatenateBtn->rect().topRight());
+    menu.exec(point);
 }
 
 void MainWindow::on_Concatenate()
 {
-    WrapperBox * box = WrapperFactory::create( WrapperFactory::CONCATENATE, 200, 100 );
-    scene->addItem(box->getGraphics());
+    this->scene->addItem(WrapperFactory::createNew(WrapperFactory::CONCATENATE, 200, 100));
 }
 
 void MainWindow::on_ConcatenateEpsilon()
 {
-    WrapperBox * box = WrapperFactory::create( WrapperFactory::CONCATENATE_EPSILON, 200, 100 );
-    scene->addItem(box->getGraphics());
+    this->scene->addItem(WrapperFactory::createNew(WrapperFactory::CONCATENATE_EPSILON, 200, 100));
 }
 
 void MainWindow::on_UnionBtn_clicked()
@@ -177,31 +178,27 @@ void MainWindow::on_UnionBtn_clicked()
     QObject::connect(a,SIGNAL(triggered()), this, SLOT(on_Union()));
     a = menu.addAction("&Epsilon transitions");
     QObject::connect(a,SIGNAL(triggered()), this, SLOT(on_UnionEpsilon()));
-    QPoint point = ui->UnionBtn->mapToGlobal( ui->UnionBtn->rect().topRight() );
-    menu.exec( point );
+    QPoint point = ui->UnionBtn->mapToGlobal(ui->UnionBtn->rect().topRight());
+    menu.exec(point);
 }
 
 void MainWindow::on_Union()
 {
-    WrapperBox * box = WrapperFactory::create( WrapperFactory::UNION, 200, 100 );
-    scene->addItem(box->getGraphics());
+    this->scene->addItem(WrapperFactory::createNew(WrapperFactory::UNION, 200, 100));
 }
 
 void MainWindow::on_UnionEpsilon()
 {
-    WrapperBox * box = WrapperFactory::create( WrapperFactory::UNION_EPSILON, 200, 100 );
-    scene->addItem(box->getGraphics());
+    this->scene->addItem(WrapperFactory::createNew(WrapperFactory::UNION_EPSILON, 200, 100));
 }
 
 void MainWindow::on_IntersectBtn_clicked()
 {
-    WrapperBox * box = WrapperFactory::create( WrapperFactory::INTERSECT, 200, 100 );
-    scene->addItem(box->getGraphics());
+    this->scene->addItem(WrapperFactory::createNew(WrapperFactory::INTERSECT, 200, 100));
 }
 
 void MainWindow::on_AddInputBtn_clicked()
 {
     int y = qrand()%4 * 100;
-    WrapperBox * box = WrapperFactory::create( WrapperFactory::INPUT, 0, y );
-    scene->addItem(box->getGraphics());
+    this->scene->addItem(WrapperFactory::createNew(WrapperFactory::INPUT, 0, y));
 }
diff --git a/agui2/MainWindow.h b/agui2/MainWindow.h
index f7f83910e5..30c55aec01 100644
--- a/agui2/MainWindow.h
+++ b/agui2/MainWindow.h
@@ -9,7 +9,7 @@
 #include <Graphics/GraphicsScene.h>
 #include <ui_MainWindow.h>
 
-class WrapperBox;
+class GraphicsBox;
 
 class MainWindow : public QMainWindow
 {
@@ -18,6 +18,9 @@ class MainWindow : public QMainWindow
 public:
     explicit MainWindow();
 
+private:
+    void displayError(const QString& text) const;
+
 private slots:
     void on_AddInputBtn_clicked();
     void on_RunBtn_clicked();
@@ -50,7 +53,7 @@ private slots:
 private:
     std::unique_ptr<Ui::MainWindow> ui;
     std::unique_ptr<GraphicsScene> scene;
-    WrapperBox* m_output;
+    GraphicsBox* outputBox;
 };
 
 
diff --git a/agui2/Models/AlgorithmModelBox.cpp b/agui2/Models/AlgorithmModelBox.cpp
new file mode 100644
index 0000000000..3cf697fc25
--- /dev/null
+++ b/agui2/Models/AlgorithmModelBox.cpp
@@ -0,0 +1,71 @@
+#include <Models/AlgorithmModelBox.h>
+
+#include <string>
+
+#include <registry/AlgorithmRegistry.hpp>
+#include <common/AlgorithmHelper.h>
+#include <exception/CommonException.h>
+
+#include <AlibExceptionHandler.h>
+
+namespace {
+    uint8_t determineNumberOfInputs(const std::string& name) {
+        ext::set<ext::tuple<abstraction::AlgorithmCategories::AlgorithmCategory,
+                            ext::pair<std::string,
+                                     ext::set<abstraction::ParamQualifiers::ParamQualifier>>,
+                            ext::vector<ext::tuple<std::string,
+                                                   ext::set<abstraction::ParamQualifiers::ParamQualifier>,
+                                                   std::string>>>> data = abstraction::AlgorithmRegistry::listOverloads(name, {});
+        for (const auto& tup: data) {
+            const auto& out = std::get<1>(tup).first;
+            if (out.find("automaton::DFA") == 0 || out.find("automaton::NFA") == 0)
+            {
+                bool ok = true;
+                for (const auto& tup2: std::get<2>(tup))
+                {
+                    const auto& in = std::get<0>(tup2);
+                    if (in.find("automaton::DFA") != 0 && in.find("automaton::NFA") != 0)
+                    {
+                        ok = false;
+                        break;
+                    }
+                }
+                if (!ok)
+                    continue;
+                return static_cast<uint8_t>(std::get<2>(tup).size());
+            }
+        }
+        Q_ASSERT(false && "Failed to determine proper overload.");
+        return 0;
+    }
+}
+
+AlgorithmModelBox::AlgorithmModelBox(std::string name)
+    : ModelBox(ModelType::Algorithm, determineNumberOfInputs(name))
+    , name(std::move(name)) {
+    Q_ASSERT(!this->name.empty());
+}
+
+std::shared_ptr<abstraction::OperationAbstraction> AlgorithmModelBox::run() {
+    ext::vector<std::shared_ptr<abstraction::OperationAbstraction>> params;
+    for (const auto& p: this->inputs)
+    {
+        if (!p.second)
+            return nullptr;
+        params.push_back(p.second->run());
+        if (!params.back())
+            return nullptr;
+    }
+
+    std::vector<bool> moves(params.size(), true);
+    try {
+        return abstraction::AlgorithmHelper::eval(this->name,
+                                                  {},
+                                                  params,
+                                                  moves,
+                                                  abstraction::AlgorithmCategories::AlgorithmCategory::DEFAULT);
+    } catch (const exception::CommonException& e) {
+        AlibExceptionHandler::getInstance().setMessage(QString::fromStdString(e.getCause()));
+        return nullptr;
+    }
+}
diff --git a/agui2/Models/AlgorithmModelBox.h b/agui2/Models/AlgorithmModelBox.h
new file mode 100644
index 0000000000..95987d92ea
--- /dev/null
+++ b/agui2/Models/AlgorithmModelBox.h
@@ -0,0 +1,14 @@
+#pragma once
+#include <Models/ModelBox.h>
+
+class AlgorithmModelBox : public ModelBox {
+public:
+    explicit AlgorithmModelBox(std::string name);
+
+    std::shared_ptr<abstraction::OperationAbstraction> run() override;
+
+private:
+    std::string name;
+};
+
+
diff --git a/agui2/Models/DoubleModelBox.cpp b/agui2/Models/DoubleModelBox.cpp
deleted file mode 100644
index 13709540d5..0000000000
--- a/agui2/Models/DoubleModelBox.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-#include <Models/DoubleModelBox.h>
-
-#include <common/AlgorithmHelper.h>
-
-#include <AlibExceptionHandler.h>
-
-DoubleModelBox::DoubleModelBox(std::string func)
-{
-    m_func = func;
-}
-
-bool DoubleModelBox::addInput(ModelBox *origin)
-{
-    if( m_InConnectionOne && m_InConnectionTwo )
-        return false;
-    if( m_InConnectionOne == nullptr )
-    {
-        m_InConnectionOne = origin;
-        return true;
-    }
-    else
-    {
-        m_InConnectionTwo = origin;
-        return true;
-    }
-}
-
-bool DoubleModelBox::addOutput(ModelBox *target)
-{
-    if( m_OutConnection )
-        return false;
-    else
-        m_OutConnection = target;
-    return true;
-}
-
-void DoubleModelBox::removeInput(ModelBox *origin)
-{
-    if( m_InConnectionOne == origin )
-        m_InConnectionOne = nullptr;
-    if ( m_InConnectionTwo == origin )
-        m_InConnectionTwo = nullptr;
-}
-
-bool DoubleModelBox::isInputAvailable()
-{
-    return (m_InConnectionOne == nullptr || m_InConnectionTwo == nullptr );
-}
-
-std::shared_ptr < abstraction::OperationAbstraction > DoubleModelBox::run()
-{
-    std::shared_ptr < abstraction::OperationAbstraction > inOne = nullptr;
-    std::shared_ptr < abstraction::OperationAbstraction > inTwo = nullptr;
-    std::shared_ptr < abstraction::OperationAbstraction > res = nullptr;
-    if( m_InConnectionOne && m_InConnectionTwo )
-    {
-         inOne = m_InConnectionOne->run();
-         inTwo = m_InConnectionTwo->run();
-    }
-    if( inOne && inTwo )
-    {
-        try
-        {
-            ext::vector < std::shared_ptr < abstraction::OperationAbstraction > > params;
-            params.push_back ( inOne );
-            params.push_back ( inTwo );
-
-            std::vector < bool > moves;
-            moves.push_back ( true );
-            moves.push_back ( true );
-
-            res = abstraction::AlgorithmHelper::eval( m_func, {}, params, moves, abstraction::AlgorithmCategories::AlgorithmCategory::DEFAULT );
-        }
-        catch (const exception::CommonException& e)
-        {
-            QString mes = QString::fromStdString( e.getCause() );
-            AlibExceptionHandler::getInstance().setMessage( mes );
-            res = nullptr;
-        }
-    }
-    return res;
-}
diff --git a/agui2/Models/DoubleModelBox.h b/agui2/Models/DoubleModelBox.h
deleted file mode 100644
index fc3990aa2f..0000000000
--- a/agui2/Models/DoubleModelBox.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#pragma once
-#include <Models/ModelBox.h>
-
-class DoubleModelBox : public ModelBox
-{
-public:
-    DoubleModelBox(std::string func);
-    // Inherited
-    virtual bool addInput( ModelBox * origin );
-    virtual bool addOutput( ModelBox * target );
-    virtual void removeInput( ModelBox * origin );
-    virtual void removeOutput() { m_OutConnection = nullptr; }
-    virtual bool isInputAvailable();
-    virtual bool isOutputAvailable() { return m_OutConnection == nullptr; }
-    virtual bool acceptInput() { return true; }
-    virtual bool isOutputSet() { return m_OutConnection != nullptr; }
-    virtual std::shared_ptr < abstraction::OperationAbstraction > run();
-private:
-    ModelBox * m_OutConnection = nullptr;
-    ModelBox * m_InConnectionOne = nullptr;
-    ModelBox * m_InConnectionTwo = nullptr;
-    std::string m_func;
-};
-
-
diff --git a/agui2/Models/InputModelBox.cpp b/agui2/Models/InputModelBox.cpp
index 735a353189..52c16b8d52 100644
--- a/agui2/Models/InputModelBox.cpp
+++ b/agui2/Models/InputModelBox.cpp
@@ -1,36 +1,9 @@
 #include <Models/InputModelBox.h>
 
-void InputModelBox::setAutomaton(std::shared_ptr < abstraction::OperationAbstraction > automaton)
-{
-    m_automaton = automaton;
-}
-
-const std::shared_ptr < abstraction::OperationAbstraction > InputModelBox::getAutomaton()
-{
-    return m_automaton;
-}
-
-bool InputModelBox::addOutput(ModelBox *target)
-{
-    if( m_OutConnection )
-        return false;
-    else
-        m_OutConnection = target;
-    return true;
-}
+InputModelBox::InputModelBox()
+    : ModelBox(ModelType::Input, 0)
+{}
 
-std::shared_ptr < abstraction::OperationAbstraction > InputModelBox::run()
-{
-    return m_automaton;
+std::shared_ptr<abstraction::OperationAbstraction> InputModelBox::run() {
+    return this->automaton;
 }
-
-void InputModelBox::setSettings(const InputSettings &settings)
-{
-    m_settings = settings;
-}
-
-InputSettings InputModelBox::getSettings()
-{
-    return m_settings;
-}
-
diff --git a/agui2/Models/InputModelBox.h b/agui2/Models/InputModelBox.h
index c215b5fb3f..ab3e650f63 100644
--- a/agui2/Models/InputModelBox.h
+++ b/agui2/Models/InputModelBox.h
@@ -1,32 +1,22 @@
 #pragma once
 #include <Models/ModelBox.h>
-#include <Models/InputSettings.h>
+#include <utility>
 
-class InputModelBox : public ModelBox
-{
+class InputModelBox : public ModelBox {
 public:
-    InputModelBox() = default;
-    void setAutomaton( std::shared_ptr < abstraction::OperationAbstraction > automaton );
-    const std::shared_ptr < abstraction::OperationAbstraction > getAutomaton();
+    explicit InputModelBox();
+
+    std::shared_ptr<abstraction::OperationAbstraction> run() override;
+
+    const InputSettings& getSettings() const { return this->settings; }
+    void setSettings(const InputSettings& settings) { this->settings = settings; }
+
+    const std::shared_ptr<abstraction::OperationAbstraction> getAutomaton() const { return this->automaton; }
+    void setAutomaton(std::shared_ptr<abstraction::OperationAbstraction> automaton) { this->automaton = std::move(automaton); }
 
-    // Inherited
-    virtual ~InputModelBox() {}
-    virtual bool addInput( ModelBox * origin __attribute__((unused)) ) { return false; }
-    virtual bool addOutput( ModelBox * target );
-    virtual void removeInput( ModelBox * origin __attribute__((unused)) ){}
-    virtual void removeOutput() { m_OutConnection = nullptr; }
-    virtual bool isInputAvailable() { return false; }
-    virtual bool isOutputAvailable() { return m_OutConnection == nullptr; }
-    virtual bool acceptInput() { return false; }
-    virtual bool isOutputSet() { return m_OutConnection != nullptr; }
-    virtual std::shared_ptr < abstraction::OperationAbstraction > run();
-    bool isInputEmpty() { return m_automaton == nullptr; }
-    void setSettings( const InputSettings & settings );
-    InputSettings getSettings();
 private:
-    ModelBox * m_OutConnection = nullptr;
-    std::shared_ptr < abstraction::OperationAbstraction > m_automaton = nullptr;
-    InputSettings m_settings;
+    InputSettings settings;
+    std::shared_ptr<abstraction::OperationAbstraction> automaton;
 };
 
 
diff --git a/agui2/Models/ModelBox.cpp b/agui2/Models/ModelBox.cpp
index c62c7205f4..164e00cdd5 100644
--- a/agui2/Models/ModelBox.cpp
+++ b/agui2/Models/ModelBox.cpp
@@ -1,6 +1,32 @@
 #include <Models/ModelBox.h>
 
-void ModelBox::setWrapper(WrapperBox* wrapper)
+#include <utility>
+
+#include <qplatformdefs.h>
+#include <common/AlgorithmHelper.h>
+#include <exception/CommonException.h>
+#include <QtCore/QString>
+#include <AlibExceptionHandler.h>
+
+ModelBox::ModelBox(ModelType type, uint8_t maxInputCount)
+    : type(type)
+    , maxInputCount(maxInputCount)
 {
-    m_wrapper = wrapper;
+    // Input box cannot have inputs, other boxes must have inputs
+    Q_ASSERT((this->type == ModelType::Input) == (this->maxInputCount == 0));
+}
+
+void ModelBox::setInput(uint8_t slot, ModelBox* model) {
+    Q_ASSERT(slot < this->maxInputCount);
+    this->inputs[slot] = model;
 }
+
+void ModelBox::addOutput(ModelBox* model, uint8_t slot) {
+    Q_ASSERT(this->canHaveOutput());
+    this->outputs.emplace(model, slot);
+}
+
+void ModelBox::removeOutput(ModelBox* model, uint8_t slot) {
+    Q_ASSERT(this->canHaveOutput());
+    this->outputs.erase({model, slot});
+}
\ No newline at end of file
diff --git a/agui2/Models/ModelBox.h b/agui2/Models/ModelBox.h
index a3c3146948..cc26ce4973 100644
--- a/agui2/Models/ModelBox.h
+++ b/agui2/Models/ModelBox.h
@@ -1,32 +1,49 @@
 #pragma once
-#include <memory>
-
-#include <QString>
-#include <QList>
+#include <map>
+#include <set>
+#include <string>
+#include <utility>
 
 #include <abstraction/OperationAbstraction.hpp>
-#include <exception/CommonException.h>
 
-class WrapperBox;
+#include <Models/OutputSettings.h>
+#include <Models/InputSettings.h>
+
+class GraphicsBox;
+
+enum class ModelType {
+    Input,
+    Output,
+    Algorithm
+};
+
+class ModelBox {
+protected:
+    explicit ModelBox(ModelType type, uint8_t maxInputCount);
 
-class ModelBox
-{
 public:
     virtual ~ModelBox() = default;
-    virtual bool addInput( ModelBox * origin ) = 0;
-    virtual bool addOutput( ModelBox * target ) = 0;
-    virtual void removeInput( ModelBox * origin ) = 0;
-    virtual void removeOutput() = 0;
-    virtual bool isInputAvailable() = 0;
-    virtual bool isOutputAvailable() = 0;
-    virtual bool acceptInput() = 0;
-    virtual bool isOutputSet() = 0;
-    virtual std::shared_ptr < abstraction::OperationAbstraction > run() = 0;
-    friend class WrapperBox;
+
+    void setGraphicsBox(GraphicsBox* graphicsBox) { this->graphicsBox = graphicsBox; }
+    ModelType getType() const { return this->type; }
+
+    void setInput(uint8_t slot, ModelBox* model);
+    void addOutput(ModelBox* model, uint8_t slot);
+    void removeOutput(ModelBox* model, uint8_t slot);
+
+    uint8_t getMaxInputCount() const { return this->maxInputCount; }
+    virtual bool canHaveOutput() const { return true; }
+
+    virtual std::shared_ptr<abstraction::OperationAbstraction> run() = 0;
+
 protected:
-    WrapperBox* m_wrapper = nullptr;
-private:
-    void setWrapper( WrapperBox* wrapper );
+    ModelType type;
+
+    uint8_t maxInputCount = 0;
+    std::map<uint8_t, ModelBox*> inputs;
+    std::set<std::pair<ModelBox*, uint8_t>> outputs;
+
+    GraphicsBox* graphicsBox = nullptr;
 };
 
 
diff --git a/agui2/Models/OutputModelBox.cpp b/agui2/Models/OutputModelBox.cpp
index bf0988abaf..80da8e0b2e 100644
--- a/agui2/Models/OutputModelBox.cpp
+++ b/agui2/Models/OutputModelBox.cpp
@@ -1,190 +1,11 @@
 #include <Models/OutputModelBox.h>
 
-#include <QGraphicsScene>
-#include <QGraphicsView>
-#include <QMessageBox>
-#include <QTextStream>
-
-#include <AlibExceptionHandler.h>
-#include <Converter.h>
-#include <Graphics/Dialogs/ResultDialog.h>
-#include <WrapperBox.h>
-
-class ModelBox;
-
-std::shared_ptr < abstraction::OperationAbstraction > OutputModelBox::run()
-{
-    std::shared_ptr < abstraction::OperationAbstraction > res = nullptr;
-    AlibExceptionHandler::getInstance().reset();
-
-    if( m_InConnection )
-         res = m_InConnection->run();
-    if( res )
-    {
-        switch (m_Settings.m_destination) {
-        case OutputSettings::RESULT_DIALOG:
-            displayResult( res );
-            break;
-        case OutputSettings::FILE:
-            saveResultToFile( res );
-            break;
-        default:
-            break;
-        }
-    }
-    else
-    {
-        if( AlibExceptionHandler::getInstance().isActive() )
-            displayError( AlibExceptionHandler::getInstance().getMessage() );
-        else
-            displayError( "Missing an input" );
-    }
-    return nullptr;
-}
-
-void OutputModelBox::setSettings(const OutputSettings & settings)
-{
-    m_Settings = settings;
-}
-
-OutputSettings OutputModelBox::getSettings()
-{
-    return m_Settings;
-}
-
-void OutputModelBox::displayError(const QString &text)
-{
-    QMessageBox::warning( m_wrapper->getGraphics()->scene()->views().first(), "Output fail", text, QMessageBox::Ok );
-}
-
-void OutputModelBox::displayResult(std::shared_ptr < abstraction::OperationAbstraction > automaton)
-{
-    switch (m_Settings.m_format)
-    {
-        case OutputSettings::XML:
-            displayXML( automaton );
-            break;
-        case OutputSettings::TXT:
-            displayTXT( automaton );
-            break;
-        case OutputSettings::PNG:
-            displayPNG( automaton );
-            break;
-        case OutputSettings::SVG:
-            displaySVG( automaton );
-            break;
-        default:
-            break;
-    }
-}
-
-void OutputModelBox::displayXML( std::shared_ptr < abstraction::OperationAbstraction > automaton )
-{
-    ResultDialog * resultDlg = new ResultDialog();
-    resultDlg->setTextContent( Converter::automatonToXML( automaton) );
-    resultDlg->exec();
-}
-
-void OutputModelBox::displayTXT(std::shared_ptr < abstraction::OperationAbstraction > automaton)
-{
-    QString text( Converter::automatonToTXT( automaton) );
-    ResultDialog * resultDlg = new ResultDialog();
-    resultDlg->setTextContent( text );
-    resultDlg->exec();
-}
-
-void OutputModelBox::displayPNG(std::shared_ptr < abstraction::OperationAbstraction > automaton)
-{
-    displayImage( automaton, GraphvizIntegrator::PNG );
-}
-
-void OutputModelBox::displaySVG(std::shared_ptr < abstraction::OperationAbstraction > automaton)
-{
-    displayImage( automaton, GraphvizIntegrator::SVG );
-}
-
-void OutputModelBox::displayImage(std::shared_ptr < abstraction::OperationAbstraction > automaton, GraphvizIntegrator::PictureFormat format)
-{
-    ResultDialog * resultDlg = new ResultDialog();
-    QImage img;
-    try
-    {
-        switch (format)
-        {
-        case GraphvizIntegrator::PNG:
-            img = Converter::automatonToPNG(automaton);
-            break;
-        case GraphvizIntegrator::SVG:
-            img = Converter::automatonToSVG(automaton);
-            break;
-        default:
-            break;
-        }
-    } catch (exception::CommonException e ) {
-        displayError( QString::fromStdString(e.getCause()) );
-    }
-
-    if( img.isNull() )
-        resultDlg->setTextContent( "<span style=\" font-size:16pt; font-weight:600;\">Graphviz failed</span><b/>");
-    else
-        resultDlg->setImageContent( img );
-    resultDlg->exec();
-}
-
-void OutputModelBox::saveResultToFile(std::shared_ptr < abstraction::OperationAbstraction > automaton)
-{
-    switch (m_Settings.m_format)
-    {
-        case OutputSettings::XML:
-            saveXMLToFile( automaton );
-            break;
-        case OutputSettings::TXT:
-            saveTXTToFile( automaton );
-            break;
-        case OutputSettings::PNG:
-            savePNGToFile( automaton );
-            break;
-        case OutputSettings::SVG:
-            saveSVGToFile( automaton );
-            break;
-        default:
-            break;
-    }
-}
-
-void OutputModelBox::saveXMLToFile(std::shared_ptr < abstraction::OperationAbstraction > automaton)
-{
-    QFile file(m_Settings.m_filename);
-    file.open(QFile::ReadWrite | QFile::Text);
-    QTextStream s1(&file);
-    s1 << Converter::automatonToXML(automaton) << endl;
-    file.close();
-}
-
-void OutputModelBox::saveTXTToFile(std::shared_ptr < abstraction::OperationAbstraction > automaton)
-{
-    QFile file(m_Settings.m_filename);
-    file.open(QFile::ReadWrite | QFile::Text);
-    QTextStream s1(&file);
-    s1 << Converter::automatonToTXT(automaton);
-    file.close();
-}
-
-void OutputModelBox::savePNGToFile(std::shared_ptr < abstraction::OperationAbstraction > automaton)
-{
-    GraphvizIntegrator::createImageFile(Converter::automatonToDOT(automaton), m_Settings.m_filename, GraphvizIntegrator::PNG);
-}
-
-void OutputModelBox::saveSVGToFile(std::shared_ptr < abstraction::OperationAbstraction > automaton)
-{
-    GraphvizIntegrator::createImageFile(Converter::automatonToDOT(automaton), m_Settings.m_filename, GraphvizIntegrator::SVG);
-}
-
-bool OutputModelBox::addInput(ModelBox *origin)
-{
-    if( m_InConnection )
-        return false;
-    else
-        m_InConnection = origin;
-    return true;
+OutputModelBox::OutputModelBox()
+    : ModelBox(ModelType::Output, 1)
+{}
+
+std::shared_ptr<abstraction::OperationAbstraction> OutputModelBox::run() {
+    if (!this->inputs[0])
+        return nullptr;
+    return inputs[0]->run();
 }
diff --git a/agui2/Models/OutputModelBox.h b/agui2/Models/OutputModelBox.h
index 2f765afb57..656a063e96 100644
--- a/agui2/Models/OutputModelBox.h
+++ b/agui2/Models/OutputModelBox.h
@@ -1,40 +1,16 @@
 #pragma once
-#include <GraphvizIntegrator.h>
 #include <Models/ModelBox.h>
-#include <Models/OutputSettings.h>
 
-class OutputModelBox : public ModelBox
-{
+class OutputModelBox : public ModelBox {
 public:
-    OutputModelBox() = default;
-    // Inherited
-    virtual bool addInput( ModelBox * origin );
-    virtual bool addOutput( ModelBox * target __attribute__((unused)) ) { return false; }
-    virtual void removeInput( ModelBox * origin __attribute__((unused)) ) { m_InConnection = nullptr; }
-    virtual void removeOutput() {}
-    virtual bool isInputAvailable() { return m_InConnection == nullptr; }
-    virtual bool isOutputAvailable() { return false; }
-    virtual bool acceptInput() { return true; }
-    virtual bool isOutputSet() { return false; }
-    virtual std::shared_ptr < abstraction::OperationAbstraction > run();
-    void setSettings(const OutputSettings &settings );
-    OutputSettings getSettings();
-private:
-    void displayError(const QString & text);
-    void displayResult(std::shared_ptr < abstraction::OperationAbstraction > automaton);
-    void displayXML(std::shared_ptr < abstraction::OperationAbstraction > automaton);
-    void displayTXT(std::shared_ptr < abstraction::OperationAbstraction > automaton);
-    void displayPNG(std::shared_ptr < abstraction::OperationAbstraction > automaton);
-    void displaySVG(std::shared_ptr < abstraction::OperationAbstraction > automaton);
-    void displayImage(std::shared_ptr < abstraction::OperationAbstraction > automaton, GraphvizIntegrator::PictureFormat format);
-    void saveResultToFile(std::shared_ptr < abstraction::OperationAbstraction > automaton);
-    void saveXMLToFile(std::shared_ptr < abstraction::OperationAbstraction > automaton);
-    void saveTXTToFile(std::shared_ptr < abstraction::OperationAbstraction > automaton);
-    void savePNGToFile(std::shared_ptr < abstraction::OperationAbstraction > automaton);
-    void saveSVGToFile(std::shared_ptr < abstraction::OperationAbstraction > automaton);
+    explicit OutputModelBox();
+
+    bool canHaveOutput() const override { return false; }
 
-    ModelBox * m_InConnection = nullptr;
-    OutputSettings m_Settings;
+    std::shared_ptr<abstraction::OperationAbstraction> run() override;
+
+private:
+    OutputSettings settings;
 };
 
 
diff --git a/agui2/Models/SingleModelBox.cpp b/agui2/Models/SingleModelBox.cpp
deleted file mode 100644
index ff8d71073c..0000000000
--- a/agui2/Models/SingleModelBox.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-#include <Models/SingleModelBox.h>
-
-#include <common/AlgorithmHelper.h>
-
-#include <AlibExceptionHandler.h>
-
-SingleModelBox::SingleModelBox( std::string func )
-{
-    m_func = func;
-}
-
-bool SingleModelBox::addInput(ModelBox *origin)
-{
-    if( m_InConnection )
-        return false;
-    else
-        m_InConnection = origin;
-    return true;
-}
-
-bool SingleModelBox::addOutput(ModelBox *target)
-{
-    if( m_OutConnection )
-        return false;
-    else
-        m_OutConnection = target;
-    return true;
-}
-
-std::shared_ptr < abstraction::OperationAbstraction > SingleModelBox::run()
-{
-    std::shared_ptr < abstraction::OperationAbstraction > res = nullptr;
-    if( m_InConnection )
-         res = m_InConnection->run();
-    if( res )
-    {
-        try{
-             ext::vector < std::shared_ptr < abstraction::OperationAbstraction > > params;
-             params.push_back ( res );
-
-             std::vector < bool > moves;
-             moves.push_back ( true );
-
-            res = abstraction::AlgorithmHelper::eval ( m_func, {}, params, moves, abstraction::AlgorithmCategories::AlgorithmCategory::DEFAULT );
-        } catch (exception::CommonException e) {
-            QString mes = QString::fromStdString( e.getCause() );
-            AlibExceptionHandler::getInstance().setMessage( mes );
-            res = nullptr;
-        }
-    }
-    return res;
-}
diff --git a/agui2/Models/SingleModelBox.h b/agui2/Models/SingleModelBox.h
deleted file mode 100644
index f4e3728d48..0000000000
--- a/agui2/Models/SingleModelBox.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#pragma once
-#include <Models/ModelBox.h>
-
-class SingleModelBox : public ModelBox
-{
-public:
-    SingleModelBox(std::string);
-    // Inherited
-    virtual ~SingleModelBox() {}
-    virtual bool addInput( ModelBox * origin );
-    virtual bool addOutput( ModelBox * target );
-    virtual void removeInput( ModelBox * origin __attribute__((unused)) ) { m_InConnection = nullptr; }
-    virtual void removeOutput() { m_OutConnection = nullptr; }
-    virtual bool isInputAvailable() { return m_InConnection == nullptr; }
-    virtual bool isOutputAvailable() { return m_OutConnection == nullptr; }
-    virtual bool acceptInput() { return true; }
-    virtual bool isOutputSet() { return m_OutConnection != nullptr; }
-    virtual std::shared_ptr < abstraction::OperationAbstraction > run();
-private:
-    ModelBox * m_InConnection = nullptr;
-    ModelBox * m_OutConnection = nullptr;
-    std::string m_func;
-};
-
-
diff --git a/agui2/WrapperBox.cpp b/agui2/WrapperBox.cpp
deleted file mode 100644
index fe34203052..0000000000
--- a/agui2/WrapperBox.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-#include <WrapperBox.h>
-
-WrapperBox::WrapperBox( ModelBox * model, GraphicsBox * graphics ) :
-    m_model( model ), m_graphics( graphics )
-{
-    model->setWrapper( this );
-    graphics->setWrapper( this );
-}
-
-WrapperBox::~WrapperBox()
-{
-    delete m_graphics;
-    delete m_model;
-}
-
-bool WrapperBox::addInput(WrapperBox *origin, GraphicsConnection *connection)
-{
-    if( !m_model->addInput( origin->getModel() ) )
-        return false;
-    m_graphics->addInput( connection );
-    return true;
-}
-
-bool WrapperBox::addOutput(WrapperBox *target, GraphicsConnection *connection)
-{
-    if( !m_model->addOutput( target->getModel() ))
-        return false;
-    m_graphics->addOutput( connection );
-    return true;
-}
-
-void WrapperBox::removeInput(WrapperBox *origin, GraphicsConnection *connection)
-{
-    m_model->removeInput( origin->getModel() );
-    m_graphics->removeInput( connection );
-}
-
-void WrapperBox::removeOutput()
-{
-    m_model->removeOutput();
-    m_graphics->removeOutput();
-}
-
-void WrapperBox::disconnectOutput()
-{
-    if( m_model->isOutputSet() )
-        m_graphics->m_OutConnection->on_Disconnect();
-}
-
-void WrapperBox::getAvailableInput()
-{
-    if( !m_model->isInputAvailable() )
-        m_graphics->inConnections[0]->on_Disconnect();
-}
-
-ModelBox *WrapperBox::getModel()
-{
-    return m_model;
-}
-
-GraphicsBox *WrapperBox::getGraphics()
-{
-    return m_graphics;
-}
-
-
-
-
-
-
-
-
diff --git a/agui2/WrapperBox.h b/agui2/WrapperBox.h
deleted file mode 100644
index f57caf6f55..0000000000
--- a/agui2/WrapperBox.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#pragma once
-#include <Models/ModelBox.h>
-#include <Graphics/GraphicsConnection.h>
-#include <Graphics/GraphicsBox.h>
-
-class ModelBox;
-class GraphicsBox;
-class GraphicsConnection;
-
-class WrapperBox
-{
-public:
-    WrapperBox(ModelBox *model, GraphicsBox *graphics);
-    ~WrapperBox();
-    bool addInput( WrapperBox * origin, GraphicsConnection * connection );
-    bool addOutput( WrapperBox * target, GraphicsConnection * connection );
-    void removeInput( WrapperBox * origin, GraphicsConnection * connection );
-    void removeOutput();
-    void disconnectOutput();
-    void getAvailableInput();
-    ModelBox *getModel();
-    GraphicsBox *getGraphics();
-private:
-    ModelBox *m_model;
-    GraphicsBox *m_graphics;
-};
-
diff --git a/agui2/WrapperFactory.cpp b/agui2/WrapperFactory.cpp
index 6c2d6e8fdb..20d03e1e2c 100644
--- a/agui2/WrapperFactory.cpp
+++ b/agui2/WrapperFactory.cpp
@@ -4,70 +4,73 @@
 #include <QString>
 
 #include <Graphics/InputGraphicsBox.h>
-#include <Graphics/OutputGraphicsBox.h>
-#include <Models/DoubleModelBox.h>
 #include <Models/InputModelBox.h>
 #include <Models/OutputModelBox.h>
-#include <Models/SingleModelBox.h>
 
-WrapperBox *WrapperFactory::create(WrapperFactory::Algorithms algorithm, qreal x = 0, qreal y = 0)
+#include <Models/AlgorithmModelBox.h>
+#include <Models/InputModelBox.h>
+#include <Models/OutputModelBox.h>
+#include <Graphics/GraphicsBox.h>
+#include <Graphics/InputGraphicsBox.h>
+
+GraphicsBox* WrapperFactory::createNew(WrapperFactory::Algorithms algorithm, qreal x = 0, qreal y = 0)
 {
-    QString str( QChar(0xb5, 0x03) );
+    QString eps (QChar(0xb5, 0x03));
 
     switch( algorithm )
     {
-    // Special
-    case INPUT:
-        return new WrapperBox( new InputModelBox(), new InputGraphicsBox( x, y ) );
-    case OUTPUT:
-        return new WrapperBox( new OutputModelBox(), new OutputGraphicsBox( x, y ) );
+        // Special
+        case INPUT:
+            return new InputGraphicsBox(std::make_unique<InputModelBox>(), "INPUT", {x, y});
+        case OUTPUT:
+            return new GraphicsBox(std::make_unique<OutputModelBox>(), "OUTPUT", {x, y});
 
-    // Single simplify
-    case DETERMINIZE:
-        return new WrapperBox( new SingleModelBox( "automaton::determinize::Determinize" ), new GraphicsBox( "Determinize", x, y ) );
-    case TOTAL:
-        return new WrapperBox( new SingleModelBox( "automaton::simplify::Total" ), new GraphicsBox( "Total", x, y ) );
-    case MINIMIZE:
-        return new WrapperBox( new SingleModelBox( "automaton::simplify::Minimize" ), new GraphicsBox( "Minimize", x, y ) );
-    case NORMALIZE:
-        return new WrapperBox( new SingleModelBox( "automaton::simplify::Normalize" ), new GraphicsBox( "Normalize", x, y ) );
-    case SINGLE_INITIAL:
-        return new WrapperBox( new SingleModelBox( "automaton::simplify::SingleInitialState" ), new GraphicsBox( "Single Initial", x, y ) );
-    case EPSILON_REMOVE_IN:
-        return new WrapperBox( new SingleModelBox( "automaton::simplify::EpsilonRemoverIncoming" ), new GraphicsBox( str.append( "-Remove In" ), x, y ) );
-    case EPSILON_REMOVE_OUT:
-        return new WrapperBox( new SingleModelBox( "automaton::simplify::EpsilonRemoverOutgoing" ), new GraphicsBox( str.append( "-Remove Out" ), x, y ) );
-    case RENAME:
-        return new WrapperBox( new SingleModelBox( "automaton::simplify::Rename" ), new GraphicsBox( "Rename", x, y ) );
-    case TRIM:
-        return new WrapperBox( new SingleModelBox( "automaton::simplify::Trim" ), new GraphicsBox( "Trim", x, y ) );
-    case REMOVE_USELES:
-        return new WrapperBox( new SingleModelBox( "automaton::simplify::UselessStatesRemover" ), new GraphicsBox( "Remove Useless", x, y ) );
-    case REMOVE_UNREACHABLE:
-        return new WrapperBox( new SingleModelBox( "automaton::simplify::UnreachableStatesRemover" ), new GraphicsBox( "Remove Unreachable", x, y ) );
+            // Single simplify
+        case DETERMINIZE:
+            return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::determinize::Determinize"), "Determinize", {x, y});
+        case TOTAL:
+            return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::simplify::Total"), "Total", {x, y});
+        case MINIMIZE:
+            return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::simplify::Minimize"), "Minimize", {x, y});
+        case NORMALIZE:
+            return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::simplify::Normalize"), "Normalize", {x, y});
+        case SINGLE_INITIAL:
+            return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::simplify::SingleInitialState"), "Single Initial", {x, y});
+        case EPSILON_REMOVE_IN:
+            return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::simplify::EpsilonRemoverIncoming"), eps.append("-Remove In"), {x, y});
+        case EPSILON_REMOVE_OUT:
+            return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::simplify::EpsilonRemoverOutgoing"), eps.append("-Remove Out"), {x, y});
+        case RENAME:
+            return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::simplify::Rename"), "Rename", {x, y});
+        case TRIM:
+            return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::simplify::Trim"), "Trim", {x, y});
+        case REMOVE_USELES:
+            return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::simplify::UselessStatesRemover"), "Remove Useless", {x, y});
+        case REMOVE_UNREACHABLE:
+            return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::simplify::UnreachableStatesRemover"), "Remove Unreachable", {x, y});
 
-    // Single transform
-    case COMPACT:
-        return new WrapperBox( new SingleModelBox( "automaton::transform::Compaction" ), new GraphicsBox( "Compact", x, y ) );
-    case REVERSE:
-        return new WrapperBox( new SingleModelBox( "automaton::transform::Reverse" ), new GraphicsBox( "Reverse", x, y ) );
-    case ITERATE:
-        return new WrapperBox( new SingleModelBox( "automaton::transform::AutomatonIteration" ), new GraphicsBox( "Iterate", x, y ) );
-    case ITERATE_EPSILON:
-        return new WrapperBox( new SingleModelBox( "automaton::transform::AutomatonIterationEpsilonTransition" ), new GraphicsBox( str.append( "-Iterate" ), x, y ) );
+            // Single transform
+        case COMPACT:
+            return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::transform::Compaction"), "Compact", {x, y});
+        case REVERSE:
+            return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::transform::Reverse"), "Reverse", {x, y});
+        case ITERATE:
+            return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::transform::AutomatonIteration"), "Iterate", {x, y});
+        case ITERATE_EPSILON:
+            return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::transform::AutomatonIterationEpsilonTransition"), eps.append("-Iterate"), {x, y});
 
-    //Double
-    case CONCATENATE:
-        return new WrapperBox( new DoubleModelBox( "automaton::transform::AutomataConcatenation" ), new GraphicsBox( "Concatenate", x, y, 2 ) );
-    case CONCATENATE_EPSILON:
-        return new WrapperBox( new DoubleModelBox( "automaton::transform::AutomataConcatenationEpsilonTransition" ), new GraphicsBox( str.append( "-Concatenate" ), x, y, 2 ) );
-    case UNION:
-        return new WrapperBox( new DoubleModelBox( "automaton::transform::AutomataUnionCartesianProduct" ), new GraphicsBox( "Union", x, y, 2 ) );
-    case UNION_EPSILON:
-        return new WrapperBox( new DoubleModelBox( "automaton::transform::AutomataUnionEpsilonTransition" ), new GraphicsBox( str.append( "-Union" ), x, y, 2 ) );
-    case INTERSECT:
-        return new WrapperBox( new DoubleModelBox( "automaton::transform::AutomataIntersectionCartesianProduct" ), new GraphicsBox( "Intersect", x, y, 2 ) );
-    default:
-        return nullptr;
+            //Double
+        case CONCATENATE:
+            return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::transform::AutomataConcatenation"), "Concatenate", {x, y});
+        case CONCATENATE_EPSILON:
+            return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::transform::AutomataConcatenationEpsilonTransition"), eps.append("-Concatenate"), {x, y});
+        case UNION:
+            return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::transform::AutomataUnionCartesianProduct"), "Union", {x, y});
+        case UNION_EPSILON:
+            return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::transform::AutomataUnionEpsilonTransition"), eps.append("-Union"), {x, y});
+        case INTERSECT:
+            return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::transform::AutomataIntersectionCartesianProduct"), "Intersect", {x, y});
+        default:
+            return nullptr;
     }
 }
diff --git a/agui2/WrapperFactory.h b/agui2/WrapperFactory.h
index d11e105934..202f215d94 100644
--- a/agui2/WrapperFactory.h
+++ b/agui2/WrapperFactory.h
@@ -1,7 +1,8 @@
 #pragma once
-#include <WrapperBox.h>
 
-class WrapperBox;
+#include <QRectF>
+
+class GraphicsBox;
 
 class WrapperFactory
 {
@@ -31,7 +32,7 @@ public:
         ITERATE,
         ITERATE_EPSILON
     };
-    static WrapperBox* create( WrapperFactory::Algorithms algorithm, qreal x, qreal y );
+    static GraphicsBox* createNew( WrapperFactory::Algorithms algorithm, qreal x, qreal y );
 };
 
 
-- 
GitLab