KiCad PCB EDA Suite
block_libedit.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) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
5  * Copyright (C) 2008-2011 Wayne Stambaugh <stambaughw@verizon.net>
6  * Copyright (C) 2004-2017 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 
30 #include <fctsys.h>
31 #include <gr_basic.h>
32 #include <class_drawpanel.h>
33 #include <confirm.h>
34 
35 #include <general.h>
36 #include <class_library.h>
37 #include <libeditframe.h>
38 
39 
40 static void DrawMovingBlockOutlines( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition,
41  bool aErase );
42 
43 
45 {
46  int cmd = BLOCK_IDLE;
47 
48  switch( key )
49  {
50  default:
51  cmd = key & 0xFF;
52  break;
53 
54  case EDA_KEY_C( 0xffffffff ): // -1
55  // Historically, -1 has been used as a key, which can cause bit flag
56  // clashes with unaware code. On debug builds, catch any old code that
57  // might still be doing this. TODO: remove if sure all this old code is gone.
58  wxFAIL_MSG( "negative EDA_KEY value should be converted to GR_KEY_INVALID" );
59  // fall through on release builds
60 
61  case GR_KEY_INVALID:
63  break;
64 
65  case GR_KEY_NONE:
66  cmd = BLOCK_MOVE;
67  break;
68 
69  case GR_KB_SHIFT:
70  cmd = BLOCK_DUPLICATE;
71  break;
72 
73  case GR_KB_ALT:
74  cmd = BLOCK_ROTATE;
75  break;
76 
77  case GR_KB_SHIFTCTRL:
78  cmd = BLOCK_DELETE;
79  break;
80 
81  case GR_KB_CTRL:
82  cmd = BLOCK_MIRROR_Y;
83  break;
84 
85  case MOUSE_MIDDLE:
86  cmd = BLOCK_ZOOM;
87  break;
88  }
89 
90  return cmd;
91 }
92 
93 
95 {
96  int ItemCount = 0;
97  bool nextCmd = false;
99  wxPoint pt;
100 
101  if( block->GetCount() )
102  {
103  BLOCK_STATE_T state = block->GetState();
104  BLOCK_COMMAND_T command = block->GetCommand();
106  block->SetState( state );
107  block->SetCommand( command );
110  block->GetBottom() ) );
112  }
113 
114  switch( block->GetCommand() )
115  {
116  case BLOCK_IDLE:
117  DisplayError( this, wxT( "Error in HandleBlockPLace" ) );
118  break;
119 
120  case BLOCK_DRAG: // Drag
121  case BLOCK_DRAG_ITEM:
122  case BLOCK_MOVE: // Move
123  case BLOCK_DUPLICATE: // Duplicate
124  if( GetCurPart() )
125  ItemCount = GetCurPart()->SelectItems( *block,
126  m_unit, m_convert,
128  if( ItemCount )
129  {
130  nextCmd = true;
131 
132  if( m_canvas->IsMouseCaptured() )
133  {
134  m_canvas->CallMouseCapture( aDC, wxDefaultPosition, false );
136  m_canvas->CallMouseCapture( aDC, wxDefaultPosition, false );
137  }
138 
139  block->SetState( STATE_BLOCK_MOVE );
140  m_canvas->Refresh( true );
141  }
142  break;
143 
144  case BLOCK_PRESELECT_MOVE: // Move with preselection list
145  nextCmd = true;
147  block->SetState( STATE_BLOCK_MOVE );
148  break;
149 
150  case BLOCK_COPY: // Save a copy of items in the clipboard buffer
151  case BLOCK_CUT:
152  if( GetCurPart() )
153  ItemCount = GetCurPart()->SelectItems( *block, m_unit, m_convert,
155 
156  if( ItemCount )
157  {
159  auto cmd = block->GetCommand();
160 
161  if( cmd == BLOCK_COPY )
162  {
164  block->ClearItemsList();
165  }
166  else if( cmd == BLOCK_CUT )
167  {
170  OnModify();
171  }
172  }
173  break;
174 
175  case BLOCK_DELETE: // Delete
176  if( GetCurPart() )
177  ItemCount = GetCurPart()->SelectItems( *block,
178  m_unit, m_convert,
180  if( ItemCount )
182 
183  if( GetCurPart() )
184  {
186  OnModify();
187  }
188  break;
189 
190  case BLOCK_PASTE:
191  wxFAIL; // should not happen
192  break;
193 
194  case BLOCK_FLIP:
195  break;
196 
197  case BLOCK_ROTATE:
198  case BLOCK_MIRROR_X:
199  case BLOCK_MIRROR_Y:
200  if( GetCurPart() )
201  ItemCount = GetCurPart()->SelectItems( *block,
202  m_unit, m_convert,
204  if( ItemCount )
206 
207  pt = block->Centre();
208  pt = GetNearestGridPosition( pt );
209  pt.y = -pt.y;
210 
211  if( GetCurPart() )
212  {
213  OnModify();
214  int block_cmd = block->GetCommand();
215 
216  if( block_cmd == BLOCK_MIRROR_Y)
218  else if( block_cmd == BLOCK_MIRROR_X)
220  else if( block_cmd == BLOCK_ROTATE )
222  }
223 
224  break;
225 
226  case BLOCK_ZOOM: // Window Zoom
227  Window_Zoom( *block );
228  break;
229 
230  case BLOCK_ABORT:
231  break;
232 
234  break;
235 
236  case BLOCK_DUPLICATE_AND_INCREMENT: // not used in Eeschema
237  case BLOCK_MOVE_EXACT: // not used in Eeschema
238  break;
239  }
240 
241  if( !nextCmd )
242  {
243  if( block->GetCommand() != BLOCK_SELECT_ITEMS_ONLY && GetCurPart() )
245 
246  block->SetState( STATE_NO_BLOCK );
247  block->SetCommand( BLOCK_IDLE );
248  GetScreen()->SetCurItem( NULL );
250  false );
251  m_canvas->Refresh( true );
252  }
253 
254  return nextCmd;
255 }
256 
257 
259 {
261  wxPoint pt;
262 
263  if( !m_canvas->IsMouseCaptured() )
264  {
265  DisplayError( this, wxT( "HandleBlockPLace : m_mouseCaptureCallback = NULL" ) );
266  }
267 
268  block->SetState( STATE_BLOCK_STOP );
269 
270  switch( block->GetCommand() )
271  {
272  case BLOCK_IDLE:
273  break;
274 
275  case BLOCK_DRAG: // Drag
276  case BLOCK_DRAG_ITEM:
277  case BLOCK_MOVE: // Move
278  case BLOCK_PRESELECT_MOVE: // Move with preselection list
279  block->ClearItemsList();
280 
281  if( GetCurPart() )
283 
284  pt = block->GetMoveVector();
285  pt.y *= -1;
286 
287  if( GetCurPart() )
288  GetCurPart()->MoveSelectedItems( pt );
289 
290  m_canvas->Refresh( true );
291  break;
292 
293  case BLOCK_DUPLICATE: // Duplicate
294  block->ClearItemsList();
295 
296  if( GetCurPart() )
298 
299  pt = block->GetMoveVector();
300  pt.y = -pt.y;
301 
302  if( GetCurPart() )
303  GetCurPart()->CopySelectedItems( pt );
304 
305  break;
306 
307  case BLOCK_PASTE: // Paste (recopy the last block saved)
308  block->ClearItemsList();
309 
310  if( GetCurPart() )
312 
313  pt = block->GetMoveVector();
314  pt.y = -pt.y;
315 
316  pasteClipboard( pt );
317  break;
318 
319  case BLOCK_ROTATE: // Invert by popup menu, from block move
320  case BLOCK_MIRROR_X: // Invert by popup menu, from block move
321  case BLOCK_MIRROR_Y: // Invert by popup menu, from block move
322  if( GetCurPart() )
324 
325  pt = block->Centre();
326  pt = GetNearestGridPosition( pt );
327  pt.y = -pt.y;
328 
329  if( GetCurPart() )
330  {
331  int block_cmd = block->GetCommand();
332 
333  if( block_cmd == BLOCK_MIRROR_Y)
335  else if( block_cmd == BLOCK_MIRROR_X)
337  else if( block_cmd == BLOCK_ROTATE )
339  }
340 
341  break;
342 
343  case BLOCK_ZOOM: // Handled by HandleBlockEnd
344  case BLOCK_DELETE:
345  case BLOCK_COPY:
346  case BLOCK_ABORT:
347  default:
348  break;
349  }
350 
351  OnModify();
352 
353  block->SetState( STATE_NO_BLOCK );
354  block->SetCommand( BLOCK_IDLE );
355  GetScreen()->SetCurItem( NULL );
356  m_canvas->EndMouseCapture( GetToolId(), m_canvas->GetCurrentCursor(), wxEmptyString, false );
357  m_canvas->Refresh( true );
358 }
359 
360 
362 {
364 
365  // Copy the clipboard contents to the screen block selector
366  // (only the copy, the new instances will be appended to the part once the items are placed)
367  block.GetItems().CopyList( m_clipboard.GetItems() );
368 
369  // Set the pate reference point
372 }
373 
374 
376 {
377  LIB_PART* part = GetCurPart();
378 
379  if( !part )
380  return;
381 
382  m_clipboard.ClearListAndDeleteItems(); // delete previous saved list, if exists
383  m_clipboard.SetLastCursorPosition( GetScreen()->m_BlockLocate.GetEnd() ); // store the reference point
384 
385  for( LIB_ITEM& item : part->GetDrawItems() )
386  {
387  // We *do not* copy fields because they are unique for the whole component
388  // so skip them (do not duplicate) if they are flagged selected.
389  if( item.Type() == LIB_FIELD_T )
390  item.ClearFlags( SELECTED );
391 
392  if( !item.IsSelected() )
393  continue;
394 
395  // Do not clear the 'selected' flag. It is required to have items drawn when they are pasted.
396  LIB_ITEM* copy = (LIB_ITEM*) item.Clone();
397 
398  // In list the wrapper is owner of the schematic item, we can use the UR_DELETED
399  // status for the picker because pickers with this status are owner of the picked item
400  // (or TODO ?: create a new status like UR_DUPLICATE)
401  ITEM_PICKER picker( copy, UR_DELETED );
402  m_clipboard.PushItem( picker );
403  }
404 }
405 
406 
408 {
409  LIB_PART* part = GetCurPart();
410 
411  if( !part || m_clipboard.GetCount() == 0 )
412  return;
413 
414  for( unsigned int i = 0; i < m_clipboard.GetCount(); i++ )
415  {
416  // Append a copy to the current part, so the clipboard buffer might be pasted multiple times
417  LIB_ITEM* item = (LIB_ITEM*) m_clipboard.GetItem( i )->Clone();
418  item->SetParent( part );
419  item->SetSelected();
420  part->AddDrawItem( item );
421  }
422 
423  GetCurPart()->MoveSelectedItems( aOffset );
424  OnModify();
425 }
426 
427 
428 /*
429  * Traces the outline of the search block structures
430  * The entire block follows the cursor
431  */
432 void DrawMovingBlockOutlines( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition,
433  bool aErase )
434 {
435  BASE_SCREEN* screen = aPanel->GetScreen();
436  BLOCK_SELECTOR* block = &screen->m_BlockLocate;
437 
438  LIB_EDIT_FRAME* parent = (LIB_EDIT_FRAME*) aPanel->GetParent();
439  wxASSERT( parent != NULL );
440 
441  LIB_PART* component = parent->GetCurPart();
442 
443  if( component == NULL )
444  return;
445 
446  int unit = parent->GetUnit();
447  int convert = parent->GetConvert();
448 
449  auto opts = PART_DRAW_OPTIONS::Default();
450  opts.draw_mode = g_XorMode;
451  opts.only_selected = true;
452 
453  if( aErase )
454  {
455  block->Draw( aPanel, aDC, block->GetMoveVector(), g_XorMode, block->GetColor() );
456  component->Draw( aPanel, aDC, block->GetMoveVector(), unit, convert, opts );
457 
458  for( unsigned ii = 0; ii < block->GetCount(); ii++ )
459  {
460  LIB_ITEM* libItem = (LIB_ITEM*) block->GetItem( ii );
461  libItem->Draw( aPanel, aDC, block->GetMoveVector(), g_GhostColor, g_XorMode, nullptr, opts.transform );
462  }
463  }
464 
465  // Repaint new view
466  block->SetMoveVector( parent->GetCrossHairPosition() - block->GetLastCursorPosition() );
467 
468  GRSetDrawMode( aDC, g_XorMode );
469  block->Draw( aPanel, aDC, block->GetMoveVector(), g_XorMode, block->GetColor() );
470 
471  for( unsigned ii = 0; ii < block->GetCount(); ii++ )
472  {
473  LIB_ITEM* libItem = (LIB_ITEM*) block->GetItem( ii );
474  libItem->Draw( aPanel, aDC, block->GetMoveVector(), g_GhostColor, g_XorMode, nullptr, opts.transform );
475  }
476 
477  component->Draw( aPanel, aDC, block->GetMoveVector(), unit, convert, opts );
478 }
GR_DRAWMODE g_XorMode
Definition: gr_basic.cpp:51
void Draw(EDA_DRAW_PANEL *aPanel, wxDC *aDc, const wxPoint &aOffset, int aMulti, int aConvert, const PART_DRAW_OPTIONS &aOpts)
Draw part.
BLOCK_SELECTOR m_BlockLocate
Block description for block commands.
virtual int BlockCommand(EDA_KEY aKey) override
Returns the block command (BLOCK_MOVE, BLOCK_DUPLICATE...) corresponding to the aKey (ALT...
void GRSetDrawMode(wxDC *DC, GR_DRAWMODE draw_mode)
Definition: gr_basic.cpp:296
static int m_convert
Definition: libeditframe.h:108
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
void Draw(EDA_DRAW_PANEL *aPanel, wxDC *aDC, const wxPoint &aOffset, GR_DRAWMODE aDrawMode, COLOR4D aColor)
This file is part of the common library.
virtual EDA_ITEM * Clone() const
Function Clone creates a duplicate of this item with linked list members set to NULL.
int GetCurrentCursor() const
Function GetCurrentCursor.
void SetMoveVector(const wxPoint &aMoveVector)
SCH_SCREEN * GetScreen() const override
Function GetScreen returns a pointer to a BASE_SCREEN or one of its derivatives.
void EndMouseCapture(int aId=-1, int aCursorId=-1, const wxString &aTitle=wxEmptyString, bool aCallEndFunc=true)
Function EndMouseCapture ends mouse a capture.
BLOCK_COMMAND_T
void OnModify()
Must be called after a schematic change in order to set the "modify" flag of the current screen...
EDA_ITEM * GetItem(unsigned aIndex)
BLOCK_STATE_T
void ClearSelectedItems()
Clears all the draw items marked by a block select.
void DrawAndSizingBlockOutlines(EDA_DRAW_PANEL *aPanel, wxDC *aDC, const wxPoint &aPosition, bool aErase)
Function DrawAndSizingBlockOutlines redraws the outlines of the block which shows the search area for...
void MoveCursorToCrossHair()
Function MoveCursorToCrossHair warps the cursor to the current cross hair position.
Definition: draw_panel.cpp:347
void copySelectedItems()
Copies items selected in the current part to the internal clipboard.
#define GR_KB_ALT
Definition: common.h:64
void CallEndMouseCapture(wxDC *aDC)
Function CallEndMouseCapture calls the end mouse capture callback.
virtual bool HandleBlockEnd(wxDC *DC) override
Performs a block end command.
#define GR_KEY_INVALID
Definition: common.h:68
Class LIB_ITEM is the base class for drawable items used by schematic library components.
Definition: lib_draw_item.h:67
void MirrorSelectedItemsH(const wxPoint &aCenter)
Horizontally (X axis) mirror selected draw items about a point.
void ClearItemsList()
Function ClearItemsList clear only the list of EDA_ITEM pointers, it does NOT delete the EDA_ITEM obj...
void MirrorSelectedItemsV(const wxPoint &aCenter)
Vertically (Y axis) mirror selected draw items about a point.
void AddDrawItem(LIB_ITEM *aItem)
Add a new draw aItem to the draw object list.
void pasteClipboard(const wxPoint &aOffset)
Pastes items from the internal clipboard to the current part.
void SetState(BLOCK_STATE_T aState)
#define SELECTED
Definition: base_struct.h:134
void CopyList(const PICKED_ITEMS_LIST &aSource)
Function CopyList copies all data from aSource to the list.
LIB_PART * GetCurPart() const
Return the current part being edited or NULL if none selected.
Definition: libeditframe.h:158
void ClearListAndDeleteItems()
Function ClearListAndDeleteItems deletes only the list of EDA_ITEM * pointers, AND the data printed b...
COLOR4D GetColor() const
void SetSelected()
Definition: base_struct.h:241
void SetParent(EDA_ITEM *aParent)
Definition: base_struct.h:227
#define GR_KB_SHIFT
Definition: common.h:65
bool IsMouseCaptured() const
void CopySelectedItems(const wxPoint &aOffset)
Make a copy of the selected draw items marked by a block select.
LIB_ITEMS_CONTAINER & GetDrawItems()
Return a reference to the draw item list.
void RotateSelectedItems(const wxPoint &aCenter)
Rotate CCW selected draw items about a point.
Class BASE_SCREEN handles how to draw a screen (a board, a schematic ...)
void CallMouseCapture(wxDC *aDC, const wxPoint &aPosition, bool aErase)
Function CallMouseCapture calls the mouse capture callback.
Class LIB_PART defines a library part object.
uint32_t EDA_KEY
Definition: common.h:51
EDA_DRAW_FRAME * GetParent() const
Definition: draw_panel.cpp:174
int GetBottom() const
wxPoint Centre() const
static PART_DRAW_OPTIONS Default()
int GetRight() const
#define GR_KB_SHIFTCTRL
Definition: common.h:66
void SetMouseCaptureCallback(MOUSE_CAPTURE_CALLBACK aMouseCaptureCallback)
Definition: solve.cpp:178
void AbortBlockCurrentCommand(EDA_DRAW_PANEL *aPanel, wxDC *aDC)
Function AbortBlockCurrentCommand cancels the current block operation.
#define GR_KEY_NONE
Definition: common.h:69
wxPoint GetLastCursorPosition() const
EDA_DRAW_PANEL * m_canvas
The area to draw on.
Definition: draw_frame.h:93
wxPoint GetNearestGridPosition(const wxPoint &aPosition, wxRealPoint *aGridSize=NULL) const
Function GetNearestGridPosition returns the nearest aGridSize location to aPosition.
The symbol library editor main window.
Definition: libeditframe.h:58
BLOCK_SELECTOR m_clipboard
Clipboard buffer storing LIB_ITEMs
Definition: libeditframe.h:754
int SelectItems(EDA_RECT &aRect, int aUnit, int aConvert, bool aEditPinByPin)
Checks all draw objects of part to see if they are with block.
virtual void Draw(EDA_DRAW_PANEL *aPanel, wxDC *aDC, const wxPoint &aOffset, COLOR4D aColor, GR_DRAWMODE aDrawMode, void *aData, const TRANSFORM &aTransform)
Draw an item.
static int m_unit
Definition: libeditframe.h:104
BLOCK_STATE_T GetState() const
virtual void HandleBlockPlace(wxDC *DC) override
Handles the block place command.
int GetToolId() const
Definition: draw_frame.h:471
#define MOUSE_MIDDLE
Definition: common.h:67
void SetCurItem(SCH_ITEM *aItem)
Sets the currently selected object, m_CurrentItem.
BASE_SCREEN * GetScreen()
Definition: draw_panel.cpp:187
void InitBlockPasteInfos() override
PICKED_ITEMS_LIST & GetItems()
void MoveSelectedItems(const wxPoint &aOffset)
Move the selected draw items marked by a block select.
void Window_Zoom(EDA_RECT &Rect)
Compute the zoom factor and the new draw offset to draw the selected area (Rect) in full window scree...
Definition: zoom.cpp:103
static void DrawMovingBlockOutlines(EDA_DRAW_PANEL *aPanel, wxDC *aDC, const wxPoint &aPosition, bool aErase)
BLOCK_COMMAND_T GetCommand() const
#define EDA_KEY_C
Definition: common.h:59
Definition for part library class.
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 SetCrossHairPosition(const wxPoint &aPosition, bool aSnapToGrid=true)
Function SetCrossHairPosition sets the screen cross hair position to aPosition in logical (drawing) u...
void DeleteSelectedItems()
Deletes the select draw items marked by a block select.
void SetLastCursorPosition(const wxPoint &aPosition)
Function SetLastCursorPosition sets the last cursor position to aPosition.
#define GR_KB_CTRL
Definition: common.h:63
bool m_editPinsPerPartOrConvert
Set to true to not synchronize pins at the same position when editing components with multiple parts ...
Definition: libeditframe.h:86
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:73
wxPoint GetCrossHairPosition(bool aInvertY=false) const
Function GetCrossHairPosition return the current cross hair position in logical (drawing) coordinates...
unsigned GetCount() const
Definition of class LIB_EDIT_FRAME.
COLOR4D g_GhostColor
Draw color for moving objects.
Definition: common.cpp:57
void SetCommand(BLOCK_COMMAND_T aCommand)
wxPoint GetMoveVector() const
void PushItem(ITEM_PICKER &aItem)
Function PushItem adds aItem to the list of items.
void SaveCopyInUndoList(EDA_ITEM *ItemToCopy)
Create a copy of the current component, and save it in the undo list.