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-2020 KiCad Developers, see AUTHORS.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 #include <class_board.h>
29 #include <class_module.h>
30 #include <class_edge_mod.h>
31 #include <collectors.h>
32 #include <pcb_edit_frame.h>
33 #include <ws_proxy_view_item.h>
34 #include <kiway.h>
35 #include <array_creator.h>
36 #include <pcbnew_settings.h>
37 #include <status_popup.h>
39 #include <tool/tool_manager.h>
40 #include <tools/pcb_actions.h>
41 #include <tools/selection_tool.h>
42 #include <tools/edit_tool.h>
44 #include <tools/tool_event_utils.h>
45 #include <tools/grid_helper.h>
46 #include <tools/pad_tool.h>
47 #include <pad_naming.h>
48 #include <view/view_controls.h>
50 #include <confirm.h>
51 #include <bitmaps.h>
52 #include <cassert>
53 #include <functional>
54 using namespace std::placeholders;
55 #include "kicad_clipboard.h"
56 #include <router/router_tool.h>
59 #include <board_commit.h>
60 #include <zone_filler.h>
61 
62 
63 void EditToolSelectionFilter( GENERAL_COLLECTOR& aCollector, int aFlags, SELECTION_TOOL* selectionTool )
64 {
65  // Iterate from the back so we don't have to worry about removals.
66  for( int i = aCollector.GetCount() - 1; i >= 0; --i )
67  {
68  BOARD_ITEM* item = aCollector[ i ];
69 
70  if( ( aFlags & EXCLUDE_LOCKED ) && item->IsLocked() )
71  {
72  aCollector.Remove( item );
73  }
74  else if( item->Type() == PCB_MODULE_ZONE_AREA_T )
75  {
76  MODULE* mod = static_cast<MODULE*>( item->GetParent() );
77 
78  // case 1: handle locking
79  if( ( aFlags & EXCLUDE_LOCKED ) && mod && mod->IsLocked() )
80  {
81  aCollector.Remove( item );
82  }
83 
84  // case 2: selection contains both the module and its pads - remove the pads
85  if( !( aFlags & INCLUDE_PADS_AND_MODULES ) && mod && aCollector.HasItem( mod ) )
86  aCollector.Remove( item );
87  }
88  else if( item->Type() == PCB_PAD_T )
89  {
90  MODULE* mod = static_cast<MODULE*>( item->GetParent() );
91 
92  // case 1: handle locking
93  if( ( aFlags & EXCLUDE_LOCKED ) && mod && mod->IsLocked() )
94  {
95  aCollector.Remove( item );
96  }
97  else if( ( aFlags & EXCLUDE_LOCKED_PADS ) && mod && mod->PadsLocked() )
98  {
99  // Pad locking is considerably "softer" than item locking
100  aCollector.Remove( item );
101 
102  if( !mod->IsLocked() && !aCollector.HasItem( mod ) )
103  aCollector.Append( mod );
104  }
105 
106  // case 2: selection contains both the module and its pads - remove the pads
107  if( !( aFlags & INCLUDE_PADS_AND_MODULES ) && mod && aCollector.HasItem( mod ) )
108  aCollector.Remove( item );
109  }
110  else if( ( aFlags & EXCLUDE_TRANSIENTS ) && item->Type() == PCB_MARKER_T )
111  {
112  aCollector.Remove( item );
113  }
114  }
115  selectionTool->FilterCollectorForGroups( aCollector );
116 }
117 
118 
120  PCB_TOOL_BASE( "pcbnew.InteractiveEdit" ),
121  m_selectionTool( NULL ),
122  m_dragging( false ),
123  m_lockedSelected( false )
124 {
125 }
126 
127 
129 {
130  m_dragging = false;
131 
132  m_statusPopup = std::make_unique<STATUS_TEXT_POPUP>( getEditFrame<PCB_BASE_EDIT_FRAME>() );
133 
134  if( aReason != RUN )
135  m_commit.reset( new BOARD_COMMIT( this ) );
136 }
137 
138 
140  CONDITIONAL_MENU( aTool )
141 {
143  SetTitle( _( "Special Tools..." ) );
144 
149 }
150 
151 
153 {
154  // Find the selection tool, so they can cooperate
155  m_selectionTool = static_cast<SELECTION_TOOL*>( m_toolMgr->FindTool( "pcbnew.InteractiveSelection" ) );
156  wxASSERT_MSG( m_selectionTool, "pcbnew.InteractiveSelection tool is not available" );
157 
158  auto editingModuleCondition =
159  [ this ] ( const SELECTION& aSelection )
160  {
161  return m_editModules;
162  };
163 
164  auto singleModuleCondition = SELECTION_CONDITIONS::OnlyType( PCB_MODULE_T )
166 
167  auto noActiveToolCondition =
168  [ this ] ( const SELECTION& aSelection )
169  {
170  return frame()->ToolStackIsEmpty();
171  };
172 
173  auto notMovingCondition =
174  [ this ] ( const SELECTION& aSelection )
175  {
178  };
179 
180  auto noItemsCondition =
181  [ this ] ( const SELECTION& aSelections ) -> bool
182  {
183  return frame()->GetBoard() && !frame()->GetBoard()->IsEmpty();
184  };
185 
186  // Add context menu entries that are displayed when selection tool is active
188 
189  menu.AddItem( PCB_ACTIONS::move, SELECTION_CONDITIONS::NotEmpty && notMovingCondition );
197  menu.AddItem( PCB_ACTIONS::mirror, editingModuleCondition && SELECTION_CONDITIONS::NotEmpty );
198 
202 
204 
205  // Add the submenu for create array and special move
206  auto specialToolsSubMenu = std::make_shared<SPECIAL_TOOLS_CONTEXT_MENU>( this );
207  menu.AddSeparator();
208  m_selectionTool->GetToolMenu().AddSubMenu( specialToolsSubMenu );
209  menu.AddMenu( specialToolsSubMenu.get(), SELECTION_CONDITIONS::NotEmpty, 100 );
210 
211  menu.AddSeparator( 150 );
214  // Selection tool handles the context menu for some other tools, such as the Picker.
215  // Don't add things like Paste when another tool is active.
216  menu.AddItem( ACTIONS::paste, noActiveToolCondition, 150 );
217  menu.AddItem( ACTIONS::selectAll, noItemsCondition, 150 );
218 
219  // Footprint actions
220  menu.AddSeparator( 150 );
221  menu.AddItem( PCB_ACTIONS::editFpInFpEditor, singleModuleCondition, 150 );
222  menu.AddItem( PCB_ACTIONS::updateFootprint, singleModuleCondition, 150 );
223  menu.AddItem( PCB_ACTIONS::changeFootprint, singleModuleCondition, 150 );
224 
225  return true;
226 }
227 
228 
229 int EDIT_TOOL::GetAndPlace( const TOOL_EVENT& aEvent )
230 {
231  SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SELECTION_TOOL>();
232  MODULE* module = getEditFrame<PCB_BASE_FRAME>()->GetFootprintFromBoardByReference();
233 
234  if( module )
235  {
238 
239  selectionTool->GetSelection().SetReferencePoint( module->GetPosition() );
241  }
242 
243  return 0;
244 }
245 
246 
247 bool EDIT_TOOL::invokeInlineRouter( int aDragMode )
248 {
250 
251  if( !theRouter )
252  return false;
253 
254  // don't allow switch from moving to dragging
255  if( m_dragging )
256  {
257  wxBell();
258  return false;
259  }
260 
261  // make sure we don't accidentally invoke inline routing mode while the router is already active!
262  if( theRouter->IsToolActive() )
263  return false;
264 
265  if( theRouter->CanInlineDrag() )
266  {
268  return true;
269  }
270 
271  return false;
272 }
273 
274 
276 {
278 
279  return router && router->Router()->Settings().InlineDragEnabled();
280 }
281 
282 
284 {
286 
287  return router && router->IsToolActive();
288 }
289 
290 
291 int EDIT_TOOL::Drag( const TOOL_EVENT& aEvent )
292 {
293  int mode = PNS::DM_ANY;
294 
295  if( aEvent.IsAction( &PCB_ACTIONS::dragFreeAngle ) )
296  mode |= PNS::DM_FREE_ANGLE;
297 
298  invokeInlineRouter( mode );
299 
300  return 0;
301 }
302 
303 
304 int EDIT_TOOL::Move( const TOOL_EVENT& aEvent )
305 {
306  if( isRouterActive() )
307  {
308  wxBell();
309  return 0;
310  }
311 
312  return doMoveSelection( aEvent );
313 }
314 
315 
317 {
318  if( isRouterActive() )
319  {
320  wxBell();
321  return 0;
322  }
323 
324  return doMoveSelection( aEvent, true );
325 }
326 
327 
328 // Note: aEvent MUST NOT be const&; the source will get de-allocated if we go into the picker's
329 // event loop.
330 int EDIT_TOOL::doMoveSelection( TOOL_EVENT aEvent, bool aPickReference )
331 {
332  PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();
334  VECTOR2I originalCursorPos = controls->GetCursorPosition();
335 
336  // Be sure that there is at least one item that we can modify. If nothing was selected before,
337  // try looking for the stuff under mouse cursor (i.e. Kicad old-style hover selection)
339  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, SELECTION_TOOL* sTool )
340  {
341  EditToolSelectionFilter( aCollector, EXCLUDE_TRANSIENTS, sTool );
342  } );
343 
344  if( m_dragging || selection.Empty() )
345  return 0;
346 
347  LSET item_layers = selection.GetSelectionLayers();
348  bool unselect = selection.IsHover(); // N.B. This must be saved before the re-selection below
349  VECTOR2I pickedReferencePoint;
350 
351  // Now filter out locked pads. We cannot do this in the first RequestSelection() as we need
352  // the item_layers when a pad is the selection front (ie: will become curr_tiem).
354  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, SELECTION_TOOL* sTool )
355  {
356  EditToolSelectionFilter( aCollector, EXCLUDE_LOCKED_PADS, sTool );
357  } );
358 
359  if( selection.Empty() )
360  return 0;
361 
362  std::string tool = aEvent.GetCommandStr().get();
363  editFrame->PushTool( tool );
364  Activate();
365  controls->ShowCursor( true );
366  controls->SetAutoPan( true );
367 
368  if( aPickReference && !pickReferencePoint( _( "Select reference point for move..." ), "", "",
369  pickedReferencePoint ) )
370  {
371  if( unselect )
373 
374  editFrame->PopTool( tool );
375  return 0;
376  }
377 
378  std::vector<BOARD_ITEM*> sel_items;
379 
380  for( EDA_ITEM* item : selection )
381  {
382  BOARD_ITEM* boardItem = dynamic_cast<BOARD_ITEM*>( item );
383  MODULE* module = dynamic_cast<MODULE*>( item );
384 
385  if( boardItem )
386  sel_items.push_back( boardItem );
387 
388  if( module )
389  {
390  for( D_PAD* pad : module->Pads() )
391  sel_items.push_back( pad );
392  }
393  }
394 
395  bool restore_state = false;
396  bool fromOtherCommand = false;
397  VECTOR2I totalMovement;
398  GRID_HELPER grid( m_toolMgr, editFrame->GetMagneticItemsSettings() );
399  TOOL_EVENT* evt = const_cast<TOOL_EVENT*>( &aEvent );
400  VECTOR2I prevPos;
401 
402  // Prime the pump
404 
405  // Main loop: keep receiving events
406  do
407  {
408  VECTOR2I movement;
409  editFrame->GetCanvas()->SetCurrentCursor( wxCURSOR_ARROW );
410  grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
411  grid.SetUseGrid( !evt->Modifier( MD_ALT ) );
412 
413  if( evt->IsAction( &PCB_ACTIONS::move ) || evt->IsMotion() || evt->IsDrag( BUT_LEFT )
414  || evt->IsAction( &ACTIONS::refreshPreview )
415  || evt->IsAction( &PCB_ACTIONS::moveWithReference ) )
416  {
417  if( m_dragging && evt->Category() == TC_MOUSE )
418  {
419  VECTOR2I mousePos( controls->GetMousePosition() );
420 
421  m_cursor = grid.BestSnapAnchor( mousePos, item_layers, sel_items );
422 
424  {
426 
427  // The arrow keys are by definition SINGLE AXIS. Do not allow the other
428  // axis to be snapped to the grid.
429  if( action == ACTIONS::CURSOR_LEFT || action == ACTIONS::CURSOR_RIGHT )
430  m_cursor.y = prevPos.y;
431  else if( action == ACTIONS::CURSOR_UP || action == ACTIONS::CURSOR_DOWN )
432  m_cursor.x = prevPos.x;
433  }
434 
437 
438  movement = m_cursor - prevPos;
439  prevPos = m_cursor;
440  totalMovement += movement;
441 
442  // Drag items to the current cursor position
443  for( EDA_ITEM* item : sel_items )
444  {
445  // Don't double move footprint pads, fields, etc.
446  //
447  // For PCB_GROUP_T, we make sure the selection includes only the top level
448  // group and not its descendants.
449  if( !item->GetParent() || !item->GetParent()->IsSelected() )
450  static_cast<BOARD_ITEM*>( item )->Move( movement );
451  }
452 
454  }
455  else if( !m_dragging && !evt->IsAction( &ACTIONS::refreshPreview ) )
456  {
457  // Prepare to start dragging
458 
459  if( !( evt->IsAction( &PCB_ACTIONS::move )
460  || evt->IsAction( &PCB_ACTIONS::moveWithReference ) )
462  {
464  break;
465  }
466 
467  // deal with locked items (override lock or abort the operation)
469 
470  if( lockFlags == SELECTION_LOCKED )
471  break;
472 
473  m_dragging = true;
474 
475  // When editing modules, all items have the same parent
476  if( EditingModules() )
477  {
478  m_commit->Modify( selection.Front() );
479  }
480  else
481  {
482  // Save items, so changes can be undone
483  for( EDA_ITEM* item : selection )
484  {
485  // Don't double move footprint pads, fields, etc.
486  //
487  // For PCB_GROUP_T, the parent is the board.
488  if( item->GetParent() && item->GetParent()->IsSelected() )
489  continue;
490 
491  m_commit->Modify( item );
492 
493  // If moving a group, record position of all the descendants for undo
494  if( item->Type() == PCB_GROUP_T )
495  {
496  PCB_GROUP* group = static_cast<PCB_GROUP*>( item );
497  group->RunOnDescendants( [&]( BOARD_ITEM* bItem )
498  {
499  m_commit->Modify( bItem );
500  });
501  }
502 
503  if( item->IsNew() )
504  fromOtherCommand = true;
505  }
506  }
507 
508  editFrame->UndoRedoBlock( true );
510 
512  {
513  // start moving with the reference point attached to the cursor
514  grid.SetAuxAxes( false );
515 
516  movement = m_cursor - selection.GetReferencePoint();
517 
518  // Drag items to the current cursor position
519  for( EDA_ITEM* item : selection )
520  {
521  // Don't double move footprint pads, fields, etc.
522  if( item->GetParent() && item->GetParent()->IsSelected() )
523  continue;
524 
525  static_cast<BOARD_ITEM*>( item )->Move( movement );
526  }
527 
529  }
530  else
531  {
532  std::vector<BOARD_ITEM*> items;
533 
534  for( EDA_ITEM* item : selection )
535  items.push_back( static_cast<BOARD_ITEM*>( item ) );
536 
537  m_cursor = grid.BestDragOrigin( originalCursorPos, items );
538 
539  // Set the current cursor position to the first dragged item origin, so the
540  // movement vector could be computed later
541  if( aPickReference )
542  {
543  selection.SetReferencePoint( pickedReferencePoint );
544  controls->ForceCursorPosition( true, pickedReferencePoint );
545  m_cursor = pickedReferencePoint;
546  }
547  else
548  {
549  // Check if user wants to warp the mouse to origin of moved object
550  if( !editFrame->GetMoveWarpsCursor() )
551  m_cursor = originalCursorPos; // No, so use original mouse pos instead
552 
554  grid.SetAuxAxes( true, m_cursor );
555  }
556  }
557 
559 
560  prevPos = m_cursor;
561  controls->SetAutoPan( true );
563  }
564 
565  m_toolMgr->RunAction( PCB_ACTIONS::updateLocalRatsnest, false, new VECTOR2I( movement ) );
566  }
567 
568  else if( evt->IsCancelInteractive() || evt->IsActivate() )
569  {
570  if( m_dragging && evt->IsCancelInteractive() )
571  evt->SetPassEvent( false );
572 
573  restore_state = true; // Canceling the tool means that items have to be restored
574  break; // Finish
575  }
576 
577  else if( evt->IsAction( &ACTIONS::undo ) )
578  {
579  restore_state = true; // Perform undo locally
580  break; // Finish
581  }
582 
583  // Dispatch TOOL_ACTIONs
584  else if( evt->IsAction( &ACTIONS::doDelete ) )
585  {
586  break; // finish -- there is no further processing for removed items
587  }
588  else if( evt->IsAction( &ACTIONS::duplicate ) )
589  {
590  break; // finish -- Duplicate tool will start a new Move with the dup'ed items
591  }
592  else if( evt->IsAction( &PCB_ACTIONS::moveExact ) )
593  {
594  // Reset positions so the Move Exactly is from the start.
595  for( EDA_ITEM* item : selection )
596  {
597  BOARD_ITEM* i = static_cast<BOARD_ITEM*>( item );
598  i->Move( -totalMovement );
599  }
600 
601  break; // finish -- we moved exactly, so we are finished
602  }
603 
604  else if( evt->IsMouseUp( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) )
605  {
606  break; // finish
607  }
608 
609  else
610  {
611  evt->SetPassEvent();
612  }
613 
614  } while( ( evt = Wait() ) ); // Assignment (instead of equality test) is intentional
615 
616  m_lockedSelected = false;
617  controls->ForceCursorPosition( false );
618  controls->ShowCursor( false );
619  controls->SetAutoPan( false );
620 
621  m_dragging = false;
622  editFrame->UndoRedoBlock( false );
623 
624  // Discard reference point when selection is "dropped" onto the board (ie: not dragging anymore)
626 
627  // If canceled, we need to remove the dynamic ratsnest from the screen
628  if( restore_state )
629  {
630  m_commit->Revert();
631 
632  if( fromOtherCommand )
633  {
634  PICKED_ITEMS_LIST* undo = editFrame->PopCommandFromUndoList();
635 
636  if( undo )
637  {
638  editFrame->PutDataInPreviousState( undo, false );
639  undo->ClearListAndDeleteItems();
640  delete undo;
641  }
642  }
643  }
644  else
645  {
646  m_commit->Push( _( "Drag" ) );
647  }
648 
650 
651  if( unselect )
653 
654  editFrame->PopTool( tool );
655  return 0;
656 }
657 
658 
660 {
662  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, SELECTION_TOOL* sTool )
663  {
664  EditToolSelectionFilter( aCollector, EXCLUDE_TRANSIENTS, sTool );
665  } );
666 
667  for( EDA_ITEM* item : selection )
668  {
669  if( auto via = dyn_cast<VIA*>( item ) )
670  {
671  m_commit->Modify( item );
672 
673  int new_width;
674  int new_drill;
675 
676  if( via->GetViaType() == VIATYPE::MICROVIA )
677  {
678  NETINFO_ITEM* net = via->GetNet();
679 
680  new_width = net->GetMicroViaSize();
681  new_drill = net->GetMicroViaDrillSize();
682  }
683  else
684  {
685  new_width = board()->GetDesignSettings().GetCurrentViaSize();
686  new_drill = board()->GetDesignSettings().GetCurrentViaDrill();
687  }
688 
689  via->SetDrill( new_drill );
690  via->SetWidth( new_width );
691  }
692  else if ( TRACK* track = dyn_cast<TRACK*>( item ) )
693  {
694  m_commit->Modify( item );
695 
696  int new_width = board()->GetDesignSettings().GetCurrentTrackWidth();
697  track->SetWidth( new_width );
698  }
699  }
700 
701  m_commit->Push( _("Edit track width/via size") );
702 
703  if( selection.IsHover() )
704  {
706 
707  // Notify other tools of the changes -- This updates the visual ratsnest
709  }
710 
711  return 0;
712 }
713 
714 
715 int EDIT_TOOL::Properties( const TOOL_EVENT& aEvent )
716 {
717  PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();
719  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, SELECTION_TOOL* sTool )
720  {
721  EditToolSelectionFilter( aCollector, EXCLUDE_TRANSIENTS, sTool );
722  } );
723 
724  // Tracks & vias are treated in a special way:
726  {
727  DIALOG_TRACK_VIA_PROPERTIES dlg( editFrame, selection, *m_commit );
728  dlg.ShowQuasiModal(); // QuasiModal required for NET_SELECTOR
729  }
730  else if( selection.Size() == 1 )
731  {
732  // Display properties dialog
733  BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.Front() );
734 
735  // Do not handle undo buffer, it is done by the properties dialogs
736  editFrame->OnEditItemRequest( item );
737 
738  // Notify other tools of the changes
740  }
741  else if( selection.Size() == 0 && getView()->IsLayerVisible( LAYER_WORKSHEET ) )
742  {
743  KIGFX::WS_PROXY_VIEW_ITEM* worksheet = editFrame->GetCanvas()->GetWorksheet();
744  VECTOR2D cursorPos = getViewControls()->GetCursorPosition( false );
745 
746  if( worksheet && worksheet->HitTestWorksheetItems( getView(), (wxPoint) cursorPos ) )
748  }
749 
750  if( selection.IsHover() )
751  {
753 
754  // Notify other tools of the changes -- This updates the visual ratsnest
756  }
757 
758  return 0;
759 }
760 
761 
762 int EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
763 {
764  if( isRouterActive() )
765  {
766  wxBell();
767  return 0;
768  }
769 
770  PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();
771 
773  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, SELECTION_TOOL* sTool )
774  {
776  },
777  nullptr, ! m_dragging );
778 
779  if( selection.Empty() )
780  return 0;
781 
783  auto refPt = selection.GetReferencePoint();
784  const int rotateAngle = TOOL_EVT_UTILS::GetEventRotationAngle( *editFrame, aEvent );
785 
786  // When editing modules, all items have the same parent
787  if( EditingModules() )
788  m_commit->Modify( selection.Front() );
789 
790  for( auto item : selection )
791  {
792  if( !item->IsNew() && !EditingModules() )
793  {
794  m_commit->Modify( item );
795 
796  // If rotating a group, record position of all the descendants for undo
797  if( item->Type() == PCB_GROUP_T )
798  {
799  static_cast<PCB_GROUP*>( item )->RunOnDescendants( [&]( BOARD_ITEM* bItem )
800  {
801  m_commit->Modify( bItem );
802  });
803  }
804  }
805 
806  static_cast<BOARD_ITEM*>( item )->Rotate( refPt, rotateAngle );
807  }
808 
809  if( !m_dragging )
810  m_commit->Push( _( "Rotate" ) );
811 
812  if( selection.IsHover() && !m_dragging )
814 
816 
817  if( m_dragging )
819 
820  return 0;
821 }
822 
823 
827 static wxPoint mirrorPointX( const wxPoint& aPoint, const wxPoint& aMirrorPoint )
828 {
829  wxPoint mirrored = aPoint;
830 
831  mirrored.x -= aMirrorPoint.x;
832  mirrored.x = -mirrored.x;
833  mirrored.x += aMirrorPoint.x;
834 
835  return mirrored;
836 }
837 
838 
842 static void mirrorPadX( D_PAD& aPad, const wxPoint& aMirrorPoint )
843 {
844  if( aPad.GetShape() == PAD_SHAPE_CUSTOM )
845  aPad.FlipPrimitives( true ); // mirror primitives left to right
846 
847  wxPoint tmpPt = mirrorPointX( aPad.GetPosition(), aMirrorPoint );
848  aPad.SetPosition( tmpPt );
849 
850  aPad.SetX0( aPad.GetPosition().x );
851 
852  tmpPt = aPad.GetOffset();
853  tmpPt.x = -tmpPt.x;
854  aPad.SetOffset( tmpPt );
855 
856  auto tmpz = aPad.GetDelta();
857  tmpz.x = -tmpz.x;
858  aPad.SetDelta( tmpz );
859 
860  aPad.SetOrientation( -aPad.GetOrientation() );
861 }
862 
863 
864 int EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent )
865 {
866  if( isRouterActive() )
867  {
868  wxBell();
869  return 0;
870  }
871 
873  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, SELECTION_TOOL* sTool )
874  {
876  },
877  nullptr, !m_dragging );
878 
879  if( selection.Empty() )
880  return 0;
881 
883  auto refPoint = selection.GetReferencePoint();
884  wxPoint mirrorPoint( refPoint.x, refPoint.y );
885 
886  // When editing modules, all items have the same parent
887  if( EditingModules() )
888  m_commit->Modify( selection.Front() );
889 
890  for( EDA_ITEM* item : selection )
891  {
892  // only modify items we can mirror
893  switch( item->Type() )
894  {
895  case PCB_MODULE_EDGE_T:
896  case PCB_MODULE_TEXT_T:
898  case PCB_PAD_T:
899  // Only create undo entry for items on the board
900  if( !item->IsNew() && !EditingModules() )
901  m_commit->Modify( item );
902 
903  break;
904  default:
905  continue;
906  }
907 
908  // modify each object as necessary
909  switch( item->Type() )
910  {
911  case PCB_MODULE_EDGE_T:
912  {
913  EDGE_MODULE* edge = static_cast<EDGE_MODULE*>( item );
914  edge->Mirror( mirrorPoint, false );
915  break;
916  }
917 
919  {
920  MODULE_ZONE_CONTAINER* zone = static_cast<MODULE_ZONE_CONTAINER*>( item );
921  zone->Mirror( mirrorPoint, false );
922  break;
923  }
924 
925  case PCB_MODULE_TEXT_T:
926  {
927  TEXTE_MODULE* modText = static_cast<TEXTE_MODULE*>( item );
928  modText->Mirror( mirrorPoint, false );
929  break;
930  }
931 
932  case PCB_PAD_T:
933  {
934  D_PAD* pad = static_cast<D_PAD*>( item );
935  mirrorPadX( *pad, mirrorPoint );
936  break;
937  }
938 
939  default:
940  // it's likely the commit object is wrong if you get here
941  // Unsure if PCB_GROUP_T needs special attention here.
942  assert( false );
943  break;
944  }
945  }
946 
947  if( !m_dragging )
948  m_commit->Push( _( "Mirror" ) );
949 
950  if( selection.IsHover() && !m_dragging )
952 
954 
955  if( m_dragging )
957 
958  return 0;
959 }
960 
961 
962 int EDIT_TOOL::Flip( const TOOL_EVENT& aEvent )
963 {
964  if( isRouterActive() )
965  {
966  wxBell();
967  return 0;
968  }
969 
971  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, SELECTION_TOOL* sTool )
972  {
974  },
975  nullptr, !m_dragging );
976 
977  if( selection.Empty() )
978  return 0;
979 
981 
982  // Flip around the anchor for footprints, and the bounding box center for board items
983  VECTOR2I modPoint = EditingModules() ? VECTOR2I( 0, 0 ) : selection.GetCenter();
984 
985  // If only one item selected, flip around the item anchor point, instead
986  // of the bounding box center, to avoid moving the item anchor
987  if( selection.GetSize() == 1 )
988  modPoint = static_cast<BOARD_ITEM*>( selection.GetItem( 0 ) )->GetPosition();
989 
990  bool leftRight = frame()->Settings().m_FlipLeftRight;
991 
992  // When editing modules, all items have the same parent
993  if( EditingModules() )
994  m_commit->Modify( selection.Front() );
995 
996  for( EDA_ITEM* item : selection )
997  {
998  if( !item->IsNew() && !EditingModules() )
999  m_commit->Modify( item );
1000 
1001  if( item->Type() == PCB_GROUP_T )
1002  {
1003  static_cast<PCB_GROUP*>( item )->RunOnDescendants( [&]( BOARD_ITEM* bItem )
1004  {
1005  m_commit->Modify( bItem );
1006  });
1007  }
1008 
1009  static_cast<BOARD_ITEM*>( item )->Flip( modPoint, leftRight );
1010  }
1011 
1012  if( !m_dragging )
1013  m_commit->Push( _( "Flip" ) );
1014 
1015  if( selection.IsHover() && !m_dragging )
1017 
1019 
1020  if( m_dragging )
1022 
1023  return 0;
1024 }
1025 
1026 
1027 int EDIT_TOOL::Remove( const TOOL_EVENT& aEvent )
1028 {
1029  if( isRouterActive() )
1030  {
1031  wxBell();
1032  return 0;
1033  }
1034 
1035  std::vector<BOARD_ITEM*> lockedItems;
1036  Activate();
1037 
1038  // get a copy instead of reference (as we're going to clear the selection before removing items)
1039  PCBNEW_SELECTION selectionCopy;
1042 
1043  // If we are in a "Cut" operation, then the copied selection exists already
1044  if( isCut )
1045  {
1046  selectionCopy = m_selectionTool->GetSelection();
1047  }
1048  else
1049  {
1050  selectionCopy = m_selectionTool->RequestSelection(
1051  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, SELECTION_TOOL* sTool )
1052  {
1054  } );
1055  }
1056 
1057  bool isHover = selectionCopy.IsHover();
1058 
1059  // in "alternative" mode, deletion is not just a simple list of selected items,
1060  // it removes whole tracks, not just segments
1061  if( isAlt && isHover
1062  && ( selectionCopy.HasType( PCB_TRACE_T ) || selectionCopy.HasType( PCB_VIA_T ) ) )
1063  {
1065  }
1066 
1067  if( selectionCopy.Empty() )
1068  return 0;
1069 
1070  // N.B. Setting the CUT flag prevents lock filtering as we only want to delete the items that
1071  // were copied to the clipboard, no more, no fewer. Filtering for locked item, if any will be done
1072  // in the copyToClipboard() routine
1073  if( !m_lockedSelected && !isCut )
1074  {
1075  // Second RequestSelection removes locked items but keeps a copy of their pointers
1076  selectionCopy = m_selectionTool->RequestSelection(
1077  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, SELECTION_TOOL* sTool )
1078  {
1079  EditToolSelectionFilter( aCollector, EXCLUDE_LOCKED, sTool );
1080  },
1081  &lockedItems );
1082  }
1083 
1084 
1085  // As we are about to remove items, they have to be removed from the selection first
1087 
1088  PCBNEW_SELECTION removed;
1089 
1090  for( EDA_ITEM* item : selectionCopy )
1091  {
1092  if( m_editModules )
1093  {
1094  m_commit->Remove( item );
1095  removed.Add( item );
1096  continue;
1097  }
1098 
1099  switch( item->Type() )
1100  {
1101  case PCB_MODULE_TEXT_T:
1102  {
1103  TEXTE_MODULE* text = static_cast<TEXTE_MODULE*>( item );
1104  MODULE* parent = static_cast<MODULE*>( item->GetParent() );
1105 
1106  if( text->GetType() == TEXTE_MODULE::TEXT_is_DIVERS )
1107  {
1108  m_commit->Modify( text );
1109  getView()->Remove( text );
1110  parent->Remove( text );
1111  }
1112  }
1113  break;
1114 
1115  case PCB_PAD_T:
1116  {
1117  D_PAD* pad = static_cast<D_PAD*>( item );
1118  MODULE* parent = static_cast<MODULE*>( item->GetParent() );
1119 
1120  m_commit->Modify( parent );
1121  getView()->Remove( pad );
1122  parent->Remove( pad );
1123  }
1124  break;
1125 
1127  {
1128  MODULE_ZONE_CONTAINER* zone = static_cast<MODULE_ZONE_CONTAINER*>( item );
1129  MODULE* parent = static_cast<MODULE*>( item->GetParent() );
1130 
1131  m_commit->Modify( parent );
1132  getView()->Remove( zone );
1133  parent->Remove( zone );
1134  }
1135  break;
1136 
1137  case PCB_ZONE_AREA_T:
1138  // We process the zones special so that cutouts can be deleted when the delete tool
1139  // is called from inside a cutout when the zone is selected.
1140  {
1141  // Only interact with cutouts when deleting and a single item is selected
1142  if( !isCut && selectionCopy.GetSize() == 1 )
1143  {
1145  ZONE_CONTAINER* zone = static_cast<ZONE_CONTAINER*>( item );
1146 
1147  int outlineIdx, holeIdx;
1148 
1149  if( zone->HitTestCutout( curPos, &outlineIdx, &holeIdx ) )
1150  {
1151  // Remove the cutout
1152  m_commit->Modify( zone );
1153  zone->RemoveCutout( outlineIdx, holeIdx );
1154 
1155  std::vector<ZONE_CONTAINER*> toFill;
1156  toFill.emplace_back( zone );
1157 
1158  // Fill the modified zone
1159  ZONE_FILLER filler( board(), m_commit.get() );
1160  filler.InstallNewProgressReporter( frame(), _( "Fill Zone" ), 4 );
1161 
1162  if( !filler.Fill( toFill ) )
1163  {
1164  m_commit->Revert();
1165  return 1;
1166  }
1167 
1168  // Update the display
1169  zone->HatchBorder();
1170  canvas()->Refresh();
1171 
1172  // Restore the selection on the original zone
1174 
1175  break;
1176  }
1177  }
1178 
1179  // Remove the entire zone otherwise
1180  m_commit->Remove( item );
1181  removed.Add( item );
1182  }
1183  break;
1184 
1185  case PCB_GROUP_T:
1186  {
1187  m_commit->Remove( item );
1188  removed.Add( item );
1189 
1190  static_cast<PCB_GROUP*>( item )->RunOnDescendants( [&]( BOARD_ITEM* bItem )
1191  {
1192  m_commit->Remove( bItem );
1193  });
1194  }
1195  break;
1196 
1197  default:
1198  m_commit->Remove( item );
1199  removed.Add( item );
1200  break;
1201  }
1202  }
1203 
1204  // Figure out status of a group containing items to be removed. if entered
1205  // group is not set in the selection tool, then any groups to be removed are
1206  // removed in their entirety and so no empty group could remain. If entered
1207  // group is set, then we could be removing all items of the entered group,
1208  // in which case we need to remove the group itself.
1209  PCB_GROUP* enteredGroup = m_selectionTool->GetEnteredGroup();
1210 
1211  if( enteredGroup != nullptr )
1212  {
1213  board()->GroupRemoveItems( removed, m_commit.get() );
1214 
1215  if( m_commit->HasRemoveEntry( enteredGroup ) )
1217  }
1218 
1219  if( isCut )
1220  m_commit->Push( _( "Cut" ) );
1221  else
1222  m_commit->Push( _( "Delete" ) );
1223 
1224  if( enteredGroup != nullptr )
1225  {
1226  wxString check = board()->GroupsSanityCheck();
1227  wxCHECK_MSG( check == wxEmptyString, 0,
1228  _( "Remove of items in entered group resulted in inconsistent state: " )+ check );
1229  }
1230 
1231  if( !m_lockedSelected && !lockedItems.empty() )
1232  {
1234  m_lockedSelected = true;
1235  m_toolMgr->RunAction( PCB_ACTIONS::selectItems, true, &lockedItems );
1236  m_statusPopup->SetText( _( "Delete again to remove locked items" ) );
1237  m_statusPopup->PopupFor( 2000 );
1238  m_statusPopup->Move( wxGetMousePosition() + wxPoint( 20, 20 ) );
1239 
1240  Activate();
1241 
1242  while( m_lockedSelected && m_statusPopup->IsShown() )
1243  {
1244  m_statusPopup->Move( wxGetMousePosition() + wxPoint( 20, 20 ) );
1245  Wait();
1246  }
1247 
1248  // Ensure statusPopup is hidden after use
1249  m_statusPopup->Hide();
1250  }
1251 
1252  m_lockedSelected = false;
1253 
1254  return 0;
1255 }
1256 
1257 
1258 int EDIT_TOOL::MoveExact( const TOOL_EVENT& aEvent )
1259 {
1260  if( isRouterActive() )
1261  {
1262  wxBell();
1263  return 0;
1264  }
1265 
1267  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, SELECTION_TOOL* sTool )
1268  {
1269  EditToolSelectionFilter( aCollector,
1271  } );
1272 
1273  if( selection.Empty() )
1274  return 0;
1275 
1276  wxPoint translation;
1277  double rotation;
1278  ROTATION_ANCHOR rotationAnchor = selection.Size() > 1 ? ROTATE_AROUND_SEL_CENTER
1280 
1281  // TODO: Implement a visible bounding border at the edge
1282  auto sel_box = selection.GetBoundingBox();
1283 
1284  DIALOG_MOVE_EXACT dialog( frame(), translation, rotation, rotationAnchor, sel_box );
1285  int ret = dialog.ShowModal();
1286 
1287  if( ret == wxID_OK )
1288  {
1289  VECTOR2I rp = selection.GetCenter();
1290  wxPoint selCenter( rp.x, rp.y );
1291 
1292  // Make sure the rotation is from the right reference point
1293  selCenter += translation;
1294 
1295  // When editing modules, all items have the same parent
1296  if( EditingModules() )
1297  m_commit->Modify( selection.Front() );
1298 
1299  for( EDA_ITEM* selItem : selection )
1300  {
1301  BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selItem );
1302 
1303  if( !item->IsNew() && !EditingModules() )
1304  {
1305  m_commit->Modify( item );
1306 
1307  if( item->Type() == PCB_GROUP_T )
1308  {
1309  static_cast<PCB_GROUP*>( item )->RunOnDescendants(
1310  [&]( BOARD_ITEM* bItem )
1311  {
1312  m_commit->Modify( bItem );
1313  });
1314  }
1315  }
1316 
1317  item->Move( translation );
1318 
1319  switch( rotationAnchor )
1320  {
1322  item->Rotate( item->GetPosition(), rotation );
1323  break;
1325  item->Rotate( selCenter, rotation );
1326  break;
1328  item->Rotate( (wxPoint) frame()->GetScreen()->m_LocalOrigin, rotation );
1329  break;
1331  item->Rotate( board()->GetDesignSettings().m_AuxOrigin, rotation );
1332  break;
1333  }
1334 
1335  if( !m_dragging )
1336  getView()->Update( item );
1337  }
1338 
1339  m_commit->Push( _( "Move exact" ) );
1340 
1341  if( selection.IsHover() )
1343 
1345 
1346  if( m_dragging )
1348  }
1349 
1350  return 0;
1351 }
1352 
1353 
1354 int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent )
1355 {
1356  if( isRouterActive() )
1357  {
1358  wxBell();
1359  return 0;
1360  }
1361 
1362  bool increment = aEvent.IsAction( &PCB_ACTIONS::duplicateIncrement );
1363 
1364  // Be sure that there is at least one item that we can modify
1366  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, SELECTION_TOOL* sTool )
1367  {
1369  } );
1370 
1371  if( selection.Empty() )
1372  return 0;
1373 
1374  // we have a selection to work on now, so start the tool process
1375  PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();
1376 
1377  // If the selection was given a hover, we do not keep the selection after completion
1378  bool is_hover = selection.IsHover();
1379 
1380  std::vector<BOARD_ITEM*> new_items;
1381  new_items.reserve( selection.Size() );
1382 
1383 
1384  // Each selected item is duplicated and pushed to new_items list
1385  // Old selection is cleared, and new items are then selected.
1386  for( EDA_ITEM* item : selection )
1387  {
1388  BOARD_ITEM* dupe_item = nullptr;
1389  BOARD_ITEM* orig_item = static_cast<BOARD_ITEM*>( item );
1390 
1391  if( m_editModules )
1392  {
1393  MODULE* editModule = editFrame->GetBoard()->GetFirstModule();
1394  dupe_item = editModule->DuplicateItem( orig_item );
1395 
1396  if( increment && item->Type() == PCB_PAD_T
1397  && PAD_NAMING::PadCanHaveName( *static_cast<D_PAD*>( dupe_item ) ) )
1398  {
1399  PAD_TOOL* padTool = m_toolMgr->GetTool<PAD_TOOL>();
1400  wxString padName = padTool->GetLastPadName();
1401  padName = editModule->GetNextPadName( padName );
1402  padTool->SetLastPadName( padName );
1403  static_cast<D_PAD*>( dupe_item )->SetName( padName );
1404  }
1405  }
1406  else if( orig_item->GetParent() && orig_item->GetParent()->Type() == PCB_MODULE_T )
1407  {
1408  MODULE* parent = static_cast<MODULE*>( orig_item->GetParent() );
1409 
1410  m_commit->Modify( parent );
1411  dupe_item = parent->DuplicateItem( orig_item, true /* add to parent */ );
1412  }
1413  else
1414  {
1415  switch( orig_item->Type() )
1416  {
1417  case PCB_MODULE_T:
1418  case PCB_TEXT_T:
1419  case PCB_LINE_T:
1420  case PCB_TRACE_T:
1421  case PCB_VIA_T:
1422  case PCB_ZONE_AREA_T:
1423  case PCB_TARGET_T:
1424  case PCB_DIM_ALIGNED_T:
1425  case PCB_DIM_CENTER_T:
1426  case PCB_DIM_ORTHOGONAL_T:
1427  case PCB_DIM_LEADER_T:
1428  dupe_item = orig_item->Duplicate();
1429  break;
1430 
1431  case PCB_GROUP_T:
1432  dupe_item = static_cast<PCB_GROUP*>( orig_item )->DeepDuplicate();
1433  break;
1434 
1435  default:
1436  // Silently drop other items (such as footprint texts) from duplication
1437  break;
1438  }
1439  }
1440 
1441  if( dupe_item )
1442  {
1443  if( dupe_item->Type() == PCB_GROUP_T )
1444  {
1445  static_cast<PCB_GROUP*>( dupe_item )->RunOnDescendants( [&]( BOARD_ITEM* bItem )
1446  {
1447  m_commit->Add( bItem );
1448  });
1449  }
1450 
1451  // Clear the selection flag here, otherwise the SELECTION_TOOL
1452  // will not properly select it later on
1453  dupe_item->ClearSelected();
1454 
1455  new_items.push_back( dupe_item );
1456  m_commit->Add( dupe_item );
1457  }
1458  }
1459 
1460  // Clear the old selection first
1462 
1463  // Select the new items
1464  m_toolMgr->RunAction( PCB_ACTIONS::selectItems, true, &new_items );
1465 
1466  // record the new items as added
1467  if( !selection.Empty() )
1468  {
1469  editFrame->DisplayToolMsg( wxString::Format( _( "Duplicated %d item(s)" ),
1470  (int) new_items.size() ) );
1471 
1472  // If items were duplicated, pick them up
1473  // this works well for "dropping" copies around and pushes the commit
1475  Move( evt );
1476 
1477  // After moving the new items, we need to refresh the group and view flags
1479 
1480  if( !is_hover )
1481  m_toolMgr->RunAction( PCB_ACTIONS::selectItems, true, &new_items );
1482  }
1483 
1484  return 0;
1485 }
1486 
1487 
1489 {
1490  if( isRouterActive() )
1491  {
1492  wxBell();
1493  return 0;
1494  }
1495 
1497  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, SELECTION_TOOL* sTool )
1498  {
1500  } );
1501 
1502  if( selection.Empty() )
1503  return 0;
1504 
1505  // we have a selection to work on now, so start the tool process
1506  PCB_BASE_FRAME* editFrame = getEditFrame<PCB_BASE_FRAME>();
1507  ARRAY_CREATOR array_creator( *editFrame, m_editModules, selection );
1508  array_creator.Invoke();
1509 
1510  return 0;
1511 }
1512 
1513 
1515 {
1516  for( int i = aCollector.GetCount() - 1; i >= 0; i-- )
1517  {
1518  BOARD_ITEM* item = static_cast<BOARD_ITEM*>( aCollector[i] );
1519 
1520  if( item->Type() != PCB_PAD_T )
1521  aCollector.Remove( i );
1522  }
1523 }
1524 
1525 
1527 {
1528  for( int i = aCollector.GetCount() - 1; i >= 0; i-- )
1529  {
1530  BOARD_ITEM* item = static_cast<BOARD_ITEM*>( aCollector[i] );
1531 
1532  if( item->Type() != PCB_MODULE_T )
1533  aCollector.Remove( i );
1534  }
1535 }
1536 
1537 
1539 {
1540  if( m_dragging && aSelection.HasReferencePoint() )
1541  return false;
1542 
1543  // When there is only one item selected, the reference point is its position...
1544  if( aSelection.Size() == 1 )
1545  {
1546  auto item = static_cast<BOARD_ITEM*>( aSelection.Front() );
1547  auto pos = item->GetPosition();
1548  aSelection.SetReferencePoint( VECTOR2I( pos.x, pos.y ) );
1549  }
1550  // ...otherwise modify items with regard to the grid-snapped cursor position
1551  else
1552  {
1554  aSelection.SetReferencePoint( m_cursor );
1555  }
1556 
1557  return true;
1558 }
1559 
1560 
1561 bool EDIT_TOOL::pickReferencePoint( const wxString& aTooltip, const wxString& aSuccessMessage,
1562  const wxString& aCanceledMessage, VECTOR2I& aReferencePoint )
1563 {
1565  OPT<VECTOR2I> pickedPoint;
1566  bool done = false;
1567 
1568  m_statusPopup->SetText( aTooltip );
1569 
1570  picker->SetClickHandler(
1571  [&]( const VECTOR2D& aPoint ) -> bool
1572  {
1573  pickedPoint = aPoint;
1574 
1575  if( !aSuccessMessage.empty() )
1576  {
1577  m_statusPopup->SetText( aSuccessMessage );
1578  m_statusPopup->Expire( 800 );
1579  }
1580  else
1581  {
1582  m_statusPopup->Hide();
1583  }
1584 
1585  return false; // we don't need any more points
1586  } );
1587 
1588  picker->SetMotionHandler(
1589  [&]( const VECTOR2D& aPos )
1590  {
1591  m_statusPopup->Move( wxGetMousePosition() + wxPoint( 20, -50 ) );
1592  } );
1593 
1594  picker->SetCancelHandler(
1595  [&]()
1596  {
1597  if( !aCanceledMessage.empty() )
1598  {
1599  m_statusPopup->SetText( aCanceledMessage );
1600  m_statusPopup->Expire( 800 );
1601  }
1602  else
1603  {
1604  m_statusPopup->Hide();
1605  }
1606  } );
1607 
1608  picker->SetFinalizeHandler(
1609  [&]( const int& aFinalState )
1610  {
1611  done = true;
1612  } );
1613 
1614  m_statusPopup->Move( wxGetMousePosition() + wxPoint( 20, -50 ) );
1615  m_statusPopup->Popup();
1616 
1617  std::string tool = "";
1618  m_toolMgr->RunAction( ACTIONS::pickerTool, true, &tool );
1619 
1620  while( !done )
1621  Wait();
1622 
1623  // Ensure statusPopup is hidden after use and before deleting it:
1624  m_statusPopup->Hide();
1625 
1626  if( pickedPoint.is_initialized() )
1627  aReferencePoint = pickedPoint.get();
1628 
1629  return pickedPoint.is_initialized();
1630 }
1631 
1632 
1634 {
1635  std::string tool = "pcbnew.InteractiveEdit.selectReferencePoint";
1636  CLIPBOARD_IO io;
1637  GRID_HELPER grid( m_toolMgr, getEditFrame<PCB_BASE_EDIT_FRAME>()->GetMagneticItemsSettings() );
1638 
1639  frame()->PushTool( tool );
1640  Activate();
1641 
1643  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, SELECTION_TOOL* sTool ) {
1645  } );
1646 
1647  if( !selection.Empty() )
1648  {
1649  m_statusPopup->SetText( _( "Selection copied" ) );
1650  m_statusPopup->Move( wxGetMousePosition() + wxPoint( 20, 20 ) );
1651 
1652  std::vector<BOARD_ITEM*> items;
1653 
1654  for( EDA_ITEM* item : selection )
1655  items.push_back( static_cast<BOARD_ITEM*>( item ) );
1656 
1657  VECTOR2I refPoint = grid.BestDragOrigin( getViewControls()->GetCursorPosition( false ), items );
1658  selection.SetReferencePoint( refPoint );
1659 
1660  io.SetBoard( board() );
1662  m_statusPopup->Expire( 800 );
1663  m_statusPopup->Show();
1664  }
1665 
1666  frame()->PopTool( tool );
1667 
1668  return 0;
1669 }
1670 
1671 
1673 {
1674  if( !copyToClipboard( aEvent ) )
1675  {
1676  // N.B. Setting the CUT flag prevents lock filtering as we only want to delete the items that
1677  // were copied to the clipboard, no more, no fewer. Filtering for locked item, if any will be done
1678  // in the copyToClipboard() routine
1679  TOOL_EVENT evt( aEvent.Category(), aEvent.Action(), TOOL_ACTION_SCOPE::AS_GLOBAL );
1681  Remove( evt );
1682  }
1683 
1684  return 0;
1685 }
1686 
1687 
1689 {
1691  Go( &EDIT_TOOL::Move, PCB_ACTIONS::move.MakeEvent() );
1692  Go( &EDIT_TOOL::Drag, PCB_ACTIONS::drag45Degree.MakeEvent() );
1694  Go( &EDIT_TOOL::Rotate, PCB_ACTIONS::rotateCw.MakeEvent() );
1695  Go( &EDIT_TOOL::Rotate, PCB_ACTIONS::rotateCcw.MakeEvent() );
1696  Go( &EDIT_TOOL::Flip, PCB_ACTIONS::flip.MakeEvent() );
1697  Go( &EDIT_TOOL::Remove, ACTIONS::doDelete.MakeEvent() );
1698  Go( &EDIT_TOOL::Remove, PCB_ACTIONS::deleteFull.MakeEvent() );
1702  Go( &EDIT_TOOL::Duplicate, ACTIONS::duplicate.MakeEvent() );
1705  Go( &EDIT_TOOL::Mirror, PCB_ACTIONS::mirror.MakeEvent() );
1707 
1708  Go( &EDIT_TOOL::copyToClipboard, ACTIONS::copy.MakeEvent() );
1709  Go( &EDIT_TOOL::cutToClipboard, ACTIONS::cut.MakeEvent() );
1710 }
1711 
1712 
static TOOL_ACTION selectItems
Selects a list of items (specified as the event parameter)
Definition: pcb_actions.h:69
static TOOL_ACTION selectionClear
Clears the current selection.
Definition: pcb_actions.h:62
VECTOR2I GetReferencePoint() const
Definition: selection.h:240
virtual void ShowCursor(bool aEnabled)
Function ShowCursor() Enables or disables display of cursor.
static bool ShowAlways(const SELECTION &aSelection)
The default condition function (always returns true).
void setTransitions() override
Sets up handlers for various events.
Definition: edit_tool.cpp:1688
void AddMenu(ACTION_MENU *aMenu, const SELECTION_CONDITION &aCondition=SELECTION_CONDITIONS::ShowAlways, int aOrder=ANY_ORDER)
Adds a submenu to the menu.
VECTOR2I m_cursor
Definition: edit_tool.h:205
void ClearReferencePoint()
Definition: selection.h:250
ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:61
void HatchBorder()
Function HatchBorder computes the hatch lines depending on the hatch parameters and stores it in the ...
Definition: class_zone.cpp:906
bool IsCurrentTool(const TOOL_ACTION &aAction) const
void Mirror(const wxPoint &aMirrorRef, bool aMirrorLeftRight)
Function Mirror Mirror the outlines , relative to a given horizontal axis the layer is not changed.
Definition: class_zone.cpp:727
int Properties(const TOOL_EVENT &aEvent)
Function Properties() Displays properties window for the selected object.
Definition: edit_tool.cpp:715
int Rotate(const TOOL_EVENT &aEvent)
Function Rotate() Rotates currently selected items.
Definition: edit_tool.cpp:762
static TOOL_ACTION move
move or drag an item
Definition: pcb_actions.h:95
static TOOL_ACTION deleteFull
Definition: pcb_actions.h:124
class ALIGNED_DIMENSION, a linear dimension (graphic item)
Definition: typeinfo.h:101
class LEADER, a leader dimension (graphic item)
Definition: typeinfo.h:102
bool IsHover() const
Definition: selection.h:71
static const KICAD_T Tracks[]
A scan list for only TRACKS.
Definition: collectors.h:313
#define INCLUDE_PADS_AND_MODULES
Definition: edit_tool.h:56
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Function Wait()
virtual VECTOR2D GetMousePosition(bool aWorldCoordinates=true) const =0
Function GetMousePosition() Returns the current mouse pointer position.
BOARD * board() const
static TOOL_ACTION editFpInFpEditor
Definition: pcb_actions.h:328
int GetCurrentViaDrill() const
Function GetCurrentViaDrill.
static TOOL_ACTION pageSettings
Definition: actions.h:59
REMOVE_FLAGS
Remove event modifier flags
Definition: actions.h:194
int GetCurrentTrackWidth() const
Function GetCurrentTrackWidth.
static TOOL_ACTION changeTrackWidth
Updates selected tracks & vias to the current track & via dimensions.
Definition: pcb_actions.h:111
void EditToolSelectionFilter(GENERAL_COLLECTOR &aCollector, int aFlags, SELECTION_TOOL *selectionTool)
Definition: edit_tool.cpp:63
This file is part of the common library.
static TOOL_ACTION doDelete
Definition: actions.h:75
BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
bool HasType(KICAD_T aType) const
Checks if there is at least one item of requested kind.
Definition: selection.h:214
class PCB_GROUP, a set of BOARD_ITEMs
Definition: typeinfo.h:109
std::unique_ptr< BOARD_COMMIT > m_commit
Definition: edit_tool.h:207
wxPoint GetPosition() const override
Definition: class_pad.h:165
void ClearSelected()
Definition: base_struct.h:211
void SetCurrentCursor(wxStockCursor aStockCursorID)
Function SetCurrentCursor Set the current cursor shape for this panel.
VIEW_CONTROLS class definition.
PCB_GROUP is a set of BOARD_ITEMs (i.e., without duplicates)
TOOL_ACTIONS Action() const
Returns more specific information about the type of an event.
Definition: tool_event.h:250
static SELECTION_CONDITION OnlyTypes(const KICAD_T aTypes[])
Creates a functor that tests if the selected items are only of given types.
SELECTION_TOOL.
void FlipPrimitives(bool aFlipLeftRight)
Flip (mirror) the primitives left to right or top to bottom, around the anchor position in custom pad...
Definition: class_pad.cpp:587
class CENTER_DIMENSION, a center point marking (graphic item)
Definition: typeinfo.h:103
int ChangeTrackWidth(const TOOL_EVENT &aEvent)
Definition: edit_tool.cpp:659
SELECTION_LOCK_FLAGS CheckLock()
Checks if the user has agreed to modify locked items for the given selection.
virtual VECTOR2I GetCenter() const
Returns the center point of the selection area bounding box.
Definition: selection.h:138
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
CONDITIONAL_MENU & GetMenu()
Function GetMenu.
Definition: tool_menu.cpp:46
static TOOL_ACTION dragFreeAngle
Definition: pcb_actions.h:135
Tool is invoked after being inactive.
Definition: tool_base.h:81
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:219
virtual void OnEditItemRequest(BOARD_ITEM *aItem)=0
Function OnEditItemRequest Install the corresponding dialog editor for the given item.
virtual void PushTool(const std::string &actionName)
NB: the definition of "tool" is different at the user level.
class ZONE_CONTAINER, a zone area
Definition: typeinfo.h:106
virtual void Remove(VIEW_ITEM *aItem)
Function Remove() Removes a VIEW_ITEM from the view.
Definition: view.cpp:375
static TOOL_ACTION properties
Activation of the edit tool.
Definition: pcb_actions.h:114
PADS & Pads()
Definition: class_module.h:181
bool PadCanHaveName(const D_PAD &aPad)
Check if a pad should be named.
Definition: pad_naming.cpp:26
PAD_TOOL.
Definition: pad_tool.h:37
TOOL_MENU & GetToolMenu()
class TEXTE_PCB, text on a layer
Definition: typeinfo.h:92
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Function RunAction() Runs the specified action.
Definition: tool_manager.h:140
static TOOL_ACTION selectConnection
Selects tracks between junctions or expands an existing selection to pads or the entire connection.
Definition: pcb_actions.h:77
static TOOL_ACTION getAndPlace
Find an item and start moving.
Definition: pcb_actions.h:447
void SetPosition(const wxPoint &aPos) override
Definition: class_pad.h:159
void SaveSelection(const PCBNEW_SELECTION &selected, bool isModEdit)
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:537
static TOOL_ACTION drag45Degree
Definition: pcb_actions.h:134
TOOL_EVENT_CATEGORY Category() const
Returns the category (eg. mouse/keyboard/action) of an event..
Definition: tool_event.h:247
static TOOL_ACTION mirror
Mirroring of selected items.
Definition: pcb_actions.h:108
virtual void SetCursorPosition(const VECTOR2D &aPosition, bool aWarpView=true, bool aTriggeredByArrows=false, long aArrowCommand=0)=0
Moves cursor to the requested position expressed in world coordinates.
static TOOL_ACTION changeFootprint
Definition: pcb_actions.h:308
class D_PAD, a pad in a footprint
Definition: typeinfo.h:90
static TOOL_ACTION updateFootprint
Definition: pcb_actions.h:306
void UndoRedoBlock(bool aBlock=true)
Function UndoRedoBlock Enables/disable undo and redo operations.
virtual MAGNETIC_SETTINGS * GetMagneticItemsSettings()
TOOL_BASE * FindTool(int aId) const
Function FindTool() Searches for a tool with given ID.
virtual wxPoint GetPosition() const
Definition: base_struct.h:337
void RemoveCutout(int aOutlineIdx, int aHoleIdx)
Remove a cutout from the zone.
Definition: class_zone.cpp:772
SELECTION_TOOL * m_selectionTool
Definition: edit_tool.h:202
static SELECTION_CONDITION Count(int aNumber)
Creates a functor that tests if the number of selected items is equal to the value given as parameter...
VECTOR2< int > VECTOR2I
Definition: vector2d.h:594
void SetBoard(BOARD *aBoard)
static bool NotEmpty(const SELECTION &aSelection)
Tests if there are any items selected.
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
void SetFinalizeHandler(FINALIZE_HANDLER aHandler)
Function SetFinalizeHandler() Sets a handler for the finalize event.
void Remove(int aIndex)
Function Remove removes the item at aIndex (first position is 0);.
Definition: collector.h:130
static const TOOL_EVENT SelectedItemsModified
Definition: actions.h:211
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:96
int Mirror(const TOOL_EVENT &aEvent)
Function Mirror Mirrors the current selection.
Definition: edit_tool.cpp:864
void InstallNewProgressReporter(wxWindow *aParent, const wxString &aTitle, int aNumPhases)
Definition: zone_filler.cpp:71
const VC_SETTINGS & GetSettings() const
Returns the current VIEW_CONTROLS settings
virtual void Add(EDA_ITEM *aItem)
Definition: selection.h:76
bool IsNew() const
Definition: base_struct.h:199
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:67
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:1672
bool pickReferencePoint(const wxString &aTooltip, const wxString &aSuccessMessage, const wxString &aCanceledMessage, VECTOR2I &aReferencePoint)
Definition: edit_tool.cpp:1561
PCBNEW_SELECTION & GetSelection()
Function GetSelection()
static TOOL_ACTION pickerTool
Definition: actions.h:151
void Append(EDA_ITEM *item)
Function Append adds an item to the end of the list.
Definition: collector.h:120
const LSET GetSelectionLayers()
PCB_BASE_EDIT_FRAME * frame() const
bool m_lockedSelected
Definition: edit_tool.h:204
void GroupRemoveItems(const PCBNEW_SELECTION &selection, BOARD_COMMIT *commit)
void SetParameter(T aParam)
Function SetParameter() Sets a non-standard parameter assigned to the event.
Definition: tool_event.h:453
int GetCount() const
Function GetCount returns the number of objects in the list.
Definition: collector.h:101
class MODULE, a footprint
Definition: typeinfo.h:89
static TOOL_ACTION copy
Definition: actions.h:70
int Flip(const TOOL_EVENT &aEvent)
Function Flip() Rotates currently selected items.
Definition: edit_tool.cpp:962
void SetReferencePoint(const VECTOR2I &aP)
Definition: selection.h:245
static TOOL_ACTION duplicateIncrement
Activation of the duplication tool with incrementing (e.g. pad number)
Definition: pcb_actions.h:120
bool HitTestWorksheetItems(VIEW *aView, const wxPoint &aPosition)
bool isInteractiveDragEnabled() const
Definition: edit_tool.cpp:275
int GetAndPlace(const TOOL_EVENT &aEvent)
Find an item and start moving.
Definition: edit_tool.cpp:229
Generic tool for picking a point.
static TOOL_ACTION rotateCw
Rotation of selected objects.
Definition: pcb_actions.h:101
VECTOR2I BestDragOrigin(const VECTOR2I &aMousePos, std::vector< BOARD_ITEM * > &aItem)
LSET is a set of PCB_LAYER_IDs.
const PCBNEW_SELECTION & selection() const
void SetLastPadName(const wxString &aPadName)
Definition: pad_tool.h:74
void PutDataInPreviousState(PICKED_ITEMS_LIST *aList, bool aRedoCommand, bool aRebuildRatsnet=true)
Function PutDataInPreviousState Used in undo or redo command.
Definition: undo_redo.cpp:393
#define NULL
int doMoveSelection(TOOL_EVENT aEvent, bool aPickReference=false)
Definition: edit_tool.cpp:330
wxString GetLastPadName() const
Definition: pad_tool.h:73
bool m_dragging
Definition: edit_tool.h:203
bool ProcessEvent(const TOOL_EVENT &aEvent)
Propagates an event to tools that requested events of matching type(s).
static void FootprintFilter(const VECTOR2I &, GENERAL_COLLECTOR &aCollector, SELECTION_TOOL *sTool)
Function FootprintFilter() A selection filter which prunes the selection to contain only items of typ...
Definition: edit_tool.cpp:1526
virtual void Move(const wxPoint &aMoveVector)
Function Move move this object.
virtual void PopTool(const std::string &actionName)
int ShowQuasiModal()
SELECTION_LOCK_FLAGS
Definition: selection.h:279
T Parameter() const
Function Parameter() Returns a non-standard parameter assigned to the event.
Definition: tool_event.h:435
void SetIcon(const BITMAP_OPAQUE *aIcon)
Assigns an icon for the entry.
Definition: action_menu.cpp:71
const wxPoint & GetOffset() const
Definition: class_pad.h:233
TOOL_EVENT.
Definition: tool_event.h:171
TEXT_TYPE GetType() const
static TOOL_ACTION createArray
Tool for creating an array of objects.
Definition: pcb_actions.h:370
void Mirror(const wxPoint &aCentre, bool aMirrorAroundXAxis)
Mirror an edge of the footprint.
static TOOL_ACTION cut
Definition: actions.h:69
MODULE * GetFirstModule() const
Gets the first module in the list (used in footprint viewer/editor) or NULL if none.
Definition: class_board.h:310
void FilterCollectorForGroups(GENERAL_COLLECTOR &aCollector) const
bool ToolStackIsEmpty()
Definition: tools_holder.h:117
bool HasItem(const EDA_ITEM *aItem) const
Function HasItem tests if aItem has already been collected.
Definition: collector.h:229
virtual PICKED_ITEMS_LIST * PopCommandFromUndoList()
PopCommandFromUndoList return the last command to undo and remove it from list nothing is deleted.
bool Init() override
Function Init() Init() is called once upon a registration of the tool.
Definition: edit_tool.cpp:152
VIEW_CONTROLS is an interface for classes handling user events controlling the view behaviour (such a...
int MoveWithReference(const TOOL_EVENT &aEvent)
Moves an item but with a reference point selected first.
Definition: edit_tool.cpp:316
int Drag(const TOOL_EVENT &aEvent)
Function Drag() Invoke the PNS router to drag tracks.
Definition: edit_tool.cpp:291
virtual void ForceCursorPosition(bool aEnabled, const VECTOR2D &aPosition=VECTOR2D(0, 0))
Function ForceCursorPosition() Places the cursor immediately at a given point.
wxString GetNextPadName(const wxString &aLastPadName) const
Function GetNextPadName returns the next available pad name in the module.
std::unique_ptr< STATUS_TEXT_POPUP > m_statusPopup
Definition: edit_tool.h:209
static const TOOL_EVENT SelectedItemsMoved
Definition: actions.h:214
virtual void Rotate(const wxPoint &aRotCentre, double aAngle)
Function Rotate Rotate this object.
void Remove(BOARD_ITEM *aItem) override
PICKED_ITEMS_LIST is a holder to handle information on schematic or board items.
const wxSize & GetDelta() const
Definition: class_pad.h:227
All active tools
Definition: tool_event.h:147
BOARD_ITEM * DuplicateItem(const BOARD_ITEM *aItem, bool aAddToModule=false)
Function DuplicateItem Duplicate a given item within the module, optionally adding it to the board.
virtual KIGFX::VIEW_ITEM * GetItem(unsigned int aIdx) const override
Definition: selection.h:105
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:1531
ROTATION_ANCHOR
bool IsLocked() const override
Function IsLocked.
Definition: class_module.h:311
static TOOL_ACTION routerInlineDrag
Activation of the Push and Shove router (inline dragging mode)
Definition: pcb_actions.h:199
static TOOL_ACTION hideDynamicRatsnest
Definition: pcb_actions.h:440
void RunOnDescendants(const std::function< void(BOARD_ITEM *)> &aFunction)
Invokes a function on all descendents of the group.
KIGFX::VIEW * getView() const
Function getView()
Definition: tool_base.cpp:36
virtual void SetAutoPan(bool aEnabled)
Function SetAutoPan Turns on/off auto panning (this feature is used when there is a tool active (eg.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=NULL) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
int Move(const TOOL_EVENT &aEvent)
Function Move() Main loop in which events are handled.
Definition: edit_tool.cpp:304
#define EXCLUDE_TRANSIENTS
Definition: edit_tool.h:55
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:121
class PCB_TARGET, a target (graphic item)
Definition: typeinfo.h:105
static TOOL_ACTION inlineBreakTrack
Breaks track when router is not activated.
Definition: pcb_actions.h:132
void Reset(RESET_REASON aReason) override
Function Reset() Brings the tool to a known, initial state.
Definition: edit_tool.cpp:128
bool EditingModules() const
void AddSeparator(int aOrder=ANY_ORDER)
Adds a separator to the menu.
virtual unsigned int GetSize() const override
Function GetSize() Returns the number of stored items.
Definition: selection.h:100
static TOOL_ACTION rotateCcw
Definition: pcb_actions.h:102
class TEXTE_MODULE, text in a footprint
Definition: typeinfo.h:93
int MoveExact(const TOOL_EVENT &aEvent)
Function MoveExact() Invokes a dialog box to allow moving of the item by an exact amount.
Definition: edit_tool.cpp:1258
OPT< std::string > GetCommandStr() const
Definition: tool_event.h:463
int Remove(const TOOL_EVENT &aEvent)
Function Remove() Deletes currently selected items.
Definition: edit_tool.cpp:1027
static ROUTER * theRouter
Definition: pns_router.cpp:63
static TOOL_ACTION flip
Flipping of selected objects.
Definition: pcb_actions.h:105
SPECIAL_TOOLS_CONTEXT_MENU(TOOL_INTERACTIVE *aTool)
Definition: edit_tool.cpp:139
int GetCurrentViaSize() const
Function GetCurrentViaSize.
NETINFO_ITEM handles the data for a net.
Definition: netinfo.h:65
virtual bool IsLocked() const
Function IsLocked.
bool invokeInlineRouter(int aDragMode)
Definition: edit_tool.cpp:247
bool HasReferencePoint() const
Definition: selection.h:235
class MARKER_PCB, a marker used to show something
Definition: typeinfo.h:99
PCB_GROUP * GetEnteredGroup()
void SetTitle(const wxString &aTitle) override
Sets title for the menu.
Definition: action_menu.cpp:89
int CreateArray(const TOOL_EVENT &aEvent)
Function CreateArray() Creates an array of the selected items, invoking the array editor dialog to se...
Definition: edit_tool.cpp:1488
KIGFX::WS_PROXY_VIEW_ITEM * GetWorksheet() const
PCBNEW_SELECTION & RequestSelection(CLIENT_SELECTION_FILTER aClientFilter, std::vector< BOARD_ITEM * > *aFiltered=nullptr, bool aConfirmLockedItems=false)
Function RequestSelection()
KIGFX::VIEW_CONTROLS * controls() const
Common, abstract interface for edit frames.
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:201
int GetNet() const
Function GetNet.
Definition: netinfo.h:223
MODULE * module() const
#define _(s)
Definition: 3d_actions.cpp:33
long m_lastKeyboardCursorCommand
ACTIONS::CURSOR_UP, ACTIONS::CURSOR_DOWN, etc.
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in a variety of units (the basic call r...
Definition: class_pad.h:321
Used when the right click button is pressed, or when the select tool is in effect.
Definition: collectors.h:240
bool HitTestCutout(const VECTOR2I &aRefPos, int *aOutlineIdx=nullptr, int *aHoleIdx=nullptr) const
Tests if the given point is contained within a cutout of the zone.
Definition: class_zone.cpp:488
void AddSubMenu(std::shared_ptr< ACTION_MENU > aSubMenu)
Function CreateSubMenu.
Definition: tool_menu.cpp:52
static void PadFilter(const VECTOR2I &, GENERAL_COLLECTOR &aCollector, SELECTION_TOOL *sTool)
Function PadFilter() A selection filter which prunes the selection to contain only items of type PCB_...
Definition: edit_tool.cpp:1514
bool m_lastKeyboardCursorPositionValid
Is last cursor motion event coming from keyboard arrow cursor motion action
bool IsToolActive() const
Definition: tool_base.cpp:31
static TOOL_ACTION selectItem
Selects an item (specified as the event parameter).
Definition: pcb_actions.h:65
static SELECTION_CONDITION OnlyType(KICAD_T aType)
Creates a functor that tests if the selected items are only of given type.
PCBNEW_SETTINGS & Settings()
TOOL_EVENT MakeEvent() const
Returns the event associated with the action (i.e.
Definition: tool_action.h:113
int Size() const
Returns the number of selected parts.
Definition: selection.h:127
bool isRouterActive() const
Definition: edit_tool.cpp:283
EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boards.
Definition: base_struct.h:159
static wxPoint mirrorPointX(const wxPoint &aPoint, const wxPoint &aMirrorPoint)
Definition: edit_tool.cpp:827
void SetMotionHandler(MOTION_HANDLER aHandler)
Function SetMotionHandler() Sets a handler for mouse motion.
MODULE_ZONE_CONTAINER is the same item as ZONE_CONTAINER, but with a specific type id ZONE_CONTAINER ...
Definition: class_zone.h:953
static TOOL_ACTION positionRelative
Activation of the position relative tool.
Definition: pcb_actions.h:220
RESET_REASON
Determines the reason of reset for a tool
Definition: tool_base.h:79
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 GetMicroViaDrillSize()
Function GetViaDrillSize returns the size of via drills used to route this net.
Definition: netinfo.h:188
boost::optional< T > OPT
Definition: optional.h:7
void SetOrientation(double aAngle)
Function SetOrientation sets the rotation angle of the pad.
Definition: class_pad.cpp:519
bool PadsLocked() const
Definition: class_module.h:347
bool GetMoveWarpsCursor() const
Indicates that a move operation should warp the mouse pointer to the origin of the move object.
Definition: tools_holder.h:140
void Activate()
Function Activate() Runs the tool.
wxString GroupsSanityCheck(bool repair=false)
virtual BOARD_ITEM * Duplicate() const
Function Duplicate creates a copy of a BOARD_ITEM.
class ORTHOGONAL_DIMENSION, a linear dimension constrained to x/y
Definition: typeinfo.h:104
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
static TOOL_ACTION undo
Definition: actions.h:67
void ExitGroup(bool aSelectGroup=false)
Leave the currently entered group.
void SetX0(int x)
Definition: class_pad.h:221
wxPoint GetPosition() const override
Definition: class_module.h:219
#define EXCLUDE_LOCKED
Function EditToolSelectionFilter.
Definition: edit_tool.h:53
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:1633
PAD_SHAPE_T GetShape() const
Definition: class_pad.h:157
static TOOL_ACTION updateLocalRatsnest
Definition: pcb_actions.h:441
BOARD * GetBoard() const
KIGFX::VIEW_CONTROLS * getViewControls() const
Function getViewControls()
Definition: tool_base.cpp:42
class ZONE_CONTAINER, managed by a footprint
Definition: typeinfo.h:95
ROUTER * Router() const
#define EXCLUDE_LOCKED_PADS
Definition: edit_tool.h:54
EDGE_MODULE class definition.
class DRAWSEGMENT, a segment not on copper layers
Definition: typeinfo.h:91
PCB_DRAW_PANEL_GAL * canvas() const
int GetMicroViaSize()
Function GetMicroViaSize returns the size of vias used to route this net.
Definition: netinfo.h:168
BOARD_ITEM_CONTAINER * GetParent() const
static TOOL_ACTION moveWithReference
move with a reference point
Definition: pcb_actions.h:98
int GetEventRotationAngle(const PCB_BASE_EDIT_FRAME &aFrame, const TOOL_EVENT &aEvt)
Function getEventRotationAngle()
void SetOffset(const wxPoint &aOffset)
Definition: class_pad.h:232
bool updateModificationPoint(PCBNEW_SELECTION &aSelection)
Returns the right modification point (e.g.
Definition: edit_tool.cpp:1538
void SetCancelHandler(CANCEL_HANDLER aHandler)
Function SetCancelHandler() Sets a handler for cancel events (ESC or context-menu Cancel).
void PostEvent(const TOOL_EVENT &aEvent)
Puts an event to the event queue to be processed at the end of event processing cycle.
Definition: tool_manager.h:273
int Duplicate(const TOOL_EVENT &aEvent)
Function Duplicate() Duplicates the current selection and starts a move action.
Definition: edit_tool.cpp:1354
void AddItem(const TOOL_ACTION &aAction, const SELECTION_CONDITION &aCondition, int aOrder=ANY_ORDER)
Adds a menu entry to run a TOOL_ACTION on selected items.
static TOOL_ACTION selectAll
Definition: actions.h:73
EDA_RECT GetBoundingBox() const
Definition: selection.h:156
ROUTING_SETTINGS & Settings()
Definition: pns_router.h:203
static void mirrorPadX(D_PAD &aPad, const wxPoint &aMirrorPoint)
Mirror a pad in the vertical axis passing through a point (mirror left to right)
Definition: edit_tool.cpp:842
bool IsEmpty() const
Definition: class_board.h:292
static TOOL_ACTION paste
Definition: actions.h:71
PCB_BASE_FRAME basic PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
static TOOL_ACTION duplicate
Definition: actions.h:74
void ClearListAndDeleteItems()
Function ClearListAndDeleteItems deletes the list of pickers, AND the data pointed by m_PickedItem or...
static TOOL_ACTION refreshPreview
Definition: actions.h:104
void SetDelta(const wxSize &aSize)
Definition: class_pad.h:226
VECTOR2D GetCursorPosition() const
Returns the current cursor position in world coordinates.
EDA_ITEM * Front() const
Definition: selection.h:184
void DisplayToolMsg(const wxString &msg) override
const BITMAP_OPAQUE options_board_xpm[1]
KICAD_T Type() const
Function Type()
Definition: base_struct.h:193
bool IsLayerVisible(int aLayer) const
Function IsLayerVisible() Returns information about visibility of a particular layer.
Definition: view.h:405
void SetClickHandler(CLICK_HANDLER aHandler)
Function SetClickHandler() Sets a handler for mouse click event.