KiCad PCB EDA Suite
symbol_editor_pin_tool.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2019 CERN
5 * Copyright (C) 2019-2022 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25#include <tool/tool_manager.h>
27#include <symbol_edit_frame.h>
28#include <confirm.h>
29#include <ee_actions.h>
33#include <pgm_base.h>
34#include <wx/log.h>
36
37
41static bool g_LastPinCommonConvert = false;
42static bool g_LastPinCommonUnit = false;
43static bool g_LastPinVisible = true;
44
45// The -1 is a non-valid value to trigger delayed initialization
46static int g_LastPinLength = -1;
47static int g_LastPinNameSize = -1;
48static int g_LastPinNumSize = -1;
49
50static int GetLastPinLength()
51{
52 if( g_LastPinLength == -1 )
53 {
54 auto* settings = Pgm().GetSettingsManager().GetAppSettings<SYMBOL_EDITOR_SETTINGS>();
55 g_LastPinLength = schIUScale.MilsToIU( settings->m_Defaults.pin_length );
56 }
57
58 return g_LastPinLength;
59}
60
62{
63 if( g_LastPinNameSize == -1 )
64 {
65 auto* settings = Pgm().GetSettingsManager().GetAppSettings<SYMBOL_EDITOR_SETTINGS>();
66 g_LastPinNameSize = schIUScale.MilsToIU( settings->m_Defaults.pin_name_size );
67 }
68
69 return g_LastPinNameSize;
70}
71
73{
74 if( g_LastPinNumSize == -1 )
75 {
76 auto* settings = Pgm().GetSettingsManager().GetAppSettings<SYMBOL_EDITOR_SETTINGS>();
77 g_LastPinNumSize = schIUScale.MilsToIU( settings->m_Defaults.pin_num_size );
78 }
79
80 return g_LastPinNumSize;
81}
82
83
84extern bool IncrementLabelMember( wxString& name, int aIncrement );
85
86
88 EE_TOOL_BASE<SYMBOL_EDIT_FRAME>( "eeschema.PinEditing" )
89{
90}
91
92
94{
96
97 auto canEdit =
98 [&]( const SELECTION& sel )
99 {
101 wxCHECK( editor, false );
102
103 return editor->IsSymbolEditable() && !editor->IsSymbolAlias();
104 };
105
106 auto singlePinCondition = EE_CONDITIONS::Count( 1 ) && EE_CONDITIONS::OnlyTypes( { LIB_PIN_T } );
107
109
110 selToolMenu.AddSeparator( 250 );
111 selToolMenu.AddItem( EE_ACTIONS::pushPinLength, canEdit && singlePinCondition, 250 );
112 selToolMenu.AddItem( EE_ACTIONS::pushPinNameSize, canEdit && singlePinCondition, 250 );
113 selToolMenu.AddItem( EE_ACTIONS::pushPinNumSize, canEdit && singlePinCondition, 250 );
114
115 return true;
116}
117
118
120{
121 LIB_PIN original_pin( *aPin );
122 DIALOG_PIN_PROPERTIES dlg( m_frame, aPin );
123
124 if( aPin->GetEditFlags() == 0 )
126
127 if( dlg.ShowModal() == wxID_CANCEL )
128 {
129 if( aPin->GetEditFlags() == 0 )
131
132 return false;
133 }
134
135 aPin->SetModified();
136
137 if( !aPin->IsNew() && m_frame->SynchronizePins() && aPin->GetParent() )
138 {
139 LIB_PINS pinList;
140 aPin->GetParent()->GetPins( pinList );
141
142 // a pin can have a unit id = 0 (common to all units) to unit count
143 // So we need a buffer size = GetUnitCount()+1 to store a value in a vector
144 // when using the unit id of a pin as index
145 std::vector<bool> got_unit( aPin->GetParent()->GetUnitCount() + 1 );
146
147 got_unit[static_cast<size_t>(aPin->GetUnit())] = true;
148
149 for( LIB_PIN* other : pinList )
150 {
151 if( other == aPin )
152 continue;
153
157 if( got_unit[static_cast<size_t>( other->GetUnit() )] )
158 continue;
159
160 if( other->GetPosition() == original_pin.GetPosition()
161 && other->GetOrientation() == original_pin.GetOrientation()
162 && other->GetType() == original_pin.GetType()
163 && other->IsVisible() == original_pin.IsVisible()
164 && other->GetName() == original_pin.GetName() )
165 {
166 if( aPin->GetConvert() == 0 )
167 {
168 if( !aPin->GetUnit() || other->GetUnit() == aPin->GetUnit() )
169 aPin->GetParent()->RemoveDrawItem( other );
170 }
171 else if( other->GetConvert() == aPin->GetConvert() )
172 {
173 other->SetPosition( aPin->GetPosition() );
174 other->ChangeLength( aPin->GetLength() );
175 other->SetShape( aPin->GetShape() );
176 }
177
178 if( aPin->GetUnit() == 0 )
179 {
180 if( !aPin->GetConvert() || other->GetConvert() == aPin->GetConvert() )
181 aPin->GetParent()->RemoveDrawItem( other );
182 }
183
184 other->SetOrientation( aPin->GetOrientation() );
185 other->SetType( aPin->GetType() );
186 other->SetVisible( aPin->IsVisible() );
187 other->SetName( aPin->GetName() );
188 other->SetNameTextSize( aPin->GetNameTextSize() );
189 other->SetNumberTextSize( aPin->GetNumberTextSize() );
190
191 other->SetModified();
192 got_unit[static_cast<size_t>( other->GetUnit() )] = true;
193 }
194 }
195 }
196
197 m_frame->UpdateItem( aPin, false, true );
198 m_frame->OnModify( );
199
200 std::vector<MSG_PANEL_ITEM> items;
201 aPin->GetMsgPanelInfo( m_frame, items );
202 m_frame->SetMsgPanel( items );
203
204 // Save the pin properties to use for the next new pin.
208 g_LastPinLength = aPin->GetLength();
209 g_LastPinShape = aPin->GetShape();
210 g_LastPinType = aPin->GetType();
211 g_LastPinCommonConvert = aPin->GetConvert() == 0;
212 g_LastPinCommonUnit = aPin->GetUnit() == 0;
213 g_LastPinVisible = aPin->IsVisible();
214
215 return true;
216}
217
218
220{
221 LIB_SYMBOL* symbol = m_frame->GetCurSymbol();
222 bool ask_for_pin = true; // Test for another pin in same position in other units
223
224 for( LIB_PIN* test = symbol->GetNextPin(); test; test = symbol->GetNextPin( test ) )
225 {
226 if( test == aPin || aPin->GetPosition() != test->GetPosition() || test->GetEditFlags() )
227 continue;
228
229 // test for same body style
230 if( test->GetConvert() && test->GetConvert() != aPin->GetConvert() )
231 continue;
232
233 if( ask_for_pin && m_frame->SynchronizePins() )
234 {
235 wxString msg;
236 msg.Printf( _( "This position is already occupied by another pin, in unit %d." ),
237 test->GetUnit() );
238
239 KIDIALOG dlg( m_frame, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
240 dlg.SetOKLabel( _( "Place Pin Anyway" ) );
241 dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
242
243 bool status = dlg.ShowModal() == wxID_OK;
244
245 if( !status )
246 {
247 if( aPin->IsNew() && !aPin->HasFlag( IS_PASTED ) )
248 delete aPin;
249
250 return false;
251 }
252 else
253 {
254 ask_for_pin = false;
255 }
256 }
257 }
258
259 if( aPin->IsNew() && !aPin->HasFlag( IS_PASTED ) )
260 {
262 g_LastPinType = aPin->GetType();
263 g_LastPinShape = aPin->GetShape();
264
265 if( m_frame->SynchronizePins() )
266 CreateImagePins( aPin );
267
268 symbol->AddDrawItem( aPin );
269 aPin->ClearFlags( IS_NEW );
270 }
271
272 // Put linked pins in new position, and clear flags
273 for( LIB_PIN* pin = symbol->GetNextPin(); pin; pin = symbol->GetNextPin( pin ) )
274 {
275 if( ( pin->GetEditFlags() & IS_LINKED ) == 0 )
276 continue;
277
278 pin->MoveTo( aPin->GetPosition() );
279 pin->ClearFlags();
280 }
281
283 m_frame->OnModify();
284
285 return true;
286}
287
288
289/*
290 * Create a new pin.
291 */
293{
294 aSymbol->ClearTempFlags();
295
296 LIB_PIN* pin = new LIB_PIN( aSymbol );
297
298 pin->SetFlags( IS_NEW );
299
300 // Flag pins to consider
301 if( m_frame->SynchronizePins() )
302 pin->SetFlags( IS_LINKED );
303
304 pin->MoveTo( aPosition );
305 pin->SetLength( GetLastPinLength() );
306 pin->SetOrientation( g_LastPinOrient );
307 pin->SetType( g_LastPinType );
308 pin->SetShape( g_LastPinShape );
309 pin->SetNameTextSize( GetLastPinNameSize() );
310 pin->SetNumberTextSize( GetLastPinNumSize() );
311 pin->SetConvert( g_LastPinCommonConvert ? 0 : m_frame->GetConvert() );
312 pin->SetUnit( g_LastPinCommonUnit ? 0 : m_frame->GetUnit() );
313 pin->SetVisible( g_LastPinVisible );
314
315 if( !EditPinProperties( pin ) )
316 {
317 delete pin;
318 pin = nullptr;
319 }
320
321 return pin;
322}
323
324
326{
327 int ii;
328 LIB_PIN* newPin;
329
330 // if "synchronize pins editing" option is off, do not create any similar pin for other
331 // units and/or shapes: each unit is edited regardless other units or body
332 if( !m_frame->SynchronizePins() )
333 return;
334
335 if( aPin->GetUnit() == 0 ) // Pin common to all units: no need to create similar pins.
336 return;
337
338 // When units are interchangeable, all units are expected to have similar pins
339 // at the same position
340 // to facilitate pin editing, create pins for all other units for the current body style
341 // at the same position as aPin
342
343 for( ii = 1; ii <= aPin->GetParent()->GetUnitCount(); ii++ )
344 {
345 if( ii == aPin->GetUnit() )
346 continue;
347
348 newPin = (LIB_PIN*) aPin->Clone();
349
350 // To avoid mistakes, gives this pin a new pin number because
351 // it does no have the save pin number as the master pin
352 // Because we do not know the actual number, give it a temporary number
353 wxString unknownNum;
354 unknownNum.Printf( "%s-U%c", aPin->GetNumber(), wxChar( 'A' + ii - 1 ) );
355 newPin->SetNumber( unknownNum );
356
357 newPin->SetUnit( ii );
358
359 try
360 {
361 aPin->GetParent()->AddDrawItem( newPin );
362 }
363 catch( const boost::bad_pointer& e )
364 {
365 wxLogError( "Cannot add new pin to symbol. Boost pointer error %s occurred.",
366 e.what() );
367 delete newPin;
368 return;
369 }
370
371 newPin->ClearFlags( IS_NEW );
372 }
373}
374
375
377{
378 LIB_SYMBOL* symbol = m_frame->GetCurSymbol();
380 LIB_PIN* sourcePin = dynamic_cast<LIB_PIN*>( selection.Front() );
381
382 if( !sourcePin )
383 return 0;
384
386
387 for( LIB_PIN* pin = symbol->GetNextPin(); pin; pin = symbol->GetNextPin( pin ) )
388 {
389 if( pin == sourcePin )
390 continue;
391
392 if( aEvent.IsAction( &EE_ACTIONS::pushPinLength ) )
393 {
394 if( !pin->GetConvert() || pin->GetConvert() == m_frame->GetConvert() )
395 pin->ChangeLength( sourcePin->GetLength() );
396 }
397 else if( aEvent.IsAction( &EE_ACTIONS::pushPinNameSize ) )
398 {
399 pin->SetNameTextSize( sourcePin->GetNameTextSize() );
400 }
401 else if( aEvent.IsAction( &EE_ACTIONS::pushPinNumSize ) )
402 {
403 pin->SetNumberTextSize( sourcePin->GetNumberTextSize() );
404 }
405 }
406
408 m_frame->OnModify();
409
410 return 0;
411}
412
413
414// Create a new pin based on the previous pin with an incremented pin number.
416{
417 LIB_PIN* pin = (LIB_PIN*) aSourcePin->Clone();
418 wxPoint step;
419
420 pin->ClearFlags();
421 pin->SetFlags( IS_NEW );
422
423 auto* settings = Pgm().GetSettingsManager().GetAppSettings<SYMBOL_EDITOR_SETTINGS>();
424
425 switch( pin->GetOrientation() )
426 {
427 case PIN_UP: step.x = schIUScale.MilsToIU(settings->m_Repeat.pin_step); break;
428 case PIN_DOWN: step.x = schIUScale.MilsToIU(settings->m_Repeat.pin_step); break;
429 case PIN_LEFT: step.y = schIUScale.MilsToIU(-settings->m_Repeat.pin_step); break;
430 case PIN_RIGHT: step.y = schIUScale.MilsToIU(-settings->m_Repeat.pin_step); break;
431 }
432
433 pin->Offset( step );
434
435 wxString nextName = pin->GetName();
436 IncrementLabelMember( nextName, settings->m_Repeat.label_delta );
437 pin->SetName( nextName );
438
439 wxString nextNumber = pin->GetNumber();
440 IncrementLabelMember( nextNumber, settings->m_Repeat.label_delta );
441 pin->SetNumber( nextNumber );
442
443 if( m_frame->SynchronizePins() )
444 pin->SetFlags( IS_LINKED );
445
446 if( PlacePin( pin ) )
447 return pin;
448
449 return nullptr;
450}
451
452
454{
458}
const char * name
Definition: DXF_plotter.cpp:56
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:111
void AddSeparator(int aOrder=ANY_ORDER)
Add a separator to the menu.
virtual PICKED_ITEMS_LIST * PopCommandFromUndoList()
Return the last command to undo and remove it from list, nothing is deleted.
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
EDA_ITEM_FLAGS GetEditFlags() const
Definition: eda_item.h:147
void SetModified()
Definition: eda_item.cpp:64
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:143
bool HasFlag(EDA_ITEM_FLAGS aFlag) const
Definition: eda_item.h:145
bool IsNew() const
Definition: eda_item.h:103
static TOOL_ACTION pushPinNameSize
Definition: ee_actions.h:225
static TOOL_ACTION pushPinNumSize
Definition: ee_actions.h:226
static TOOL_ACTION pushPinLength
Definition: ee_actions.h:224
EE_SELECTION & GetSelection()
A foundation class for a tool operating on a schematic or symbol.
Definition: ee_tool_base.h:50
void saveCopyInUndoList(EDA_ITEM *aItem, UNDO_REDO aType, bool aAppend=false, bool aDirtyConnectivity=true)
Definition: ee_tool_base.h:134
EE_SELECTION_TOOL * m_selectionTool
Definition: ee_tool_base.h:184
bool Init() override
Init() is called once upon a registration of the tool.
Definition: ee_tool_base.h:66
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: confirm.h:46
void DoNotShowCheckbox(wxString file, int line)
Checks the 'do not show again' setting for the dialog.
Definition: confirm.cpp:56
int ShowModal() override
Definition: confirm.cpp:100
int GetUnit() const
Definition: lib_item.h:273
int GetConvert() const
Definition: lib_item.h:276
LIB_SYMBOL * GetParent() const
Definition: lib_item.h:168
void SetUnit(int aUnit)
Definition: lib_item.h:272
int GetLength() const
Definition: lib_pin.h:80
ELECTRICAL_PINTYPE GetType() const
Definition: lib_pin.h:90
int GetOrientation() const
Definition: lib_pin.h:74
int GetNumberTextSize() const
Definition: lib_pin.h:135
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Display basic info (type, part and convert) about the current item in message panel.
Definition: lib_pin.cpp:1141
VECTOR2I GetPosition() const override
Definition: lib_pin.h:222
const wxString & GetNumber() const
Definition: lib_pin.h:122
GRAPHIC_PINSHAPE GetShape() const
Definition: lib_pin.h:77
bool IsVisible() const
Definition: lib_pin.h:103
void SetNumber(const wxString &aNumber)
Definition: lib_pin.h:124
const wxString & GetName() const
Definition: lib_pin.h:112
int GetNameTextSize() const
Definition: lib_pin.h:132
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: lib_pin.cpp:943
Define a library symbol object.
Definition: lib_symbol.h:98
void ClearTempFlags()
Clears the status flag all draw objects in this symbol.
void RemoveDrawItem(LIB_ITEM *aItem)
Remove draw aItem from list.
Definition: lib_symbol.cpp:790
void AddDrawItem(LIB_ITEM *aItem, bool aSort=true)
Add a new draw aItem to the draw object list and sort according to aSort.
Definition: lib_symbol.cpp:816
LIB_PIN * GetNextPin(LIB_PIN *aItem=nullptr)
Return the next pin object from the draw list.
Definition: lib_symbol.h:412
int GetUnitCount() const override
For items with units, return the number of units.
void GetPins(LIB_PINS &aList, int aUnit=0, int aConvert=0) const
Return a list of pin object pointers from the draw item list.
Definition: lib_symbol.cpp:856
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.
EDA_ITEM * Front() const
Definition: selection.h:206
void setTransitions() override
< Set up handlers for various events.
LIB_PIN * CreatePin(const VECTOR2I &aPosition, LIB_SYMBOL *aSymbol)
LIB_PIN * RepeatPin(const LIB_PIN *aSourcePin)
void CreateImagePins(LIB_PIN *aPin)
int PushPinProperties(const TOOL_EVENT &aEvent)
bool Init() override
Init() is called once upon a registration of the tool.
bool EditPinProperties(LIB_PIN *aPin)
The symbol library editor main window.
void UpdateItem(EDA_ITEM *aItem, bool isAddOrDelete=false, bool aUpdateRtree=false) override
Mark an item for refresh.
LIB_SYMBOL * GetCurSymbol() const
Return the current symbol being edited or NULL if none selected.
void OnModify() override
Must be called after a schematic change in order to set the "modify" flag of the current symbol.
void SaveCopyInUndoList(EDA_ITEM *aItem, UNDO_REDO aUndoType=UNDO_REDO::LIBEDIT, bool aAppend=false)
Create a copy of the current symbol, and save it in the undo list.
Generic, UI-independent tool event.
Definition: tool_event.h:156
bool IsAction(const TOOL_ACTION *aAction) const
Test if the event contains an action issued upon activation of the given TOOL_ACTION.
Definition: tool_event.cpp:88
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Define which state (aStateFunc) to go when a certain event arrives (aConditions).
TOOL_MENU & GetToolMenu()
CONDITIONAL_MENU & GetMenu()
Definition: tool_menu.cpp:44
This file is part of the common library.
#define _(s)
#define IS_PASTED
Modifier on IS_NEW which indicates it came from clipboard.
#define IS_NEW
New item, just created.
#define IS_LINKED
Used in calculation to mark linked items (temporary use)
std::vector< LIB_PIN * > LIB_PINS
Helper for defining a list of pin object pointers.
Definition: lib_item.h:54
@ PIN_LEFT
Definition: lib_pin.h:46
@ PIN_RIGHT
Definition: lib_pin.h:45
@ PIN_UP
Definition: lib_pin.h:47
@ PIN_DOWN
Definition: lib_pin.h:48
see class PGM_BASE
ELECTRICAL_PINTYPE
The symbol library pin object electrical types used in ERC tests.
Definition: pin_type.h:36
@ PT_INPUT
usual pin input: must be connected
GRAPHIC_PINSHAPE
Definition: pin_type.h:56
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:111
constexpr int MilsToIU(int mils) const
Definition: base_units.h:94
static GRAPHIC_PINSHAPE g_LastPinShape
static bool g_LastPinCommonConvert
static bool g_LastPinCommonUnit
static bool g_LastPinVisible
bool IncrementLabelMember(wxString &name, int aIncrement)
Definition: sch_label.cpp:49
static int GetLastPinNameSize()
static ELECTRICAL_PINTYPE g_LastPinType
static int GetLastPinLength()
static int g_LastPinLength
static int g_LastPinNameSize
static int g_LastPinNumSize
static int GetLastPinNumSize()
static int g_LastPinOrient
@ LIB_PIN_T
Definition: typeinfo.h:203