KiCad PCB EDA Suite
lib_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 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 <lib_edit_frame.h>
28 #include <confirm.h>
29 #include <ee_actions.h>
33 #include <pgm_base.h>
34 #include "lib_pin_tool.h"
35 
36 
40 static bool g_LastPinCommonConvert = false;
41 static bool g_LastPinCommonUnit = false;
42 static bool g_LastPinVisible = true;
43 
44 // The -1 is a non-valid value to trigger delayed initialization
45 static int g_LastPinLength = -1;
46 static int g_LastPinNameSize = -1;
47 static int g_LastPinNumSize = -1;
48 
49 static int GetLastPinLength()
50 {
51  if( g_LastPinLength == -1 )
52  {
53  LIBEDIT_SETTINGS* settings = Pgm().GetSettingsManager().GetAppSettings<LIBEDIT_SETTINGS>();
54  g_LastPinLength = Mils2iu( settings->m_Defaults.pin_length );
55  }
56 
57  return g_LastPinLength;
58 }
59 
60 static int GetLastPinNameSize()
61 {
62  if( g_LastPinNameSize == -1 )
63  {
64  LIBEDIT_SETTINGS* settings = Pgm().GetSettingsManager().GetAppSettings<LIBEDIT_SETTINGS>();
65  g_LastPinNameSize = Mils2iu( settings->m_Defaults.pin_name_size );
66  }
67 
68  return g_LastPinNameSize;
69 }
70 
71 static int GetLastPinNumSize()
72 {
73  if( g_LastPinNumSize == -1 )
74  {
75  LIBEDIT_SETTINGS* settings = Pgm().GetSettingsManager().GetAppSettings<LIBEDIT_SETTINGS>();
76  g_LastPinNumSize = Mils2iu( settings->m_Defaults.pin_num_size );
77  }
78 
79  return g_LastPinNumSize;
80 }
81 
82 
83 extern void IncrementLabelMember( wxString& name, int aIncrement );
84 
85 
87  EE_TOOL_BASE<LIB_EDIT_FRAME>( "eeschema.PinEditing" )
88 {
89 }
90 
91 
93 {
95 
96  auto singlePinCondition = EE_CONDITIONS::Count( 1 ) && EE_CONDITIONS::OnlyType( LIB_PIN_T );
97 
99 
100  selToolMenu.AddSeparator( 400 );
101  selToolMenu.AddItem( EE_ACTIONS::pushPinLength, singlePinCondition, 400 );
102  selToolMenu.AddItem( EE_ACTIONS::pushPinNameSize, singlePinCondition, 400 );
103  selToolMenu.AddItem( EE_ACTIONS::pushPinNumSize, singlePinCondition, 400 );
104 
105  return true;
106 }
107 
108 
110 {
111  DIALOG_PIN_PROPERTIES dlg( m_frame, aPin );
112 
113  if( aPin->GetEditFlags() == 0 )
115 
116  if( dlg.ShowModal() == wxID_CANCEL )
117  {
118  if( aPin->GetEditFlags() == 0 )
120 
121  return false;
122  }
123 
124  aPin->SetModified();
125 
126  if( !aPin->IsNew() && m_frame->SynchronizePins() && aPin->GetParent() )
127  {
128  LIB_PINS pinList;
129  aPin->GetParent()->GetPins( pinList );
130 
131  for( LIB_PIN* other : pinList )
132  {
133  if( other == aPin )
134  continue;
135 
136  if( other->GetPosition() == aPin->GetPosition()
137  && other->GetOrientation() == aPin->GetOrientation() )
138  {
139  if( aPin->GetConvert() == 0 )
140  {
141  if( !aPin->GetUnit() || other->GetUnit() == aPin->GetUnit() )
142  aPin->GetParent()->RemoveDrawItem( other );
143  }
144  else if( other->GetConvert() == aPin->GetConvert() )
145  {
146  other->SetPosition( aPin->GetPosition() );
147  other->SetLength( aPin->GetLength() );
148  other->SetShape( aPin->GetShape() );
149  }
150 
151  if( aPin->GetUnit() == 0 )
152  {
153  if( !aPin->GetConvert() || other->GetConvert() == aPin->GetConvert() )
154  aPin->GetParent()->RemoveDrawItem( other );
155  }
156 
157  other->SetOrientation( aPin->GetOrientation() );
158  other->SetType( aPin->GetType() );
159  other->SetVisible( aPin->IsVisible() );
160  other->SetName( aPin->GetName() );
161  other->SetNameTextSize( aPin->GetNameTextSize() );
162  other->SetNumberTextSize( aPin->GetNumberTextSize() );
163 
164  other->SetModified();
165  }
166  }
167  }
168 
169  m_frame->UpdateItem( aPin );
170  m_frame->OnModify( );
171 
172  MSG_PANEL_ITEMS items;
173  aPin->GetMsgPanelInfo( m_frame, items );
174  m_frame->SetMsgPanel( items );
175 
176  // Save the pin properties to use for the next new pin.
180  g_LastPinLength = aPin->GetLength();
181  g_LastPinShape = aPin->GetShape();
182  g_LastPinType = aPin->GetType();
183  g_LastPinCommonConvert = aPin->GetConvert() == 0;
184  g_LastPinCommonUnit = aPin->GetUnit() == 0;
185  g_LastPinVisible = aPin->IsVisible();
186 
187  return true;
188 }
189 
190 
192 {
193  LIB_PART* part = m_frame->GetCurPart();
194  bool ask_for_pin = true; // Test for another pin in same position in other units
195 
196  for( LIB_PIN* test = part->GetNextPin(); test; test = part->GetNextPin( test ) )
197  {
198  if( test == aPin || aPin->GetPosition() != test->GetPosition() || test->GetEditFlags() )
199  continue;
200 
201  // test for same body style
202  if( test->GetConvert() && test->GetConvert() != aPin->GetConvert() )
203  continue;
204 
205  if( ask_for_pin && m_frame->SynchronizePins() )
206  {
207  wxString msg;
208  msg.Printf( _( "This position is already occupied by another pin, in unit %d." ),
209  test->GetUnit() );
210 
211  KIDIALOG dlg( m_frame, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
212  dlg.SetOKLabel( _( "Place Pin Anyway" ) );
213  dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
214 
215  bool status = dlg.ShowModal() == wxID_OK;
216 
217  if( !status )
218  {
219  if( aPin->IsNew() )
220  delete aPin;
221 
222  return false;
223  }
224  else
225  {
226  ask_for_pin = false;
227  }
228  }
229  }
230 
231  if( aPin->IsNew() && !aPin->HasFlag( IS_PASTED ) )
232  {
234  g_LastPinType = aPin->GetType();
235  g_LastPinShape = aPin->GetShape();
236 
237  if( m_frame->SynchronizePins() )
238  CreateImagePins( aPin );
239 
240  part->AddDrawItem( aPin );
241  aPin->ClearFlags( IS_NEW );
242  }
243 
244  // Put linked pins in new position, and clear flags
245  for( LIB_PIN* pin = part->GetNextPin(); pin; pin = part->GetNextPin( pin ) )
246  {
247  if( ( pin->GetEditFlags() & IS_LINKED ) == 0 )
248  continue;
249 
250  pin->MoveTo( aPin->GetPosition() );
251  pin->ClearFlags();
252  }
253 
254  m_frame->RebuildView();
255  m_frame->OnModify();
256 
257  return true;
258 }
259 
260 
261 /*
262  * Create a new pin.
263  */
264 LIB_PIN* LIB_PIN_TOOL::CreatePin( const VECTOR2I& aPosition, LIB_PART* aPart )
265 {
266  aPart->ClearTempFlags();
267 
268  LIB_PIN* pin = new LIB_PIN( aPart );
269 
270  pin->SetFlags( IS_NEW );
271 
272  // Flag pins to consider
273  if( m_frame->SynchronizePins() )
274  pin->SetFlags( IS_LINKED );
275 
276  pin->MoveTo((wxPoint) aPosition );
277  pin->SetLength( GetLastPinLength() );
279  pin->SetType( g_LastPinType );
280  pin->SetShape( g_LastPinShape );
284  pin->SetUnit( g_LastPinCommonUnit ? 0 : m_frame->GetUnit() );
286 
287  if( !EditPinProperties( pin ) )
288  {
289  delete pin;
290  pin = nullptr;
291  }
292 
293  return pin;
294 }
295 
296 
298 {
299  int ii;
300  LIB_PIN* newPin;
301 
302  // if "synchronize pins editing" option is off, do not create any similar pin for other
303  // units and/or shapes: each unit is edited regardless other units or body
304  if( !m_frame->SynchronizePins() )
305  return;
306 
307  if( aPin->GetUnit() == 0 ) // Pin common to all units: no need to create similar pins.
308  return;
309 
310  // When units are interchangeable, all units are expected to have similar pins
311  // at the same position
312  // to facilitate pin editing, create pins for all other units for the current body style
313  // at the same position as aPin
314 
315  for( ii = 1; ii <= aPin->GetParent()->GetUnitCount(); ii++ )
316  {
317  if( ii == aPin->GetUnit() )
318  continue;
319 
320  newPin = (LIB_PIN*) aPin->Clone();
321 
322  // To avoid mistakes, gives this pin a new pin number because
323  // it does no have the save pin number as the master pin
324  // Because we do not know the actual number, give it a temporary number
325  wxString unknownNum;
326  unknownNum.Printf( "%s-U%c", aPin->GetNumber(), wxChar( 'A' + ii - 1 ) );
327  newPin->SetNumber( unknownNum );
328 
329  newPin->SetUnit( ii );
330  aPin->GetParent()->AddDrawItem( newPin );
331  newPin->ClearFlags( IS_NEW );
332  }
333 }
334 
335 
337 {
338  LIB_PART* part = m_frame->GetCurPart();
339  EE_SELECTION& selection = m_selectionTool->GetSelection();
340  LIB_PIN* sourcePin = dynamic_cast<LIB_PIN*>( selection.Front() );
341 
342  if( !sourcePin )
343  return 0;
344 
346 
347  for( LIB_PIN* pin = part->GetNextPin(); pin; pin = part->GetNextPin( pin ) )
348  {
349  if( pin == sourcePin )
350  continue;
351 
352  if( aEvent.IsAction( &EE_ACTIONS::pushPinLength ) )
353  {
354  if( !pin->GetConvert() || pin->GetConvert() == m_frame->GetConvert() )
355  pin->SetLength( sourcePin->GetLength() );
356  }
357  else if( aEvent.IsAction( &EE_ACTIONS::pushPinNameSize ) )
358  {
359  pin->SetNameTextSize( sourcePin->GetNameTextSize() );
360  }
361  else if( aEvent.IsAction( &EE_ACTIONS::pushPinNumSize ) )
362  {
363  pin->SetNumberTextSize( sourcePin->GetNumberTextSize() );
364  }
365  }
366 
367  m_frame->RebuildView();
368  m_frame->OnModify();
369 
370  return 0;
371 }
372 
373 
374 // Create a new pin based on the previous pin with an incremented pin number.
376 {
377  LIB_PIN* pin = (LIB_PIN*) aSourcePin->Clone();
378  wxPoint step;
379 
380  pin->ClearFlags();
381  pin->SetFlags( IS_NEW );
382 
383  LIBEDIT_SETTINGS* settings = Pgm().GetSettingsManager().GetAppSettings<LIBEDIT_SETTINGS>();
384 
385  switch( pin->GetOrientation() )
386  {
387  case PIN_UP: step.x = settings->m_Repeat.pin_step; break;
388  case PIN_DOWN: step.x = settings->m_Repeat.pin_step; break;
389  case PIN_LEFT: step.y = -settings->m_Repeat.pin_step; break;
390  case PIN_RIGHT: step.y = -settings->m_Repeat.pin_step; break;
391  }
392 
393  pin->Offset( step );
394 
395  wxString nextName = pin->GetName();
396  IncrementLabelMember( nextName, settings->m_Repeat.label_delta );
397  pin->SetName( nextName );
398 
399  wxString nextNumber = pin->GetNumber();
400  IncrementLabelMember( nextNumber, settings->m_Repeat.label_delta );
401  pin->SetNumber( nextNumber );
402 
403  if( m_frame->SynchronizePins() )
404  pin->SetFlags( IS_LINKED );
405 
406  if( PlacePin( pin ) )
407  return pin;
408 
409  return nullptr;
410 }
411 
412 
414 {
418 }
419 
void SetNumberTextSize(int aSize)
Definition: lib_pin.h:178
#define IS_LINKED
Used in calculation to mark linked items (temporary use)
Definition: base_struct.h:114
void SetModified()
Definition: base_struct.cpp:87
EDA_ITEM * Clone() const override
Function Clone creates a duplicate of this item with linked list members set to NULL.
Definition: lib_pin.cpp:834
void DoNotShowCheckbox(wxString file, int line)
Shows the 'do not show again' checkbox
Definition: confirm.cpp:53
void UpdateItem(EDA_ITEM *aItem, bool isAddOrDelete=false)
Mark an item for refresh.
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:104
bool Init() override
Function Init() Init() is called once upon a registration of the tool.
void SetOrientation(int aOrientation)
Definition: lib_pin.h:126
int GetConvert() const
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: confirm.h:44
This file is part of the common library.
int GetOrientation() const
Definition: lib_pin.h:125
static bool g_LastPinCommonConvert
LIB_PART * GetParent() const
Definition: lib_item.h:182
std::vector< LIB_PIN * > LIB_PINS
Helper for defining a list of pin object pointers.
Definition: lib_item.h:55
void SaveCopyInUndoList(EDA_ITEM *ItemToCopy, UNDO_REDO undoType=UNDO_REDO::LIBEDIT, bool aAppend=false)
Create a copy of the current component, and save it in the undo list.
void SetShape(GRAPHIC_PINSHAPE aShape)
Definition: lib_pin.h:129
GRAPHIC_PINSHAPE GetShape() const
Definition: lib_pin.h:128
CONDITIONAL_MENU & GetMenu()
Function GetMenu.
Definition: tool_menu.cpp:46
TOOL_MENU & GetToolMenu()
static int GetLastPinLength()
static int g_LastPinNameSize
void SetLength(int aLength)
Definition: lib_pin.h:132
static int g_LastPinNumSize
LIB_PART * GetCurPart()
Return the current part being edited or NULL if none selected.
Definition: lib_pin.h:50
static SELECTION_CONDITION Count(int aNumber)
Creates a functor that tests if the number of selected items is equal to the value given as parameter...
GRAPHIC_PINSHAPE
Definition: pin_type.h:53
static TOOL_ACTION pushPinNameSize
Definition: ee_actions.h:199
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Function Go()
void ClearTempFlags()
Clears the status flag all draw objects in this part.
bool IsAction(const TOOL_ACTION *aAction) const
Function IsAction() Tests if the event contains an action issued upon activation of the given TOOL_AC...
Definition: tool_event.cpp:67
bool IsNew() const
Definition: base_struct.h:199
bool Init() override
Function Init() Init() is called once upon a registration of the tool.
Definition: ee_tool_base.h:69
void AddDrawItem(LIB_ITEM *aItem)
Add a new draw aItem to the draw object list.
EE_SELECTION & GetSelection()
Function GetSelection()
#define IS_NEW
New item, just created.
Definition: base_struct.h:117
void SetNumber(const wxString &aNumber)
Definition: lib_pin.h:166
void GetPins(LIB_PINS &aList, int aUnit=0, int aConvert=0)
Return a list of pin object pointers from the draw item list.
int GetUnit() const
Definition: lib_item.h:295
static int g_LastPinOrient
void SetType(ELECTRICAL_PINTYPE aType)
Definition: lib_pin.h:135
int GetUnit() const
void SetFlags(STATUS_FLAGS aMask)
Definition: base_struct.h:232
static int g_LastPinLength
int GetUnitCount() const override
For items with units, return the number of units.
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
void saveCopyInUndoList(EDA_ITEM *aItem, UNDO_REDO aType, bool aAppend=false)
Similar to m_frame->SaveCopyInUndoList(), but handles items that are owned by their parents.
Definition: ee_tool_base.h:117
STATUS_FLAGS GetEditFlags() const
Definition: base_struct.h:237
const wxString & GetName() const
Definition: lib_pin.h:156
TOOL_EVENT.
Definition: tool_event.h:171
bool EditPinProperties(LIB_PIN *aPin)
Define a library symbol object.
void SetVisible(bool aVisible)
Definition: lib_pin.h:148
virtual PICKED_ITEMS_LIST * PopCommandFromUndoList()
PopCommandFromUndoList return the last command to undo and remove it from list nothing is deleted.
static TOOL_ACTION pushPinLength
Definition: ee_actions.h:198
EE_SELECTION_TOOL * m_selectionTool
Definition: ee_tool_base.h:160
void IncrementLabelMember(wxString &name, int aIncrement)
Definition: sch_text.cpp:51
bool IsVisible() const
Definition: lib_pin.h:147
int GetNameTextSize() const
Definition: lib_pin.h:174
Implementing DIALOG_LIB_EDIT_PIN_BASE.
int GetConvert() const
Definition: lib_item.h:298
LIB_PIN * RepeatPin(const LIB_PIN *aSourcePin)
static int GetLastPinNameSize()
void CreateImagePins(LIB_PIN *aPin)
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:978
void AddSeparator(int aOrder=ANY_ORDER)
Adds a separator to the menu.
void SetConvert(int aConvert)
Definition: lib_item.h:297
wxPoint GetPosition() const override
Definition: lib_pin.h:254
static GRAPHIC_PINSHAPE g_LastPinShape
LIB_PIN * GetNextPin(LIB_PIN *aItem=NULL)
Return the next pin object from the draw list.
const wxString & GetNumber() const
Definition: lib_pin.h:165
ELECTRICAL_PINTYPE GetType() const
Definition: lib_pin.h:134
void SetUnit(int aUnit)
Definition: lib_item.h:294
void MoveTo(const wxPoint &aPosition) override
Move a draw object to aPosition.
Definition: lib_pin.cpp:898
static int GetLastPinNumSize()
int GetNumberTextSize() const
Definition: lib_pin.h:177
The symbol library editor main window.
see class PGM_BASE
void SetName(const wxString &aName)
Definition: lib_pin.h:157
const char * name
Definition: DXF_plotter.cpp:60
void SetNameTextSize(int aSize)
Definition: lib_pin.h:175
ELECTRICAL_PINTYPE
The component library pin object electrical types used in ERC tests.
Definition: pin_type.h:34
int GetLength() const
Definition: lib_pin.h:131
#define _(s)
Definition: 3d_actions.cpp:33
usual pin input: must be connected
static SELECTION_CONDITION OnlyType(KICAD_T aType)
Creates a functor that tests if the selected items are only of given type.
int PushPinProperties(const TOOL_EVENT &aEvent)
void OnModify() override
Must be called after a schematic change in order to set the "modify" flag of the current symbol.
std::vector< MSG_PANEL_ITEM > MSG_PANEL_ITEMS
Definition: msgpanel.h:102
void setTransitions() override
Sets up handlers for various events.
int ShowModal() override
Definition: confirm.cpp:95
void ClearFlags(STATUS_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: base_struct.h:233
static TOOL_ACTION pushPinNumSize
Definition: ee_actions.h:200
EE_TOOL_BASE.
Definition: ee_tool_base.h:50
bool HasFlag(STATUS_FLAGS aFlag)
Definition: base_struct.h:235
LIB_PIN * CreatePin(const VECTOR2I &aPosition, LIB_PART *aPart)
void Offset(const wxPoint &aOffset) override
Set the drawing object by aOffset from the current position.
Definition: lib_pin.cpp:892
void AddItem(const TOOL_ACTION &aAction, const SELECTION_CONDITION &aCondition, int aOrder=ANY_ORDER)
Adds a menu entry to run a TOOL_ACTION on selected items.
bool PlacePin(LIB_PIN *aPin)
static ELECTRICAL_PINTYPE g_LastPinType
static bool g_LastPinCommonUnit
#define IS_PASTED
Modifier on IS_NEW which indicates it came from clipboard.
Definition: base_struct.h:130
EDA_ITEM * Front() const
Definition: selection.h:184
static bool g_LastPinVisible
void RemoveDrawItem(LIB_ITEM *aItem)
Remove draw aItem from list.