Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8ad2755ae3 | |||
| c90d9b7ebe | |||
| 613f13c576 | |||
| 4d8269c5fd | |||
| 99ac73630a | |||
| bec70ff39d | |||
| cd5827a694 | |||
| a32e7a44e3 | |||
| 8c3c82153d | |||
| 28e433cc54 | |||
| 3fd353d837 | |||
| f238e09990 | |||
| b0b523bfdb | |||
| e5ef33d227 |
@@ -37,7 +37,7 @@
|
||||
# KiCad.
|
||||
#
|
||||
# Note: This version string should follow the semantic versioning system
|
||||
set( KICAD_SEMANTIC_VERSION "7.0.11" )
|
||||
set( KICAD_SEMANTIC_VERSION "7.0.11-unknown" )
|
||||
|
||||
# Default the version to the semantic version.
|
||||
# This is overridden by the git repository tag though (if using git)
|
||||
|
||||
@@ -569,7 +569,7 @@ TOOL_ACTION ACTIONS::selectionTool( "common.InteractiveSelection.selectionTool",
|
||||
_( "Select item(s)" ), _( "Select item(s)" ),
|
||||
BITMAPS::cursor, AF_ACTIVATE );
|
||||
|
||||
TOOL_ACTION ACTIONS::measureTool( "common.InteractiveEdit.measureTool",
|
||||
TOOL_ACTION ACTIONS::measureTool( "common.Interactive.measureTool",
|
||||
AS_GLOBAL,
|
||||
// Don't be tempted to remove "Modern Toolset only". It's in the legacy property name.
|
||||
MD_CTRL + MD_SHIFT + 'M', LEGACY_HK_NAME( "Measure Distance (Modern Toolset only)" ),
|
||||
|
||||
@@ -360,7 +360,8 @@ void PAGED_DIALOG::onCharHook( wxKeyEvent& aEvent )
|
||||
{
|
||||
if( dynamic_cast<wxTextEntry*>( aEvent.GetEventObject() )
|
||||
|| dynamic_cast<wxStyledTextCtrl*>( aEvent.GetEventObject() )
|
||||
|| dynamic_cast<wxListView*>( aEvent.GetEventObject() ) )
|
||||
|| dynamic_cast<wxListView*>( aEvent.GetEventObject() )
|
||||
|| dynamic_cast<wxGrid*>( FindFocus() ) )
|
||||
{
|
||||
aEvent.Skip();
|
||||
return;
|
||||
@@ -378,7 +379,7 @@ void PAGED_DIALOG::onCharHook( wxKeyEvent& aEvent )
|
||||
m_treebook->SetSelection( page - 1 );
|
||||
}
|
||||
|
||||
m_treebook->GetTreeCtrl()->SetFocus(); // Don't allow preview canvas to steal focus
|
||||
m_treebook->GetTreeCtrl()->SetFocus(); // Don't allow preview canvas to steal gridFocus
|
||||
}
|
||||
else if( aEvent.GetKeyCode() == WXK_DOWN )
|
||||
{
|
||||
@@ -386,7 +387,7 @@ void PAGED_DIALOG::onCharHook( wxKeyEvent& aEvent )
|
||||
|
||||
m_treebook->SetSelection( std::min<int>( page + 1, m_treebook->GetPageCount() - 1 ) );
|
||||
|
||||
m_treebook->GetTreeCtrl()->SetFocus(); // Don't allow preview canvas to steal focus
|
||||
m_treebook->GetTreeCtrl()->SetFocus(); // Don't allow preview canvas to steal gridFocus
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -185,6 +185,28 @@ bool SCH_EDIT_FRAME::SchematicCleanUp( SCH_SCREEN* aScreen )
|
||||
} );
|
||||
|
||||
|
||||
auto minX = []( const SCH_LINE* l )
|
||||
{
|
||||
return std::min( l->GetStartPoint().x, l->GetEndPoint().x );
|
||||
};
|
||||
|
||||
auto maxX = []( const SCH_LINE* l )
|
||||
{
|
||||
return std::max( l->GetStartPoint().x, l->GetEndPoint().x );
|
||||
};
|
||||
|
||||
auto minY = []( const SCH_LINE* l )
|
||||
{
|
||||
return std::min( l->GetStartPoint().y, l->GetEndPoint().y );
|
||||
};
|
||||
|
||||
auto maxY = []( const SCH_LINE* l )
|
||||
{
|
||||
return std::max( l->GetStartPoint().y, l->GetEndPoint().y );
|
||||
};
|
||||
|
||||
// Would be nice to put lines in a canonical form here by swapping
|
||||
// start <-> end as needed but I don't know what swapping breaks.
|
||||
while( changed )
|
||||
{
|
||||
changed = false;
|
||||
@@ -196,6 +218,13 @@ bool SCH_EDIT_FRAME::SchematicCleanUp( SCH_SCREEN* aScreen )
|
||||
lines.push_back( static_cast<SCH_LINE*>( item ) );
|
||||
}
|
||||
|
||||
// Sort by minimum X position
|
||||
std::sort( lines.begin(), lines.end(),
|
||||
[&]( const SCH_LINE* a, const SCH_LINE* b )
|
||||
{
|
||||
return minX( a ) < minX( b );
|
||||
} );
|
||||
|
||||
for( auto it1 = lines.begin(); it1 != lines.end(); ++it1 )
|
||||
{
|
||||
SCH_LINE* firstLine = *it1;
|
||||
@@ -209,11 +238,24 @@ bool SCH_EDIT_FRAME::SchematicCleanUp( SCH_SCREEN* aScreen )
|
||||
continue;
|
||||
}
|
||||
|
||||
int firstRightXEdge = maxX( firstLine );
|
||||
auto it2 = it1;
|
||||
|
||||
for( ++it2; it2 != lines.end(); ++it2 )
|
||||
{
|
||||
SCH_LINE* secondLine = *it2;
|
||||
int secondLeftXEdge = minX( secondLine );
|
||||
|
||||
// impossible to overlap remaining lines
|
||||
if( secondLeftXEdge > firstRightXEdge )
|
||||
break;
|
||||
|
||||
// No Y axis overlap
|
||||
if( !( std::max( minY( firstLine ), minY( secondLine ) )
|
||||
<= std::min( maxY( firstLine ), maxY( secondLine ) ) ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if( secondLine->GetFlags() & STRUCT_DELETED )
|
||||
continue;
|
||||
|
||||
@@ -238,7 +238,7 @@ void PANEL_EESCHEMA_COLOR_SETTINGS::createPreviewItems()
|
||||
{
|
||||
KIGFX::VIEW* view = m_preview->GetView();
|
||||
|
||||
std::vector<DANGLING_END_ITEM> endPoints;
|
||||
std::vector<DANGLING_END_ITEM> endPointsByType;
|
||||
|
||||
m_page = new PAGE_INFO( PAGE_INFO::Custom );
|
||||
m_titleBlock = new TITLE_BLOCK;
|
||||
@@ -396,7 +396,7 @@ void PANEL_EESCHEMA_COLOR_SETTINGS::createPreviewItems()
|
||||
pin->SetNumber( wxT( "1" ) );
|
||||
pin->SetName( wxT( "-" ) );
|
||||
|
||||
endPoints.emplace_back( PIN_END, pin, mapLibItemPosition( pin->GetPosition() ) );
|
||||
endPointsByType.emplace_back( PIN_END, pin, mapLibItemPosition( pin->GetPosition() ) );
|
||||
symbol->AddDrawItem( pin );
|
||||
|
||||
pin = new LIB_PIN( symbol );
|
||||
@@ -408,7 +408,7 @@ void PANEL_EESCHEMA_COLOR_SETTINGS::createPreviewItems()
|
||||
pin->SetNumber( wxT( "2" ) );
|
||||
pin->SetName( wxT( "+" ) );
|
||||
|
||||
endPoints.emplace_back( PIN_END, pin, mapLibItemPosition( pin->GetPosition() ) );
|
||||
endPointsByType.emplace_back( PIN_END, pin, mapLibItemPosition( pin->GetPosition() ) );
|
||||
symbol->AddDrawItem( pin );
|
||||
|
||||
pin = new LIB_PIN( symbol );
|
||||
@@ -420,7 +420,7 @@ void PANEL_EESCHEMA_COLOR_SETTINGS::createPreviewItems()
|
||||
pin->SetNumber( wxT( "3" ) );
|
||||
pin->SetName( wxT( "OUT" ) );
|
||||
|
||||
endPoints.emplace_back( PIN_END, pin, mapLibItemPosition( pin->GetPosition() ) );
|
||||
endPointsByType.emplace_back( PIN_END, pin, mapLibItemPosition( pin->GetPosition() ) );
|
||||
symbol->AddDrawItem( pin );
|
||||
|
||||
addItem( symbol );
|
||||
@@ -445,16 +445,19 @@ void PANEL_EESCHEMA_COLOR_SETTINGS::createPreviewItems()
|
||||
if( sch_item && sch_item->IsConnectable() )
|
||||
{
|
||||
sch_item->AutoplaceFields( nullptr, false );
|
||||
sch_item->GetEndPoints( endPoints );
|
||||
sch_item->GetEndPoints( endPointsByType );
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<DANGLING_END_ITEM> endPointsByPos = endPointsByType;
|
||||
DANGLING_END_ITEM_HELPER::sort_dangling_end_items( endPointsByType, endPointsByPos );
|
||||
|
||||
for( EDA_ITEM* item : m_previewItems )
|
||||
{
|
||||
SCH_ITEM* sch_item = dynamic_cast<SCH_ITEM*>( item );
|
||||
|
||||
if( sch_item && sch_item->IsConnectable() )
|
||||
sch_item->UpdateDanglingState( endPoints, nullptr );
|
||||
sch_item->UpdateDanglingState( endPointsByType, endPointsByPos, nullptr );
|
||||
}
|
||||
|
||||
zoomFitPreview();
|
||||
|
||||
+13
-10
@@ -304,8 +304,9 @@ void SCH_BUS_ENTRY_BASE::Rotate( const VECTOR2I& aCenter )
|
||||
}
|
||||
|
||||
|
||||
bool SCH_BUS_WIRE_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
bool SCH_BUS_WIRE_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
{
|
||||
bool previousStateStart = m_isDanglingStart;
|
||||
bool previousStateEnd = m_isDanglingEnd;
|
||||
@@ -316,9 +317,9 @@ bool SCH_BUS_WIRE_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aI
|
||||
bool has_wire[2] = { false };
|
||||
bool has_bus[2] = { false };
|
||||
|
||||
for( unsigned ii = 0; ii < aItemList.size(); ii++ )
|
||||
for( unsigned ii = 0; ii < aItemListByType.size(); ii++ )
|
||||
{
|
||||
DANGLING_END_ITEM& item = aItemList[ii];
|
||||
DANGLING_END_ITEM& item = aItemListByType[ii];
|
||||
|
||||
if( item.GetItem() == this )
|
||||
continue;
|
||||
@@ -336,7 +337,7 @@ bool SCH_BUS_WIRE_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aI
|
||||
case BUS_END:
|
||||
{
|
||||
// The bus has created 2 DANGLING_END_ITEMs, one per end.
|
||||
DANGLING_END_ITEM& nextItem = aItemList[++ii];
|
||||
DANGLING_END_ITEM& nextItem = aItemListByType[++ii];
|
||||
|
||||
if( IsPointOnSegment( item.GetPosition(), nextItem.GetPosition(), m_pos ) )
|
||||
has_bus[0] = true;
|
||||
@@ -363,17 +364,19 @@ bool SCH_BUS_WIRE_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aI
|
||||
}
|
||||
|
||||
|
||||
bool SCH_BUS_BUS_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
bool SCH_BUS_BUS_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
{
|
||||
bool previousStateStart = m_isDanglingStart;
|
||||
bool previousStateEnd = m_isDanglingEnd;
|
||||
|
||||
m_isDanglingStart = m_isDanglingEnd = true;
|
||||
|
||||
for( unsigned ii = 0; ii < aItemList.size(); ii++ )
|
||||
// TODO: filter using get_lower as we only use one item type
|
||||
for( unsigned ii = 0; ii < aItemListByType.size(); ii++ )
|
||||
{
|
||||
DANGLING_END_ITEM& item = aItemList[ii];
|
||||
DANGLING_END_ITEM& item = aItemListByType[ii];
|
||||
|
||||
if( item.GetItem() == this )
|
||||
continue;
|
||||
@@ -383,7 +386,7 @@ bool SCH_BUS_BUS_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aIt
|
||||
case BUS_END:
|
||||
{
|
||||
// The bus has created 2 DANGLING_END_ITEMs, one per end.
|
||||
DANGLING_END_ITEM& nextItem = aItemList[++ii];
|
||||
DANGLING_END_ITEM& nextItem = aItemListByType[++ii];
|
||||
|
||||
if( IsPointOnSegment( item.GetPosition(), nextItem.GetPosition(), m_pos ) )
|
||||
m_isDanglingStart = false;
|
||||
|
||||
@@ -188,8 +188,9 @@ public:
|
||||
|
||||
BITMAPS GetMenuImage() const override;
|
||||
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
|
||||
/**
|
||||
* Pointer to the bus item (usually a bus wire) connected to this bus-wire
|
||||
@@ -233,8 +234,9 @@ public:
|
||||
|
||||
BITMAPS GetMenuImage() const override;
|
||||
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
|
||||
/**
|
||||
* Pointer to the bus items (usually bus wires) connected to this bus-bus
|
||||
|
||||
@@ -316,3 +316,50 @@ void SCH_ITEM::Plot( PLOTTER* aPlotter, bool aBackground ) const
|
||||
{
|
||||
wxFAIL_MSG( wxT( "Plot() method not implemented for class " ) + GetClass() );
|
||||
}
|
||||
|
||||
|
||||
static bool lessYX( const DANGLING_END_ITEM& a, const DANGLING_END_ITEM& b )
|
||||
{
|
||||
const auto aPos = a.GetPosition();
|
||||
const auto bPos = b.GetPosition();
|
||||
return aPos.y < bPos.y ? true : ( aPos.y > bPos.y ? false : aPos.x < bPos.x );
|
||||
};
|
||||
|
||||
|
||||
static bool lessType( const DANGLING_END_ITEM& a, const DANGLING_END_ITEM& b )
|
||||
{
|
||||
return a.GetType() < b.GetType();
|
||||
};
|
||||
|
||||
|
||||
std::vector<DANGLING_END_ITEM>::iterator
|
||||
DANGLING_END_ITEM_HELPER::get_lower_pos( std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const VECTOR2I& aPos )
|
||||
{
|
||||
DANGLING_END_ITEM needle = DANGLING_END_ITEM( PIN_END, nullptr, aPos );
|
||||
auto start = aItemListByPos.begin();
|
||||
auto end = aItemListByPos.end();
|
||||
return std::lower_bound( start, end, needle, lessYX );
|
||||
}
|
||||
|
||||
|
||||
std::vector<DANGLING_END_ITEM>::iterator
|
||||
DANGLING_END_ITEM_HELPER::get_lower_type( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
const DANGLING_END_T& aType )
|
||||
{
|
||||
DANGLING_END_ITEM needle = DANGLING_END_ITEM( aType, nullptr, VECTOR2I{} );
|
||||
auto start = aItemListByType.begin();
|
||||
auto end = aItemListByType.end();
|
||||
return std::lower_bound( start, end, needle, lessType );
|
||||
}
|
||||
|
||||
|
||||
void DANGLING_END_ITEM_HELPER::sort_dangling_end_items(
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos )
|
||||
{
|
||||
// WIRE_END pairs must be kept together. Hence stable sort.
|
||||
std::stable_sort( aItemListByType.begin(), aItemListByType.end(), lessType );
|
||||
// Sort by y first, pins are more likely to share x than y.
|
||||
std::sort( aItemListByPos.begin(), aItemListByPos.end(), lessYX );
|
||||
}
|
||||
|
||||
+20
-3
@@ -133,6 +133,20 @@ private:
|
||||
};
|
||||
|
||||
|
||||
class DANGLING_END_ITEM_HELPER
|
||||
{
|
||||
public:
|
||||
static std::vector<DANGLING_END_ITEM>::iterator
|
||||
get_lower_pos( std::vector<DANGLING_END_ITEM>& aItemListByPos, const VECTOR2I& aPos );
|
||||
|
||||
static std::vector<DANGLING_END_ITEM>::iterator
|
||||
get_lower_type( std::vector<DANGLING_END_ITEM>& aItemListByType, const DANGLING_END_T& aType );
|
||||
|
||||
/** Both contain the same information */
|
||||
static void sort_dangling_end_items( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos );
|
||||
};
|
||||
|
||||
typedef std::vector<SCH_ITEM*> SCH_ITEM_SET;
|
||||
|
||||
|
||||
@@ -329,12 +343,15 @@ public:
|
||||
* If aSheet is passed a non-null pointer to a SCH_SHEET_PATH, the overridden method can
|
||||
* optionally use it to update sheet-local connectivity information
|
||||
*
|
||||
* @param aItemList is the list of items to test item against.
|
||||
* @param aItemListByType is the list of items to test item against. It's sorted
|
||||
* by item type, keeping WIRE_END pairs together.
|
||||
* @param aItemListByPos is the same list but sorted first by Y then by X.
|
||||
* @param aSheet is the sheet path to update connections for.
|
||||
* @return True if the dangling state has changed from it's current setting.
|
||||
*/
|
||||
virtual bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath = nullptr )
|
||||
virtual bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath = nullptr )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
+58
-27
@@ -868,16 +868,19 @@ bool SCH_LABEL_BASE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy
|
||||
}
|
||||
|
||||
|
||||
bool SCH_LABEL_BASE::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
bool SCH_LABEL_BASE::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
{
|
||||
bool previousState = m_isDangling;
|
||||
m_isDangling = true;
|
||||
bool previousState = m_isDangling;
|
||||
VECTOR2I text_pos = GetTextPos();
|
||||
m_isDangling = true;
|
||||
m_connectionType = CONNECTION_TYPE::NONE;
|
||||
|
||||
for( unsigned ii = 0; ii < aItemList.size(); ii++ )
|
||||
for( auto it = DANGLING_END_ITEM_HELPER::get_lower_pos( aItemListByPos, text_pos );
|
||||
it < aItemListByPos.end() && it->GetPosition() == text_pos; it++ )
|
||||
{
|
||||
DANGLING_END_ITEM& item = aItemList[ii];
|
||||
DANGLING_END_ITEM& item = *it;
|
||||
|
||||
if( item.GetItem() == this )
|
||||
continue;
|
||||
@@ -888,33 +891,68 @@ bool SCH_LABEL_BASE::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemL
|
||||
case LABEL_END:
|
||||
case SHEET_LABEL_END:
|
||||
case NO_CONNECT_END:
|
||||
if( GetTextPos() == item.GetPosition() )
|
||||
if( text_pos == item.GetPosition() )
|
||||
{
|
||||
m_isDangling = false;
|
||||
|
||||
if( aPath && item.GetType() != PIN_END )
|
||||
AddConnectionTo( *aPath, static_cast<SCH_ITEM*>( item.GetItem() ) );
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case BUS_END:
|
||||
m_connectionType = CONNECTION_TYPE::BUS;
|
||||
KI_FALLTHROUGH;
|
||||
default: break;
|
||||
}
|
||||
|
||||
case WIRE_END:
|
||||
if( !m_isDangling )
|
||||
break;
|
||||
}
|
||||
|
||||
if( m_isDangling )
|
||||
{
|
||||
for( auto it = DANGLING_END_ITEM_HELPER::get_lower_type( aItemListByType, BUS_END );
|
||||
it < aItemListByType.end() && it->GetType() == BUS_END; it++ )
|
||||
{
|
||||
DANGLING_END_ITEM& nextItem = aItemList[++ii];
|
||||
DANGLING_END_ITEM& item = *it;
|
||||
DANGLING_END_ITEM& nextItem = *( ++it );
|
||||
|
||||
int accuracy = 1; // We have rounding issues with an accuracy of 0
|
||||
int accuracy = 1; // We have rounding issues with an accuracy of 0
|
||||
|
||||
m_isDangling = !TestSegmentHit( GetTextPos(), item.GetPosition(),
|
||||
nextItem.GetPosition(), accuracy );
|
||||
m_isDangling = !TestSegmentHit( text_pos, item.GetPosition(), nextItem.GetPosition(),
|
||||
accuracy );
|
||||
|
||||
if( !m_isDangling )
|
||||
if( m_isDangling )
|
||||
continue;
|
||||
|
||||
m_connectionType = CONNECTION_TYPE::BUS;
|
||||
|
||||
// Add the line to the connected items, since it won't be picked
|
||||
// up by a search of intersecting connection points
|
||||
if( aPath )
|
||||
{
|
||||
if( m_connectionType != CONNECTION_TYPE::BUS )
|
||||
m_connectionType = CONNECTION_TYPE::NET;
|
||||
auto sch_item = static_cast<SCH_ITEM*>( item.GetItem() );
|
||||
AddConnectionTo( *aPath, sch_item );
|
||||
sch_item->AddConnectionTo( *aPath, this );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if( m_isDangling )
|
||||
{
|
||||
for( auto it = DANGLING_END_ITEM_HELPER::get_lower_type( aItemListByType, WIRE_END );
|
||||
it < aItemListByType.end() && it->GetType() == WIRE_END; it++ )
|
||||
{
|
||||
DANGLING_END_ITEM& item = *it;
|
||||
DANGLING_END_ITEM& nextItem = *( ++it );
|
||||
|
||||
int accuracy = 1; // We have rounding issues with an accuracy of 0
|
||||
|
||||
m_isDangling = !TestSegmentHit( text_pos, item.GetPosition(),
|
||||
nextItem.GetPosition(), accuracy );
|
||||
|
||||
if( m_isDangling )
|
||||
continue;
|
||||
|
||||
m_connectionType = CONNECTION_TYPE::NET;
|
||||
|
||||
// Add the line to the connected items, since it won't be picked
|
||||
// up by a search of intersecting connection points
|
||||
@@ -924,16 +962,9 @@ bool SCH_LABEL_BASE::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemL
|
||||
AddConnectionTo( *aPath, sch_item );
|
||||
sch_item->AddConnectionTo( *aPath, this );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if( !m_isDangling )
|
||||
break;
|
||||
}
|
||||
|
||||
if( m_isDangling )
|
||||
|
||||
@@ -187,8 +187,9 @@ public:
|
||||
|
||||
void GetEndPoints( std::vector< DANGLING_END_ITEM >& aItemList ) override;
|
||||
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
|
||||
bool IsDangling() const override { return m_isDangling; }
|
||||
void SetIsDangling( bool aIsDangling ) { m_isDangling = aIsDangling; }
|
||||
|
||||
+42
-30
@@ -580,44 +580,56 @@ void SCH_LINE::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
|
||||
}
|
||||
|
||||
|
||||
bool SCH_LINE::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
bool SCH_LINE::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
{
|
||||
if( IsConnectable() )
|
||||
if( !IsConnectable() )
|
||||
return false;
|
||||
|
||||
bool previousStartState = m_startIsDangling;
|
||||
bool previousEndState = m_endIsDangling;
|
||||
|
||||
m_startIsDangling = m_endIsDangling = true;
|
||||
|
||||
for( auto it = DANGLING_END_ITEM_HELPER::get_lower_pos( aItemListByPos, m_start );
|
||||
it < aItemListByPos.end() && it->GetPosition() == m_start; it++ )
|
||||
{
|
||||
bool previousStartState = m_startIsDangling;
|
||||
bool previousEndState = m_endIsDangling;
|
||||
DANGLING_END_ITEM& item = *it;
|
||||
|
||||
m_startIsDangling = m_endIsDangling = true;
|
||||
if( item.GetItem() == this )
|
||||
continue;
|
||||
|
||||
for( DANGLING_END_ITEM item : aItemList )
|
||||
if( ( IsWire() && item.GetType() != BUS_END && item.GetType() != BUS_ENTRY_END )
|
||||
|| ( IsBus() && item.GetType() != WIRE_END && item.GetType() != PIN_END ) )
|
||||
{
|
||||
if( item.GetItem() == this )
|
||||
continue;
|
||||
|
||||
if( ( IsWire() && item.GetType() != BUS_END && item.GetType() != BUS_ENTRY_END )
|
||||
|| ( IsBus() && item.GetType() != WIRE_END && item.GetType() != PIN_END ) )
|
||||
{
|
||||
if( m_start == item.GetPosition() )
|
||||
m_startIsDangling = false;
|
||||
|
||||
if( m_end == item.GetPosition() )
|
||||
m_endIsDangling = false;
|
||||
|
||||
if( !m_startIsDangling && !m_endIsDangling )
|
||||
break;
|
||||
}
|
||||
m_startIsDangling = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// We only use the bus dangling state for automatic line starting, so we don't care if it
|
||||
// has changed or not (and returning true will result in extra work)
|
||||
if( IsBus() )
|
||||
return false;
|
||||
|
||||
return previousStartState != m_startIsDangling || previousEndState != m_endIsDangling;
|
||||
}
|
||||
|
||||
return false;
|
||||
for( auto it = DANGLING_END_ITEM_HELPER::get_lower_pos( aItemListByPos, m_end );
|
||||
it < aItemListByPos.end() && it->GetPosition() == m_end; it++ )
|
||||
{
|
||||
DANGLING_END_ITEM& item = *it;
|
||||
|
||||
if( item.GetItem() == this )
|
||||
continue;
|
||||
|
||||
if( ( IsWire() && item.GetType() != BUS_END && item.GetType() != BUS_ENTRY_END )
|
||||
|| ( IsBus() && item.GetType() != WIRE_END && item.GetType() != PIN_END ) )
|
||||
{
|
||||
m_endIsDangling = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// We only use the bus dangling state for automatic line starting, so we don't care if it
|
||||
// has changed or not (and returning true will result in extra work)
|
||||
if( IsBus() )
|
||||
return false;
|
||||
|
||||
return previousStartState != m_startIsDangling || previousEndState != m_endIsDangling;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+3
-2
@@ -251,8 +251,9 @@ public:
|
||||
|
||||
void GetEndPoints( std::vector<DANGLING_END_ITEM>& aItemList ) override;
|
||||
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
|
||||
bool IsStartDangling() const { return m_startIsDangling; }
|
||||
bool IsEndDangling() const { return m_endIsDangling; }
|
||||
|
||||
@@ -790,15 +790,6 @@ LIB_FIELD* SCH_SEXPR_PARSER::parseProperty( std::unique_ptr<LIB_SYMBOL>& aSymbol
|
||||
CurOffset() );
|
||||
}
|
||||
|
||||
if( LIB_FIELD* existingName = aSymbol->FindField( name ) )
|
||||
{
|
||||
if( existingName->GetId() > MANDATORY_FIELDS )
|
||||
{
|
||||
THROW_PARSE_ERROR( wxString::Format( _( "Duplicate field '%s'" ), name ),
|
||||
CurSource(), CurLine(), CurLineNumber(), CurOffset() );
|
||||
}
|
||||
}
|
||||
|
||||
field->SetName( name );
|
||||
|
||||
// Correctly set the ID based on canonical (untranslated) field name
|
||||
|
||||
@@ -675,13 +675,14 @@ void SCH_LEGACY_PLUGIN_CACHE::loadField( std::unique_ptr<LIB_SYMBOL>& aSymbol,
|
||||
if( fieldName.IsEmpty() )
|
||||
return;
|
||||
|
||||
if( aSymbol->FindField( fieldName ) != nullptr )
|
||||
{
|
||||
SCH_PARSE_ERROR( wxString::Format( _( "Duplicate field '%s'" ), fieldName ),
|
||||
aReader, line );
|
||||
}
|
||||
wxString candidateFieldName = fieldName;
|
||||
int suffix = 0;
|
||||
|
||||
field->m_name = fieldName;
|
||||
//Deduplicate field name
|
||||
while( aSymbol->FindField( candidateFieldName ) != nullptr )
|
||||
candidateFieldName = wxString::Format( "%s_%d", fieldName, ++suffix );
|
||||
|
||||
field->m_name = candidateFieldName;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+18
-8
@@ -1370,36 +1370,46 @@ void SCH_SCREEN::TestDanglingEnds( const SCH_SHEET_PATH* aPath,
|
||||
{
|
||||
PROF_TIMER timer( __FUNCTION__ );
|
||||
|
||||
std::vector<DANGLING_END_ITEM> endPoints;
|
||||
std::vector<DANGLING_END_ITEM> endPointsByPos;
|
||||
std::vector<DANGLING_END_ITEM> endPointsByType;
|
||||
|
||||
auto getends =
|
||||
auto get_ends =
|
||||
[&]( SCH_ITEM* item )
|
||||
{
|
||||
if( item->IsConnectable() )
|
||||
item->GetEndPoints( endPoints );
|
||||
item->GetEndPoints( endPointsByType );
|
||||
};
|
||||
|
||||
auto update_state =
|
||||
[&]( SCH_ITEM* item )
|
||||
{
|
||||
if( item->UpdateDanglingState( endPoints, aPath ) )
|
||||
if( item->UpdateDanglingState( endPointsByType, endPointsByPos, aPath ) )
|
||||
{
|
||||
if( aChangedHandler )
|
||||
(*aChangedHandler)( item );
|
||||
( *aChangedHandler )( item );
|
||||
}
|
||||
};
|
||||
|
||||
for( SCH_ITEM* item : Items() )
|
||||
{
|
||||
|
||||
getends( item );
|
||||
item->RunOnChildren( getends );
|
||||
get_ends( item );
|
||||
item->RunOnChildren( get_ends );
|
||||
}
|
||||
|
||||
PROF_TIMER sortTimer( "SCH_SCREEN::TestDanglingEnds pre-sort" );
|
||||
endPointsByPos = endPointsByType;
|
||||
DANGLING_END_ITEM_HELPER::sort_dangling_end_items( endPointsByType, endPointsByPos );
|
||||
sortTimer.Stop();
|
||||
|
||||
if( wxLog::IsAllowedTraceMask( DanglingProfileMask ) )
|
||||
sortTimer.Show();
|
||||
|
||||
for( SCH_ITEM* item : Items() )
|
||||
{
|
||||
update_state( item );
|
||||
item->RunOnChildren( update_state );
|
||||
}
|
||||
|
||||
if( wxLog::IsAllowedTraceMask( DanglingProfileMask ) )
|
||||
timer.Show();
|
||||
}
|
||||
|
||||
@@ -984,13 +984,14 @@ void SCH_SHEET::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
|
||||
}
|
||||
|
||||
|
||||
bool SCH_SHEET::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
bool SCH_SHEET::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
for( SCH_SHEET_PIN* sheetPin : m_pins )
|
||||
changed |= sheetPin->UpdateDanglingState( aItemList );
|
||||
changed |= sheetPin->UpdateDanglingState( aItemListByType, aItemListByPos );
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
@@ -343,8 +343,9 @@ public:
|
||||
|
||||
void GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList ) override;
|
||||
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
|
||||
bool IsConnectable() const override { return true; }
|
||||
|
||||
|
||||
+11
-8
@@ -1954,8 +1954,9 @@ void SCH_SYMBOL::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
|
||||
}
|
||||
|
||||
|
||||
bool SCH_SYMBOL::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
bool SCH_SYMBOL::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
@@ -1966,8 +1967,12 @@ bool SCH_SYMBOL::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
|
||||
VECTOR2I pos = m_transform.TransformCoordinate( pin->GetLocalPosition() ) + m_pos;
|
||||
|
||||
for( DANGLING_END_ITEM& each_item : aItemList )
|
||||
auto lower = DANGLING_END_ITEM_HELPER::get_lower_pos( aItemListByPos, pos );
|
||||
bool do_break = false;
|
||||
|
||||
for( auto it = lower; it < aItemListByPos.end() && it->GetPosition() == pos; it++ )
|
||||
{
|
||||
DANGLING_END_ITEM& each_item = *it;
|
||||
// Some people like to stack pins on top of each other in a symbol to indicate
|
||||
// internal connection. While technically connected, it is not particularly useful
|
||||
// to display them that way, so skip any pins that are in the same symbol as this
|
||||
@@ -1983,17 +1988,15 @@ bool SCH_SYMBOL::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
case WIRE_END:
|
||||
case NO_CONNECT_END:
|
||||
case JUNCTION_END:
|
||||
|
||||
if( pos == each_item.GetPosition() )
|
||||
pin->SetIsDangling( false );
|
||||
|
||||
pin->SetIsDangling( false );
|
||||
do_break = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if( !pin->IsDangling() )
|
||||
if( do_break )
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -662,8 +662,9 @@ public:
|
||||
* @param aItemList is list of all #DANGLING_END_ITEM items to be tested.
|
||||
* @return true if any pin's state has changed.
|
||||
*/
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
|
||||
VECTOR2I GetPinPhysicalPosition( const LIB_PIN* Pin ) const;
|
||||
|
||||
|
||||
@@ -75,6 +75,14 @@
|
||||
#include <wx/filedlg.h>
|
||||
|
||||
|
||||
/**
|
||||
* Flag to enable schematic paste debugging output.
|
||||
*
|
||||
* @ingroup trace_env_vars
|
||||
*/
|
||||
static const wxChar traceSchPaste[] = wxT( "KICAD_SCH_PASTE" );
|
||||
|
||||
|
||||
int SCH_EDITOR_CONTROL::New( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
m_frame->NewProject();
|
||||
@@ -1435,12 +1443,16 @@ void SCH_EDITOR_CONTROL::updatePastedSymbol( SCH_SYMBOL* aSymbol,
|
||||
|
||||
for( const SCH_SYMBOL_INSTANCE& tmp : aSymbol->GetInstanceReferences() )
|
||||
{
|
||||
if( tmp.m_Path.EndsWith( aClipPath ) )
|
||||
if( ( tmp.m_Path.empty() && aClipPath.empty() )
|
||||
|| ( !aClipPath.empty() && tmp.m_Path.EndsWith( aClipPath ) ) )
|
||||
{
|
||||
newInstance = tmp;
|
||||
instanceFound = true;
|
||||
|
||||
wxLogDebug( wxS( "Pasting found symbol instance:\n\tpath: %s\n\tuuid: %s." ),
|
||||
wxLogTrace( traceSchPaste,
|
||||
wxS( "Pasting found symbol instance with reference %s, unit %d:"
|
||||
"\n\tClipboard path: %s\n\tSymbol UUID: %s." ),
|
||||
tmp.m_Reference, tmp.m_Unit,
|
||||
aClipPath.AsString(), aSymbol->m_Uuid.AsString() );
|
||||
|
||||
break;
|
||||
@@ -1452,7 +1464,9 @@ void SCH_EDITOR_CONTROL::updatePastedSymbol( SCH_SYMBOL* aSymbol,
|
||||
|
||||
if( !instanceFound )
|
||||
{
|
||||
wxLogDebug( wxS( "Clipboard symbol instance **not** found:\n\tpath: %s\n\tuuid: %s." ),
|
||||
wxLogTrace( traceSchPaste,
|
||||
wxS( "Clipboard symbol instance **not** found:\n\tClipboard path: %s\n\t"
|
||||
"Symbol UUID: %s." ),
|
||||
aClipPath.AsString(), aSymbol->m_Uuid.AsString() );
|
||||
|
||||
// Some legacy versions saved value fields escaped. While we still do in the symbol
|
||||
@@ -1484,7 +1498,8 @@ SCH_SHEET_PATH SCH_EDITOR_CONTROL::updatePastedSheet( SCH_SHEET* aSheet,
|
||||
const KIID_PATH& aClipPath,
|
||||
bool aForceKeepAnnotations,
|
||||
SCH_SHEET_LIST* aPastedSheets,
|
||||
std::map<SCH_SHEET_PATH, SCH_REFERENCE_LIST>& aPastedSymbols )
|
||||
std::map<SCH_SHEET_PATH,
|
||||
SCH_REFERENCE_LIST>& aPastedSymbols )
|
||||
{
|
||||
wxCHECK( aSheet && aPastedSheets, aPastePath );
|
||||
|
||||
|
||||
@@ -406,12 +406,14 @@ SCH_LINE* SCH_LINE_WIRE_BUS_TOOL::doUnfoldBus( const wxString& aNet, const VECTO
|
||||
|
||||
getViewControls()->SetCrossHairCursorPosition( m_busUnfold.entry->GetEnd(), false );
|
||||
|
||||
std::vector<DANGLING_END_ITEM> endPoints;
|
||||
std::vector<DANGLING_END_ITEM> endPointsByType;
|
||||
|
||||
for( SCH_ITEM* item : screen->Items().Overlapping( m_busUnfold.entry->GetBoundingBox() ) )
|
||||
item->GetEndPoints( endPoints );
|
||||
item->GetEndPoints( endPointsByType );
|
||||
|
||||
m_busUnfold.entry->UpdateDanglingState( endPoints );
|
||||
std::vector<DANGLING_END_ITEM> endPointsByPos = endPointsByType;
|
||||
DANGLING_END_ITEM_HELPER::sort_dangling_end_items( endPointsByType, endPointsByPos );
|
||||
m_busUnfold.entry->UpdateDanglingState( endPointsByType, endPointsByPos );
|
||||
m_busUnfold.entry->SetEndDangling( false );
|
||||
m_busUnfold.label->SetIsDangling( false );
|
||||
|
||||
|
||||
@@ -569,8 +569,14 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
|
||||
for( EDA_ITEM* item : selection )
|
||||
static_cast<SCH_ITEM*>( item )->GetEndPoints( internalPoints );
|
||||
|
||||
std::vector<DANGLING_END_ITEM> endPointsByType = internalPoints;
|
||||
std::vector<DANGLING_END_ITEM> endPointsByPos = endPointsByType;
|
||||
DANGLING_END_ITEM_HELPER::sort_dangling_end_items( endPointsByType,
|
||||
endPointsByPos );
|
||||
|
||||
for( EDA_ITEM* item : selection )
|
||||
static_cast<SCH_ITEM*>( item )->UpdateDanglingState( internalPoints );
|
||||
static_cast<SCH_ITEM*>( item )->UpdateDanglingState( endPointsByType,
|
||||
endPointsByPos );
|
||||
}
|
||||
|
||||
// Generic setup
|
||||
|
||||
@@ -129,35 +129,35 @@ enum class RATSNEST_MODE
|
||||
*/
|
||||
struct LAYER_PRESET
|
||||
{
|
||||
LAYER_PRESET( const wxString& aName = wxEmptyString ) :
|
||||
LAYER_PRESET( const wxString& aName = wxS( "" ) ) :
|
||||
name( aName ),
|
||||
layers( LSET::AllLayersMask() ),
|
||||
renderLayers( GAL_SET::DefaultVisible() ),
|
||||
flipBoard( false ),
|
||||
activeLayer( UNSELECTED_LAYER )
|
||||
{
|
||||
layers = LSET::AllLayersMask();
|
||||
renderLayers = GAL_SET::DefaultVisible();
|
||||
readOnly = false;
|
||||
flipBoard = false;
|
||||
}
|
||||
|
||||
LAYER_PRESET( const wxString& aName, const LSET& aVisibleLayers ) :
|
||||
LAYER_PRESET( const wxString& aName, const LSET& aVisibleLayers, bool aFlipBoard ) :
|
||||
name( aName ),
|
||||
layers( aVisibleLayers ),
|
||||
renderLayers( GAL_SET::DefaultVisible() ),
|
||||
flipBoard( aFlipBoard ),
|
||||
activeLayer( UNSELECTED_LAYER )
|
||||
{
|
||||
renderLayers = GAL_SET::DefaultVisible();
|
||||
readOnly = false;
|
||||
flipBoard = false;
|
||||
}
|
||||
|
||||
LAYER_PRESET( const wxString& aName, const LSET& aVisibleLayers, const GAL_SET& aVisibleObjects,
|
||||
PCB_LAYER_ID aActiveLayer ) :
|
||||
PCB_LAYER_ID aActiveLayer, bool aFlipBoard ) :
|
||||
name( aName ),
|
||||
layers( aVisibleLayers ),
|
||||
renderLayers( aVisibleObjects ),
|
||||
flipBoard( aFlipBoard ),
|
||||
activeLayer( aActiveLayer )
|
||||
{
|
||||
readOnly = false;
|
||||
flipBoard = false;
|
||||
}
|
||||
|
||||
bool LayersMatch( const LAYER_PRESET& aOther )
|
||||
|
||||
@@ -285,11 +285,15 @@ void DRC_TEST_PROVIDER_MISC::testTextVars()
|
||||
return false;
|
||||
|
||||
BOARD_ITEM* boardItem = dynamic_cast<BOARD_ITEM*>( item );
|
||||
EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( boardItem );
|
||||
EDA_TEXT* textItem = dynamic_cast<EDA_TEXT*>( boardItem );
|
||||
|
||||
wxCHECK( boardItem, false );
|
||||
if( !textItem )
|
||||
return true;
|
||||
|
||||
if( text && text->GetShownText( true ).Matches( wxT( "*${*}*" ) ) )
|
||||
wxString resolved = ExpandEnvVarSubstitutions( textItem->GetShownText( true ),
|
||||
nullptr /*project already done*/ );
|
||||
|
||||
if( resolved.Matches( wxT( "*${*}*" ) ) )
|
||||
{
|
||||
std::shared_ptr<DRC_ITEM>drcItem = DRC_ITEM::Create( DRCE_UNRESOLVED_VARIABLE );
|
||||
drcItem->SetItems( item );
|
||||
|
||||
@@ -502,7 +502,7 @@ void NODE::addSolid( SOLID* aSolid )
|
||||
}
|
||||
|
||||
|
||||
void NODE::Add( std::unique_ptr< SOLID >&& aSolid )
|
||||
void NODE::Add( std::unique_ptr< SOLID > aSolid )
|
||||
{
|
||||
aSolid->SetOwner( this );
|
||||
addSolid( aSolid.release() );
|
||||
@@ -537,7 +537,7 @@ void NODE::addHole( HOLE* aHole )
|
||||
}
|
||||
|
||||
|
||||
void NODE::Add( std::unique_ptr< VIA >&& aVia )
|
||||
void NODE::Add( std::unique_ptr< VIA > aVia )
|
||||
{
|
||||
addVia( aVia.release() );
|
||||
}
|
||||
@@ -630,7 +630,7 @@ void NODE::addSegment( SEGMENT* aSeg )
|
||||
}
|
||||
|
||||
|
||||
bool NODE::Add( std::unique_ptr< SEGMENT >&& aSegment, bool aAllowRedundant )
|
||||
bool NODE::Add( std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant )
|
||||
{
|
||||
if( aSegment->Seg().A == aSegment->Seg().B )
|
||||
{
|
||||
@@ -659,7 +659,7 @@ void NODE::addArc( ARC* aArc )
|
||||
}
|
||||
|
||||
|
||||
bool NODE::Add( std::unique_ptr< ARC >&& aArc, bool aAllowRedundant )
|
||||
bool NODE::Add( std::unique_ptr< ARC > aArc, bool aAllowRedundant )
|
||||
{
|
||||
const SHAPE_ARC& arc = aArc->CArc();
|
||||
|
||||
@@ -811,7 +811,7 @@ void NODE::removeSolidIndex( SOLID* aSolid )
|
||||
}
|
||||
|
||||
|
||||
void NODE::Replace( ITEM* aOldItem, std::unique_ptr< ITEM >&& aNewItem )
|
||||
void NODE::Replace( ITEM* aOldItem, std::unique_ptr< ITEM > aNewItem )
|
||||
{
|
||||
Remove( aOldItem );
|
||||
add( aNewItem.release() );
|
||||
|
||||
@@ -314,10 +314,10 @@ public:
|
||||
* at the same coordinates as an existing one).
|
||||
* @return true if added
|
||||
*/
|
||||
bool Add( std::unique_ptr< SEGMENT >&& aSegment, bool aAllowRedundant = false );
|
||||
void Add( std::unique_ptr< SOLID >&& aSolid );
|
||||
void Add( std::unique_ptr< VIA >&& aVia );
|
||||
bool Add( std::unique_ptr< ARC >&& aArc, bool aAllowRedundant = false );
|
||||
bool Add( std::unique_ptr<SEGMENT> aSegment, bool aAllowRedundant = false );
|
||||
void Add( std::unique_ptr<SOLID> aSolid );
|
||||
void Add( std::unique_ptr<VIA> aVia );
|
||||
bool Add( std::unique_ptr<ARC> aArc, bool aAllowRedundant = false );
|
||||
|
||||
void Add( LINE& aLine, bool aAllowRedundant = false );
|
||||
|
||||
@@ -346,7 +346,7 @@ public:
|
||||
* @param aOldItem item to be removed
|
||||
* @param aNewItem item add instead
|
||||
*/
|
||||
void Replace( ITEM* aOldItem, std::unique_ptr< ITEM >&& aNewItem );
|
||||
void Replace( ITEM* aOldItem, std::unique_ptr< ITEM > aNewItem );
|
||||
void Replace( LINE& aOldLine, LINE& aNewLine );
|
||||
|
||||
/**
|
||||
|
||||
@@ -394,7 +394,12 @@ int PAD_TOOL::EnumeratePads( const TOOL_EVENT& aEvent )
|
||||
collector.Collect( board(), { PCB_PAD_T }, testpoint, guide );
|
||||
|
||||
for( int i = 0; i < collector.GetCount(); ++i )
|
||||
selectedPads.push_back( static_cast<PAD*>( collector[i] ) );
|
||||
{
|
||||
PAD* pad = static_cast<PAD*>( collector[i] );
|
||||
|
||||
if( !pad->IsAperturePad() )
|
||||
selectedPads.push_back( pad );
|
||||
}
|
||||
}
|
||||
|
||||
selectedPads.unique();
|
||||
|
||||
@@ -373,27 +373,28 @@ static std::set<int> s_allowedInFpEditor =
|
||||
|
||||
// These are the built-in layer presets that cannot be deleted
|
||||
|
||||
LAYER_PRESET APPEARANCE_CONTROLS::presetNoLayers( _HKI( "No Layers" ), LSET() );
|
||||
LAYER_PRESET APPEARANCE_CONTROLS::presetNoLayers( _HKI( "No Layers" ), LSET(), false );
|
||||
|
||||
LAYER_PRESET APPEARANCE_CONTROLS::presetAllLayers( _HKI( "All Layers" ), LSET::AllLayersMask() );
|
||||
LAYER_PRESET APPEARANCE_CONTROLS::presetAllLayers( _HKI( "All Layers" ),
|
||||
LSET::AllLayersMask(), false );
|
||||
|
||||
LAYER_PRESET APPEARANCE_CONTROLS::presetAllCopper( _HKI( "All Copper Layers" ),
|
||||
LSET::AllCuMask().set( Edge_Cuts ) );
|
||||
LSET::AllCuMask().set( Edge_Cuts ), false );
|
||||
|
||||
LAYER_PRESET APPEARANCE_CONTROLS::presetInnerCopper( _HKI( "Inner Copper Layers" ),
|
||||
LSET::InternalCuMask().set( Edge_Cuts ) );
|
||||
LSET::InternalCuMask().set( Edge_Cuts ), false );
|
||||
|
||||
LAYER_PRESET APPEARANCE_CONTROLS::presetFront( _HKI( "Front Layers" ),
|
||||
LSET::FrontMask().set( Edge_Cuts ) );
|
||||
LSET::FrontMask().set( Edge_Cuts ), false );
|
||||
|
||||
LAYER_PRESET APPEARANCE_CONTROLS::presetFrontAssembly( _HKI( "Front Assembly View" ),
|
||||
LSET::FrontAssembly().set( Edge_Cuts ), GAL_SET::DefaultVisible(), F_SilkS );
|
||||
LSET::FrontAssembly().set( Edge_Cuts ), GAL_SET::DefaultVisible(), F_SilkS, false );
|
||||
|
||||
LAYER_PRESET APPEARANCE_CONTROLS::presetBack( _HKI( "Back Layers" ),
|
||||
LSET::BackMask().set( Edge_Cuts ) );
|
||||
LSET::BackMask().set( Edge_Cuts ), true );
|
||||
|
||||
LAYER_PRESET APPEARANCE_CONTROLS::presetBackAssembly( _HKI( "Back Assembly View" ),
|
||||
LSET::BackAssembly().set( Edge_Cuts ), GAL_SET::DefaultVisible(), B_SilkS );
|
||||
LSET::BackAssembly().set( Edge_Cuts ), GAL_SET::DefaultVisible(), B_SilkS, true );
|
||||
|
||||
// this one is only used to store the object visibility settings of the last used
|
||||
// built-in layer preset
|
||||
@@ -526,6 +527,7 @@ APPEARANCE_CONTROLS::APPEARANCE_CONTROLS( PCB_BASE_FRAME* aParent, wxWindow* aFo
|
||||
[&]( wxCommandEvent& aEvent )
|
||||
{
|
||||
m_frame->GetToolManager()->RunAction( PCB_ACTIONS::flipBoard, true );
|
||||
syncLayerPresetSelection();
|
||||
} );
|
||||
|
||||
m_toggleGridRenderer = new GRID_BITMAP_TOGGLE_RENDERER( KiBitmap( BITMAPS::visibility ),
|
||||
@@ -2533,12 +2535,14 @@ void APPEARANCE_CONTROLS::syncLayerPresetSelection()
|
||||
{
|
||||
LSET visibleLayers = getVisibleLayers();
|
||||
GAL_SET visibleObjects = getVisibleObjects();
|
||||
bool flipBoard = m_cbFlipBoard->GetValue();
|
||||
|
||||
auto it = std::find_if( m_layerPresets.begin(), m_layerPresets.end(),
|
||||
[&]( const std::pair<const wxString, LAYER_PRESET>& aPair )
|
||||
{
|
||||
return ( aPair.second.layers == visibleLayers
|
||||
&& aPair.second.renderLayers == visibleObjects );
|
||||
&& aPair.second.renderLayers == visibleObjects
|
||||
&& aPair.second.flipBoard == flipBoard );
|
||||
} );
|
||||
|
||||
if( it != m_layerPresets.end() )
|
||||
@@ -2634,8 +2638,8 @@ void APPEARANCE_CONTROLS::onLayerPresetChanged( wxCommandEvent& aEvent )
|
||||
|
||||
if( !exists )
|
||||
{
|
||||
m_layerPresets[name] = LAYER_PRESET( name, getVisibleLayers(),
|
||||
getVisibleObjects(), UNSELECTED_LAYER );
|
||||
m_layerPresets[name] = LAYER_PRESET( name, getVisibleLayers(), getVisibleObjects(),
|
||||
UNSELECTED_LAYER, m_cbFlipBoard->GetValue() );
|
||||
}
|
||||
|
||||
LAYER_PRESET* preset = &m_layerPresets[name];
|
||||
@@ -2644,7 +2648,6 @@ void APPEARANCE_CONTROLS::onLayerPresetChanged( wxCommandEvent& aEvent )
|
||||
if( !exists )
|
||||
{
|
||||
index = m_cbLayerPresets->Insert( name, index - 1, static_cast<void*>( preset ) );
|
||||
preset->flipBoard = m_cbFlipBoard->GetValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2711,7 +2714,7 @@ void APPEARANCE_CONTROLS::onLayerPresetChanged( wxCommandEvent& aEvent )
|
||||
}
|
||||
|
||||
LAYER_PRESET* preset = static_cast<LAYER_PRESET*>( m_cbLayerPresets->GetClientData( index ) );
|
||||
m_currentPreset = preset;
|
||||
m_currentPreset = preset;
|
||||
|
||||
m_lastSelectedUserPreset = ( !preset || preset->readOnly ) ? nullptr : preset;
|
||||
|
||||
@@ -2740,7 +2743,8 @@ void APPEARANCE_CONTROLS::onLayerPresetChanged( wxCommandEvent& aEvent )
|
||||
|
||||
void APPEARANCE_CONTROLS::doApplyLayerPreset( const LAYER_PRESET& aPreset )
|
||||
{
|
||||
BOARD* board = m_frame->GetBoard();
|
||||
BOARD* board = m_frame->GetBoard();
|
||||
KIGFX::PCB_VIEW* view = m_frame->GetCanvas()->GetView();
|
||||
|
||||
setVisibleLayers( aPreset.layers );
|
||||
setVisibleObjects( aPreset.renderLayers );
|
||||
@@ -2762,15 +2766,16 @@ void APPEARANCE_CONTROLS::doApplyLayerPreset( const LAYER_PRESET& aPreset )
|
||||
if( !m_isFpEditor )
|
||||
m_frame->GetCanvas()->SyncLayersVisibility( board );
|
||||
|
||||
if( aPreset.flipBoard )
|
||||
if( aPreset.flipBoard != view->IsMirroredX() )
|
||||
{
|
||||
m_frame->GetCanvas()->GetView()->SetMirror( true, false );
|
||||
m_frame->GetCanvas()->GetView()->RecacheAllItems();
|
||||
view->SetMirror( !view->IsMirroredX(), view->IsMirroredY() );
|
||||
view->RecacheAllItems();
|
||||
}
|
||||
|
||||
m_frame->GetCanvas()->Refresh();
|
||||
|
||||
syncColorsAndVisibility();
|
||||
UpdateDisplayOptions();
|
||||
}
|
||||
|
||||
|
||||
@@ -2913,11 +2918,6 @@ void APPEARANCE_CONTROLS::onViewportChanged( wxCommandEvent& aEvent )
|
||||
void APPEARANCE_CONTROLS::doApplyViewport( const VIEWPORT& aViewport )
|
||||
{
|
||||
m_frame->GetCanvas()->GetView()->SetViewport( aViewport.rect );
|
||||
if( m_cbFlipBoard->GetValue() )
|
||||
{
|
||||
m_frame->GetCanvas()->GetView()->SetMirror( true, false );
|
||||
m_frame->GetCanvas()->GetView()->RecacheAllItems();
|
||||
}
|
||||
m_frame->GetCanvas()->Refresh();
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <stdexcept>
|
||||
#if (!defined(_MSC_VER) || (_MSC_VER > 1600))
|
||||
#include <mutex>
|
||||
#include <chrono>
|
||||
#else
|
||||
#pragma warning(disable : 4482) // non-standard
|
||||
#include <boost/thread/lock_guard.hpp>
|
||||
|
||||
Reference in New Issue
Block a user