diff --git a/common/rc_item.cpp b/common/rc_item.cpp index 5f950d86b5..19c2d1fa8d 100644 --- a/common/rc_item.cpp +++ b/common/rc_item.cpp @@ -594,7 +594,7 @@ void RC_TREE_MODEL::NextMarker() } -void RC_TREE_MODEL::SelectMarker( MARKER_BASE* aMarker ) +void RC_TREE_MODEL::SelectMarker( const MARKER_BASE* aMarker ) { for( RC_TREE_NODE* candidate : m_tree ) { @@ -607,6 +607,19 @@ void RC_TREE_MODEL::SelectMarker( MARKER_BASE* aMarker ) } +void RC_TREE_MODEL::CenterMarker( const MARKER_BASE* aMarker ) +{ + for( RC_TREE_NODE* candidate : m_tree ) + { + if( candidate->m_RcItem->GetParent() == aMarker ) + { + m_view->EnsureVisible( ToItem( candidate ) ); + break; + } + } +} + + void RC_TREE_MODEL::onSizeView( wxSizeEvent& aEvent ) { int width = m_view->GetMainWindow()->GetRect().GetWidth() - WX_DATAVIEW_WINDOW_PADDING; diff --git a/include/rc_item.h b/include/rc_item.h index ec74df34a5..e5f744eea3 100644 --- a/include/rc_item.h +++ b/include/rc_item.h @@ -227,7 +227,8 @@ public: void PrevMarker(); void NextMarker(); - void SelectMarker( MARKER_BASE* aMarker ); + void SelectMarker( const MARKER_BASE* aMarker ); + void CenterMarker( const MARKER_BASE* aMarker ); bool IsContainer( wxDataViewItem const& aItem ) const override; diff --git a/pcbnew/dialogs/dialog_drc.cpp b/pcbnew/dialogs/dialog_drc.cpp index 6c87ad99e5..4b3b916169 100644 --- a/pcbnew/dialogs/dialog_drc.cpp +++ b/pcbnew/dialogs/dialog_drc.cpp @@ -395,7 +395,15 @@ void DIALOG_DRC::OnDRCItemSelected( wxDataViewEvent& aEvent ) if( board->GetVisibleLayers().test( principalLayer ) ) m_frame->SetActiveLayer( principalLayer ); - m_frame->FocusOnItem( item, principalLayer ); + if( m_centerMarkerOnIdle ) + { + // we already came from a cross-probe of the marker in the document; don't go + // around in circles + } + else + { + m_frame->FocusOnItem( item, principalLayer ); + } } aEvent.Skip(); @@ -743,16 +751,28 @@ void DIALOG_DRC::NextMarker() } -void DIALOG_DRC::SelectMarker( PCB_MARKER* aMarker ) +void DIALOG_DRC::SelectMarker( const PCB_MARKER* aMarker ) { if( m_Notebook->IsShown() ) { m_Notebook->SetSelection( 0 ); m_markersTreeModel->SelectMarker( aMarker ); + + // wxWidgets on some platforms fails to correctly ensure that a selected item is + // visible, so we have to do it in a separate idle event. + m_centerMarkerOnIdle = aMarker; + Bind( wxEVT_IDLE, &DIALOG_DRC::centerMarkerIdleHandler, this ); } } +void DIALOG_DRC::centerMarkerIdleHandler( wxIdleEvent& aEvent ) +{ + m_markersTreeModel->CenterMarker( m_centerMarkerOnIdle ); + Unbind( wxEVT_IDLE, &DIALOG_DRC::centerMarkerIdleHandler, this ); +} + + void DIALOG_DRC::ExcludeMarker() { if( !m_Notebook->IsShown() || m_Notebook->GetSelection() != 0 ) diff --git a/pcbnew/dialogs/dialog_drc.h b/pcbnew/dialogs/dialog_drc.h index e73d5d272d..d35712b261 100644 --- a/pcbnew/dialogs/dialog_drc.h +++ b/pcbnew/dialogs/dialog_drc.h @@ -57,7 +57,7 @@ public: void PrevMarker(); void NextMarker(); - void SelectMarker( PCB_MARKER* aMarker ); + void SelectMarker( const PCB_MARKER* aMarker ); void ExcludeMarker(); @@ -97,6 +97,8 @@ private: void OnChangingNotebookPage( wxNotebookEvent& aEvent ) override; + void centerMarkerIdleHandler( wxIdleEvent& aEvent ); + void deleteAllMarkers( bool aIncludeExclusions ); void refreshEditor(); @@ -126,7 +128,9 @@ private: RC_ITEMS_PROVIDER* m_footprintWarningsProvider; RC_TREE_MODEL* m_footprintWarningsTreeModel; - int m_severities; + const PCB_MARKER* m_centerMarkerOnIdle; + + int m_severities; // A mask of SEVERITY flags }; #endif // _DIALOG_DRC_H_ diff --git a/pcbnew/edit.cpp b/pcbnew/edit.cpp index f33dd0d19f..432a39b82e 100644 --- a/pcbnew/edit.cpp +++ b/pcbnew/edit.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include // Handles the selection of command events. @@ -157,6 +158,10 @@ void PCB_EDIT_FRAME::OnEditItemRequest( BOARD_ITEM* aItem ) m_toolManager->RunAction( PCB_ACTIONS::groupProperties, true, aItem ); break; + case PCB_MARKER_T: + m_toolManager->GetTool()->CrossProbe( static_cast( aItem ) ); + break; + default: break; } diff --git a/pcbnew/tools/drc_tool.cpp b/pcbnew/tools/drc_tool.cpp index 9b3eb11e0e..ce4e4254ff 100644 --- a/pcbnew/tools/drc_tool.cpp +++ b/pcbnew/tools/drc_tool.cpp @@ -275,7 +275,9 @@ int DRC_TOOL::CrossProbe( const TOOL_EVENT& aEvent ) if( selection.GetSize() == 1 && selection.Front()->Type() == PCB_MARKER_T ) { - m_drcDialog->Show( true ); + if( !m_drcDialog->IsShown() ) + m_drcDialog->Show( true ); + m_drcDialog->Raise(); m_drcDialog->SelectMarker( static_cast( selection.Front() ) ); } @@ -285,6 +287,16 @@ int DRC_TOOL::CrossProbe( const TOOL_EVENT& aEvent ) } +void DRC_TOOL::CrossProbe( const PCB_MARKER* aMarker ) +{ + if( !IsDRCDialogShown() ) + ShowDRCDialog( nullptr ); + + m_drcDialog->Raise(); + m_drcDialog->SelectMarker( aMarker ); +} + + int DRC_TOOL::ExcludeMarker( const TOOL_EVENT& aEvent ) { if( m_drcDialog ) diff --git a/pcbnew/tools/drc_tool.h b/pcbnew/tools/drc_tool.h index c439417947..595fd24139 100644 --- a/pcbnew/tools/drc_tool.h +++ b/pcbnew/tools/drc_tool.h @@ -51,17 +51,10 @@ public: void Reset( RESET_REASON aReason ) override; /** - * Open a dialog and prompts the user, then if a test run button is - * clicked, runs the test(s) and creates the MARKERS. The dialog is only - * created if it is not already in existence. + * Opens the DRC dialog. The dialog is only created if it is not already in existence. * - * @param aParent is the parent window for wxWidgets. Usually the PCB editor frame - * but can be another dialog - * if aParent == NULL (default), the parent will be the PCB editor frame - * and the dialog will be not modal (just float on parent - * if aParent is specified, the dialog will be modal. - * The modal mode is mandatory if the dialog is created from another dialog, not - * from the PCB editor frame + * @param aParent is the parent window for modal invocations. If nullptr, the parent will + * be the PCB_EDIT_FRAME and the dialog will be modeless. */ void ShowDRCDialog( wxWindow* aParent ); @@ -69,15 +62,11 @@ public: /** * Check to see if the DRC_TOOL dialog is currently shown - * - * @return true if the dialog is shown */ bool IsDRCDialogShown(); /** * Check to see if the DRC engine is running the tests - * - * @return true if the DRC engine is running the tests */ bool IsDRCRunning() const { return m_drcRunning; } @@ -98,6 +87,12 @@ public: int NextMarker( const TOOL_EVENT& aEvent ); int CrossProbe( const TOOL_EVENT& aEvent ); + /** + * A more "active" CrossProbe which will open the DRC dialog if it is closed. Used when + * double-clicking on a marker. + */ + void CrossProbe( const PCB_MARKER* aMarker ); + int ExcludeMarker( const TOOL_EVENT& aEvent ); private: