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  int mask = EDA_ITEM_ALL_FLAGS - ( SELECTED | HIGHLIGHTED | BRIGHTENED );
121  if( Segment->IsNew() ) // Trace in progress.
122  {
123  // Delete current segment.
124  displ_opts->m_DisplayDrawItemsFill = SKETCH;
125  Segment->Draw( m_canvas, DC, GR_XOR );
126  Segment->DeleteStructure();
127  displ_opts->m_DisplayDrawItemsFill = tmp;
128  SetCurItem( NULL );
129  }
130  else if( ( Segment->GetFlags() & mask ) == 0 ) // i.e. not edited, or moved
131  {
132  Segment->Draw( m_canvas, DC, GR_XOR );
133  Segment->ClearFlags();
134  SaveCopyInUndoList(Segment, UR_DELETED);
135  Segment->UnLink();
136  SetCurItem( NULL );
137  OnModify();
138  }
139 }
140 
141 
143 {
144  if( IsCopperLayer( aLayer ) )
145  {
146  DisplayError( this, _( "Copper layer global delete not allowed!" ) );
147  return;
148  }
149 
150  wxString msg;
151  msg.Printf( _( "Delete everything on layer %s?" ),
152  GetChars( GetBoard()->GetLayerName( aLayer ) ) );
153 
154  if( !IsOK( this, msg ) )
155  return;
156 
157  // Step 1: build the list of items to remove.
158  // because we are using iterators, we cannot modify the drawing list during iterate
159  // so we are using a 2 steps calculation:
160  // First, collect items.
161  // Second, remove items.
162  std::vector<BOARD_ITEM*> list;
163 
164  for( auto item : GetBoard()->Drawings() )
165  {
166  switch( item->Type() )
167  {
168  case PCB_LINE_T:
169  case PCB_TEXT_T:
170  case PCB_DIMENSION_T:
171  case PCB_TARGET_T:
172  if( item->GetLayer() == aLayer )
173  list.push_back( item );
174 
175  break;
176 
177  default:
178  wxLogDebug( wxT( "Delete_Drawings_All_Layer() error: unknown type %d" ), item->Type() );
179 
180  }
181  }
182 
183  if( list.size() == 0 ) // No item found
184  return;
185 
186  // Step 2: remove items from main list, and move them to the undo list
187  PICKED_ITEMS_LIST pickList;
188  ITEM_PICKER picker( NULL, UR_DELETED );
189 
190  for( auto item : list )
191  {
192  item->UnLink();
193  picker.SetItem( item );
194  pickList.PushItem( picker );
195  }
196 
197  OnModify();
198  SaveCopyInUndoList(pickList, UR_DELETED);
199 }
200 
201 
202 static void Abort_EditEdge( EDA_DRAW_PANEL* aPanel, wxDC* DC )
203 {
204  DRAWSEGMENT* Segment = (DRAWSEGMENT*) aPanel->GetScreen()->GetCurItem();
205 
206  if( Segment == NULL )
207  {
208  aPanel->SetMouseCapture( NULL, NULL );
209  return;
210  }
211 
212  if( Segment->IsNew() )
213  {
214  aPanel->CallMouseCapture( DC, wxDefaultPosition, false );
215  Segment ->DeleteStructure();
216  Segment = NULL;
217  }
218  else
219  {
220  wxPoint pos = aPanel->GetParent()->GetCrossHairPosition();
222  aPanel->CallMouseCapture( DC, wxDefaultPosition, true );
223  aPanel->GetParent()->SetCrossHairPosition( pos );
224  Segment->ClearFlags();
225  Segment->Draw( aPanel, DC, GR_OR );
226  }
227 
228 #ifdef USE_WX_OVERLAY
229  aPanel->Refresh();
230 #endif
231 
232  aPanel->SetMouseCapture( NULL, NULL );
233  ( (PCB_EDIT_FRAME*) aPanel->GetParent() )->SetCurItem( NULL );
234 }
235 
236 
237 /* Initialize the drawing of a segment of type other than trace.
238  */
240 {
241  int lineWidth;
242  DRAWSEGMENT* DrawItem;
243 
245 
246  if( Segment == NULL ) // Create new segment.
247  {
248  SetCurItem( Segment = new DRAWSEGMENT( GetBoard() ) );
249  Segment->SetFlags( IS_NEW );
250  Segment->SetLayer( GetActiveLayer() );
251  Segment->SetWidth( lineWidth );
252  Segment->SetShape( shape );
253  Segment->SetAngle( 900 );
254  Segment->SetStart( GetCrossHairPosition() );
255  Segment->SetEnd( GetCrossHairPosition() );
257  }
258  else
259  {
260  // The ending point coordinate Segment->m_End was updated by the function
261  // DrawSegment() called on a move mouse event during the segment creation
262  if( Segment->GetStart() != Segment->GetEnd() )
263  {
264  if( Segment->GetShape() == S_SEGMENT )
265  {
266  SaveCopyInUndoList( Segment, UR_NEW );
267  GetBoard()->Add( Segment );
268 
269  OnModify();
270  Segment->ClearFlags();
271 
272  Segment->Draw( m_canvas, DC, GR_OR );
273 
274  DrawItem = Segment;
275 
276  SetCurItem( Segment = new DRAWSEGMENT( GetBoard() ) );
277 
278  Segment->SetFlags( IS_NEW );
279  Segment->SetLayer( DrawItem->GetLayer() );
280  Segment->SetWidth( lineWidth );
281  Segment->SetShape( DrawItem->GetShape() );
282  Segment->SetType( DrawItem->GetType() );
283  Segment->SetAngle( DrawItem->GetAngle() );
284  Segment->SetStart( DrawItem->GetEnd() );
285  Segment->SetEnd( DrawItem->GetEnd() );
286  DrawSegment( m_canvas, DC, wxDefaultPosition, false );
287  }
288  else
289  {
290  End_Edge( Segment, DC );
291  Segment = NULL;
292  }
293  }
294  }
295 
296  return Segment;
297 }
298 
299 
300 void PCB_EDIT_FRAME::End_Edge( DRAWSEGMENT* Segment, wxDC* DC )
301 {
302  if( Segment == NULL )
303  return;
304 
305  Segment->Draw( m_canvas, DC, GR_OR );
306 
307  // Delete if segment length is zero.
308  if( Segment->GetStart() == Segment->GetEnd() )
309  {
310  Segment->DeleteStructure();
311  }
312  else
313  {
314  Segment->ClearFlags();
315  GetBoard()->Add( Segment );
316  OnModify();
317  SaveCopyInUndoList( Segment, UR_NEW );
318  }
319 
320  m_canvas->SetMouseCapture( NULL, NULL );
321  SetCurItem( NULL );
322 }
323 
324 
325 /* Redraw segment during cursor movement
326  */
327 static void DrawSegment( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition, bool aErase )
328 {
329  DRAWSEGMENT* Segment = (DRAWSEGMENT*) aPanel->GetScreen()->GetCurItem();
330  auto frame = (PCB_EDIT_FRAME*) ( aPanel->GetParent() );
331  if( Segment == NULL )
332  return;
333 
334  auto displ_opts = (PCB_DISPLAY_OPTIONS*) ( aPanel->GetDisplayOptions() );
335  bool tmp = displ_opts->m_DisplayDrawItemsFill;
336 
337  displ_opts->m_DisplayDrawItemsFill = SKETCH;
338 
339  if( aErase )
340  Segment->Draw( aPanel, aDC, GR_XOR );
341 
342  if( frame->Settings().m_use45DegreeGraphicSegments && Segment->GetShape() == S_SEGMENT )
343  {
344  wxPoint pt;
345 
347  Segment->GetStart() );
348  Segment->SetEnd( pt );
349  }
350  else // here the angle is arbitrary
351  {
352  Segment->SetEnd( aPanel->GetParent()->GetCrossHairPosition() );
353  }
354 
355  Segment->Draw( aPanel, aDC, GR_XOR );
356  displ_opts->m_DisplayDrawItemsFill = tmp;
357 }
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:239
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:202
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.
#define EDA_ITEM_ALL_FLAGS
Definition: base_struct.h:145
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:219
#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 ...
#define SELECTED
Definition: base_struct.h:121
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:256
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
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.
#define BRIGHTENED
item is drawn with a bright contour
Definition: base_struct.h:138
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:327
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:202
void SetItem(EDA_ITEM *aItem)
class DIMENSION, a dimension (graphic item)
Definition: typeinfo.h:100
class PCB_TARGET, a target (graphic item)
Definition: typeinfo.h:101
void SetStart(const wxPoint &aStart)
Definition: gr_basic.h:38
EDA_DRAW_PANEL * m_canvas
The area to draw on.
Definition: draw_frame.h:126
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:92
#define HIGHLIGHTED
item is drawn in normal colors, when the rest is darkened
Definition: base_struct.h:137
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:257
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
STATUS_FLAGS GetFlags() const
Definition: base_struct.h:258
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:243
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Function IsOK displays a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:293
void Delete_Drawings_All_Layer(PCB_LAYER_ID aLayer)
Definition: editedge.cpp:142
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:300
#define IS_MOVED
Item being moved.
Definition: base_struct.h:113
void SetWidth(int aWidth)