Work around EnsureVisible bug in wxWidgets during DRC cross-probe.

Also adds double-click-marker to open DRC dialog and select marker
in list.

Fixes https://gitlab.com/kicad/code/kicad/issues/7246
This commit is contained in:
Jeff Young 2021-10-05 23:33:30 +01:00
parent 95f841a037
commit 1bb5fc3fd6
7 changed files with 71 additions and 21 deletions

View File

@ -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;

View File

@ -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;

View File

@ -395,8 +395,16 @@ void DIALOG_DRC::OnDRCItemSelected( wxDataViewEvent& aEvent )
if( board->GetVisibleLayers().test( principalLayer ) )
m_frame->SetActiveLayer( 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 )

View File

@ -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_

View File

@ -40,6 +40,7 @@
#include <connectivity/connectivity_data.h>
#include <tool/tool_manager.h>
#include <tools/pcb_actions.h>
#include <tools/drc_tool.h>
#include <dialogs/dialog_dimension_properties.h>
// 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<DRC_TOOL>()->CrossProbe( static_cast<PCB_MARKER*>( aItem ) );
break;
default:
break;
}

View File

@ -275,7 +275,9 @@ int DRC_TOOL::CrossProbe( const TOOL_EVENT& aEvent )
if( selection.GetSize() == 1 && selection.Front()->Type() == PCB_MARKER_T )
{
if( !m_drcDialog->IsShown() )
m_drcDialog->Show( true );
m_drcDialog->Raise();
m_drcDialog->SelectMarker( static_cast<PCB_MARKER*>( 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 )

View File

@ -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: