diff --git a/Source/Processors/Editors/VisualizerEditor.cpp b/Source/Processors/Editors/VisualizerEditor.cpp
index ccabfae1da3a11ca47ecb5e13d1803a8a358fc15..49f00c6d761f84ca0eb01a253cabb53de5320c31 100755
--- a/Source/Processors/Editors/VisualizerEditor.cpp
+++ b/Source/Processors/Editors/VisualizerEditor.cpp
@@ -114,8 +114,10 @@ VisualizerEditor::~VisualizerEditor()
 
     if (tabIndex > -1)
     {
-		AccessClass::getDataViewport()->destroyTab(tabIndex);
+        AccessClass::getDataViewport()->destroyTab(tabIndex);
     }
+    if (dataWindow != nullptr)
+        dataWindow->removeListener(this);
 
     deleteAllChildren();
 
@@ -149,13 +151,18 @@ void VisualizerEditor::updateVisualizer()
 
 }
 
+void VisualizerEditor::windowClosed()
+{
+
+}
+
 void VisualizerEditor::editorWasClicked()
 {
 
     if (tabIndex > -1)
     {
         std::cout << "Setting tab index to " << tabIndex << std::endl;
-		AccessClass::getDataViewport()->selectTab(tabIndex);
+        AccessClass::getDataViewport()->selectTab(tabIndex);
     }
 
 }
@@ -184,16 +191,18 @@ void VisualizerEditor::buttonClicked(Button* button)
         if (tabSelector->getToggleState() && windowSelector->getToggleState())
         {
             tabSelector->setToggleState(false, dontSendNotification);
-			AccessClass::getDataViewport()->destroyTab(tabIndex);
-            tabIndex = -1;
+            // AccessClass::getDataViewport()->destroyTab(tabIndex);
+            // tabIndex = -1;
+            removeTab(tabIndex);
         }
 
         if (dataWindow == nullptr) // have we created a window already?
         {
-
-            dataWindow = new DataWindow(windowSelector, tabText);
+            makeNewWindow();
             dataWindow->setContentNonOwned(canvas, false);
             dataWindow->setVisible(true);
+            // enable windowClosed() callback
+            dataWindow->addListener(this);
             //canvas->refreshState();
 
         }
@@ -228,15 +237,15 @@ void VisualizerEditor::buttonClicked(Button* button)
                 dataWindow->setVisible(false);
             }
 
-			tabIndex = AccessClass::getDataViewport()->addTabToDataViewport(tabText, canvas, this);
-
+            // tabIndex = AccessClass::getDataViewport()->addTabToDataViewport(tabText, canvas, this);
+            addTab(tabText, canvas);
 
         }
         else if (!tabSelector->getToggleState() && tabIndex > -1)
         {
-			AccessClass::getDataViewport()->destroyTab(tabIndex);
-            tabIndex = -1;
-
+            // AccessClass::getDataViewport()->destroyTab(tabIndex);
+            // tabIndex = -1;
+            removeTab(tabIndex);
         }
     }
 
@@ -313,6 +322,47 @@ void VisualizerEditor::loadCustomParameters(XmlElement* xml)
     }
 }
 
+void VisualizerEditor::makeNewWindow()
+{
+    dataWindow = new DataWindow(windowSelector, tabText);
+}
+
+void VisualizerEditor::addWindowListener(DataWindow* dw, DataWindow::Listener* newListener) /* static method */
+{
+    if (dw != nullptr && newListener != nullptr){
+        dw->addListener(newListener);
+    }
+}
+
+void VisualizerEditor::removeWindowListener(DataWindow* dw, DataWindow::Listener* oldListener) /* static method */
+{
+    if (dw != nullptr && oldListener != nullptr){
+        dw->removeListener(oldListener);
+    }
+}
+
+Component* VisualizerEditor::getActiveTabContentComponent() const
+{
+    return AccessClass::getDataViewport()->getCurrentContentComponent();
+}
+
+void VisualizerEditor::setActiveTabId(int tindex)
+{
+    AccessClass::getDataViewport()->selectTab(tindex);
+}
+
+void VisualizerEditor::removeTab(int tindex)
+{
+    AccessClass::getDataViewport()->destroyTab(tindex);
+    tabIndex = -1;
+}
+
+int VisualizerEditor::addTab(String tab_text, Visualizer* vis_canvas)
+{
+    tabText = tab_text;
+    tabIndex = AccessClass::getDataViewport()->addTabToDataViewport(tab_text, vis_canvas, this);
+    return tabIndex;
+}
 
 void VisualizerEditor::saveVisualizerParameters(XmlElement* xml)
 {
diff --git a/Source/Processors/Editors/VisualizerEditor.h b/Source/Processors/Editors/VisualizerEditor.h
index dbf876746d515fc7bca0388db260331e6fba27d3..fab530133803f9ce957d557bb75d73bed440e964 100755
--- a/Source/Processors/Editors/VisualizerEditor.h
+++ b/Source/Processors/Editors/VisualizerEditor.h
@@ -65,6 +65,7 @@ private:
 */
 
 class PLUGIN_API VisualizerEditor : public GenericEditor
+                                  , public DataWindow::Listener
 {
 public:
     /**
@@ -84,17 +85,17 @@ public:
     VisualizerEditor(GenericProcessor* processor, bool useDefaultParameterEditors);
     ~VisualizerEditor();
 
-	/**
+    /**
      * @brief      This method handles the button evnets which open visualizer in a tab or window.
      * @warning    Do not override this function unless you call ``VisualizerEditor::buttonClicked``
      *             somewhere!
      */
     void buttonClicked(Button* button);
-	
-	/**
+    
+    /**
      * @brief      All additional buttons that you create _for the editor_ should be handled here.
      */
-	virtual void buttonEvent(Button* button);
+    virtual void buttonEvent(Button* button);
 
     /**
      * @brief      Creates a new canvas. This is like a factory method and must be defined in your sub-class.
@@ -107,6 +108,7 @@ public:
     void editorWasClicked();
 
     void updateVisualizer();
+    virtual void windowClosed();
 
     void saveCustomParameters(XmlElement* xml);
     void loadCustomParameters(XmlElement* xml);
@@ -120,17 +122,84 @@ public:
 
     String tabText;
 
-private:
+protected: // these should be available to sub-classes if needed.
+    
+    /**
+     * @brief      Creates a new DataWindow using the windowSelector (button)
+     *             and ``tabText``. The new object is stored in (and owned by)
+     *             VisualizerEditor::dataWindow.
+     * @details    Use this to make a new DataWindow. If needed, you can
+     *             transfer ownership of the new object from
+     *             VisualizerEditor::dataWindow to _your_ own ScopedPointer.
+     * @note       This method provides an interface to DataWindow, DataWindow
+     *             methods cannot be defined in derivations (ie, plugins).
+     */
+    void makeNewWindow();
 
-    void initializeSelectors();
-    bool isPlaying;
+    /**
+     * @brief      Adds a closeWindow listener for dw.
+     *
+     * @param      dw           The datawindow
+     * @param      newListener  The new listener
+     * 
+     * @note       This method provides an interface to DataWindow, DataWindow
+     *             methods cannot be defined in derivations (ie, plugins).
+     */
+    static void addWindowListener(DataWindow* dw, DataWindow::Listener* newListener);
+
+    /**
+     * @brief      Removes a closeWindow listener for dw.
+     *
+     * @param      dw           The datawindow
+     * @param      oldListener  The old listener
+     *
+     * @note       This method provides an interface to DataWindow, DataWindow
+     *             methods cannot be defined in derivations (ie, plugins).
+     */
+    static void removeWindowListener(DataWindow* dw, DataWindow::Listener* oldListener);
+
+    /**
+     * @brief      Use this to efficiently compare or find what is on the
+     *             currently active tab.
+     *
+     * @return     The active tab content Component.
+     */
+    Component* getActiveTabContentComponent() const;
 
+    /**
+     * @brief      Selects the specified _tab_ in the DataViewport.
+     *
+     * @param[in]  tindex  The index which was returned by VisualizerEditor::addTab
+     */
+    void setActiveTabId(int tindex);
+
+    /**
+     * @brief      Remove the specified tab from DataViewport.
+     *
+     * @param[in]  tindex  The index which was returned by VisualizerEditor::addTab
+     */
+    void removeTab(int tindex);
+
+    /**
+     * @brief      Adds a new tab to the DataViewport.
+     *
+     * @param[in]  tab_text    The tab text
+     * @param      vis_canvas  The content Visualizer (Canvas) Component for this tab.
+     *
+     * @return     The identifier token for this tab. You must provide this
+     *             identifier to access/remove this tab.
+     */
+    int addTab(String tab_text, Visualizer* vis_canvas);
+
+    bool isPlaying; /**< Acquisition status flag */
+
+    // So that we can override buttonClick. That's not possible if these are private.
     SelectorButton* windowSelector;
     SelectorButton* tabSelector;
-
     int tabIndex;
 
-
+private:
+    void initializeSelectors();
 
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(VisualizerEditor);
 
diff --git a/Source/Processors/Visualization/DataWindow.cpp b/Source/Processors/Visualization/DataWindow.cpp
index 62746822919dc2cb4d4895621c1ed21912e3c8f7..59099227ed83d34b933003cd6d5347070b30af7b 100755
--- a/Source/Processors/Visualization/DataWindow.cpp
+++ b/Source/Processors/Visualization/DataWindow.cpp
@@ -27,8 +27,8 @@
 DataWindow::DataWindow(Button* cButton, String name)
     : DocumentWindow(name,
                      Colours::black,
-                     DocumentWindow::allButtons),
-    controlButton(cButton)
+                     DocumentWindow::allButtons)
+    , controlButton(cButton)
 
 {
     centreWithSize(800,500);
@@ -46,4 +46,23 @@ void DataWindow::closeButtonPressed()
     setContentNonOwned(0,false);
     setVisible(false);
     controlButton->setToggleState(false,dontSendNotification);
+    // with the BailOutChecker, it is safe to "delete" a DataWindow instance
+    // from this callback/listener. This would (typically) not be done, because instances
+    // of DataWindow are (typically) "owned" by Editors, and will be deleted
+    // when the Editor dies.
+    //
+    Component::BailOutChecker checker (this);
+    if (! checker.shouldBailOut()){
+        closeWindowListeners.callChecked (checker, &DataWindow::Listener::windowClosed);
+    }
+}
+
+void DataWindow::addListener (DataWindow::Listener* const newListener)
+{
+    closeWindowListeners.add (newListener);
+}
+
+void DataWindow::removeListener (DataWindow::Listener* const listener)
+{
+    closeWindowListeners.remove (listener);
 }
diff --git a/Source/Processors/Visualization/DataWindow.h b/Source/Processors/Visualization/DataWindow.h
index e068e54118f0d38130bd8ec3d7a990bde1e1896b..6a4f7890de49b18ba72e306dea9178870c9e78c7 100755
--- a/Source/Processors/Visualization/DataWindow.h
+++ b/Source/Processors/Visualization/DataWindow.h
@@ -39,14 +39,36 @@ class DataWindow : public DocumentWindow
 public:
     DataWindow(Button* button, String name);
     ~DataWindow();
-
+    
     void closeButtonPressed();
+    
+    class Listener
+    {
+    public:
+        /** Destructor. */
+        virtual ~Listener()  {}
+
+        /** Called when the window is closed. */
+        virtual void windowClosed () = 0;
+    };
+
+    /**
+     * @brief      Registers a listener to receive event when this is closed. If
+     *             the listener is already registered, this will not register it
+     *             again.
+     */
+    void addListener (Listener* newListener);
+
+    /**
+     * @brief      Removes a previously-registered DataWindow listener
+     */
+    void removeListener (Listener* listener);
 
 private:
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(DataWindow);
 
     Button* controlButton;
-
+    ListenerList<Listener> closeWindowListeners;
 };