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 );
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->Move( delta );
105 
106  s_LastPosition = aPanel->GetParent()->GetCrossHairPosition();
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  {
179  msg.Printf( wxT("Delete_Drawings_All_Layer() error: unknown type %d"),
180  item->Type() );
181  wxMessageBox( msg );
182  break;
183  }
184  }
185  }
186 
187  if( list.size() == 0 ) // No item found
188  return;
189 
190  // Step 2: remove items from main list, and move them to the undo list
191  PICKED_ITEMS_LIST pickList;
192  ITEM_PICKER picker( NULL, UR_DELETED );
193 
194  for( auto item : list )
195  {
196  item->UnLink();
197  picker.SetItem( item );
198  pickList.PushItem( picker );
199  }
200 
201  OnModify();
202  SaveCopyInUndoList(pickList, UR_DELETED);
203 }
204 
205 
206 static void Abort_EditEdge( EDA_DRAW_PANEL* aPanel, wxDC* DC )
207 {
208  DRAWSEGMENT* Segment = (DRAWSEGMENT*) aPanel->GetScreen()->GetCurItem();
209 
210  if( Segment == NULL )
211  {
212  aPanel->SetMouseCapture( NULL, NULL );
213  return;
214  }
215 
216  if( Segment->IsNew() )
217  {
218  aPanel->CallMouseCapture( DC, wxDefaultPosition, false );
219  Segment ->DeleteStructure();
220  Segment = NULL;
221  }
222  else
223  {
224  wxPoint pos = aPanel->GetParent()->GetCrossHairPosition();
225  aPanel->GetParent()->SetCrossHairPosition( s_InitialPosition );
226  aPanel->CallMouseCapture( DC, wxDefaultPosition, true );
227  aPanel->GetParent()->SetCrossHairPosition( pos );
228  Segment->ClearFlags();
229  Segment->Draw( aPanel, DC, GR_OR );
230  }
231 
232 #ifdef USE_WX_OVERLAY
233  aPanel->Refresh();
234 #endif
235 
236  aPanel->SetMouseCapture( NULL, NULL );
237  ( (PCB_EDIT_FRAME*) aPanel->GetParent() )->SetCurItem( NULL );
238 }
239 
240 
241 /* Initialize the drawing of a segment of type other than trace.
242  */
244 {
245  int lineWidth;
246  DRAWSEGMENT* DrawItem;
247 
249 
250  if( Segment == NULL ) // Create new segment.
251  {
252  SetCurItem( Segment = new DRAWSEGMENT( GetBoard() ) );
253  Segment->SetFlags( IS_NEW );
254  Segment->SetLayer( GetActiveLayer() );
255  Segment->SetWidth( lineWidth );
256  Segment->SetShape( shape );
257  Segment->SetAngle( 900 );
258  Segment->SetStart( GetCrossHairPosition() );
259  Segment->SetEnd( GetCrossHairPosition() );
261  }
262  else
263  {
264  // The ending point coordinate Segment->m_End was updated by the function
265  // DrawSegment() called on a move mouse event during the segment creation
266  if( Segment->GetStart() != Segment->GetEnd() )
267  {
268  if( Segment->GetShape() == S_SEGMENT )
269  {
270  SaveCopyInUndoList( Segment, UR_NEW );
271  GetBoard()->Add( Segment );
272 
273  OnModify();
274  Segment->ClearFlags();
275 
276  Segment->Draw( m_canvas, DC, GR_OR );
277 
278  DrawItem = Segment;
279 
280  SetCurItem( Segment = new DRAWSEGMENT( GetBoard() ) );
281 
282  Segment->SetFlags( IS_NEW );
283  Segment->SetLayer( DrawItem->GetLayer() );
284  Segment->SetWidth( lineWidth );
285  Segment->SetShape( DrawItem->GetShape() );
286  Segment->SetType( DrawItem->GetType() );
287  Segment->SetAngle( DrawItem->GetAngle() );
288  Segment->SetStart( DrawItem->GetEnd() );
289  Segment->SetEnd( DrawItem->GetEnd() );
290  DrawSegment( m_canvas, DC, wxDefaultPosition, false );
291  }
292  else
293  {
294  End_Edge( Segment, DC );
295  Segment = NULL;
296  }
297  }
298  }
299 
300  return Segment;
301 }
302 
303 
304 void PCB_EDIT_FRAME::End_Edge( DRAWSEGMENT* Segment, wxDC* DC )
305 {
306  if( Segment == NULL )
307  return;
308 
309  Segment->Draw( m_canvas, DC, GR_OR );
310 
311  // Delete if segment length is zero.
312  if( Segment->GetStart() == Segment->GetEnd() )
313  {
314  Segment->DeleteStructure();
315  }
316  else
317  {
318  Segment->ClearFlags();
319  GetBoard()->Add( Segment );
320  OnModify();
321  SaveCopyInUndoList( Segment, UR_NEW );
322  }
323 
324  m_canvas->SetMouseCapture( NULL, NULL );
325  SetCurItem( NULL );
326 }
327 
328 
329 /* Redraw segment during cursor movement
330  */
331 static void DrawSegment( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition, bool aErase )
332 {
333  DRAWSEGMENT* Segment = (DRAWSEGMENT*) aPanel->GetScreen()->GetCurItem();
334  auto frame = (PCB_EDIT_FRAME*) ( aPanel->GetParent() );
335  if( Segment == NULL )
336  return;
337 
338  auto displ_opts = (PCB_DISPLAY_OPTIONS*) ( aPanel->GetDisplayOptions() );
339  bool tmp = displ_opts->m_DisplayDrawItemsFill;
340 
341  displ_opts->m_DisplayDrawItemsFill = SKETCH;
342 
343  if( aErase )
344  Segment->Draw( aPanel, aDC, GR_XOR );
345 
346  if( frame->Settings().m_use45DegreeGraphicSegments && Segment->GetShape() == S_SEGMENT )
347  {
348  wxPoint pt;
349 
351  Segment->GetStart() );
352  Segment->SetEnd( pt );
353  }
354  else // here the angle is arbitrary
355  {
356  Segment->SetEnd( aPanel->GetParent()->GetCrossHairPosition() );
357  }
358 
359  Segment->Draw( aPanel, aDC, GR_XOR );
360  displ_opts->m_DisplayDrawItemsFill = tmp;
361 }
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.
STATUS_FLAGS GetFlags() const
Definition: base_struct.h:258
void SetShape(STROKE_T aShape)
virtual void Move(const wxPoint &aMoveVector) override
Function Move move this object.
EDA_ITEM * GetCurItem() const
Definition: base_screen.h:233
DRAWSEGMENT * Begin_DrawSegment(DRAWSEGMENT *Segment, STROKE_T shape, wxDC *DC)
Definition: editedge.cpp:243
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:219
void SetType(int aType)
static void Abort_EditEdge(EDA_DRAW_PANEL *aPanel, wxDC *DC)
Definition: editedge.cpp:206
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
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:92
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.
#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&#39;s position from the ...
Definition: editrack.cpp:800
This file contains miscellaneous commonly used macros and functions.
#define IS_NEW
New item, just created.
Definition: base_struct.h:114
virtual EDA_DRAW_FRAME * GetParent() const =0
#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:
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: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 ...
virtual BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings returns the BOARD_DESIGN_SETTINGS for the BOARD owned by this frame...
int GetType() const
static void DrawSegment(EDA_DRAW_PANEL *aPanel, wxDC *aDC, const wxPoint &aPosition, bool aErase)
Definition: editedge.cpp:331
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
int GetLineThickness(PCB_LAYER_ID aLayer) const
Function GetLineThickness Returns the default graphic segment thickness from the layer class for the ...
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:123
static void Move_Segment(EDA_DRAW_PANEL *aPanel, wxDC *aDC, const wxPoint &aPosition, bool aErase)
Definition: editedge.cpp:90
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
#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
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
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:245
wxPoint GetCrossHairPosition(bool aInvertY=false) const
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:295
virtual PCB_LAYER_ID GetActiveLayer() const
Function GetActiveLayer returns the active layer.
void Delete_Drawings_All_Layer(PCB_LAYER_ID aLayer)
Definition: editedge.cpp:142
void End_Edge(DRAWSEGMENT *Segment, wxDC *DC)
Definition: editedge.cpp:304
#define IS_MOVED
Item being moved.
Definition: base_struct.h:113
void SetWidth(int aWidth)