KiCad PCB EDA Suite
editedge.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) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
5  * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
6  * Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
31 #include <fctsys.h>
32 #include <class_drawpanel.h>
33 #include <confirm.h>
34 #include <wxPcbStruct.h>
35 #include <gr_basic.h>
36 
37 #include <pcbnew.h>
38 #include <protos.h>
39 #include <macros.h>
40 
41 #include <class_board.h>
42 #include <class_drawsegment.h>
43 
44 
45 static void Abort_EditEdge( EDA_DRAW_PANEL* aPanel, wxDC* DC );
46 static void DrawSegment( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition, bool aErase );
47 static void Move_Segment( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition,
48  bool aErase );
49 
50 
51 static wxPoint s_InitialPosition; // Initial cursor position.
52 static wxPoint s_LastPosition; // Current cursor position.
53 
54 
55 // Start move of a graphic element type DRAWSEGMENT
57 {
58  if( drawitem == NULL )
59  return;
60 
61  drawitem->Draw( m_canvas, DC, GR_XOR );
62  drawitem->SetFlags( IS_MOVED );
63  s_InitialPosition = s_LastPosition = GetCrossHairPosition();
64  SetMsgPanel( drawitem );
66  SetCurItem( drawitem );
67  m_canvas->CallMouseCapture( DC, wxDefaultPosition, false );
68 }
69 
70 
71 /*
72  * Place graphic element of type DRAWSEGMENT.
73  */
74 void PCB_EDIT_FRAME::Place_DrawItem( DRAWSEGMENT* drawitem, wxDC* DC )
75 {
76  if( drawitem == NULL )
77  return;
78 
79  drawitem->ClearFlags();
80  SaveCopyInUndoList(drawitem, UR_MOVED, s_LastPosition - s_InitialPosition);
81  drawitem->Draw( m_canvas, DC, GR_OR );
82  m_canvas->SetMouseCapture( NULL, NULL );
83  SetCurItem( NULL );
84  OnModify();
85 }
86 
87 /*
88  * Redraw segment during cursor movement.
89  */
90 static void Move_Segment( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition,
91  bool aErase )
92 {
93  DRAWSEGMENT* segment = (DRAWSEGMENT*) aPanel->GetScreen()->GetCurItem();
94 
95  if( segment == NULL )
96  return;
97 
98  if( aErase )
99  segment->Draw( aPanel, aDC, GR_XOR );
100 
101  wxPoint delta;
102  delta = aPanel->GetParent()->GetCrossHairPosition() - s_LastPosition;
103 
104  segment->SetStart( segment->GetStart() + delta );
105  segment->SetEnd( segment->GetEnd() + delta );
106 
107  s_LastPosition = aPanel->GetParent()->GetCrossHairPosition();
108 
109  segment->Draw( aPanel, aDC, GR_XOR );
110 }
111 
112 
114 {
115  EDA_ITEM* PtStruct;
117  bool tmp = displ_opts->m_DisplayDrawItemsFill;
118 
119  if( Segment == NULL )
120  return;
121 
122  if( Segment->IsNew() ) // Trace in progress.
123  {
124  // Delete current segment.
125  displ_opts->m_DisplayDrawItemsFill = SKETCH;
126  Segment->Draw( m_canvas, DC, GR_XOR );
127  PtStruct = Segment->Back();
128  Segment ->DeleteStructure();
129 
130  if( PtStruct && (PtStruct->Type() == PCB_LINE_T ) )
131  Segment = (DRAWSEGMENT*) PtStruct;
132 
133  displ_opts->m_DisplayDrawItemsFill = tmp;
134  SetCurItem( NULL );
135  }
136  else if( Segment->GetFlags() == 0 )
137  {
138  Segment->Draw( m_canvas, DC, GR_XOR );
139  Segment->ClearFlags();
140  SaveCopyInUndoList(Segment, UR_DELETED);
141  Segment->UnLink();
142  SetCurItem( NULL );
143  OnModify();
144  }
145 }
146 
147 
149 {
150  if( IsCopperLayer( aLayer ) )
151  {
152  DisplayError( this, _( "Copper layer global delete not allowed!" ) );
153  return;
154  }
155 
156  wxString msg;
157  msg.Printf( _( "Delete everything on layer %s?" ),
158  GetChars( GetBoard()->GetLayerName( aLayer ) ) );
159 
160  if( !IsOK( this, msg ) )
161  return;
162 
163  // Step 1: build the list of items to remove.
164  // because we are using iterators, we cannot modify the drawing list during iterate
165  // so we are using a 2 steps calculation:
166  // First, collect items.
167  // Second, remove items.
168  std::vector<BOARD_ITEM*> list;
169 
170  for( auto item : GetBoard()->Drawings() )
171  {
172  switch( item->Type() )
173  {
174  case PCB_LINE_T:
175  case PCB_TEXT_T:
176  case PCB_DIMENSION_T:
177  case PCB_TARGET_T:
178  if( item->GetLayer() == aLayer )
179  list.push_back( item );
180 
181  break;
182 
183  default:
184  {
185  msg.Printf( wxT("Delete_Drawings_All_Layer() error: unknown type %d"),
186  item->Type() );
187  wxMessageBox( msg );
188  break;
189  }
190  }
191  }
192 
193  if( list.size() == 0 ) // No item found
194  return;
195 
196  // Step 2: remove items from main list, and move them to the undo list
197  PICKED_ITEMS_LIST pickList;
198  ITEM_PICKER picker( NULL, UR_DELETED );
199 
200  for( auto item : list )
201  {
202  item->UnLink();
203  picker.SetItem( item );
204  pickList.PushItem( picker );
205  }
206 
207  OnModify();
208  SaveCopyInUndoList(pickList, UR_DELETED);
209 }
210 
211 
212 static void Abort_EditEdge( EDA_DRAW_PANEL* aPanel, wxDC* DC )
213 {
214  DRAWSEGMENT* Segment = (DRAWSEGMENT*) aPanel->GetScreen()->GetCurItem();
215 
216  if( Segment == NULL )
217  {
218  aPanel->SetMouseCapture( NULL, NULL );
219  return;
220  }
221 
222  if( Segment->IsNew() )
223  {
224  aPanel->CallMouseCapture( DC, wxDefaultPosition, false );
225  Segment ->DeleteStructure();
226  Segment = NULL;
227  }
228  else
229  {
230  wxPoint pos = aPanel->GetParent()->GetCrossHairPosition();
231  aPanel->GetParent()->SetCrossHairPosition( s_InitialPosition );
232  aPanel->CallMouseCapture( DC, wxDefaultPosition, true );
233  aPanel->GetParent()->SetCrossHairPosition( pos );
234  Segment->ClearFlags();
235  Segment->Draw( aPanel, DC, GR_OR );
236  }
237 
238 #ifdef USE_WX_OVERLAY
239  aPanel->Refresh();
240 #endif
241 
242  aPanel->SetMouseCapture( NULL, NULL );
243  ( (PCB_EDIT_FRAME*) aPanel->GetParent() )->SetCurItem( NULL );
244 }
245 
246 
247 /* Initialize the drawing of a segment of type other than trace.
248  */
250 {
251  int s_large;
252  DRAWSEGMENT* DrawItem;
253 
255 
256  if( GetActiveLayer() == Edge_Cuts )
257  {
259  }
260 
261  if( Segment == NULL ) // Create new trace.
262  {
263  SetCurItem( Segment = new DRAWSEGMENT( GetBoard() ) );
264  Segment->SetFlags( IS_NEW );
265  Segment->SetLayer( GetActiveLayer() );
266  Segment->SetWidth( s_large );
267  Segment->SetShape( shape );
268  Segment->SetAngle( 900 );
269  Segment->SetStart( GetCrossHairPosition() );
270  Segment->SetEnd( GetCrossHairPosition() );
272  }
273  else /* The ending point ccordinate Segment->m_End was updated by he function
274  * DrawSegment() called on a move mouse event
275  * during the segment creation
276  */
277  {
278  if( Segment->GetStart() != Segment->GetEnd() )
279  {
280  if( Segment->GetShape() == S_SEGMENT )
281  {
282  SaveCopyInUndoList( Segment, UR_NEW );
283  GetBoard()->Add( Segment );
284 
285  OnModify();
286  Segment->ClearFlags();
287 
288  Segment->Draw( m_canvas, DC, GR_OR );
289 
290  DrawItem = Segment;
291 
292  SetCurItem( Segment = new DRAWSEGMENT( GetBoard() ) );
293 
294  Segment->SetFlags( IS_NEW );
295  Segment->SetLayer( DrawItem->GetLayer() );
296  Segment->SetWidth( s_large );
297  Segment->SetShape( DrawItem->GetShape() );
298  Segment->SetType( DrawItem->GetType() );
299  Segment->SetAngle( DrawItem->GetAngle() );
300  Segment->SetStart( DrawItem->GetEnd() );
301  Segment->SetEnd( DrawItem->GetEnd() );
302  DrawSegment( m_canvas, DC, wxDefaultPosition, false );
303  }
304  else
305  {
306  End_Edge( Segment, DC );
307  Segment = NULL;
308  }
309  }
310  }
311 
312  return Segment;
313 }
314 
315 
316 void PCB_EDIT_FRAME::End_Edge( DRAWSEGMENT* Segment, wxDC* DC )
317 {
318  if( Segment == NULL )
319  return;
320 
321  Segment->Draw( m_canvas, DC, GR_OR );
322 
323  // Delete if segment length is zero.
324  if( Segment->GetStart() == Segment->GetEnd() )
325  {
326  Segment->DeleteStructure();
327  }
328  else
329  {
330  Segment->ClearFlags();
331  GetBoard()->Add( Segment );
332  OnModify();
333  SaveCopyInUndoList( Segment, UR_NEW );
334  }
335 
336  m_canvas->SetMouseCapture( NULL, NULL );
337  SetCurItem( NULL );
338 }
339 
340 
341 /* Redraw segment during cursor movement
342  */
343 static void DrawSegment( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition, bool aErase )
344 {
345  DRAWSEGMENT* Segment = (DRAWSEGMENT*) aPanel->GetScreen()->GetCurItem();
346  auto frame = (PCB_EDIT_FRAME*) ( aPanel->GetParent() );
347  if( Segment == NULL )
348  return;
349 
350  DISPLAY_OPTIONS* displ_opts = (DISPLAY_OPTIONS*)aPanel->GetDisplayOptions();
351  bool tmp = displ_opts->m_DisplayDrawItemsFill;
352 
353  displ_opts->m_DisplayDrawItemsFill = SKETCH;
354 
355  if( aErase )
356  Segment->Draw( aPanel, aDC, GR_XOR );
357 
358  if( frame->Settings().m_use45DegreeGraphicSegments && Segment->GetShape() == S_SEGMENT )
359  {
360  wxPoint pt;
361 
363  Segment->GetStart() );
364  Segment->SetEnd( pt );
365  }
366  else // here the angle is arbitrary
367  {
368  Segment->SetEnd( aPanel->GetParent()->GetCrossHairPosition() );
369  }
370 
371  Segment->Draw( aPanel, aDC, GR_XOR );
372  displ_opts->m_DisplayDrawItemsFill = tmp;
373 }
void Place_DrawItem(DRAWSEGMENT *drawitem, wxDC *DC)
Definition: editedge.cpp:74
KICAD_T Type() const
Function Type()
Definition: base_struct.h:212
virtual void OnModify() override
Function OnModify must be called after a board change to set the modified flag.
Definition: pcbframe.cpp:999
STATUS_FLAGS GetFlags() const
Definition: base_struct.h:269
void SetShape(STROKE_T aShape)
EDA_ITEM * GetCurItem() const
virtual void Refresh(bool eraseBackground=true, const wxRect *rect=NULL) override
Update the board display after modifying it bu a python script (note: it is automatically called by a...
Definition: draw_panel.cpp:325
DRAWSEGMENT * Begin_DrawSegment(DRAWSEGMENT *Segment, STROKE_T shape, wxDC *DC)
Definition: editedge.cpp:249
virtual void SetLayer(PCB_LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
This file is part of the common library.
bool IsNew() const
Definition: base_struct.h:230
void SetType(int aType)
static void Abort_EditEdge(EDA_DRAW_PANEL *aPanel, wxDC *DC)
Definition: editedge.cpp:212
Class BOARD to handle a board.
static wxPoint s_InitialPosition
Definition: editedge.cpp:51
void SetCurItem(BOARD_ITEM *aItem, bool aDisplayInfo=true)
Function SetCurItem sets the currently selected item and displays it in the MsgPanel.
void DeleteStructure()
Function DeleteStructure deletes this object after UnLink()ing it from its owner if it has one...
class TEXTE_PCB, text on a layer
Definition: typeinfo.h:104
BOARD * GetBoard() const
void PushItem(const ITEM_PICKER &aItem)
Function PushItem pushes aItem to the top of the list.
usual segment : line with rounded ends
virtual void UnLink()
Function UnLink detaches this object from its owner.
void Start_Move_DrawItem(DRAWSEGMENT *drawitem, wxDC *DC)
Definition: editedge.cpp:56
static const int delta[8][2]
Definition: solve.cpp:112
void * GetDisplayOptions() override
Function GetDisplayOptions returns the display options current in use Display options are relative to...
wxPoint CalculateSegmentEndPoint(const wxPoint &aPosition, const wxPoint &aOrigin)
Determine end point for a segment direction 0, 90, or 45 degrees depending on it's position from the ...
Definition: editrack.cpp:831
This file contains miscellaneous commonly used macros and functions.
#define IS_NEW
New item, just created.
Definition: base_struct.h:127
PCB_LAYER_ID
A quick note on layer IDs:
STROKE_T GetShape() const
const wxPoint & GetEnd() const
Function GetEnd returns the ending point of the graphic.
void SetFlags(STATUS_FLAGS aMask)
Definition: base_struct.h:267
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Function SetMsgPanel clears the message panel and populates it with the contents of aList...
Definition: draw_frame.cpp:773
static wxPoint s_LastPosition
Definition: editedge.cpp:52
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_INSERT) override
Adds an item to the container.
int m_DrawSegmentWidth
current graphic line width (not EDGE layer)
void CallMouseCapture(wxDC *aDC, const wxPoint &aPosition, bool aErase)
Function CallMouseCapture calls the mouse capture callback.
bool m_DisplayDrawItemsFill
Definition: pcbstruct.h:84
void Delete_Segment_Edge(DRAWSEGMENT *Segment, wxDC *DC)
Definition: editedge.cpp:113
STROKE_T
Enum STROKE_T is the set of shapes for segments (graphic segments and tracks) which are often in the ...
virtual BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings returns the BOARD_DESIGN_SETTINGS for the BOARD owned by this frame...
EDA_DRAW_FRAME * GetParent() const
Definition: draw_panel.cpp:174
int GetType() const
static void DrawSegment(EDA_DRAW_PANEL *aPanel, wxDC *aDC, const wxPoint &aPosition, bool aErase)
Definition: editedge.cpp:343
Class PICKED_ITEMS_LIST is a holder to handle information on schematic or board items.
void SaveCopyInUndoList(BOARD_ITEM *aItemToCopy, UNDO_REDO_T aTypeCommand, const wxPoint &aTransformPoint=wxPoint(0, 0)) override
Function SaveCopyInUndoList Creates a new entry in undo list of commands.
Definition: undo_redo.cpp:172
void SetItem(EDA_ITEM *aItem)
class DIMENSION, a dimension (graphic item)
Definition: typeinfo.h:112
class PCB_TARGET, a target (graphic item)
Definition: typeinfo.h:113
void SetStart(const wxPoint &aStart)
Class DISPLAY_OPTIONS handles display options like enable/disable some optional drawings.
Definition: pcbstruct.h:62
Definition: gr_basic.h:42
EDA_DRAW_PANEL * m_canvas
The area to draw on.
Definition: draw_frame.h:92
static void Move_Segment(EDA_DRAW_PANEL *aPanel, wxDC *aDC, const wxPoint &aPosition, bool aErase)
Definition: editedge.cpp:90
PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
double GetAngle() const
Class to handle a graphic segment.
BASE_SCREEN * GetScreen()
Definition: draw_panel.cpp:187
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:165
void SetEnd(const wxPoint &aEnd)
void SetAngle(double aAngle)
Function SetAngle sets the angle for arcs, and normalizes it within the range 0 - 360 degrees...
bool IsCopperLayer(LAYER_NUM aLayerId)
Function IsCopperLayer tests whether a layer is a copper layer.
void ClearFlags(STATUS_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: base_struct.h:268
void * GetDisplayOptions()
Function GetDisplayOptions A way to pass info to draw functions.
Definition: draw_panel.cpp:181
void SetMouseCapture(MOUSE_CAPTURE_CALLBACK aMouseCaptureCallback, END_MOUSE_CAPTURE_CALLBACK aEndMouseCaptureCallback)
Function SetMouseCapture sets the mouse capture and end mouse capture callbacks to aMouseCaptureCallb...
int m_EdgeSegmentWidth
current graphic line width (EDGE layer only)
void SetCrossHairPosition(const wxPoint &aPosition, bool aSnapToGrid=true)
Function SetCrossHairPosition sets the screen cross hair position to aPosition in logical (drawing) u...
void Draw(EDA_DRAW_PANEL *panel, wxDC *DC, GR_DRAWMODE aDrawMode, const wxPoint &aOffset=ZeroOffset) override
Function Draw BOARD_ITEMs have their own color information.
class DRAWSEGMENT, a segment not on copper layers
Definition: typeinfo.h:103
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:71
wxPoint GetCrossHairPosition(bool aInvertY=false) const
Function GetCrossHairPosition return the current cross hair position in logical (drawing) coordinates...
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Function IsOK displays a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:129
virtual PCB_LAYER_ID GetActiveLayer() const
Function GetActiveLayer returns the active layer.
void Delete_Drawings_All_Layer(PCB_LAYER_ID aLayer)
Definition: editedge.cpp:148
BOARD_ITEM * Back() const
void End_Edge(DRAWSEGMENT *Segment, wxDC *DC)
Definition: editedge.cpp:316
#define IS_MOVED
Item being moved.
Definition: base_struct.h:126
void SetWidth(int aWidth)