diff --git a/common/status_popup.cpp b/common/status_popup.cpp
index 24898ff8c0..000982ee06 100644
--- a/common/status_popup.cpp
+++ b/common/status_popup.cpp
@@ -141,86 +141,3 @@ void STATUS_TEXT_POPUP::SetTextColor( const wxColour& aColor )
 }
 
 
-STATUS_MIN_MAX_POPUP::STATUS_MIN_MAX_POPUP( EDA_DRAW_FRAME* aFrame ) :
-        STATUS_POPUP( aFrame ),
-        m_frame( aFrame ),
-        m_min( 0.0 ),
-        m_max( 0.0 )
-{
-    m_icon = new wxStaticBitmap( m_panel, wxID_ANY, KiBitmap( BITMAPS::checked_ok ),
-                                 wxDefaultPosition, wxSize( 12, 12 ) );
-
-    m_currentLabel = new wxStaticText( m_panel, wxID_ANY, _( "current" ) );
-    wxStaticText* minLabel = new wxStaticText( m_panel, wxID_ANY, _( "min" ) );
-    wxStaticText* maxLabel = new wxStaticText( m_panel, wxID_ANY, _( "max" ) );
-
-    wxFont infoFont = KIUI::GetStatusFont( this );
-    m_currentLabel->SetFont( infoFont );
-    minLabel->SetFont( infoFont );
-    maxLabel->SetFont( infoFont );
-
-    m_currentText = new wxStaticText( m_panel, wxID_ANY, wxEmptyString );
-    m_minText = new wxStaticText( m_panel, wxID_ANY, wxEmptyString );
-    m_maxText = new wxStaticText( m_panel, wxID_ANY, wxEmptyString );
-
-    wxBoxSizer* currentSizer = new wxBoxSizer( wxVERTICAL );
-    currentSizer->Add( m_currentLabel, 0, 0, 5 );
-    currentSizer->Add( m_currentText, 0, 0, 5 );
-
-    wxBoxSizer* minSizer = new wxBoxSizer( wxVERTICAL );
-    minSizer->Add( minLabel, 0, 0, 5 );
-    minSizer->Add( m_minText, 0, 0, 5 );
-
-    wxBoxSizer* maxSizer = new wxBoxSizer( wxVERTICAL );
-    maxSizer->Add( maxLabel, 0, 0, 5 );
-    maxSizer->Add( m_maxText, 0, 0, 5 );
-
-    m_topSizer->Add( currentSizer, 0, wxLEFT | wxRIGHT, 3 );
-    m_topSizer->Add( m_icon, 0, wxALL | wxALIGN_BOTTOM | wxRESERVE_SPACE_EVEN_IF_HIDDEN, 1 );
-    m_topSizer->Add( minSizer, 0, wxLEFT | wxRIGHT, 3 );
-    m_topSizer->Add( maxSizer, 0, wxLEFT | wxRIGHT, 3 );
-}
-
-
-void STATUS_MIN_MAX_POPUP::SetMinMax( double aMin, double aMax )
-{
-    m_min = aMin;
-    m_minText->SetLabel( m_frame->MessageTextFromValue( m_min, false ) );
-    m_max = aMax;
-    m_maxText->SetLabel( m_frame->MessageTextFromValue( m_max, false ) );
-}
-
-
-void STATUS_MIN_MAX_POPUP::ClearMinMax()
-{
-    m_min = 0;
-    m_minText->SetLabel( wxT( "---" ) );
-    m_max = std::numeric_limits<double>::max();
-    m_maxText->SetLabel( wxT( "---" ) );
-}
-
-
-void STATUS_MIN_MAX_POPUP::SetCurrent( double aCurrent, const wxString& aLabel )
-{
-    m_currentLabel->SetLabel( aLabel );
-    m_currentText->SetLabel( m_frame->MessageTextFromValue( aCurrent ) );
-    m_icon->Show( aCurrent >= m_min && aCurrent <= m_max );
-
-    wxColour normal = wxSystemSettings::GetColour( wxSYS_COLOUR_BTNTEXT );
-
-    // Determine the background color first and choose a contrasting value
-    COLOR4D bg = GetBackgroundColour();
-    COLOR4D red;
-    double  bg_h, bg_s, bg_l;
-    bg.ToHSL( bg_h, bg_s, bg_l );
-    red.FromHSL( 0, 1.0, bg_l < 0.5 ? 0.7 : 0.3 );
-
-    m_minText->SetForegroundColour( aCurrent < m_min ? red.ToColour() : normal );
-    m_maxText->SetForegroundColour( aCurrent > m_max ? red.ToColour() : normal );
-
-    m_topSizer->Layout();
-    updateSize();
-
-    Refresh();
-    Update();
-}
\ No newline at end of file
diff --git a/include/status_popup.h b/include/status_popup.h
index 85f12ba259..4eb4ae30cc 100644
--- a/include/status_popup.h
+++ b/include/status_popup.h
@@ -105,31 +105,4 @@ protected:
 };
 
 
-/**
- * Extension of #STATUS_POPUP for displaying a value with min and max.
- */
-class STATUS_MIN_MAX_POPUP : public STATUS_POPUP
-{
-public:
-    STATUS_MIN_MAX_POPUP( EDA_DRAW_FRAME* aFrame );
-    virtual ~STATUS_MIN_MAX_POPUP() {}
-
-    void SetMinMax( double aMin, double aMax );
-    void ClearMinMax();
-
-    void SetCurrent( double aCurrent, const wxString& aLabel );
-
-protected:
-    EDA_DRAW_FRAME* m_frame;
-    double          m_min;
-    double          m_max;
-
-private:
-    wxStaticText*   m_currentLabel;
-    wxStaticText*   m_currentText;
-    wxStaticText*   m_minText;
-    wxStaticText*   m_maxText;
-    wxStaticBitmap* m_icon;
-};
-
 #endif /* __STATUS_POPUP_H_*/
diff --git a/pcbnew/generators/pcb_tuning_pattern.cpp b/pcbnew/generators/pcb_tuning_pattern.cpp
index c5ac0ebc1a..560fd3ab68 100644
--- a/pcbnew/generators/pcb_tuning_pattern.cpp
+++ b/pcbnew/generators/pcb_tuning_pattern.cpp
@@ -29,10 +29,10 @@
 #include <magic_enum.hpp>
 
 #include <wx/debug.h>
+#include <gal/graphics_abstraction_layer.h>
 #include <geometry/shape_circle.h>
 #include <kiplatform/ui.h>
 #include <dialogs/dialog_unit_entry.h>
-#include <status_popup.h>
 #include <collectors.h>
 #include <scoped_set_reset.h>
 
@@ -50,6 +50,7 @@
 #include <tools/zone_filler_tool.h>
 
 #include <preview_items/draw_context.h>
+#include <preview_items/preview_utils.h>
 #include <view/view.h>
 
 #include <router/pns_dp_meander_placer.h>
@@ -60,6 +61,7 @@
 #include <router/pns_arc.h>
 #include <router/pns_solid.h>
 #include <router/pns_topology.h>
+#include <router/router_preview_item.h>
 
 #include <dialogs/dialog_tuning_pattern_properties.h>
 
@@ -72,6 +74,112 @@ enum LENGTH_TUNING_MODE
 };
 
 
+class TUNING_STATUS_VIEW_ITEM : public EDA_ITEM
+{
+public:
+    TUNING_STATUS_VIEW_ITEM( PCB_BASE_EDIT_FRAME* aFrame ) :
+            EDA_ITEM( NOT_USED ),    // Never added to anything - just a preview
+            m_frame( aFrame )
+    { }
+
+    wxString GetClass() const override { return wxT( "TUNING_STATUS" ); }
+
+#if defined(DEBUG)
+    void Show( int nestLevel, std::ostream& os ) const override {}
+#endif
+
+    VECTOR2I GetPosition() const override { return m_pos; }
+    void     SetPosition( const VECTOR2I& aPos ) override { m_pos = aPos; };
+
+    void SetMinMax( double aMin, double aMax )
+    {
+        m_min = aMin;
+        m_minText = m_frame->MessageTextFromValue( m_min, false );
+        m_max = aMax;
+        m_maxText = m_frame->MessageTextFromValue( m_max, false );
+    }
+
+    void ClearMinMax()
+    {
+        m_min = 0.0;
+        m_minText = wxT( "---" );
+        m_max = std::numeric_limits<double>::max();
+        m_maxText = wxT( "---" );
+    }
+
+    void SetCurrent( double aCurrent, const wxString& aLabel )
+    {
+        m_current = aCurrent;
+        m_currentText = m_frame->MessageTextFromValue( aCurrent );
+        m_currentLabel = aLabel;
+    }
+
+    const BOX2I ViewBBox() const override
+    {
+        BOX2I tmp;
+
+        // this is an edit-time artefact; no reason to try and be smart with the bounding box
+        // (besides, we can't tell the text extents without a view to know what the scale is)
+        tmp.SetMaximum();
+        return tmp;
+    }
+
+    void ViewGetLayers( int aLayers[], int& aCount ) const override
+    {
+        aLayers[0] = LAYER_SELECT_OVERLAY;
+        aLayers[1] = LAYER_GP_OVERLAY;
+        aCount = 2;
+    }
+
+    void ViewDraw( int aLayer, KIGFX::VIEW* aView ) const override
+    {
+        KIGFX::GAL*      gal = aView->GetGAL();
+        RENDER_SETTINGS* rs = aView->GetPainter()->GetSettings();
+        bool             drawingDropShadows = ( aLayer == LAYER_GP_OVERLAY );
+
+        gal->PushDepth();
+        gal->SetLayerDepth( gal->GetMinDepth() );
+
+        if( drawingDropShadows )
+            gal->SetStrokeColor( KIGFX::PREVIEW::GetShadowColor( gal->GetStrokeColor() ) );
+        else
+            gal->SetStrokeColor( rs->GetLayerColor( LAYER_AUX_ITEMS ) );
+
+        std::vector<wxString> strings;
+        wxString status;
+
+        if( m_current < m_min )
+            status = _( "(too short)" );
+        else if( m_current > m_max )
+            status = _( "(too long)" );
+
+        strings.push_back( wxString::Format( wxT( "%s: %s %s" ),
+                                             m_currentLabel,
+                                             m_currentText,
+                                             status ) );
+
+        strings.push_back( wxString::Format( _( "Min: %s" ), m_minText ) );
+        strings.push_back( wxString::Format( _( "Max: %s" ), m_maxText ) );
+
+        KIGFX::PREVIEW::DrawTextNextToCursor( aView, GetPosition(), { -1 , 1 }, strings,
+                                              drawingDropShadows );
+
+        gal->PopDepth();
+    }
+
+protected:
+    EDA_DRAW_FRAME* m_frame;
+    VECTOR2I        m_pos;
+    double          m_min;
+    double          m_max;
+    double          m_current;
+    wxString        m_currentLabel;
+    wxString        m_currentText;
+    wxString        m_minText;
+    wxString        m_maxText;
+};
+
+
 class PCB_TUNING_PATTERN : public PCB_GENERATOR
 {
 public:
@@ -240,8 +348,8 @@ public:
 
     void ShowPropertiesDialog( PCB_BASE_EDIT_FRAME* aEditFrame ) override;
 
-    void UpdateStatus( GENERATOR_TOOL* aTool, PCB_BASE_EDIT_FRAME* aFrame,
-                       STATUS_MIN_MAX_POPUP* aPopup ) override;
+    std::vector<EDA_ITEM*> GetPreviewItems( GENERATOR_TOOL* aTool, PCB_BASE_EDIT_FRAME* aFrame,
+                                            bool aStatusOnly = false ) override;
 
     void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
@@ -1681,32 +1789,49 @@ void PCB_TUNING_PATTERN::ShowPropertiesDialog( PCB_BASE_EDIT_FRAME* aEditFrame )
 }
 
 
-void PCB_TUNING_PATTERN::UpdateStatus( GENERATOR_TOOL* aTool, PCB_BASE_EDIT_FRAME* aFrame,
-                                       STATUS_MIN_MAX_POPUP* aPopup )
+std::vector<EDA_ITEM*> PCB_TUNING_PATTERN::GetPreviewItems( GENERATOR_TOOL* aTool,
+                                                            PCB_BASE_EDIT_FRAME* aFrame,
+                                                            bool aStatusOnly )
 {
-    auto* placer = dynamic_cast<PNS::MEANDER_PLACER_BASE*>( aTool->Router()->Placer() );
+    std::vector<EDA_ITEM*> previewItems;
+    KIGFX::VIEW*           view = aFrame->GetCanvas()->GetView();
 
-    if( !placer )
-        return;
+    if( auto* placer = dynamic_cast<PNS::MEANDER_PLACER_BASE*>( aTool->Router()->Placer() ) )
+    {
+        if( !aStatusOnly )
+        {
+            PNS::ITEM_SET items = placer->TunedPath();
 
-    if( m_unconstrained )
-    {
-        aPopup->ClearMinMax();
-    }
-    else if( m_tuningMode == DIFF_PAIR_SKEW )
-    {
-        aPopup->SetMinMax( m_settings.m_targetSkew.Min(), m_settings.m_targetSkew.Max() );
-    }
-    else
-    {
-        aPopup->SetMinMax( (double) m_settings.m_targetLength.Min(),
-                           (double) m_settings.m_targetLength.Max() );
+            for( PNS::ITEM* item : items )
+                previewItems.push_back( new ROUTER_PREVIEW_ITEM( item, view, true ) );
+        }
+
+        TUNING_STATUS_VIEW_ITEM* statusItem = new TUNING_STATUS_VIEW_ITEM( aFrame );
+
+        if( m_unconstrained )
+        {
+            statusItem->ClearMinMax();
+        }
+        else if( m_tuningMode == DIFF_PAIR_SKEW )
+        {
+            statusItem->SetMinMax( m_settings.m_targetSkew.Min(), m_settings.m_targetSkew.Max() );
+        }
+        else
+        {
+            statusItem->SetMinMax( (double) m_settings.m_targetLength.Min(),
+                                   (double) m_settings.m_targetLength.Max() );
+        }
+
+        if( m_tuningMode == DIFF_PAIR_SKEW )
+            statusItem->SetCurrent( (double) placer->TuningResult(), _( "Skew" ) );
+        else
+            statusItem->SetCurrent( (double) placer->TuningResult(), _( "Length" ) );
+
+        statusItem->SetPosition( aFrame->GetToolManager()->GetMousePosition() );
+        previewItems.push_back( statusItem );
     }
 
-    if( m_tuningMode == DIFF_PAIR_SKEW )
-        aPopup->SetCurrent( (double) placer->TuningResult(), _( "current skew" ) );
-    else
-        aPopup->SetCurrent( (double) placer->TuningResult(), _( "current length" ) );
+    return previewItems;
 }
 
 
@@ -1912,20 +2037,22 @@ int DRAWING_TOOL::PlaceTuningPattern( const TOOL_EVENT& aEvent )
 
                 if( dummyPattern )
                 {
-                    m_statusPopup->Popup();
-                    canvas()->SetStatusPopup( m_statusPopup.get() );
-
                     dummyPattern->EditStart( generatorTool, m_board, m_frame, nullptr );
                     dummyPattern->Update( generatorTool, m_board, m_frame, nullptr );
 
-                    dummyPattern->UpdateStatus( generatorTool, m_frame, m_statusPopup.get() );
-                    m_statusPopup->Move( KIPLATFORM::UI::GetMousePosition() + wxPoint( 20, 20 ) );
+                    m_preview.FreeItems();
+
+                    for( EDA_ITEM* item : dummyPattern->GetPreviewItems( generatorTool, m_frame ) )
+                        m_preview.Add( item );
 
                     generatorTool->Router()->StopRouting();
+
+                    m_view->Update( &m_preview );
                 }
                 else
                 {
-                    m_statusPopup->Hide();
+                    m_preview.FreeItems();
+                    m_view->Update( &m_preview );
                 }
             };
 
@@ -1937,13 +2064,7 @@ int DRAWING_TOOL::PlaceTuningPattern( const TOOL_EVENT& aEvent )
                     m_tuningPattern->EditStart( generatorTool, m_board, m_frame, nullptr );
                     m_tuningPattern->Update( generatorTool, m_board, m_frame, nullptr );
 
-                    m_statusPopup->Popup();
-                    canvas()->SetStatusPopup( m_statusPopup.get() );
-
                     m_view->Update( &m_preview );
-
-                    m_tuningPattern->UpdateStatus( generatorTool, m_frame, m_statusPopup.get() );
-                    m_statusPopup->Move( KIPLATFORM::UI::GetMousePosition() + wxPoint( 20, 20 ) );
                 }
             };
 
@@ -1962,8 +2083,6 @@ int DRAWING_TOOL::PlaceTuningPattern( const TOOL_EVENT& aEvent )
                 // First click already made; clean up tuning pattern preview
                 m_tuningPattern->EditRevert( generatorTool, m_board, m_frame, nullptr );
 
-                m_preview.Clear();
-
                 delete m_tuningPattern;
                 m_tuningPattern = nullptr;
             }
@@ -1989,18 +2108,10 @@ int DRAWING_TOOL::PlaceTuningPattern( const TOOL_EVENT& aEvent )
                 if( collector.GetCount() > 1 )
                     selectionTool->GuessSelectionCandidates( collector, cursorPos );
 
-                BOARD_ITEM* item = collector.GetCount() == 1 ? collector[ 0 ] : nullptr;
-
-                if( !m_pickerItem )
-                {
-                    m_pickerItem = static_cast<BOARD_CONNECTED_ITEM*>( item );
-                    generatorTool->HighlightNets( m_pickerItem );
-                }
+                if( collector.GetCount() == 1 )
+                    m_pickerItem = static_cast<BOARD_CONNECTED_ITEM*>( collector[0] );
                 else
-                {
-                    m_pickerItem = static_cast<BOARD_CONNECTED_ITEM*>( item );
-                    generatorTool->UpdateHighlightedNets( m_pickerItem );
-                }
+                    m_pickerItem = nullptr;
 
                 updateHoverStatus();
             }
@@ -2018,7 +2129,7 @@ int DRAWING_TOOL::PlaceTuningPattern( const TOOL_EVENT& aEvent )
             {
                 // First click; create a tuning pattern
 
-                generatorTool->HighlightNets( nullptr );
+                m_preview.FreeItems();
 
                 m_frame->SetActiveLayer( m_pickerItem->GetLayer() );
                 m_tuningPattern = PCB_TUNING_PATTERN::CreateNew( generatorTool, m_frame,
@@ -2039,7 +2150,7 @@ int DRAWING_TOOL::PlaceTuningPattern( const TOOL_EVENT& aEvent )
                         m_tuningPattern->SetEnd( closestPt );
                     }
 
-                    m_preview.Add( m_tuningPattern );
+                    m_preview.Add( m_tuningPattern->Clone() );
                 }
             }
             else if( m_pickerItem && m_tuningPattern )
@@ -2107,12 +2218,7 @@ int DRAWING_TOOL::PlaceTuningPattern( const TOOL_EVENT& aEvent )
     controls->ShowCursor( false );
     m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
 
-    canvas()->SetStatusPopup( nullptr );
-    m_statusPopup->Hide();
-
-    generatorTool->HighlightNets( nullptr );
-
-    m_preview.Clear();
+    m_preview.FreeItems();
     m_view->Remove( &m_preview );
 
     m_frame->GetCanvas()->Refresh();
diff --git a/pcbnew/pcb_generator.cpp b/pcbnew/pcb_generator.cpp
index aac6291078..a0d1fb1493 100644
--- a/pcbnew/pcb_generator.cpp
+++ b/pcbnew/pcb_generator.cpp
@@ -71,6 +71,14 @@ bool PCB_GENERATOR::Update( GENERATOR_TOOL* aTool, BOARD* aBoard, PCB_BASE_EDIT_
 }
 
 
+std::vector<EDA_ITEM*> PCB_GENERATOR::GetPreviewItems( GENERATOR_TOOL* aTool,
+                                                       PCB_BASE_EDIT_FRAME* aFrame,
+                                                       bool aStatusOnly )
+{
+    return std::vector<EDA_ITEM*>();
+}
+
+
 bool PCB_GENERATOR::MakeEditPoints( std::shared_ptr<EDIT_POINTS> aEditPoints ) const
 {
     return true;
diff --git a/pcbnew/pcb_generator.h b/pcbnew/pcb_generator.h
index 553cea1ac7..c6864e21fc 100644
--- a/pcbnew/pcb_generator.h
+++ b/pcbnew/pcb_generator.h
@@ -63,6 +63,10 @@ public:
     virtual bool Update( GENERATOR_TOOL* aTool, BOARD* aBoard, PCB_BASE_EDIT_FRAME* aFrame,
                          BOARD_COMMIT* aCommit );
 
+    virtual std::vector<EDA_ITEM*> GetPreviewItems( GENERATOR_TOOL* aTool,
+                                                    PCB_BASE_EDIT_FRAME* aFrame,
+                                                    bool aStatusOnly = false );
+
     virtual bool MakeEditPoints( std::shared_ptr<EDIT_POINTS> aEditPoints ) const;
 
     virtual bool UpdateFromEditPoints( std::shared_ptr<EDIT_POINTS> aEditPoints,
@@ -93,9 +97,6 @@ public:
 
     virtual void ShowPropertiesDialog( PCB_BASE_EDIT_FRAME* aEditFrame ) {};
 
-    virtual void UpdateStatus( GENERATOR_TOOL* aTool, PCB_BASE_EDIT_FRAME* aFrame,
-                               STATUS_MIN_MAX_POPUP* aPopup ) {};
-
     wxString GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const override;
 
     virtual wxString GetPluralName() const = 0;
diff --git a/pcbnew/router/pns_dp_meander_placer.cpp b/pcbnew/router/pns_dp_meander_placer.cpp
index 5173af0fc4..093dd42837 100644
--- a/pcbnew/router/pns_dp_meander_placer.cpp
+++ b/pcbnew/router/pns_dp_meander_placer.cpp
@@ -464,6 +464,20 @@ const ITEM_SET DP_MEANDER_PLACER::Traces()
 }
 
 
+const ITEM_SET DP_MEANDER_PLACER::TunedPath()
+{
+    ITEM_SET lines;
+
+    for( ITEM* item : m_tunedPathN )
+        lines.Add( item );
+
+    for( ITEM* item : m_tunedPathP )
+        lines.Add( item );
+
+    return lines;
+}
+
+
 const VECTOR2I& DP_MEANDER_PLACER::CurrentStart() const
 {
     return m_currentStart;
diff --git a/pcbnew/router/pns_dp_meander_placer.h b/pcbnew/router/pns_dp_meander_placer.h
index 71345b4870..6b65d3acc0 100644
--- a/pcbnew/router/pns_dp_meander_placer.h
+++ b/pcbnew/router/pns_dp_meander_placer.h
@@ -93,6 +93,8 @@ public:
 
     const ITEM_SET Traces() override;
 
+    const ITEM_SET TunedPath() override;
+
     /// @copydoc PLACEMENT_ALGO::CurrentStart()
     const VECTOR2I& CurrentStart() const override;
 
diff --git a/pcbnew/router/pns_meander_placer.cpp b/pcbnew/router/pns_meander_placer.cpp
index 20fb92ec55..673dbcef31 100644
--- a/pcbnew/router/pns_meander_placer.cpp
+++ b/pcbnew/router/pns_meander_placer.cpp
@@ -278,6 +278,11 @@ const ITEM_SET MEANDER_PLACER::Traces()
     return ITEM_SET( &m_currentTrace );
 }
 
+const ITEM_SET MEANDER_PLACER::TunedPath()
+{
+    return m_tunedPath;
+}
+
 const VECTOR2I& MEANDER_PLACER::CurrentStart() const
 {
     return m_currentStart;
diff --git a/pcbnew/router/pns_meander_placer.h b/pcbnew/router/pns_meander_placer.h
index 3edeeb1ad2..89f25932c8 100644
--- a/pcbnew/router/pns_meander_placer.h
+++ b/pcbnew/router/pns_meander_placer.h
@@ -73,6 +73,9 @@ public:
     /// @copydoc PLACEMENT_ALGO::Traces()
     const ITEM_SET Traces() override;
 
+    /// @copydoc PNS_MEANDER_PLACER_BASE::TunedPath()
+    const ITEM_SET TunedPath() override;
+
     /// @copydoc PLACEMENT_ALGO::CurrentStart()
     const VECTOR2I& CurrentStart() const override;
 
diff --git a/pcbnew/router/pns_meander_placer_base.h b/pcbnew/router/pns_meander_placer_base.h
index 77cb45d144..f85e6e1b28 100644
--- a/pcbnew/router/pns_meander_placer_base.h
+++ b/pcbnew/router/pns_meander_placer_base.h
@@ -114,6 +114,8 @@ public:
 
     int GetTotalPadToDieLength( const LINE& aLine ) const;
 
+    virtual const ITEM_SET TunedPath() = 0;
+
 protected:
     /**
      * Take a set of meanders in \a aTuned and tunes their length to extend the original line
diff --git a/pcbnew/router/router_preview_item.cpp b/pcbnew/router/router_preview_item.cpp
index c2d4df5bca..07bea30ff9 100644
--- a/pcbnew/router/router_preview_item.cpp
+++ b/pcbnew/router/router_preview_item.cpp
@@ -38,11 +38,13 @@
 using namespace KIGFX;
 
 
-ROUTER_PREVIEW_ITEM::ROUTER_PREVIEW_ITEM( const PNS::ITEM* aItem, KIGFX::VIEW* aView ) :
+ROUTER_PREVIEW_ITEM::ROUTER_PREVIEW_ITEM( const PNS::ITEM* aItem, KIGFX::VIEW* aView,
+                                          bool aIsHoverItem ) :
     EDA_ITEM( NOT_USED ),
     m_view( aView ),
     m_shape( nullptr ),
-    m_hole( nullptr )
+    m_hole( nullptr ),
+    m_isHoverItem( aIsHoverItem )
 {
     BOARD_ITEM* boardItem = aItem ? aItem->BoardItem() : nullptr;
 
@@ -94,6 +96,7 @@ ROUTER_PREVIEW_ITEM::ROUTER_PREVIEW_ITEM( const SHAPE& aShape, KIGFX::VIEW* aVie
     m_width = 0;
     m_depth = 0;
     m_isHeadTrace = false;
+    m_isHoverItem = false;
 }
 
 
@@ -175,6 +178,9 @@ void ROUTER_PREVIEW_ITEM::Update( const PNS::ITEM* aItem )
 
     if( aItem->Marker() & PNS::MK_VIOLATION )
         m_color = COLOR4D( 0, 1, 0, 1 );
+
+    if( m_isHoverItem )
+        m_color = m_color.WithAlpha( 1.0 );
 }
 
 
@@ -501,34 +507,14 @@ const COLOR4D ROUTER_PREVIEW_ITEM::getLayerColor( int aLayer ) const
     COLOR4D color = settings->GetLayerColor( aLayer );
 
     if( m_isHeadTrace )
-    {
         return color.Saturate( 1.0 );
-    }
+    else if( m_isHoverItem )
+        return color.Brightened( 0.7 );
 
     return color;
 }
 
 
-const COLOR4D ROUTER_PREVIEW_ITEM::assignColor( int aStyle ) const
-{
-    COLOR4D color;
-
-    switch( aStyle )
-    {
-    case 0:  color = COLOR4D( 0, 1, 0, 1 );       break;
-    case 1:  color = COLOR4D( 1, 0, 0, 1 );       break;
-    case 2:  color = COLOR4D( 1, 1, 0, 1 );       break;
-    case 3:  color = COLOR4D( 0, 0, 1, 1 );       break;
-    case 4:  color = COLOR4D( 1, 1, 1, 1 );       break;
-    case 5:  color = COLOR4D( 1, 1, 0, 1 );       break;
-    case 6:  color = COLOR4D( 0, 1, 1, 1 );       break;
-    case 32: color = COLOR4D( 0, 0, 1, 1 );       break;
-    default: color = COLOR4D( 0.4, 0.4, 0.4, 1 ); break;
-    }
-
-    return color;
-}
-
 const int ROUTER_PREVIEW_ITEM::ClearanceOverlayDepth = -VIEW::VIEW_MAX_LAYERS - 10;
 const int ROUTER_PREVIEW_ITEM::BaseOverlayDepth = -VIEW::VIEW_MAX_LAYERS - 20;
 const int ROUTER_PREVIEW_ITEM::ViaOverlayDepth = -VIEW::VIEW_MAX_LAYERS - 50;
diff --git a/pcbnew/router/router_preview_item.h b/pcbnew/router/router_preview_item.h
index 6385c7dda9..ca10f8ddae 100644
--- a/pcbnew/router/router_preview_item.h
+++ b/pcbnew/router/router_preview_item.h
@@ -62,40 +62,20 @@ public:
     static const int PathOverlayDepth;
 
     ROUTER_PREVIEW_ITEM( const SHAPE& aShape, KIGFX::VIEW* aView = nullptr);
-    ROUTER_PREVIEW_ITEM( const PNS::ITEM* aItem = nullptr, KIGFX::VIEW* aView = nullptr);
+    ROUTER_PREVIEW_ITEM( const PNS::ITEM* aItem = nullptr, KIGFX::VIEW* aView = nullptr,
+                         bool aIsHoverItem = false );
     ~ROUTER_PREVIEW_ITEM();
 
     void Update( const PNS::ITEM* aItem );
 
-    void SetColor( const KIGFX::COLOR4D& aColor )
-    {
-        m_color = aColor;
-    }
+    void SetColor( const KIGFX::COLOR4D& aColor ) { m_color = aColor; }
+    void SetDepth( double aDepth ) { m_depth = aDepth; }
+    void SetWidth( int aWidth ) { m_width = aWidth; }
 
-    void SetDepth( double aDepth )
-    {
-        m_depth = aDepth;
-    }
+    void SetClearance( int aClearance ) { m_clearance = aClearance; }
+    void ShowClearance( bool aEnabled ) { m_showClearance = aEnabled; }
 
-    void SetWidth( double aWidth )
-    {
-        m_width = aWidth;
-    }
-
-    void SetClearance( int aClearance )
-    {
-        m_clearance = aClearance;
-    }
-
-    void ShowClearance( bool aEnabled )
-    {
-        m_showClearance = aEnabled;
-    }
-
-    void SetIsHeadTrace( bool aIsHead )
-    {
-        m_isHeadTrace = aIsHead;
-    }
+    void SetIsHeadTrace( bool aIsHead )  { m_isHeadTrace = aIsHead; }
 
 #if defined(DEBUG)
     void Show( int aA, std::ostream& aB ) const override {}
@@ -124,23 +104,23 @@ public:
     void drawShape( const SHAPE* aShape, KIGFX::GAL* aGal ) const;
 
 private:
-    const KIGFX::COLOR4D assignColor( int aStyle ) const;
     const KIGFX::COLOR4D getLayerColor( int aLayer ) const;
 
 private:
-    KIGFX::VIEW* m_view;
+    KIGFX::VIEW*   m_view;
 
-    SHAPE*       m_shape;
-    SHAPE*       m_hole;
+    SHAPE*         m_shape;
+    SHAPE*         m_hole;
 
-    ITEM_TYPE    m_type;
+    ITEM_TYPE      m_type;
 
-    bool         m_isHeadTrace;
-    int          m_width;
-    int          m_layer;
-    int          m_originLayer;
-    int          m_clearance;
-    bool         m_showClearance;
+    bool           m_isHeadTrace;
+    bool           m_isHoverItem;
+    int            m_width;
+    int            m_layer;
+    int            m_originLayer;
+    int            m_clearance;
+    bool           m_showClearance;
 
     double         m_depth;
 
diff --git a/pcbnew/tools/drawing_tool.cpp b/pcbnew/tools/drawing_tool.cpp
index 79ea2e357c..ef480faa63 100644
--- a/pcbnew/tools/drawing_tool.cpp
+++ b/pcbnew/tools/drawing_tool.cpp
@@ -301,8 +301,6 @@ void DRAWING_TOOL::Reset( RESET_REASON aReason )
     m_textAttrs.m_Halign = GR_TEXT_H_ALIGN_LEFT;
     m_textAttrs.m_Valign = GR_TEXT_V_ALIGN_TOP;
 
-    m_statusPopup = std::make_unique<STATUS_MIN_MAX_POPUP>( m_frame );
-
     UpdateStatusBar();
 }
 
diff --git a/pcbnew/tools/drawing_tool.h b/pcbnew/tools/drawing_tool.h
index 01af35820c..2827655121 100644
--- a/pcbnew/tools/drawing_tool.h
+++ b/pcbnew/tools/drawing_tool.h
@@ -358,9 +358,6 @@ private:
     BOARD_CONNECTED_ITEM*     m_pickerItem;
     PCB_TUNING_PATTERN*       m_tuningPattern;
 
-    std::unique_ptr<STATUS_MIN_MAX_POPUP>  m_statusPopup;
-
-
     static const unsigned int WIDTH_STEP;          // Amount of width change for one -/+ key press
     static const unsigned int COORDS_PADDING;      // Padding from coordinates limits for this tool
 
diff --git a/pcbnew/tools/generator_tool.cpp b/pcbnew/tools/generator_tool.cpp
index 55a61f3f2c..bb146a684f 100644
--- a/pcbnew/tools/generator_tool.cpp
+++ b/pcbnew/tools/generator_tool.cpp
@@ -259,44 +259,6 @@ int GENERATOR_TOOL::GenEditAction( const TOOL_EVENT& aEvent )
 }
 
 
-void GENERATOR_TOOL::HighlightNets( BOARD_CONNECTED_ITEM* aStartItem )
-{
-    if( aStartItem && aStartItem->GetNet() )
-    {
-        PNS::RULE_RESOLVER*       resolver = m_router->GetRuleResolver();
-        std::set<PNS::NET_HANDLE> nets = { aStartItem->GetNet() };
-
-        if( PNS::NET_HANDLE coupledNet = resolver->DpCoupledNet( aStartItem->GetNet() ) )
-            nets.insert( coupledNet );
-
-        highlightNets( true, nets );
-    }
-    else
-    {
-        highlightNets( false );
-    }
-}
-
-
-void GENERATOR_TOOL::UpdateHighlightedNets( BOARD_CONNECTED_ITEM* aStartItem )
-{
-    if( aStartItem && aStartItem->GetNet() )
-    {
-        PNS::RULE_RESOLVER*       resolver = m_router->GetRuleResolver();
-        std::set<PNS::NET_HANDLE> nets = { aStartItem->GetNet() };
-
-        if( PNS::NET_HANDLE coupledNet = resolver->DpCoupledNet( aStartItem->GetNet() ) )
-            nets.insert( coupledNet );
-
-        updateHighlightedNets( nets );
-    }
-    else
-    {
-        highlightNets( false );
-    }
-}
-
-
 void GENERATOR_TOOL::setTransitions()
 {
     // Generator actions
diff --git a/pcbnew/tools/generator_tool.h b/pcbnew/tools/generator_tool.h
index 21a751c03f..287bdeaeb9 100644
--- a/pcbnew/tools/generator_tool.h
+++ b/pcbnew/tools/generator_tool.h
@@ -60,9 +60,6 @@ public:
     int RegenerateItem( const TOOL_EVENT& aEvent );
     int GenEditAction( const TOOL_EVENT& aEvent );
 
-    void HighlightNets( BOARD_CONNECTED_ITEM* aStartItem );
-    void UpdateHighlightedNets( BOARD_CONNECTED_ITEM* aStartItem );
-
 private:
     ///< Set up handlers for various events.
     void setTransitions() override;
diff --git a/pcbnew/tools/pcb_point_editor.cpp b/pcbnew/tools/pcb_point_editor.cpp
index 3e1e25c774..ecbc116ee0 100644
--- a/pcbnew/tools/pcb_point_editor.cpp
+++ b/pcbnew/tools/pcb_point_editor.cpp
@@ -124,8 +124,6 @@ void PCB_POINT_EDITOR::Reset( RESET_REASON aReason )
     m_editPoints.reset();
     m_altConstraint.reset();
     getViewControls()->SetAutoPan( false );
-
-    m_statusPopup = std::make_unique<STATUS_MIN_MAX_POPUP>( getEditFrame<PCB_BASE_EDIT_FRAME>() );
 }
 
 
@@ -492,6 +490,9 @@ int PCB_POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent )
     if( !m_editPoints )
         return 0;
 
+    m_preview.FreeItems();
+    getView()->Add( &m_preview );
+
     getView()->Add( m_editPoints.get() );
     setEditedPoint( nullptr );
     updateEditedPoint( aEvent );
@@ -582,11 +583,14 @@ int PCB_POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent )
             {
                 if( grid.GetUseGrid() )
                 {
-                    VECTOR2I gridPt = grid.BestSnapAnchor( pos, {}, grid.GetItemGrid( item ), { item } );
+                    VECTOR2I gridPt = grid.BestSnapAnchor( pos, {}, grid.GetItemGrid( item ),
+                                                           { item } );
 
                     VECTOR2I last = m_editedPoint->GetPosition();
                     VECTOR2I delta = pos - last;
-                    VECTOR2I deltaGrid = gridPt - grid.BestSnapAnchor( last, {}, grid.GetItemGrid( item ), { item } );
+                    VECTOR2I deltaGrid = gridPt - grid.BestSnapAnchor( last, {},
+                                                                       grid.GetItemGrid( item ),
+                                                                       { item } );
 
                     if( abs( delta.x ) > grid.GetGrid().x / 2 )
                         pos.x = last.x + deltaGrid.x;
@@ -613,9 +617,10 @@ int PCB_POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent )
             }
             else if( m_editedPoint->GetGridConstraint() == SNAP_TO_GRID )
             {
-                m_editedPoint->SetPosition(
-                        grid.BestSnapAnchor( m_editedPoint->GetPosition(), snapLayers,
-                                             grid.GetItemGrid( item ), { item } ) );
+                m_editedPoint->SetPosition( grid.BestSnapAnchor( m_editedPoint->GetPosition(),
+                                                                 snapLayers,
+                                                                 grid.GetItemGrid( item ),
+                                                                 { item } ) );
             }
 
             updateItem( &commit );
@@ -649,8 +654,7 @@ int PCB_POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent )
 
             if( item->Type() == PCB_GENERATOR_T )
             {
-                m_statusPopup->Hide();
-
+                m_preview.FreeItems();
                 m_toolMgr->RunSynchronousAction( PCB_ACTIONS::genPushEdit, &commit,
                                                  static_cast<PCB_GENERATOR*>( item ) );
             }
@@ -696,6 +700,9 @@ int PCB_POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent )
         }
     }
 
+    m_preview.FreeItems();
+    getView()->Remove( &m_preview );
+
     if( m_editPoints )
     {
         getView()->Remove( m_editPoints.get() );
@@ -1499,9 +1506,14 @@ void PCB_POINT_EDITOR::updateItem( BOARD_COMMIT* aCommit )
         generatorItem->UpdateFromEditPoints( m_editPoints, aCommit );
         m_toolMgr->RunSynchronousAction( PCB_ACTIONS::genUpdateEdit, aCommit, generatorItem );
 
-        m_statusPopup->Popup();
-        generatorItem->UpdateStatus( generatorTool, frame(), m_statusPopup.get() );
-        m_statusPopup->Move( KIPLATFORM::UI::GetMousePosition() + wxPoint( 20, 20 ) );
+        m_preview.FreeItems();
+
+        for( EDA_ITEM* previewItem : generatorItem->GetPreviewItems( generatorTool, frame(), true ) )
+            m_preview.Add( previewItem );
+
+        generatorTool->Router()->StopRouting();
+
+        getView()->Update( &m_preview );
         break;
     }
 
diff --git a/pcbnew/tools/pcb_point_editor.h b/pcbnew/tools/pcb_point_editor.h
index efcd3265b5..8a4f28094c 100644
--- a/pcbnew/tools/pcb_point_editor.h
+++ b/pcbnew/tools/pcb_point_editor.h
@@ -184,7 +184,7 @@ private:
 
     ARC_EDIT_MODE                 m_arcEditMode;
 
-    std::unique_ptr<STATUS_MIN_MAX_POPUP>        m_statusPopup;
+    PCB_SELECTION                 m_preview;
 
     // Alternative constraint, enabled while a modifier key is held
     std::shared_ptr<EDIT_CONSTRAINT<EDIT_POINT>> m_altConstraint;