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 The 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
27#include <sch_commit.h>
28#include <kidialog.h>
29#include <sch_actions.h>
31#include <increment.h>
34#include <pgm_base.h>
35#include <wx/debug.h>
36
37
41static bool g_LastPinCommonBodyStyle = 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 {
55 g_LastPinLength = schIUScale.MilsToIU( cfg->m_Defaults.pin_length );
56 }
57
58 return g_LastPinLength;
59}
60
62{
63 if( g_LastPinNameSize == -1 )
64 {
66 g_LastPinNameSize = schIUScale.MilsToIU( cfg->m_Defaults.pin_name_size );
67 }
68
69 return g_LastPinNameSize;
70}
71
73{
74 if( g_LastPinNumSize == -1 )
75 {
77 g_LastPinNumSize = schIUScale.MilsToIU( cfg->m_Defaults.pin_num_size );
78 }
79
80 return g_LastPinNumSize;
81}
82
83
88
89
91{
93
94 auto canEdit =
95 [this]( const SELECTION& sel )
96 {
98
99 return editor && editor->IsSymbolEditable() && !editor->IsSymbolAlias();
100 };
101
102 static const std::vector<KICAD_T> pinTypes = { SCH_PIN_T };
103
104 auto singlePinCondition = SCH_CONDITIONS::Count( 1 ) && SCH_CONDITIONS::OnlyTypes( pinTypes );
105
106 CONDITIONAL_MENU& selToolMenu = m_selectionTool->GetToolMenu().GetMenu();
107
108 selToolMenu.AddSeparator( 250 );
109 selToolMenu.AddItem( SCH_ACTIONS::pushPinLength, canEdit && singlePinCondition, 250 );
110 selToolMenu.AddItem( SCH_ACTIONS::pushPinNameSize, canEdit && singlePinCondition, 250 );
111 selToolMenu.AddItem( SCH_ACTIONS::pushPinNumSize, canEdit && singlePinCondition, 250 );
112
113 return true;
114}
115
116
117bool SYMBOL_EDITOR_PIN_TOOL::EditPinProperties( SCH_PIN* aPin, bool aFocusPinNumber )
118{
119 SCH_PIN original_pin( *aPin );
120 DIALOG_PIN_PROPERTIES dlg( m_frame, aPin, aFocusPinNumber );
121 SCH_COMMIT commit( m_frame );
122 LIB_SYMBOL* parentSymbol = static_cast<LIB_SYMBOL*>( aPin->GetParentSymbol() );
123
124 if( aPin->GetEditFlags() == 0 )
125 commit.Modify( parentSymbol, m_frame->GetScreen() );
126
127 if( dlg.ShowModal() == wxID_CANCEL )
128 return false;
129
130 if( !aPin->IsNew() && m_frame->SynchronizePins() && parentSymbol )
131 {
132 // a pin can have a unit id = 0 (common to all units) to unit count
133 // So we need a buffer size = GetUnitCount()+1 to store a value in a vector
134 // when using the unit id of a pin as index
135 std::vector<bool> got_unit( parentSymbol->GetUnitCount() + 1 );
136
137 got_unit[static_cast<size_t>(aPin->GetUnit())] = true;
138
139 for( SCH_PIN* other : parentSymbol->GetPins() )
140 {
141 if( other == aPin )
142 continue;
143
147 if( got_unit[static_cast<size_t>( other->GetUnit() )] )
148 continue;
149
150 if( other->GetPosition() == original_pin.GetPosition()
151 && other->GetOrientation() == original_pin.GetOrientation()
152 && other->GetType() == original_pin.GetType()
153 && other->IsVisible() == original_pin.IsVisible()
154 && other->GetName() == original_pin.GetName() )
155 {
156 if( aPin->GetBodyStyle() == 0 )
157 {
158 if( !aPin->GetUnit() || other->GetUnit() == aPin->GetUnit() )
159 parentSymbol->RemoveDrawItem( other );
160 }
161
162 if( other->GetBodyStyle() == aPin->GetBodyStyle() )
163 {
164 other->ChangeLength( aPin->GetLength() );
165
166 // Must be done after ChangeLenght(), which can alter the position
167 other->SetPosition( aPin->GetPosition() );
168
169 other->SetShape( aPin->GetShape() );
170 }
171
172 if( aPin->GetUnit() == 0 )
173 {
174 if( !aPin->GetBodyStyle() || other->GetBodyStyle() == aPin->GetBodyStyle() )
175 parentSymbol->RemoveDrawItem( other );
176 }
177
178 other->SetOrientation( aPin->GetOrientation() );
179 other->SetType( aPin->GetType() );
180 other->SetVisible( aPin->IsVisible() );
181 other->SetName( aPin->GetName() );
182 other->SetNameTextSize( aPin->GetNameTextSize() );
183 other->SetNumberTextSize( aPin->GetNumberTextSize() );
184
185 got_unit[static_cast<size_t>( other->GetUnit() )] = true;
186 }
187 }
188 }
189
190 commit.Push( _( "Edit Pin Properties" ) );
191
192 std::vector<MSG_PANEL_ITEM> items;
193 aPin->GetMsgPanelInfo( m_frame, items );
194 m_frame->SetMsgPanel( items );
195
196 // Save the pin properties to use for the next new pin.
200 g_LastPinLength = aPin->GetLength();
201 g_LastPinShape = aPin->GetShape();
202 g_LastPinType = aPin->GetType();
204 g_LastPinCommonUnit = aPin->GetUnit() == 0;
205 g_LastPinVisible = aPin->IsVisible();
206
207 return true;
208}
209
210
212{
213 LIB_SYMBOL* symbol = m_frame->GetCurSymbol();
214 bool ask_for_pin = true; // Test for another pin in same position in other units
215
216 std::vector<SCH_PIN*> pins = symbol->GetPins();
217
218 for( SCH_PIN* test : pins )
219 {
220 if( test == aPin || aPin->GetPosition() != test->GetPosition() || test->GetEditFlags() )
221 continue;
222
223 // test for same body style
224 if( test->GetBodyStyle() && test->GetBodyStyle() != aPin->GetBodyStyle() )
225 continue;
226
227 if( ask_for_pin && m_frame->SynchronizePins() )
228 {
229 wxString msg;
230 msg.Printf( _( "This position is already occupied by another pin, in unit %d." ),
231 test->GetUnit() );
232
233 KIDIALOG dlg( m_frame, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
234 dlg.SetExtendedMessage( _( "Disable the 'Synchronized Pins Mode' option to avoid this message." ) );
235 dlg.SetOKLabel( _( "Place Pin Anyway" ) );
236 dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
237
238 bool status = dlg.ShowModal() == wxID_OK;
239
240 if( !status )
241 {
242 if( aPin->IsNew() && !aPin->HasFlag( IS_PASTED ) )
243 delete aPin;
244
245 return false;
246 }
247 else
248 {
249 ask_for_pin = false;
250 }
251 }
252 }
253
254 if( aPin->IsNew() && !aPin->HasFlag( IS_PASTED ) )
255 {
257 g_LastPinType = aPin->GetType();
258 g_LastPinShape = aPin->GetShape();
259
260 if( m_frame->SynchronizePins() )
261 CreateImagePins( aCommit, aPin );
262
263 symbol->AddDrawItem( aPin );
264 aPin->ClearFlags( IS_NEW );
265 }
266
267 // Put linked pins in new position, and clear flags
268 for( SCH_PIN* pin : pins )
269 {
270 if( ( pin->GetEditFlags() & IS_LINKED ) == 0 )
271 continue;
272
273 pin->SetPosition( aPin->GetPosition() );
274 pin->ClearFlags();
275 }
276
277 m_frame->RebuildView();
278 m_frame->OnModify();
279
280 return true;
281}
282
283
284/*
285 * Create a new pin.
286 */
288{
289 aSymbol->ClearTempFlags();
290
291 SCH_PIN* pin = new SCH_PIN( aSymbol );
292
293 pin->SetFlags( IS_NEW );
294
295 // Flag pins to consider
296 if( m_frame->SynchronizePins() )
297 pin->SetFlags( IS_LINKED );
298
299 pin->SetPosition( aPosition );
300 pin->SetLength( GetLastPinLength() );
301 pin->SetOrientation( g_LastPinOrient );
302 pin->SetType( g_LastPinType );
303 pin->SetShape( g_LastPinShape );
304 pin->SetNameTextSize( GetLastPinNameSize() );
305 pin->SetNumberTextSize( GetLastPinNumSize() );
306 pin->SetBodyStyle( g_LastPinCommonBodyStyle ? 0 : m_frame->GetBodyStyle() );
307 pin->SetUnit( g_LastPinCommonUnit ? 0 : m_frame->GetUnit() );
308 pin->SetVisible( g_LastPinVisible );
309
310 if( !EditPinProperties( pin, false ) )
311 {
312 delete pin;
313 pin = nullptr;
314 }
315
316 return pin;
317}
318
319
321{
322 int ii;
323 SCH_PIN* newPin;
324
325 // if "synchronize pins editing" option is off, do not create any similar pin for other
326 // units and/or shapes: each unit is edited regardless other units or body
327 if( !m_frame->SynchronizePins() )
328 return;
329
330 if( aPin->GetUnit() == 0 ) // Pin common to all units: no need to create similar pins.
331 return;
332
333 // When units are interchangeable, all units are expected to have similar pins
334 // at the same position
335 // to facilitate pin editing, create pins for all other units for the current body style
336 // at the same position as aPin
337
338 for( ii = 1; ii <= aPin->GetParentSymbol()->GetUnitCount(); ii++ )
339 {
340 if( ii == aPin->GetUnit() )
341 continue;
342
343 // Already called Modify() on parent symbol; no need for Modify() calls on individual items
345 newPin = static_cast<SCH_PIN*>( aPin->Duplicate( true, &dummy ) );
346
347 // To avoid mistakes, gives this pin a new pin number because
348 // it does no have the save pin number as the master pin
349 // Because we do not know the actual number, give it a temporary number
350 wxString unknownNum;
351 unknownNum.Printf( "%s-U%c", aPin->GetNumber(), wxChar( 'A' + ii - 1 ) );
352 newPin->SetNumber( unknownNum );
353
354 newPin->SetUnit( ii );
355
356 try
357 {
358 LIB_SYMBOL* symbol = static_cast<LIB_SYMBOL*>( aPin->GetParentSymbol() );
359 symbol->AddDrawItem( newPin );
360 }
361 catch( const boost::bad_pointer& e )
362 {
363 wxFAIL_MSG( wxString::Format( wxT( "Boost pointer exception occurred: %s" ), e.what() ));
364 delete newPin;
365 return;
366 }
367
368 newPin->ClearFlags( IS_NEW );
369 }
370}
371
372
374{
375 LIB_SYMBOL* symbol = m_frame->GetCurSymbol();
376 SCH_SELECTION& selection = m_selectionTool->GetSelection();
377 SCH_PIN* sourcePin = dynamic_cast<SCH_PIN*>( selection.Front() );
378
379 if( !sourcePin )
380 return 0;
381
383
384 for( SCH_PIN* pin : symbol->GetPins() )
385 {
386 if( pin == sourcePin )
387 continue;
388
389 if( aEvent.IsAction( &SCH_ACTIONS::pushPinLength ) )
390 {
391 if( !pin->GetBodyStyle() || pin->GetBodyStyle() == m_frame->GetBodyStyle() )
392 pin->ChangeLength( sourcePin->GetLength() );
393 }
394 else if( aEvent.IsAction( &SCH_ACTIONS::pushPinNameSize ) )
395 {
396 pin->SetNameTextSize( sourcePin->GetNameTextSize() );
397 }
398 else if( aEvent.IsAction( &SCH_ACTIONS::pushPinNumSize ) )
399 {
400 pin->SetNumberTextSize( sourcePin->GetNumberTextSize() );
401 }
402 }
403
404 m_frame->RebuildView();
405 m_frame->OnModify();
406
407 return 0;
408}
409
410
411// Create a new pin based on the previous pin with an incremented pin number.
413{
414 SCH_COMMIT commit( m_frame );
415 LIB_SYMBOL* symbol = m_frame->GetCurSymbol();
416
417 commit.Modify( symbol, m_frame->GetScreen() );
418
419 SCH_PIN* pin = static_cast<SCH_PIN*>( aSourcePin->Duplicate( true, &commit ) );
420
421 pin->ClearFlags();
422 pin->SetFlags( IS_NEW );
423
425 {
426 VECTOR2I step;
427
428 switch( pin->GetOrientation() )
429 {
430 default:
431 case PIN_ORIENTATION::PIN_RIGHT: step.y = schIUScale.MilsToIU( cfg->m_Repeat.pin_step ); break;
432 case PIN_ORIENTATION::PIN_UP: step.x = schIUScale.MilsToIU( cfg->m_Repeat.pin_step ); break;
433 case PIN_ORIENTATION::PIN_DOWN: step.x = schIUScale.MilsToIU( cfg->m_Repeat.pin_step) ; break;
434 case PIN_ORIENTATION::PIN_LEFT: step.y = schIUScale.MilsToIU( cfg->m_Repeat.pin_step ); break;
435 }
436
437 pin->Move( step );
438
439 wxString nextName = pin->GetName();
440 IncrementString( nextName, cfg->m_Repeat.label_delta );
441 pin->SetName( nextName );
442
443 wxString nextNumber = pin->GetNumber();
444 IncrementString( nextNumber, cfg->m_Repeat.label_delta );
445 pin->SetNumber( nextNumber );
446 }
447
448 if( m_frame->SynchronizePins() )
449 pin->SetFlags( IS_LINKED );
450
451 if( PlacePin( &commit, pin ) )
452 {
453 commit.Push( _( "Repeat Pin" ) );
454 return pin;
455 }
456
457 return nullptr;
458}
459
460
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:114
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
Definition commit.h:106
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
EDA_ITEM_FLAGS GetEditFlags() const
Definition eda_item.h:148
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition eda_item.h:144
bool HasFlag(EDA_ITEM_FLAGS aFlag) const
Definition eda_item.h:146
bool IsNew() const
Definition eda_item.h:124
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition kidialog.h:42
void DoNotShowCheckbox(wxString file, int line)
Shows the 'do not show again' checkbox.
Definition kidialog.cpp:55
int ShowModal() override
Definition kidialog.cpp:93
Define a library symbol object.
Definition lib_symbol.h:85
void ClearTempFlags() override
Clears the status flag all draw objects in this symbol.
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.
static TOOL_ACTION pushPinLength
static TOOL_ACTION pushPinNameSize
static TOOL_ACTION pushPinNumSize
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Execute the changes.
SCH_ITEM * Duplicate(bool addToParentGroup, SCH_COMMIT *aCommit=nullptr, bool doClone=false) const
Routine to create a new copy of given item.
Definition sch_item.cpp:137
const SYMBOL * GetParentSymbol() const
Definition sch_item.cpp:223
int GetBodyStyle() const
Definition sch_item.h:244
int GetUnit() const
Definition sch_item.h:238
virtual void SetUnit(int aUnit)
Definition sch_item.h:237
int GetNumberTextSize() const
Definition sch_pin.cpp:670
int GetLength() const
Definition sch_pin.cpp:298
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:1326
void SetNumber(const wxString &aNumber)
Definition sch_pin.cpp:633
bool IsVisible() const
Definition sch_pin.cpp:386
const wxString & GetName() const
Definition sch_pin.cpp:400
PIN_ORIENTATION GetOrientation() const
Definition sch_pin.cpp:263
VECTOR2I GetPosition() const override
Definition sch_pin.cpp:255
int GetNameTextSize() const
Definition sch_pin.cpp:646
const wxString & GetNumber() const
Definition sch_pin.h:124
GRAPHIC_PINSHAPE GetShape() const
Definition sch_pin.cpp:277
ELECTRICAL_PINTYPE GetType() const
Definition sch_pin.cpp:312
void saveCopyInUndoList(EDA_ITEM *aItem, UNDO_REDO aType, bool aAppend=false, bool aDirtyConnectivity=true)
bool Init() override
Init() is called once upon a registration of the tool.
SCH_TOOL_BASE(const std::string &aName)
SCH_SELECTION_TOOL * m_selectionTool
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:177
void setTransitions() override
< Set up handlers for various events.
int PushPinProperties(const TOOL_EVENT &aEvent)
bool EditPinProperties(SCH_PIN *aPin, bool aFocusPinNumber)
void CreateImagePins(SCH_COMMIT *aCommit, SCH_PIN *aPin)
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)
bool PlacePin(SCH_COMMIT *aCommit, SCH_PIN *aPin)
The symbol library editor main window.
Generic, UI-independent tool event.
Definition tool_event.h:171
bool IsAction(const TOOL_ACTION *aAction) const
Test if the event contains an action issued upon activation of the given TOOL_ACTION.
void Go(int(SYMBOL_EDIT_FRAME::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
#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
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
Definition pin_type.h:37
PIN_ORIENTATION
The symbol library pin object orientations.
Definition pin_type.h:105
@ PIN_UP
The pin extends upwards from the connection point: Probably on the bottom side of the symbol.
Definition pin_type.h:127
@ PIN_RIGHT
The pin extends rightwards from the connection point.
Definition pin_type.h:111
@ PIN_LEFT
The pin extends leftwards from the connection point: Probably on the right side of the symbol.
Definition pin_type.h:118
@ PIN_DOWN
The pin extends downwards from the connection: Probably on the top side of the symbol.
Definition pin_type.h:135
GRAPHIC_PINSHAPE
Definition pin_type.h:84
T * GetAppSettings(const char *aFilename)
std::vector< FAB_LAYER_COLOR > dummy
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:155
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695