From c7ec110fbaef1b2f9f45d1dce79beb25519cd0dc Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Mon, 24 Feb 2020 17:18:23 +0000 Subject: [PATCH] Only center focused items when they're not visible. This includes outside the window and behind an occluding dialog. This keeps the view from jumping around when focusing on nearby objects. --- common/eda_draw_frame.cpp | 28 ++++++++++-- eeschema/dialogs/dialog_erc.cpp | 4 +- eeschema/tools/sch_editor_control.cpp | 2 +- include/eda_draw_frame.h | 3 +- include/pcb_base_frame.h | 2 + .../dialog_cleanup_tracks_and_vias.cpp | 4 +- pcbnew/dialogs/dialog_find.cpp | 2 +- pcbnew/pcb_base_frame.cpp | 43 +++++++++++++++++++ 8 files changed, 76 insertions(+), 12 deletions(-) diff --git a/common/eda_draw_frame.cpp b/common/eda_draw_frame.cpp index 684e6e9e21..bc3224f334 100644 --- a/common/eda_draw_frame.cpp +++ b/common/eda_draw_frame.cpp @@ -686,12 +686,32 @@ wxWindow* findDialog( wxWindowList& aList ) } -void EDA_DRAW_FRAME::FocusOnLocation( const wxPoint& aPos, bool aCenterView ) +void EDA_DRAW_FRAME::FocusOnLocation( const wxPoint& aPos ) { - if( aCenterView ) - { - wxWindow* dialog = findDialog( GetChildren() ); + bool centerView = false; + BOX2D r = GetCanvas()->GetView()->GetViewport(); + // Center if we're off the current view, or within 10% of its edge + r.Inflate( - (int) r.GetWidth() / 10 ); + + if( !r.Contains( aPos ) ) + centerView = true; + + // Center if we're behind an obscuring dialog, or within 10% of its edge + wxWindow* dialog = findDialog( GetChildren() ); + + if( dialog ) + { + wxRect dialogRect( GetCanvas()->ScreenToClient( dialog->GetScreenPosition() ), + dialog->GetSize() ); + dialogRect.Inflate( dialogRect.GetWidth() / 10 ); + + if( dialogRect.Contains( (wxPoint) GetCanvas()->GetView()->ToScreen( aPos ) ) ) + centerView = true; + } + + if( centerView ) + { // If a dialog partly obscures the window, then center on the uncovered area. if( dialog ) { diff --git a/eeschema/dialogs/dialog_erc.cpp b/eeschema/dialogs/dialog_erc.cpp index ef081e2c74..3cd5d0dde2 100644 --- a/eeschema/dialogs/dialog_erc.cpp +++ b/eeschema/dialogs/dialog_erc.cpp @@ -292,7 +292,7 @@ void DIALOG_ERC::OnLeftClickMarkersList( wxHtmlLinkEvent& event ) } m_lastMarkerFound = marker; - m_parent->FocusOnLocation( marker->m_Pos, true ); + m_parent->FocusOnLocation( marker->m_Pos ); RedrawDrawPanel(); } @@ -303,7 +303,7 @@ void DIALOG_ERC::OnLeftDblClickMarkersList( wxMouseEvent& event ) // was initialized (NULL if not found). if( m_lastMarkerFound ) { - m_parent->FocusOnLocation( m_lastMarkerFound->m_Pos, true ); + m_parent->FocusOnLocation( m_lastMarkerFound->m_Pos ); RedrawDrawPanel(); } diff --git a/eeschema/tools/sch_editor_control.cpp b/eeschema/tools/sch_editor_control.cpp index 927dccad12..bcf90e88a5 100644 --- a/eeschema/tools/sch_editor_control.cpp +++ b/eeschema/tools/sch_editor_control.cpp @@ -276,7 +276,7 @@ int SCH_EDITOR_CONTROL::FindNext( const TOOL_EVENT& aEvent ) if( item ) { m_selectionTool->AddItemToSel( item ); - m_frame->FocusOnLocation( item->GetBoundingBox().GetCenter(), true ); + m_frame->FocusOnLocation( item->GetBoundingBox().GetCenter() ); m_frame->GetCanvas()->Refresh(); } else diff --git a/include/eda_draw_frame.h b/include/eda_draw_frame.h index 172e110ab1..c0dc23fee0 100644 --- a/include/eda_draw_frame.h +++ b/include/eda_draw_frame.h @@ -338,9 +338,8 @@ public: * Move the graphic cursor (crosshair cursor) at a given coordinate and reframes * the drawing if the requested point is out of view or if center on location is requested. * @param aPos is the point to go to. - * @param aCenterView is true if the new cursor position should be centered on canvas. */ - void FocusOnLocation( const wxPoint& aPos, bool aCenterView = false ); + void FocusOnLocation( const wxPoint& aPos ); /** * @return The current zoom level. diff --git a/include/pcb_base_frame.h b/include/pcb_base_frame.h index 4dd29eccf3..6cd3eb97cf 100644 --- a/include/pcb_base_frame.h +++ b/include/pcb_base_frame.h @@ -211,6 +211,8 @@ public: return m_Pcb; } + void FocusOnItem( BOARD_ITEM* aItem ); + // General virtual void OnCloseWindow( wxCloseEvent& Event ) = 0; virtual void ReCreateOptToolbar() override { } diff --git a/pcbnew/dialogs/dialog_cleanup_tracks_and_vias.cpp b/pcbnew/dialogs/dialog_cleanup_tracks_and_vias.cpp index 1a673a8e07..a6a419bf67 100644 --- a/pcbnew/dialogs/dialog_cleanup_tracks_and_vias.cpp +++ b/pcbnew/dialogs/dialog_cleanup_tracks_and_vias.cpp @@ -147,7 +147,7 @@ void DIALOG_CLEANUP_TRACKS_AND_VIAS::OnSelectItem( wxCommandEvent& event ) if( item ) { - m_parentFrame->FocusOnLocation( item->GetPointA(), true ); + m_parentFrame->FocusOnLocation( item->GetPointA() ); WINDOW_THAWER thawer( m_parentFrame ); m_parentFrame->GetCanvas()->Refresh(); } @@ -170,7 +170,7 @@ void DIALOG_CLEANUP_TRACKS_AND_VIAS::OnLeftDClickItem( wxMouseEvent& event ) const DRC_ITEM* item = m_ItemsListBox->GetItem( selection ); if( item ) { - m_parentFrame->FocusOnLocation( item->GetPointA(), true ); + m_parentFrame->FocusOnLocation( item->GetPointA() ); if( !IsModal() ) Show( false ); diff --git a/pcbnew/dialogs/dialog_find.cpp b/pcbnew/dialogs/dialog_find.cpp index e82ec190e0..5ccce9c23a 100644 --- a/pcbnew/dialogs/dialog_find.cpp +++ b/pcbnew/dialogs/dialog_find.cpp @@ -330,7 +330,7 @@ void DIALOG_FIND::search( bool aDirection ) if( m_it != m_hitList.end() ) { m_frame->GetToolManager()->RunAction( PCB_ACTIONS::selectItem, true, *m_it ); - m_frame->FocusOnLocation( ( *m_it )->GetPosition(), true ); + m_frame->FocusOnLocation( ( *m_it )->GetPosition() ); msg.Printf( _( "\"%s\" found" ), searchString ); m_frame->SetStatusText( msg ); diff --git a/pcbnew/pcb_base_frame.cpp b/pcbnew/pcb_base_frame.cpp index 51bc952bbd..ee47cd6346 100644 --- a/pcbnew/pcb_base_frame.cpp +++ b/pcbnew/pcb_base_frame.cpp @@ -185,6 +185,49 @@ void PCB_BASE_FRAME::AddModuleToBoard( MODULE* module ) } +void PCB_BASE_FRAME::FocusOnItem( BOARD_ITEM* aItem ) +{ + static KIID lastBrightenedItemID( niluuid ); + + BOARD_ITEM* lastItem = GetBoard()->GetItem( lastBrightenedItemID ); + + if( lastItem && lastItem != aItem ) + { + lastItem->ClearBrightened(); + + if( lastItem->Type() == PCB_MODULE_T ) + { + static_cast( lastItem )->RunOnChildren( [&] ( BOARD_ITEM* child ) + { + child->ClearBrightened(); + }); + } + + GetCanvas()->GetView()->Update( lastItem ); + lastBrightenedItemID = niluuid; + GetCanvas()->Refresh(); + } + + if( aItem ) + { + aItem->SetBrightened(); + + if( aItem->Type() == PCB_MODULE_T ) + { + static_cast( aItem )->RunOnChildren( [&] ( BOARD_ITEM* child ) + { + child->SetBrightened(); + }); + } + + GetCanvas()->GetView()->Update( aItem ); + lastBrightenedItemID = aItem->m_Uuid; + FocusOnLocation( aItem->GetPosition() ); + GetCanvas()->Refresh(); + } +} + + void PCB_BASE_FRAME::SetPageSettings( const PAGE_INFO& aPageSettings ) { wxASSERT( m_Pcb );