41#include <dialogs/dialog_text_properties.h>
50#include <wx/textdlg.h>
67 wxASSERT_MSG( drawingTools,
"eeschema.SymbolDrawing tool is not available" );
69 auto haveSymbolCondition =
78 if( !
m_frame->IsSymbolEditable() )
102 const auto canConvertStackedPins =
106 if( sel.Size() >= 2 )
108 std::vector<SCH_PIN*> pins;
113 pins.push_back(
static_cast<SCH_PIN*
>( item ) );
117 VECTOR2I pos = pins[0]->GetPosition();
118 for(
size_t i = 1; i < pins.size(); ++i )
120 if( pins[i]->GetPosition() != pos )
127 if( sel.Size() == 1 && sel.Front()->Type() ==
SCH_PIN_T )
137 int coLocatedCount = 0;
141 if(
pin->GetPosition() == pos )
145 if( coLocatedCount >= 2 )
154 const auto canExplodeStackedPin =
157 if( sel.Size() != 1 || sel.Front()->Type() !=
SCH_PIN_T )
162 std::vector<wxString> stackedNumbers =
pin->GetStackedPinNumbers( &isValid );
163 return isValid && stackedNumbers.size() > 1;
250 commit = &localCommit;
260 for(
unsigned ii = 0; ii < selection.
GetSize(); ii++ )
263 item->
Rotate( rotPoint, ccw );
264 m_frame->UpdateItem( item,
false,
true );
276 if( !localCommit.
Empty() )
277 localCommit.
Push(
_(
"Rotate" ) );
302 switch( item->
Type() )
326 m_frame->UpdateItem( item,
false,
true );
332 for(
unsigned ii = 0; ii < selection.
GetSize(); ii++ )
341 m_frame->UpdateItem( item,
false,
true );
376 if( selection.
Size() < 2 )
386 for(
size_t i = 0; i < sorted.size() - 1; i++ )
392 std::swap( aPos, bPos );
419 m_frame->UpdateItem( a,
false,
true );
420 m_frame->UpdateItem( b,
false,
true );
424 for(
EDA_ITEM* selected : selection )
456 std::deque<EDA_ITEM*> items =
m_selectionTool->RequestSelection().GetItems();
467 std::set<SCH_ITEM*> toDelete;
468 int fieldsHidden = 0;
469 int fieldsAlreadyHidden = 0;
478 toDelete.insert( curr_pin );
482 if(
m_frame->SynchronizePins() )
484 std::vector<bool> got_unit( symbol->
GetUnitCount() + 1 );
486 got_unit[curr_pin->
GetUnit()] =
true;
490 if( got_unit[
pin->GetUnit()] )
493 if(
pin->GetPosition() != pos )
505 toDelete.insert(
pin );
506 got_unit[
pin->GetUnit()] =
true;
522 fieldsAlreadyHidden++;
527 toDelete.insert( schItem );
534 if( toDelete.size() == 0 )
536 if( fieldsHidden == 1 )
537 commit.
Push(
_(
"Hide Field" ) );
538 else if( fieldsHidden > 1 )
539 commit.
Push(
_(
"Hide Fields" ) );
540 else if( fieldsAlreadyHidden > 0 )
541 m_frame->ShowInfoBarError(
_(
"Use the Symbol Properties dialog to remove fields." ) );
545 commit.
Push(
_(
"Delete" ) );
562 else if( selection.
Size() == 1 )
570 switch( item->
Type() )
580 bool mouseOverNumber =
false;
583 mouseOverNumber = numberBox->Contains( mousePos );
587 pinTool->EditPinProperties( &
pin, mouseOverNumber );
608 wxFAIL_MSG( wxT(
"Unhandled item <" ) + item->
GetClass() + wxT(
">" ) );
628 m_frame->GetCanvas()->Refresh();
635 std::vector<MSG_PANEL_ITEM> items;
652 m_frame->GetCanvas()->Refresh();
668 m_frame->GetCanvas()->Refresh();
675 if( aField ==
nullptr )
683 caption.Printf(
_(
"Edit '%s' Field" ), aField->
GetName() );
697 commit.
Push( caption );
699 m_frame->GetCanvas()->Refresh();
700 m_frame->UpdateSymbolMsgPanelInfo();
721 m_frame->RebuildSymbolUnitAndBodyStyleLists();
752 wxCHECK( selTool, -1 );
754 std::vector<SCH_PIN*> selectedPins;
763 selectedPins.push_back( pinItem );
776 commit.
Push(
_(
"Edit Pins" ) );
792 wxCHECK( selTool, -1 );
797 std::vector<SCH_PIN*> pinsToConvert;
807 if(
pin->GetPosition() == pos )
808 pinsToConvert.push_back(
pin );
817 pinsToConvert.push_back(
static_cast<SCH_PIN*
>( item ) );
821 if( pinsToConvert.size() < 2 )
823 m_frame->ShowInfoBarError(
_(
"At least two pins are needed to convert to stacked pins" ) );
828 VECTOR2I pos = pinsToConvert[0]->GetPosition();
829 for(
size_t i = 1; i < pinsToConvert.size(); ++i )
831 if( pinsToConvert[i]->GetPosition() != pos )
833 m_frame->ShowInfoBarError(
_(
"All pins must be at the same location" ) );
844 std::sort( pinsToConvert.begin(), pinsToConvert.end(),
847 wxString numA = a->GetNumber();
848 wxString numB = b->GetNumber();
852 bool aIsNumeric = numA.ToLong( &longA );
853 bool bIsNumeric = numB.ToLong( &longB );
856 if( aIsNumeric && bIsNumeric )
857 return longA < longB;
860 if( aIsNumeric && !bIsNumeric )
862 if( !aIsNumeric && bIsNumeric )
870 wxString stackedNotation = wxT(
"[");
873 auto collapseRanges = [&]() -> wxString
875 if( pinsToConvert.empty() )
881 std::map<wxString, std::vector<long>> prefixGroups;
882 std::vector<wxString> nonNumericPins;
887 wxString pinNumber =
pin->GetNumber();
890 if( pinNumber.IsEmpty() )
892 nonNumericPins.push_back( wxT(
"(empty)") );
897 wxString numericPart;
900 size_t numStart = pinNumber.length();
901 for(
int i = pinNumber.length() - 1; i >= 0; i-- )
903 if( !wxIsdigit( pinNumber[i] ) )
912 if( numStart < pinNumber.length() )
914 prefix = pinNumber.Left( numStart );
915 numericPart = pinNumber.Mid( numStart );
918 if( numericPart.ToLong( &numValue ) && numValue >= 0 )
920 prefixGroups[prefix].push_back( numValue );
925 nonNumericPins.push_back( pinNumber );
930 nonNumericPins.push_back( pinNumber );
935 for(
auto& [prefix, numbers] : prefixGroups )
941 std::sort( numbers.begin(), numbers.end() );
945 while( i < numbers.size() )
950 long start = numbers[i];
954 while( i + 1 < numbers.size() && numbers[i + 1] == numbers[i] + 1 )
961 if(
end > start + 1 )
962 result += wxString::Format( wxT(
"%s%ld-%s%ld"), prefix, start, prefix,
end );
963 else if(
end == start + 1 )
964 result += wxString::Format( wxT(
"%s%ld,%s%ld"), prefix, start, prefix,
end );
966 result += wxString::Format( wxT(
"%s%ld"), prefix, start );
973 for(
const wxString& nonNum : nonNumericPins )
983 stackedNotation += collapseRanges();
984 stackedNotation += wxT(
"]");
987 SCH_PIN* masterPin = pinsToConvert[0];
991 wxLogTrace(
"KICAD_STACKED_PINS",
992 wxString::Format(
"Converting %zu pins to stacked notation '%s'",
993 pinsToConvert.size(), stackedNotation ) );
997 std::vector<SCH_PIN*> pinsToRemove;
998 for(
size_t i = 1; i < pinsToConvert.size(); ++i )
1000 SCH_PIN* pinToRemove = pinsToConvert[i];
1003 wxLogTrace(
"KICAD_STACKED_PINS",
1004 wxString::Format(
"Will remove pin '%s' at position (%d, %d)",
1009 pinsToRemove.push_back( pinToRemove );
1018 commit.
Push( wxString::Format(
_(
"Convert %zu Stacked Pins to '%s'" ),
1019 pinsToConvert.size(), stackedNotation ) );
1034 wxCHECK( selTool, -1 );
1040 m_frame->ShowInfoBarError(
_(
"Select a single pin with stacked notation to explode" ) );
1048 std::vector<wxString> stackedNumbers =
pin->GetStackedPinNumbers( &isValid );
1050 if( !isValid || stackedNumbers.size() <= 1 )
1052 m_frame->ShowInfoBarError(
_(
"Selected pin does not have valid stacked notation" ) );
1062 std::sort( stackedNumbers.begin(), stackedNumbers.end(),
1063 [](
const wxString& a,
const wxString& b )
1067 if( a.ToLong( &numA ) && b.ToLong( &numB ) )
1075 pin->SetNumber( stackedNumbers[0] );
1076 pin->SetVisible(
true );
1079 for(
size_t i = 1; i < stackedNumbers.size(); ++i )
1101 commit.
Push(
_(
"Explode Stacked Pin" ) );
1116 m_frame->ShowInfoBarError(
_(
"Symbol is not derived from another symbol." ) );
1138 m_frame->GetSymbolFromUndoList();
1154 m_frame->GetSymbolFromRedoList();
1164 int retVal =
Copy( aEvent );
1178 if( !symbol || !selection.
GetSize() )
1188 if( !item.IsSelected() )
1202 std::string prettyData = formatter.
GetString();
1217 if( selection.Empty() )
1222 if( selection.IsHover() )
1243 if( newParts.empty() || !newParts[0] )
1246 newPart = newParts[0];
1253 wxString pasteText( clipboardData );
1257 if( pasteText.Length() > 5000 )
1258 pasteText = pasteText.Left( 5000 ) + wxT(
"..." );
1294 if( !selection.
Empty() )
1299 commit.
Push(
_(
"Paste" ) );
1314 if( selection.
GetSize() == 0 )
1319 std::vector<EDA_ITEM*> oldItems;
1320 std::vector<EDA_ITEM*> newItems;
1322 std::copy( selection.
begin(), selection.
end(), std::back_inserter( oldItems ) );
1323 std::sort( oldItems.begin(), oldItems.end(), [](
EDA_ITEM* a,
EDA_ITEM* b )
1327 if( a->Type() != b->Type() )
1328 return a->Type() < b->Type();
1331 if( a->Type() == SCH_PIN_T )
1333 const wxString& aNum = static_cast<SCH_PIN*>( a )->GetNumber();
1334 const wxString& bNum = static_cast<SCH_PIN*>( b )->GetNumber();
1336 cmp = StrNumCmp( aNum, bNum );
1340 if( aNum.IsNumber() && bNum.IsNumber() && cmp != 0 )
1362 newPin->
SetNumber( wxString::Format( wxT(
"%i" ), symbol->GetMaxPinNumber() + 1 ) );
1368 newItems.push_back( newItem );
1370 symbol->AddDrawItem( newItem );
1371 getView()->Add( newItem );
1377 selection.SetReferencePoint( getViewControls()->GetCursorPosition(
true ) );
1380 commit.Push(
_(
"Duplicate" ) );
std::optional< BOX2I > OPT_BOX2I
static TOOL_ACTION decrementPrimary
static TOOL_ACTION cancelInteractive
static TOOL_ACTION unselectAll
static TOOL_ACTION decrementSecondary
static TOOL_ACTION incrementSecondary
static TOOL_ACTION duplicate
static TOOL_ACTION incrementPrimary
static TOOL_ACTION doDelete
static TOOL_ACTION deleteTool
static TOOL_ACTION increment
static TOOL_ACTION selectionClear
Clear the current selection.
static TOOL_ACTION copyAsText
static TOOL_ACTION refreshPreview
static TOOL_ACTION selectAll
static TOOL_ACTION selectItems
Select a list of items (specified as the event parameter)
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
This class is setup in expectation of its children possibly using Kiway player so DIALOG_SHIM::ShowQu...
void UpdateField(SCH_FIELD *aField)
bool GetApplyToAllConversions()
bool GetApplyToAllUnits()
Dialog to update or change schematic library symbols.
A base class for most all the KiCad significant classes used in schematics and boards.
virtual VECTOR2I GetPosition() const
virtual void SetPosition(const VECTOR2I &aPos)
EDA_ITEM_FLAGS GetEditFlags() const
void SetFlags(EDA_ITEM_FLAGS aMask)
KICAD_T Type() const
Returns the type of object.
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
virtual void SetParent(EDA_ITEM *aParent)
EDA_ITEM * GetParent() const
virtual bool IsVisible() const
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
GR_TEXT_H_ALIGN_T GetHorizJustify() const
virtual void SetVisible(bool aVisible)
GR_TEXT_V_ALIGN_T GetVertJustify() const
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Define a library symbol object.
bool UnitsLocked() const
Check whether symbol units are interchangeable.
LIB_ITEMS_CONTAINER & GetDrawItems()
Return a reference to the draw item list.
void RemoveDrawItem(SCH_ITEM *aItem)
Remove draw aItem from list.
std::vector< SCH_PIN * > GetPins() const override
int GetUnitCount() const override
void AddDrawItem(SCH_ITEM *aItem, bool aSort=true)
Add a new draw aItem to the draw object list and sort according to aSort.
A pin layout helper is a class that manages the layout of the parts of a pin on a schematic symbol:
OPT_BOX2I GetPinNumberBBox()
Get the bounding box of the pin number, if there is one.
static TOOL_ACTION rotateCCW
static TOOL_ACTION mirrorV
static TOOL_ACTION convertStackedPins
static TOOL_ACTION pinTable
static TOOL_ACTION properties
static TOOL_ACTION rotateCW
static TOOL_ACTION mirrorH
static TOOL_ACTION symbolProperties
static TOOL_ACTION explodeStackedPin
static TOOL_ACTION updateSymbolFields
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Execute the changes.
virtual void Revert() override
Revert the commit by restoring the modified items state.
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
static void FormatLibSymbol(LIB_SYMBOL *aPart, OUTPUTFORMATTER &aFormatter)
static std::vector< LIB_SYMBOL * > ParseLibSymbols(std::string &aSymbolText, std::string aSource, int aFileVersion=SEXPR_SCHEMATIC_FILE_VERSION)
Base class for any item which can be embedded within the SCHEMATIC container class,...
SCH_ITEM * Duplicate(bool addToParentGroup, SCH_COMMIT *aCommit=nullptr, bool doClone=false) const
Routine to create a new copy of given item.
virtual void SetBodyStyle(int aBodyStyle)
virtual void MirrorHorizontally(int aCenter)
Mirror item horizontally about aCenter.
virtual void Rotate(const VECTOR2I &aCenter, bool aRotateCCW)
Rotate the item around aCenter 90 degrees in the clockwise direction.
virtual void SetUnit(int aUnit)
wxString GetClass() const override
Return the class name.
virtual void MirrorVertically(int aCenter)
Mirror item vertically about aCenter.
void SetNumber(const wxString &aNumber)
void SetVisible(bool aVisible)
void SetOrientation(PIN_ORIENTATION aOrientation)
void SetName(const wxString &aName)
void SetPosition(const VECTOR2I &aPos) override
const wxString & GetName() const
void SetLength(int aLength)
PIN_ORIENTATION GetOrientation() const
void SetNumberTextSize(int aSize)
void SetShape(GRAPHIC_PINSHAPE aShape)
VECTOR2I GetPosition() const override
void SetType(ELECTRICAL_PINTYPE aType)
const wxString & GetNumber() const
ELECTRICAL_PINTYPE GetType() const
void SetNameTextSize(int aSize)
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Populate aList of MSG_PANEL_ITEM objects with it's internal state for display purposes.
static bool NotEmpty(const SELECTION &aSelection)
Test if there are any items selected.
static SELECTION_CONDITION MoreThan(int aNumber)
Create a functor that tests if the number of selected items is greater than the value given as parame...
static bool Idle(const SELECTION &aSelection)
Test if there no items selected or being edited.
static bool IdleSelection(const SELECTION &aSelection)
Test if all selected items are not being edited.
static SELECTION_CONDITION Count(int aNumber)
Create a functor that tests if the number of selected items is equal to the value given as parameter.
static SELECTION_CONDITION OnlyTypes(std::vector< KICAD_T > aTypes)
Create a functor that tests if the selected items are only of given types.
virtual KIGFX::VIEW_ITEM * GetItem(unsigned int aIdx) const override
virtual VECTOR2I GetCenter() const
Returns the center point of the selection area bounding box.
virtual unsigned int GetSize() const override
Return the number of stored items.
virtual void Clear() override
Remove all the stored items from the group.
int Size() const
Returns the number of selected parts.
std::vector< EDA_ITEM * > GetItemsSortedBySelectionOrder() const
void SetReferencePoint(const VECTOR2I &aP)
bool Empty() const
Checks if there is anything selected.
bool SaveClipboard(const std::string &aTextUTF8)
Store information to the system clipboard.
std::string GetClipboardUTF8()
Return the information currently stored in the system clipboard.
std::vector< EDA_ITEM * > EDA_ITEMS
Define list of drawing items for screens.
#define IS_PASTED
Modifier on IS_NEW which indicates it came from clipboard.
#define IS_NEW
New item, just created.
#define SELECTED
Item was manually selected by the user.
#define STRUCT_DELETED
flag indication structures to be erased
PIN_ORIENTATION
The symbol library pin object orientations.
wxString TitleCaps(const wxString &aString)
Capitalize the first letter in each word.
wxString result
Test unit parsing edge cases and error handling.
constexpr GR_TEXT_H_ALIGN_T GetFlippedAlignment(GR_TEXT_H_ALIGN_T aAlign)
Get the reverse alignment: left-right are swapped, others are unchanged.
VECTOR2< int32_t > VECTOR2I
constexpr int LexicographicalCompare(const VECTOR2< T > &aA, const VECTOR2< T > &aB)