KiCad PCB EDA Suite
drawing_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) 2014-2017 CERN
5  * Copyright (C) 2018-2020 KiCad Developers, see AUTHORS.txt for contributors.
6  * @author Maciej Suminski <maciej.suminski@cern.ch>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
26 #include "drawing_tool.h"
27 #include "pcb_actions.h"
28 #include <pcb_edit_frame.h>
29 #include <confirm.h>
31 #include <view/view_controls.h>
32 #include <view/view.h>
33 #include <tool/tool_manager.h>
35 #include <board_commit.h>
36 #include <scoped_set_reset.h>
37 #include <bitmaps.h>
38 #include <painter.h>
39 #include <status_popup.h>
42 
43 #include <class_board.h>
44 #include <class_edge_mod.h>
45 #include <class_pcb_text.h>
46 #include <class_dimension.h>
47 #include <class_zone.h>
48 #include <class_module.h>
49 
52 #include <ratsnest/ratsnest_data.h>
53 #include <tools/grid_helper.h>
54 #include <tools/point_editor.h>
55 #include <tools/selection_tool.h>
56 #include <tools/tool_event_utils.h>
58 #include <pcbnew_id.h>
60 
62 
63 
64 class VIA_SIZE_MENU : public ACTION_MENU
65 {
66 public:
68  ACTION_MENU( true )
69  {
71  SetTitle( _( "Select Via Size" ) );
72  }
73 
74 protected:
75  ACTION_MENU* create() const override
76  {
77  return new VIA_SIZE_MENU();
78  }
79 
80  void update() override
81  {
83  EDA_UNITS units = frame->GetUserUnits();
85  bool useIndex = !bds.m_UseConnectedTrackWidth
86  && !bds.UseCustomTrackViaSize();
87  wxString msg;
88 
89  Clear();
90 
91  Append( ID_POPUP_PCB_SELECT_CUSTOM_WIDTH, _( "Use Custom Values..." ),
92  _( "Specify custom track and via sizes" ), wxITEM_CHECK );
94 
95  AppendSeparator();
96 
97  for( unsigned i = 1; i < bds.m_ViasDimensionsList.size(); i++ )
98  {
100 
101  if( via.m_Drill > 0 )
102  msg.Printf( _("Via %s, drill %s" ),
103  MessageTextFromValue( units, via.m_Diameter, true ),
104  MessageTextFromValue( units, via.m_Drill, true ) );
105  else
106  msg.Printf( _( "Via %s" ), MessageTextFromValue( units, via.m_Diameter, true ) );
107 
108  int menuIdx = ID_POPUP_PCB_SELECT_VIASIZE1 + i;
109  Append( menuIdx, msg, wxEmptyString, wxITEM_CHECK );
110  Check( menuIdx, useIndex && bds.GetViaSizeIndex() == i );
111  }
112  }
113 
114  OPT_TOOL_EVENT eventHandler( const wxMenuEvent& aEvent ) override
115  {
118  int id = aEvent.GetId();
119 
120  // On Windows, this handler can be called with an event ID not existing in any
121  // menuitem, so only set flags when we have an ID match.
122 
124  {
125  DIALOG_TRACK_VIA_SIZE sizeDlg( frame, bds );
126 
127  if( sizeDlg.ShowModal() )
128  {
129  bds.UseCustomTrackViaSize( true );
130  bds.m_UseConnectedTrackWidth = false;
131  }
132  }
134  {
135  bds.UseCustomTrackViaSize( false );
136  bds.m_UseConnectedTrackWidth = false;
138  }
139 
140  return OPT_TOOL_EVENT( PCB_ACTIONS::trackViaSizeChanged.MakeEvent() );
141  }
142 };
143 
144 
146  PCB_TOOL_BASE( "pcbnew.InteractiveDrawing" ),
147  m_view( nullptr ), m_controls( nullptr ),
148  m_board( nullptr ), m_frame( nullptr ), m_mode( MODE::NONE ),
149  m_lineWidth( 1 )
150 {
151 }
152 
153 
155 {
156 }
157 
158 
160 {
161  auto activeToolFunctor = [this]( const SELECTION& aSel )
162  {
163  return m_mode != MODE::NONE;
164  };
165 
166  // some interactive drawing tools can undo the last point
167  auto canUndoPoint = [this]( const SELECTION& aSel )
168  {
169  return ( m_mode == MODE::ARC
170  || m_mode == MODE::ZONE
171  || m_mode == MODE::KEEPOUT
173  };
174 
175  // functor for tools that can automatically close the outline
176  auto canCloseOutline = [this]( const SELECTION& aSel )
177  {
178  return ( m_mode == MODE::ZONE
179  || m_mode == MODE::KEEPOUT
181  };
182 
183  auto viaToolActive = [this]( const SELECTION& aSel )
184  {
185  return m_mode == MODE::VIA;
186  };
187 
188  auto& ctxMenu = m_menu.GetMenu();
189 
190  // cancel current tool goes in main context menu at the top if present
191  ctxMenu.AddItem( ACTIONS::cancelInteractive, activeToolFunctor, 1 );
192  ctxMenu.AddSeparator( 1 );
193 
194  // tool-specific actions
195  ctxMenu.AddItem( PCB_ACTIONS::closeOutline, canCloseOutline, 200 );
196  ctxMenu.AddItem( PCB_ACTIONS::deleteLastPoint, canUndoPoint, 200 );
197 
198  ctxMenu.AddSeparator( 500 );
199 
200  std::shared_ptr<VIA_SIZE_MENU> viaSizeMenu = std::make_shared<VIA_SIZE_MENU>();
201  viaSizeMenu->SetTool( this );
202  m_menu.AddSubMenu( viaSizeMenu );
203  ctxMenu.AddMenu( viaSizeMenu.get(), viaToolActive, 500 );
204 
205  ctxMenu.AddSeparator( 500 );
206 
207  // Type-specific sub-menus will be added for us by other tools
208  // For example, zone fill/unfill is provided by the PCB control tool
209 
210  // Finally, add the standard zoom/grid items
211  getEditFrame<PCB_BASE_FRAME>()->AddStandardSubMenus( m_menu );
212 
213  return true;
214 }
215 
216 
218 {
219  // Init variables used by every drawing tool
220  m_view = getView();
222  m_board = getModel<BOARD>();
223  m_frame = getEditFrame<PCB_BASE_EDIT_FRAME>();
224 }
225 
226 
228 {
229  return m_mode;
230 }
231 
232 
233 int DRAWING_TOOL::DrawLine( const TOOL_EVENT& aEvent )
234 {
235  if( m_editModules && !m_frame->GetModel() )
236  return 0;
237 
238  MODULE* module = dynamic_cast<MODULE*>( m_frame->GetModel() );
239  DRAWSEGMENT* line = m_editModules ? new EDGE_MODULE( module ) : new DRAWSEGMENT;
240  BOARD_COMMIT commit( m_frame );
241  SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::LINE );
242  OPT<VECTOR2D> startingPoint = boost::make_optional<VECTOR2D>( false, VECTOR2D( 0, 0 ) );
243 
244  line->SetFlags( IS_NEW );
245 
246  if( aEvent.HasPosition() )
247  startingPoint = getViewControls()->GetCursorPosition( !aEvent.Modifier( MD_ALT ) );
248 
249  std::string tool = aEvent.GetCommandStr().get();
250  m_frame->PushTool( tool );
251  Activate();
252 
253  while( drawSegment( tool, S_SEGMENT, &line, startingPoint ) )
254  {
255  if( line )
256  {
257  if( m_editModules )
258  static_cast<EDGE_MODULE*>( line )->SetLocalCoord();
259 
260  commit.Add( line );
261  commit.Push( _( "Draw a line segment" ) );
262  startingPoint = VECTOR2D( line->GetEnd() );
263  }
264  else
265  {
266  startingPoint = NULLOPT;
267  }
268 
269  line = m_editModules ? new EDGE_MODULE( module ) : new DRAWSEGMENT;
270  line->SetFlags( IS_NEW );
271  }
272 
273  return 0;
274 }
275 
276 
278 {
279  if( m_editModules && !m_frame->GetModel() )
280  return 0;
281 
282  MODULE* module = dynamic_cast<MODULE*>( m_frame->GetModel() );
283  DRAWSEGMENT* rect = m_editModules ? new EDGE_MODULE( module ) : new DRAWSEGMENT;
284  BOARD_COMMIT commit( m_frame );
285  SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::RECTANGLE );
286  OPT<VECTOR2D> startingPoint = boost::make_optional<VECTOR2D>( false, VECTOR2D( 0, 0 ) );
287 
288  rect->SetFlags(IS_NEW );
289 
290  if( aEvent.HasPosition() )
291  startingPoint = getViewControls()->GetCursorPosition( !aEvent.Modifier( MD_ALT ) );
292 
293  std::string tool = aEvent.GetCommandStr().get();
294  m_frame->PushTool( tool );
295  Activate();
296 
297  while( drawSegment( tool, S_RECT, &rect, startingPoint ) )
298  {
299  if( rect )
300  {
301  if( m_editModules )
302  static_cast<EDGE_MODULE*>( rect )->SetLocalCoord();
303 
304  commit.Add( rect );
305  commit.Push( _( "Draw a rectangle" ) );
306 
308  }
309 
310  rect = m_editModules ? new EDGE_MODULE( module ) : new DRAWSEGMENT;
311  rect->SetFlags(IS_NEW );
312  startingPoint = NULLOPT;
313  }
314 
315  return 0;
316 }
317 
318 
320 {
321  if( m_editModules && !m_frame->GetModel() )
322  return 0;
323 
324  MODULE* module = dynamic_cast<MODULE*>( m_frame->GetModel() );
325  DRAWSEGMENT* circle = m_editModules ? new EDGE_MODULE( module ) : new DRAWSEGMENT;
326  BOARD_COMMIT commit( m_frame );
327  SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::CIRCLE );
328  OPT<VECTOR2D> startingPoint = boost::make_optional<VECTOR2D>( false, VECTOR2D( 0, 0 ) );
329 
330  circle->SetFlags( IS_NEW );
331 
332  if( aEvent.HasPosition() )
333  startingPoint = getViewControls()->GetCursorPosition( !aEvent.Modifier( MD_ALT ) );
334 
335  std::string tool = aEvent.GetCommandStr().get();
336  m_frame->PushTool( tool );
337  Activate();
338 
339  while( drawSegment( tool, S_CIRCLE, &circle, startingPoint ) )
340  {
341  if( circle )
342  {
343  if( m_editModules )
344  static_cast<EDGE_MODULE*>( circle )->SetLocalCoord();
345 
346  commit.Add( circle );
347  commit.Push( _( "Draw a circle" ) );
348 
349  m_toolMgr->RunAction( PCB_ACTIONS::selectItem, true, circle );
350  }
351 
352  circle = m_editModules ? new EDGE_MODULE( module ) : new DRAWSEGMENT;
353  circle->SetFlags( IS_NEW );
354  startingPoint = NULLOPT;
355  }
356 
357  return 0;
358 }
359 
360 
361 int DRAWING_TOOL::DrawArc( const TOOL_EVENT& aEvent )
362 {
363  if( m_editModules && !m_frame->GetModel() )
364  return 0;
365 
366  MODULE* module = dynamic_cast<MODULE*>( m_frame->GetModel() );
368  BOARD_COMMIT commit( m_frame );
369  SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::ARC );
370  bool immediateMode = aEvent.HasPosition();
371 
372  arc->SetFlags( IS_NEW );
373 
374  std::string tool = aEvent.GetCommandStr().get();
375  m_frame->PushTool( tool );
376  Activate();
377 
378  while( drawArc( tool, &arc, immediateMode ) )
379  {
380  if( arc )
381  {
382  if( m_editModules )
383  static_cast<EDGE_MODULE*>( arc )->SetLocalCoord();
384 
385  commit.Add( arc );
386  commit.Push( _( "Draw an arc" ) );
387 
389  }
390 
391  arc = m_editModules ? new EDGE_MODULE( module ) : new DRAWSEGMENT;
392  arc->SetFlags( IS_NEW );
393  immediateMode = false;
394  }
395 
396  return 0;
397 }
398 
399 
401 {
402  if( m_editModules && !m_frame->GetModel() )
403  return 0;
404 
405  BOARD_ITEM* text = NULL;
406  const BOARD_DESIGN_SETTINGS& dsnSettings = m_frame->GetDesignSettings();
407  BOARD_COMMIT commit( m_frame );
408 
410  m_controls->ShowCursor( true );
411  // do not capture or auto-pan until we start placing some text
412 
413  SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::TEXT );
414 
415  std::string tool = aEvent.GetCommandStr().get();
416  m_frame->PushTool( tool );
417  Activate();
418 
419  // Prime the pump
420  if( aEvent.HasPosition() )
422 
423  // Main loop: keep receiving events
424  while( TOOL_EVENT* evt = Wait() )
425  {
426  m_frame->GetCanvas()->SetCurrentCursor( text ? wxCURSOR_ARROW : wxCURSOR_PENCIL );
427  VECTOR2I cursorPos = m_controls->GetCursorPosition();
428 
429  auto cleanup = [&]()
430  {
433  m_controls->ShowCursor( true );
434  m_controls->SetAutoPan( false );
435  m_controls->CaptureCursor( false );
436  delete text;
437  text = NULL;
438  };
439 
440  if( evt->IsCancelInteractive() )
441  {
442  if( text )
443  cleanup();
444  else
445  {
446  m_frame->PopTool( tool );
447  break;
448  }
449  }
450  else if( evt->IsActivate() )
451  {
452  if( text )
453  cleanup();
454 
455  if( evt->IsMoveTool() )
456  {
457  // leave ourselves on the stack so we come back after the move
458  break;
459  }
460  else
461  {
462  m_frame->PopTool( tool );
463  break;
464  }
465  }
466  else if( evt->IsClick( BUT_RIGHT ) )
467  {
469  }
470  else if( evt->IsClick( BUT_LEFT ) )
471  {
472  bool placing = text != nullptr;
473 
474  if( !text )
475  {
478 
479  // Init the new item attributes
480  if( m_editModules )
481  {
482  TEXTE_MODULE* textMod = new TEXTE_MODULE( (MODULE*) m_frame->GetModel() );
483 
484  textMod->SetLayer( layer );
485  textMod->SetTextSize( dsnSettings.GetTextSize( layer ) );
486  textMod->SetTextThickness( dsnSettings.GetTextThickness( layer ) );
487  textMod->SetItalic( dsnSettings.GetTextItalic( layer ) );
488  textMod->SetKeepUpright( dsnSettings.GetTextUpright( layer ) );
489  textMod->SetTextPos( (wxPoint) cursorPos );
490 
491  text = textMod;
492 
493  DIALOG_TEXT_PROPERTIES textDialog( m_frame, textMod );
494  bool cancelled;
495 
496  RunMainStack( [&]()
497  {
498  cancelled = !textDialog.ShowModal()
499  || textMod->GetText().IsEmpty();
500  } );
501 
502  if( cancelled )
503  {
504  delete text;
505  text = nullptr;
506  }
507  else if( textMod->GetTextPos() != (wxPoint) cursorPos )
508  {
509  // If the user modified the location then go ahead and place it there.
510  // Otherwise we'll drag.
511  placing = true;
512  }
513  }
514  else
515  {
516  TEXTE_PCB* textPcb = new TEXTE_PCB( m_frame->GetModel() );
517  // TODO we have to set IS_NEW, otherwise InstallTextPCB.. creates an undo entry :| LEGACY_CLEANUP
518  textPcb->SetFlags( IS_NEW );
519 
520  textPcb->SetLayer( layer );
521 
522  // Set the mirrored option for layers on the BACK side of the board
523  if( IsBackLayer( layer ) )
524  textPcb->SetMirrored( true );
525 
526  textPcb->SetTextSize( dsnSettings.GetTextSize( layer ) );
527  textPcb->SetTextThickness( dsnSettings.GetTextThickness( layer ) );
528  textPcb->SetItalic( dsnSettings.GetTextItalic( layer ) );
529  textPcb->SetTextPos( (wxPoint) cursorPos );
530 
531  RunMainStack( [&]()
532  {
533  m_frame->InstallTextOptionsFrame( textPcb );
534  } );
535 
536  if( textPcb->GetText().IsEmpty() )
537  delete textPcb;
538  else
539  text = textPcb;
540  }
541 
542  if( text )
543  {
544  m_controls->WarpCursor( text->GetPosition(), true );
546  m_view->Update( &selection() );
547  }
548  }
549 
550  if( placing )
551  {
552  text->ClearFlags();
554 
555  commit.Add( text );
556  commit.Push( _( "Place a text" ) );
557 
559 
560  text = nullptr;
561  }
562 
564  m_controls->ShowCursor( true );
565  m_controls->CaptureCursor( text != nullptr );
566  m_controls->SetAutoPan( text != nullptr );
567  }
568  else if( text && evt->IsMotion() )
569  {
570  text->SetPosition( (wxPoint) cursorPos );
571  selection().SetReferencePoint( cursorPos );
572  m_view->Update( &selection() );
573  }
574  else if( evt->IsAction( &PCB_ACTIONS::properties ) )
575  {
576  if( text )
577  {
578  frame()->OnEditItemRequest( text );
579  m_view->Update( &selection() );
580  frame()->SetMsgPanel( text );
581  }
582  }
583  else
584  evt->SetPassEvent();
585  }
586 
587  frame()->SetMsgPanel( board() );
588  return 0;
589 }
590 
591 
593 {
594  const VECTOR2I lineVector{ aDim->GetEnd() - aDim->GetStart() };
595 
596  aDim->SetEnd( wxPoint( VECTOR2I( aDim->GetStart() ) + GetVectorSnapped45( lineVector ) ) );
597 }
598 
599 
601 {
602  if( m_editModules && !m_frame->GetModel() )
603  return 0;
604 
605  TOOL_EVENT originalEvent = aEvent;
606  POINT_EDITOR* pointEditor = m_toolMgr->GetTool<POINT_EDITOR>();
607  DIMENSION* dimension = nullptr;
608  BOARD_COMMIT commit( m_frame );
610 
611  const BOARD_DESIGN_SETTINGS& boardSettings = m_board->GetDesignSettings();
612 
613  // Add a VIEW_GROUP that serves as a preview for the new item
614  PCBNEW_SELECTION preview;
615 
616  m_view->Add( &preview );
617 
619  m_controls->ShowCursor( true );
620 
621  SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::DIMENSION );
622 
623  std::string tool = aEvent.GetCommandStr().get();
624  m_frame->PushTool( tool );
625  Activate();
626 
627  enum DIMENSION_STEPS
628  {
629  SET_ORIGIN = 0,
630  SET_END,
631  SET_HEIGHT,
632  FINISHED
633  };
634  int step = SET_ORIGIN;
635 
636  // Prime the pump
638 
639  if( aEvent.HasPosition() )
640  m_toolMgr->PrimeTool( aEvent.Position() );
641 
642  // Main loop: keep receiving events
643  while( TOOL_EVENT* evt = Wait() )
644  {
645  if( !pointEditor->HasPoint() )
646  m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_PENCIL );
647 
648  grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
649  grid.SetUseGrid( m_frame->IsGridVisible() );
650  VECTOR2I cursorPos = grid.BestSnapAnchor(
651  evt->IsPrime() ? evt->Position() : m_controls->GetMousePosition(), nullptr );
652  m_controls->ForceCursorPosition( true, cursorPos );
653 
654  auto cleanup = [&]()
655  {
656  m_controls->SetAutoPan( false );
657  m_controls->CaptureCursor( false );
658 
659  preview.Clear();
660  m_view->Update( &preview );
661 
662  delete dimension;
663  dimension = nullptr;
664  step = SET_ORIGIN;
665  };
666 
667  if( evt->IsCancelInteractive() )
668  {
669  m_controls->SetAutoPan( false );
670 
671  if( step != SET_ORIGIN ) // start from the beginning
672  cleanup();
673  else
674  {
675  m_frame->PopTool( tool );
676  break;
677  }
678  }
679  else if( evt->IsActivate() )
680  {
681  if( step != SET_ORIGIN )
682  cleanup();
683 
684  if( evt->IsPointEditor() )
685  {
686  // don't exit (the point editor runs in the background)
687  }
688  else if( evt->IsMoveTool() )
689  {
690  // leave ourselves on the stack so we come back after the move
691  break;
692  }
693  else
694  {
695  m_frame->PopTool( tool );
696  break;
697  }
698  }
699  else if( evt->IsAction( &PCB_ACTIONS::incWidth ) && step != SET_ORIGIN )
700  {
702  dimension->SetLineThickness( m_lineWidth );
703  m_view->Update( &preview );
704  frame()->SetMsgPanel( dimension );
705  }
706  else if( evt->IsAction( &PCB_ACTIONS::decWidth ) && step != SET_ORIGIN )
707  {
708  if( m_lineWidth > WIDTH_STEP )
709  {
711  dimension->SetLineThickness( m_lineWidth );
712  m_view->Update( &preview );
713  frame()->SetMsgPanel( dimension );
714  }
715  }
716  else if( evt->IsClick( BUT_RIGHT ) )
717  {
719  }
720  else if( evt->IsClick( BUT_LEFT ) )
721  {
722  switch( step )
723  {
724  case SET_ORIGIN:
725  {
727 
729 
730  if( layer == Edge_Cuts ) // dimensions are not allowed on EdgeCuts
731  layer = Dwgs_User;
732 
733  // Init the new item attributes
734  auto setMeasurementAttributes =
735  [&]( DIMENSION* aDim )
736  {
737  aDim->SetUnitsMode( boardSettings.m_DimensionUnitsMode );
738  aDim->SetUnitsFormat( boardSettings.m_DimensionUnitsFormat );
739  aDim->SetPrecision( boardSettings.m_DimensionPrecision );
740  aDim->SetSuppressZeroes( boardSettings.m_DimensionSuppressZeroes );
741  aDim->SetTextPositionMode( boardSettings.m_DimensionTextPosition );
742  aDim->SetKeepTextAligned( boardSettings.m_DimensionKeepTextAligned );
743 
744  if( boardSettings.m_DimensionUnitsMode == DIM_UNITS_MODE::AUTOMATIC )
745  aDim->SetUnits( m_frame->GetUserUnits(), false );
746  };
747 
748  if( originalEvent.IsAction( &PCB_ACTIONS::drawAlignedDimension ) )
749  {
750  dimension = new ALIGNED_DIMENSION( m_board );
751  setMeasurementAttributes( dimension );
752  }
753  else if( originalEvent.IsAction( &PCB_ACTIONS::drawOrthogonalDimension ) )
754  {
755  dimension = new ORTHOGONAL_DIMENSION( m_board );
756  setMeasurementAttributes( dimension );
757  }
758  else if( originalEvent.IsAction( &PCB_ACTIONS::drawCenterDimension ) )
759  {
760  dimension = new CENTER_DIMENSION( m_board );
761  }
762  else if( originalEvent.IsAction( &PCB_ACTIONS::drawLeader ) )
763  {
764  dimension = new LEADER( m_board );
765  dimension->Text().SetPosition( wxPoint( cursorPos ) );
766  }
767  else
768  {
769  wxFAIL_MSG( "Unhandled action in DRAWING_TOOL::DrawDimension" );
770  }
771 
772  dimension->SetLayer( layer );
773  dimension->Text().SetTextSize( boardSettings.GetTextSize( layer ) );
774  dimension->Text().SetTextThickness( boardSettings.GetTextThickness( layer ) );
775  dimension->Text().SetItalic( boardSettings.GetTextItalic( layer ) );
776  dimension->SetLineThickness( boardSettings.GetLineThickness( layer ) );
777  dimension->SetArrowLength( boardSettings.m_DimensionArrowLength );
778  dimension->SetExtensionOffset( boardSettings.m_DimensionExtensionOffset );
779  dimension->SetStart( (wxPoint) cursorPos );
780  dimension->SetEnd( (wxPoint) cursorPos );
781 
782  preview.Add( dimension );
783 
784  m_controls->SetAutoPan( true );
785  m_controls->CaptureCursor( true );
786  }
787  break;
788 
789  case SET_END:
790  {
791  dimension->SetEnd( (wxPoint) cursorPos );
792 
793  if( !!evt->Modifier( MD_CTRL ) || dimension->Type() == PCB_DIM_CENTER_T )
794  constrainDimension( dimension );
795 
796  // Dimensions that have origin and end in the same spot are not valid
797  if( dimension->GetStart() == dimension->GetEnd() )
798  --step;
799  else if( dimension->Type() == PCB_DIM_LEADER_T )
800  dimension->SetText( wxT( "?" ) );
801 
802  if( dimension->Type() == PCB_DIM_CENTER_T )
803  {
804  // No separate height/text step
805  ++step;
807  }
808  else
809  break;
810  }
811 
812  case SET_HEIGHT:
813  {
814  if( dimension->Type() == PCB_DIM_LEADER_T )
815  {
816  assert( dimension->GetStart() != dimension->GetEnd() );
817  assert( dimension->GetLineThickness() > 0 );
818 
819  preview.Remove( dimension );
820 
821  commit.Add( dimension );
822  commit.Push( _( "Draw a leader" ) );
823 
824  // Run the edit immediately to set the leader text
825  m_toolMgr->RunAction( PCB_ACTIONS::properties, true, dimension );
826  }
827  else if( (wxPoint) cursorPos != dimension->GetPosition() )
828  {
829  assert( dimension->GetStart() != dimension->GetEnd() );
830  assert( dimension->GetLineThickness() > 0 );
831 
832  preview.Remove( dimension );
833 
834  commit.Add( dimension );
835  commit.Push( _( "Draw a dimension" ) );
836 
837  m_toolMgr->RunAction( PCB_ACTIONS::selectItem, true, dimension );
838  }
839 
840  break;
841  }
842  }
843 
844  if( ++step == FINISHED )
845  {
846  step = SET_ORIGIN;
847  m_controls->SetAutoPan( false );
848  m_controls->CaptureCursor( false );
849  }
850  }
851  else if( evt->IsMotion() )
852  {
853  switch( step )
854  {
855  case SET_END:
856  dimension->SetEnd( (wxPoint) cursorPos );
857 
858  if( !!evt->Modifier( MD_CTRL ) || dimension->Type() == PCB_DIM_CENTER_T )
859  constrainDimension( dimension );
860 
861  break;
862 
863  case SET_HEIGHT:
864  {
865  if( dimension->Type() == PCB_DIM_ALIGNED_T )
866  {
867  ALIGNED_DIMENSION* aligned = static_cast<ALIGNED_DIMENSION*>( dimension );
868 
869  // Calculating the direction of travel perpendicular to the selected axis
870  double angle = aligned->GetAngle() + ( M_PI / 2 );
871 
872  wxPoint delta( (wxPoint) cursorPos - dimension->GetEnd() );
873  double height = ( delta.x * cos( angle ) ) + ( delta.y * sin( angle ) );
874  aligned->SetHeight( height );
875  }
876  else if( dimension->Type() == PCB_DIM_ORTHOGONAL_T )
877  {
878  ORTHOGONAL_DIMENSION* ortho = static_cast<ORTHOGONAL_DIMENSION*>( dimension );
879 
880  BOX2I bounds( dimension->GetStart(),
881  dimension->GetEnd() - dimension->GetStart() );
882  VECTOR2I direction( cursorPos - bounds.Centre() );
883  bool vert = std::abs( direction.y ) < std::abs( direction.x );
884 
885  // Only change the orientation when we move outside the bounds
886  if( !bounds.Contains( cursorPos ) )
887  {
890  }
891  else
892  {
894  }
895 
896  VECTOR2I heightVector( cursorPos - dimension->GetStart() );
897  ortho->SetHeight( vert ? heightVector.x : heightVector.y );
898  }
899  else if( dimension->Type() == PCB_DIM_LEADER_T )
900  {
901  // Leader: SET_HEIGHT actually sets the text position directly
902  VECTOR2I lineVector( cursorPos - dimension->GetEnd() );
903  dimension->Text().SetPosition( wxPoint( VECTOR2I( dimension->GetEnd() ) +
904  GetVectorSnapped45( lineVector ) ) );
905  dimension->Update();
906  }
907  }
908  break;
909  }
910 
911  // Show a preview of the item
912  m_view->Update( &preview );
913  }
914  else if( evt->IsAction( &PCB_ACTIONS::properties ) )
915  {
916  if( step != SET_ORIGIN )
917  {
918  frame()->OnEditItemRequest( dimension );
919  dimension->Update();
920  frame()->SetMsgPanel( dimension );
921  }
922  }
923  else
924  evt->SetPassEvent();
925  }
926 
927  if( step != SET_ORIGIN )
928  delete dimension;
929 
930  m_controls->SetAutoPan( false );
932  m_controls->CaptureCursor( false );
933 
934  m_view->Remove( &preview );
935  frame()->SetMsgPanel( board() );
936  return 0;
937 }
938 
939 
941 {
942  if( !m_frame->GetModel() )
943  return 0;
944 
945  // Note: PlaceImportedGraphics() will convert PCB_LINE_T and PCB_TEXT_T to module graphic
946  // items if needed
948  int dlgResult = dlg.ShowModal();
949 
950  std::list<std::unique_ptr<EDA_ITEM>>& list = dlg.GetImportedItems();
951 
952  if( dlgResult != wxID_OK )
953  return 0;
954 
955  // Ensure the list is not empty:
956  if( list.empty() )
957  {
958  wxMessageBox( _( "No graphic items found in file to import") );
959  return 0;
960  }
961 
963 
964  // Add a VIEW_GROUP that serves as a preview for the new item
965  PCBNEW_SELECTION preview;
966  BOARD_COMMIT commit( m_frame );
967  PCB_GROUP* grp = nullptr;
968 
969  if( dlg.ShouldGroupItems() )
970  grp = new PCB_GROUP( m_frame->GetBoard() );
971 
972  // Build the undo list & add items to the current view
973  for( auto& ptr : list)
974  {
975  EDA_ITEM* item = ptr.get();
976 
977  if( m_editModules )
978  wxASSERT( item->Type() == PCB_MODULE_EDGE_T || item->Type() == PCB_MODULE_TEXT_T );
979  else
980  wxASSERT( item->Type() == PCB_LINE_T || item->Type() == PCB_TEXT_T );
981 
982  if( grp )
983  grp->AddItem( static_cast<BOARD_ITEM*>( item ) );
984  else if( dlg.IsPlacementInteractive() )
985  preview.Add( item );
986  else
987  commit.Add( item );
988 
989  ptr.release();
990  }
991 
992  if( !dlg.IsPlacementInteractive() )
993  {
994  if( grp )
995  {
996  grp->AddChildrenToCommit( commit );
997  commit.Add( grp );
998  }
999 
1000  commit.Push( _( "Place a DXF_SVG drawing" ) );
1001  return 0;
1002  }
1003 
1004  if( grp )
1005  preview.Add( grp );
1006 
1007  std::vector<BOARD_ITEM*> newItems;
1008 
1009  for( EDA_ITEM* item : preview )
1010  newItems.push_back( static_cast<BOARD_ITEM*>( item ) );
1011 
1012  BOARD_ITEM* firstItem = static_cast<BOARD_ITEM*>( preview.Front() );
1013  m_view->Add( &preview );
1014 
1015  // Clear the current selection then select the drawings so that edit tools work on them
1017  m_toolMgr->RunAction( PCB_ACTIONS::selectItems, true, &newItems );
1018 
1019  m_controls->ShowCursor( true );
1020  m_controls->ForceCursorPosition( false );
1021 
1022  SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::DXF );
1023 
1024  // Now move the new items to the current cursor position:
1025  VECTOR2I cursorPos = m_controls->GetCursorPosition();
1026  VECTOR2I delta = cursorPos - firstItem->GetPosition();
1027 
1028  for( EDA_ITEM* item : preview )
1029  static_cast<BOARD_ITEM*>( item )->Move( (wxPoint) delta );
1030 
1031  m_view->Update( &preview );
1032 
1033  std::string tool = aEvent.GetCommandStr().get();
1034  m_frame->PushTool( tool );
1035  Activate();
1036 
1037  // Main loop: keep receiving events
1038  while( TOOL_EVENT* evt = Wait() )
1039  {
1040  m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_ARROW );
1041  cursorPos = m_controls->GetCursorPosition();
1042 
1043  if( evt->IsCancelInteractive() || evt->IsActivate() )
1044  {
1046 
1047  // If a group is being used, we must delete the items themselves,
1048  // since they are only in the group and not in the preview
1049  if( grp )
1050  {
1051  grp->RunOnChildren( [&]( BOARD_ITEM* bItem )
1052  {
1053  delete bItem ;
1054  } );
1055  }
1056 
1057  preview.FreeItems();
1058  break;
1059  }
1060  else if( evt->IsMotion() )
1061  {
1062  delta = cursorPos - firstItem->GetPosition();
1063 
1064  for( auto item : preview )
1065  static_cast<BOARD_ITEM*>( item )->Move( (wxPoint) delta );
1066 
1067  m_view->Update( &preview );
1068  }
1069  else if( evt->IsClick( BUT_RIGHT ) )
1070  {
1072  }
1073  else if( evt->IsClick( BUT_LEFT ) )
1074  {
1075  // Place the imported drawings
1076  for( EDA_ITEM* item : preview )
1077  {
1078  if( item->Type() == PCB_GROUP_T )
1079  static_cast<PCB_GROUP*>( item )->AddChildrenToCommit( commit );
1080 
1081  commit.Add( item );
1082  }
1083 
1084  commit.Push( _( "Place a DXF_SVG drawing" ) );
1085  break; // This is a one-shot command, not a tool
1086  }
1087  else
1088  evt->SetPassEvent();
1089  }
1090 
1091  preview.Clear();
1092  m_view->Remove( &preview );
1093  m_frame->PopTool( tool );
1094  return 0;
1095 }
1096 
1097 
1099 {
1100  wxASSERT( m_editModules );
1101 
1102  if( !m_frame->GetModel() )
1103  return 0;
1104 
1105  SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::ANCHOR );
1107 
1108  std::string tool = aEvent.GetCommandStr().get();
1109  m_frame->PushTool( tool );
1110  Activate();
1111 
1113  m_controls->ShowCursor( true );
1114  m_controls->SetAutoPan( true );
1115  m_controls->CaptureCursor( false );
1116 
1117  while( TOOL_EVENT* evt = Wait() )
1118  {
1119  m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_BULLSEYE );
1120 
1121  grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
1122  grid.SetUseGrid( m_frame->IsGridVisible() );
1123  VECTOR2I cursorPos = grid.BestSnapAnchor( m_controls->GetMousePosition(), LSET::AllLayersMask() );
1124  m_controls->ForceCursorPosition( true, cursorPos );
1125 
1126  if( evt->IsClick( BUT_LEFT ) )
1127  {
1128  MODULE* module = (MODULE*) m_frame->GetModel();
1129  BOARD_COMMIT commit( m_frame );
1130  commit.Modify( module );
1131 
1132  // set the new relative internal local coordinates of footprint items
1133  wxPoint moveVector = module->GetPosition() - (wxPoint) cursorPos;
1134  module->MoveAnchorPosition( moveVector );
1135 
1136  commit.Push( _( "Move the footprint reference anchor" ) );
1137 
1138  // Usually, we do not need to change twice the anchor position,
1139  // so deselect the active tool
1140  m_frame->PopTool( tool );
1141  break;
1142  }
1143  else if( evt->IsClick( BUT_RIGHT ) )
1144  {
1146  }
1147  else if( evt->IsCancelInteractive() || evt->IsActivate() )
1148  {
1149  m_frame->PopTool( tool );
1150  break;
1151  }
1152  else
1153  evt->SetPassEvent();
1154  }
1155 
1156  return 0;
1157 }
1158 
1159 
1166 {
1167  auto vec = aMgr.GetOrigin();
1168 
1169  aGraphic->SetStart( { vec.x, vec.y } );
1170 
1171  vec = aMgr.GetEnd();
1172  aGraphic->SetEnd( { vec.x, vec.y } );
1173 }
1174 
1175 
1176 bool DRAWING_TOOL::drawSegment( const std::string& aTool, int aShape, DRAWSEGMENT** aGraphic,
1177  OPT<VECTOR2D> aStartingPoint )
1178 {
1179  // Only three shapes are currently supported
1180  assert( aShape == S_SEGMENT || aShape == S_CIRCLE || aShape == S_RECT );
1182  POINT_EDITOR* pointEditor = m_toolMgr->GetTool<POINT_EDITOR>();
1183  DRAWSEGMENT*& graphic = *aGraphic;
1184 
1186 
1187  // geometric construction manager
1189 
1190  // drawing assistant overlay
1191  // TODO: workaround because STROKE_T is not visible from commons.
1192  KIGFX::PREVIEW::GEOM_SHAPE geomShape( static_cast<KIGFX::PREVIEW::GEOM_SHAPE>( aShape ) );
1194  twoPointManager, m_frame->GetUserUnits(), geomShape );
1195 
1196  // Add a VIEW_GROUP that serves as a preview for the new item
1197  PCBNEW_SELECTION preview;
1198  m_view->Add( &preview );
1199  m_view->Add( &twoPointAsst );
1200 
1201  m_controls->ShowCursor( true );
1202 
1203  bool started = false;
1204  bool cancelled = false;
1205  bool isLocalOriginSet = ( m_frame->GetScreen()->m_LocalOrigin != VECTOR2D( 0, 0 ) );
1206  VECTOR2I cursorPos = m_controls->GetMousePosition();
1207 
1208  // Prime the pump
1210 
1211  if( aStartingPoint )
1213 
1214  frame()->SetMsgPanel( graphic );
1215  // Main loop: keep receiving events
1216  while( TOOL_EVENT* evt = Wait() )
1217  {
1218  if( !pointEditor->HasPoint() )
1219  m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_PENCIL );
1220 
1221  m_frame->SetMsgPanel( graphic );
1222 
1223  grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
1224  grid.SetUseGrid( m_frame->IsGridVisible() );
1225  cursorPos = grid.BestSnapAnchor( m_controls->GetMousePosition(), m_frame->GetActiveLayer() );
1226  m_controls->ForceCursorPosition( true, cursorPos );
1227 
1228  // 45 degree angle constraint enabled with an option and toggled with Ctrl
1229  bool limit45 = frame()->Settings().m_Use45DegreeGraphicSegments;
1230 
1231  if( evt->Modifier( MD_CTRL ) )
1232  limit45 = !limit45;
1233 
1234  auto cleanup = [&] () {
1235  preview.Clear();
1236  m_view->Update( &preview );
1237  delete graphic;
1238  graphic = nullptr;
1239 
1240  if( !isLocalOriginSet )
1241  m_frame->GetScreen()->m_LocalOrigin = VECTOR2D( 0, 0 );
1242  };
1243 
1244  if( evt->IsCancelInteractive() )
1245  {
1246  cleanup();
1247 
1248  if( !started )
1249  {
1250  m_frame->PopTool( aTool );
1251  cancelled = true;
1252  }
1253 
1254  break;
1255  }
1256  else if( evt->IsActivate() )
1257  {
1258  if( evt->IsPointEditor() )
1259  {
1260  // don't exit (the point editor runs in the background)
1261  }
1262  else if( evt->IsMoveTool() )
1263  {
1264  cleanup();
1265  // leave ourselves on the stack so we come back after the move
1266  cancelled = true;
1267  break;
1268  }
1269  else
1270  {
1271  cleanup();
1272  m_frame->PopTool( aTool );
1273  cancelled = true;
1274  break;
1275  }
1276  }
1277  else if( evt->IsAction( &PCB_ACTIONS::layerChanged ) )
1278  {
1280  graphic->SetLayer( m_frame->GetActiveLayer() );
1281  graphic->SetWidth( m_lineWidth );
1282  m_view->Update( &preview );
1283  frame()->SetMsgPanel( graphic );
1284  }
1285  else if( evt->IsAction( &PCB_ACTIONS::properties ) )
1286  {
1287  if( started )
1288  {
1289  frame()->OnEditItemRequest( graphic );
1290  m_view->Update( &preview );
1291  frame()->SetMsgPanel( graphic );
1292  }
1293  }
1294  else if( evt->IsClick( BUT_RIGHT ) )
1295  {
1297  }
1298  else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) )
1299  {
1300  if( !started )
1301  {
1303 
1304  if( aStartingPoint )
1305  {
1306  cursorPos = aStartingPoint.get();
1307  aStartingPoint = NULLOPT;
1308  }
1309 
1311 
1312  // Init the new item attributes
1313  graphic->SetShape( (STROKE_T) aShape );
1314  graphic->SetWidth( m_lineWidth );
1315  graphic->SetLayer( m_frame->GetActiveLayer() );
1316  grid.SetSkipPoint( cursorPos );
1317 
1318  twoPointManager.SetOrigin( (wxPoint) cursorPos );
1319  twoPointManager.SetEnd( (wxPoint) cursorPos );
1320 
1321  if( !isLocalOriginSet )
1322  m_frame->GetScreen()->m_LocalOrigin = cursorPos;
1323 
1324  preview.Add( graphic );
1325  frame()->SetMsgPanel( board() );
1326  m_controls->SetAutoPan( true );
1327  m_controls->CaptureCursor( true );
1328 
1329  updateSegmentFromConstructionMgr( twoPointManager, graphic );
1330 
1331  started = true;
1332  }
1333  else
1334  {
1335  auto snapItem = dyn_cast<DRAWSEGMENT*>( grid.GetSnapped() );
1336 
1337  if( twoPointManager.GetOrigin() == twoPointManager.GetEnd()
1338  || ( evt->IsDblClick( BUT_LEFT ) && aShape == S_SEGMENT ) || snapItem )
1339  // User has clicked twice in the same spot
1340  // or clicked on the end of an existing segment (closing a path)
1341  {
1342  BOARD_COMMIT commit( m_frame );
1343 
1344  // If the user clicks on an existing snap point from a drawsegment
1345  // we finish the segment as they are likely closing a path
1346  if( snapItem && ( aShape == S_RECT || graphic->GetLength() > 0.0 ) )
1347  {
1348  commit.Add( graphic );
1349  commit.Push( _( "Draw a line segment" ) );
1350  m_toolMgr->RunAction( PCB_ACTIONS::selectItem, true, graphic );
1351  }
1352  else
1353  {
1354  delete graphic;
1355  }
1356 
1357  graphic = nullptr;
1358  }
1359 
1360  preview.Clear();
1361  break;
1362  }
1363 
1364  twoPointManager.SetEnd( cursorPos );
1365  }
1366  else if( evt->IsMotion() )
1367  {
1368  // 45 degree lines
1369  if( ( limit45 && aShape == S_SEGMENT )
1370  || ( evt->Modifier( MD_CTRL ) && aShape == S_RECT ) )
1371  {
1372  const VECTOR2I lineVector( cursorPos - VECTOR2I( twoPointManager.GetOrigin() ) );
1373 
1374  // get a restricted 45/H/V line from the last fixed point to the cursor
1375  auto newEnd = GetVectorSnapped45( lineVector, ( aShape == S_RECT ) );
1376  m_controls->ForceCursorPosition( true, VECTOR2I( twoPointManager.GetEnd() ) );
1377  twoPointManager.SetEnd( twoPointManager.GetOrigin() + (wxPoint) newEnd );
1378  twoPointManager.SetAngleSnap( true );
1379  }
1380  else
1381  {
1382  twoPointManager.SetEnd( (wxPoint) cursorPos );
1383  twoPointManager.SetAngleSnap( false );
1384  }
1385 
1386  updateSegmentFromConstructionMgr( twoPointManager, graphic );
1387  m_view->Update( &preview );
1388  m_view->Update( &twoPointAsst );
1389  }
1390  else if( evt->IsAction( &PCB_ACTIONS::incWidth ) )
1391  {
1393  graphic->SetWidth( m_lineWidth );
1394  m_view->Update( &preview );
1395  frame()->SetMsgPanel( graphic );
1396  }
1397  else if( evt->IsAction( &PCB_ACTIONS::decWidth ) && ( m_lineWidth > WIDTH_STEP ) )
1398  {
1400  graphic->SetWidth( m_lineWidth );
1401  m_view->Update( &preview );
1402  frame()->SetMsgPanel( graphic );
1403  }
1404  else if( evt->IsAction( &ACTIONS::resetLocalCoords ) )
1405  {
1406  isLocalOriginSet = true;
1407  }
1408  else
1409  evt->SetPassEvent();
1410  }
1411 
1412  if( !isLocalOriginSet ) // reset the relative coordinte if it was not set before
1413  m_frame->GetScreen()->m_LocalOrigin = VECTOR2D( 0, 0 );
1414 
1415  m_view->Remove( &twoPointAsst );
1416  m_view->Remove( &preview );
1417  frame()->SetMsgPanel( board() );
1418  m_controls->SetAutoPan( false );
1419  m_controls->CaptureCursor( false );
1420  m_controls->ForceCursorPosition( false );
1421 
1422  return !cancelled;
1423 }
1424 
1425 
1431  DRAWSEGMENT& aArc )
1432 {
1433  auto vec = aMgr.GetOrigin();
1434 
1435  aArc.SetCenter( { vec.x, vec.y } );
1436 
1437  vec = aMgr.GetStartRadiusEnd();
1438  aArc.SetArcStart( { vec.x, vec.y } );
1439 
1440  aArc.SetAngle( RAD2DECIDEG( -aMgr.GetSubtended() ) );
1441 
1442  vec = aMgr.GetEndRadiusEnd();
1443  aArc.SetArcEnd( { vec.x, vec.y } );
1444 }
1445 
1446 
1447 bool DRAWING_TOOL::drawArc( const std::string& aTool, DRAWSEGMENT** aGraphic, bool aImmediateMode )
1448 {
1449  DRAWSEGMENT*& graphic = *aGraphic;
1451 
1452  // Arc geometric construction manager
1454 
1455  // Arc drawing assistant overlay
1456  KIGFX::PREVIEW::ARC_ASSISTANT arcAsst( arcManager, m_frame->GetUserUnits() );
1457 
1458  // Add a VIEW_GROUP that serves as a preview for the new item
1459  PCBNEW_SELECTION preview;
1460  m_view->Add( &preview );
1461  m_view->Add( &arcAsst );
1463 
1464  m_controls->ShowCursor( true );
1465 
1466  bool firstPoint = false;
1467  bool cancelled = false;
1468 
1469  // Prime the pump
1471 
1472  if( aImmediateMode )
1474 
1475  // Main loop: keep receiving events
1476  while( TOOL_EVENT* evt = Wait() )
1477  {
1478  PCB_LAYER_ID layer = m_frame->GetActiveLayer();
1479  graphic->SetLayer( layer );
1480 
1481  m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_PENCIL );
1482  grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
1483  grid.SetUseGrid( m_frame->IsGridVisible() );
1484  VECTOR2I cursorPos = grid.BestSnapAnchor( m_controls->GetMousePosition(), graphic );
1485  m_controls->ForceCursorPosition( true, cursorPos );
1486 
1487  auto cleanup = [&] () {
1488  preview.Clear();
1489  delete *aGraphic;
1490  *aGraphic = nullptr;
1491  };
1492 
1493  if( evt->IsCancelInteractive() )
1494  {
1495  cleanup();
1496 
1497  if( !firstPoint )
1498  {
1499  m_frame->PopTool( aTool );
1500  cancelled = true;
1501  }
1502 
1503  break;
1504  }
1505  else if( evt->IsActivate() )
1506  {
1507  if( evt->IsPointEditor() )
1508  {
1509  // don't exit (the point editor runs in the background)
1510  }
1511  else if( evt->IsMoveTool() )
1512  {
1513  cleanup();
1514  // leave ourselves on the stack so we come back after the move
1515  cancelled = true;
1516  break;
1517  }
1518  else
1519  {
1520  cleanup();
1521  m_frame->PopTool( aTool );
1522  cancelled = true;
1523  break;
1524  }
1525  }
1526  else if( evt->IsClick( BUT_LEFT ) )
1527  {
1528  if( !firstPoint )
1529  {
1531 
1532  m_controls->SetAutoPan( true );
1533  m_controls->CaptureCursor( true );
1534 
1536 
1537  // Init the new item attributes
1538  // (non-geometric, those are handled by the manager)
1539  graphic->SetShape( S_ARC );
1540  graphic->SetWidth( m_lineWidth );
1541 
1542  preview.Add( graphic );
1543  firstPoint = true;
1544  }
1545 
1546  arcManager.AddPoint( cursorPos, true );
1547  }
1548  else if( evt->IsAction( &PCB_ACTIONS::deleteLastPoint ) )
1549  {
1550  arcManager.RemoveLastPoint();
1551  }
1552  else if( evt->IsMotion() )
1553  {
1554  // set angle snap
1555  arcManager.SetAngleSnap( evt->Modifier( MD_CTRL ) );
1556 
1557  // update, but don't step the manager state
1558  arcManager.AddPoint( cursorPos, false );
1559  }
1560  else if( evt->IsAction( &PCB_ACTIONS::layerChanged ) )
1561  {
1563  graphic->SetLayer( m_frame->GetActiveLayer() );
1564  graphic->SetWidth( m_lineWidth );
1565  m_view->Update( &preview );
1566  frame()->SetMsgPanel( graphic );
1567  }
1568  else if( evt->IsAction( &PCB_ACTIONS::properties ) )
1569  {
1570  if( firstPoint )
1571  {
1572  frame()->OnEditItemRequest( graphic );
1573  m_view->Update( &preview );
1574  frame()->SetMsgPanel( graphic );
1575  }
1576  }
1577  else if( evt->IsClick( BUT_RIGHT ) )
1578  {
1580  }
1581  else if( evt->IsAction( &PCB_ACTIONS::incWidth ) )
1582  {
1584  graphic->SetWidth( m_lineWidth );
1585  m_view->Update( &preview );
1586  frame()->SetMsgPanel( graphic );
1587  }
1588  else if( evt->IsAction( &PCB_ACTIONS::decWidth ) && m_lineWidth > WIDTH_STEP )
1589  {
1591  graphic->SetWidth( m_lineWidth );
1592  m_view->Update( &preview );
1593  frame()->SetMsgPanel( graphic );
1594  }
1595  else if( evt->IsAction( &PCB_ACTIONS::arcPosture ) )
1596  {
1597  arcManager.ToggleClockwise();
1598  }
1599  else
1600  evt->SetPassEvent();
1601 
1602  if( arcManager.IsComplete() )
1603  {
1604  break;
1605  }
1606  else if( arcManager.HasGeometryChanged() )
1607  {
1608  updateArcFromConstructionMgr( arcManager, *graphic );
1609  m_view->Update( &preview );
1610  m_view->Update( &arcAsst );
1611 
1612  if( firstPoint )
1613  frame()->SetMsgPanel( graphic );
1614  else
1615  frame()->SetMsgPanel( board() );
1616  }
1617  }
1618 
1619  preview.Remove( graphic );
1620  m_view->Remove( &arcAsst );
1621  m_view->Remove( &preview );
1622  frame()->SetMsgPanel( board() );
1623  m_controls->SetAutoPan( false );
1624  m_controls->CaptureCursor( false );
1625  m_controls->ForceCursorPosition( false );
1626 
1627  return !cancelled;
1628 }
1629 
1630 
1632 {
1633  bool clearSelection = false;
1634  *aZone = nullptr;
1635 
1636  // not an action that needs a source zone
1637  if( aMode == ZONE_MODE::ADD || aMode == ZONE_MODE::GRAPHIC_POLYGON )
1638  return true;
1639 
1641  const PCBNEW_SELECTION& selection = selTool->GetSelection();
1642 
1643  if( selection.Empty() )
1644  {
1645  clearSelection = true;
1647  }
1648 
1649  // we want a single zone
1650  if( selection.Size() == 1 )
1651  *aZone = dyn_cast<ZONE_CONTAINER*>( selection[0] );
1652 
1653  // expected a zone, but didn't get one
1654  if( !*aZone )
1655  {
1656  if( clearSelection )
1658 
1659  return false;
1660  }
1661 
1662  return true;
1663 }
1664 
1666 {
1667  if( m_editModules && !m_frame->GetModel() )
1668  return 0;
1669 
1670  ZONE_MODE zoneMode = aEvent.Parameter<ZONE_MODE>();
1671  MODE drawMode = MODE::ZONE;
1672 
1673  if( aEvent.IsAction( &PCB_ACTIONS::drawRuleArea ) )
1674  drawMode = MODE::KEEPOUT;
1675 
1676  if( aEvent.IsAction( &PCB_ACTIONS::drawPolygon ) )
1677  drawMode = MODE::GRAPHIC_POLYGON;
1678 
1679  SCOPED_DRAW_MODE scopedDrawMode( m_mode, drawMode );
1680 
1681  // get a source zone, if we need one. We need it for:
1682  // ZONE_MODE::CUTOUT (adding a hole to the source zone)
1683  // ZONE_MODE::SIMILAR (creating a new zone using settings of source zone
1684  ZONE_CONTAINER* sourceZone = nullptr;
1685 
1686  if( !getSourceZoneForAction( zoneMode, &sourceZone ) )
1687  return 0;
1688 
1690 
1691  params.m_keepout = drawMode == MODE::KEEPOUT;
1692  params.m_mode = zoneMode;
1693  params.m_sourceZone = sourceZone;
1694 
1695  if( zoneMode == ZONE_MODE::SIMILAR )
1696  params.m_layer = sourceZone->GetLayer();
1697  else
1698  params.m_layer = m_frame->GetActiveLayer();
1699 
1700  ZONE_CREATE_HELPER zoneTool( *this, params );
1701 
1702  // the geometry manager which handles the zone geometry, and
1703  // hands the calculated points over to the zone creator tool
1704  POLYGON_GEOM_MANAGER polyGeomMgr( zoneTool );
1705  bool constrainAngle = false;
1706 
1707  std::string tool = aEvent.GetCommandStr().get();
1708  m_frame->PushTool( tool );
1709  Activate(); // register for events
1710 
1711  m_controls->ShowCursor( true );
1712 
1713  bool started = false;
1715  STATUS_TEXT_POPUP status( m_frame );
1716  status.SetTextColor( wxColour( 255, 0, 0 ) );
1717  status.SetText( _( "Self-intersecting polygons are not allowed" ) );
1718 
1719  // Prime the pump
1720  if( aEvent.HasPosition() )
1721  m_toolMgr->PrimeTool( aEvent.Position() );
1722 
1723  // Main loop: keep receiving events
1724  while( TOOL_EVENT* evt = Wait() )
1725  {
1726  m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_PENCIL );
1727  LSET layers( m_frame->GetActiveLayer() );
1728  grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
1729  grid.SetUseGrid( m_frame->IsGridVisible() );
1730  VECTOR2I cursorPos = grid.BestSnapAnchor( evt->IsPrime() ? evt->Position()
1732  layers );
1733  m_controls->ForceCursorPosition( true, cursorPos );
1734 
1735  if( ( sourceZone && sourceZone->GetHV45() ) || constrainAngle || evt->Modifier( MD_CTRL ) )
1737  else
1739 
1740  auto cleanup = [&] ()
1741  {
1742  polyGeomMgr.Reset();
1743  started = false;
1744  grid.ClearSkipPoint();
1745  m_controls->SetAutoPan( false );
1746  m_controls->CaptureCursor( false );
1747  };
1748 
1749  if( evt->IsCancelInteractive())
1750  {
1751  if( polyGeomMgr.IsPolygonInProgress() )
1752  cleanup();
1753  else
1754  {
1755  m_frame->PopTool( tool );
1756  break;
1757  }
1758  }
1759  else if( evt->IsActivate() )
1760  {
1761  if( polyGeomMgr.IsPolygonInProgress() )
1762  cleanup();
1763 
1764  if( evt->IsPointEditor() )
1765  {
1766  // don't exit (the point editor runs in the background)
1767  }
1768  else if( evt->IsMoveTool() )
1769  {
1770  // leave ourselves on the stack so we come back after the move
1771  break;
1772  }
1773  else
1774  {
1775  m_frame->PopTool( tool );
1776  break;
1777  }
1778  }
1779  else if( evt->IsAction( &PCB_ACTIONS::layerChanged ) )
1780  {
1781  if( zoneMode != ZONE_MODE::SIMILAR )
1782  params.m_layer = frame()->GetActiveLayer();
1783  }
1784  else if( evt->IsClick( BUT_RIGHT ) )
1785  {
1787  }
1788  // events that lock in nodes
1789  else if( evt->IsClick( BUT_LEFT )
1790  || evt->IsDblClick( BUT_LEFT )
1791  || evt->IsAction( &PCB_ACTIONS::closeOutline ) )
1792  {
1793  // Check if it is double click / closing line (so we have to finish the zone)
1794  const bool endPolygon = evt->IsDblClick( BUT_LEFT )
1795  || evt->IsAction( &PCB_ACTIONS::closeOutline )
1796  || polyGeomMgr.NewPointClosesOutline( cursorPos );
1797 
1798  if( endPolygon )
1799  {
1800  polyGeomMgr.SetFinished();
1801  polyGeomMgr.Reset();
1802 
1803  started = false;
1804  m_controls->SetAutoPan( false );
1805  m_controls->CaptureCursor( false );
1806  }
1807 
1808  // adding a corner
1809  else if( polyGeomMgr.AddPoint( cursorPos ) )
1810  {
1811  if( !started )
1812  {
1813  started = true;
1814  constrainAngle = ( polyGeomMgr.GetLeaderMode() ==
1816  m_controls->SetAutoPan( true );
1817  m_controls->CaptureCursor( true );
1818  }
1819  }
1820  }
1821  else if( evt->IsAction( &PCB_ACTIONS::deleteLastPoint ) )
1822  {
1823  polyGeomMgr.DeleteLastCorner();
1824 
1825  if( !polyGeomMgr.IsPolygonInProgress() )
1826  {
1827  // report finished as an empty shape
1828  polyGeomMgr.SetFinished();
1829 
1830  // start again
1831  started = false;
1832  m_controls->SetAutoPan( false );
1833  m_controls->CaptureCursor( false );
1834  }
1835  }
1836  else if( polyGeomMgr.IsPolygonInProgress()
1837  && ( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) )
1838  {
1839  polyGeomMgr.SetCursorPosition( cursorPos );
1840 
1841  if( polyGeomMgr.IsSelfIntersecting( true ) )
1842  {
1843  wxPoint p = wxGetMousePosition() + wxPoint( 20, 20 );
1844  status.Move( p );
1845  status.PopupFor( 1500 );
1846  }
1847  else
1848  {
1849  status.Hide();
1850  }
1851  }
1852  else if( evt->IsAction( &PCB_ACTIONS::properties ) )
1853  {
1854  if( started )
1855  {
1856  frame()->OnEditItemRequest( zoneTool.GetZone() );
1857  zoneTool.OnGeometryChange( polyGeomMgr );
1858  frame()->SetMsgPanel( zoneTool.GetZone() );
1859  }
1860  }
1861  else
1862  evt->SetPassEvent();
1863 
1864  } // end while
1865 
1866  m_controls->ForceCursorPosition( false );
1867  return 0;
1868 }
1869 
1870 
1871 int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
1872 {
1873  struct VIA_PLACER : public INTERACTIVE_PLACER_BASE
1874  {
1875  GRID_HELPER m_gridHelper;
1876 
1877  VIA_PLACER( PCB_BASE_EDIT_FRAME* aFrame ) :
1878  m_gridHelper( aFrame->GetToolManager(), aFrame->GetMagneticItemsSettings() )
1879  {}
1880 
1881  virtual ~VIA_PLACER()
1882  {
1883  }
1884 
1885  TRACK* findTrack( VIA* aVia )
1886  {
1887  const LSET lset = aVia->GetLayerSet();
1888  wxPoint position = aVia->GetPosition();
1889  BOX2I bbox = aVia->GetBoundingBox();
1890 
1891  std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> items;
1892  auto view = m_frame->GetCanvas()->GetView();
1893  std::vector<TRACK*> possible_tracks;
1894 
1895  view->Query( bbox, items );
1896 
1897  for( auto it : items )
1898  {
1899  BOARD_ITEM* item = static_cast<BOARD_ITEM*>( it.first );
1900 
1901  if( !(item->GetLayerSet() & lset ).any() )
1902  continue;
1903 
1904  if( auto track = dyn_cast<TRACK*>( item ) )
1905  {
1906  if( TestSegmentHit( position, track->GetStart(), track->GetEnd(),
1907  ( track->GetWidth() + aVia->GetWidth() ) / 2 ) )
1908  possible_tracks.push_back( track );
1909  }
1910  }
1911 
1912  TRACK* return_track = nullptr;
1913  int min_d = std::numeric_limits<int>::max();
1914  for( auto track : possible_tracks )
1915  {
1916  SEG test( track->GetStart(), track->GetEnd() );
1917  auto dist = ( test.NearestPoint( position ) - position ).EuclideanNorm();
1918 
1919  if( dist < min_d )
1920  {
1921  min_d = dist;
1922  return_track = track;
1923  }
1924  }
1925 
1926  return return_track;
1927  }
1928 
1929 
1930  bool hasDRCViolation( VIA* aVia )
1931  {
1932  const LSET lset = aVia->GetLayerSet();
1933  wxPoint position = aVia->GetPosition();
1934  int drillRadius = aVia->GetDrillValue() / 2;
1935  BOX2I bbox = aVia->GetBoundingBox();
1936 
1937  std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> items;
1938  int net = 0;
1939  int clearance = 0;
1940  auto view = m_frame->GetCanvas()->GetView();
1941  int holeToHoleMin = m_frame->GetBoard()->GetDesignSettings().m_HoleToHoleMin;
1942 
1943  view->Query( bbox, items );
1944 
1945  for( auto it : items )
1946  {
1947  BOARD_ITEM* item = static_cast<BOARD_ITEM*>( it.first );
1948 
1949  if( !(item->GetLayerSet() & lset ).any() )
1950  continue;
1951 
1952  if( TRACK* track = dyn_cast<TRACK*>( item ) )
1953  {
1954  int max_clearance = std::max( clearance,
1955  track->GetClearance( track->GetLayer() ) );
1956 
1957  if( TestSegmentHit( position, track->GetStart(), track->GetEnd(),
1958  ( track->GetWidth() + aVia->GetWidth() ) / 2 + max_clearance ) )
1959  {
1960  if( net && track->GetNetCode() != net )
1961  return true;
1962 
1963  net = track->GetNetCode();
1964  clearance = track->GetClearance( track->GetLayer() );
1965  }
1966  }
1967 
1968  if( VIA* via = dyn_cast<VIA*>( item ) )
1969  {
1970  int dist = KiROUND( GetLineLength( position, via->GetPosition() ) );
1971 
1972  if( dist < drillRadius + via->GetDrillValue() / 2 + holeToHoleMin )
1973  return true;
1974  }
1975 
1976  if( MODULE* mod = dyn_cast<MODULE*>( item ) )
1977  {
1978  for( D_PAD* pad : mod->Pads() )
1979  {
1980  for( PCB_LAYER_ID layer : pad->GetLayerSet().Seq() )
1981  {
1982  int max_clearance = std::max( clearance, pad->GetClearance( layer ) );
1983 
1984  if( pad->HitTest( aVia->GetBoundingBox(), false, max_clearance ) )
1985  {
1986  if( net && pad->GetNetCode() != net )
1987  return true;
1988 
1989  net = pad->GetNetCode();
1990  clearance = pad->GetClearance( layer );
1991  }
1992 
1993  if( pad->GetDrillSize().x && pad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
1994  {
1995  int dist = KiROUND( GetLineLength( position, pad->GetPosition() ) );
1996 
1997  if( dist < drillRadius + pad->GetDrillSize().x / 2 + holeToHoleMin )
1998  return true;
1999  }
2000  }
2001  }
2002  }
2003  }
2004 
2005  return false;
2006  }
2007 
2008 
2009  int findStitchedZoneNet( VIA* aVia )
2010  {
2011  const wxPoint position = aVia->GetPosition();
2012  const LSET lset = aVia->GetLayerSet();
2013 
2014  for( auto mod : m_board->Modules() )
2015  {
2016  for( D_PAD* pad : mod->Pads() )
2017  {
2018  if( pad->HitTest( position ) && ( pad->GetLayerSet() & lset ).any() )
2019  return -1;
2020  }
2021  }
2022 
2023  std::vector<ZONE_CONTAINER*> foundZones;
2024 
2025  for( ZONE_CONTAINER* zone : m_board->Zones() )
2026  {
2027  for( PCB_LAYER_ID layer : LSET( zone->GetLayerSet() & lset ).Seq() )
2028  if( zone->HitTestFilledArea( layer, position ) )
2029  foundZones.push_back( zone );
2030  }
2031 
2032  std::sort( foundZones.begin(), foundZones.end(),
2033  [] ( const ZONE_CONTAINER* a, const ZONE_CONTAINER* b )
2034  {
2035  return a->GetLayer() < b->GetLayer();
2036  } );
2037 
2038  // first take the net of the active layer
2039  for( ZONE_CONTAINER* z : foundZones )
2040  {
2041  if( m_frame->GetActiveLayer() == z->GetLayer() )
2042  return z->GetNetCode();
2043  }
2044 
2045  // none? take the topmost visible layer
2046  for( ZONE_CONTAINER* z : foundZones )
2047  {
2048  if( m_board->IsLayerVisible( z->GetLayer() ) )
2049  return z->GetNetCode();
2050  }
2051 
2052  return -1;
2053  }
2054 
2055  void SnapItem( BOARD_ITEM *aItem ) override
2056  {
2057  // If you place a Via on a track but not on its centerline, the current
2058  // connectivity algorithm will require us to put a kink in the track when
2059  // we break it (so that each of the two segments ends on the via center).
2060  // That's not ideal, and is in fact probably worse than forcing snap in
2061  // this situation.
2062 
2063  m_gridHelper.SetSnap( !( m_modifiers & MD_SHIFT ) );
2064  auto via = static_cast<VIA*>( aItem );
2065  wxPoint position = via->GetPosition();
2066  TRACK* track = findTrack( via );
2067 
2068  if( track )
2069  {
2070  SEG trackSeg( track->GetStart(), track->GetEnd() );
2071  VECTOR2I snap = m_gridHelper.AlignToSegment( position, trackSeg );
2072 
2073  aItem->SetPosition( (wxPoint) snap );
2074  }
2075  }
2076 
2077  bool PlaceItem( BOARD_ITEM* aItem, BOARD_COMMIT& aCommit ) override
2078  {
2079  VIA* via = static_cast<VIA*>( aItem );
2080  wxPoint viaPos = via->GetPosition();
2081  int newNet;
2082  TRACK* track = findTrack( via );
2083 
2084  if( hasDRCViolation( via ) )
2085  return false;
2086 
2087  if( track )
2088  {
2089  if( viaPos != track->GetStart() && viaPos != track->GetEnd() )
2090  {
2091  aCommit.Modify( track );
2092 
2093  TRACK* newTrack = dynamic_cast<TRACK*>( track->Clone() );
2094  const_cast<KIID&>( newTrack->m_Uuid ) = KIID();
2095 
2096  track->SetEnd( viaPos );
2097  newTrack->SetStart( viaPos );
2098  aCommit.Add( newTrack );
2099  }
2100 
2101  newNet = track->GetNetCode();
2102  }
2103  else
2104  newNet = findStitchedZoneNet( via );
2105 
2106  if( newNet > 0 )
2107  via->SetNetCode( newNet );
2108 
2109  aCommit.Add( aItem );
2110  return true;
2111  }
2112 
2113  std::unique_ptr<BOARD_ITEM> CreateItem() override
2114  {
2115  auto& ds = m_board->GetDesignSettings();
2116  VIA* via = new VIA( m_board );
2117 
2118  via->SetNetCode( 0 );
2119  via->SetViaType( ds.m_CurrentViaType );
2120 
2121  // for microvias, the size and hole will be changed later.
2122  via->SetWidth( ds.GetCurrentViaSize() );
2123  via->SetDrill( ds.GetCurrentViaDrill() );
2124 
2125  // Usual via is from copper to component.
2126  // layer pair is B_Cu and F_Cu.
2127  via->SetLayerPair( B_Cu, F_Cu );
2128 
2129  PCB_LAYER_ID first_layer = m_frame->GetActiveLayer();
2130  PCB_LAYER_ID last_layer;
2131 
2132  // prepare switch to new active layer:
2133  if( first_layer != m_frame->GetScreen()->m_Route_Layer_TOP )
2134  last_layer = m_frame->GetScreen()->m_Route_Layer_TOP;
2135  else
2136  last_layer = m_frame->GetScreen()->m_Route_Layer_BOTTOM;
2137 
2138  // Adjust the actual via layer pair
2139  switch( via->GetViaType() )
2140  {
2141  case VIATYPE::BLIND_BURIED:
2142  via->SetLayerPair( first_layer, last_layer );
2143  break;
2144 
2145  case VIATYPE::MICROVIA: // from external to the near neighbor inner layer
2146  {
2147  PCB_LAYER_ID last_inner_layer =
2148  ToLAYER_ID( ( m_board->GetCopperLayerCount() - 2 ) );
2149 
2150  if( first_layer == B_Cu )
2151  last_layer = last_inner_layer;
2152  else if( first_layer == F_Cu )
2153  last_layer = In1_Cu;
2154  else if( first_layer == last_inner_layer )
2155  last_layer = B_Cu;
2156  else if( first_layer == In1_Cu )
2157  last_layer = F_Cu;
2158 
2159  // else error: will be removed later
2160  via->SetLayerPair( first_layer, last_layer );
2161 
2162  // Update diameter and hole size, which where set previously
2163  // for normal vias
2164  NETINFO_ITEM* net = via->GetNet();
2165 
2166  if( net )
2167  {
2168  via->SetWidth( net->GetMicroViaSize() );
2169  via->SetDrill( net->GetMicroViaDrillSize() );
2170  }
2171  }
2172  break;
2173 
2174  default:
2175  break;
2176  }
2177 
2178  return std::unique_ptr<BOARD_ITEM>( via );
2179  }
2180  };
2181 
2182  VIA_PLACER placer( frame() );
2183 
2184  SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::VIA );
2185 
2186  doInteractiveItemPlacement( aEvent.GetCommandStr().get(), &placer, _( "Place via" ),
2188 
2189  return 0;
2190 }
2191 
2192 
2194 {
2195  assert( m_board );
2196  return m_board->GetDesignSettings().GetLineThickness( aLayer );
2197 }
2198 
2199 
2200 const unsigned int DRAWING_TOOL::WIDTH_STEP = Millimeter2iu( 0.1 );
2201 
2202 
2204 {
2222 }
void SetMirrored(bool isMirrored)
Definition: eda_text.h:188
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:133
OPT_TOOL_EVENT eventHandler(const wxMenuEvent &aEvent) override
Event handler stub.
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
virtual void ShowCursor(bool aEnabled)
Function ShowCursor() Enables or disables display of cursor.
EDA_UNITS
Definition: common.h:198
static TOOL_ACTION drawLine
Definition: pcb_actions.h:139
static TOOL_ACTION drawCenterDimension
Definition: pcb_actions.h:146
Struct VIA_DIMENSION is a small helper container to handle a stock of specific vias each with unique ...
bool AddItem(BOARD_ITEM *aItem)
Adds item to group.
ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:61
COMMIT & Modify(EDA_ITEM *aItem)
Modifies a given item in the model.
Definition: commit.h:103
int DrawCircle(const TOOL_EVENT &aEvent)
Function DrawCircle() Starts interactively drawing a circle.
VECTOR2< T > GetVectorSnapped45(const VECTOR2< T > &aVec, bool only45=false)
Snap a vector onto the nearest 0, 45 or 90 degree line.
void SetKeepUpright(bool aKeepUpright)
TOOL_MENU m_menu
functions below are not yet implemented - their interface may change
static TOOL_ACTION placeImportedGraphics
Definition: pcb_actions.h:156
class ALIGNED_DIMENSION, a linear dimension (graphic item)
Definition: typeinfo.h:101
void SetShape(STROKE_T aShape)
virtual void Clear() override
Function Clear() Removes all the stored items from the group.
Definition: selection.h:95
int GetNetCode() const
Function GetNetCode.
virtual BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Returns the BOARD_DESIGN_SETTINGS for the open project Overloaded in FOOTPRINT_EDIT_FRAME.
class LEADER, a leader dimension (graphic item)
Definition: typeinfo.h:102
VECTOR2I GetEndRadiusEnd() const
Get the coordinates of the arc end point
double GetLineLength(const wxPoint &aPointA, const wxPoint &aPointB)
Return the length of a line segment defined by aPointA and aPointB.
Definition: trigo.h:211
TEXTE_PCB class definition.
Add a new zone with the same settings as an existing one.
int DrawVia(const TOOL_EVENT &aEvent)
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.
virtual LSET GetLayerSet() const override
Function GetLayerSet returns a std::bitset of all layers on which the item physically resides.
BOARD * board() const
int DrawZone(const TOOL_EVENT &aEvent)
Function DrawZone() Starts interactively drawing a zone.
void AddChildrenToCommit(BOARD_COMMIT &aCommit)
Add all the immediate children of this group to the board commit.
BOARD * m_board
Definition: drawing_tool.h:229
static TOOL_ACTION incWidth
Increase width of currently drawn line.
Definition: pcb_actions.h:162
void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction)
Invokes a function on all members of the group.
void SetArcStart(const wxPoint &aArcStartPoint)
Initialize the start arc point.
static TOOL_ACTION drawSimilarZone
Definition: pcb_actions.h:153
virtual void SetLayer(PCB_LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
Defines the structure of a menu based on ACTIONs.
Definition: action_menu.h:43
This file is part of the common library.
virtual void SetPosition(const wxPoint &aPos)
Definition: base_struct.h:338
BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
void SetEnd(const wxPoint &aEnd)
Definition: class_track.h:112
static TOOL_ACTION drawArc
Definition: pcb_actions.h:143
class PCB_GROUP, a set of BOARD_ITEMs
Definition: typeinfo.h:109
int DrawLine(const TOOL_EVENT &aEvent)
Function DrawLine() Starts interactively drawing a line.
COMMIT & Add(EDA_ITEM *aItem)
Adds a new item to the model
Definition: commit.h:78
void SetCurrentCursor(wxStockCursor aStockCursorID)
Function SetCurrentCursor Set the current cursor shape for this panel.
NETINFO_ITEM * GetNet() const
Function GetNet Returns NET_INFO object for a given item.
const wxPoint & GetStart() const
Definition: class_track.h:116
VIEW_CONTROLS class definition.
PCB_GROUP is a set of BOARD_ITEMs (i.e., without duplicates)
void RunMainStack(std::function< void()> aFunc)
Function RunMainStack()
bool IsBackLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a back layer.
SELECTION_TOOL.
class CENTER_DIMENSION, a center point marking (graphic item)
Definition: typeinfo.h:103
std::list< std::unique_ptr< EDA_ITEM > > & GetImportedItems()
int DrawRectangle(const TOOL_EVENT &aEvent)
Function DrawRectangle() Starts interactively drawing a rectangle.
STATUS_TEXT_POPUP.
Definition: status_popup.h:79
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
Class that computes missing connections on a PCB.
CONDITIONAL_MENU & GetMenu()
Function GetMenu.
Definition: tool_menu.cpp:46
static const unsigned int WIDTH_STEP
Definition: drawing_tool.h:234
void SetItalic(bool isItalic)
Definition: eda_text.h:179
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.
static TOOL_ACTION drawAlignedDimension
Definition: pcb_actions.h:145
static TOOL_ACTION cancelInteractive
Definition: actions.h:65
virtual void PushTool(const std::string &actionName)
NB: the definition of "tool" is different at the user level.
virtual void Remove(VIEW_ITEM *aItem)
Function Remove() Removes a VIEW_ITEM from the view.
Definition: view.cpp:375
void SetTextPos(const wxPoint &aPoint)
Definition: eda_text.h:247
virtual PCB_LAYER_ID GetLayer() const override
Function GetLayer returns the primary layer this item is on.
Definition: class_zone.cpp:214
static TOOL_ACTION properties
Activation of the edit tool.
Definition: pcb_actions.h:114
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes.
VECTOR2I AlignToSegment(const VECTOR2I &aPoint, const SEG &aSeg)
static TOOL_ACTION drawOrthogonalDimension
Definition: pcb_actions.h:147
virtual EDA_ITEM * Clone() const override
Function Clone creates a duplicate of this item with linked list members set to NULL.
Definition: class_track.cpp:50
class TEXTE_PCB, text on a layer
Definition: typeinfo.h:92
bool SetNetCode(int aNetCode, bool aNoAssert)
Sets net using a net code.
PCB_LAYER_ID m_layer
Layer to begin drawing
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 drawPolygon
Definition: pcb_actions.h:140
double RAD2DECIDEG(double rad)
Definition: trigo.h:224
VECTOR2I GetStartRadiusEnd() const
Get the coordinates of the arc start
void PrimeTool(const VECTOR2D &aPosition)
Function PrimeTool() "Primes" a tool by sending a cursor left-click event with the mouse position set...
static TOOL_ACTION trackViaSizeChanged
Definition: pcb_actions.h:287
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:537
usual segment : line with rounded ends
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition: macros.h:88
static void updateArcFromConstructionMgr(const KIGFX::PREVIEW::ARC_GEOM_MANAGER &aMgr, DRAWSEGMENT &aArc)
Update an arc DRAWSEGMENT from the current state of an Arc Geometry Manager.
virtual const wxPoint & GetEnd() const
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:238
virtual MAGNETIC_SETTINGS * GetMagneticItemsSettings()
virtual wxPoint GetPosition() const
Definition: base_struct.h:337
Parameters used to fully describe a zone creation process.
bool NewPointClosesOutline(const VECTOR2I &aPt) const
int GetTextThickness(PCB_LAYER_ID aLayer) const
Function GetTextThickness Returns the default text thickness from the layer class for the given layer...
void InstallTextOptionsFrame(BOARD_ITEM *aText)
Routine for main window class to launch text properties dialog.
VECTOR2< int > VECTOR2I
Definition: vector2d.h:594
void SetLeaderMode(LEADER_MODE aMode)
Set the leader mode to use when calculating the leader/returner lines.
bool getSourceZoneForAction(ZONE_MODE aMode, ZONE_CONTAINER **aZone)
Draws a polygon, that is added as a zone or a keepout area.
void MoveAnchorPosition(const wxPoint &aMoveVector)
Function MoveAnchorPosition Move the reference point of the footprint It looks like a move footprint:...
void SetCenter(const wxPoint &aCenterPoint)
For arcs and circles:
LEADER_MODE GetLeaderMode() const
static TOOL_ACTION setAnchor
Definition: pcb_actions.h:157
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 TOOL_ACTION placeText
Definition: pcb_actions.h:144
double GetSubtended() const
Get the angle of the vector leading to the end point (valid if step >= SET_ANGLE)
static TOOL_ACTION decWidth
Decrease width of currently drawn line.
Definition: pcb_actions.h:165
virtual void Add(EDA_ITEM *aItem)
Definition: selection.h:76
void SetWidth(int aWidth)
Definition: class_track.h:109
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
double GetAngle() const
Function GetAngle Returns angle of the crossbar.
KIGFX::VIEW * m_view
Definition: drawing_tool.h:227
PCBNEW_SELECTION & GetSelection()
Function GetSelection()
void constrainDimension(DIMENSION *aDim)
Function constrainDimension() Forces the dimension lime to be drawn on multiple of 45 degrees.
bool TestSegmentHit(const wxPoint &aRefPoint, wxPoint aStart, wxPoint aEnd, int aDist)
Test if aRefPoint is with aDistance on the line defined by aStart and aEnd.
Definition: trigo.cpp:129
bool GetTextUpright(PCB_LAYER_ID aLayer) const
#define IS_NEW
New item, just created.
Definition: base_struct.h:117
PCB_BASE_EDIT_FRAME * frame() const
bool GetTextItalic(PCB_LAYER_ID aLayer) const
virtual PCB_LAYER_ID GetActiveLayer() const
int GetLineThickness(PCB_LAYER_ID aLayer) const
Function GetLineThickness Returns the default graphic segment thickness from the layer class for the ...
void SetViaSizeIndex(unsigned aIndex)
Function SetViaSizeIndex sets the current via size list index to aIndex.
DIMENSION class definition.
bool m_Use45DegreeGraphicSegments
Definition: common.h:68
segment with non rounded ends
void SetReferencePoint(const VECTOR2I &aP)
Definition: selection.h:245
virtual void WarpCursor(const VECTOR2D &aPosition, bool aWorldCoordinates=false, bool aWarpView=false)=0
Function WarpCursor() If enabled (.
int PlaceImportedGraphics(const TOOL_EVENT &aEvent)
Function PlaceImportedGraphics() Places a drawing imported from a DXF or SVG file in module editor.
void SetArcEnd(const wxPoint &aArcEndPoint)
Initialize the end arc point.
PCB_LAYER_ID
A quick note on layer IDs:
int PlaceText(const TOOL_EVENT &aEvent)
Function PlaceText() Displays a dialog that allows one to input text and its settings and then lets t...
Unconstrained point-to-point
void SetHeight(int aHeight)
Sets the distance from the feature points to the crossbar line.
LSET is a set of PCB_LAYER_IDs.
RAII class that sets an value at construction and resets it to the original value at destruction.
const PCBNEW_SELECTION & selection() const
void SetFlags(STATUS_FLAGS aMask)
Definition: base_struct.h:232
const auto NULLOPT
Definition: optional.h:9
void update() override
Update menu state stub.
#define NULL
VECTOR2< double > VECTOR2D
Definition: vector2d.h:593
int GetDrillValue() const
Function GetDrillValue "calculates" the drill value for vias (m-Drill if > 0, or default drill value ...
MODULES & Modules()
Definition: class_board.h:249
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
bool IsGridVisible() const
Allow repeat placement of the item.
unsigned GetViaSizeIndex() const
Function GetViaSizeIndex.
virtual void PopTool(const std::string &actionName)
virtual void CaptureCursor(bool aEnabled)
Function CaptureCursor() Forces the cursor to stay within the drawing panel area.
T Parameter() const
Function Parameter() Returns a non-standard parameter assigned to the event.
Definition: tool_event.h:435
void Reset(RESET_REASON aReason) override
Function Reset() Brings the tool to a known, initial state.
VECTOR2I GetOrigin() const
Get the centre point of the arc (valid when state > SET_ORIGIN)
Arcs (with rounded ends)
bool Init() override
Function Init() Init() is called once upon a registration of the tool.
ZONE_CONTAINER * m_sourceZone
Zone settings source (for similar and cutout zones)
void SetIcon(const BITMAP_OPAQUE *aIcon)
Assigns an icon for the entry.
Definition: action_menu.cpp:71
TOOL_EVENT.
Definition: tool_event.h:171
static void updateSegmentFromConstructionMgr(const KIGFX::PREVIEW::TWO_POINT_GEOMETRY_MANAGER &aMgr, DRAWSEGMENT *aGraphic)
Update an DRAWSEGMENT from the current state of an Two POINT Geometry Manager.
DIR GetOrientation() const
unsigned int m_lineWidth
Definition: drawing_tool.h:233
An orthogonal dimension is like an aligned dimension, but the extension lines are locked to the X or ...
KIGFX::PCB_VIEW * view() const
static TOOL_ACTION drawRectangle
Definition: pcb_actions.h:141
PCB_LAYER_ID m_Route_Layer_BOTTOM
Definition: pcb_screen.h:39
STROKE_T
Enum STROKE_T is the set of shapes for segments (graphic segments and tracks) which are often in the ...
Add a new zone/keepout with fresh settings.
bool IsSelfIntersecting(bool aIncludeLeaderPts) const
Checks whether the locked points constitute a self-intersecting outline.
virtual void ForceCursorPosition(bool aEnabled, const VECTOR2D &aPosition=VECTOR2D(0, 0))
Function ForceCursorPosition() Places the cursor immediately at a given point.
a few functions useful in geometry calculations.
static LSET AllLayersMask()
Definition: lset.cpp:756
static TOOL_ACTION drawVia
Definition: pcb_actions.h:150
void SetLayerPair(PCB_LAYER_ID aTopLayer, PCB_LAYER_ID aBottomLayer)
Function SetLayerPair For a via m_Layer contains the top layer, the other layer is in m_BottomLayer.
KIGFX::VIEW_CONTROLS * m_controls
Definition: drawing_tool.h:228
Create an item immediately on placement starting, otherwise show the pencil cursor until the item is ...
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
static TOOL_ACTION drawZoneCutout
Definition: pcb_actions.h:152
const BITMAP_OPAQUE width_track_via_xpm[1]
virtual KIGFX::PCB_VIEW * GetView() const override
Function GetView() Returns a pointer to the VIEW instance used in the panel.
int getSegmentWidth(PCB_LAYER_ID aLayer) const
Returns the appropriate width for a segment depending on the settings.
void SetOrientation(DIR aOrientation)
Sets the orientation of the dimension line (so, perpendicular to the feature lines)
ZONE_MODE
Definition: pcb_actions.h:36
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.
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:121
bool GetHV45() const
Definition: class_zone.h:794
void SetStart(const wxPoint &aStart)
void setTransitions() override
Sets up handlers for various events.
PCB_BASE_EDIT_FRAME * m_frame
Definition: drawing_tool.h:230
void SetSnap(bool aSnap)
Definition: grid_helper.h:82
void DeleteLastCorner()
Remove the last-added point from the polygon.
const KIID m_Uuid
Definition: base_struct.h:162
virtual BOARD_ITEM_CONTAINER * GetModel() const =0
Function GetModel()
class TEXTE_MODULE, text in a footprint
Definition: typeinfo.h:93
int Modifier(int aMask=MD_MODIFIER_MASK) const
Returns information about key modifiers state (Ctrl, Alt, etc.)
Definition: tool_event.h:342
static TOOL_ACTION drawCircle
Definition: pcb_actions.h:142
Definition: seg.h:39
wxString MessageTextFromValue(EDA_UNITS aUnits, int aValue, bool aUseMils, EDA_DATA_TYPE aType)
Definition: base_units.cpp:124
OPT< std::string > GetCommandStr() const
Definition: tool_event.h:463
TOOLS_HOLDER * GetToolHolder() const
Definition: tool_manager.h:300
MODE
The possible drawing modes of DRAWING_TOOL
Definition: drawing_tool.h:63
void OnGeometryChange(const POLYGON_GEOM_MANAGER &aMgr) override
Sent when the polygon geometry changes
NETINFO_ITEM handles the data for a net.
Definition: netinfo.h:65
static TOOL_ACTION arcPosture
Switch posture when drawing arc.
Definition: pcb_actions.h:168
bool IsLayerVisible(PCB_LAYER_ID aLayer) const
Function IsLayerVisible is a proxy function that calls the correspondent function in m_BoardSettings ...
static TOOL_ACTION layerChanged
Definition: pcb_actions.h:277
virtual const wxPoint & GetStart() const
The dimension's origin is the first feature point for the dimension.
bool drawArc(const std::string &aTool, DRAWSEGMENT **aGraphic, bool aImmediateMode)
Starts drawing an arc.
ACTION_MENU * create() const override
Returns an instance of this class. It has to be overridden in inheriting classes.
static TOOL_ACTION drawLeader
Definition: pcb_actions.h:148
int SetAnchor(const TOOL_EVENT &aEvent)
Function SetAnchor() Places the footprint anchor (only in module editor).
ZONE_CONTAINERS & Zones()
Definition: class_board.h:254
static TOOL_ACTION drawRuleArea
Definition: pcb_actions.h:151
void SetTitle(const wxString &aTitle) override
Sets title for the menu.
Definition: action_menu.cpp:89
int GetWidth() const
Definition: class_track.h:110
Common, abstract interface for edit frames.
MODULE * module() const
#define _(s)
Definition: 3d_actions.cpp:33
TOOL_MANAGER * getToolManager() const
Returns an instance of TOOL_MANAGER class.
void AddSubMenu(std::shared_ptr< ACTION_MENU > aSubMenu)
Function CreateSubMenu.
Definition: tool_menu.cpp:52
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
int GetCopperLayerCount() const
Function GetCopperLayerCount.
static TOOL_ACTION selectItem
Selects an item (specified as the event parameter).
Definition: pcb_actions.h:65
void SetDrill(int aDrill)
Function SetDrill sets the drill value for vias.
Definition: class_track.h:483
This class is an adjuct helper to the DRAWING_TOOL interactive tool, which handles incoming geometry ...
PCB_EDIT_FRAME is the main frame for Pcbnew.
void Clear()
Removes all the entries from the menu (as well as its title).
PCBNEW_SETTINGS & Settings()
bool HasPoint()
Indicates the cursor is over an edit point.
Definition: point_editor.h:65
int Size() const
Returns the number of selected parts.
Definition: selection.h:127
VIATYPE GetViaType() const
Definition: class_track.h:381
POINT_EDITOR.
Definition: point_editor.h:43
static TOOL_ACTION resetLocalCoords
Definition: actions.h:146
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:68
EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boards.
Definition: base_struct.h:159
void Reset()
Clear the manager state and start again.
virtual void Push(const wxString &aMessage=wxT("A commit"), bool aCreateUndoEntry=true, bool aSetDirtyBit=true) override
Executes the changes.
PCB_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
RESET_REASON
Determines the reason of reset for a tool
Definition: tool_base.h:79
const wxPoint & GetEnd() const
Definition: class_track.h:113
std::vector< VIA_DIMENSION > m_ViasDimensionsList
static TOOL_ACTION deleteLastPoint
Definition: pcb_actions.h:158
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 SetEnd(const wxPoint &aEnd)
virtual void SetAngle(double aAngle)
Function SetAngle sets the angle for arcs, and normalizes it within the range 0 - 360 degrees.
void ClearFlags(STATUS_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: base_struct.h:233
void Activate()
Function Activate() Runs the tool.
ZONE_CONTAINER * GetZone() const
const wxPoint & GetTextPos() const
Definition: eda_text.h:248
bool drawSegment(const std::string &aTool, int aShape, DRAWSEGMENT **aGraphic, OPT< VECTOR2D > aStartingPoint)
Starts drawing a selected shape (i.e.
void SetStart(const wxPoint &aStart)
Definition: class_track.h:115
Implementing DIALOG_TRACK_VIA_SIZE_BASE.
class ORTHOGONAL_DIMENSION, a linear dimension constrained to x/y
Definition: typeinfo.h:104
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.h:158
bool HasPosition() const
Returns if it this event has a valid position (true for mouse events and context-menu or hotkey-based...
Definition: tool_event.h:260
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Function Add() Adds a VIEW_ITEM to the view.
Definition: view.cpp:345
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:78
wxPoint GetPosition() const override
Definition: class_module.h:219
virtual int Query(const BOX2I &aRect, std::vector< LAYER_ITEM_PAIR > &aResult) const
Function Query() Finds all visible items that touch or are within the rectangle aRect.
Definition: view.cpp:451
void doInteractiveItemPlacement(const std::string &aTool, INTERACTIVE_PLACER_BASE *aPlacer, const wxString &aCommitMessage, int aOptions=IPO_ROTATE|IPO_FLIP|IPO_REPEAT)
Helper function for performing a common interactive idiom: wait for a left click, place an item there...
BOARD * GetBoard() const
KIGFX::VIEW_CONTROLS * getViewControls() const
Function getViewControls()
Definition: tool_base.cpp:42
bool m_keepout
Should create a keepout zone?
MODE GetDrawingMode() const
Function GetDrawingMode.
wxPoint GetPosition() const override
Definition: class_track.h:420
EDGE_MODULE class definition.
For better understanding of the points that make a dimension:
class DRAWSEGMENT, a segment not on copper layers
Definition: typeinfo.h:91
int GetMicroViaSize()
Function GetMicroViaSize returns the size of vias used to route this net.
Definition: netinfo.h:168
bool AddPoint(const VECTOR2I &aPt)
Lock in a polygon point.
void SetCursorPosition(const VECTOR2I &aPos)
Set the current cursor position.
void SetViaType(VIATYPE aViaType)
Definition: class_track.h:382
static constexpr int Millimeter2iu(double mm)
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.
void SetFinished()
Mark the polygon finished and update the client.
int DrawArc(const TOOL_EVENT &aEvent)
Function DrawArc() Starts interactively drawing an arc.
void ShowContextMenu(SELECTION &aSelection)
Function ShowContextMenu.
Definition: tool_menu.cpp:59
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:127
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:856
wxSize GetTextSize(PCB_LAYER_ID aLayer) const
Function GetTextSize Returns the default text size from the layer class for the given layer.
static TOOL_ACTION drawZone
Definition: pcb_actions.h:149
Abstract dimension API.
Class that handles the drawing of a polygon, including management of last corner deletion and drawing...
const VECTOR2D Position() const
Returns mouse cursor position in world coordinates.
Definition: tool_event.h:274
static TOOL_ACTION selectionCursor
Select a single item under the cursor position.
Definition: pcb_actions.h:59
EDA_UNITS GetUserUnits() const
Return the user units currently in use.
virtual void SetEnd(const wxPoint &aPoint)
ZONE_MODE m_mode
The zone mode to operate in
PCB_LAYER_ID m_Route_Layer_TOP
Definition: pcb_screen.h:38
static TOOL_ACTION refreshPreview
Definition: actions.h:104
void UseCustomTrackViaSize(bool aEnabled)
Function UseCustomTrackViaSize Enables/disables custom track/via size settings.
virtual LSET GetLayerSet() const
Function GetLayerSet returns a std::bitset of all layers on which the item physically resides.
VECTOR2D GetCursorPosition() const
Returns the current cursor position in world coordinates.
static TOOL_ACTION cursorClick
Definition: actions.h:121
VECTOR2D m_LocalOrigin
Relative Screen cursor coordinate (on grid) in user units.
Definition: base_screen.h:62
OPT< TOOL_EVENT > OPT_TOOL_EVENT
Definition: tool_event.h:556
KICAD_T Type() const
Function Type()
Definition: base_struct.h:193
int DrawDimension(const TOOL_EVENT &aEvent)
Function DrawDimension() Starts interactively drawing a dimension.
BOARD_DESIGN_SETTINGS contains design settings for a BOARD object.
static TOOL_ACTION closeOutline
Definition: pcb_actions.h:159
void SetWidth(int aWidth)
virtual void Remove(EDA_ITEM *aItem)
Definition: selection.h:87
Marks the center of a circle or arc with a cross shape The size and orientation of the cross is adjus...