KiCad PCB EDA Suite
operations_on_items_lists.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) 2009 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2014 KiCad Developers, see CHANGELOG.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 
31 #include <fctsys.h>
32 #include <pgm_base.h>
33 #include <sch_draw_panel.h>
34 #include <sch_edit_frame.h>
35 
36 #include <general.h>
37 #include <list_operations.h>
38 #include <sch_bus_entry.h>
39 #include <sch_marker.h>
40 #include <sch_line.h>
41 #include <sch_no_connect.h>
42 #include <sch_sheet.h>
43 #include <sch_component.h>
44 #include <sch_junction.h>
45 
46 
47 void SetSchItemParent( SCH_ITEM* Struct, SCH_SCREEN* Screen )
48 {
49  switch( Struct->Type() )
50  {
51  case SCH_JUNCTION_T:
52  case SCH_TEXT_T:
53  case SCH_LABEL_T:
54  case SCH_GLOBAL_LABEL_T:
56  case SCH_COMPONENT_T:
57  case SCH_LINE_T:
60  case SCH_SHEET_T:
61  case SCH_MARKER_T:
62  case SCH_NO_CONNECT_T:
63  Struct->SetParent( Screen );
64  break;
65 
66  case SCH_SHEET_PIN_T:
67  break;
68 
69  default:
70  break;
71  }
72 }
73 
74 
75 void RotateListOfItems( PICKED_ITEMS_LIST& aItemsList, const wxPoint& rotationPoint )
76 {
77  for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ )
78  {
79  SCH_ITEM* item = static_cast<SCH_ITEM*>( aItemsList.GetPickedItem( ii ) );
80  item->Rotate( rotationPoint ); // Place it in its new position.
81  item->ClearFlags();
82  }
83 }
84 
85 
86 void MirrorY( PICKED_ITEMS_LIST& aItemsList, const wxPoint& aMirrorPoint )
87 {
88  for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ )
89  {
90  SCH_ITEM* item = static_cast<SCH_ITEM*>( aItemsList.GetPickedItem( ii ) );
91  item->MirrorY( aMirrorPoint.x ); // Place it in its new position.
92  item->ClearFlags();
93  }
94 }
95 
96 
97 void MirrorX( PICKED_ITEMS_LIST& aItemsList, const wxPoint& aMirrorPoint )
98 {
99  for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ )
100  {
101  SCH_ITEM* item = static_cast<SCH_ITEM*>( aItemsList.GetPickedItem( ii ) );
102  item->MirrorX( aMirrorPoint.y ); // Place it in its new position.
103  item->ClearFlags();
104  }
105 }
106 
107 
109 {
110  std::vector< wxPoint > pts;
111  std::vector< wxPoint > connections;
112 
113  GetSchematicConnections( connections );
114  for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ )
115  {
116  SCH_ITEM* item = static_cast<SCH_ITEM*>( aItemsList.GetPickedItem( ii ) );
117  std::vector< wxPoint > new_pts;
118 
119  if( !item->IsConnectable() )
120  continue;
121 
122  item->GetConnectionPoints( new_pts );
123  pts.insert( pts.end(), new_pts.begin(), new_pts.end() );
124 
125  // If the item is a line, we also add any connection points from the rest of the schematic
126  // that terminate on the line after it is moved.
127  if( item->Type() == SCH_LINE_T )
128  {
129  SCH_LINE* line = (SCH_LINE*) item;
130  for( auto i : connections )
131  if( IsPointOnSegment( line->GetStartPoint(), line->GetEndPoint(), i ) )
132  pts.push_back( i );
133  }
134  else
135  {
136  // Clean up any wires that short non-wire connections in the list
137  for( auto point = new_pts.begin(); point != new_pts.end(); point++ )
138  {
139  for( auto second_point = point + 1; second_point != new_pts.end(); second_point++ )
140  {
141  aAppend |= TrimWire( *point, *second_point, aAppend );
142  }
143  }
144  }
145  }
146 
147  // We always have some overlapping connection points. Drop duplicates here
148  std::sort( pts.begin(), pts.end(),
149  []( const wxPoint& a, const wxPoint& b ) -> bool
150  { return a.x < b.x || (a.x == b.x && a.y < b.y); } );
151  pts.erase( unique( pts.begin(), pts.end() ), pts.end() );
152 
153  for( auto point : pts )
154  {
155  if( GetScreen()->IsJunctionNeeded( point, true ) )
156  {
157  AddJunction( point, aAppend );
158  aAppend = true;
159  }
160  }
161 }
162 
163 
164 void SCH_EDIT_FRAME::DeleteItemsInList( PICKED_ITEMS_LIST& aItemsList, bool aAppend )
165 {
166  for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ )
167  {
168  SCH_ITEM* item = static_cast<SCH_ITEM*>( aItemsList.GetPickedItem( ii ) );
169 
170  if( item->GetFlags() & STRUCT_DELETED )
171  continue;
172 
173  DeleteItem( item, aAppend );
174  aAppend = true;
175  }
176 
178 }
179 
180 
181 void SCH_EDIT_FRAME::DeleteItem( SCH_ITEM* aItem, bool aAppend )
182 {
183  wxCHECK_RET( aItem != NULL, wxT( "Cannot delete invalid item." ) );
184  wxCHECK_RET( !( aItem->GetFlags() & STRUCT_DELETED ),
185  wxT( "Cannot delete item that is already deleted." ) );
186 
187  // Here, aItem is not null.
188  SCH_SCREEN* screen = GetScreen();
189 
190  if( aItem->Type() == SCH_SHEET_PIN_T )
191  {
192  // This item is attached to its parent hierarchical sheet,
193  // and is not accessible by the global list directly and cannot be removed from this list.
194  SCH_SHEET* sheet = (SCH_SHEET*) aItem->GetParent();
195  wxCHECK_RET( (sheet != NULL) && (sheet->Type() == SCH_SHEET_T),
196  wxT( "Sheet label has invalid parent item." ) );
197  SaveCopyInUndoList( (SCH_ITEM*) sheet, UR_CHANGED, aAppend );
198  sheet->RemovePin( (SCH_SHEET_PIN*) aItem );
199  RefreshItem( sheet );
200  }
201  else if( aItem->Type() == SCH_JUNCTION_T )
202  {
203  DeleteJunction( aItem, aAppend );
204  }
205  else
206  {
207  aItem->SetFlags( STRUCT_DELETED );
208  SaveCopyInUndoList( aItem, UR_DELETED, aAppend );
209  RemoveFromScreen( aItem );
210 
211  std::vector< wxPoint > pts;
212  aItem->GetConnectionPoints( pts );
213  for( auto point : pts )
214  {
215  SCH_ITEM* junction = screen->GetItem( point, 0, SCH_JUNCTION_T );
216  if( junction && !screen->IsJunctionNeeded( point ) )
217  DeleteJunction( junction, true );
218  }
219  }
220 }
221 
222 
224  const wxPoint& aMoveVector )
225 {
226  SCH_ITEM* olditem;
227  SCH_ITEM* newitem;
228 
229  if( aItemsList.GetCount() == 0 )
230  return;
231 
232  // Keep track of existing sheet paths. Duplicate block can modify this list
233  bool hasSheetCopied = false;
234  SCH_SHEET_LIST initial_sheetpathList( g_RootSheet );
235 
236 
237  for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ )
238  {
239  olditem = static_cast<SCH_ITEM*>( aItemsList.GetPickedItem( ii ) );
240  newitem = DuplicateStruct( olditem );
241  newitem->Move( aMoveVector );
242 
243  aItemsList.SetPickedItem( newitem, ii );
244  aItemsList.SetPickedItemStatus( UR_NEW, ii );
245 
246  switch( newitem->Type() )
247  {
248  case SCH_JUNCTION_T:
249  case SCH_LINE_T:
250  case SCH_BUS_BUS_ENTRY_T:
252  case SCH_TEXT_T:
253  case SCH_LABEL_T:
254  case SCH_GLOBAL_LABEL_T:
256  case SCH_SHEET_PIN_T:
257  case SCH_MARKER_T:
258  case SCH_NO_CONNECT_T:
259  default:
260  break;
261 
262  case SCH_SHEET_T:
263  {
264  SCH_SHEET* sheet = (SCH_SHEET*) newitem;
265  // Duplicate sheet names and sheet time stamps are not valid. Use a time stamp
266  // based sheet name and update the time stamp for each sheet in the block.
267  timestamp_t timeStamp = GetNewTimeStamp();
268 
269  sheet->SetName( wxString::Format( wxT( "sheet%8.8lX" ), (unsigned long)timeStamp ) );
270  sheet->SetTimeStamp( timeStamp );
271  hasSheetCopied = true;
272  break;
273  }
274 
275  case SCH_COMPONENT_T:
276  ( (SCH_COMPONENT*) newitem )->SetTimeStamp( GetNewTimeStamp() );
277  ( (SCH_COMPONENT*) newitem )->ClearAnnotation( NULL );
278  break;
279  }
280 
281  SetSchItemParent( newitem, screen );
282  AddToScreen( newitem );
283  }
284 
285  if( hasSheetCopied )
286  {
287  // We clear annotation of new sheet paths.
288  // Annotation of new components added in current sheet is already cleared.
289  SCH_SCREENS screensList( g_RootSheet );
290  screensList.ClearAnnotationOfNewSheetPaths( initial_sheetpathList );
291  }
292 }
293 
294 
295 SCH_ITEM* DuplicateStruct( SCH_ITEM* aDrawStruct, bool aClone )
296 {
297  wxCHECK_MSG( aDrawStruct != NULL, NULL,
298  wxT( "Cannot duplicate NULL schematic item! Bad programmer." ) );
299 
300  SCH_ITEM* NewDrawStruct = (SCH_ITEM*) aDrawStruct->Clone();
301 
302  if( aClone )
303  NewDrawStruct->SetTimeStamp( aDrawStruct->GetTimeStamp() );
304 
305  return NewDrawStruct;
306 }
Definition of the SCH_SHEET class for Eeschema.
Class SCH_SHEET_LIST.
SCH_JUNCTION * AddJunction(const wxPoint &aPosition, bool aPutInUndoList=false)
Add a new junction at aPosition.
KICAD_T Type() const
Function Type()
Definition: base_struct.h:201
bool IsPointOnSegment(const wxPoint &aSegStart, const wxPoint &aSegEnd, const wxPoint &aTestPoint)
Function IsPointOnSegment.
Definition: trigo.cpp:39
STATUS_FLAGS GetFlags() const
Definition: base_struct.h:258
long timestamp_t
timestamp_t is our type to represent unique IDs for all kinds of elements; historically simply the ti...
Definition: common.h:52
void GetSchematicConnections(std::vector< wxPoint > &aConnections)
Collects a unique list of all possible connection points in the schematic.
bool IsJunctionNeeded(const wxPoint &aPosition, bool aNew=false)
Test if a junction is required for the items at aPosition on the screen.
Definition: sch_screen.cpp:325
void DuplicateItemsInList(SCH_SCREEN *screen, PICKED_ITEMS_LIST &aItemsList, const wxPoint &aMoveVector)
virtual EDA_ITEM * Clone() const
Function Clone creates a duplicate of this item with linked list members set to NULL.
void MirrorX(PICKED_ITEMS_LIST &aItemsList, const wxPoint &aMirrorPoint)
void RemoveFromScreen(SCH_ITEM *aItem)
Remove an item from the screen (and view)
EDA_ITEM * GetParent() const
Definition: base_struct.h:211
wxPoint GetEndPoint() const
Definition: sch_line.h:80
void SetSchItemParent(SCH_ITEM *Struct, SCH_SCREEN *Screen)
wxPoint GetStartPoint() const
Definition: sch_line.h:76
virtual void Rotate(wxPoint aPosition)=0
Function Rotate rotates the item around aPosition 90 degrees in the clockwise direction.
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
void RotateListOfItems(PICKED_ITEMS_LIST &aItemsList, const wxPoint &rotationPoint)
timestamp_t GetNewTimeStamp()
Definition: common.cpp:212
void RemovePin(SCH_SHEET_PIN *aSheetPin)
Remove aSheetPin from the sheet.
Definition: sch_sheet.cpp:187
void SetFlags(STATUS_FLAGS aMask)
Definition: base_struct.h:256
SCH_SHEET * g_RootSheet
Definition: eeschema.cpp:56
void SetName(const wxString &aName)
Definition: sch_sheet.h:269
void SetParent(EDA_ITEM *aParent)
Definition: base_struct.h:216
bool SetPickedItem(EDA_ITEM *aItem, unsigned aIdx)
Function SetPickedItem.
virtual bool IsConnectable() const
Function IsConnectable returns true if the schematic item can connect to another schematic item...
void SaveCopyInUndoList(SCH_ITEM *aItemToCopy, UNDO_REDO_T aTypeCommand, bool aAppend=false, const wxPoint &aTransformPoint=wxPoint(0, 0))
Create a copy of the current schematic item, and put it in the undo list.
#define STRUCT_DELETED
flag indication structures to be erased
Definition: base_struct.h:123
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet.h:61
virtual void MirrorX(int aXaxis_position)=0
Function MirrorX mirrors item relative to the X axis about aXaxis_position.
Class PICKED_ITEMS_LIST is a holder to handle information on schematic or board items.
virtual void MirrorY(int aYaxis_position)=0
Function MirrorY mirrors item relative to the Y axis about aYaxis_position.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:209
unsigned GetCount() const
Function GetCount.
void AddToScreen(SCH_ITEM *aItem)
Add an item to the screen (and view)
virtual void GetConnectionPoints(std::vector< wxPoint > &aPoints) const
Function GetConnectionPoints add all the connection points for this item to aPoints.
Definition the SCH_COMPONENT class for Eeschema.
see class PGM_BASE
void CheckListConnections(PICKED_ITEMS_LIST &aItemsList, bool aAppend=false)
Adds junctions if needed to each item in the list after they have been moved.
bool SetPickedItemStatus(UNDO_REDO_T aStatus, unsigned aIdx)
Function SetPickedItemStatus sets the type of undo/redo operation for a given picked item...
Segment description base class to describe items which have 2 end points (track, wire, draw line ...)
Definition: sch_line.h:41
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
EDA_ITEM * GetPickedItem(unsigned int aIdx) const
Function GetPickedItem.
void RefreshItem(SCH_ITEM *aItem, bool isAddOrDelete=false)
Mark an item for refresh.
void DeleteJunction(SCH_ITEM *aItem, bool aAppend=false)
Removes a given junction and heals any wire segments under the junction.
size_t i
Definition: json11.cpp:597
void DeleteItemsInList(PICKED_ITEMS_LIST &aItemsList, bool aAppend=false)
Removes all items (and unused junctions that connect to them) and saves each in the undo list...
Class SCH_COMPONENT describes a real schematic component.
Definition: sch_component.h:69
bool TrimWire(const wxPoint &aStart, const wxPoint &aEnd, bool aAppend=true)
If any single wire passes through both points, remove the portion between the two points...
void ClearFlags(STATUS_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: base_struct.h:257
void ClearDrawingState()
Clear the state flags of all the items in the screen.
Definition: sch_screen.cpp:561
void ClearAnnotationOfNewSheetPaths(SCH_SHEET_LIST &aInitialSheetPathList)
Clear the annotation for the components inside new sheetpaths when a complex hierarchy is modified an...
Class SCH_ITEM is a base class for any item which can be embedded within the SCHEMATIC container clas...
void MirrorY(PICKED_ITEMS_LIST &aItemsList, const wxPoint &aMirrorPoint)
void DeleteItem(SCH_ITEM *aItem, bool aAppend=false)
Remove aItem from the current screen and saves it in the undo list.
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:523
timestamp_t GetTimeStamp() const
Definition: base_struct.h:207
SCH_ITEM * DuplicateStruct(SCH_ITEM *aDrawStruct, bool aClone)
Routine to create a new copy of given struct.
void SetTimeStamp(timestamp_t aNewTimeStamp)
Definition: base_struct.h:206
virtual void Move(const wxPoint &aMoveVector)=0
Function Move moves the item by aMoveVector to a new position.