KiCad PCB EDA Suite
edit_tool.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) 2013-2017 CERN
5  * @author Maciej Suminski <maciej.suminski@cern.ch>
6  * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
7  * Copyright (C) 2017 KiCad Developers, see CHANGELOG.TXT for contributors.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, you may find one here:
21  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22  * or you may search the http://www.gnu.org website for the version 2 license,
23  * or you may write to the Free Software Foundation, Inc.,
24  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25  */
26 
27 #include <limits>
28 
29 #include <class_board.h>
30 #include <class_module.h>
31 #include <class_edge_mod.h>
32 #include <class_zone.h>
33 #include <collectors.h>
34 #include <pcb_edit_frame.h>
35 #include <kiway.h>
36 #include <class_draw_panel_gal.h>
37 #include <footprint_edit_frame.h>
38 #include <array_creator.h>
39 #include <pcbnew_id.h>
40 #include <status_popup.h>
41 #include <tool/tool_manager.h>
42 #include <view/view_controls.h>
43 #include <view/view.h>
46 #include <confirm.h>
47 #include <bitmaps.h>
48 #include <hotkeys.h>
49 
50 #include <cassert>
51 #include <functional>
52 using namespace std::placeholders;
53 
54 #include "pcb_actions.h"
55 #include "selection_tool.h"
56 #include "edit_tool.h"
57 #include "picker_tool.h"
58 #include "grid_helper.h"
59 #include "kicad_clipboard.h"
60 #include "pcbnew_control.h"
61 
62 #include <router/router_tool.h>
63 
67 
68 #include <tools/tool_event_utils.h>
69 
71 
72 #include <board_commit.h>
73 
74 
75 // Edit tool actions
76 TOOL_ACTION PCB_ACTIONS::editFootprintInFpEditor( "pcbnew.InteractiveEdit.editFootprintInFpEditor",
78  _( "Open in Footprint Editor" ),
79  _( "Opens the selected footprint in the Footprint Editor" ),
80  module_editor_xpm );
81 
82 TOOL_ACTION PCB_ACTIONS::editActivate( "pcbnew.InteractiveEdit",
83  AS_GLOBAL, 0,
84  _( "Edit Activate" ), "", move_xpm, AF_ACTIVATE );
85 
86 TOOL_ACTION PCB_ACTIONS::move( "pcbnew.InteractiveEdit.move",
88  _( "Move" ), _( "Moves the selected item(s)" ), move_xpm, AF_ACTIVATE );
89 
90 TOOL_ACTION PCB_ACTIONS::duplicate( "pcbnew.InteractiveEdit.duplicate",
92  _( "Duplicate" ), _( "Duplicates the selected item(s)" ), duplicate_xpm );
93 
94 TOOL_ACTION PCB_ACTIONS::duplicateIncrement( "pcbnew.InteractiveEdit.duplicateIncrementPads",
96  _( "Duplicate" ), _( "Duplicates the selected item(s), incrementing pad numbers" ) );
97 
98 TOOL_ACTION PCB_ACTIONS::moveExact( "pcbnew.InteractiveEdit.moveExact",
100  _( "Move Exactly..." ), _( "Moves the selected item(s) by an exact amount" ),
101  move_exactly_xpm );
102 
103 TOOL_ACTION PCB_ACTIONS::createArray( "pcbnew.InteractiveEdit.createArray",
105  _( "Create Array..." ), _( "Create array" ), array_xpm, AF_ACTIVATE );
106 
107 TOOL_ACTION PCB_ACTIONS::rotateCw( "pcbnew.InteractiveEdit.rotateCw",
109  _( "Rotate Clockwise" ), _( "Rotates selected item(s) clockwise" ),
110  rotate_cw_xpm, AF_NONE, (void*) -1 );
111 
112 TOOL_ACTION PCB_ACTIONS::rotateCcw( "pcbnew.InteractiveEdit.rotateCcw",
114  _( "Rotate Counterclockwise" ), _( "Rotates selected item(s) counterclockwise" ),
115  rotate_ccw_xpm, AF_NONE, (void*) 1 );
116 
117 TOOL_ACTION PCB_ACTIONS::flip( "pcbnew.InteractiveEdit.flip",
119  _( "Flip" ), _( "Flips selected item(s)" ), swap_layer_xpm );
120 
121 TOOL_ACTION PCB_ACTIONS::mirror( "pcbnew.InteractiveEdit.mirror",
122  AS_GLOBAL, 0,
123  _( "Mirror" ), _( "Mirrors selected item" ), mirror_h_xpm );
124 
125 TOOL_ACTION PCB_ACTIONS::remove( "pcbnew.InteractiveEdit.remove",
127  _( "Delete" ), _( "Deletes selected item(s)" ), delete_xpm,
128  AF_NONE, (void*) REMOVE_FLAGS::NORMAL );
129 
130 TOOL_ACTION PCB_ACTIONS::removeAlt( "pcbnew.InteractiveEdit.removeAlt",
132  _( "Delete (Alternative)" ), _( "Deletes selected item(s)" ), delete_xpm,
133  AF_NONE, (void*) REMOVE_FLAGS::ALT );
134 
135 TOOL_ACTION PCB_ACTIONS::updateFootprints( "pcbnew.InteractiveEdit.updateFootprints",
136  AS_GLOBAL, 0,
137  _( "Update Footprint..." ), _( "Update the footprint from the library" ),
138  reload_xpm );
139 
140 TOOL_ACTION PCB_ACTIONS::exchangeFootprints( "pcbnew.InteractiveEdit.ExchangeFootprints",
141  AS_GLOBAL, 0,
142  _( "Change Footprint..." ), _( "Assign a different footprint from the library" ),
143  exchange_xpm );
144 
145 TOOL_ACTION PCB_ACTIONS::properties( "pcbnew.InteractiveEdit.properties",
147  _( "Properties..." ), _( "Displays item properties dialog" ), config_xpm );
148 
149 TOOL_ACTION PCB_ACTIONS::selectionModified( "pcbnew.InteractiveEdit.ModifiedSelection",
150  AS_GLOBAL, 0,
151  "", "", nullptr, AF_NOTIFY );
152 
153 TOOL_ACTION PCB_ACTIONS::measureTool( "pcbnew.InteractiveEdit.measureTool",
155  _( "Measuring Tool" ), _( "Interactively measure distance between points" ),
156  nullptr, AF_ACTIVATE );
157 
158 TOOL_ACTION PCB_ACTIONS::copyToClipboard( "pcbnew.InteractiveEdit.CopyToClipboard",
159  AS_GLOBAL, 0, // do not define a hotkey and let TranslateLegacyId() handle the event
160  _( "Copy" ), _( "Copy selected content to clipboard" ),
161  copy_xpm );
162 
163 TOOL_ACTION PCB_ACTIONS::cutToClipboard( "pcbnew.InteractiveEdit.CutToClipboard",
164  AS_GLOBAL, 0, // do not define a hotkey and let TranslateLegacyId() handle the event
165  _( "Cut" ), _( "Cut selected content to clipboard" ),
166  cut_xpm );
167 
168 TOOL_ACTION PCB_ACTIONS::updateUnits( "pcbnew.InteractiveEdit.updateUnits",
169  AS_GLOBAL, 0,
170  "", "" );
171 
172 
173 void EditToolSelectionFilter( GENERAL_COLLECTOR& aCollector, int aFlags )
174 {
175  // Iterate from the back so we don't have to worry about removals.
176  for( int i = aCollector.GetCount() - 1; i >= 0; --i )
177  {
178  BOARD_ITEM* item = aCollector[ i ];
179 
180  if( ( aFlags & EXCLUDE_LOCKED ) && item->IsLocked() )
181  {
182  aCollector.Remove( item );
183  }
184  else if( item->Type() == PCB_PAD_T )
185  {
186  MODULE* mod = static_cast<MODULE*>( item->GetParent() );
187 
188  // case 1: handle locking
189  if( ( aFlags & EXCLUDE_LOCKED ) && mod && mod->IsLocked() )
190  {
191  aCollector.Remove( item );
192  }
193  else if( ( aFlags & EXCLUDE_LOCKED_PADS ) && mod && mod->PadsLocked() )
194  {
195  // Pad locking is considerably "softer" than item locking
196  aCollector.Remove( item );
197 
198  if( !mod->IsLocked() && !aCollector.HasItem( mod ) )
199  aCollector.Append( mod );
200  }
201 
202  // case 2: selection contains both the module and its pads - remove the pads
203  if( mod && aCollector.HasItem( mod ) )
204  aCollector.Remove( item );
205  }
206  else if( ( aFlags & EXCLUDE_TRANSIENTS ) && item->Type() == PCB_MARKER_T )
207  {
208  aCollector.Remove( item );
209  }
210  }
211 }
212 
213 
215  PCB_TOOL( "pcbnew.InteractiveEdit" ), m_selectionTool( NULL ),
216  m_dragging( false )
217 {
218 }
219 
220 
222 {
223  m_dragging = false;
224 
225  if( aReason != RUN )
226  m_commit.reset( new BOARD_COMMIT( this ) );
227 }
228 
229 
231 {
232  // Find the selection tool, so they can cooperate
233  m_selectionTool = static_cast<SELECTION_TOOL*>( m_toolMgr->FindTool( "pcbnew.InteractiveSelection" ) );
234 
235  if( !m_selectionTool )
236  {
237  DisplayError( NULL, wxT( "pcbnew.InteractiveSelection tool is not available" ) );
238  return false;
239  }
240 
241  auto editingModuleCondition = [ this ] ( const SELECTION& aSelection ) {
242  return m_editModules;
243  };
244 
245  auto singleModuleCondition = SELECTION_CONDITIONS::OnlyType( PCB_MODULE_T )
247 
248  auto noActiveToolCondition = [ this ] ( const SELECTION& aSelection ) {
249  return ( frame()->GetToolId() == ID_NO_TOOL_SELECTED );
250  };
251 
252  // Add context menu entries that are displayed when selection tool is active
254 
264 
265 
270 
271 
275  // Selection tool handles the context menu for some other tools, such as the Picker.
276  // Don't add things like Paste when another tool is active.
277  menu.AddItem( PCB_ACTIONS::pasteFromClipboard, noActiveToolCondition );
278 
279  // Mirror only available in modedit
280  menu.AddSeparator( editingModuleCondition && SELECTION_CONDITIONS::NotEmpty );
281  menu.AddItem( PCB_ACTIONS::mirror, editingModuleCondition && SELECTION_CONDITIONS::NotEmpty );
284 
285  // Footprint actions
286  menu.AddSeparator( singleModuleCondition );
287  menu.AddItem( PCB_ACTIONS::editFootprintInFpEditor, singleModuleCondition );
288  menu.AddItem( PCB_ACTIONS::updateFootprints, singleModuleCondition );
289  menu.AddItem( PCB_ACTIONS::exchangeFootprints, singleModuleCondition );
290 
291  return true;
292 }
293 
294 
295 bool EDIT_TOOL::invokeInlineRouter( int aDragMode )
296 {
297  auto theRouter = static_cast<ROUTER_TOOL*>( m_toolMgr->FindTool( "pcbnew.InteractiveRouter" ) );
298 
299  if( !theRouter )
300  return false;
301 
302  // make sure we don't accidentally invoke inline routing mode while the router is already active!
303  if( theRouter->IsToolActive() )
304  return false;
305 
306  if( theRouter->CanInlineDrag() )
307  {
309  return true;
310  }
311 
312  return false;
313 }
314 
315 
317 {
318  auto theRouter = static_cast<ROUTER_TOOL*>( m_toolMgr->FindTool( "pcbnew.InteractiveRouter" ) );
319 
320  return theRouter ? theRouter->Router()->Settings().InlineDragEnabled() : false;
321 }
322 
323 
324 int EDIT_TOOL::Drag( const TOOL_EVENT& aEvent )
325 {
326  int mode = PNS::DM_ANY;
327 
328  if( aEvent.IsAction( &PCB_ACTIONS::dragFreeAngle ) )
329  mode |= PNS::DM_FREE_ANGLE;
330 
331  invokeInlineRouter( mode );
332 
333  return 0;
334 }
335 
336 int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
337 {
339  PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();
340  VECTOR2I originalCursorPos = controls->GetCursorPosition();
341 
342  // Be sure that there is at least one item that we can modify. If nothing was selected before,
343  // try looking for the stuff under mouse cursor (i.e. Kicad old-style hover selection)
345  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector )
347 
348  if( m_dragging || selection.Empty() )
349  return 0;
350 
351  LSET item_layers = static_cast<BOARD_ITEM*>( selection.Front() )->GetLayerSet();
352  bool unselect = selection.IsHover(); //N.B. This must be saved before the re-selection below
353 
354  // Filter out locked pads here
355  // We cannot do this in the selection filter as we need the pad layers
356  // when it is the curr_item.
358  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector )
360 
361  if( selection.Empty() )
362  return 0;
363 
364  Activate();
365  controls->ShowCursor( true );
366  controls->SetAutoPan( true );
367 
368  auto curr_item = static_cast<BOARD_ITEM*>( selection.Front() );
369  bool restore_state = false;
370  VECTOR2I totalMovement;
371  GRID_HELPER grid( editFrame );
372  OPT_TOOL_EVENT evt = aEvent;
373  VECTOR2I prevPos;
374 
375  // Main loop: keep receiving events
376  do
377  {
378  grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
379  grid.SetUseGrid( !evt->Modifier( MD_ALT ) );
380  controls->SetSnapping( !evt->Modifier( MD_ALT ) );
381 
382  if( evt->IsAction( &PCB_ACTIONS::editActivate ) ||
383  evt->IsAction( &PCB_ACTIONS::move ) ||
384  evt->IsMotion() || evt->IsDrag( BUT_LEFT ) )
385  {
386  if( m_dragging && evt->Category() == TC_MOUSE )
387  {
388  m_cursor = grid.BestSnapAnchor( controls->GetMousePosition(), item_layers );
389  controls->ForceCursorPosition(true, m_cursor );
390  VECTOR2I movement( m_cursor - prevPos );
392 
393  totalMovement += movement;
394  prevPos = m_cursor;
395 
396  // Drag items to the current cursor position
397  for( auto item : selection )
398  {
399  // Don't double move footprint pads, fields, etc.
400  if( item->GetParent() && item->GetParent()->IsSelected() )
401  continue;
402 
403  static_cast<BOARD_ITEM*>( item )->Move( movement );
404  }
405 
406  frame()->UpdateMsgPanel();
407  }
408  else if( !m_dragging ) // Prepare to start dragging
409  {
410  bool invokedRouter = false;
411 
412  if ( !evt->IsAction( &PCB_ACTIONS::move ) && isInteractiveDragEnabled() )
413  invokedRouter = invokeInlineRouter( PNS::DM_ANY );
414 
415  if( !invokedRouter )
416  {
417  // deal with locked items (override lock or abort the operation)
419 
420  if( lockFlags == SELECTION_LOCKED )
421  break;
422 
423  // When editing modules, all items have the same parent
424  if( EditingModules() )
425  {
426  m_commit->Modify( selection.Front() );
427  }
428  else
429  {
430  // Save items, so changes can be undone
431  for( auto item : selection )
432  {
433  // Don't double move footprint pads, fields, etc.
434  if( item->GetParent() && item->GetParent()->IsSelected() )
435  continue;
436 
437  m_commit->Modify( item );
438  }
439  }
440 
441  for( auto item : selection )
442  {
443  item->SetFlags( IS_DRAGGED ); //todo: flags structure rework
444 
445  if( auto module = dyn_cast<MODULE*>( item ) )
446  module->RunOnChildren( [&] ( BOARD_ITEM* bitem )
447  { bitem->SetFlags( IS_DRAGGED ); } );
448  }
449 
450  editFrame->UndoRedoBlock( true );
451  m_cursor = controls->GetCursorPosition();
452 
453  if ( selection.HasReferencePoint() )
454  {
455  // start moving with the reference point attached to the cursor
456  grid.SetAuxAxes( false );
457 
458  auto delta = m_cursor - selection.GetReferencePoint();
459 
460  // Drag items to the current cursor position
461  for( auto item : selection )
462  {
463  // Don't double move footprint pads, fields, etc.
464  if( item->GetParent() && item->GetParent()->IsSelected() )
465  continue;
466 
467  static_cast<BOARD_ITEM*>( item )->Move( delta );
468  }
469 
470  selection.SetReferencePoint( m_cursor );
471  }
472  else if( selection.Size() == 1 )
473  {
474  // Set the current cursor position to the first dragged item origin, so the
475  // movement vector could be computed later
476  updateModificationPoint( selection );
477  m_cursor = grid.BestDragOrigin( originalCursorPos, curr_item );
478  grid.SetAuxAxes( true, m_cursor );
479  }
480  else
481  {
482  updateModificationPoint( selection );
483  m_cursor = grid.Align( m_cursor );
484  }
485 
486  controls->SetCursorPosition( m_cursor, false );
487 
488  prevPos = m_cursor;
489  controls->SetAutoPan( true );
490  m_dragging = true;
491  }
492  }
493 
495  }
496 
497  else if( evt->IsCancel() || evt->IsActivate() )
498  {
499  restore_state = true; // Canceling the tool means that items have to be restored
500  break; // Finish
501  }
502 
503  else if( evt->Action() == TA_UNDO_REDO_PRE )
504  {
505  unselect = true;
506  break;
507  }
508 
509  // Dispatch TOOL_ACTIONs
510  else if( evt->Category() == TC_COMMAND )
511  {
512  if( evt->IsAction( &PCB_ACTIONS::remove ) )
513  {
514  // exit the loop, as there is no further processing for removed items
515  break;
516  }
517  else if( evt->IsAction( &PCB_ACTIONS::duplicate ) )
518  {
519  // On duplicate, stop moving this item
520  // The duplicate tool should then select the new item and start
521  // a new move procedure
522  break;
523  }
524  else if( evt->IsAction( &PCB_ACTIONS::moveExact ) )
525  {
526  // Can't do this, because the selection will then contain
527  // stale pointers and it will all go horribly wrong...
528  //editFrame->RestoreCopyFromUndoList( dummy );
529  //
530  // So, instead, reset the position manually
531  for( auto item : selection )
532  {
533  BOARD_ITEM* i = static_cast<BOARD_ITEM*>( item );
534  auto delta = VECTOR2I( i->GetPosition() ) - totalMovement;
535  i->SetPosition( wxPoint( delta.x, delta.y ) );
536 
537  // And what about flipping and rotation?
538  // for now, they won't be undone, but maybe that is how
539  // it should be, so you can flip and move exact in the
540  // same action?
541  }
542 
543  // This causes a double event, so we will get the dialogue
544  // correctly, somehow - why does Rotate not?
545  //MoveExact( aEvent );
546  break; // exit the loop - we move exactly, so we have finished moving
547  }
548  }
549 
550  else if( evt->IsMouseUp( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) )
551  {
552  break; // Finish
553  }
554  } while( ( evt = Wait() ) ); //Should be assignment not equality test
555 
556  controls->ForceCursorPosition( false );
557  controls->ShowCursor( false );
558  controls->SetSnapping( false );
559  controls->SetAutoPan( false );
560 
561  m_dragging = false;
562  editFrame->UndoRedoBlock( false );
563 
564  // Discard reference point when selection is "dropped" onto the board (ie: not dragging anymore)
566 
567  if( unselect || restore_state )
569 
570  for( auto item : selection )
571  {
572  item->ClearFlags( IS_DRAGGED ); //todo: flags structure rework
573 
574  if( auto module = dyn_cast<MODULE*>( item ) )
575  module->RunOnChildren( [&] ( BOARD_ITEM* bitem )
576  { bitem->SetFlags( IS_DRAGGED ); } );
577  }
578 
579  if( restore_state )
580  m_commit->Revert();
581  else
582  m_commit->Push( _( "Drag" ) );
583 
584  return 0;
585 }
586 
588 {
589  if ( selection.Size() == 1 && frame()->Settings().m_editActionChangesTrackWidth )
590  {
591  auto item = static_cast<BOARD_ITEM *>( selection[0] );
592 
593  m_commit->Modify( item );
594 
595  if( auto via = dyn_cast<VIA*>( item ) )
596  {
597  int new_width, new_drill;
598 
599  if( via->GetViaType() == VIA_MICROVIA )
600  {
601  auto net = via->GetNet();
602 
603  new_width = net->GetMicroViaSize();
604  new_drill = net->GetMicroViaDrillSize();
605  }
606  else
607  {
608  new_width = board()->GetDesignSettings().GetCurrentViaSize();
609  new_drill = board()->GetDesignSettings().GetCurrentViaDrill();
610  }
611 
612  via->SetDrill( new_drill );
613  via->SetWidth( new_width );
614  }
615  else if ( auto track = dyn_cast<TRACK*>( item ) )
616  {
617  int new_width = board()->GetDesignSettings().GetCurrentTrackWidth();
618  track->SetWidth( new_width );
619  }
620 
621  m_commit->Push( _("Edit track width/via size") );
622  return true;
623  }
624 
625  return false;
626 }
627 
628 int EDIT_TOOL::Properties( const TOOL_EVENT& aEvent )
629 {
630  PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();
631 
633  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector )
634  { EditToolSelectionFilter( aCollector, EXCLUDE_TRANSIENTS ); } );
635 
636  // Tracks & vias are treated in a special way:
638  {
639  if ( !changeTrackWidthOnClick( selection ) )
640  {
641  DIALOG_TRACK_VIA_PROPERTIES dlg( editFrame, selection, *m_commit );
642  dlg.ShowQuasiModal(); // QuasiModal required for NET_SELECTOR
643  }
644  }
645  else if( selection.Size() == 1 ) // Properties are displayed when there is only one item selected
646  {
647  // Display properties dialog
648  BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.Front() );
649 
650  // Do not handle undo buffer, it is done by the properties dialogs @todo LEGACY
651  // Display properties dialog provided by the legacy canvas frame
652  editFrame->OnEditItemRequest( NULL, item );
653 
654  // Notify other tools of the changes
656  }
657 
658  if( selection.IsHover() )
659  {
661 
662  // Notify other tools of the changes -- This updates the visual ratsnest
664  }
665 
666  return 0;
667 }
668 
669 
670 int EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
671 {
672  PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();
673 
675  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector )
677 
678  if( selection.Empty() )
679  return 0;
680 
681  updateModificationPoint( selection );
682  const int rotateAngle = TOOL_EVT_UTILS::GetEventRotationAngle( *editFrame, aEvent );
683 
684  // When editing modules, all items have the same parent
685  if( EditingModules() )
686  {
687  m_commit->Modify( selection.Front() );
688  }
689 
690  for( auto item : selection )
691  {
692  if( !item->IsNew() && !EditingModules() )
693  m_commit->Modify( item );
694 
695  static_cast<BOARD_ITEM*>( item )->Rotate( selection.GetReferencePoint(), rotateAngle );
696  }
697 
698  if( !m_dragging )
699  m_commit->Push( _( "Rotate" ) );
700 
701  if( selection.IsHover() && !m_dragging )
703 
705 
706  return 0;
707 }
708 
709 
713 static wxPoint mirrorPointX( const wxPoint& aPoint, const wxPoint& aMirrorPoint )
714 {
715  wxPoint mirrored = aPoint;
716 
717  mirrored.x -= aMirrorPoint.x;
718  mirrored.x = -mirrored.x;
719  mirrored.x += aMirrorPoint.x;
720 
721  return mirrored;
722 }
723 
724 
728 static void mirrorPadX( D_PAD& aPad, const wxPoint& aMirrorPoint )
729 {
730  wxPoint tmpPt = mirrorPointX( aPad.GetPosition(), aMirrorPoint );
731 
732  aPad.SetPosition( tmpPt );
733 
734  aPad.SetX0( aPad.GetPosition().x );
735 
736  tmpPt = aPad.GetOffset();
737  tmpPt.x = -tmpPt.x;
738  aPad.SetOffset( tmpPt );
739 
740  auto tmpz = aPad.GetDelta();
741  tmpz.x = -tmpz.x;
742  aPad.SetDelta( tmpz );
743 
744  aPad.SetOrientation( -aPad.GetOrientation() );
745 }
746 
747 
748 int EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent )
749 {
751  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector )
753 
754  if( selection.Empty() )
755  return 0;
756 
758  auto refPoint = selection.GetReferencePoint();
759  wxPoint mirrorPoint( refPoint.x, refPoint.y );
760 
761  // When editing modules, all items have the same parent
762  if( EditingModules() )
763  {
764  m_commit->Modify( selection.Front() );
765  }
766 
767  for( auto item : selection )
768  {
769  // only modify items we can mirror
770  switch( item->Type() )
771  {
772  case PCB_MODULE_EDGE_T:
773  case PCB_MODULE_TEXT_T:
774  case PCB_PAD_T:
775  // Only create undo entry for items on the board
776  if( !item->IsNew() && !EditingModules() )
777  m_commit->Modify( item );
778 
779  break;
780  default:
781  continue;
782  }
783 
784  // modify each object as necessary
785  switch( item->Type() )
786  {
787  case PCB_MODULE_EDGE_T:
788  {
789  auto& edge = static_cast<EDGE_MODULE&>( *item );
790  edge.Mirror( mirrorPoint, false );
791  break;
792  }
793 
794  case PCB_MODULE_TEXT_T:
795  {
796  auto& modText = static_cast<TEXTE_MODULE&>( *item );
797  modText.Mirror( mirrorPoint, false );
798  break;
799  }
800 
801  case PCB_PAD_T:
802  {
803  auto& pad = static_cast<D_PAD&>( *item );
804  mirrorPadX( pad, mirrorPoint );
805  break;
806  }
807 
808  default:
809  // it's likely the commit object is wrong if you get here
810  assert( false );
811  break;
812  }
813  }
814 
815  if( !m_dragging )
816  m_commit->Push( _( "Mirror" ) );
817 
818  if( selection.IsHover() && !m_dragging )
820 
822 
823  return 0;
824 }
825 
826 
827 int EDIT_TOOL::Flip( const TOOL_EVENT& aEvent )
828 {
830  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector )
832 
833  if( selection.Empty() )
834  return 0;
835 
837  auto modPoint = selection.GetReferencePoint();
838 
839  // When editing modules, all items have the same parent
840  if( EditingModules() )
841  {
842  m_commit->Modify( selection.Front() );
843  }
844 
845  for( auto item : selection )
846  {
847  if( !item->IsNew() && !EditingModules() )
848  m_commit->Modify( item );
849 
850  static_cast<BOARD_ITEM*>( item )->Flip( modPoint );
851  }
852 
853  if( !m_dragging )
854  m_commit->Push( _( "Flip" ) );
855 
856  if( selection.IsHover() && !m_dragging )
858 
860 
861  return 0;
862 }
863 
864 
865 int EDIT_TOOL::Remove( const TOOL_EVENT& aEvent )
866 {
867  ROUTER_TOOL* routerTool = static_cast<ROUTER_TOOL*>
868  ( m_toolMgr->FindTool( "pcbnew.InteractiveRouter" ) );
869 
870  // Do not delete items while actively routing.
871  if( routerTool && routerTool->Router() && routerTool->Router()->RoutingInProgress() )
872  return 0;
873 
874  // get a copy instead of reference (as we're going to clear the selection before removing items)
875  auto selectionCopy = m_selectionTool->RequestSelection(
876  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector )
878 
879  // is this "alternative" remove?
880  const bool isAlt = aEvent.Parameter<intptr_t>() == (int) PCB_ACTIONS::REMOVE_FLAGS::ALT;
881 
882  // in "alternative" mode, deletion is not just a simple list of selected items,
883  // it removes whole tracks, not just segments
884  if( isAlt && selectionCopy.IsHover()
885  && ( selectionCopy.HasType( PCB_TRACE_T ) || selectionCopy.HasType( PCB_VIA_T ) ) )
886  {
888  selectionCopy = m_selectionTool->GetSelection();
889  }
890 
891  if( selectionCopy.Empty() )
892  return 0;
893 
894  // As we are about to remove items, they have to be removed from the selection first
896 
897  for( auto item : selectionCopy )
898  {
899  if( m_editModules )
900  {
901  m_commit->Remove( item );
902  continue;
903  }
904 
905  switch( item->Type() )
906  {
907  case PCB_MODULE_TEXT_T:
908  {
909  auto text = static_cast<TEXTE_MODULE*>( item );
910  auto parent = static_cast<MODULE*>( item->GetParent() );
911 
912  if( text->GetType() == TEXTE_MODULE::TEXT_is_DIVERS )
913  {
914  m_commit->Modify( text );
915  getView()->Remove( text );
916  parent->Remove( text );
917  }
918  }
919  break;
920 
921  default:
922  m_commit->Remove( item );
923  break;
924  }
925  }
926 
927  m_commit->Push( _( "Delete" ) );
928 
929  return 0;
930 }
931 
932 
933 int EDIT_TOOL::MoveExact( const TOOL_EVENT& aEvent )
934 {
936  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector )
938 
939  if( selection.Empty() )
940  return 0;
941 
942  PCB_BASE_FRAME* editFrame = getEditFrame<PCB_BASE_FRAME>();
943  wxPoint translation;
944  double rotation;
945  ROTATION_ANCHOR rotationAnchor = selection.Size() > 1 ? ROTATE_AROUND_SEL_CENTER
947 
948  DIALOG_MOVE_EXACT dialog( editFrame, translation, rotation, rotationAnchor );
949  int ret = dialog.ShowModal();
950 
951  if( ret == wxID_OK )
952  {
954  wxPoint selCenter( rp.x, rp.y );
955 
956  // Make sure the rotation is from the right reference point
957  selCenter += translation;
958 
959  // When editing modules, all items have the same parent
960  if( EditingModules() )
961  {
962  m_commit->Modify( selection.Front() );
963  }
964 
965  for( auto selItem : selection )
966  {
967  BOARD_ITEM* item = dynamic_cast<BOARD_ITEM*>( selItem );
968 
969  if( !item->IsNew() && !EditingModules() )
970  m_commit->Modify( item );
971 
972  item->Move( translation );
973 
974  switch( rotationAnchor )
975  {
977  item->Rotate( item->GetPosition(), rotation );
978  break;
980  item->Rotate( selCenter, rotation );
981  break;
983  item->Rotate( editFrame->GetScreen()->m_O_Curseur, rotation );
984  break;
986  item->Rotate( editFrame->GetAuxOrigin(), rotation );
987  break;
988  }
989 
990  if( !m_dragging )
991  getView()->Update( item );
992  }
993 
994  m_commit->Push( _( "Move exact" ) );
995 
996  if( selection.IsHover() )
998 
1000  }
1001 
1002  return 0;
1003 }
1004 
1005 
1006 int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent )
1007 {
1008  bool increment = aEvent.IsAction( &PCB_ACTIONS::duplicateIncrement );
1009 
1010  // Be sure that there is at least one item that we can modify
1012  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector )
1014 
1015  if( selection.Empty() )
1016  return 0;
1017 
1018  // we have a selection to work on now, so start the tool process
1019  PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();
1020 
1021  std::vector<BOARD_ITEM*> new_items;
1022  new_items.reserve( selection.Size() );
1023 
1024  BOARD_ITEM* orig_item = nullptr;
1025  BOARD_ITEM* dupe_item = nullptr;
1026 
1027  // Each selected item is duplicated and pushed to new_items list
1028  // Old selection is cleared, and new items are then selected.
1029  for( auto item : selection )
1030  {
1031  if( !item )
1032  continue;
1033 
1034  orig_item = static_cast<BOARD_ITEM*>( item );
1035 
1036  if( m_editModules )
1037  {
1038  dupe_item = editFrame->GetBoard()->m_Modules->Duplicate( orig_item, increment );
1039  }
1040  else
1041  {
1042 #if 0
1043  // @TODO: see if we allow zone duplication here
1044  // Duplicate zones is especially tricky (overlaping zones must be merged)
1045  // so zones are not duplicated
1046  if( item->Type() != PCB_ZONE_AREA_T )
1047 #endif
1048  dupe_item = editFrame->GetBoard()->Duplicate( orig_item );
1049  }
1050 
1051  if( dupe_item )
1052  {
1053  // Clear the selection flag here, otherwise the SELECTION_TOOL
1054  // will not properly select it later on
1055  dupe_item->ClearSelected();
1056 
1057  new_items.push_back( dupe_item );
1058  m_commit->Add( dupe_item );
1059  }
1060  }
1061 
1062  // Clear the old selection first
1064 
1065  // Select the new items
1066  m_toolMgr->RunAction( PCB_ACTIONS::selectItems, true, &new_items );
1067 
1068  // record the new items as added
1069  if( !selection.Empty() )
1070  {
1071  editFrame->DisplayToolMsg( wxString::Format( _( "Duplicated %d item(s)" ),
1072  (int) new_items.size() ) );
1073 
1074 
1075  // If items were duplicated, pick them up
1076  // this works well for "dropping" copies around and pushes the commit
1078  Main( evt );
1079  }
1080 
1081  return 0;
1082 }
1083 
1084 
1086 {
1087 public:
1088 
1089  GAL_ARRAY_CREATOR( PCB_BASE_FRAME& editFrame, bool editModules,
1090  const SELECTION& selection ):
1091  ARRAY_CREATOR( editFrame ),
1092  m_editModules( editModules ),
1093  m_selection( selection )
1094  {}
1095 
1096 private:
1097 
1098  int getNumberOfItemsToArray() const override
1099  {
1100  // only handle single items
1101  return m_selection.Size();
1102  }
1103 
1104  BOARD_ITEM* getNthItemToArray( int n ) const override
1105  {
1106  return static_cast<BOARD_ITEM*>( m_selection[n] );
1107  }
1108 
1109  BOARD* getBoard() const override
1110  {
1111  return m_parent.GetBoard();
1112  }
1113 
1114  MODULE* getModule() const override
1115  {
1116  // Remember this is valid and used only in the module editor.
1117  // in board editor, the parent of items is usually the board.
1118  return m_editModules ? m_parent.GetBoard()->m_Modules.GetFirst() : NULL;
1119  }
1120 
1121  wxPoint getRotationCentre() const override
1122  {
1123  const VECTOR2I rp = m_selection.GetCenter();
1124  return wxPoint( rp.x, rp.y );
1125  }
1126 
1127  void prePushAction( BOARD_ITEM* aItem ) override
1128  {
1129  // Because aItem is/can be created from a selected item, and inherits from
1130  // it this state, reset the selected stated of aItem:
1131  aItem->ClearSelected();
1132 
1133  if( aItem->Type() == PCB_MODULE_T )
1134  {
1135  static_cast<MODULE*>( aItem )->RunOnChildren( [&] ( BOARD_ITEM* item )
1136  {
1137  item->ClearSelected();
1138  }
1139  );
1140  }
1141  }
1142 
1143  void postPushAction( BOARD_ITEM* new_item ) override
1144  {
1145  }
1146 
1147  void finalise() override
1148  {
1149  }
1150 
1153 };
1154 
1155 
1157 {
1159  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector )
1161 
1162  if( selection.Empty() )
1163  return 0;
1164 
1165  // we have a selection to work on now, so start the tool process
1166  PCB_BASE_FRAME* editFrame = getEditFrame<PCB_BASE_FRAME>();
1167  GAL_ARRAY_CREATOR array_creator( *editFrame, m_editModules, selection );
1168  array_creator.Invoke();
1169 
1170  return 0;
1171 }
1172 
1173 
1175 {
1176  for( int i = aCollector.GetCount() - 1; i >= 0; i-- )
1177  {
1178  BOARD_ITEM* item = static_cast<BOARD_ITEM*>( aCollector[i] );
1179 
1180  if( item->Type() != PCB_MODULE_T )
1181  aCollector.Remove( i );
1182  }
1183 }
1184 
1185 
1187 {
1189 
1190  bool updateMode = aEvent.IsAction( &PCB_ACTIONS::updateFootprints );
1191 
1192  MODULE* mod = (selection.Empty() ? nullptr : selection.FirstOfKind<MODULE> () );
1193 
1194  frame()->SetCurItem( mod );
1195 
1196  // Footprint exchange could remove modules, so they have to be
1197  // removed from the selection first
1199 
1200  // invoke the exchange dialog process
1201  {
1202  DIALOG_EXCHANGE_FOOTPRINTS dialog( frame(), mod, updateMode, mod != nullptr );
1203  dialog.ShowQuasiModal();
1204  }
1205 
1206  return 0;
1207 }
1208 
1209 
1211 {
1212  if( EditingModules() && !frame()->GetModel())
1213  return 0;
1214 
1215  auto& view = *getView();
1216  auto& controls = *getViewControls();
1218 
1219  Activate();
1220  frame()->SetToolID( toolID, wxCURSOR_PENCIL, _( "Measure distance" ) );
1221 
1222  EDA_UNITS_T units = frame()->GetUserUnits();
1224  KIGFX::PREVIEW::RULER_ITEM ruler( twoPtMgr, units );
1225 
1226  view.Add( &ruler );
1227  view.SetVisible( &ruler, false );
1228 
1229  GRID_HELPER grid( frame() );
1230 
1231  bool originSet = false;
1232 
1233  controls.ShowCursor( true );
1234  controls.SetAutoPan( false );
1235 
1236  while( auto evt = Wait() )
1237  {
1238  grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
1239  grid.SetUseGrid( !evt->Modifier( MD_ALT ) );
1240  controls.SetSnapping( !evt->Modifier( MD_ALT ) );
1241  const VECTOR2I cursorPos = grid.BestSnapAnchor( controls.GetMousePosition(), nullptr );
1242  controls.ForceCursorPosition(true, cursorPos );
1243 
1244  if( evt->IsCancel() || TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
1245  {
1246  break;
1247  }
1248 
1249  // click or drag starts
1250  else if( !originSet && ( evt->IsDrag( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) ) )
1251  {
1252  twoPtMgr.SetOrigin( cursorPos );
1253  twoPtMgr.SetEnd( cursorPos );
1254 
1255  controls.CaptureCursor( true );
1256  controls.SetAutoPan( true );
1257 
1258  originSet = true;
1259  }
1260 
1261  // second click or mouse up after drag ends
1262  else if( originSet && ( evt->IsClick( BUT_LEFT ) || evt->IsMouseUp( BUT_LEFT ) ) )
1263  {
1264  originSet = false;
1265 
1266  controls.SetAutoPan( false );
1267  controls.CaptureCursor( false );
1268  }
1269 
1270  // move or drag when origin set updates rules
1271  else if( originSet && ( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) )
1272  {
1273  twoPtMgr.SetAngleSnap( evt->Modifier( MD_CTRL ) );
1274  twoPtMgr.SetEnd( cursorPos );
1275 
1276  view.SetVisible( &ruler, true );
1277  view.Update( &ruler, KIGFX::GEOMETRY );
1278  }
1279 
1280  else if( evt->IsAction( &PCB_ACTIONS::switchUnits )
1281  || evt->IsAction( &PCB_ACTIONS::updateUnits ) )
1282  {
1283  if( frame()->GetUserUnits() != units )
1284  {
1285  units = frame()->GetUserUnits();
1286  ruler.SwitchUnits();
1287  view.Update( &ruler, KIGFX::GEOMETRY );
1288  }
1289  }
1290 
1291  else if( evt->IsClick( BUT_RIGHT ) )
1292  {
1294  }
1295  }
1296 
1297  view.SetVisible( &ruler, false );
1298  view.Remove( &ruler );
1299 
1300  frame()->SetNoToolSelected();
1301 
1302  return 0;
1303 }
1304 
1305 
1307 {
1308  Go( &EDIT_TOOL::Main, PCB_ACTIONS::editActivate.MakeEvent() );
1309  Go( &EDIT_TOOL::Main, PCB_ACTIONS::move.MakeEvent() );
1310  Go( &EDIT_TOOL::Drag, PCB_ACTIONS::drag45Degree.MakeEvent() );
1312  Go( &EDIT_TOOL::Rotate, PCB_ACTIONS::rotateCw.MakeEvent() );
1313  Go( &EDIT_TOOL::Rotate, PCB_ACTIONS::rotateCcw.MakeEvent() );
1314  Go( &EDIT_TOOL::Flip, PCB_ACTIONS::flip.MakeEvent() );
1315  Go( &EDIT_TOOL::Remove, PCB_ACTIONS::remove.MakeEvent() );
1316  Go( &EDIT_TOOL::Remove, PCB_ACTIONS::removeAlt.MakeEvent() );
1322  Go( &EDIT_TOOL::Mirror, PCB_ACTIONS::mirror.MakeEvent() );
1323 
1330 }
1331 
1332 
1334 {
1335  if( m_dragging && aSelection.HasReferencePoint() )
1336  return false;
1337 
1338  // When there is only one item selected, the reference point is its position...
1339  if( aSelection.Size() == 1 )
1340  {
1341  auto item = static_cast<BOARD_ITEM*>( aSelection.Front() );
1342  auto pos = item->GetPosition();
1343  aSelection.SetReferencePoint( VECTOR2I( pos.x, pos.y ) );
1344  }
1345  // ...otherwise modify items with regard to the cursor position
1346  else
1347  {
1349  aSelection.SetReferencePoint( m_cursor );
1350  }
1351 
1352  return true;
1353 }
1354 
1355 
1357 {
1359 
1360  if( selection.Empty() )
1361  return 0;
1362 
1364 
1365  if( !mod )
1366  return 0;
1367 
1368  PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();
1369 
1370  editFrame->SetCurItem( mod );
1371 
1372  if( editFrame->GetCurItem()->GetTimeStamp() == 0 ) // Module Editor needs a non null timestamp
1373  {
1374  editFrame->GetCurItem()->SetTimeStamp( GetNewTimeStamp() );
1375  editFrame->OnModify();
1376  }
1377 
1379 
1380  editor->Load_Module_From_BOARD( (MODULE*) editFrame->GetCurItem() );
1381  editFrame->SetCurItem( NULL ); // the current module could be deleted by
1382 
1383  editor->Show( true );
1384  editor->Raise(); // Iconize( false );
1385 
1386  if( selection.IsHover() )
1388 
1389  return 0;
1390 }
1391 
1392 
1394 {
1395  STATUS_TEXT_POPUP statusPopup( frame() );
1396  PICKER_TOOL* picker = m_toolMgr->GetTool<PICKER_TOOL>();
1397  bool picking = true;
1398  bool retVal = true;
1399 
1400  statusPopup.SetText( _( "Select reference point for the copy..." ) );
1401  picker->Activate();
1402  picker->SetClickHandler( [&]( const VECTOR2D& aPoint ) -> bool
1403  {
1404  aP = aPoint;
1405  statusPopup.SetText( _( "Selection copied." ) );
1406  statusPopup.Expire( 800 );
1407  picking = false;
1408  return false; // we don't need any more points
1409  } );
1410  picker->SetCancelHandler( [&]()
1411  {
1412  statusPopup.SetText( _( "Copy cancelled." ) );
1413  statusPopup.Expire( 800 );
1414  picking = false;
1415  retVal = false;
1416  } );
1417 
1418  statusPopup.Move( wxGetMousePosition() + wxPoint( 20, -50 ) );
1419  statusPopup.Popup();
1420 
1421  while( picking )
1422  {
1423  statusPopup.Move( wxGetMousePosition() + wxPoint( 20, -50 ) );
1424  Wait();
1425  }
1426 
1427  statusPopup.Hide();
1428  return retVal;
1429 }
1430 
1431 
1432 int EDIT_TOOL::doCopyToClipboard( bool withAnchor )
1433 {
1434  CLIPBOARD_IO io;
1435 
1436  Activate();
1437 
1439  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector )
1441 
1442  if( selection.Empty() )
1443  return 1;
1444 
1445  if( withAnchor )
1446  {
1447  VECTOR2I refPoint;
1448  bool rv = pickCopyReferencePoint( refPoint );
1449  frame()->SetMsgPanel( board() );
1450 
1451  if( !rv )
1452  return 1;
1453 
1454  selection.SetReferencePoint( refPoint );
1455  }
1456 
1457  io.SetBoard( board() );
1458  io.SaveSelection( selection );
1459 
1460  return 0;
1461 }
1462 
1463 
1465 {
1466  return doCopyToClipboard( true );
1467 }
1468 
1469 
1471 {
1472  return doCopyToClipboard( true );
1473 }
1474 
1475 
1477 {
1478  if( !copyToClipboard( aEvent ) )
1479  Remove( aEvent );
1480 
1481  return 0;
1482 }
static TOOL_ACTION selectItems
Selects a list of items (specified as the event parameter)
Definition: pcb_actions.h:59
static TOOL_ACTION selectionClear
Clears the current selection.
Definition: pcb_actions.h:53
VECTOR2I BestDragOrigin(const VECTOR2I &aMousePos, BOARD_ITEM *aItem)
virtual void ShowCursor(bool aEnabled)
Function ShowCursor() Enables or disables display of cursor.
void setTransitions() override
Sets up handlers for various events.
Definition: edit_tool.cpp:1306
int GetCount() const
Function GetCount returns the number of objects in the list.
Definition: collector.h:114
VECTOR2I m_cursor
Last cursor position (needed for getModificationPoint() to avoid changes of edit reference point)...
Definition: edit_tool.h:198
void ClearReferencePoint()
Definition: selection.h:210
KICAD_T Type() const
Function Type()
Definition: base_struct.h:201
BOARD_ITEM_CONTAINER * GetParent() const
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:116
int Main(const TOOL_EVENT &aEvent)
Function Main()
Definition: edit_tool.cpp:336
int Properties(const TOOL_EVENT &aEvent)
Function Edit()
Definition: edit_tool.cpp:628
int Rotate(const TOOL_EVENT &aEvent)
Function Rotate()
Definition: edit_tool.cpp:670
TOOL_BASE * FindTool(int aId) const
Function FindTool() Searches for a tool with given ID.
static TOOL_ACTION move
move an item
Definition: pcb_actions.h:96
int GetCurrentViaDrill() const
Function GetCurrentViaDrill.
VECTOR2I GetReferencePoint() const
Definition: selection.h:200
KIWAY & Kiway() const
Function Kiway returns a reference to the KIWAY that this object has an opportunity to participate in...
Definition: kiway_player.h:60
virtual void SetToolID(int aId, int aCursor, const wxString &aToolMsg) override
Set the tool command ID to aId and sets the cursor to aCursor.
int ExchangeFootprints(const TOOL_EVENT &aEvent)
Function ExchangeFootprints()
Definition: edit_tool.cpp:1186
void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction)
Function RunOnChildren.
SELECTION & RequestSelection(CLIENT_SELECTION_FILTER aClientFilter)
Function RequestSelection()
static TOOL_ACTION editActivate
Activation of the edit tool.
Definition: pcb_actions.h:93
static const KICAD_T Tracks[]
A scan list for only TRACKS.
Definition: collectors.h:315
virtual VECTOR2D GetMousePosition(bool aWorldCoordinates=true) const =0
Function GetMousePosition() Returns the current mouse pointer position.
virtual void SetPosition(const wxPoint &aPos)=0
TOOL_MENU m_menu
Menu model displayed by the tool.
Definition: pcb_tool.h:148
virtual void Update(VIEW_ITEM *aItem, int aUpdateFlags) override
For dynamic VIEWs, informs the associated VIEW that the graphical representation of this item has cha...
Definition: pcb_view.cpp:81
This file is part of the common library.
bool IsNew() const
Definition: base_struct.h:219
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class...
void SetClickHandler(CLICK_HANDLER aHandler)
Function SetClickHandler() Sets a handler for mouse click event.
Definition: picker_tool.h:85
std::unique_ptr< BOARD_COMMIT > m_commit
Definition: edit_tool.h:212
void ClearSelected()
Definition: base_struct.h:234
VECTOR2I Align(const VECTOR2I &aPoint) const
int doCopyToClipboard(bool withAnchor)
Definition: edit_tool.cpp:1432
void AddSeparator(const SELECTION_CONDITION &aCondition=SELECTION_CONDITIONS::ShowAlways, int aOrder=ANY_ORDER)
Function AddSeparator()
VIEW_CONTROLS class definition.
Class SELECTION_TOOL.
Class TWO_POINT_GEOMETRY_MANAGER.
virtual void OnEditItemRequest(wxDC *aDC, BOARD_ITEM *aItem)=0
Function OnEditItemRequest Install the corresponding dialog editor for the given item.
Class BOARD to handle a board.
SELECTION_LOCK_FLAGS CheckLock()
Checks if the user has agreed to modify locked items for the given selection.
Class STATUS_TEXT_POPUP.
Definition: status_popup.h:77
CONDITIONAL_MENU & GetMenu()
Function GetMenu.
Definition: tool_menu.cpp:49
bool updateModificationPoint(SELECTION &aSelection)
Returns the right modification point (e.g.
Definition: edit_tool.cpp:1333
static TOOL_ACTION dragFreeAngle
Definition: pcb_actions.h:137
Tool is invoked after being inactive.
Definition: tool_base.h:82
static TOOL_ACTION explodePadToShapes
Definition: pcb_actions.h:312
EDA_ITEM * Front() const
Definition: selection.h:152
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:215
BOARD_ITEM * Duplicate(const BOARD_ITEM *aItem, bool aIncrementPadNumbers, bool aAddToModule=false)
Function Duplicate Duplicate a given item within the module, without adding to the board...
class ZONE_CONTAINER, a zone area
Definition: typeinfo.h:102
virtual void Remove(VIEW_ITEM *aItem)
Function Remove() Removes a VIEW_ITEM from the view.
Definition: view.cpp:365
static TOOL_ACTION properties
Activation of the edit tool.
Definition: pcb_actions.h:111
void SetCurItem(BOARD_ITEM *aItem, bool aDisplayInfo=true)
Function SetCurItem sets the currently selected item and displays it in the MsgPanel.
OPT_TOOL_EVENT Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Function Wait()
Action activates a tool
Definition: tool_event.h:152
virtual void SetSnapping(bool aEnabled)
Function SetSnapping() Enables/disables snapping cursor to grid.
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Function RunAction() Runs the specified action.
Definition: tool_manager.h:125
static int LegacyHotKey(int aHotKey)
Creates a hot key code that refers to a legacy hot key setting, instead of a particular key...
Definition: tool_action.h:174
BOARD * GetBoard() const
void SetPosition(const wxPoint &aPos) override
Definition: class_pad.h:219
static TOOL_ACTION removeAlt
Definition: pcb_actions.h:133
Classes to handle copper zones.
bool IsAction(const TOOL_ACTION *aAction) const
Function IsAction() Tests if the event contains an action issued upon activation of the given TOOL_AC...
Definition: tool_event.cpp:54
static TOOL_ACTION drag45Degree
Definition: pcb_actions.h:136
static TOOL_ACTION mirror
Mirroring of selected items.
Definition: pcb_actions.h:108
class D_PAD, a pad in a footprint
Definition: typeinfo.h:90
VECTOR2I BestSnapAnchor(const VECTOR2I &aOrigin, BOARD_ITEM *aDraggedItem)
static TOOL_ACTION updateUnits
Definition: pcb_actions.h:368
void UndoRedoBlock(bool aBlock=true)
Function UndoRedoBlock Enables/disable undo and redo operations.
SELECTION_TOOL * m_selectionTool
Selection tool used for obtaining selected items
Definition: edit_tool.h:191
static SELECTION_CONDITION Count(int aNumber)
Function Count Creates a functor that tests if the number of selected items is equal to the value giv...
void SaveSelection(const SELECTION &selected)
static TOOL_ACTION pasteFromClipboard
Paste from clipboard.
Definition: pcb_actions.h:324
VECTOR2< int > VECTOR2I
Definition: vector2d.h:587
static TOOL_ACTION switchUnits
Definition: pcb_actions.h:367
void SetBoard(BOARD *aBoard)
int GetCurrentViaSize() const
Function GetCurrentViaSize.
Definition of class FOOTPRINT_EDIT_FRAME.
static bool NotEmpty(const SELECTION &aSelection)
Function NotEmpty Tests if there are any items selected.
wxPoint m_O_Curseur
Relative Screen cursor coordinate (on grid) in user units.
Definition: base_screen.h:185
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Function Go()
class EDGE_MODULE, a footprint edge
Definition: typeinfo.h:94
static const int delta[8][2]
Definition: solve.cpp:112
void Remove(int aIndex)
Function Remove removes the item at aIndex (first position is 0);.
Definition: collector.h:143
virtual void Remove(VIEW_ITEM *aItem) override
Function Remove() Removes a VIEW_ITEM from the view.
Definition: pcb_view.cpp:64
const wxPoint & GetAuxOrigin() const override
Return the origin of the axis used for plotting and various exports.
MODULE * getModule() const override
Definition: edit_tool.cpp:1114
static TOOL_ACTION selectionModified
Modified selection notification.
Definition: pcb_actions.h:114
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
int Mirror(const TOOL_EVENT &aEvent)
Function Mirror.
Definition: edit_tool.cpp:748
Pcbnew hotkeys.
BOARD_ITEM * getNthItemToArray(int n) const override
Definition: edit_tool.cpp:1104
static TOOL_ACTION moveExact
Activation of the exact move tool.
Definition: pcb_actions.h:117
int cutToClipboard(const TOOL_EVENT &aEvent)
Function cutToClipboard() Cuts the current selection to the clipboard by formatting it as a fake pcb ...
Definition: edit_tool.cpp:1476
Generic tool for picking a point.
Definition: picker_tool.h:34
void Append(EDA_ITEM *item)
Function Append adds an item to the end of the list.
Definition: collector.h:133
bool RoutingInProgress() const
Definition: pns_router.cpp:112
void finalise() override
Definition: edit_tool.cpp:1147
virtual void SetCursorPosition(const VECTOR2D &aPosition, bool aWarpView=true)=0
Moves cursor to the requested position expressed in world coordinates.
#define IS_DRAGGED
Item being dragged.
Definition: base_struct.h:116
bool PadsLocked() const
Definition: class_module.h:304
KIGFX::VIEW_CONTROLS * controls() const
Definition: pcb_tool.h:138
static TOOL_ACTION duplicate
Activation of the duplication tool.
Definition: pcb_actions.h:120
void Mirror(const wxPoint aCentre, bool aMirrorAroundXAxis)
Mirror an edge of the footprint.
class MODULE, a footprint
Definition: typeinfo.h:89
int Flip(const TOOL_EVENT &aEvent)
Function Flip()
Definition: edit_tool.cpp:827
void SetReferencePoint(const VECTOR2I &aP)
Definition: selection.h:205
static TOOL_ACTION duplicateIncrement
Activation of the duplication tool with incrementing (e.g. pad number)
Definition: pcb_actions.h:123
timestamp_t GetNewTimeStamp()
Definition: common.cpp:212
static TOOL_ACTION rotateCw
Rotation of selected objects clockwise.
Definition: pcb_actions.h:99
Class LSET is a set of PCB_LAYER_IDs.
int getNumberOfItemsToArray() const override
Definition: edit_tool.cpp:1098
wxPoint getRotationCentre() const override
Definition: edit_tool.cpp:1121
void SetFlags(STATUS_FLAGS aMask)
Definition: base_struct.h:256
VTBL_ENTRY KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=NULL)
Function Player returns the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:300
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
bool m_dragging
Flag determining if anything is being dragged right now
Definition: edit_tool.h:194
virtual void Move(const wxPoint &aMoveVector)
Function Move move this object.
virtual void CaptureCursor(bool aEnabled)
Function CaptureCursor() Forces the cursor to stay within the drawing panel area. ...
PCB_GENERAL_SETTINGS & Settings()
int ShowQuasiModal()
static SELECTION_CONDITION OnlyTypes(const std::vector< KICAD_T > &aTypes)
Function OnlyTypes Creates a functor that tests if the selected items are only of given types...
EDA_UNITS_T GetUserUnits() const override
Return the user units currently in use.
Definition: draw_frame.h:284
SELECTION_LOCK_FLAGS
Definition: selection.h:229
VECTOR2D GetCursorPosition() const
Returns the current cursor position in world coordinates.
PCB_EDIT_FRAME * frame() const
Definition: pcb_tool.h:139
Class TOOL_EVENT.
Definition: tool_event.h:168
static TOOL_ACTION createArray
Tool for creating an array of objects.
Definition: pcb_actions.h:318
void SetOrigin(const VECTOR2I &aOrigin)
Set the origin of the ruler (the fixed end)
GAL_ARRAY_CREATOR(PCB_BASE_FRAME &editFrame, bool editModules, const SELECTION &selection)
Definition: edit_tool.cpp:1089
SELECTION & GetSelection()
Function GetSelection()
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:538
bool Init() override
Function Init() Init() is called once upon a registration of the tool.
Definition: edit_tool.cpp:230
Class VIEW_CONTROLS is an interface for classes handling user events controlling the view behaviour (...
bool Load_Module_From_BOARD(MODULE *Module)
Load in Modedit a footprint from the main board.
virtual void Popup(wxWindow *aFocus=nullptr)
MODULE * module() const
Definition: pcb_tool.h:141
int Drag(const TOOL_EVENT &aEvent)
Function Drag()
Definition: edit_tool.cpp:324
Class RULER_ITEM.
Definition: ruler_item.h:43
virtual void ForceCursorPosition(bool aEnabled, const VECTOR2D &aPosition=VECTOR2D(0, 0))
Function ForceCursorPosition() Places the cursor immediately at a given point.
virtual void Rotate(const wxPoint &aRotCentre, double aAngle)
Function Rotate Rotate this object.
const SELECTION & selection() const
Definition: pcb_tool.cpp:245
bool isInteractiveDragEnabled() const
Definition: edit_tool.cpp:316
static TOOL_ACTION exchangeFootprints
Exchange footprints of modules.
Definition: pcb_actions.h:129
virtual void Move(const wxPoint &aWhere)
bool IsCancelInteractive(const TOOL_EVENT &aEvt)
Function IsCancelInteractive()
All active tools
Definition: tool_event.h:144
static TOOL_ACTION cutToClipboard
Paste from clipboard.
Definition: pcb_actions.h:327
virtual void Update(VIEW_ITEM *aItem, int aUpdateFlags)
For dynamic VIEWs, informs the associated VIEW that the graphical representation of this item has cha...
Definition: view.cpp:1521
BOARD * getBoard() const override
Definition: edit_tool.cpp:1109
void Expire(int aMsecs)
Hides the popup after a specified time.
const SELECTION & m_selection
Definition: edit_tool.cpp:1152
ROTATION_ANCHOR
bool IsLocked() const override
Function IsLocked.
Definition: class_module.h:268
static TOOL_ACTION copyToClipboard
Copy selected items to clipboard.
Definition: pcb_actions.h:321
static TOOL_ACTION routerInlineDrag
Activation of the Push and Shove router (inline dragging mode)
Definition: pcb_actions.h:218
virtual void SetAutoPan(bool aEnabled)
Function SetAutoPan Turns on/off auto panning (this feature is used when there is a tool active (eg...
KIGFX::VIEW_CONTROLS * getViewControls() const
Function getViewControls()
Definition: tool_base.cpp:41
#define EXCLUDE_TRANSIENTS
Definition: edit_tool.h:47
void SetCancelHandler(CANCEL_HANDLER aHandler)
Function SetCancelHandler() Sets a handler for cancel events (ESC or context-menu Cancel)...
Definition: picker_tool.h:95
virtual const wxPoint GetPosition() const =0
bool m_editModules
Definition: pcb_tool.h:150
void SetSnap(bool aSnap)
Definition: grid_helper.h:62
void Reset(RESET_REASON aReason) override
Function Reset() Brings the tool to a known, initial state.
Definition: edit_tool.cpp:221
static TOOL_ACTION expandSelectedConnection
Expands the current selection to select a connection between two junctions.
Definition: pcb_actions.h:74
KIGFX::VIEW * getView() const
Function getView()
Definition: tool_base.cpp:35
T * FirstOfKind() const
Definition: selection.h:163
static TOOL_ACTION updateFootprints
Update footprints to reflect any changes in the library.
Definition: pcb_actions.h:126
static TOOL_ACTION rotateCcw
Rotation of selected objects counter-clockwise.
Definition: pcb_actions.h:102
class TEXTE_MODULE, text in a footprint
Definition: typeinfo.h:93
int MoveExact(const TOOL_EVENT &aEvent)
Function MoveExact()
Definition: edit_tool.cpp:933
ID_MODEDIT_MEASUREMENT_TOOL
int Remove(const TOOL_EVENT &aEvent)
Function Remove()
Definition: edit_tool.cpp:865
static ROUTER * theRouter
Definition: pns_router.cpp:59
static TOOL_ACTION createPadFromShapes
Definition: pcb_actions.h:311
bool EditingModules() const
Definition: pcb_tool.h:102
static TOOL_ACTION flip
Flipping of selected objects.
Definition: pcb_actions.h:105
virtual void SetNoToolSelected()
Select the ID_NO_TOOL_SELECTED id tool (Idle tool)
virtual void OnModify()
Function OnModify Virtual Must be called after a change in order to set the "modify" flag of the curr...
T Parameter() const
Function Parameter() Returns a non-standard parameter assigned to the event.
Definition: tool_event.h:387
bool invokeInlineRouter(int aDragMode)
Definition: edit_tool.cpp:295
TOOL_EVENT MakeEvent() const
Function HasHotKey() Checks if the action has a hot key assigned.
Definition: tool_action.h:104
class MARKER_PCB, a marker used to show something
Definition: typeinfo.h:99
bool pickCopyReferencePoint(VECTOR2I &aP)
Definition: edit_tool.cpp:1393
void DisplayToolMsg(const wxString &msg)
int CreateArray(const TOOL_EVENT &aEvent)
Function CreateArray()
Definition: edit_tool.cpp:1156
bool changeTrackWidthOnClick(const SELECTION &selection)
Definition: edit_tool.cpp:587
Common, abstract interface for edit frames.
int MeasureTool(const TOOL_EVENT &aEvent)
Launches a tool to measure between points
Definition: edit_tool.cpp:1210
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:170
KIGFX::PCB_VIEW * view() const
Definition: pcb_tool.h:137
virtual bool IsLocked() const
Function IsLocked.
void AddItem(const TOOL_ACTION &aAction, const SELECTION_CONDITION &aCondition=SELECTION_CONDITIONS::ShowAlways, int aOrder=ANY_ORDER)
Function AddItem()
static TOOL_ACTION editFootprintInFpEditor
Definition: pcb_actions.h:387
DLIST< MODULE > m_Modules
Definition: class_board.h:248
Used when the right click button is pressed, or when the select tool is in effect.
Definition: collectors.h:242
int GetToolId() const
Definition: draw_frame.h:519
Class TOOL_ACTION.
Definition: tool_action.h:46
size_t i
Definition: json11.cpp:597
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in tenths of degrees, but soon degrees.
Definition: class_pad.h:382
static SELECTION_CONDITION OnlyType(KICAD_T aType)
Function OnlyType Creates a functor that tests if the selected items are only of given type...
const wxSize & GetDelta() const
Definition: class_pad.h:272
void SetAuxAxes(bool aEnable, const VECTOR2I &aOrigin=VECTOR2I(0, 0), bool aEnableDiagonal=false)
static wxPoint mirrorPointX(const wxPoint &aPoint, const wxPoint &aMirrorPoint)
Definition: edit_tool.cpp:713
PCB_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
static TOOL_ACTION positionRelative
Activation of the position relative tool.
Definition: pcb_actions.h:254
RESET_REASON
Determines the reason of reset for a tool
Definition: tool_base.h:80
void Mirror(const wxPoint &aCentre, bool aMirrorAroundXAxis)
Mirror text position in footprint editing the text itself is not mirrored, and the layer not modified...
int editFootprintInFpEditor(const TOOL_EVENT &aEvent)
Definition: edit_tool.cpp:1356
bool IsHover() const
Definition: selection.h:69
bool HasItem(const EDA_ITEM *aItem) const
Function HasItem tests if aItem has already been collected.
Definition: collector.h:197
void SetOrientation(double aAngle)
Function SetOrientation sets the rotation angle of the pad.
Definition: class_pad.cpp:418
virtual BOARD * GetBoard() const
Function GetBoard returns the BOARD in which this BOARD_ITEM resides, or NULL if none.
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Sets the item visibility.
Definition: view.cpp:1467
void Activate()
Function Activate() Runs the tool.
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1) override
Function Add() Adds a VIEW_ITEM to the view.
Definition: pcb_view.cpp:48
int Size() const
Returns the number of selected parts.
Definition: selection.h:122
void SetUseGrid(bool aGrid=true)
Definition: grid_helper.h:67
void SetX0(int x)
Definition: class_pad.h:266
#define EXCLUDE_LOCKED
Function EditToolSelectionFilter.
Definition: edit_tool.h:45
int copyToClipboard(const TOOL_EVENT &aEvent)
Function copyToClipboard() Sends the current selection to the clipboard by formatting it as a fake pc...
Definition: edit_tool.cpp:1464
int copyToClipboardWithAnchor(const TOOL_EVENT &aEvent)
Definition: edit_tool.cpp:1470
Module description (excepted pads)
static void FootprintFilter(const VECTOR2I &, GENERAL_COLLECTOR &aCollector)
Function FootprintFilter()
Definition: edit_tool.cpp:1174
bool HasReferencePoint() const
Definition: selection.h:195
SGLIB_API S3DMODEL * GetModel(SCENEGRAPH *aNode)
Function GetModel creates an S3DMODEL representation of aNode (raw data, no transforms) ...
Definition: ifsg_api.cpp:471
static TOOL_ACTION remove
Deleting a BOARD_ITEM.
Definition: pcb_actions.h:132
void UpdateMsgPanel() override
>
const wxPoint GetPosition() const override
Definition: class_pad.h:220
#define EXCLUDE_LOCKED_PADS
Definition: edit_tool.h:46
int GetCurrentTrackWidth() const
Function GetCurrentTrackWidth.
EDGE_MODULE class definition.
void postPushAction(BOARD_ITEM *new_item) override
Definition: edit_tool.cpp:1143
ROUTER * Router() const
int GetEventRotationAngle(const PCB_BASE_EDIT_FRAME &aFrame, const TOOL_EVENT &aEvt)
Function getEventRotationAngle()
BOARD_ITEM * GetCurItem()
void SetOffset(const wxPoint &aOffset)
Definition: class_pad.h:277
void EditToolSelectionFilter(GENERAL_COLLECTOR &aCollector, int aFlags)
Definition: edit_tool.cpp:173
VECTOR2I GetCenter() const
Returns the center point of the selection area bounding box.
Definition: selection.cpp:67
int Duplicate(const TOOL_EVENT &aEvent)
Function Duplicate()
Definition: edit_tool.cpp:1006
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:245
void ShowContextMenu(SELECTION &aSelection)
Function ShowContextMenu.
Definition: tool_menu.cpp:62
ROUTING_SETTINGS & Settings()
Definition: pns_router.h:187
static void mirrorPadX(D_PAD &aPad, const wxPoint &aMirrorPoint)
Mirror a pad in the vertical axis passing through a point.
Definition: edit_tool.cpp:728
#define mod(a, n)
Definition: greymap.cpp:24
class PCB_BASE_FRAME basic PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer...
static TOOL_ACTION measureTool
Definition: pcb_actions.h:365
EDA_UNITS_T
Definition: common.h:159
const wxPoint & GetOffset() const
Definition: class_pad.h:278
void SetText(const wxString &aText)
Display a text.
void SetDelta(const wxSize &aSize)
Definition: class_pad.h:271
timestamp_t GetTimeStamp() const
Definition: base_struct.h:207
void prePushAction(BOARD_ITEM *aItem) override
Definition: edit_tool.cpp:1127
void SetEnd(const VECTOR2I &aEnd)
Set the current end of the rectangle (the end that moves with the cursor.
OPT< TOOL_EVENT > OPT_TOOL_EVENT
Definition: tool_event.h:495
void SetTimeStamp(timestamp_t aNewTimeStamp)
Definition: base_struct.h:206
Color has changed.
Definition: view_item.h:57
BOARD * board() const
Definition: pcb_tool.h:140
BOARD_ITEM * Duplicate(const BOARD_ITEM *aItem, bool aAddToBoard=false)