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 <pcb_edit_frame.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 );
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();
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;
103 
104  segment->Move( delta );
105 
107 
108  segment->Draw( aPanel, aDC, GR_XOR );
109 }
110 
111 
113 {
114  auto displ_opts = (PCB_DISPLAY_OPTIONS*)GetDisplayOptions();
115  bool tmp = displ_opts->m_DisplayDrawItemsFill;
116 
117  if( Segment == NULL )
118  return;
119 
120  if( Segment->IsNew() ) // Trace in progress.
121  {
122  // Delete current segment.
123  displ_opts->m_DisplayDrawItemsFill = SKETCH;
124  Segment->Draw( m_canvas, DC, GR_XOR );
125  Segment->DeleteStructure();
126  displ_opts->m_DisplayDrawItemsFill = tmp;
127  SetCurItem( NULL );
128  }
129  else if( Segment->GetEditFlags() == 0 ) // i.e. not edited, or moved
130  {
131  Segment->Draw( m_canvas, DC, GR_XOR );
132  Segment->ClearFlags();
133  SaveCopyInUndoList(Segment, UR_DELETED);
134  Segment->UnLink();
135  SetCurItem( NULL );
136  OnModify();
137  }
138 }
139 
140 
142 {
143  if( IsCopperLayer( aLayer ) )
144  {
145  DisplayError( this, _( "Copper layer global delete not allowed!" ) );
146  return;
147  }
148 
149  wxString msg;
150  msg.Printf( _( "Delete everything on layer %s?" ),
151  GetChars( GetBoard()->GetLayerName( aLayer ) ) );
152 
153  if( !IsOK( this, msg ) )
154  return;
155 
156  // Step 1: build the list of items to remove.
157  // because we are using iterators, we cannot modify the drawing list during iterate
158  // so we are using a 2 steps calculation:
159  // First, collect items.
160  // Second, remove items.
161  std::vector<BOARD_ITEM*> list;
162 
163  for( auto item : GetBoard()->Drawings() )
164  {
165  switch( item->Type() )
166  {
167  case PCB_LINE_T:
168  case PCB_TEXT_T:
169  case PCB_DIMENSION_T:
170  case PCB_TARGET_T:
171  if( item->GetLayer() == aLayer )
172  list.push_back( item );
173 
174  break;
175 
176  default:
177  wxLogDebug( wxT( "Delete_Drawings_All_Layer() error: unknown type %d" ), item->Type() );
178 
179  }
180  }
181 
182  if( list.size() == 0 ) // No item found
183  return;
184 
185  // Step 2: remove items from main list, and move them to the undo list
186  PICKED_ITEMS_LIST pickList;
187  ITEM_PICKER picker( NULL, UR_DELETED );
188 
189  for( auto item : list )
190  {
191  item->UnLink();
192  picker.SetItem( item );
193  pickList.PushItem( picker );
194  }
195 
196  OnModify();
197  SaveCopyInUndoList(pickList, UR_DELETED);
198 }
199 
200 
201 static void Abort_EditEdge( EDA_DRAW_PANEL* aPanel, wxDC* DC )
202 {
203  DRAWSEGMENT* Segment = (DRAWSEGMENT*) aPanel->GetScreen()->GetCurItem();
204 
205  if( Segment == NULL )
206  {
207  aPanel->SetMouseCapture( NULL, NULL );
208  return;
209  }
210 
211  if( Segment->IsNew() )
212  {
213  aPanel->CallMouseCapture( DC, wxDefaultPosition, false );
214  Segment ->DeleteStructure();
215  Segment = NULL;
216  }
217  else
218  {
219  wxPoint pos = aPanel->GetParent()->GetCrossHairPosition();
221  aPanel->CallMouseCapture( DC, wxDefaultPosition, true );
222  aPanel->GetParent()->SetCrossHairPosition( pos );
223  Segment->ClearFlags();
224  Segment->Draw( aPanel, DC, GR_OR );
225  }
226 
227 #ifdef USE_WX_OVERLAY
228  aPanel->Refresh();
229 #endif
230 
231  aPanel->SetMouseCapture( NULL, NULL );
232  ( (PCB_EDIT_FRAME*) aPanel->GetParent() )->SetCurItem( NULL );
233 }
234 
235 
236 /* Initialize the drawing of a segment of type other than trace.
237  */
239 {
240  int lineWidth;
241  DRAWSEGMENT* DrawItem;
242 
244 
245  if( Segment == NULL ) // Create new segment.
246  {
247  SetCurItem( Segment = new DRAWSEGMENT( GetBoard() ) );
248  Segment->SetFlags( IS_NEW );
249  Segment->SetLayer( GetActiveLayer() );
250  Segment->SetWidth( lineWidth );
251  Segment->SetShape( shape );
252  Segment->SetAngle( 900 );
253  Segment->SetStart( GetCrossHairPosition() );
254  Segment->SetEnd( GetCrossHairPosition() );
256  }
257  else
258  {
259  // The ending point coordinate Segment->m_End was updated by the function
260  // DrawSegment() called on a move mouse event during the segment creation
261  if( Segment->GetStart() != Segment->GetEnd() )
262  {
263  if( Segment->GetShape() == S_SEGMENT )
264  {
265  SaveCopyInUndoList( Segment, UR_NEW );
266  GetBoard()->Add( Segment );
267 
268  OnModify();
269  Segment->ClearFlags();
270 
271  Segment->Draw( m_canvas, DC, GR_OR );
272 
273  DrawItem = Segment;
274 
275  SetCurItem( Segment = new DRAWSEGMENT( GetBoard() ) );
276 
277  Segment->SetFlags( IS_NEW );
278  Segment->SetLayer( DrawItem->GetLayer() );
279  Segment->SetWidth( lineWidth );
280  Segment->SetShape( DrawItem->GetShape() );
281  Segment->SetType( DrawItem->GetType() );
282  Segment->SetAngle( DrawItem->GetAngle() );
283  Segment->SetStart( DrawItem->GetEnd() );
284  Segment->SetEnd( DrawItem->GetEnd() );
285  DrawSegment( m_canvas, DC, wxDefaultPosition, false );
286  }
287  else
288  {
289  End_Edge( Segment, DC );
290  Segment = NULL;
291  }
292  }
293  }
294 
295  return Segment;
296 }
297 
298 
299 void PCB_EDIT_FRAME::End_Edge( DRAWSEGMENT* Segment, wxDC* DC )
300 {
301  if( Segment == NULL )
302  return;
303 
304  Segment->Draw( m_canvas, DC, GR_OR );
305 
306  // Delete if segment length is zero.
307  if( Segment->GetStart() == Segment->GetEnd() )
308  {
309  Segment->DeleteStructure();
310  }
311  else
312  {
313  Segment->ClearFlags();
314  GetBoard()->Add( Segment );
315  OnModify();
316  SaveCopyInUndoList( Segment, UR_NEW );
317  }
318 
319  m_canvas->SetMouseCapture( NULL, NULL );
320  SetCurItem( NULL );
321 }
322 
323 
324 /* Redraw segment during cursor movement
325  */
326 static void DrawSegment( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition, bool aErase )
327 {
328  DRAWSEGMENT* Segment = (DRAWSEGMENT*) aPanel->GetScreen()->GetCurItem();
329  auto frame = (PCB_EDIT_FRAME*) ( aPanel->GetParent() );
330  if( Segment == NULL )
331  return;
332 
333  auto displ_opts = (PCB_DISPLAY_OPTIONS*) ( aPanel->GetDisplayOptions() );
334  bool tmp = displ_opts->m_DisplayDrawItemsFill;
335 
336  displ_opts->m_DisplayDrawItemsFill = SKETCH;
337 
338  if( aErase )
339  Segment->Draw( aPanel, aDC, GR_XOR );
340 
341  if( frame->Settings().m_use45DegreeGraphicSegments && Segment->GetShape() == S_SEGMENT )
342  {
343  wxPoint pt;
344 
346  Segment->GetStart() );
347  Segment->SetEnd( pt );
348  }
349  else // here the angle is arbitrary
350  {
351  Segment->SetEnd( aPanel->GetParent()->GetCrossHairPosition() );
352  }
353 
354  Segment->Draw( aPanel, aDC, GR_XOR );
355  displ_opts->m_DisplayDrawItemsFill = tmp;
356 }
virtual BASE_SCREEN * GetScreen()=0
void Place_DrawItem(DRAWSEGMENT *drawitem, wxDC *DC)
Definition: editedge.cpp:74
virtual void OnModify() override
Function OnModify must be called after a board change to set the modified flag.
void SetShape(STROKE_T aShape)
virtual BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings returns the BOARD_DESIGN_SETTINGS for the BOARD owned by this frame.
virtual void Move(const wxPoint &aMoveVector) override
Function Move move this object.
DRAWSEGMENT * Begin_DrawSegment(DRAWSEGMENT *Segment, STROKE_T shape, wxDC *DC)
Definition: editedge.cpp:238
virtual void SetLayer(PCB_LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
This file is part of the common library.
void SetType(int aType)
static void Abort_EditEdge(EDA_DRAW_PANEL *aPanel, wxDC *DC)
Definition: editedge.cpp:201
STROKE_T GetShape() const
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.
int GetType() const
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:92
EDA_ITEM * GetCurItem() const
Definition: base_screen.h:233
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.
const wxPoint & GetEnd() const
Function GetEnd returns the ending point of the graphic.
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:800
This file contains miscellaneous commonly used macros and functions.
bool IsNew() const
Definition: base_struct.h:222
#define IS_NEW
New item, just created.
Definition: base_struct.h:114
virtual PCB_LAYER_ID GetActiveLayer() const
Function GetActiveLayer returns the active layer.
virtual EDA_DRAW_FRAME * GetParent() const =0
int GetLineThickness(PCB_LAYER_ID aLayer) const
Function GetLineThickness Returns the default graphic segment thickness from the layer class for the ...
Class PCB_DISPLAY_OPTIONS handles display options like enable/disable some optional drawings.
PCB_LAYER_ID
A quick note on layer IDs:
void SetFlags(STATUS_FLAGS aMask)
Definition: base_struct.h:259
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
STATUS_FLAGS GetEditFlags() const
Definition: base_struct.h:263
static wxPoint s_LastPosition
Definition: editedge.cpp:52
virtual void SetMouseCapture(MOUSE_CAPTURE_CALLBACK aMouseCaptureCallback, END_MOUSE_CAPTURE_CALLBACK aEndMouseCaptureCallback)
Function SetMouseCapture sets the mouse capture and end mouse capture callbacks to aMouseCaptureCallb...
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_INSERT) override
Adds an item to the container.
virtual void CallMouseCapture(wxDC *aDC, const wxPoint &aPosition, bool aErase)
Function CallMouseCapture calls the mouse capture callback.
void Delete_Segment_Edge(DRAWSEGMENT *Segment, wxDC *DC)
Definition: editedge.cpp:112
STROKE_T
Enum STROKE_T is the set of shapes for segments (graphic segments and tracks) which are often in the ...
static void DrawSegment(EDA_DRAW_PANEL *aPanel, wxDC *aDC, const wxPoint &aPosition, bool aErase)
Definition: editedge.cpp:326
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:198
void SetItem(EDA_ITEM *aItem)
class DIMENSION, a dimension (graphic item)
Definition: typeinfo.h:98
class PCB_TARGET, a target (graphic item)
Definition: typeinfo.h:99
void SetStart(const wxPoint &aStart)
Definition: gr_basic.h:38
EDA_DRAW_PANEL * m_canvas
The area to draw on.
Definition: draw_frame.h:128
static void Move_Segment(EDA_DRAW_PANEL *aPanel, wxDC *aDC, const wxPoint &aPosition, bool aErase)
Definition: editedge.cpp:90
double GetAngle() const
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:100
Class to handle a graphic segment.
Class PCB_EDIT_FRAME is the main frame for Pcbnew.
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:260
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.
BOARD * GetBoard() const
virtual void * GetDisplayOptions()
Function GetDisplayOptions A way to pass info to draw functions.
virtual void Refresh(bool eraseBackground=true, const wxRect *rect=NULL)
void SetCrossHairPosition(const wxPoint &aPosition, bool aSnapToGrid=true)
Set the screen cross hair position to aPosition in logical (drawing) units.
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:91
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:244
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Function IsOK displays a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:294
void Delete_Drawings_All_Layer(PCB_LAYER_ID aLayer)
Definition: editedge.cpp:141
wxPoint GetCrossHairPosition(bool aInvertY=false) const
Return the current cross hair position in logical (drawing) coordinates.
void End_Edge(DRAWSEGMENT *Segment, wxDC *DC)
Definition: editedge.cpp:299
#define IS_MOVED
Item being moved.
Definition: base_struct.h:113
void SetWidth(int aWidth)