KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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
26
28#include <symbol_edit_frame.h>
29#include <sch_commit.h>
30#include <kidialog.h>
31#include <ee_actions.h>
33#include <increment.h>
36#include <pgm_base.h>
37#include <wx/debug.h>
38
39
43static bool g_LastPinCommonBodyStyle = false;
44static bool g_LastPinCommonUnit = false;
45static bool g_LastPinVisible = true;
46
47// The -1 is a non-valid value to trigger delayed initialization
48static int g_LastPinLength = -1;
49static int g_LastPinNameSize = -1;
50static int g_LastPinNumSize = -1;
51
52static int GetLastPinLength()
53{
54 if( g_LastPinLength == -1 )
55 {
58
60 }
61
62 return g_LastPinLength;
63}
64
66{
67 if( g_LastPinNameSize == -1 )
68 {
71
73 }
74
75 return g_LastPinNameSize;
76}
77
79{
80 if( g_LastPinNumSize == -1 )
81 {
84
86 }
87
88 return g_LastPinNumSize;
89}
90
91
93 EE_TOOL_BASE<SYMBOL_EDIT_FRAME>( "eeschema.PinEditing" )
94{
95}
96
97
99{
101
102 auto canEdit =
103 [&]( const SELECTION& sel )
104 {
106 wxCHECK( editor, false );
107
108 return editor->IsSymbolEditable() && !editor->IsSymbolAlias();
109 };
110
111 static const std::vector<KICAD_T> pinTypes = { SCH_PIN_T };
112
113 auto singlePinCondition = EE_CONDITIONS::Count( 1 ) && EE_CONDITIONS::OnlyTypes( pinTypes );
114
116
117 selToolMenu.AddSeparator( 250 );
118 selToolMenu.AddItem( EE_ACTIONS::pushPinLength, canEdit && singlePinCondition, 250 );
119 selToolMenu.AddItem( EE_ACTIONS::pushPinNameSize, canEdit && singlePinCondition, 250 );
120 selToolMenu.AddItem( EE_ACTIONS::pushPinNumSize, canEdit && singlePinCondition, 250 );
121
122 return true;
123}
124
125
126bool SYMBOL_EDITOR_PIN_TOOL::EditPinProperties( SCH_PIN* aPin, bool aFocusPinNumber )
127{
128 SCH_PIN original_pin( *aPin );
129 DIALOG_PIN_PROPERTIES dlg( m_frame, aPin, aFocusPinNumber );
130 SCH_COMMIT commit( m_frame );
131 LIB_SYMBOL* parentSymbol = static_cast<LIB_SYMBOL*>( aPin->GetParentSymbol() );
132
133 if( aPin->GetEditFlags() == 0 )
134 commit.Modify( parentSymbol );
135
136 if( dlg.ShowModal() == wxID_CANCEL )
137 return false;
138
139 if( !aPin->IsNew() && m_frame->SynchronizePins() && parentSymbol )
140 {
141 // a pin can have a unit id = 0 (common to all units) to unit count
142 // So we need a buffer size = GetUnitCount()+1 to store a value in a vector
143 // when using the unit id of a pin as index
144 std::vector<bool> got_unit( parentSymbol->GetUnitCount() + 1 );
145
146 got_unit[static_cast<size_t>(aPin->GetUnit())] = true;
147
148 for( SCH_PIN* other : parentSymbol->GetPins() )
149 {
150 if( other == aPin )
151 continue;
152
156 if( got_unit[static_cast<size_t>( other->GetUnit() )] )
157 continue;
158
159 if( other->GetPosition() == original_pin.GetPosition()
160 && other->GetOrientation() == original_pin.GetOrientation()
161 && other->GetType() == original_pin.GetType()
162 && other->IsVisible() == original_pin.IsVisible()
163 && other->GetName() == original_pin.GetName() )
164 {
165 if( aPin->GetBodyStyle() == 0 )
166 {
167 if( !aPin->GetUnit() || other->GetUnit() == aPin->GetUnit() )
168 parentSymbol->RemoveDrawItem( other );
169 }
170 else if( other->GetBodyStyle() == aPin->GetBodyStyle() )
171 {
172 other->SetPosition( aPin->GetPosition() );
173 other->ChangeLength( aPin->GetLength() );
174 other->SetShape( aPin->GetShape() );
175 }
176
177 if( aPin->GetUnit() == 0 )
178 {
179 if( !aPin->GetBodyStyle() || other->GetBodyStyle() == aPin->GetBodyStyle() )
180 parentSymbol->RemoveDrawItem( other );
181 }
182
183 other->SetOrientation( aPin->GetOrientation() );
184 other->SetType( aPin->GetType() );
185 other->SetVisible( aPin->IsVisible() );
186 other->SetName( aPin->GetName() );
187 other->SetNameTextSize( aPin->GetNameTextSize() );
188 other->SetNumberTextSize( aPin->GetNumberTextSize() );
189
190 got_unit[static_cast<size_t>( other->GetUnit() )] = true;
191 }
192 }
193 }
194
195 commit.Push( _( "Edit Pin Properties" ) );
196
197 std::vector<MSG_PANEL_ITEM> items;
198 aPin->GetMsgPanelInfo( m_frame, items );
199 m_frame->SetMsgPanel( items );
200
201 // Save the pin properties to use for the next new pin.
205 g_LastPinLength = aPin->GetLength();
206 g_LastPinShape = aPin->GetShape();
207 g_LastPinType = aPin->GetType();
209 g_LastPinCommonUnit = aPin->GetUnit() == 0;
210 g_LastPinVisible = aPin->IsVisible();
211
212 return true;
213}
214
215
217{
218 LIB_SYMBOL* symbol = m_frame->GetCurSymbol();
219 bool ask_for_pin = true; // Test for another pin in same position in other units
220
221 std::vector<SCH_PIN*> pins = symbol->GetAllLibPins();
222
223 for( SCH_PIN* test : pins )
224 {
225 if( test == aPin || aPin->GetPosition() != test->GetPosition() || test->GetEditFlags() )
226 continue;
227
228 // test for same body style
229 if( test->GetBodyStyle() && test->GetBodyStyle() != aPin->GetBodyStyle() )
230 continue;
231
232 if( ask_for_pin && m_frame->SynchronizePins() )
233 {
234 wxString msg;
235 msg.Printf( _( "This position is already occupied by another pin, in unit %d." ),
236 test->GetUnit() );
237
238 KIDIALOG dlg( m_frame, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
239 dlg.SetOKLabel( _( "Place Pin Anyway" ) );
240 dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
241
242 bool status = dlg.ShowModal() == wxID_OK;
243
244 if( !status )
245 {
246 if( aPin->IsNew() && !aPin->HasFlag( IS_PASTED ) )
247 delete aPin;
248
249 return false;
250 }
251 else
252 {
253 ask_for_pin = false;
254 }
255 }
256 }
257
258 if( aPin->IsNew() && !aPin->HasFlag( IS_PASTED ) )
259 {
261 g_LastPinType = aPin->GetType();
262 g_LastPinShape = aPin->GetShape();
263
264 if( m_frame->SynchronizePins() )
265 CreateImagePins( aPin );
266
267 symbol->AddDrawItem( aPin );
268 aPin->ClearFlags( IS_NEW );
269 }
270
271 // Put linked pins in new position, and clear flags
272 for( SCH_PIN* pin : pins )
273 {
274 if( ( pin->GetEditFlags() & IS_LINKED ) == 0 )
275 continue;
276
277 pin->SetPosition( aPin->GetPosition() );
278 pin->ClearFlags();
279 }
280
282 m_frame->OnModify();
283
284 return true;
285}
286
287
288/*
289 * Create a new pin.
290 */
292{
293 aSymbol->ClearTempFlags();
294
295 SCH_PIN* pin = new SCH_PIN( aSymbol );
296
297 pin->SetFlags( IS_NEW );
298
299 // Flag pins to consider
300 if( m_frame->SynchronizePins() )
301 pin->SetFlags( IS_LINKED );
302
303 pin->SetPosition( aPosition );
304 pin->SetLength( GetLastPinLength() );
305 pin->SetOrientation( g_LastPinOrient );
306 pin->SetType( g_LastPinType );
307 pin->SetShape( g_LastPinShape );
308 pin->SetNameTextSize( GetLastPinNameSize() );
309 pin->SetNumberTextSize( GetLastPinNumSize() );
310 pin->SetBodyStyle( g_LastPinCommonBodyStyle ? 0 : m_frame->GetBodyStyle() );
311 pin->SetUnit( g_LastPinCommonUnit ? 0 : m_frame->GetUnit() );
312 pin->SetVisible( g_LastPinVisible );
313
314 if( !EditPinProperties( pin, false ) )
315 {
316 delete pin;
317 pin = nullptr;
318 }
319
320 return pin;
321}
322
323
325{
326 int ii;
327 SCH_PIN* newPin;
328
329 // if "synchronize pins editing" option is off, do not create any similar pin for other
330 // units and/or shapes: each unit is edited regardless other units or body
331 if( !m_frame->SynchronizePins() )
332 return;
333
334 if( aPin->GetUnit() == 0 ) // Pin common to all units: no need to create similar pins.
335 return;
336
337 // When units are interchangeable, all units are expected to have similar pins
338 // at the same position
339 // to facilitate pin editing, create pins for all other units for the current body style
340 // at the same position as aPin
341
342 for( ii = 1; ii <= aPin->GetParentSymbol()->GetUnitCount(); ii++ )
343 {
344 if( ii == aPin->GetUnit() )
345 continue;
346
347 newPin = static_cast<SCH_PIN*>( aPin->Duplicate() );
348
349 // To avoid mistakes, gives this pin a new pin number because
350 // it does no have the save pin number as the master pin
351 // Because we do not know the actual number, give it a temporary number
352 wxString unknownNum;
353 unknownNum.Printf( "%s-U%c", aPin->GetNumber(), wxChar( 'A' + ii - 1 ) );
354 newPin->SetNumber( unknownNum );
355
356 newPin->SetUnit( ii );
357
358 try
359 {
360 LIB_SYMBOL* symbol = static_cast<LIB_SYMBOL*>( aPin->GetParentSymbol() );
361 symbol->AddDrawItem( newPin );
362 }
363 catch( const boost::bad_pointer& e )
364 {
365 wxFAIL_MSG( wxString::Format( wxT( "Boost pointer exception occurred: %s" ),
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 SCH_PIN* sourcePin = dynamic_cast<SCH_PIN*>( selection.Front() );
381
382 if( !sourcePin )
383 return 0;
384
385 saveCopyInUndoList( symbol, UNDO_REDO::LIBEDIT );
386
387 for( SCH_PIN* pin : symbol->GetAllLibPins() )
388 {
389 if( pin == sourcePin )
390 continue;
391
392 if( aEvent.IsAction( &EE_ACTIONS::pushPinLength ) )
393 {
394 if( !pin->GetBodyStyle() || pin->GetBodyStyle() == m_frame->GetBodyStyle() )
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 SCH_COMMIT commit( m_frame );
418 LIB_SYMBOL* symbol = m_frame->GetCurSymbol();
419
420 commit.Modify( symbol );
421
422 SCH_PIN* pin = static_cast<SCH_PIN*>( aSourcePin->Duplicate() );
423 VECTOR2I step;
424
425 pin->ClearFlags();
426 pin->SetFlags( IS_NEW );
427
429 SYMBOL_EDITOR_SETTINGS* cfg = mgr.GetAppSettings<SYMBOL_EDITOR_SETTINGS>( "symbol_editor" );
430
431 switch( pin->GetOrientation() )
432 {
433 default:
434 case PIN_ORIENTATION::PIN_RIGHT: step.y = schIUScale.MilsToIU( -cfg->m_Repeat.pin_step ); break;
435 case PIN_ORIENTATION::PIN_UP: step.x = schIUScale.MilsToIU( cfg->m_Repeat.pin_step ); break;
436 case PIN_ORIENTATION::PIN_DOWN: step.x = schIUScale.MilsToIU( cfg->m_Repeat.pin_step) ; break;
437 case PIN_ORIENTATION::PIN_LEFT: step.y = schIUScale.MilsToIU( -cfg->m_Repeat.pin_step ); break;
438 }
439
440 pin->Move( step );
441
442 wxString nextName = pin->GetName();
443 IncrementString( nextName, cfg->m_Repeat.label_delta );
444 pin->SetName( nextName );
445
446 wxString nextNumber = pin->GetNumber();
447 IncrementString( nextNumber, cfg->m_Repeat.label_delta );
448 pin->SetNumber( nextNumber );
449
450 if( m_frame->SynchronizePins() )
451 pin->SetFlags( IS_LINKED );
452
453 if( PlacePin( pin ) )
454 {
455 commit.Push( _( "Repeat Pin" ) );
456 return pin;
457 }
458
459 return nullptr;
460}
461
462
464{
468}
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:110
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Create an undo entry for an item that has been already modified.
Definition: commit.h:105
void AddItem(const TOOL_ACTION &aAction, const SELECTION_CONDITION &aCondition, int aOrder=ANY_ORDER)
Add a menu entry to run a TOOL_ACTION on selected items.
void AddSeparator(int aOrder=ANY_ORDER)
Add a separator to the menu.
int ShowModal() override
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:133
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:129
bool HasFlag(EDA_ITEM_FLAGS aFlag) const
Definition: eda_item.h:131
bool IsNew() const
Definition: eda_item.h:107
static TOOL_ACTION pushPinNameSize
Definition: ee_actions.h:263
static TOOL_ACTION pushPinNumSize
Definition: ee_actions.h:264
static TOOL_ACTION pushPinLength
Definition: ee_actions.h:262
EE_SELECTION & GetSelection()
A foundation class for a tool operating on a schematic or symbol.
Definition: ee_tool_base.h:48
void saveCopyInUndoList(EDA_ITEM *aItem, UNDO_REDO aType, bool aAppend=false, bool aDirtyConnectivity=true)
Definition: ee_tool_base.h:143
EE_SELECTION_TOOL * m_selectionTool
Definition: ee_tool_base.h:200
bool Init() override
Init() is called once upon a registration of the tool.
Definition: ee_tool_base.h:64
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: kidialog.h:43
void DoNotShowCheckbox(wxString file, int line)
Checks the 'do not show again' setting for the dialog.
Definition: kidialog.cpp:51
int ShowModal() override
Definition: kidialog.cpp:95
Define a library symbol object.
Definition: lib_symbol.h:78
std::vector< SCH_PIN * > GetPins(int aUnit=0, int aBodyStyle=0) const
Return a list of pin object pointers from the draw item list.
Definition: lib_symbol.cpp:822
void ClearTempFlags() override
Clears the status flag all draw objects in this symbol.
std::vector< SCH_PIN * > GetAllLibPins() const
Return a list of pin pointers for all units / converts.
Definition: lib_symbol.cpp:854
void RemoveDrawItem(SCH_ITEM *aItem)
Remove draw aItem from list.
Definition: lib_symbol.cpp:783
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.
Definition: lib_symbol.cpp:808
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition: pgm_base.h:142
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Revert the commit by restoring the modified items state.
Definition: sch_commit.cpp:432
const SYMBOL * GetParentSymbol() const
Definition: sch_item.cpp:166
int GetBodyStyle() const
Definition: sch_item.h:232
int GetUnit() const
Definition: sch_item.h:229
virtual void SetUnit(int aUnit)
Definition: sch_item.h:228
SCH_ITEM * Duplicate(bool doClone=false) const
Routine to create a new copy of given item.
Definition: sch_item.cpp:131
int GetNumberTextSize() const
Definition: sch_pin.cpp:557
int GetLength() const
Definition: sch_pin.cpp:295
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.
Definition: sch_pin.cpp:1544
void SetNumber(const wxString &aNumber)
Definition: sch_pin.cpp:520
bool IsVisible() const
Definition: sch_pin.cpp:367
const wxString & GetName() const
Definition: sch_pin.cpp:381
PIN_ORIENTATION GetOrientation() const
Definition: sch_pin.cpp:260
VECTOR2I GetPosition() const override
Definition: sch_pin.cpp:252
int GetNameTextSize() const
Definition: sch_pin.cpp:533
const wxString & GetNumber() const
Definition: sch_pin.h:117
GRAPHIC_PINSHAPE GetShape() const
Definition: sch_pin.cpp:274
ELECTRICAL_PINTYPE GetType() const
Definition: sch_pin.cpp:309
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:172
T * GetAppSettings(const wxString &aFilename)
Returns a handle to the a given settings by type If the settings have already been loaded,...
void setTransitions() override
< Set up handlers for various events.
int PushPinProperties(const TOOL_EVENT &aEvent)
bool EditPinProperties(SCH_PIN *aPin, bool aFocusPinNumber)
SCH_PIN * RepeatPin(const SCH_PIN *aSourcePin)
bool Init() override
Init() is called once upon a registration of the tool.
SCH_PIN * CreatePin(const VECTOR2I &aPosition, LIB_SYMBOL *aSymbol)
void CreateImagePins(SCH_PIN *aPin)
The symbol library editor main window.
int GetBodyStyle() const
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.
Generic, UI-independent tool event.
Definition: tool_event.h:167
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:82
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
#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)
KICOMMON_API bool IncrementString(wxString &name, int aIncrement)
Generic string incrementer.
Definition: increment.cpp:33
This file is part of the common library.
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: pgm_base.cpp:1060
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
PIN_ORIENTATION
The symbol library pin object orientations.
Definition: pin_type.h:78
@ PIN_RIGHT
The pin extends rightwards from the connection point.
GRAPHIC_PINSHAPE
Definition: pin_type.h:57
constexpr int MilsToIU(int mils) const
Definition: base_units.h:93
static GRAPHIC_PINSHAPE g_LastPinShape
static bool g_LastPinCommonUnit
static bool g_LastPinVisible
static int GetLastPinNameSize()
static ELECTRICAL_PINTYPE g_LastPinType
static bool g_LastPinCommonBodyStyle
static int GetLastPinLength()
static int g_LastPinLength
static int g_LastPinNameSize
static int g_LastPinNumSize
static int GetLastPinNumSize()
static PIN_ORIENTATION g_LastPinOrient
@ SCH_PIN_T
Definition: typeinfo.h:153