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 <class_drawpanel.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 = (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 = (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 = (SCH_ITEM*) aItemsList.GetPickedItem( ii );
102  item->MirrorX( aMirrorPoint.y ); // Place it in its new position.
103  item->ClearFlags();
104  }
105 }
106 
107 
108 void MoveItemsInList( PICKED_ITEMS_LIST& aItemsList, const wxPoint& aMoveVector )
109 {
110  for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ )
111  {
112  SCH_ITEM* item = (SCH_ITEM*) aItemsList.GetPickedItem( ii );
113  item->Move( aMoveVector );
114  }
115 }
116 
117 
119 {
120  std::vector< wxPoint > pts;
121  std::vector< wxPoint > connections;
122 
123  GetSchematicConnections( connections );
124  for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ )
125  {
126  SCH_ITEM* item = (SCH_ITEM*) aItemsList.GetPickedItem( ii );
127  std::vector< wxPoint > new_pts;
128 
129  if( !item->IsConnectable() )
130  continue;
131 
132  item->GetConnectionPoints( new_pts );
133  pts.insert( pts.end(), new_pts.begin(), new_pts.end() );
134 
135  // If the item is a line, we also add any connection points from the rest of the schematic
136  // that terminate on the line after it is moved.
137  if( item->Type() == SCH_LINE_T )
138  {
139  SCH_LINE* line = (SCH_LINE*) item;
140  for( auto i : connections )
141  if( IsPointOnSegment( line->GetStartPoint(), line->GetEndPoint(), i ) )
142  pts.push_back( i );
143  }
144  else
145  {
146  // Clean up any wires that short non-wire connections in the list
147  for( auto point = new_pts.begin(); point != new_pts.end(); point++ )
148  {
149  for( auto second_point = point + 1; second_point != new_pts.end(); second_point++ )
150  {
151  aAppend |= TrimWire( *point, *second_point, aAppend );
152  }
153  }
154  }
155  }
156 
157  // We always have some overlapping connection points. Drop duplicates here
158  std::sort( pts.begin(), pts.end(),
159  []( const wxPoint& a, const wxPoint& b ) -> bool
160  { return a.x < b.x || (a.x == b.x && a.y < b.y); } );
161  pts.erase( unique( pts.begin(), pts.end() ), pts.end() );
162 
163  for( auto point : pts )
164  {
165  if( GetScreen()->IsJunctionNeeded( point, true ) )
166  {
167  AddJunction( point, aAppend );
168  aAppend = true;
169  }
170  }
171 }
172 
173 
174 void SCH_EDIT_FRAME::DeleteItemsInList( PICKED_ITEMS_LIST& aItemsList, bool aAppend )
175 {
176  for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ )
177  {
178  SCH_ITEM* item = (SCH_ITEM*) aItemsList.GetPickedItem( ii );
179 
180  if( item->GetFlags() & STRUCT_DELETED )
181  continue;
182 
183  DeleteItem( item, aAppend );
184  aAppend = true;
185  }
186 
188 }
189 
190 
191 void SCH_EDIT_FRAME::DeleteItem( SCH_ITEM* aItem, bool aAppend )
192 {
193  wxCHECK_RET( aItem != NULL, wxT( "Cannot delete invalid item." ) );
194  wxCHECK_RET( !( aItem->GetFlags() & STRUCT_DELETED ),
195  wxT( "Cannot delete item that is already deleted." ) );
196 
197  // Here, aItem is not null.
198  SCH_SCREEN* screen = GetScreen();
199 
200  if( aItem->Type() == SCH_SHEET_PIN_T )
201  {
202  // This item is attached to a node, and is not accessible by the global list directly.
203  SCH_SHEET* sheet = (SCH_SHEET*) aItem->GetParent();
204  wxCHECK_RET( (sheet != NULL) && (sheet->Type() == SCH_SHEET_T),
205  wxT( "Sheet label has invalid parent item." ) );
206  SaveCopyInUndoList( (SCH_ITEM*) sheet, UR_CHANGED, aAppend );
207  sheet->RemovePin( (SCH_SHEET_PIN*) aItem );
209  }
210  else if( aItem->Type() == SCH_JUNCTION_T )
211  {
212  DeleteJunction( aItem, aAppend );
213  }
214  else
215  {
216  aItem->SetFlags( STRUCT_DELETED );
217  SaveCopyInUndoList( aItem, UR_DELETED, aAppend );
218  screen->Remove( aItem );
219 
220  std::vector< wxPoint > pts;
221  aItem->GetConnectionPoints( pts );
222  for( auto point : pts )
223  {
224  SCH_ITEM* junction = screen->GetItem( point, 0, SCH_JUNCTION_T );
225  if( junction && !screen->IsJunctionNeeded( point ) )
226  DeleteJunction( junction, true );
227  }
228 
230  }
231 }
232 
233 
235  const wxPoint& aMoveVector )
236 {
237  SCH_ITEM* newitem;
238 
239  if( aItemsList.GetCount() == 0 )
240  return;
241 
242  for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ )
243  {
244  newitem = DuplicateStruct( (SCH_ITEM*) aItemsList.GetPickedItem( ii ) );
245  aItemsList.SetPickedItem( newitem, ii );
246  aItemsList.SetPickedItemStatus( UR_NEW, ii );
247  {
248  switch( newitem->Type() )
249  {
250  case SCH_JUNCTION_T:
251  case SCH_LINE_T:
252  case SCH_BUS_BUS_ENTRY_T:
254  case SCH_TEXT_T:
255  case SCH_LABEL_T:
256  case SCH_GLOBAL_LABEL_T:
258  case SCH_SHEET_PIN_T:
259  case SCH_MARKER_T:
260  case SCH_NO_CONNECT_T:
261  default:
262  break;
263 
264  case SCH_SHEET_T:
265  {
266  SCH_SHEET* sheet = (SCH_SHEET*) newitem;
267  // Duplicate sheet names and sheet time stamps are not valid. Use a time stamp
268  // based sheet name and update the time stamp for each sheet in the block.
269  timestamp_t timeStamp = GetNewTimeStamp();
270 
271  sheet->SetName( wxString::Format( wxT( "sheet%8.8lX" ), (unsigned long)timeStamp ) );
272  sheet->SetTimeStamp( timeStamp );
273  break;
274  }
275 
276  case SCH_COMPONENT_T:
277  ( (SCH_COMPONENT*) newitem )->SetTimeStamp( GetNewTimeStamp() );
278  ( (SCH_COMPONENT*) newitem )->ClearAnnotation( NULL );
279  break;
280  }
281 
282  SetSchItemParent( newitem, screen );
283  screen->Append( newitem );
284  }
285  }
286 
287  MoveItemsInList( aItemsList, aMoveVector );
288 }
289 
290 
291 SCH_ITEM* DuplicateStruct( SCH_ITEM* aDrawStruct, bool aClone )
292 {
293  wxCHECK_MSG( aDrawStruct != NULL, NULL,
294  wxT( "Cannot duplicate NULL schematic item! Bad programmer." ) );
295 
296  SCH_ITEM* NewDrawStruct = (SCH_ITEM*) aDrawStruct->Clone();
297 
298  if( aClone )
299  NewDrawStruct->SetTimeStamp( aDrawStruct->GetTimeStamp() );
300 
301  return NewDrawStruct;
302 }
Definition of the SCH_SHEET class for Eeschema.
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:209
long timestamp_t
timestamp_t is our type to represent unique IDs for all kinds of elements; historically simply the ti...
Definition: base_struct.h:155
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:266
virtual const EDA_RECT GetBoundingBox() const
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes...
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:346
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 MoveItemsInList(PICKED_ITEMS_LIST &aItemsList, const wxPoint &aMoveVector)
Function MoveItemsInList Move a list of items to a given move vector.
EDA_ITEM * GetParent() const
Definition: base_struct.h:219
void RefreshDrawingRect(const EDA_RECT &aRect, bool aEraseBackground=true)
Function RefreshDrawingRect redraws the contents of aRect in drawing units.
Definition: draw_panel.cpp:318
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
Function GetScreen returns 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:160
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:264
EDA_RECT const GetBoundingBox() const override
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes...
Definition: sch_sheet.cpp:499
void SetName(const wxString &aName)
Definition: sch_sheet.h:269
void SetParent(EDA_ITEM *aParent)
Definition: base_struct.h:224
bool SetPickedItem(EDA_ITEM *aItem, unsigned aIdx)
Function SetPickedItem.
void DuplicateItemsInList(SCH_SCREEN *screen, PICKED_ITEMS_LIST &aItemsList, const wxPoint &aMoveVector)
Routine to copy a new entity of an object for each object in list and reposition it.
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:118
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.
virtual void GetConnectionPoints(std::vector< wxPoint > &aPoints) const
Function GetConnectionPoints add all the connection points for this item to aPoints.
EDA_DRAW_PANEL * m_canvas
The area to draw on.
Definition: draw_frame.h:106
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 Append(SCH_ITEM *aItem)
Definition: sch_screen.h:140
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:265
void ClearDrawingState()
Clear the state flags of all the items in the screen.
Definition: sch_screen.cpp:582
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.
timestamp_t GetTimeStamp() const
Definition: base_struct.h:215
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:214
virtual void Move(const wxPoint &aMoveVector)=0
Function Move moves the item by aMoveVector to a new position.