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  PICKED_ITEMS_LIST pickList;
164  ITEM_PICKER picker( NULL, UR_DELETED );
165  BOARD_ITEM* PtNext;
166 
167  for( BOARD_ITEM* item = GetBoard()->m_Drawings; item; item = PtNext )
168  {
169  PtNext = item->Next();
170 
171  switch( item->Type() )
172  {
173  case PCB_LINE_T:
174  case PCB_TEXT_T:
175  case PCB_DIMENSION_T:
176  case PCB_TARGET_T:
177  if( item->GetLayer() == aLayer )
178  {
179  item->UnLink();
180  picker.SetItem( item );
181  pickList.PushItem( picker );
182  }
183 
184  break;
185 
186  default:
187  {
188  msg.Printf( wxT("Delete_Drawings_All_Layer() error: unknown type %d"),
189  item->Type() );
190  wxMessageBox( msg );
191  break;
192  }
193  }
194  }
195 
196  if( pickList.GetCount() )
197  {
198  OnModify();
199  SaveCopyInUndoList(pickList, UR_DELETED);
200  }
201 }
202 
203 
204 static void Abort_EditEdge( EDA_DRAW_PANEL* aPanel, wxDC* DC )
205 {
206  DRAWSEGMENT* Segment = (DRAWSEGMENT*) aPanel->GetScreen()->GetCurItem();
207 
208  if( Segment == NULL )
209  {
210  aPanel->SetMouseCapture( NULL, NULL );
211  return;
212  }
213 
214  if( Segment->IsNew() )
215  {
216  aPanel->CallMouseCapture( DC, wxDefaultPosition, false );
217  Segment ->DeleteStructure();
218  Segment = NULL;
219  }
220  else
221  {
222  wxPoint pos = aPanel->GetParent()->GetCrossHairPosition();
223  aPanel->GetParent()->SetCrossHairPosition( s_InitialPosition );
224  aPanel->CallMouseCapture( DC, wxDefaultPosition, true );
225  aPanel->GetParent()->SetCrossHairPosition( pos );
226  Segment->ClearFlags();
227  Segment->Draw( aPanel, DC, GR_OR );
228  }
229 
230 #ifdef USE_WX_OVERLAY
231  aPanel->Refresh();
232 #endif
233 
234  aPanel->SetMouseCapture( NULL, NULL );
235  ( (PCB_EDIT_FRAME*) aPanel->GetParent() )->SetCurItem( NULL );
236 }
237 
238 
239 /* Initialize the drawing of a segment of type other than trace.
240  */
242 {
243  int s_large;
244  DRAWSEGMENT* DrawItem;
245 
247 
248  if( GetActiveLayer() == Edge_Cuts )
249  {
251  }
252 
253  if( Segment == NULL ) // Create new trace.
254  {
255  SetCurItem( Segment = new DRAWSEGMENT( GetBoard() ) );
256  Segment->SetFlags( IS_NEW );
257  Segment->SetLayer( GetActiveLayer() );
258  Segment->SetWidth( s_large );
259  Segment->SetShape( shape );
260  Segment->SetAngle( 900 );
261  Segment->SetStart( GetCrossHairPosition() );
262  Segment->SetEnd( GetCrossHairPosition() );
264  }
265  else /* The ending point ccordinate Segment->m_End was updated by he function
266  * DrawSegment() called on a move mouse event
267  * during the segment creation
268  */
269  {
270  if( Segment->GetStart() != Segment->GetEnd() )
271  {
272  if( Segment->GetShape() == S_SEGMENT )
273  {
274  SaveCopyInUndoList( Segment, UR_NEW );
275  GetBoard()->Add( Segment );
276 
277  OnModify();
278  Segment->ClearFlags();
279 
280  Segment->Draw( m_canvas, DC, GR_OR );
281 
282  DrawItem = Segment;
283 
284  SetCurItem( Segment = new DRAWSEGMENT( GetBoard() ) );
285 
286  Segment->SetFlags( IS_NEW );
287  Segment->SetLayer( DrawItem->GetLayer() );
288  Segment->SetWidth( s_large );
289  Segment->SetShape( DrawItem->GetShape() );
290  Segment->SetType( DrawItem->GetType() );
291  Segment->SetAngle( DrawItem->GetAngle() );
292  Segment->SetStart( DrawItem->GetEnd() );
293  Segment->SetEnd( DrawItem->GetEnd() );
294  DrawSegment( m_canvas, DC, wxDefaultPosition, false );
295  }
296  else
297  {
298  End_Edge( Segment, DC );
299  Segment = NULL;
300  }
301  }
302  }
303 
304  return Segment;
305 }
306 
307 
308 void PCB_EDIT_FRAME::End_Edge( DRAWSEGMENT* Segment, wxDC* DC )
309 {
310  if( Segment == NULL )
311  return;
312 
313  Segment->Draw( m_canvas, DC, GR_OR );
314 
315  // Delete if segment length is zero.
316  if( Segment->GetStart() == Segment->GetEnd() )
317  {
318  Segment->DeleteStructure();
319  }
320  else
321  {
322  Segment->ClearFlags();
323  GetBoard()->Add( Segment );
324  OnModify();
325  SaveCopyInUndoList( Segment, UR_NEW );
326  }
327 
328  m_canvas->SetMouseCapture( NULL, NULL );
329  SetCurItem( NULL );
330 }
331 
332 
333 /* Redraw segment during cursor movement
334  */
335 static void DrawSegment( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition, bool aErase )
336 {
337  DRAWSEGMENT* Segment = (DRAWSEGMENT*) aPanel->GetScreen()->GetCurItem();
338 
339  if( Segment == NULL )
340  return;
341 
342  DISPLAY_OPTIONS* displ_opts = (DISPLAY_OPTIONS*)aPanel->GetDisplayOptions();
343  bool tmp = displ_opts->m_DisplayDrawItemsFill;
344 
345  displ_opts->m_DisplayDrawItemsFill = SKETCH;
346 
347  if( aErase )
348  Segment->Draw( aPanel, aDC, GR_XOR );
349 
350  if( g_Segments_45_Only && Segment->GetShape() == S_SEGMENT )
351  {
352  wxPoint pt;
353 
355  Segment->GetStart() );
356  Segment->SetEnd( pt );
357  }
358  else // here the angle is arbitrary
359  {
360  Segment->SetEnd( aPanel->GetParent()->GetCrossHairPosition() );
361  }
362 
363  Segment->Draw( aPanel, aDC, GR_XOR );
364  displ_opts->m_DisplayDrawItemsFill = tmp;
365 }
bool g_Segments_45_Only
Definition: pcbnew.cpp:75
void Place_DrawItem(DRAWSEGMENT *drawitem, wxDC *DC)
Definition: editedge.cpp:74
KICAD_T Type() const
Function Type()
Definition: base_struct.h:198
virtual void OnModify() override
Function OnModify must be called after a board change to set the modified flag.
Definition: pcbframe.cpp:996
STATUS_FLAGS GetFlags() const
Definition: base_struct.h:255
void SetShape(STROKE_T aShape)
EDA_ITEM * GetCurItem() const
virtual void Refresh(bool eraseBackground=true, const wxRect *rect=NULL) override
Definition: draw_panel.cpp:326
DRAWSEGMENT * Begin_DrawSegment(DRAWSEGMENT *Segment, STROKE_T shape, wxDC *DC)
Definition: editedge.cpp:241
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:216
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class...
void SetType(int aType)
static void Abort_EditEdge(EDA_DRAW_PANEL *aPanel, wxDC *DC)
Definition: editedge.cpp:204
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:833
This file contains miscellaneous commonly used macros and functions.
#define IS_NEW
New item, just created.
Definition: base_struct.h:113
BOARD_ITEM * Next() const
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:253
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:754
static wxPoint s_LastPosition
Definition: editedge.cpp:52
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_INSERT) override
>
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:175
int GetType() const
static void DrawSegment(EDA_DRAW_PANEL *aPanel, wxDC *aDC, const wxPoint &aPosition, bool aErase)
Definition: editedge.cpp:335
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
unsigned GetCount() const
Function GetCount.
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:188
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:151
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:254
void * GetDisplayOptions()
Function GetDisplayOptions A way to pass info to draw functions.
Definition: draw_panel.cpp:182
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:69
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:111
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:308
#define IS_MOVED
Item being moved.
Definition: base_struct.h:112
void SetWidth(int aWidth)