Performance improvements for SchematicCleanup().

Fixes https://gitlab.com/kicad/code/kicad/issues/4563
This commit is contained in:
Jeff Young 2020-08-10 12:40:58 +01:00
parent dbede14ed2
commit f4ab14f32d
20 changed files with 110 additions and 63 deletions

View File

@ -179,21 +179,27 @@ bool SCH_EDIT_FRAME::SchematicCleanUp( SCH_SCREEN* aScreen )
ncs.push_back( static_cast<SCH_NO_CONNECT*>( item ) );
}
alg::for_all_pairs(
junctions.begin(), junctions.end(), [&]( SCH_JUNCTION* aFirst, SCH_JUNCTION* aSecond ) {
alg::for_all_pairs( junctions.begin(), junctions.end(),
[&]( SCH_JUNCTION* aFirst, SCH_JUNCTION* aSecond )
{
if( ( aFirst->GetEditFlags() & STRUCT_DELETED )
|| ( aSecond->GetEditFlags() & STRUCT_DELETED ) )
{
return;
}
if( aFirst->GetPosition() == aSecond->GetPosition() )
remove_item( aSecond );
} );
alg::for_all_pairs(
ncs.begin(), ncs.end(), [&]( SCH_NO_CONNECT* aFirst, SCH_NO_CONNECT* aSecond ) {
alg::for_all_pairs( ncs.begin(), ncs.end(),
[&]( SCH_NO_CONNECT* aFirst, SCH_NO_CONNECT* aSecond )
{
if( ( aFirst->GetEditFlags() & STRUCT_DELETED )
|| ( aSecond->GetEditFlags() & STRUCT_DELETED ) )
{
return;
}
if( aFirst->GetPosition() == aSecond->GetPosition() )
remove_item( aSecond );
@ -223,9 +229,7 @@ bool SCH_EDIT_FRAME::SchematicCleanUp( SCH_SCREEN* aScreen )
continue;
if( !secondLine->IsParallel( firstLine )
|| secondLine->GetLineStyle() != firstLine->GetLineStyle()
|| secondLine->GetLineColor() != firstLine->GetLineColor()
|| secondLine->GetLineSize() != firstLine->GetLineSize()
|| secondLine->GetStroke() != firstLine->GetStroke()
|| secondLine->GetLayer() != firstLine->GetLayer() )
continue;
@ -252,6 +256,7 @@ bool SCH_EDIT_FRAME::SchematicCleanUp( SCH_SCREEN* aScreen )
itemList.PushItem( ITEM_PICKER( aScreen, mergedLine, UR_NEW ) );
AddToScreen( mergedLine, aScreen );
mergedLine->SetLineColor( COLOR4D( PURECYAN ) );
if( firstLine->IsSelected() )
selectionTool->AddItemToSel( mergedLine, true /*quiet mode*/ );
@ -295,7 +300,7 @@ bool SCH_EDIT_FRAME::BreakSegment( SCH_LINE* aSegment, const wxPoint& aPoint,
SaveCopyInUndoList( aScreen, newSegment, UR_NEW, true );
SaveCopyInUndoList( aScreen, aSegment, UR_CHANGED, true );
RefreshItem( aSegment );
UpdateItem( aSegment );
aSegment->SetEndPoint( aPoint );
if( aNewSegment )
@ -385,12 +390,15 @@ void SCH_EDIT_FRAME::DeleteJunction( SCH_ITEM* aJunction, bool aAppend )
lines.push_back( line );
}
alg::for_all_pairs(
lines.begin(), lines.end(), [&]( SCH_LINE* firstLine, SCH_LINE* secondLine ) {
alg::for_all_pairs( lines.begin(), lines.end(),
[&]( SCH_LINE* firstLine, SCH_LINE* secondLine )
{
if( ( firstLine->GetEditFlags() & STRUCT_DELETED )
|| ( secondLine->GetEditFlags() & STRUCT_DELETED )
|| !secondLine->IsParallel( firstLine ) )
{
return;
}
// Remove identical lines
if( firstLine->IsEndPoint( secondLine->GetStartPoint() )

View File

@ -525,14 +525,14 @@ bool DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::TransferDataFromWindow()
otherUnit->GetField( DATASHEET )->SetText( m_fields->at( DATASHEET ).GetText() );
otherUnit->SetIncludeInBom( !m_cbExcludeFromBom->IsChecked() );
otherUnit->SetIncludeOnBoard( !m_cbExcludeFromBoard->IsChecked() );
GetParent()->RefreshItem( otherUnit );
GetParent()->UpdateItem( otherUnit );
}
}
}
currentScreen->Append( m_cmp );
GetParent()->TestDanglingEnds();
GetParent()->RefreshItem( m_cmp );
GetParent()->UpdateItem( m_cmp );
GetParent()->OnModify();
return true;

View File

@ -336,7 +336,7 @@ bool DIALOG_LABEL_EDITOR::TransferDataFromWindow()
m_CurrentText->SetTextThickness( 0 ); // Use default pen width
}
m_Parent->RefreshItem( m_CurrentText );
m_Parent->UpdateItem( m_CurrentText );
m_Parent->GetCanvas()->Refresh();
m_Parent->OnModify();

View File

@ -243,7 +243,7 @@ bool DIALOG_EDIT_LINE_STYLE::TransferDataFromWindow()
stroke.SetColor( m_selectedColor );
strokeItem->SetStroke( stroke );
m_frame->RefreshItem( strokeItem );
m_frame->UpdateItem( strokeItem );
}
m_frame->GetCanvas()->Refresh();

View File

@ -437,7 +437,7 @@ void DIALOG_SCH_EDIT_ONE_FIELD::UpdateField( SCH_FIELD* aField, SCH_SHEET_PATH*
{
editFrame->SaveCopyInUndoList( screen, otherUnit, UR_CHANGED, true /* append */);
otherUnit->GetField( fieldType )->SetText( m_text );
editFrame->RefreshItem( otherUnit );
editFrame->UpdateItem( otherUnit );
}
}
}

View File

@ -110,7 +110,7 @@ bool DIALOG_EDIT_SHEET_PIN::TransferDataFromWindow()
auto shape = static_cast<PINSHEETLABEL_SHAPE>( m_choiceConnectionType->GetCurrentSelection() );
m_sheetPin->SetShape( shape );
m_frame->RefreshItem( m_sheetPin );
m_frame->UpdateItem( m_sheetPin );
m_frame->GetCanvas()->Refresh();
m_frame->OnModify();

View File

@ -321,7 +321,7 @@ bool DIALOG_SCH_SHEET_PROPS::TransferDataFromWindow()
// Refresh all sheets in case ordering changed.
for( SCH_ITEM* item : m_frame->GetScreen()->Items().OfType( SCH_SHEET_T ) )
m_frame->RefreshItem( item );
m_frame->UpdateItem( item );
m_frame->OnModify();

View File

@ -712,7 +712,7 @@ bool SCH_EDIT_FRAME::SaveProject()
sheetFileName.SetExt( KiCadSchematicFileExtension );
sheet->SetFileName( sheetFileName.GetFullPath() );
RefreshItem( sheet );
UpdateItem( sheet );
}
screen->SetFileName( tmpFn.GetFullPath() );

View File

@ -226,7 +226,7 @@ void SCH_EDIT_FRAME::SelectUnit( SCH_COMPONENT* aComponent, int aUnit )
TestDanglingEnds();
RefreshItem( aComponent );
UpdateItem( aComponent );
OnModify();
}
}
@ -270,6 +270,6 @@ void SCH_EDIT_FRAME::ConvertPart( SCH_COMPONENT* aComponent )
if( aComponent->IsSelected() )
m_toolManager->RunAction( EE_ACTIONS::addItemToSel, true, aComponent );
RefreshItem( aComponent );
UpdateItem( aComponent );
OnModify();
}

View File

@ -315,7 +315,7 @@ void SCH_BASE_FRAME::createCanvas()
}
void SCH_BASE_FRAME::RefreshItem( EDA_ITEM* aItem, bool isAddOrDelete )
void SCH_BASE_FRAME::UpdateItem( EDA_ITEM* aItem, bool isAddOrDelete )
{
EDA_ITEM* parent = aItem->GetParent();
@ -337,7 +337,11 @@ void SCH_BASE_FRAME::RefreshItem( EDA_ITEM* aItem, bool isAddOrDelete )
GetCanvas()->GetView()->Update( parent, KIGFX::REPAINT );
}
GetCanvas()->Refresh();
// Calling Refresh() here introduces a bi-stable state: when doing operations on a
// large number of items if at some point the refresh timer times out and does a
// refresh it will take long enough that the next item will also time out, and the
// next, and the next, etc.
// GetCanvas()->Refresh();
}
@ -384,7 +388,7 @@ void SCH_BASE_FRAME::AddToScreen( EDA_ITEM* aItem, SCH_SCREEN* aScreen )
if( screen == GetScreen() )
{
GetCanvas()->GetView()->Add( aItem );
RefreshItem( aItem, true ); // handle any additional parent semantics
UpdateItem( aItem, true ); // handle any additional parent semantics
}
}
@ -402,7 +406,7 @@ void SCH_BASE_FRAME::RemoveFromScreen( EDA_ITEM* aItem, SCH_SCREEN* aScreen )
screen->Remove( (SCH_ITEM*) aItem );
if( screen == GetScreen() )
RefreshItem( aItem, true ); // handle any additional parent semantics
UpdateItem( aItem, true ); // handle any additional parent semantics
}

View File

@ -260,7 +260,7 @@ public:
/**
* Mark an item for refresh.
*/
void RefreshItem( EDA_ITEM* aItem, bool isAddOrDelete = false );
void UpdateItem( EDA_ITEM* aItem, bool isAddOrDelete = false );
/**
* Mark selected items for refresh.

View File

@ -959,7 +959,7 @@ void SCH_EDIT_FRAME::AddItemToScreenAndUndoList( SCH_SCREEN* aScreen, SCH_ITEM*
aItem->ClearFlags( IS_NEW );
aScreen->SetModify();
RefreshItem( aItem );
UpdateItem( aItem );
if( !aItem->IsMoving() && aItem->IsConnectable() )
{
@ -978,7 +978,7 @@ void SCH_EDIT_FRAME::AddItemToScreenAndUndoList( SCH_SCREEN* aScreen, SCH_ITEM*
TestDanglingEnds();
for( SCH_ITEM* item : aItem->ConnectedItems( GetCurrentSheet() ) )
RefreshItem( item );
UpdateItem( item );
}
aItem->ClearEditFlags();
@ -1171,7 +1171,7 @@ void SCH_EDIT_FRAME::FocusOnItem( SCH_ITEM* aItem )
{
lastItem->ClearBrightened();
RefreshItem( lastItem );
UpdateItem( lastItem );
lastBrightenedItemID = niluuid;
}
@ -1179,7 +1179,7 @@ void SCH_EDIT_FRAME::FocusOnItem( SCH_ITEM* aItem )
{
aItem->SetBrightened();
RefreshItem( aItem );
UpdateItem( aItem );
lastBrightenedItemID = aItem->m_Uuid;
FocusOnLocation( aItem->GetFocusPosition() );

View File

@ -174,6 +174,13 @@ public:
COLOR4D GetColor() const { return m_color; }
void SetColor( const COLOR4D& aColor ) { m_color = aColor; }
bool operator!=( const STROKE_PARAMS& aOther )
{
return m_width != aOther.m_width
|| m_type != aOther.m_type
|| m_color != aOther.m_color;
}
};

View File

@ -1705,6 +1705,9 @@ void SCH_PAINTER::draw( SCH_BUS_ENTRY_BASE *aEntry, int aLayer )
SCH_LINE line;
bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
if( drawingShadows && !aEntry->IsSelected() )
return;
line.SetLayer( aEntry->Type() == SCH_BUS_WIRE_ENTRY_T ? LAYER_WIRE : LAYER_BUS );
if( aEntry->IsSelected() )
@ -1728,7 +1731,7 @@ void SCH_PAINTER::draw( SCH_BUS_ENTRY_BASE *aEntry, int aLayer )
m_gal->SetIsFill( false );
m_gal->SetIsStroke( true );
m_gal->SetLineWidth( drawingShadows ? getShadowWidth() : 1.0 );
m_gal->SetLineWidth( drawingShadows ? getShadowWidth() : 1.0F );
if( aEntry->IsDanglingStart() )
m_gal->DrawCircle( aEntry->GetPosition(),

View File

@ -65,7 +65,7 @@
// TODO(JE) Debugging only
#include <profile.h>
#include "sch_bus_entry.h"
SCH_SCREEN::SCH_SCREEN( EDA_ITEM* aParent ) :
BASE_SCREEN( aParent, SCH_SCREEN_T ),
@ -327,34 +327,33 @@ std::set<SCH_ITEM*> SCH_SCREEN::MarkConnections( SCH_LINE* aSegment )
std::set<SCH_ITEM*> retval;
std::stack<SCH_LINE*> to_search;
wxCHECK_MSG( ( aSegment ) && ( aSegment->Type() == SCH_LINE_T ), retval,
wxT( "Invalid object pointer." ) );
wxCHECK_MSG( aSegment && aSegment->Type() == SCH_LINE_T, retval, wxT( "Invalid pointer." ) );
to_search.push( aSegment );
while( !to_search.empty() )
{
auto test_item = to_search.top();
SCH_LINE* test_item = to_search.top();
to_search.pop();
for( auto item : Items().Overlapping( SCH_JUNCTION_T, test_item->GetBoundingBox() ) )
for( SCH_ITEM* item : Items().Overlapping( SCH_JUNCTION_T, test_item->GetBoundingBox() ) )
{
if( test_item->IsEndPoint( item->GetPosition() ) )
retval.insert( item );
}
for( auto item : Items().Overlapping( SCH_LINE_T, test_item->GetBoundingBox() ) )
for( SCH_ITEM* item : Items().Overlapping( SCH_LINE_T, test_item->GetBoundingBox() ) )
{
// Skip connecting lines on different layers (e.g. buses)
if( test_item->GetLayer() != item->GetLayer() )
continue;
auto line = static_cast<SCH_LINE*>( item );
SCH_LINE* line = static_cast<SCH_LINE*>( item );
if( ( test_item->IsEndPoint( line->GetStartPoint() )
&& !GetPin( line->GetStartPoint(), NULL, true ) )
|| ( test_item->IsEndPoint( line->GetEndPoint() )
&& !GetPin( line->GetEndPoint(), nullptr, true ) ) )
|| ( test_item->IsEndPoint( line->GetEndPoint() )
&& !GetPin( line->GetEndPoint(), nullptr, true ) ) )
{
auto result = retval.insert( line );
@ -374,29 +373,51 @@ bool SCH_SCREEN::IsJunctionNeeded( const wxPoint& aPosition, bool aNew )
bool has_nonparallel[ sizeof( layers ) ] = { false };
int end_count[ sizeof( layers ) ] = { 0 };
int entry_count = 0;
int pin_count = 0;
std::vector<SCH_LINE*> lines[ sizeof( layers ) ];
for( auto item : Items().Overlapping( aPosition ) )
for( SCH_ITEM* item : Items().Overlapping( aPosition ) )
{
if( item->GetEditFlags() & STRUCT_DELETED )
continue;
if( aNew && ( item->Type() == SCH_JUNCTION_T ) && ( item->HitTest( aPosition ) ) )
return false;
if( ( item->Type() == SCH_LINE_T ) && ( item->HitTest( aPosition, 0 ) ) )
switch( item->Type() )
{
if( item->GetLayer() == LAYER_WIRE )
lines[WIRES].push_back( (SCH_LINE*) item );
else if( item->GetLayer() == LAYER_BUS )
lines[BUSES].push_back( (SCH_LINE*) item );
}
case SCH_JUNCTION_T:
if( aNew && item->HitTest( aPosition ) )
return false;
if( ( ( item->Type() == SCH_COMPONENT_T ) || ( item->Type() == SCH_SHEET_T ) )
&& ( item->IsConnected( aPosition ) ) )
pin_count++;
break;
case SCH_LINE_T:
if( item->HitTest( aPosition, 0 ) )
{
if( item->GetLayer() == LAYER_WIRE )
lines[WIRES].push_back( (SCH_LINE*) item );
else if( item->GetLayer() == LAYER_BUS )
lines[BUSES].push_back( (SCH_LINE*) item );
}
break;
case SCH_BUS_WIRE_ENTRY_T:
case SCH_BUS_BUS_ENTRY_T:
if( item->IsConnected( aPosition ) )
entry_count++;
break;
case SCH_COMPONENT_T:
case SCH_SHEET_T:
if( item->IsConnected( aPosition ) )
pin_count++;
break;
default:
break;
}
}
for( int i : { WIRES, BUSES } )
@ -448,6 +469,10 @@ bool SCH_SCREEN::IsJunctionNeeded( const wxPoint& aPosition, bool aNew )
if( has_nonparallel[BUSES] && end_count[BUSES] > 2 )
return true;
// Check for bus - bus entry requirements
if( !aNew && entry_count && end_count[BUSES] )
return true;
return false;
}

View File

@ -138,7 +138,7 @@ int LIB_EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
{
item = static_cast<LIB_ITEM*>( selection.GetItem( ii ) );
item->Rotate( rotPoint, ccw );
m_frame->RefreshItem( item );
m_frame->UpdateItem( item );
}
if( item->IsMoving() )
@ -185,7 +185,7 @@ int LIB_EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent )
else
item->MirrorHorizontal( mirrorPoint );
m_frame->RefreshItem( item );
m_frame->UpdateItem( item );
}
m_toolMgr->PostEvent( EVENTS::SelectedItemsModified );

View File

@ -166,7 +166,7 @@ bool LIB_PIN_TOOL::EditPinProperties( LIB_PIN* aPin )
}
}
m_frame->RefreshItem( aPin );
m_frame->UpdateItem( aPin );
m_frame->OnModify( );
MSG_PANEL_ITEMS items;

View File

@ -506,7 +506,7 @@ int SCH_EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
}
connections = item->IsConnectable();
m_frame->RefreshItem( item );
m_frame->UpdateItem( item );
}
else if( selection.GetSize() > 1 )
{
@ -553,7 +553,7 @@ int SCH_EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
}
connections |= item->IsConnectable();
m_frame->RefreshItem( item );
m_frame->UpdateItem( item );
}
}
@ -690,7 +690,7 @@ int SCH_EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent )
}
connections = item->IsConnectable();
m_frame->RefreshItem( item );
m_frame->UpdateItem( item );
}
else if( selection.GetSize() > 1 )
{
@ -730,7 +730,7 @@ int SCH_EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent )
}
connections |= item->IsConnectable();
m_frame->RefreshItem( item );
m_frame->UpdateItem( item );
}
}
@ -1139,7 +1139,7 @@ void SCH_EDIT_TOOL::editFieldText( SCH_FIELD* aField )
static_cast<SCH_ITEM*>( aField->GetParent() )->AutoAutoplaceFields( m_frame->GetScreen() );
m_toolMgr->PostEvent( EVENTS::SelectedItemsModified );
m_frame->RefreshItem( aField );
m_frame->UpdateItem( aField );
m_frame->OnModify();
}

View File

@ -486,7 +486,7 @@ int SCH_EDITOR_CONTROL::ReplaceAndFindNext( const TOOL_EVENT& aEvent )
{
if( item->Replace( *data, &m_frame->GetCurrentSheet() ) )
{
m_frame->RefreshItem( item );
m_frame->UpdateItem( item );
m_frame->OnModify();
}
@ -513,7 +513,7 @@ int SCH_EDITOR_CONTROL::ReplaceAll( const TOOL_EVENT& aEvent )
{
if( item->Replace( *data, schematic.FindSheetForScreen( screen ) ) )
{
m_frame->RefreshItem( item );
m_frame->UpdateItem( item );
m_frame->OnModify();
}

View File

@ -651,7 +651,7 @@ int SCH_LINE_WIRE_BUS_TOOL::doDrawSegments( const std::string& aTool, int aType
m_busUnfold.flipY = flipY;
m_busUnfold.flipX = flipX;
m_frame->RefreshItem( entry );
m_frame->UpdateItem( entry );
m_wires.front()->SetStartPoint( entry->m_End() );
}