diff --git a/source/armarx/navigation/graph/Graph.cpp b/source/armarx/navigation/graph/Graph.cpp
index bce79ae3d6c1222928d2b87ea764f0c24a6527e1..f8086dce0b3252e37585f034c6b44642d315f02f 100644
--- a/source/armarx/navigation/graph/Graph.cpp
+++ b/source/armarx/navigation/graph/Graph.cpp
@@ -36,6 +36,11 @@ namespace armarx::nav::graph
         return aron.globalRobotPose;
     }
 
+    void VertexAttribs::setPose(const Eigen::Matrix4f& pose)
+    {
+        this->aron.globalRobotPose = pose;
+    }
+
 }
 
 
diff --git a/source/armarx/navigation/graph/Graph.h b/source/armarx/navigation/graph/Graph.h
index dd5704bcbdb82f65fa28189e249635662f0f3ea1..d895dd635e690c0c4a737b11fca9a7523faeb535 100644
--- a/source/armarx/navigation/graph/Graph.h
+++ b/source/armarx/navigation/graph/Graph.h
@@ -35,7 +35,9 @@ namespace armarx::nav::graph
         armarx::nav::graph::arondto::Vertex aron;
 
         std::string getName() const;
+
         Eigen::Matrix4f getPose() const;
+        void setPose(const Eigen::Matrix4f& pose);
     };
     struct EdgeAttribs
     {
diff --git a/source/armarx/navigation/gui-plugins/LocationGraphEditor/CMakeLists.txt b/source/armarx/navigation/gui-plugins/LocationGraphEditor/CMakeLists.txt
index 8235d2811d307784175818c8bb183a142e90828e..d2661dbac93f5ecba03215cc9dfad01921beffa3 100644
--- a/source/armarx/navigation/gui-plugins/LocationGraphEditor/CMakeLists.txt
+++ b/source/armarx/navigation/gui-plugins/LocationGraphEditor/CMakeLists.txt
@@ -14,25 +14,32 @@ set(SOURCES
     LocationGraphEditorWidgetController.cpp
 
     FunctionalEventFilter.cpp
-    GraphScene.cpp
     GuiGraph.cpp
 
     widgets/default_colors.cpp
     widgets/EdgeTableWidget.cpp
     widgets/VertexDataWidget.cpp
     widgets/VertexTableWidget.cpp
+
+    widgets/graph_scene/ControlWidget.cpp
+    widgets/graph_scene/Scene.cpp
+    widgets/graph_scene/Widget.cpp
 )
 set(HEADERS
     LocationGraphEditorWidgetController.h
 
     FunctionalEventFilter.h
-    GraphScene.h
     GuiGraph.h
 
     widgets/default_colors.h
     widgets/EdgeTableWidget.h
     widgets/VertexDataWidget.h
     widgets/VertexTableWidget.h
+
+    widgets/graph_scene.h
+    widgets/graph_scene/ControlWidget.h
+    widgets/graph_scene/Scene.h
+    widgets/graph_scene/Widget.h
 )
 set(GUI_UIS
     LocationGraphEditorWidget.ui
diff --git a/source/armarx/navigation/gui-plugins/LocationGraphEditor/GuiGraph.cpp b/source/armarx/navigation/gui-plugins/LocationGraphEditor/GuiGraph.cpp
index 377f726e295e0918776d19eb7154ed72f06b2ff1..f4fd3e1d100fe63545cb55c7fd80ae870fb52a2d 100644
--- a/source/armarx/navigation/gui-plugins/LocationGraphEditor/GuiGraph.cpp
+++ b/source/armarx/navigation/gui-plugins/LocationGraphEditor/GuiGraph.cpp
@@ -29,24 +29,54 @@
 namespace armarx::nav::locgrapheditor
 {
 
+    std::optional<GuiGraph::Vertex>
+    GuiGraph::getVertexFromTableItem(QTableWidgetItem* item)
+    {
+        for (auto vertex : vertices())
+        {
+            if (vertex.attrib().tableWidgetItem == item)
+            {
+                return vertex;
+            }
+        }
+        return std::nullopt;
+    }
+
+
+    std::map<QTableWidgetItem*, GuiGraph::Vertex>
+    GuiGraph::getTableItemToVertexMap()
+    {
+        std::map<QTableWidgetItem*, GuiGraph::Vertex> map;
+
+        for (auto vertex : vertices())
+        {
+            if (vertex.attrib().tableWidgetItem != nullptr)
+            {
+                map[vertex.attrib().tableWidgetItem] = vertex;
+            }
+        }
+
+        return map;
+    }
+
 }
 
 namespace armarx::nav
 {
 
-    float locgrapheditor::getYawAngleDegree(const Eigen::Matrix4f& pose)
-    {
-        Eigen::Vector3f rpy = simox::math::mat4f_to_rpy(pose);
-        return simox::math::rad_to_deg(rpy[2]);
-    }
+float locgrapheditor::getYawAngleDegree(const Eigen::Matrix4f& pose)
+{
+    Eigen::Vector3f rpy = simox::math::mat4f_to_rpy(pose);
+    return simox::math::rad_to_deg(rpy[2]);
+}
 
-    auto locgrapheditor::toGuiGraph(const graph::Graph& nav) -> GuiGraph
+auto locgrapheditor::toGuiGraph(const graph::Graph& nav) -> GuiGraph
+{
+    GuiGraph gui;
+    for (auto v : nav.vertices())
     {
-        GuiGraph gui;
-        for (auto v : nav.vertices())
-        {
-            gui.addVertex(v.objectID(), { v.attrib() });
-        }
+        gui.addVertex(v.objectID(), { v.attrib() });
+    }
         for (auto e : nav.edges())
         {
             gui.addEdge(e.sourceObjectID(), e.targetObjectID(), { e.attrib() });
diff --git a/source/armarx/navigation/gui-plugins/LocationGraphEditor/GuiGraph.h b/source/armarx/navigation/gui-plugins/LocationGraphEditor/GuiGraph.h
index f0b6e0bba09fcc68240f42eb24f9798220092950..87395a1fb13350128ea78fd1d5cffa6ed2f761e7 100644
--- a/source/armarx/navigation/gui-plugins/LocationGraphEditor/GuiGraph.h
+++ b/source/armarx/navigation/gui-plugins/LocationGraphEditor/GuiGraph.h
@@ -25,6 +25,9 @@
 
 #include <SemanticObjectRelations/RelationGraph/RelationGraph.h>
 
+#include <map>
+#include <optional>
+
 
 class QGraphicsEllipseItem;
 class QGraphicsLineItem;
@@ -73,7 +76,18 @@ namespace armarx::nav::locgrapheditor
     };
 
 
-    using GuiGraph = semrel::RelationGraph<VertexData, EdgeData, GraphData>;
+    class GuiGraph : public semrel::RelationGraph<VertexData, EdgeData, GraphData>
+    {
+    public:
+
+        using RelationGraph::RelationGraph;
+
+
+        std::optional<Vertex> getVertexFromTableItem(QTableWidgetItem* item);
+
+        std::map<QTableWidgetItem*, Vertex> getTableItemToVertexMap();
+
+    };
 
 
     GuiGraph toGuiGraph(const graph::Graph& graph);
diff --git a/source/armarx/navigation/gui-plugins/LocationGraphEditor/LocationGraphEditorWidget.ui b/source/armarx/navigation/gui-plugins/LocationGraphEditor/LocationGraphEditorWidget.ui
index 6a33a0128448d77ed4e8c65e410055cb448c93ad..a25894c76c31254fb42c7dc9611d2fa5d404d4f3 100644
--- a/source/armarx/navigation/gui-plugins/LocationGraphEditor/LocationGraphEditorWidget.ui
+++ b/source/armarx/navigation/gui-plugins/LocationGraphEditor/LocationGraphEditorWidget.ui
@@ -79,95 +79,7 @@
         <number>0</number>
        </property>
        <item>
-        <widget class="QWidget" name="graphHead" native="true">
-         <layout class="QHBoxLayout" name="horizontalLayout_2">
-          <item>
-           <widget class="QLabel" name="label_graph">
-            <property name="text">
-             <string>Graph</string>
-            </property>
-           </widget>
-          </item>
-          <item>
-           <widget class="QPushButton" name="buttonRedraw">
-            <property name="text">
-             <string>Repaint</string>
-            </property>
-           </widget>
-          </item>
-          <item>
-           <widget class="QPushButton" name="buttonClear">
-            <property name="text">
-             <string>Clear Graph</string>
-            </property>
-           </widget>
-          </item>
-          <item>
-           <spacer name="horizontalSpacer">
-            <property name="orientation">
-             <enum>Qt::Horizontal</enum>
-            </property>
-            <property name="sizeHint" stdset="0">
-             <size>
-              <width>40</width>
-              <height>20</height>
-             </size>
-            </property>
-           </spacer>
-          </item>
-          <item>
-           <widget class="QToolButton" name="buttonRotateClock">
-            <property name="text">
-             <string>↻</string>
-            </property>
-           </widget>
-          </item>
-          <item>
-           <widget class="QToolButton" name="buttonRotateCounterClock">
-            <property name="text">
-             <string>↺</string>
-            </property>
-           </widget>
-          </item>
-          <item>
-           <widget class="Line" name="line_3">
-            <property name="orientation">
-             <enum>Qt::Vertical</enum>
-            </property>
-           </widget>
-          </item>
-          <item>
-           <widget class="QLabel" name="label_zoom">
-            <property name="text">
-             <string>Zoom</string>
-            </property>
-           </widget>
-          </item>
-          <item>
-           <widget class="QDoubleSpinBox" name="viewZoomFactor">
-            <property name="decimals">
-             <number>5</number>
-            </property>
-            <property name="singleStep">
-             <double>0.001000000000000</double>
-            </property>
-            <property name="value">
-             <double>0.100000000000000</double>
-            </property>
-           </widget>
-          </item>
-          <item>
-           <widget class="QToolButton" name="buttonAutoAdjust">
-            <property name="text">
-             <string>Auto</string>
-            </property>
-           </widget>
-          </item>
-         </layout>
-        </widget>
-       </item>
-       <item>
-        <widget class="QGraphicsView" name="graphicsViewGraph"/>
+        <layout class="QVBoxLayout" name="graphSceneLayout"/>
        </item>
       </layout>
      </widget>
@@ -193,11 +105,11 @@
          <widget class="QWidget" name="verticalLayout_12Widget">
           <layout class="QVBoxLayout" name="verticalLayout_12">
            <item>
-            <widget class="QGroupBox" name="locationsTableGroupBox">
+            <widget class="QGroupBox" name="locationDataGroupBox">
              <property name="title">
-              <string>Locations (Graph Vertices)</string>
+              <string>Location Data</string>
              </property>
-             <layout class="QVBoxLayout" name="verticalLayout_7">
+             <layout class="QVBoxLayout" name="verticalLayout_3">
               <property name="leftMargin">
                <number>3</number>
               </property>
@@ -218,11 +130,11 @@
          <widget class="QWidget" name="verticalLayout_13Widget">
           <layout class="QVBoxLayout" name="verticalLayout_13">
            <item>
-            <widget class="QGroupBox" name="edgesTableGroupBox">
+            <widget class="QGroupBox" name="locationsTableGroupBox">
              <property name="title">
-              <string>Graph Edges</string>
+              <string>Locations (Graph Vertices)</string>
              </property>
-             <layout class="QVBoxLayout" name="verticalLayout_8">
+             <layout class="QVBoxLayout" name="verticalLayout_7">
               <property name="leftMargin">
                <number>3</number>
               </property>
@@ -243,11 +155,24 @@
          <widget class="QWidget" name="verticalLayout_6Widget">
           <layout class="QVBoxLayout" name="verticalLayout_6">
            <item>
-            <widget class="QGroupBox" name="locationDataGroupBox">
+            <widget class="QGroupBox" name="edgesTableGroupBox">
              <property name="title">
-              <string>Location Data</string>
+              <string>Graph Edges</string>
              </property>
-             <layout class="QVBoxLayout" name="verticalLayout_3"/>
+             <layout class="QVBoxLayout" name="verticalLayout_8">
+              <property name="leftMargin">
+               <number>3</number>
+              </property>
+              <property name="topMargin">
+               <number>3</number>
+              </property>
+              <property name="rightMargin">
+               <number>3</number>
+              </property>
+              <property name="bottomMargin">
+               <number>3</number>
+              </property>
+             </layout>
             </widget>
            </item>
           </layout>
diff --git a/source/armarx/navigation/gui-plugins/LocationGraphEditor/LocationGraphEditorWidgetController.cpp b/source/armarx/navigation/gui-plugins/LocationGraphEditor/LocationGraphEditorWidgetController.cpp
index 9510d82c920b9e8500e91322dbfe2aede3416466..e23d674833f93d45484578ff73f493f7a6012746 100644
--- a/source/armarx/navigation/gui-plugins/LocationGraphEditor/LocationGraphEditorWidgetController.cpp
+++ b/source/armarx/navigation/gui-plugins/LocationGraphEditor/LocationGraphEditorWidgetController.cpp
@@ -24,6 +24,8 @@
 #include "widgets/EdgeTableWidget.h"
 #include "widgets/VertexDataWidget.h"
 #include "widgets/VertexTableWidget.h"
+#include "widgets/graph_scene/Scene.h"
+#include "widgets/graph_scene/Widget.h"
 
 #include <Navigation/gui-plugins/LocationGraphEditor/ui_LocationGraphEditorWidget.h>
 
@@ -110,20 +112,22 @@ namespace armarx::nav::locgrapheditor
 
         loadAutomaticSettings();
 
-        dataWidgets.edgeTable = new EdgeTableWidget();
-        dataWidgets.vertexTable = new VertexTableWidget();
-        dataWidgets.vertexData = new VertexDataWidget();
-        widget.edgesTableGroupBox->layout()->addWidget(dataWidgets.edgeTable);
-        widget.locationsTableGroupBox->layout()->addWidget(dataWidgets.vertexTable);
-        widget.locationDataGroupBox->layout()->addWidget(dataWidgets.vertexData);
+        widget.loadGraphButton->setEnabled(false);
 
-        // Add scene
-        view.view = widget.graphicsViewGraph;
-        view.setScene(new GraphScene());
+        view.edgeTable = new EdgeTableWidget();
+        view.vertexTable = new VertexTableWidget();
+        view.vertexData = new VertexDataWidget();
+        view.vertexData->setEnabled(false);  // Enable on first selection of vertex.
+        widget.edgesTableGroupBox->layout()->addWidget(view.edgeTable);
+        widget.locationsTableGroupBox->layout()->addWidget(view.vertexTable);
+        widget.locationDataGroupBox->layout()->addWidget(view.vertexData);
 
+        view.graph = new GraphSceneWidget();
+        widget.graphSceneLayout->addWidget(view.graph);
+
+#if 0
         auto eventFilter = [this](QObject* obj, QEvent* event) -> bool
         {
-#if 0
             if (obj == this->view.view && event->type() == QEvent::MouseButtonPress)
             {
                 QMouseEvent* me = static_cast<QMouseEvent*>(event);
@@ -158,54 +162,38 @@ namespace armarx::nav::locgrapheditor
             {
                 this->adjustView();
             }
-#endif
-            return QObject::eventFilter(obj, event);
+            else
+            {
+                return false;
+            }
         };
         view.view->installEventFilter(new simox::gui::FunctionalEventFilter(eventFilter));
-
-
-        // Transform view
-        transformView();
+#endif
 
         // Widgets -> This
 
         // Memory Access
-        connect(widget.refreshGraphsButton, &QPushButton::clicked, this, &This::updateGraphList);
-        connect(widget.loadGraphButton, &QPushButton::clicked, this, &This::loadGraph);
+        connect(widget.refreshGraphsButton, &QPushButton::pressed, this, &This::updateGraphList);
+        connect(widget.loadGraphButton, &QPushButton::pressed, this, &This::loadGraph);
 
 
 #if 0
         // Tables
-        connect(dataWidgets.vertexTable, &QTableWidget::cellDoubleClicked, this, &This::vertexTableDoubleClicked);
-        connect(dataWidgets.vertexTable, &QTableWidget::customContextMenuRequested, this, &This::tableWidgetVerticesCustomContextMenu);
-        connect(dataWidgets.edgeTable, &QTableWidget::cellDoubleClicked, this, &This::edgeTableDoubleClicked);
-        connect(dataWidgets.edgeTable, &QTableWidget::customContextMenuRequested, this, &This::tableWidgetEdgesCustomContextMenu);
-
-        connect(widget.btnAdd, &QPushButton::clicked, this, &This::addNewGraphVertex);
-        connect(widget.btnAddEdge, &QPushButton::clicked, this, &This::addNewEdgeBoth);
-        connect(widget.btnAddEdgeStartEnd, &QPushButton::clicked, this, &This::addNewEdgeStartEnd);
-        connect(widget.btnAddEdgeEndStart, &QPushButton::clicked, this, &This::addNewEdgeEndStart);
-        connect(widget.btnEdit, &QPushButton::clicked, this, &This::editGraphVertex);
+        connect(view.vertexTable, &QTableWidget::cellDoubleClicked, this, &This::vertexTableDoubleClicked);
+        connect(view.vertexTable, &QTableWidget::customContextMenuRequested, this, &This::tableWidgetVerticesCustomContextMenu);
+        connect(view.edgeTable, &QTableWidget::cellDoubleClicked, this, &This::edgeTableDoubleClicked);
+        connect(view.edgeTable, &QTableWidget::customContextMenuRequested, this, &This::tableWidgetEdgesCustomContextMenu);
+
+        connect(widget.btnAdd, &QPushButton::pressed, this, &This::addNewGraphVertex);
+        connect(widget.btnAddEdge, &QPushButton::pressed, this, &This::addNewEdgeBoth);
+        connect(widget.btnAddEdgeStartEnd, &QPushButton::pressed, this, &This::addNewEdgeStartEnd);
+        connect(widget.btnAddEdgeEndStart, &QPushButton::pressed, this, &This::addNewEdgeEndStart);
+        connect(widget.btnEdit, &QPushButton::pressed, this, &This::editGraphVertex);
 #endif
 
-        // Zoom
-        connect(widget.viewZoomFactor, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &This::transformView);
-
-#if 0
-        // Rotation
-        connect(widget.buttonRotateClock, &QPushButton::clicked, this, &This::viewRotatedClock);
-        connect(widget.buttonRotateCounterClock, &QPushButton::clicked, this, &This::viewRotatedCounterClock);
-
-        // Redraw+clear
-        connect(widget.buttonRedraw, &QPushButton::clicked, this, &This::redraw);
-        connect(widget.buttonClear, &QPushButton::clicked, this, &This::clearGraph);
-
-        // Auto adjust view
-        connect(widget.buttonAutoAdjust, &QPushButton::clicked, this, &This::adjustView);
-#endif
-
-        connect(view.scene, &GraphScene::vertexSelected, this, &This::toggleVertexSelected);
+        // View
 
+        // connect(view.graph->scene(), &GraphScene::vertexSelected, this, &This::toggleVertexSelected);
 
         // This -> This
 
@@ -213,13 +201,19 @@ namespace armarx::nav::locgrapheditor
         connect(this, &This::connected, this, &This::queryGraphs);
         connect(this, &This::memoryDataChanged, this, &This::updateGraphList);
 
-    }
 
+        connect(view.vertexData, &VertexDataWidget::vertexDataChanged,
+                this, &This::updateVertexView);
 
-    void LocationGraphEditorWidgetController::GraphView::setScene(GraphScene* scene)
-    {
-        this->scene = scene;
-        this->view->setScene(this->scene);
+        connect(view.vertexTable, &VertexTableWidget::currentItemChanged,
+                [this](QTableWidgetItem* current, QTableWidgetItem* previous)
+        {
+            (void) previous;
+            this->selectVertex(current);
+        });
+
+        connect(view.vertexTable, &VertexTableWidget::itemSelectionChanged,
+                this, &This::updateVertexHighlighting);
     }
 
 
@@ -327,10 +321,13 @@ namespace armarx::nav::locgrapheditor
     {
         widget.graphsComboBox->clear();
 
-        data.memory.forEachEntity([this](const armem::wm::Entity& entity)
+        bool enable = false;
+        data.memory.forEachEntity([this, &enable](const armem::wm::Entity& entity)
         {
             widget.graphsComboBox->addItem(QString::fromStdString(entity.id().str()));
+            enable = true;
         });
+        widget.loadGraphButton->setEnabled(enable);
     }
 
 
@@ -384,7 +381,7 @@ namespace armarx::nav::locgrapheditor
                 if (vertex.objectID() == vertexID)
                 {
                     vertex.attrib().highlighted = true;
-                    updateVertex(vertex);
+                    updateVertexView(vertex);
                 }
             }
         }
@@ -399,11 +396,11 @@ namespace armarx::nav::locgrapheditor
         ARMARX_CHECK(not data.graph.hasVertex(vertex.objectID()));
 
         VertexData attrib { vertex.attrib() };
-        attrib.graphicsItem = view.scene->addVertex(vertex);
-        attrib.tableWidgetItem = dataWidgets.vertexTable->addVertex(vertex);
+        attrib.graphicsItem = view.graph->scene()->addVertex(vertex);
+        attrib.tableWidgetItem = view.vertexTable->addVertex(vertex);
         auto guiVertex = data.graph.addVertex(vertex.objectID(), attrib);
 
-        updateVertex(guiVertex);
+        updateVertexView(guiVertex);
         return guiVertex;
     }
 
@@ -420,22 +417,21 @@ namespace armarx::nav::locgrapheditor
         auto target = data.graph.vertex(edge.targetObjectID());
 
         EdgeData attrib { edge.attrib() };
-        attrib.tableWidgetItem = dataWidgets.edgeTable->addEdge(edge);
-        attrib.graphicsItem = view.scene->addEdge(edge);
+        attrib.tableWidgetItem = view.edgeTable->addEdge(edge);
+        attrib.graphicsItem = view.graph->scene()->addEdge(edge);
         auto guiEdge = data.graph.addEdge(source, target, attrib);
 
-        updateEdge(guiEdge);
+        updateEdgeView(guiEdge);
         return guiEdge;
     }
 
 
-    void LocationGraphEditorWidgetController::updateVertex(GuiGraph::Vertex vertex)
+    void LocationGraphEditorWidgetController::updateVertexView(GuiGraph::Vertex vertex)
     {
-        view.scene->updateVertex(vertex);
-        dataWidgets.vertexTable->updateVertex(vertex);
-
-        setEditFields(vertex);
+        view.graph->scene()->updateVertex(vertex);
+        view.vertexTable->updateVertex(vertex);
 
+        if (/* DISABLES CODE */ (false))  // Disable this for the moment.
         {
             // Highlight all edges between highlighted vertices
             std::set<semrel::ShapeID> highlightedVertices;
@@ -458,7 +454,7 @@ namespace armarx::nav::locgrapheditor
                 if (edge.attrib().highlighted != verticesHighlighted)
                 {
                     edge.attrib().highlighted = verticesHighlighted;
-                    updateEdge(edge);
+                    updateEdgeView(edge);
                 }
             }
         }
@@ -480,10 +476,10 @@ namespace armarx::nav::locgrapheditor
     }
 
 
-    void LocationGraphEditorWidgetController::updateEdge(GuiGraph::Edge edge)
+    void LocationGraphEditorWidgetController::updateEdgeView(GuiGraph::Edge edge)
     {
-        view.scene->updateEdge(edge);
-        dataWidgets.edgeTable->updateEdge(edge);
+        view.graph->scene()->updateEdge(edge);
+        view.edgeTable->updateEdge(edge);
 
 #if 0
         armarx::Vector3Ptr posStart = new armarx::Vector3(armarx::Vector3Ptr::dynamicCast(vertices.at(id.first).pose->position)->toEigen());
@@ -507,12 +503,12 @@ namespace armarx::nav::locgrapheditor
         // Remove from graphics scene
         for (auto edge : data.graph.edges())
         {
-            view.scene->removeEdge(edge.attrib().graphicsItem);
+            view.graph->scene()->removeEdge(edge.attrib().graphicsItem);
         }
 
         // Clear table widget
-        dataWidgets.edgeTable->clearContents();
-        dataWidgets.edgeTable->setRowCount(0);
+        view.edgeTable->clearContents();
+        view.edgeTable->setRowCount(0);
 
         // Clear data structure
         while (data.graph.edges().begin() != data.graph.edges().end())
@@ -527,13 +523,13 @@ namespace armarx::nav::locgrapheditor
     void LocationGraphEditorWidgetController::clearGraph()
     {
         // Clear scene
-        view.scene->clear();
+        view.graph->scene()->clear();
 
         // Clear table widgets
-        dataWidgets.edgeTable->clearContents();
-        dataWidgets.edgeTable->setRowCount(0);
-        dataWidgets.vertexTable->clearContents();
-        dataWidgets.vertexTable->setRowCount(0);
+        view.edgeTable->clearContents();
+        view.edgeTable->setRowCount(0);
+        view.vertexTable->clearContents();
+        view.vertexTable->setRowCount(0);
 
         // Clear data structure
         data.graph.clear();
@@ -544,11 +540,10 @@ namespace armarx::nav::locgrapheditor
     {
         auto vertex = data.graph.vertex(vertexID);
         vertex.attrib().highlighted ^= true;
-        updateVertex(vertex);
+        updateVertexView(vertex);
     }
 
 
-
     void LocationGraphEditorWidgetController::resetHighlighting()
     {
         for (auto vertex : data.graph.vertices())
@@ -556,7 +551,7 @@ namespace armarx::nav::locgrapheditor
             if (vertex.attrib().highlighted)
             {
                 vertex.attrib().highlighted = false;
-                updateVertex(vertex);
+                updateVertexView(vertex);
             }
         }
         for (auto edge : data.graph.edges())
@@ -564,12 +559,32 @@ namespace armarx::nav::locgrapheditor
             if (edge.attrib().highlighted)
             {
                 edge.attrib().highlighted = false;
-                updateEdge(edge);
+                updateEdgeView(edge);
             }
         }
     }
 
 
+    void LocationGraphEditorWidgetController::updateVertexHighlighting()
+    {
+        std::map<QTableWidgetItem*, GuiGraph::Vertex> map = data.graph.getTableItemToVertexMap();
+
+        for (QTableWidgetItem* selected : view.vertexTable->selectedEdgeItems())
+        {
+            if (auto it = map.find(selected); it != map.end())
+            {
+                it->second.attrib().highlighted = true;
+                updateVertexView(it->second);
+                map.erase(it);
+            }
+        }
+        for (auto& [_, unselected] : map)
+        {
+            unselected.attrib().highlighted = false;
+            updateVertexView(unselected);
+        }
+    }
+
 
 #if 0
 
@@ -612,7 +627,7 @@ namespace armarx::nav::locgrapheditor
     {
         auto vertexIt = std::find_if(vertices.cbegin(), vertices.cend(), [&](const std::pair<std::string, VertexData>& d)
         {
-            //        return d.attrib().vertex->getName() == dataWidgets.vertexTable->item(row, 0)->text().toStdString();
+            //        return d.attrib().vertex->getName() == view.vertexTable->item(row, 0)->text().toStdString();
             return d.attrib().tableWidgetVerticesIndex == row;
         });
         auto vertexId = vertexIt->second.vertex->getId();
@@ -643,35 +658,9 @@ namespace armarx::nav::locgrapheditor
         updateVertex(edge.attrib());
     }
 
-
-    void LocationGraphEditorWidgetController::redraw()
-    {
-        loadGraph();
-    }
 #endif
 
 
-    void LocationGraphEditorWidgetController::setEditFields(GuiGraph::Vertex vertex)
-    {
-#if 0
-        widget.editVertexId->setText(QString::fromStdString(vertexData.vertex->getId()));
-        widget.editSceneName->setText(QString::fromStdString(vertexData.vertex->getScene()));
-        widget.editVertexName->setText(QString::fromStdString(vertexData.vertex->getName()));
-        widget.editFrameName->setText(QString::fromStdString(vertexData.pose->frame));
-        widget.editAgentName->setText(QString::fromStdString(vertexData.pose->agent));
-
-        Eigen::Vector3f rpy;
-        VirtualRobot::MathTools::eigen4f2rpy(vertexData.pose->toEigen(), rpy);
-        widget.spinBoxX->setValue(vertexData.pose->position->x);
-        widget.spinBoxY->setValue(vertexData.pose->position->y);
-        widget.spinBoxZ->setValue(vertexData.pose->position->z);
-
-        widget.spinBoxRoll->setValue(VirtualRobot::MathTools::rad2deg(rpy[0]));
-        widget.spinBoxPitch->setValue(VirtualRobot::MathTools::rad2deg(rpy[1]));
-        widget.spinBoxYaw->setValue(VirtualRobot::MathTools::rad2deg(rpy[2]));
-#endif
-    }
-
 #if 0
     void LocationGraphEditorWidgetController::refreshGraph()
     {
@@ -681,68 +670,19 @@ namespace armarx::nav::locgrapheditor
 
 #endif
 
-    void LocationGraphEditorWidgetController::transformView()
-    {
-        double d = widget.viewZoomFactor->value();
-        widget.graphicsViewGraph->setTransform(QTransform::fromScale(d, d).rotate(view.angle));
-    }
-
-
-#if 0
-
 
-    void LocationGraphEditorWidgetController::viewRotatedClock()
+    void LocationGraphEditorWidgetController::selectVertex(QTableWidgetItem* vertexItem)
     {
-        viewAngle = std::fmod(viewAngle + VIEW_ROTATE_STEP_SIZE_CC, 360);
-        transformView();
-    }
-
-
-    void LocationGraphEditorWidgetController::viewRotatedCounterClock()
-    {
-        viewAngle = std::fmod(viewAngle + 360 - VIEW_ROTATE_STEP_SIZE_CC, 360);
-        transformView();
-    }
-#endif
-
-    void LocationGraphEditorWidgetController::adjustView()
-    {
-#if 0
-        float maxX = std::numeric_limits<float>::min();
-        float minX = std::numeric_limits<float>::max();
-        float maxY = std::numeric_limits<float>::min();
-        float minY = std::numeric_limits<float>::max();
-
-        // search bounding box
-        for (const auto& vertex : vertices)
+        if (auto vertex = data.graph.getVertexFromTableItem(vertexItem))
         {
-            maxX = (maxX < vertex.attrib().pose->position->x) ? vertex.attrib().pose->position->x : maxX;
-            minX = (minX > vertex.attrib().pose->position->x) ? vertex.attrib().pose->position->x : minX;
-            maxY = (maxY < vertex.attrib().pose->position->y) ? vertex.attrib().pose->position->y : maxY;
-            minY = (minY > vertex.attrib().pose->position->y) ? vertex.attrib().pose->position->y : minY;
+            selectVertex(vertex.value());
         }
+    }
 
-        auto deltaX = maxX - minX; // >=0
-        auto deltaY = maxY - minY; // >=0
 
-        // compare ratio of graph and view. if both horizontal (vertical) ->rotate to 0 or 180 (90,270)
-        if (std::signbit(deltaX / deltaY - 1) == std::signbit(widget.graphicsViewGraph->width() / widget.graphicsViewGraph->height() - 1))
-        {
-            // same => rotate to 0 or 180
-            viewAngle = (viewAngle < std::abs(180 - viewAngle)) ? 0 : 180;
-            // set zoom => update
-            widget.viewZoomFactor->setValue(std::min(widget.graphicsViewGraph->width() / deltaX,
-                                                 widget.graphicsViewGraph->height() / deltaY) * 0.9);
-        }
-        else
-        {
-            // different rotate to 90 or 270
-            viewAngle = (std::abs(90 - viewAngle) < std::abs(270 - viewAngle)) ? 90 : 270;
-            // set zoom => update
-            widget.viewZoomFactor->setValue(std::min(widget.graphicsViewGraph->width() / deltaY,
-                                                 widget.graphicsViewGraph->height() / deltaX) * 0.9);
-        }
-#endif
+    void LocationGraphEditorWidgetController::selectVertex(GuiGraph::Vertex vertex)
+    {
+        view.vertexData->setVertex(vertex);
     }
 
 
@@ -916,7 +856,7 @@ namespace armarx::nav::locgrapheditor
 
     void LocationGraphEditorWidgetController::tableWidgetVerticesCustomContextMenu(QPoint pos)
     {
-        int row = dataWidgets.vertexTable->rowAt(pos.y());
+        int row = view.vertexTable->rowAt(pos.y());
         auto vertexIt = std::find_if(vertices.begin(), vertices.end(), [&](const std::pair<std::string, VertexData>& d)
         {
             return d.attrib().tableWidgetVerticesIndex == row;
@@ -935,7 +875,7 @@ namespace armarx::nav::locgrapheditor
 
     void LocationGraphEditorWidgetController::tableWidgetEdgesCustomContextMenu(QPoint pos)
     {
-        int row = dataWidgets.edgeTable->rowAt(pos.y());
+        int row = view.edgeTable->rowAt(pos.y());
         auto edgeIt = std::find_if(edges.begin(), edges.end(), [&](const std::pair<EdgeId, EdgeData>& d)
         {
             return d.attrib().tableWidgetEdgesIndex == row;
diff --git a/source/armarx/navigation/gui-plugins/LocationGraphEditor/LocationGraphEditorWidgetController.h b/source/armarx/navigation/gui-plugins/LocationGraphEditor/LocationGraphEditorWidgetController.h
index d06303359ed86124fdd2f14fac4b3a8496eca329..ded79af18d0f42d05163b250f2138803822a32f4 100644
--- a/source/armarx/navigation/gui-plugins/LocationGraphEditor/LocationGraphEditorWidgetController.h
+++ b/source/armarx/navigation/gui-plugins/LocationGraphEditor/LocationGraphEditorWidgetController.h
@@ -22,8 +22,8 @@
 #pragma once
 
 #include "FunctionalEventFilter.h"
-#include "GraphScene.h"
 #include "GuiGraph.h"
+#include "widgets/graph_scene.h"
 
 #include <armarx/navigation/graph/Graph.h>
 
@@ -142,18 +142,17 @@ namespace armarx::nav::locgrapheditor
 
         // View & Tables
 
-        void updateVertex(GuiGraph::Vertex vertex);
-        void updateEdge(GuiGraph::Edge edge);
-
-        /// Applies the current transforamtion to the view.
-        void transformView();
-        /// Adjusts the view's zoom and rotation to display most of the graph.
-        void adjustView();
+        void updateVertexView(GuiGraph::Vertex vertex);
+        void updateEdgeView(GuiGraph::Edge edge);
 
 
         // Selection
 
+        void selectVertex(QTableWidgetItem* vertexItem);
+        void selectVertex(GuiGraph::Vertex vertex);
+
         void resetHighlighting();
+        void updateVertexHighlighting();
         void toggleVertexSelected(const semrel::ShapeID& vertexID);
 
 
@@ -184,52 +183,30 @@ namespace armarx::nav::locgrapheditor
         struct Data
         {
             armem::wm::Memory memory;
-            nav::locgrapheditor::GuiGraph graph;
+            GuiGraph graph;
         };
         Data data;
 
 
-        struct DataWidgets
+        struct View
         {
             VertexTableWidget* vertexTable = nullptr;
             EdgeTableWidget* edgeTable = nullptr;
             VertexDataWidget* vertexData = nullptr;
-        };
-        DataWidgets dataWidgets;
-
-
-        struct GraphView
-        {
-            QGraphicsView* view = nullptr;
 
-            /**
-             * @brief The scene displayed in the widget.
-             *
-             * For y coordinates (-y) is used to mirror the scene on the y axis.
-             * If (+y) would be used the graph displayed in the scene would not
-             * match the graph drawn to the debug layer.
-             */
-            GraphScene* scene;
-
-            /// The view's rotation angle.
-            qreal angle = 0;
-
-            void setScene(GraphScene* scene);
+            GraphSceneWidget* graph = nullptr;
         };
-        GraphView view;
-
+        View view;
 
 
     // Non-refactored
 
-
 #if 0
     private slots:
 
         void highlightEdge(const std::string& vertex1Id, const std::string& vertex2Id, bool highlighted = true);
         void highlightVertex(const std::string& vertexId, bool highlighted = true);
 
-        void redraw();
         void refreshGraph();
 
         void tableWidgetVerticesCustomContextMenu(QPoint pos);
@@ -281,8 +258,6 @@ namespace armarx::nav::locgrapheditor
         void editGraphVertex();
 #endif
 
-        void setEditFields(GuiGraph::Vertex vertex);
-
 
     private:
 
diff --git a/source/armarx/navigation/gui-plugins/LocationGraphEditor/widgets/graph_scene.h b/source/armarx/navigation/gui-plugins/LocationGraphEditor/widgets/graph_scene.h
new file mode 100644
index 0000000000000000000000000000000000000000..5edd01203df57213a8d5b0d9099d527237c6c12a
--- /dev/null
+++ b/source/armarx/navigation/gui-plugins/LocationGraphEditor/widgets/graph_scene.h
@@ -0,0 +1,17 @@
+#pragma once
+
+
+namespace armarx::nav::locgrapheditor::graph_scene
+{
+    class Scene;
+    class Widget;
+}
+
+namespace armarx::nav::locgrapheditor
+{
+
+    using GraphScene = graph_scene::Scene;
+    using GraphSceneWidget = graph_scene::Widget;
+
+}
+
diff --git a/source/armarx/navigation/gui-plugins/LocationGraphEditor/widgets/graph_scene/ControlWidget.cpp b/source/armarx/navigation/gui-plugins/LocationGraphEditor/widgets/graph_scene/ControlWidget.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5549b56f46afc984490bd9abbd16e2d98cbebe1d
--- /dev/null
+++ b/source/armarx/navigation/gui-plugins/LocationGraphEditor/widgets/graph_scene/ControlWidget.cpp
@@ -0,0 +1,107 @@
+#include "ControlWidget.h"
+
+#include <ArmarXCore/core/logging/Logging.h>
+
+#include <QDoubleSpinBox>
+#include <QFrame>
+#include <QHBoxLayout>
+#include <QLabel>
+#include <QPushButton>
+
+#include <cmath>
+
+
+namespace armarx::nav::locgrapheditor::graph_scene
+{
+
+    ControlWidget::ControlWidget()
+    {
+        _angle.turnClockwise = new QPushButton("\u21bb");  // https://unicode-table.com/de/21BB/
+        _angle.turnCounterClockwise = new QPushButton("\u21ba");  // https://unicode-table.com/de/21BA/
+        std::vector<QPushButton*> turnButtons;
+        for (QPushButton* button : turnButtons)
+        {
+            button->setMinimumWidth(button->minimumHeight());
+            button->setMaximumWidth(button->maximumHeight());
+            button->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
+        }
+
+        _angle.value = new QDoubleSpinBox();
+        _angle.value->setMinimum(-360);
+        _angle.value->setMaximum(360);
+        _angle.value->setSingleStep(15);
+        _angle.value->setValue(0);
+
+        _zoom.value = new QDoubleSpinBox();
+        _zoom.value->setDecimals(5);
+        _zoom.value->setMinimum(1e-6);
+        _zoom.value->setSingleStep(0.01);
+        _zoom.value->setValue(0.1);
+        _zoom.audoAdjust = new QPushButton("Auto");
+
+
+        QHBoxLayout* layout = new QHBoxLayout();
+        this->setLayout(layout);
+
+        layout->addWidget(new QLabel("Angle: "));
+        layout->addWidget(_angle.turnClockwise);
+        layout->addWidget(_angle.value);
+        layout->addWidget(_angle.turnCounterClockwise);
+
+        // Vertical separator line.
+        QFrame* line = new QFrame();
+        line->setFrameShape(QFrame::VLine);
+        line->setFrameShadow(QFrame::Sunken);
+        layout->addWidget(line);
+
+        layout->addWidget(new QLabel("Zoom: "));
+        layout->addWidget(_zoom.value);
+        layout->addWidget(_zoom.audoAdjust);
+
+
+        // Connect
+
+        connect(_angle.value, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
+                this, &This::angleChanged);
+
+        connect(_angle.turnClockwise, &QPushButton::pressed, [this]()
+        {
+            qreal newangle = std::fmod(angle() + _angle.rotateStepSize, 360.0);
+            ARMARX_IMPORTANT << VAROUT(newangle);
+            setAngle(newangle);
+        });
+        connect(_angle.turnCounterClockwise, &QPushButton::pressed, [this]()
+        {
+            setAngle(std::fmod(angle() - _angle.rotateStepSize, 360.0));
+        });
+
+        connect(_zoom.value, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
+                this, &This::angleChanged);
+        connect(_zoom.audoAdjust, &QPushButton::pressed,
+                this, &This::zoomAutoAdjustRequested);
+    }
+
+
+    qreal ControlWidget::angle()
+    {
+        return _angle.value->value();
+    }
+
+    void ControlWidget::setAngle(qreal angle)
+    {
+        _angle.value->setValue(angle);
+    }
+
+
+    qreal ControlWidget::zoom()
+    {
+        return _zoom.value->value();
+    }
+
+    void ControlWidget::setZoom(qreal zoom)
+    {
+        _zoom.value->setValue(zoom);
+    }
+
+}
+
diff --git a/source/armarx/navigation/gui-plugins/LocationGraphEditor/widgets/graph_scene/ControlWidget.h b/source/armarx/navigation/gui-plugins/LocationGraphEditor/widgets/graph_scene/ControlWidget.h
new file mode 100644
index 0000000000000000000000000000000000000000..64d4270e8c85c8493c408235b327b39012e3e5ed
--- /dev/null
+++ b/source/armarx/navigation/gui-plugins/LocationGraphEditor/widgets/graph_scene/ControlWidget.h
@@ -0,0 +1,59 @@
+#pragma once
+
+#include <QWidget>
+
+class QDoubleSpinBox;
+class QHBoxLayout;
+class QPushButton;
+
+
+namespace armarx::nav::locgrapheditor::graph_scene
+{
+
+    class ControlWidget : public QWidget
+    {
+        Q_OBJECT
+        using This = ControlWidget;
+
+
+    public:
+
+        ControlWidget();
+
+        qreal angle();
+        void setAngle(qreal angle);
+        qreal zoom();
+        void setZoom(qreal zoom);
+
+
+    signals:
+
+        void angleChanged(qreal value);
+
+        void zoomChanged(qreal value);
+        void zoomAutoAdjustRequested();
+
+
+    public:
+
+        struct Angle
+        {
+            QPushButton* turnClockwise = nullptr;
+            QDoubleSpinBox* value = nullptr;
+            QPushButton* turnCounterClockwise = nullptr;
+
+            qreal rotateStepSize = 45;
+        };
+        Angle _angle;
+
+        struct Zoom
+        {
+            QDoubleSpinBox* value = nullptr;
+            QPushButton* audoAdjust = nullptr;
+        };
+        Zoom _zoom;
+
+    };
+
+}
+
diff --git a/source/armarx/navigation/gui-plugins/LocationGraphEditor/widgets/graph_scene/Scene.cpp b/source/armarx/navigation/gui-plugins/LocationGraphEditor/widgets/graph_scene/Scene.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d66a24e55615b8b86d8597b09c56c4a61a1db486
--- /dev/null
+++ b/source/armarx/navigation/gui-plugins/LocationGraphEditor/widgets/graph_scene/Scene.cpp
@@ -0,0 +1,164 @@
+#include "Scene.h"
+
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
+
+#include <SemanticObjectRelations/Shapes/Shape.h>
+
+#include <Eigen/Core>
+
+
+namespace armarx::nav::locgrapheditor::graph_scene
+{
+
+    QGraphicsEllipseItem*
+    Scene::addVertex(const graph::Graph::Vertex& vertex)
+    {
+        const Eigen::Matrix4d pose = vertex.attrib().getPose().cast<qreal>();
+
+        // To capture by copy
+        semrel::ShapeID vertexID = vertex.objectID();
+
+        GraphVisualizerGraphicsEllipseItem* item = new GraphVisualizerGraphicsEllipseItem
+        {
+            [this, vertexID]() { emit vertexSelected(vertexID); },
+            pose(0, 3), - pose(1, 3),
+            1, 1
+        };
+        addItem(item);
+
+        // setToolTip on graphicsItem does not work
+        item->setZValue(std::numeric_limits<qreal>::max());
+        // dynamic_cast<QGraphicsItem*>(item)->setToolTip(QString::fromStdString("Vertex '" + name + "'"));
+        item->setToolTip(QString::fromStdString("Vertex '" + vertex.attrib().getName() + "'"));
+
+        return item;
+    }
+
+
+    QGraphicsLineItem*
+    Scene::addEdge(const graph::Graph::Edge& edge)
+    {
+        semrel::ShapeID sourceID = edge.sourceObjectID();
+        semrel::ShapeID targetID = edge.targetObjectID();
+
+        Eigen::Matrix4d sourcePose = edge.source().attrib().getPose().cast<qreal>();
+        Eigen::Matrix4d targetPose = edge.target().attrib().getPose().cast<qreal>();
+
+        GraphVisualizerGraphicsLineItem* item = new GraphVisualizerGraphicsLineItem
+        {
+            [this, sourceID, targetID]() { emit edgeSelected(sourceID, targetID); },
+            sourcePose(0, 3), - sourcePose(1, 3),
+            targetPose(0, 3), - targetPose(1, 3)
+        };
+        addItem(item);
+
+        // setToolTip on item does not work
+        std::stringstream toolTip;
+        toolTip << "Edge '" << edge.source().attrib().getName()
+                << "' -> '"  << edge.target().attrib().getName();
+        item->setToolTip(QString::fromStdString(toolTip.str()));
+
+        return item;
+    }
+
+
+    void Scene::updateVertex(GuiGraph::Vertex& vertex)
+    {
+        QGraphicsEllipseItem* item = vertex.attrib().graphicsItem;
+        ARMARX_CHECK_NOT_NULL(item);
+
+        const Eigen::Matrix4d pose = vertex.attrib().getPose().cast<qreal>();
+
+        QColor color = vertex.attrib().highlighted ? colorSelected : colorDefault;
+        double lineWidth = vertex.attrib().highlighted ? lineWidthSelected : lineWidthDefault;
+
+        item->setPen(QPen {color});
+        item->setBrush(QBrush {color});
+        item->setRect(  pose(0, 3) - lineWidth * verticesScaleFactor / 2,
+                      - pose(1, 3) - lineWidth * verticesScaleFactor / 2,
+                      lineWidth * verticesScaleFactor,
+                      lineWidth * verticesScaleFactor);
+    }
+
+
+    void Scene::updateEdge(GuiGraph::Edge& edge)
+    {
+        QGraphicsLineItem* item = edge.attrib().graphicsItem;
+        ARMARX_CHECK_NOT_NULL(item);
+
+        Eigen::Matrix4d sourcePose = edge.source().attrib().getPose().cast<qreal>();
+        Eigen::Matrix4d targetPose = edge.target().attrib().getPose().cast<qreal>();
+
+        QColor color = edge.attrib().highlighted ? colorSelected : colorDefault;
+        double lineWidth = edge.attrib().highlighted ? lineWidthSelected : lineWidthDefault;
+
+        QPen pen {color};
+        pen.setWidthF(lineWidth * lineScaleFactor);
+
+        item->setPen(pen);
+        item->setLine(sourcePose(0, 3), - sourcePose(1, 3),
+                      targetPose(0, 3), - targetPose(1, 3));
+    }
+
+
+    void Scene::removeVertex(QGraphicsEllipseItem*& item)
+    {
+        removeItem(item);
+        delete item;
+        item = nullptr;
+    }
+
+
+    void Scene::removeEdge(QGraphicsLineItem*& item)
+    {
+        removeItem(item);
+        delete item;
+        item = nullptr;
+    }
+
+
+    GraphVisualizerGraphicsEllipseItem::GraphVisualizerGraphicsEllipseItem(
+            std::function<void(void)> onDoubleClicked,
+            qreal x, qreal y,
+            qreal width, qreal height,
+            QGraphicsItem* parent) :
+        QGraphicsEllipseItem {x, y, width, height, parent},
+        onDoubleClicked{onDoubleClicked}
+    {
+    }
+
+
+    GraphVisualizerGraphicsEllipseItem::~GraphVisualizerGraphicsEllipseItem()
+    {
+    }
+
+
+    void GraphVisualizerGraphicsEllipseItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent*)
+    {
+        onDoubleClicked();
+    }
+
+
+
+    GraphVisualizerGraphicsLineItem::GraphVisualizerGraphicsLineItem(
+            std::function<void(void)> onDoubleClicked,
+            qreal x1, qreal y1, qreal x2, qreal y2,
+            QGraphicsItem* parent) :
+        QGraphicsLineItem {x1, y1, x2, y2, parent},
+        onDoubleClicked{onDoubleClicked}
+    {
+    }
+
+
+    GraphVisualizerGraphicsLineItem::~GraphVisualizerGraphicsLineItem()
+    {
+    }
+
+
+    void GraphVisualizerGraphicsLineItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent*)
+    {
+        onDoubleClicked();
+    }
+
+}
+
diff --git a/source/armarx/navigation/gui-plugins/LocationGraphEditor/widgets/graph_scene/Scene.h b/source/armarx/navigation/gui-plugins/LocationGraphEditor/widgets/graph_scene/Scene.h
new file mode 100644
index 0000000000000000000000000000000000000000..f1b1ac37a186e289b5cea0cbcd23ced1b410f117
--- /dev/null
+++ b/source/armarx/navigation/gui-plugins/LocationGraphEditor/widgets/graph_scene/Scene.h
@@ -0,0 +1,118 @@
+#pragma once
+
+#include <armarx/navigation/gui-plugins/LocationGraphEditor/GuiGraph.h>
+#include <armarx/navigation/graph/Graph.h>
+
+#include <QGraphicsScene>
+#include <QGraphicsEllipseItem>
+#include <QGraphicsLineItem>
+
+#include <functional>
+
+
+namespace semrel
+{
+    struct ShapeID;
+}
+namespace armarx::nav::locgrapheditor::graph_scene
+{
+    class Scene : public QGraphicsScene
+    {
+        Q_OBJECT
+
+    public:
+
+        using QGraphicsScene::QGraphicsScene;
+
+        QGraphicsEllipseItem* addVertex(const graph::Graph::Vertex& vertex);
+        QGraphicsLineItem* addEdge(const graph::Graph::Edge& Edge);
+
+        void updateVertex(GuiGraph::Vertex& vertex);
+        void updateEdge(GuiGraph::Edge& edge);
+
+        void removeVertex(QGraphicsEllipseItem*& item);
+        void removeEdge(QGraphicsLineItem*& item);
+
+
+    public slots:
+
+
+    signals:
+
+        void vertexSelected(const semrel::ShapeID& vertexID);
+        void edgeSelected(const semrel::ShapeID& sourceID, const semrel::ShapeID& targetID);
+
+
+    public:
+
+        double lineWidthDefault = 5;
+        double lineWidthSelected = 10;
+
+        double sceneScaleFactor = 2;
+        double verticesScaleFactor = 3.0 * sceneScaleFactor;
+        double lineScaleFactor = 1.0 * sceneScaleFactor;
+
+        QColor colorDefault = QColor::fromRgb(128, 128, 255);
+        QColor colorSelected = QColor::fromRgb(255, 128, 0);
+
+    };
+
+
+
+    /**
+     * @brief Required to override the double click event.
+     * This is required to toggle the select state.
+     */
+    class GraphVisualizerGraphicsEllipseItem : public QGraphicsEllipseItem
+    {
+    public:
+
+        GraphVisualizerGraphicsEllipseItem(
+                std::function<void(void)> onDoubleClicked,
+                qreal x, qreal y, qreal width, qreal height,
+                QGraphicsItem* parent = nullptr);
+
+        ~GraphVisualizerGraphicsEllipseItem() override;
+
+
+    protected:
+
+        void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*) override;
+
+
+        std::function<void(void)> onDoubleClicked;
+
+    };
+
+
+
+    /**
+     * @brief Required to override the double click event.
+     * This is required to toggle the select state.
+     */
+    class GraphVisualizerGraphicsLineItem : public QGraphicsLineItem
+    {
+    public:
+
+        GraphVisualizerGraphicsLineItem(
+                std::function<void(void)> onDoubleClicked,
+                qreal x1, qreal y1,
+                qreal x2, qreal y2,
+                QGraphicsItem* parent = nullptr);
+
+        ~GraphVisualizerGraphicsLineItem() override;
+
+
+    protected:
+
+
+        void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*) override;
+
+
+        std::function<void(void)> onDoubleClicked;
+
+    };
+
+
+}
+
diff --git a/source/armarx/navigation/gui-plugins/LocationGraphEditor/widgets/graph_scene/Widget.cpp b/source/armarx/navigation/gui-plugins/LocationGraphEditor/widgets/graph_scene/Widget.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e05f7e6be1fb604701496271d440503085161655
--- /dev/null
+++ b/source/armarx/navigation/gui-plugins/LocationGraphEditor/widgets/graph_scene/Widget.cpp
@@ -0,0 +1,83 @@
+#include "Widget.h"
+#include "Scene.h"
+#include "ControlWidget.h"
+
+#include <QGraphicsView>
+#include <QHBoxLayout>
+#include <QLabel>
+#include <QVBoxLayout>
+
+
+namespace armarx::nav::locgrapheditor::graph_scene
+{
+
+    Widget::Widget()
+    {
+        _control = new ControlWidget();
+
+        _scene = new Scene();
+
+        _view = new QGraphicsView();
+        _view->setScene(_scene);
+        _view->setRenderHint(QPainter::Antialiasing, true);
+
+        int margin = 0;
+        this->setContentsMargins(margin, margin, margin, margin);
+        this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+
+        QHBoxLayout* header = new QHBoxLayout();
+        header->setSpacing(0);
+        header->addWidget(new QLabel("Graph"));
+        header->addStretch();
+        header->addWidget(_control);
+
+        QVBoxLayout* layout = new QVBoxLayout();
+        this->setLayout(layout);
+
+        layout->addLayout(header);
+        layout->addWidget(_view);
+
+
+        connect(_control, &ControlWidget::angleChanged,
+                this, &This::transform);
+        connect(_control, &ControlWidget::zoomChanged,
+                this, &This::transform);
+        connect(_control, &ControlWidget::zoomAutoAdjustRequested,
+                this, &This::autoAdjustZoom);
+
+
+        // Initial transform.
+        transform();
+    }
+
+
+    QGraphicsView* Widget::view()
+    {
+        return _view;
+    }
+
+
+    Scene* Widget::scene()
+    {
+        return _scene;
+    }
+
+
+    void Widget::transform()
+    {
+        double angle = _control->angle();
+        double zoom = _control->zoom();
+        _view->setTransform(QTransform::fromScale(zoom, zoom).rotate(angle));
+    }
+
+
+    void Widget::autoAdjustZoom()
+    {
+        int margin = 3;
+        QRectF rect = _scene->sceneRect() + QMargins(margin, margin, margin, margin);
+        _view->fitInView(rect, Qt::AspectRatioMode::KeepAspectRatio);
+        _control->setZoom(_view->transform().rotate(- _control->angle()).m11());
+    }
+
+}
+
diff --git a/source/armarx/navigation/gui-plugins/LocationGraphEditor/widgets/graph_scene/Widget.h b/source/armarx/navigation/gui-plugins/LocationGraphEditor/widgets/graph_scene/Widget.h
new file mode 100644
index 0000000000000000000000000000000000000000..c8a4b649e10ac5b7e2bde4d5a680ca36c731a2b4
--- /dev/null
+++ b/source/armarx/navigation/gui-plugins/LocationGraphEditor/widgets/graph_scene/Widget.h
@@ -0,0 +1,58 @@
+#pragma once
+
+#include <QWidget>
+
+class QGraphicsView;
+
+
+namespace armarx::nav::locgrapheditor::graph_scene
+{
+    class ControlWidget;
+    class Scene;
+
+
+    class Widget : public QWidget
+    {
+        Q_OBJECT
+        using This = Widget;
+
+
+    public:
+
+        Widget();
+
+        QGraphicsView* view();
+        Scene* scene();
+
+
+    public slots:
+
+        void transform();
+        void autoAdjustZoom();
+
+
+    private:
+
+        /// Some buttons and input fields.
+        ControlWidget* _control = nullptr;
+
+        /// The "canvas".
+        QGraphicsView* _view = nullptr;
+
+        /**
+         * @brief The scene displayed in the widget.
+         *
+         * For y coordinates (-y) is used to mirror the scene on the y axis.
+         * If (+y) would be used the graph displayed in the scene would not
+         * match the graph drawn to the debug layer.
+         */
+        Scene* _scene;
+
+
+        /// The view's rotation angle.
+        qreal _angle = 0;
+
+    };
+
+}
+