From 58d4ac2a9756ffd9a75f59bcdf23f71a71e6e990 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Sun, 24 Oct 2021 11:14:54 +0100 Subject: [PATCH] Keep netnames on tracks within the viewport when possible. Fixes https://gitlab.com/kicad/code/kicad/issues/2032 --- include/eda_rect.h | 8 ++++++++ include/view/view.h | 3 +++ pcbnew/pcb_draw_panel_gal.cpp | 10 ++++------ pcbnew/pcb_edit_frame.cpp | 33 ++++++++++++++++++++++++++++++++- pcbnew/pcb_edit_frame.h | 10 +++++++++- pcbnew/pcb_painter.cpp | 23 +++++++++++++++++------ pcbnew/pcb_track.cpp | 17 +++++++++++++++++ 7 files changed, 90 insertions(+), 14 deletions(-) diff --git a/include/eda_rect.h b/include/eda_rect.h index f5267196cf..0160f6e2b3 100644 --- a/include/eda_rect.h +++ b/include/eda_rect.h @@ -50,6 +50,14 @@ public: m_init( true ) { } + template + EDA_RECT( const BOX2 aBox ) + { + m_pos = (wxPoint) aBox.GetPosition(); + m_size.x = aBox.GetWidth(); + m_size.y = aBox.GetHeight(); + } + virtual ~EDA_RECT() { }; wxPoint Centre() const diff --git a/include/view/view.h b/include/view/view.h index 488fa598c6..6f46f66171 100644 --- a/include/view/view.h +++ b/include/view/view.h @@ -451,6 +451,9 @@ public: } } + /** + * Set a layer display-only (ie: to be rendered but not returned by hit test queries). + */ inline void SetLayerDisplayOnly( int aLayer, bool aDisplayOnly = true ) { wxCHECK( aLayer < (int) m_layers.size(), /*void*/ ); diff --git a/pcbnew/pcb_draw_panel_gal.cpp b/pcbnew/pcb_draw_panel_gal.cpp index b5ec178c05..da18db9331 100644 --- a/pcbnew/pcb_draw_panel_gal.cpp +++ b/pcbnew/pcb_draw_panel_gal.cpp @@ -389,15 +389,13 @@ void PCB_DRAW_PANEL_GAL::SetTopLayer( PCB_LAYER_ID aLayer ) m_view->GetLayerOrder( LAYER_MARKER_SHADOWS ) + 4 ); } } - else if( IsCopperLayer( aLayer ) ) + + if( IsCopperLayer( aLayer ) ) { + m_view->SetTopLayer( ZONE_LAYER_FOR( aLayer ) ); + // Display labels for copper layers on the top m_view->SetTopLayer( GetNetnameLayer( aLayer ) ); - m_view->SetTopLayer( ZONE_LAYER_FOR( aLayer ) ); - } - else - { - m_view->SetTopLayer( ZONE_LAYER_FOR( aLayer ) ); } m_view->EnableTopLayer( true ); diff --git a/pcbnew/pcb_edit_frame.cpp b/pcbnew/pcb_edit_frame.cpp index b27440ff4a..6bf415fc23 100644 --- a/pcbnew/pcb_edit_frame.cpp +++ b/pcbnew/pcb_edit_frame.cpp @@ -177,7 +177,8 @@ END_EVENT_TABLE() PCB_EDIT_FRAME::PCB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : PCB_BASE_EDIT_FRAME( aKiway, aParent, FRAME_PCB_EDITOR, _( "PCB Editor" ), wxDefaultPosition, wxDefaultSize, KICAD_DEFAULT_DRAWFRAME_STYLE, PCB_EDIT_FRAME_NAME ), - m_exportNetlistAction( nullptr ), m_findDialog( nullptr ) + m_exportNetlistAction( nullptr ), + m_findDialog( nullptr ) { m_maximizeByDefault = true; m_showBorderAndTitleBlock = true; // true to display sheet references @@ -309,6 +310,22 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : // to calculate the wrong zoom size. See PCB_EDIT_FRAME::onSize(). Bind( wxEVT_SIZE, &PCB_EDIT_FRAME::onSize, this ); + // Redraw netnames (so that they fall within the current viewport) after the viewport + // has stopped changing. Redrawing them without the timer moves them smoothly with scrolling, + // making it look like the tracks are being dragged -- which we don't want. + m_redrawNetnamesTimer.SetOwner( this ); + Connect( wxEVT_TIMER, wxTimerEventHandler( PCB_EDIT_FRAME::redrawNetnames ), nullptr, this ); + + Bind( wxEVT_IDLE, + [this]( wxIdleEvent& aEvent ) + { + if( GetCanvas()->GetView()->GetViewport() != m_lastViewport ) + { + m_lastViewport = GetCanvas()->GetView()->GetViewport(); + m_redrawNetnamesTimer.StartOnce( 100 ); + } + } ); + resolveCanvasType(); setupUnits( config() ); @@ -438,6 +455,20 @@ BOARD_ITEM_CONTAINER* PCB_EDIT_FRAME::GetModel() const } +void PCB_EDIT_FRAME::redrawNetnames( wxTimerEvent& aEvent ) +{ + KIGFX::VIEW* view = GetCanvas()->GetView(); + + for( PCB_TRACK* track : GetBoard()->Tracks() ) + { + if( track->ViewGetLOD( GetNetnameLayer( track->GetLayer() ), view ) < view->GetScale() ) + view->Update( track, KIGFX::REPAINT ); + } + + GetCanvas()->Refresh(); +} + + void PCB_EDIT_FRAME::SetPageSettings( const PAGE_INFO& aPageSettings ) { PCB_BASE_FRAME::SetPageSettings( aPageSettings ); diff --git a/pcbnew/pcb_edit_frame.h b/pcbnew/pcb_edit_frame.h index 9772755ba1..7df6421477 100644 --- a/pcbnew/pcb_edit_frame.h +++ b/pcbnew/pcb_edit_frame.h @@ -760,6 +760,8 @@ protected: int inferLegacyEdgeClearance( BOARD* aBoard ); + void redrawNetnames( wxTimerEvent& aEvent ); + public: PCB_LAYER_BOX_SELECTOR* m_SelLayerBox; // a combo box to display and select active layer @@ -785,7 +787,13 @@ private: DIALOG_FIND* m_findDialog; - wxTimer* m_eventCounterTimer; + /** + * Keep track of viewport so that track net labels can be adjusted when it changes. + */ + BOX2D m_lastViewport; + wxTimer m_redrawNetnamesTimer; + + wxTimer* m_eventCounterTimer; }; #endif // __PCB_EDIT_FRAME_H__ diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp index 291f4b07f4..becb8a33cc 100644 --- a/pcbnew/pcb_painter.cpp +++ b/pcbnew/pcb_painter.cpp @@ -117,7 +117,7 @@ void PCB_RENDER_SETTINGS::LoadColors( const COLOR_SETTINGS* aSettings ) // Netnames for copper layers for( LSEQ cu = LSET::AllCuMask().CuStack(); cu; ++cu ) { - const COLOR4D lightLabel( 0.8, 0.8, 0.8, 0.7 ); + const COLOR4D lightLabel( 1.0, 1.0, 1.0, 0.7 ); const COLOR4D darkLabel = lightLabel.Inverted(); PCB_LAYER_ID layer = *cu; @@ -538,8 +538,8 @@ bool PCB_PAINTER::Draw( const VIEW_ITEM* aItem, int aLayer ) void PCB_PAINTER::draw( const PCB_TRACK* aTrack, int aLayer ) { - VECTOR2D start( aTrack->GetStart() ); - VECTOR2D end( aTrack->GetEnd() ); + VECTOR2I start( aTrack->GetStart() ); + VECTOR2I end( aTrack->GetEnd() ); int width = aTrack->GetWidth(); COLOR4D color = m_pcbSettings.GetColor( aTrack, aLayer ); @@ -551,11 +551,23 @@ void PCB_PAINTER::draw( const PCB_TRACK* aTrack, int aLayer ) if( aTrack->GetNetCode() <= NETINFO_LIST::UNCONNECTED ) return; - VECTOR2D line = ( end - start ); + // When drawing netnames, clip the track to the viewport + BOX2D viewport; + VECTOR2D screenSize = m_gal->GetScreenPixelSize(); + const MATRIX3x3D& matrix = m_gal->GetScreenWorldMatrix(); + + viewport.SetOrigin( VECTOR2D( matrix * VECTOR2D( 0, 0 ) ) ); + viewport.SetEnd( VECTOR2D( matrix * screenSize ) ); + + EDA_RECT clipBox( viewport.Normalize() ); + + ClipLine( &clipBox, start.x, start.y, end.x, end.y ); + + VECTOR2I line = ( end - start ); double length = line.EuclideanNorm(); // Check if the track is long enough to have a netname displayed - if( length < 10 * width ) + if( length < 6 * width ) return; const wxString& netName = UnescapeString( aTrack->GetShortNetname() ); @@ -581,7 +593,6 @@ void PCB_PAINTER::draw( const PCB_TRACK* aTrack, int aLayer ) textPosition.y += penWidth / 1.4; } - m_gal->SetIsStroke( true ); m_gal->SetIsFill( false ); m_gal->SetStrokeColor( color ); diff --git a/pcbnew/pcb_track.cpp b/pcbnew/pcb_track.cpp index 7698891563..1a61261f81 100644 --- a/pcbnew/pcb_track.cpp +++ b/pcbnew/pcb_track.cpp @@ -556,6 +556,9 @@ double PCB_TRACK::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const if( IsNetnameLayer( aLayer ) ) { + if( GetNetCode() <= NETINFO_LIST::UNCONNECTED ) + return HIDE; + // Hide netnames on dimmed tracks if( renderSettings->GetHighContrast() ) { @@ -563,6 +566,20 @@ double PCB_TRACK::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const return HIDE; } + // When drawing netnames, clip the track to the viewport + VECTOR2I start( GetStart() ); + VECTOR2I end( GetEnd() ); + EDA_RECT clipBox( aView->GetViewport() ); + + ClipLine( &clipBox, start.x, start.y, end.x, end.y ); + + VECTOR2I line = ( end - start ); + double length = line.EuclideanNorm(); + + // Check if the track is long enough to have a netname displayed + if( length < 6 * GetWidth() ) + return HIDE; + // Netnames will be shown only if zoom is appropriate return ( double ) Millimeter2iu( 4 ) / ( m_Width + 1 ); }