41#include <dialogs/dialog_text_properties.h>
50#include <wx/textdlg.h>
77 wxASSERT_MSG( drawingTools,
"eeschema.SymbolDrawing tool is not available" );
79 auto haveSymbolCondition =
88 if( !
m_frame->IsSymbolEditable() )
103 auto swapSelectionCondition =
115 const auto canConvertStackedPins =
119 if( sel.Size() >= 2 )
121 std::vector<SCH_PIN*> pins;
126 pins.push_back(
static_cast<SCH_PIN*
>( item ) );
130 VECTOR2I pos = pins[0]->GetPosition();
131 for(
size_t i = 1; i < pins.size(); ++i )
133 if( pins[i]->GetPosition() != pos )
140 if( sel.Size() == 1 && sel.Front()->Type() ==
SCH_PIN_T )
150 int coLocatedCount = 0;
154 if(
pin->GetPosition() == pos )
158 if( coLocatedCount >= 2 )
167 const auto canExplodeStackedPin =
170 if( sel.Size() != 1 || sel.Front()->Type() !=
SCH_PIN_T )
175 std::vector<wxString> stackedNumbers =
pin->GetStackedPinNumbers( &isValid );
176 return isValid && stackedNumbers.size() > 1;
263 commit = &localCommit;
273 for(
unsigned ii = 0; ii < selection.
GetSize(); ii++ )
276 item->
Rotate( rotPoint, ccw );
277 m_frame->UpdateItem( item,
false,
true );
289 if( !localCommit.
Empty() )
290 localCommit.
Push(
_(
"Rotate" ) );
315 switch( item->
Type() )
339 m_frame->UpdateItem( item,
false,
true );
345 for(
unsigned ii = 0; ii < selection.
GetSize(); ii++ )
354 m_frame->UpdateItem( item,
false,
true );
377 if( selection.
Size() < 2 )
387 for(
size_t i = 0; i < sorted.size() - 1; i++ )
393 std::swap( aPos, bPos );
420 m_frame->UpdateItem( a,
false,
true );
421 m_frame->UpdateItem( b,
false,
true );
425 for(
EDA_ITEM* selected : selection )
457 std::deque<EDA_ITEM*> items =
m_selectionTool->RequestSelection().GetItems();
468 std::set<SCH_ITEM*> toDelete;
469 int fieldsHidden = 0;
470 int fieldsAlreadyHidden = 0;
479 toDelete.insert( curr_pin );
483 if(
m_frame->SynchronizePins() )
485 std::vector<bool> got_unit( symbol->
GetUnitCount() + 1 );
487 got_unit[curr_pin->
GetUnit()] =
true;
491 if( got_unit[
pin->GetUnit()] )
494 if(
pin->GetPosition() != pos )
506 toDelete.insert(
pin );
507 got_unit[
pin->GetUnit()] =
true;
523 fieldsAlreadyHidden++;
528 toDelete.insert( schItem );
535 if( toDelete.size() == 0 )
537 if( fieldsHidden == 1 )
538 commit.
Push(
_(
"Hide Field" ) );
539 else if( fieldsHidden > 1 )
540 commit.
Push(
_(
"Hide Fields" ) );
541 else if( fieldsAlreadyHidden > 0 )
542 m_frame->ShowInfoBarError(
_(
"Use the Symbol Properties dialog to remove fields." ) );
546 commit.
Push(
_(
"Delete" ) );
563 else if( selection.
Size() == 1 )
571 switch( item->
Type() )
581 bool mouseOverNumber =
false;
584 mouseOverNumber = numberBox->Contains( mousePos );
588 pinTool->EditPinProperties( &
pin, mouseOverNumber );
609 wxFAIL_MSG( wxT(
"Unhandled item <" ) + item->
GetClass() + wxT(
">" ) );
629 m_frame->GetCanvas()->Refresh();
636 std::vector<MSG_PANEL_ITEM> items;
653 m_frame->GetCanvas()->Refresh();
669 m_frame->GetCanvas()->Refresh();
676 if( aField ==
nullptr )
684 caption.Printf(
_(
"Edit '%s' Field" ), aField->
GetName() );
698 commit.
Push( caption );
700 m_frame->GetCanvas()->Refresh();
701 m_frame->UpdateSymbolMsgPanelInfo();
722 m_frame->RebuildSymbolUnitAndBodyStyleLists();
753 wxCHECK( selTool, -1 );
755 std::vector<SCH_PIN*> selectedPins;
764 selectedPins.push_back( pinItem );
777 commit.
Push(
_(
"Edit Pins" ) );
793 wxCHECK( selTool, -1 );
798 std::vector<SCH_PIN*> pinsToConvert;
808 if(
pin->GetPosition() == pos )
809 pinsToConvert.push_back(
pin );
818 pinsToConvert.push_back(
static_cast<SCH_PIN*
>( item ) );
822 if( pinsToConvert.size() < 2 )
824 m_frame->ShowInfoBarError(
_(
"At least two pins are needed to convert to stacked pins" ) );
829 VECTOR2I pos = pinsToConvert[0]->GetPosition();
830 for(
size_t i = 1; i < pinsToConvert.size(); ++i )
832 if( pinsToConvert[i]->GetPosition() != pos )
834 m_frame->ShowInfoBarError(
_(
"All pins must be at the same location" ) );
845 std::sort( pinsToConvert.begin(), pinsToConvert.end(),
848 wxString numA = a->GetNumber();
849 wxString numB = b->GetNumber();
853 bool aIsNumeric = numA.ToLong( &longA );
854 bool bIsNumeric = numB.ToLong( &longB );
857 if( aIsNumeric && bIsNumeric )
858 return longA < longB;
861 if( aIsNumeric && !bIsNumeric )
863 if( !aIsNumeric && bIsNumeric )
871 wxString stackedNotation = wxT(
"[");
874 auto collapseRanges = [&]() -> wxString
876 if( pinsToConvert.empty() )
882 std::map<wxString, std::vector<long>> prefixGroups;
883 std::vector<wxString> nonNumericPins;
888 wxString pinNumber =
pin->GetNumber();
891 if( pinNumber.IsEmpty() )
893 nonNumericPins.push_back( wxT(
"(empty)") );
898 wxString numericPart;
901 size_t numStart = pinNumber.length();
902 for(
int i = pinNumber.length() - 1; i >= 0; i-- )
904 if( !wxIsdigit( pinNumber[i] ) )
913 if( numStart < pinNumber.length() )
915 prefix = pinNumber.Left( numStart );
916 numericPart = pinNumber.Mid( numStart );
919 if( numericPart.ToLong( &numValue ) && numValue >= 0 )
921 prefixGroups[prefix].push_back( numValue );
926 nonNumericPins.push_back( pinNumber );
931 nonNumericPins.push_back( pinNumber );
936 for(
auto& [prefix, numbers] : prefixGroups )
942 std::sort( numbers.begin(), numbers.end() );
946 while( i < numbers.size() )
951 long start = numbers[i];
955 while( i + 1 < numbers.size() && numbers[i + 1] == numbers[i] + 1 )
962 if(
end > start + 1 )
963 result += wxString::Format( wxT(
"%s%ld-%s%ld"), prefix, start, prefix,
end );
964 else if(
end == start + 1 )
965 result += wxString::Format( wxT(
"%s%ld,%s%ld"), prefix, start, prefix,
end );
967 result += wxString::Format( wxT(
"%s%ld"), prefix, start );
974 for(
const wxString& nonNum : nonNumericPins )
984 stackedNotation += collapseRanges();
985 stackedNotation += wxT(
"]");
988 SCH_PIN* masterPin = pinsToConvert[0];
992 wxLogTrace(
"KICAD_STACKED_PINS",
993 wxString::Format(
"Converting %zu pins to stacked notation '%s'",
994 pinsToConvert.size(), stackedNotation ) );
998 std::vector<SCH_PIN*> pinsToRemove;
999 for(
size_t i = 1; i < pinsToConvert.size(); ++i )
1001 SCH_PIN* pinToRemove = pinsToConvert[i];
1004 wxLogTrace(
"KICAD_STACKED_PINS",
1005 wxString::Format(
"Will remove pin '%s' at position (%d, %d)",
1010 pinsToRemove.push_back( pinToRemove );
1019 commit.
Push( wxString::Format(
_(
"Convert %zu Stacked Pins to '%s'" ),
1020 pinsToConvert.size(), stackedNotation ) );
1035 wxCHECK( selTool, -1 );
1041 m_frame->ShowInfoBarError(
_(
"Select a single pin with stacked notation to explode" ) );
1049 std::vector<wxString> stackedNumbers =
pin->GetStackedPinNumbers( &isValid );
1051 if( !isValid || stackedNumbers.size() <= 1 )
1053 m_frame->ShowInfoBarError(
_(
"Selected pin does not have valid stacked notation" ) );
1063 std::sort( stackedNumbers.begin(), stackedNumbers.end(),
1064 [](
const wxString& a,
const wxString& b )
1068 if( a.ToLong( &numA ) && b.ToLong( &numB ) )
1076 pin->SetNumber( stackedNumbers[0] );
1077 pin->SetVisible(
true );
1080 for(
size_t i = 1; i < stackedNumbers.size(); ++i )
1102 commit.
Push(
_(
"Explode Stacked Pin" ) );
1117 m_frame->ShowInfoBarError(
_(
"Symbol is not derived from another symbol." ) );
1139 m_frame->GetSymbolFromUndoList();
1155 m_frame->GetSymbolFromRedoList();
1165 int retVal =
Copy( aEvent );
1179 if( !symbol || !selection.
GetSize() )
1189 if( !item.IsSelected() )
1203 std::string prettyData = formatter.
GetString();
1218 if( selection.Empty() )
1223 if( selection.IsHover() )
1244 if( newParts.empty() || !newParts[0] )
1247 newPart = newParts[0];
1254 wxString pasteText( clipboardData );
1258 if( pasteText.Length() > 5000 )
1259 pasteText = pasteText.Left( 5000 ) + wxT(
"..." );
1295 if( !selection.
Empty() )
1300 commit.
Push(
_(
"Paste" ) );
1315 if( selection.
GetSize() == 0 )
1320 std::vector<EDA_ITEM*> oldItems;
1321 std::vector<EDA_ITEM*> newItems;
1323 std::copy( selection.
begin(), selection.
end(), std::back_inserter( oldItems ) );
1324 std::sort( oldItems.begin(), oldItems.end(), [](
EDA_ITEM* a,
EDA_ITEM* b )
1328 if( a->Type() != b->Type() )
1329 return a->Type() < b->Type();
1332 if( a->Type() == SCH_PIN_T )
1334 const wxString& aNum = static_cast<SCH_PIN*>( a )->GetNumber();
1335 const wxString& bNum = static_cast<SCH_PIN*>( b )->GetNumber();
1337 cmp = StrNumCmp( aNum, bNum );
1341 if( aNum.IsNumber() && bNum.IsNumber() && cmp != 0 )
1363 newPin->
SetNumber( wxString::Format( wxT(
"%i" ), symbol->GetMaxPinNumber() + 1 ) );
1369 newItems.push_back( newItem );
1371 symbol->AddDrawItem( newItem );
1372 getView()->Add( newItem );
1378 selection.SetReferencePoint( getViewControls()->GetCursorPosition(
true ) );
1381 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)