diff --git a/agui2/CMakeLists.txt b/agui2/CMakeLists.txt
index b17c68bdb5a0c735508e9042021cdc3d9141e201..f2376bf419801a035fea3b633f6dfeedc7117daf 100644
--- a/agui2/CMakeLists.txt
+++ b/agui2/CMakeLists.txt
@@ -38,6 +38,10 @@ add_executable(${PROJECT_NAME}
         Graphics/Dialogs/OutputDialog.h
         Graphics/Dialogs/ResultDialog.cpp
         Graphics/Dialogs/ResultDialog.h
+        Graphics/Connection.cpp
+        Graphics/Connection.h
+        Graphics/ConnectionBox.cpp
+        Graphics/ConnectionBox.h
         Graphics/DoubleGraphicsBox.cpp
         Graphics/DoubleGraphicsBox.h
         Graphics/GraphicsBox.cpp
@@ -76,7 +80,8 @@ add_executable(${PROJECT_NAME}
         WrapperBox.cpp
         WrapperBox.h
         WrapperFactory.cpp
-        WrapperFactory.h)
+        WrapperFactory.h
+        )
 
 target_link_libraries(
         ${PROJECT_NAME}
diff --git a/agui2/Graphics/Connection.cpp b/agui2/Graphics/Connection.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..81b049c06643249bb5060bd0b9780ad637d3729b
--- /dev/null
+++ b/agui2/Graphics/Connection.cpp
@@ -0,0 +1,47 @@
+#include <Graphics/Connection.h>
+
+#include <QGraphicsScene>
+#include <QPainter>
+
+#include <Graphics/ConnectionBox.h>
+#include <Utils.h>
+
+Connection::Connection(ConnectionBox* origin, ConnectionBox* target)
+    : originConnectionBox(origin)
+    , targetConnectionBox(target)
+{
+    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();
+}
+
+QRectF Connection::boundingRect() const {
+    return this->boundRect;
+}
+
+void Connection::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) {
+    painter->setPen(QPen(Qt::black,1));
+
+    QPointF originPoint = this->originConnectionBox->scenePos();
+    QPointF targetPoint = this->targetConnectionBox->scenePos();
+
+    QRectF rect = Utils::pointsToRect(originPoint, targetPoint);
+
+    qreal midWidth = rect.left() + rect.width() / 2.0;
+
+    painter->drawLine(originPoint,
+                      { midWidth, originPoint.y() });
+    painter->drawLine(QPointF { midWidth, originPoint.y() },
+                      { midWidth, targetPoint.y() });
+    painter->drawLine(QPointF { midWidth, targetPoint.y() },
+                      { targetPoint.x(), targetPoint.y() });
+    this->recalculateBoundingRect(originPoint, targetPoint);
+}
+
+void Connection::recalculateBoundingRect(const QPointF& a, const QPointF& b) {
+    this->prepareGeometryChange();
+    this->boundRect = Utils::pointsToRect(a, b);
+    this->boundRect.adjust(-1, -1, 1, 1);
+}
diff --git a/agui2/Graphics/Connection.h b/agui2/Graphics/Connection.h
new file mode 100644
index 0000000000000000000000000000000000000000..8628f4239482cc7c54a65ab89b82563ef0e34c62
--- /dev/null
+++ b/agui2/Graphics/Connection.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include <QtWidgets/QGraphicsItem>
+
+class ConnectionBox;
+
+class Connection : public QGraphicsItem {
+public:
+    Connection(ConnectionBox* origin, ConnectionBox* target);
+
+    QRectF boundingRect() const override;
+
+    void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) override;
+
+private:
+    void recalculateBoundingRect(const QPointF& topLeft, const QPointF& bottomRight);
+
+    QRectF boundRect;
+
+    ConnectionBox* originConnectionBox;
+    ConnectionBox* targetConnectionBox;
+};
+
+
diff --git a/agui2/Graphics/ConnectionBox.cpp b/agui2/Graphics/ConnectionBox.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5a880a5649577612f38a3dea22b53099d3541a0e
--- /dev/null
+++ b/agui2/Graphics/ConnectionBox.cpp
@@ -0,0 +1,84 @@
+#include <Graphics/ConnectionBox.h>
+
+#include <utility>
+
+#include <QtGui/QDrag>
+#include <QtWidgets/QApplication>
+
+#include <Graphics/GraphicsBox.h>
+#include <Graphics/GraphicsScene.h>
+
+const QColor ConnectionBox::defaultColor = Qt::white;
+
+ConnectionBox::ConnectionBox(GraphicsBox* parent, bool isInput)
+    : QGraphicsRectItem(-8, -8, 16, 16, parent)
+    , isInput(isInput)
+
+{
+    this->setBrush(ConnectionBox::defaultColor);
+    this->setAcceptedMouseButtons(Qt::LeftButton);
+}
+
+GraphicsBox* ConnectionBox::getParent() const {
+    return dynamic_cast<GraphicsBox*>(this->parentObject());
+}
+
+void ConnectionBox::mousePressEvent(QGraphicsSceneMouseEvent* event) {
+    this->setCursor(Qt::UpArrowCursor);
+
+    Q_ASSERT(!this->tempLine);
+    this->tempLine = this->scene()->addLine({this->scenePos(), this->scenePos()});
+    this->tempLine->setZValue(2);
+}
+
+void ConnectionBox::mouseMoveEvent(QGraphicsSceneMouseEvent* event) {
+    Q_ASSERT(this->tempLine);
+    QLineF line = this->tempLine->line();
+    line.setP2(event->scenePos());
+    this->tempLine->setLine(line);
+
+    static ConnectionBox* other = nullptr;
+    if (other)
+    {
+        other->setBrush(ConnectionBox::defaultColor);
+    }
+
+    other = nullptr;
+    for (auto* item: this->scene()->items(event->scenePos()))
+    {
+        if (auto* cb = dynamic_cast<ConnectionBox*>(item))
+        {
+            other = cb;
+            break;
+        }
+    }
+
+    if (other && other->isInput == !this->isInput)
+    {
+        other->setBrush(Qt::yellow);
+    }
+}
+
+void ConnectionBox::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) {
+    this->setCursor(Qt::ArrowCursor);
+
+    Q_ASSERT(this->tempLine);
+    delete this->tempLine;
+    this->tempLine = nullptr;
+
+    auto* other = dynamic_cast<ConnectionBox*>(this->scene()->itemAt(event->scenePos(), {}));
+    if (other && other->isInput == !this->isInput)
+    {
+        ConnectionBox::connect(this, other);
+    }
+}
+
+void ConnectionBox::connect(ConnectionBox* a, ConnectionBox* b) {
+    Q_ASSERT(a->isInput != b->isInput);
+    auto* origin = a;
+    auto* target = b;
+    if (!origin->isInput)
+        std::swap(origin, target);
+
+    origin->connection = target->connection = std::make_shared<Connection>(origin, target);
+}
diff --git a/agui2/Graphics/ConnectionBox.h b/agui2/Graphics/ConnectionBox.h
new file mode 100644
index 0000000000000000000000000000000000000000..7c5e3298c38d3842a20bb8a2c8dbd6373f25e987
--- /dev/null
+++ b/agui2/Graphics/ConnectionBox.h
@@ -0,0 +1,31 @@
+#pragma once
+#include <memory>
+
+#include <QtWidgets/QGraphicsRectItem>
+
+#include <Graphics/Connection.h>
+
+class GraphicsBox;
+
+class ConnectionBox : public QGraphicsRectItem {
+public:
+    ConnectionBox(GraphicsBox* parent, bool isInput);
+
+    static const QColor defaultColor;
+
+protected:
+    void mousePressEvent(QGraphicsSceneMouseEvent* event) override;
+    void mouseMoveEvent(QGraphicsSceneMouseEvent* event) override;
+    void mouseReleaseEvent(QGraphicsSceneMouseEvent* event) override;
+
+    static void connect(ConnectionBox* a, ConnectionBox* b);
+
+private:
+    GraphicsBox* getParent() const;
+
+    std::shared_ptr<Connection> connection;
+    QGraphicsLineItem* tempLine = nullptr;
+    bool isInput;
+};
+
+
diff --git a/agui2/Graphics/GraphicsBox.cpp b/agui2/Graphics/GraphicsBox.cpp
index ea7db09bb83874eb96adbbaf887e1c17b0068fdf..da59c5c9b4a5cb264d632116424beac4b40e7ecd 100644
--- a/agui2/Graphics/GraphicsBox.cpp
+++ b/agui2/Graphics/GraphicsBox.cpp
@@ -7,6 +7,7 @@
 #include <QGraphicsSceneContextMenuEvent>
 
 #include <ConnectionHelper.h>
+#include <Graphics/ConnectionBox.h>
 #include <Graphics/Dialogs/InputDialog.h>
 #include <Graphics/GraphicsConnection.h>
 #include <Graphics/GraphicsScene.h>
@@ -23,6 +24,22 @@ GraphicsBox::GraphicsBox(QString text, qreal x, qreal y, uint8_t inputs, uint8_t
     setZValue(1);
 
     setBoundingRectangle();
+
+    this->inputConnections.reserve(inputs);
+    for (uint8_t i = 0; i < inputs; ++i)
+    {
+        auto* box = new ConnectionBox(this, true);
+        box->setPos(this->m_boundRect.left(), this->m_boundRect.top() + ((i + 1) * this->m_boundRect.height()) / float(inputs + 1));
+        this->inputConnections.push_back(box);
+    }
+
+    this->outputConnections.reserve(outputs);
+    for (uint8_t i = 0; i < outputs; ++i)
+    {
+        auto* box = new ConnectionBox(this, false);
+        box->setPos(this->m_boundRect.right(), this->m_boundRect.top() + ((i + 1) * this->m_boundRect.height()) / float(outputs + 1));
+        this->outputConnections.push_back(box);
+    }
 }
 
 GraphicsBox::~GraphicsBox()
diff --git a/agui2/Graphics/GraphicsBox.h b/agui2/Graphics/GraphicsBox.h
index 4a31ad16f605a4753f63de886780cecfa2fb86c6..10870b613dabcae75c1a43f6ffae75319faf4554 100644
--- a/agui2/Graphics/GraphicsBox.h
+++ b/agui2/Graphics/GraphicsBox.h
@@ -11,6 +11,7 @@
 
 #define BOX_MARGIN 20
 
+class ConnectionBox;
 class GraphicsConnection;
 class WrapperBox;
 
@@ -38,6 +39,8 @@ protected:
     GraphicsConnection* m_OutConnection = nullptr;
     GraphicsConnection* m_InConnection = nullptr;
     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;