Compare commits

...

14 Commits

Author SHA1 Message Date
Mark Roszko 8ad2755ae3 Fix MSVC build error for VC 17.13+
(cherry picked from commit 7eb07c00a2)

50171749 Fix MSVC build in 17.13.2

Co-authored-by: Jan Wichmann <j-wichmann@gmx.net>

(cherry picked from commit d7388e2a70)

Co-authored-by: Mark Roszko <mark.roszko@gmail.com>
2025-02-27 23:42:27 +00:00
Wayne Stambaugh c90d9b7ebe Clean up debugging output accidentally left in previous commit.
(cherry picked from commit 33566f88a9)
2024-03-13 10:49:57 -04:00
Wayne Stambaugh 613f13c576 Fix broken paste special keep existing symbol annotations.
This was only broken for symbols on the sheet where the symbols were
copied from.  The symbol annotation for all sub-sheets was preserved.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/17231

(cherry picked from commit 0ff8d21459)
2024-03-13 09:49:56 -04:00
Seth Hillbrand 4d8269c5fd Correct usage signature for PNS_NODE::Add()
When moving a unique_ptr, you are actually passing the object, not a
reference to the object.  So we either std::move with the bare
unique_ptr parameter or we pass a reference.  But we should never pass
an rvalue reference for this or we'll make a copy without holding the
tracking (because it was moved)

Fixes https://gitlab.com/kicad/code/kicad/-/issues/16839

(cherry picked from commit b2a25cb59e)
(cherry picked from commit 38df918993)
2024-03-01 14:46:40 -08:00
Seth Hillbrand 99ac73630a Do not re-number aperture pads
Aperture pads do not have numbers, so reserving space for them will
cause the actual numbered pads to become out of order

(cherry picked from commit d3334ed9f0)
2024-03-01 13:05:06 -08:00
Jeff Young bec70ff39d Add wxGrids to list of things that get arrow keys.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/17144

(cherry picked from commit f754410c7e)
2024-02-29 18:18:39 +00:00
Jeff Young cd5827a694 Check env vars when testing for unresolved variables.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/17174

(cherry picked from commit 27031dd2c5)
2024-02-29 18:18:39 +00:00
Jeff Young a32e7a44e3 Unflip when going to viewport which isn't flipped.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/13773

(cherry picked from commit c23550dc0b)
2024-02-29 18:18:39 +00:00
Jeff Young 8c3c82153d The ruler tool is not part of InteractiveEdit.
(In particular, it should not return true to IsEditorTool().)

Fixes https://gitlab.com/kicad/code/kicad/-/issues/17164

(cherry picked from commit 48130c6982)
2024-02-29 18:18:39 +00:00
Yon Uriarte 28e433cc54 Performance UpdateDanglingState
Avoid O(N^2) by spatial sorting, don't run checks if the bounding boxes
don't overlap.
A second copy is ordered by type to help classes that only want to check
a few types having to walk the whole list.

(cherry picked from commit b7b64d959f)
2024-02-23 14:56:17 -05:00
Yon Uriarte 3fd353d837 Performance SCH_EDIT_FRAME::SchematicCleanUp
Avoid O(N^2) comparisonis by spatial presorting. If bounding boxes don't
overlap there's no need to run expensive checks.

(cherry picked from commit f3c2083018)
2024-02-23 14:48:35 -05:00
Roberto Fernandez Bautista f238e09990 Legacy libraries: De-duplicate field names on load
Fixes https://gitlab.com/kicad/code/kicad/-/issues/16902
2024-02-22 21:36:03 +01:00
Roberto Fernandez Bautista b0b523bfdb Revert "Duplicate field names not allowed - throw exception on load"
This reverts commit 9f20816b24.
2024-02-22 21:19:07 +01:00
Wayne Stambaugh e5ef33d227 Begin version 7.0.12 development. 2024-02-21 07:43:43 -05:00
30 changed files with 381 additions and 180 deletions
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -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)" ),
+4 -3
View File
@@ -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
{
+42
View File
@@ -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
View File
@@ -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;
+6 -4
View File
@@ -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
+47
View File
@@ -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
View File
@@ -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
View File
@@ -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 )
+3 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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();
}
+4 -3
View File
@@ -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;
}
+3 -2
View File
@@ -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
View File
@@ -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;
}
+3 -2
View File
@@ -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;
+19 -4
View File
@@ -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 );
+5 -3
View File
@@ -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 );
+7 -1
View File
@@ -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
+9 -9
View File
@@ -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 )
+7 -3
View File
@@ -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 );
+5 -5
View File
@@ -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() );
+5 -5
View File
@@ -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 );
/**
+6 -1
View File
@@ -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();
+22 -22
View File
@@ -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>