41#include <dialogs/dialog_text_properties.h>
50#include <wx/textdlg.h>
78 wxASSERT_MSG( drawingTools,
"eeschema.SymbolDrawing tool is not available" );
80 auto haveSymbolCondition =
89 if( !
m_frame->IsSymbolEditable() )
104 auto swapSelectionCondition =
116 const auto canConvertStackedPins =
120 if( sel.Size() >= 2 )
122 std::vector<SCH_PIN*> pins;
127 pins.push_back(
static_cast<SCH_PIN*
>( item ) );
131 VECTOR2I pos = pins[0]->GetPosition();
132 for(
size_t i = 1; i < pins.size(); ++i )
134 if( pins[i]->GetPosition() != pos )
141 if( sel.Size() == 1 && sel.Front()->Type() ==
SCH_PIN_T )
151 int coLocatedCount = 0;
155 if(
pin->GetPosition() == pos )
159 if( coLocatedCount >= 2 )
168 const auto canExplodeStackedPin =
171 if( sel.Size() != 1 || sel.Front()->Type() !=
SCH_PIN_T )
176 std::vector<wxString> stackedNumbers =
pin->GetStackedPinNumbers( &isValid );
177 return isValid && stackedNumbers.size() > 1;
264 commit = &localCommit;
274 for(
unsigned ii = 0; ii < selection.
GetSize(); ii++ )
277 item->
Rotate( rotPoint, ccw );
278 m_frame->UpdateItem( item,
false,
true );
290 if( !localCommit.
Empty() )
291 localCommit.
Push(
_(
"Rotate" ) );
316 switch( item->
Type() )
340 m_frame->UpdateItem( item,
false,
true );
346 for(
unsigned ii = 0; ii < selection.
GetSize(); ii++ )
355 m_frame->UpdateItem( item,
false,
true );
378 if( selection.
Size() < 2 )
388 for(
size_t i = 0; i < sorted.size() - 1; i++ )
394 std::swap( aPos, bPos );
421 m_frame->UpdateItem( a,
false,
true );
422 m_frame->UpdateItem( b,
false,
true );
426 for(
EDA_ITEM* selected : selection )
458 std::deque<EDA_ITEM*> items =
m_selectionTool->RequestSelection().GetItems();
469 std::set<SCH_ITEM*> toDelete;
470 int fieldsHidden = 0;
471 int fieldsAlreadyHidden = 0;
480 toDelete.insert( curr_pin );
484 if(
m_frame->SynchronizePins() )
486 std::vector<bool> got_unit( symbol->
GetUnitCount() + 1 );
488 got_unit[curr_pin->
GetUnit()] =
true;
492 if( got_unit[
pin->GetUnit()] )
495 if(
pin->GetPosition() != pos )
507 toDelete.insert(
pin );
508 got_unit[
pin->GetUnit()] =
true;
524 fieldsAlreadyHidden++;
529 toDelete.insert( schItem );
536 if( toDelete.size() == 0 )
538 if( fieldsHidden == 1 )
539 commit.
Push(
_(
"Hide Field" ) );
540 else if( fieldsHidden > 1 )
541 commit.
Push(
_(
"Hide Fields" ) );
542 else if( fieldsAlreadyHidden > 0 )
543 m_frame->ShowInfoBarError(
_(
"Use the Symbol Properties dialog to remove fields." ) );
547 commit.
Push(
_(
"Delete" ) );
564 else if( selection.
Size() == 1 )
572 switch( item->
Type() )
582 bool mouseOverNumber =
false;
585 mouseOverNumber = numberBox->Contains( mousePos );
589 pinTool->EditPinProperties( &
pin, mouseOverNumber );
610 wxFAIL_MSG( wxT(
"Unhandled item <" ) + item->
GetClass() + wxT(
">" ) );
630 m_frame->GetCanvas()->Refresh();
637 std::vector<MSG_PANEL_ITEM> items;
654 m_frame->GetCanvas()->Refresh();
670 m_frame->GetCanvas()->Refresh();
677 if( aField ==
nullptr )
685 caption.Printf(
_(
"Edit '%s' Field" ), aField->
GetName() );
699 commit.
Push( caption );
701 m_frame->GetCanvas()->Refresh();
702 m_frame->UpdateSymbolMsgPanelInfo();
723 m_frame->RebuildSymbolUnitAndBodyStyleLists();
754 wxCHECK( selTool, -1 );
756 std::vector<SCH_PIN*> selectedPins;
765 selectedPins.push_back( pinItem );
778 commit.
Push(
_(
"Edit Pins" ) );
794 wxCHECK( selTool, -1 );
799 std::vector<SCH_PIN*> pinsToConvert;
809 if(
pin->GetPosition() == pos )
810 pinsToConvert.push_back(
pin );
819 pinsToConvert.push_back(
static_cast<SCH_PIN*
>( item ) );
823 if( pinsToConvert.size() < 2 )
825 m_frame->ShowInfoBarError(
_(
"At least two pins are needed to convert to stacked pins" ) );
830 VECTOR2I pos = pinsToConvert[0]->GetPosition();
831 for(
size_t i = 1; i < pinsToConvert.size(); ++i )
833 if( pinsToConvert[i]->GetPosition() != pos )
835 m_frame->ShowInfoBarError(
_(
"All pins must be at the same location" ) );
846 std::sort( pinsToConvert.begin(), pinsToConvert.end(),
849 wxString numA = a->GetNumber();
850 wxString numB = b->GetNumber();
854 bool aIsNumeric = numA.ToLong( &longA );
855 bool bIsNumeric = numB.ToLong( &longB );
858 if( aIsNumeric && bIsNumeric )
859 return longA < longB;
862 if( aIsNumeric && !bIsNumeric )
864 if( !aIsNumeric && bIsNumeric )
872 wxString stackedNotation = wxT(
"[");
875 auto collapseRanges = [&]() -> wxString
877 if( pinsToConvert.empty() )
883 std::map<wxString, std::vector<long>> prefixGroups;
884 std::vector<wxString> nonNumericPins;
889 wxString pinNumber =
pin->GetNumber();
892 if( pinNumber.IsEmpty() )
894 nonNumericPins.push_back( wxT(
"(empty)") );
899 wxString numericPart;
902 size_t numStart = pinNumber.length();
903 for(
int i = pinNumber.length() - 1; i >= 0; i-- )
905 if( !wxIsdigit( pinNumber[i] ) )
914 if( numStart < pinNumber.length() )
916 prefix = pinNumber.Left( numStart );
917 numericPart = pinNumber.Mid( numStart );
920 if( numericPart.ToLong( &numValue ) && numValue >= 0 )
922 prefixGroups[prefix].push_back( numValue );
927 nonNumericPins.push_back( pinNumber );
932 nonNumericPins.push_back( pinNumber );
937 for(
auto& [prefix, numbers] : prefixGroups )
943 std::sort( numbers.begin(), numbers.end() );
947 while( i < numbers.size() )
952 long start = numbers[i];
956 while( i + 1 < numbers.size() && numbers[i + 1] == numbers[i] + 1 )
963 if(
end > start + 1 )
964 result += wxString::Format( wxT(
"%s%ld-%s%ld"), prefix, start, prefix,
end );
965 else if(
end == start + 1 )
966 result += wxString::Format( wxT(
"%s%ld,%s%ld"), prefix, start, prefix,
end );
968 result += wxString::Format( wxT(
"%s%ld"), prefix, start );
975 for(
const wxString& nonNum : nonNumericPins )
985 stackedNotation += collapseRanges();
986 stackedNotation += wxT(
"]");
989 SCH_PIN* masterPin = pinsToConvert[0];
994 wxString::Format(
"Converting %zu pins to stacked notation '%s'",
995 pinsToConvert.size(), stackedNotation ) );
999 std::vector<SCH_PIN*> pinsToRemove;
1000 for(
size_t i = 1; i < pinsToConvert.size(); ++i )
1002 SCH_PIN* pinToRemove = pinsToConvert[i];
1006 wxString::Format(
"Will remove pin '%s' at position (%d, %d)",
1011 pinsToRemove.push_back( pinToRemove );
1020 commit.
Push( wxString::Format(
_(
"Convert %zu Stacked Pins to '%s'" ),
1021 pinsToConvert.size(), stackedNotation ) );
1036 wxCHECK( selTool, -1 );
1042 m_frame->ShowInfoBarError(
_(
"Select a single pin with stacked notation to explode" ) );
1050 std::vector<wxString> stackedNumbers =
pin->GetStackedPinNumbers( &isValid );
1052 if( !isValid || stackedNumbers.size() <= 1 )
1054 m_frame->ShowInfoBarError(
_(
"Selected pin does not have valid stacked notation" ) );
1064 std::sort( stackedNumbers.begin(), stackedNumbers.end(),
1065 [](
const wxString& a,
const wxString& b )
1069 if( a.ToLong( &numA ) && b.ToLong( &numB ) )
1077 pin->SetNumber( stackedNumbers[0] );
1078 pin->SetVisible(
true );
1081 for(
size_t i = 1; i < stackedNumbers.size(); ++i )
1103 commit.
Push(
_(
"Explode Stacked Pin" ) );
1118 m_frame->ShowInfoBarError(
_(
"Symbol is not derived from another symbol." ) );
1140 m_frame->GetSymbolFromUndoList();
1156 m_frame->GetSymbolFromRedoList();
1166 int retVal =
Copy( aEvent );
1180 if( !symbol || !selection.
GetSize() )
1190 if( !item.IsSelected() )
1204 std::string prettyData = formatter.
GetString();
1219 if( selection.Empty() )
1224 if( selection.IsHover() )
1245 if( newParts.empty() || !newParts[0] )
1248 newPart = newParts[0];
1255 wxString pasteText( clipboardData );
1259 if( pasteText.Length() > 5000 )
1260 pasteText = pasteText.Left( 5000 ) + wxT(
"..." );
1296 if( !selection.
Empty() )
1301 commit.
Push(
_(
"Paste" ) );
1316 if( selection.
GetSize() == 0 )
1321 std::vector<EDA_ITEM*> oldItems;
1322 std::vector<EDA_ITEM*> newItems;
1324 std::copy( selection.
begin(), selection.
end(), std::back_inserter( oldItems ) );
1325 std::sort( oldItems.begin(), oldItems.end(), [](
EDA_ITEM* a,
EDA_ITEM* b )
1329 if( a->Type() != b->Type() )
1330 return a->Type() < b->Type();
1333 if( a->Type() == SCH_PIN_T )
1335 const wxString& aNum = static_cast<SCH_PIN*>( a )->GetNumber();
1336 const wxString& bNum = static_cast<SCH_PIN*>( b )->GetNumber();
1338 cmp = StrNumCmp( aNum, bNum );
1342 if( aNum.IsNumber() && bNum.IsNumber() && cmp != 0 )
1364 newPin->
SetNumber( wxString::Format( wxT(
"%i" ), symbol->GetMaxPinNumber() + 1 ) );
1370 newItems.push_back( newItem );
1372 symbol->AddDrawItem( newItem );
1373 getView()->Add( newItem );
1379 selection.SetReferencePoint( getViewControls()->GetCursorPosition(
true ) );
1382 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
const wxChar *const traceStackedPins
Flag to enable debug output for stacked pins handling in symbol/pin code.
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.
wxLogTrace helper definitions.
VECTOR2< int32_t > VECTOR2I
constexpr int LexicographicalCompare(const VECTOR2< T > &aA, const VECTOR2< T > &aB)