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) 2016 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 
29 #include <wxPcbStruct.h>
30 #include <class_draw_panel_gal.h>
31 #include <project.h>
32 #include <id.h>
33 #include <pcbnew_id.h>
34 #include <confirm.h>
37 
38 #include <view/view_group.h>
39 #include <view/view_controls.h>
40 #include <view/view.h>
42 #include <tool/tool_manager.h>
43 #include <geometry/direction45.h>
44 #include <ratsnest_data.h>
45 #include <board_commit.h>
46 #include <scoped_set_reset.h>
47 #include <bitmaps.h>
48 #include <hotkeys.h>
49 #include <painter.h>
50 
52 
53 #include <class_board.h>
54 #include <class_edge_mod.h>
55 #include <class_pcb_text.h>
56 #include <class_dimension.h>
57 #include <class_zone.h>
58 #include <class_module.h>
59 
60 #include <tools/selection_tool.h>
61 #include <tools/tool_event_utils.h>
63 
65 
66 // Drawing tool actions
67 TOOL_ACTION PCB_ACTIONS::drawLine( "pcbnew.InteractiveDrawing.line",
68  AS_GLOBAL, 0,
69  _( "Draw Line" ), _( "Draw a line" ), NULL, AF_ACTIVATE );
70 
71 TOOL_ACTION PCB_ACTIONS::drawCircle( "pcbnew.InteractiveDrawing.circle",
72  AS_GLOBAL, 0,
73  _( "Draw Circle" ), _( "Draw a circle" ), NULL, AF_ACTIVATE );
74 
75 TOOL_ACTION PCB_ACTIONS::drawArc( "pcbnew.InteractiveDrawing.arc",
76  AS_GLOBAL, 0,
77  _( "Draw Arc" ), _( "Draw an arc" ), NULL, AF_ACTIVATE );
78 
79 TOOL_ACTION PCB_ACTIONS::placeText( "pcbnew.InteractiveDrawing.text",
80  AS_GLOBAL, 0,
81  _( "Add Text" ), _( "Add a text" ), NULL, AF_ACTIVATE );
82 
83 TOOL_ACTION PCB_ACTIONS::drawDimension( "pcbnew.InteractiveDrawing.dimension",
84  AS_GLOBAL, 0,
85  _( "Add Dimension" ), _( "Add a dimension" ), NULL, AF_ACTIVATE );
86 
87 TOOL_ACTION PCB_ACTIONS::drawZone( "pcbnew.InteractiveDrawing.zone",
88  AS_GLOBAL, 0,
89  _( "Add Filled Zone" ), _( "Add a filled zone" ), NULL, AF_ACTIVATE );
90 
91 TOOL_ACTION PCB_ACTIONS::drawKeepout( "pcbnew.InteractiveDrawing.keepout",
92  AS_GLOBAL, 0,
93  _( "Add Keepout Area" ), _( "Add a keepout area" ), NULL, AF_ACTIVATE );
94 
95 TOOL_ACTION PCB_ACTIONS::drawZoneCutout( "pcbnew.InteractiveDrawing.zoneCutout",
96  AS_GLOBAL, 0,
97  _( "Add a Zone Cutout" ), _( "Add a cutout area of an existing zone" ),
98  add_zone_cutout_xpm, AF_ACTIVATE );
99 
100 TOOL_ACTION PCB_ACTIONS::drawSimilarZone( "pcbnew.InteractiveDrawing.similarZone",
101  AS_GLOBAL, 0,
102  _( "Add a Similar Zone" ), _( "Add a zone with the same settings as an existing zone" ),
103  add_zone_xpm, AF_ACTIVATE );
104 
105 TOOL_ACTION PCB_ACTIONS::placeDXF( "pcbnew.InteractiveDrawing.placeDXF",
106  AS_GLOBAL, 0,
107  "Place DXF", "", NULL, AF_ACTIVATE );
108 
109 TOOL_ACTION PCB_ACTIONS::setAnchor( "pcbnew.InteractiveDrawing.setAnchor",
110  AS_GLOBAL, 0,
111  _( "Place the Footprint Anchor" ), _( "Place the footprint anchor" ),
112  NULL, AF_ACTIVATE );
113 
114 TOOL_ACTION PCB_ACTIONS::incWidth( "pcbnew.InteractiveDrawing.incWidth",
115  AS_CONTEXT, '+',
116  _( "Increase Line Width" ), _( "Increase the line width" ) );
117 
118 TOOL_ACTION PCB_ACTIONS::decWidth( "pcbnew.InteractiveDrawing.decWidth",
119  AS_CONTEXT, '-',
120  _( "Decrease Line Width" ), _( "Decrease the line width" ) );
121 
122 TOOL_ACTION PCB_ACTIONS::arcPosture( "pcbnew.InteractiveDrawing.arcPosture",
124  _( "Switch Arc Posture" ), _( "Switch the arc posture" ) );
125 
126 /*
127  * Contextual actions
128  */
129 
130 static TOOL_ACTION deleteLastPoint( "pcbnew.InteractiveDrawing.deleteLastPoint",
131  AS_CONTEXT, WXK_BACK,
132  _( "Delete Last Point" ), _( "Delete the last point added to the current item" ),
133  undo_xpm );
134 
135 static TOOL_ACTION closeZoneOutline( "pcbnew.InteractiveDrawing.closeZoneOutline",
136  AS_CONTEXT, 0,
137  _( "Close Zone Outline" ), _( "Close the outline of a zone in progress" ),
138  checked_ok_xpm );
139 
140 
142  PCB_TOOL( "pcbnew.InteractiveDrawing" ),
143  m_view( nullptr ), m_controls( nullptr ),
144  m_board( nullptr ), m_frame( nullptr ), m_mode( MODE::NONE ),
145  m_lineWidth( 1 ),
146  m_menu( *this )
147 {
148 }
149 
150 
152 {
153 }
154 
155 
157 {
158  auto activeToolFunctor = [ this ] ( const SELECTION& aSel ) {
159  return m_mode != MODE::NONE;
160  };
161 
162  // some interactive drawing tools can undo the last point
163  auto canUndoPoint = [ this ] ( const SELECTION& aSel ) {
164  return m_mode == MODE::ARC || m_mode == MODE::ZONE;
165  };
166 
167  // functor for zone-only actions
168  auto zoneActiveFunctor = [this ] ( const SELECTION& aSel ) {
169  return m_mode == MODE::ZONE;
170  };
171 
172  auto& ctxMenu = m_menu.GetMenu();
173 
174  // cancel current toool goes in main context menu at the top if present
175  ctxMenu.AddItem( ACTIONS::cancelInteractive, activeToolFunctor, 1000 );
176 
177  // tool-specific actions
178  ctxMenu.AddItem( closeZoneOutline, zoneActiveFunctor, 1000 );
179  ctxMenu.AddItem( deleteLastPoint, canUndoPoint, 1000 );
180 
181  ctxMenu.AddSeparator( activeToolFunctor, 1000 );
182 
183  // Type-specific sub-menus will be added for us by other tools
184  // For example, zone fill/unfill is provided by the PCB control tool
185 
186  // Finally, add the standard zoom/grid items
187  m_menu.AddStandardSubMenus( *getEditFrame<PCB_BASE_FRAME>() );
188 
189  return true;
190 }
191 
192 
194 {
195  // Init variables used by every drawing tool
196  m_view = getView();
198  m_board = getModel<BOARD>();
199  m_frame = getEditFrame<PCB_BASE_EDIT_FRAME>();
200 }
201 
202 
204 {
205  return m_mode;
206 }
207 
208 
209 int DRAWING_TOOL::DrawLine( const TOOL_EVENT& aEvent )
210 {
212  DRAWSEGMENT* line = m_editModules ? new EDGE_MODULE( (MODULE*) parent ) : new DRAWSEGMENT;
213  boost::optional<VECTOR2D> startingPoint;
214  BOARD_COMMIT commit( m_frame );
215 
216  SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::LINE );
217 
219  wxCURSOR_PENCIL, _( "Add graphic line" ) );
221 
222  while( drawSegment( S_SEGMENT, line, startingPoint ) )
223  {
224  if( line )
225  {
226  commit.Add( line );
227  commit.Push( _( "Draw a line segment" ) );
228  startingPoint = line->GetEnd();
229  }
230  else
231  {
232  startingPoint = boost::none;
233  }
234 
235  line = m_editModules ? new EDGE_MODULE( (MODULE*) parent ) : new DRAWSEGMENT;
236  }
237 
238  m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString );
239 
240  return 0;
241 }
242 
243 
245 {
247  DRAWSEGMENT* circle = m_editModules ? new EDGE_MODULE( (MODULE*) parent ) : new DRAWSEGMENT;
248  BOARD_COMMIT commit( m_frame );
249 
250  SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::CIRCLE );
251 
253  wxCURSOR_PENCIL, _( "Add graphic circle" ) );
255 
256  while( drawSegment( S_CIRCLE, circle ) )
257  {
258  if( circle )
259  {
260  commit.Add( circle );
261  commit.Push( _( "Draw a circle" ) );
262  }
263 
264  circle = m_editModules ? new EDGE_MODULE( (MODULE*) parent ) : new DRAWSEGMENT;
265  }
266 
267  m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString );
268 
269  return 0;
270 }
271 
272 
273 int DRAWING_TOOL::DrawArc( const TOOL_EVENT& aEvent )
274 {
276  DRAWSEGMENT* arc = m_editModules ? new EDGE_MODULE( (MODULE*) parent ) : new DRAWSEGMENT;
277  BOARD_COMMIT commit( m_frame );
278 
279  SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::ARC );
280 
282  wxCURSOR_PENCIL, _( "Add graphic arc" ) );
284 
285  while( drawArc( arc ) )
286  {
287  if( arc )
288  {
289  commit.Add( arc );
290  commit.Push( _( "Draw an arc" ) );
291  }
292 
293  arc = m_editModules ? new EDGE_MODULE( (MODULE*) parent ) : new DRAWSEGMENT;
294  }
295 
296  m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString );
297 
298  return 0;
299 }
300 
301 
303 {
304  BOARD_ITEM* text = NULL;
305  const BOARD_DESIGN_SETTINGS& dsnSettings = m_frame->GetDesignSettings();
306  BOARD_COMMIT commit( m_frame );
307 
308  // Add a VIEW_GROUP that serves as a preview for the new item
309  SELECTION preview;
310  m_view->Add( &preview );
311 
313  m_controls->ShowCursor( true );
314  m_controls->SetSnapping( true );
315  // do not capture or auto-pan until we start placing some text
316 
317  SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::TEXT );
318 
319  Activate();
321  wxCURSOR_PENCIL, _( "Add text" ) );
322 
323  // Main loop: keep receiving events
324  while( OPT_TOOL_EVENT evt = Wait() )
325  {
326  VECTOR2I cursorPos = m_controls->GetCursorPosition();
327 
329  {
330  if( text )
331  {
332  // Delete the old text and have another try
333  delete text;
334  text = NULL;
335 
336  preview.Clear();
337 
338  m_controls->SetAutoPan( false );
339  m_controls->CaptureCursor( false );
340  m_controls->ShowCursor( true );
341  }
342  else
343  break;
344 
345  if( evt->IsActivate() ) // now finish unconditionally
346  break;
347  }
348 
349  else if( text && evt->Category() == TC_COMMAND )
350  {
351  if( TOOL_EVT_UTILS::IsRotateToolEvt( *evt ) )
352  {
353  const auto rotationAngle = TOOL_EVT_UTILS::GetEventRotationAngle(
354  *m_frame, *evt );
355 
356  text->Rotate( text->GetPosition(), rotationAngle );
357  m_view->Update( &preview );
358  }
359  else if( evt->IsAction( &PCB_ACTIONS::flip ) )
360  {
361  text->Flip( text->GetPosition() );
362  m_view->Update( &preview );
363  }
364  }
365 
366  else if( evt->IsClick( BUT_RIGHT ) )
367  {
369  }
370 
371  else if( evt->IsClick( BUT_LEFT ) )
372  {
373  if( !text )
374  {
375  // Init the new item attributes
376  if( m_editModules )
377  {
378  TEXTE_MODULE* textMod = new TEXTE_MODULE( (MODULE*) m_frame->GetModel() );
379 
380  textMod->SetLayer( m_frame->GetActiveLayer() );
381  textMod->SetTextSize( dsnSettings.m_ModuleTextSize );
382  textMod->SetThickness( dsnSettings.m_ModuleTextWidth );
383  textMod->SetTextPos( wxPoint( cursorPos.x, cursorPos.y ) );
384 
385  DialogEditModuleText textDialog( m_frame, textMod, NULL );
386  bool placing;
387 
388  RunMainStack( [&]() {
389  placing = textDialog.ShowModal() && ( textMod->GetText().Length() > 0 );
390  } );
391 
392  if( placing )
393  text = textMod;
394  else
395  delete textMod;
396  }
397  else
398  {
399  TEXTE_PCB* textPcb = new TEXTE_PCB( m_frame->GetModel() );
400  // TODO we have to set IS_NEW, otherwise InstallTextPCB.. creates an undo entry :| LEGACY_CLEANUP
401  textPcb->SetFlags( IS_NEW );
402 
403  LAYER_ID layer = m_frame->GetActiveLayer();
404  textPcb->SetLayer( layer );
405 
406  // Set the mirrored option for layers on the BACK side of the board
407  if( IsBackLayer( layer ) )
408  textPcb->SetMirrored( true );
409 
410  textPcb->SetTextSize( dsnSettings.m_PcbTextSize );
411  textPcb->SetThickness( dsnSettings.m_PcbTextWidth );
412  textPcb->SetTextPos( wxPoint( cursorPos.x, cursorPos.y ) );
413 
414  RunMainStack( [&]() {
415  getEditFrame<PCB_EDIT_FRAME>()->InstallTextPCBOptionsFrame( textPcb, NULL );
416  } );
417 
418  if( textPcb->GetText().IsEmpty() )
419  delete textPcb;
420  else
421  text = textPcb;
422  }
423 
424  if( text == NULL )
425  continue;
426 
427  m_controls->CaptureCursor( true );
428  m_controls->SetAutoPan( true );
429  //m_controls->ShowCursor( false );
430 
431  preview.Add( text );
432  }
433  else
434  {
435  //assert( text->GetText().Length() > 0 );
436  //assert( text->GetTextSize().x > 0 && text->GetTextSize().y > 0 );
437 
438  text->ClearFlags();
439  preview.Remove( text );
440 
441  commit.Add( text );
442  commit.Push( _( "Place a text" ) );
443 
444  m_controls->CaptureCursor( false );
445  m_controls->SetAutoPan( false );
446  m_controls->ShowCursor( true );
447 
448  text = NULL;
449  }
450  }
451  else if( text && evt->IsMotion() )
452  {
453  text->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) );
454 
455  // Show a preview of the item
456  m_view->Update( &preview );
457  }
458  }
459 
460  m_view->Remove( &preview );
461  m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString );
462 
463  return 0;
464 
465 }
466 
467 
469 {
470  DIMENSION* dimension = NULL;
471  BOARD_COMMIT commit( m_frame );
472  int maxThickness;
473 
474  // Add a VIEW_GROUP that serves as a preview for the new item
475  SELECTION preview;
476  m_view->Add( &preview );
477 
479  m_controls->ShowCursor( true );
480  m_controls->SetSnapping( true );
481 
482  SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::DIMENSION );
483 
484  Activate();
485  m_frame->SetToolID( ID_PCB_DIMENSION_BUTT, wxCURSOR_PENCIL, _( "Add dimension" ) );
487 
488  enum DIMENSION_STEPS
489  {
490  SET_ORIGIN = 0,
491  SET_END,
492  SET_HEIGHT,
493  FINISHED
494  };
495  int step = SET_ORIGIN;
496 
497  // Main loop: keep receiving events
498  while( OPT_TOOL_EVENT evt = Wait() )
499  {
500  VECTOR2I cursorPos = m_controls->GetCursorPosition();
501 
503  {
504  if( step != SET_ORIGIN ) // start from the beginning
505  {
506  preview.Clear();
507 
508  delete dimension;
509  step = SET_ORIGIN;
510  }
511  else
512  break;
513 
514  if( evt->IsActivate() ) // now finish unconditionally
515  break;
516  }
517 
518  else if( evt->IsAction( &PCB_ACTIONS::incWidth ) && step != SET_ORIGIN )
519  {
521  dimension->SetWidth( m_lineWidth );
522  m_view->Update( &preview );
523  }
524 
525  else if( evt->IsAction( &PCB_ACTIONS::decWidth ) && step != SET_ORIGIN )
526  {
527  if( m_lineWidth > WIDTH_STEP )
528  {
530  dimension->SetWidth( m_lineWidth );
531  m_view->Update( &preview );
532  }
533  }
534 
535  else if( evt->IsClick( BUT_RIGHT ) )
536  {
538  }
539 
540  else if( evt->IsClick( BUT_LEFT ) )
541  {
542  switch( step )
543  {
544  case SET_ORIGIN:
545  {
546  LAYER_ID layer = getDrawingLayer();
547 
548  if( layer == Edge_Cuts ) // dimensions are not allowed on EdgeCuts
549  layer = Dwgs_User;
550 
551  // Init the new item attributes
552  dimension = new DIMENSION( m_board );
553  dimension->SetLayer( layer );
554  dimension->SetOrigin( wxPoint( cursorPos.x, cursorPos.y ) );
555  dimension->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
557 
559  maxThickness = Clamp_Text_PenSize( width, dimension->Text().GetTextSize() );
560 
561  if( width > maxThickness )
562  width = maxThickness;
563 
564  dimension->Text().SetThickness( width );
565  dimension->SetWidth( width );
566  dimension->AdjustDimensionDetails();
567 
568  preview.Add( dimension );
569 
570  m_controls->SetAutoPan( true );
571  m_controls->CaptureCursor( true );
572  }
573  break;
574 
575  case SET_END:
576  dimension->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
577 
578  // Dimensions that have origin and end in the same spot are not valid
579  if( dimension->GetOrigin() == dimension->GetEnd() )
580  --step;
581  break;
582 
583  case SET_HEIGHT:
584  {
585  if( wxPoint( cursorPos.x, cursorPos.y ) != dimension->GetPosition() )
586  {
587  assert( dimension->GetOrigin() != dimension->GetEnd() );
588  assert( dimension->GetWidth() > 0 );
589 
590  preview.Remove( dimension );
591 
592  commit.Add( dimension );
593  commit.Push( _( "Draw a dimension" ) );
594 
595  }
596  }
597  break;
598  }
599 
600  if( ++step == FINISHED )
601  {
602  step = SET_ORIGIN;
603  m_controls->SetAutoPan( false );
604  m_controls->CaptureCursor( false );
605  }
606  }
607 
608  else if( evt->IsMotion() )
609  {
610  switch( step )
611  {
612  case SET_END:
613  dimension->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
614  break;
615 
616  case SET_HEIGHT:
617  {
618  // Calculating the direction of travel perpendicular to the selected axis
619  double angle = dimension->GetAngle() + ( M_PI / 2 );
620 
621  wxPoint pos( cursorPos.x, cursorPos.y );
622  wxPoint delta( pos - dimension->m_featureLineDO );
623  double height = ( delta.x * cos( angle ) ) + ( delta.y * sin( angle ) );
624  dimension->SetHeight( height );
625  }
626  break;
627  }
628 
629  // Show a preview of the item
630  m_view->Update( &preview );
631  }
632  }
633 
634  if( step != SET_ORIGIN )
635  delete dimension;
636 
637  m_view->Remove( &preview );
638  m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString );
639 
640  return 0;
641 }
642 
643 
644 int DRAWING_TOOL::DrawZone( const TOOL_EVENT& aEvent )
645 {
646  SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::ZONE );
647  m_frame->SetToolID( ID_PCB_ZONES_BUTT, wxCURSOR_PENCIL, _( "Add zones" ) );
648 
649  return drawZone( false, ZONE_MODE::ADD );
650 }
651 
652 
654 {
655  SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::KEEPOUT );
656  m_frame->SetToolID( ID_PCB_KEEPOUT_AREA_BUTT, wxCURSOR_PENCIL, _( "Add keepout" ) );
657 
658  return drawZone( true, ZONE_MODE::ADD );
659 }
660 
661 
663 {
664  SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::ZONE );
665  m_frame->SetToolID( ID_PCB_KEEPOUT_AREA_BUTT, wxCURSOR_PENCIL, _( "Add zone cutout" ) );
666 
667  return drawZone( false, ZONE_MODE::CUTOUT );
668 }
669 
670 
672 {
673  SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::ZONE );
674  m_frame->SetToolID( ID_PCB_KEEPOUT_AREA_BUTT, wxCURSOR_PENCIL, _( "Add similar zone" ) );
675 
676  return drawZone( false, ZONE_MODE::SIMILAR );
677 }
678 
679 
680 int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent )
681 {
682  if( !m_frame->GetModel() )
683  return 0;
684 
685  DIALOG_DXF_IMPORT dlg( m_frame );
686  int dlgResult = dlg.ShowModal();
687 
688  const std::list<BOARD_ITEM*>& list = dlg.GetImportedItems();
689 
690  if( dlgResult != wxID_OK || list.empty() )
691  return 0;
692 
693  VECTOR2I cursorPos = m_controls->GetCursorPosition();
694  VECTOR2I delta = cursorPos - list.front()->GetPosition();
695 
696  // Add a VIEW_GROUP that serves as a preview for the new item
697  SELECTION preview;
698  BOARD_COMMIT commit( m_frame );
699 
700  // Build the undo list & add items to the current view
701  for( auto item : list )
702  {
703  assert( item->Type() == PCB_LINE_T || item->Type() == PCB_TEXT_T );
704  preview.Add( item );
705  }
706 
707  BOARD_ITEM* firstItem = static_cast<BOARD_ITEM*>( preview.Front() );
708  m_view->Add( &preview );
709 
711  m_controls->ShowCursor( true );
712  m_controls->SetSnapping( true );
713 
714  SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::DXF );
715 
716  Activate();
717 
718  // Main loop: keep receiving events
719  while( OPT_TOOL_EVENT evt = Wait() )
720  {
721  cursorPos = m_controls->GetCursorPosition();
722 
723  if( evt->IsMotion() )
724  {
725  delta = cursorPos - firstItem->GetPosition();
726 
727  for( auto item : preview )
728  static_cast<BOARD_ITEM*>( item )->Move( wxPoint( delta.x, delta.y ) );
729 
730  m_view->Update( &preview );
731  }
732 
733  else if( evt->Category() == TC_COMMAND )
734  {
735  // TODO it should be handled by EDIT_TOOL, so add items and select?
736  if( TOOL_EVT_UTILS::IsRotateToolEvt( *evt ) )
737  {
738  const auto rotationPoint = wxPoint( cursorPos.x, cursorPos.y );
739  const auto rotationAngle = TOOL_EVT_UTILS::GetEventRotationAngle(
740  *m_frame, *evt );
741 
742  for( auto item : preview )
743  {
744  static_cast<BOARD_ITEM*>( item )->Rotate( rotationPoint, rotationAngle );
745  }
746 
747  m_view->Update( &preview );
748  }
749  else if( evt->IsAction( &PCB_ACTIONS::flip ) )
750  {
751  for( auto item : preview )
752  static_cast<BOARD_ITEM*>( item )->Flip( wxPoint( cursorPos.x, cursorPos.y ) );
753 
754  m_view->Update( &preview );
755  }
756  else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) )
757  {
758  preview.FreeItems();
759  break;
760  }
761  }
762 
763  else if( evt->IsClick( BUT_RIGHT ) )
764  {
766  }
767 
768  else if( evt->IsClick( BUT_LEFT ) )
769  {
770  // Place the drawing
772 
773  for( auto item : preview )
774  {
775  if( m_editModules )
776  {
777  // Modules use different types for the same things,
778  // so we need to convert imported items to appropriate classes.
779  BOARD_ITEM* converted = NULL;
780 
781  switch( item->Type() )
782  {
783  case PCB_TEXT_T:
784  {
785  TEXTE_PCB* text = static_cast<TEXTE_PCB*>( item );
786  TEXTE_MODULE* textMod = new TEXTE_MODULE( (MODULE*) parent );
787 
788  // Assignment operator also copies the item PCB_TEXT_T type,
789  // so it cannot be added to a module which handles PCB_MODULE_TEXT_T
790  textMod->SetText( text->GetText() );
791 #if 0
792  textMod->SetTextSize( text->GetTextSize() );
793  textMod->SetThickness( text->GetThickness() );
794  textMod->SetOrientation( text->GetTextAngle() );
795  textMod->SetTextPos( text->GetTextPos() );
796  textMod->SetTextSize( text->GetTextSize() );
797  textMod->SetVisible( text->GetVisible() );
798  textMod->SetMirrored( text->IsMirrored() );
799  textMod->SetItalic( text->IsItalic() );
800  textMod->SetBold( text->IsBold() );
801  textMod->SetHorizJustify( text->GetHorizJustify() );
802  textMod->SetVertJustify( text->GetVertJustify() );
803  textMod->SetMultilineAllowed( text->IsMultilineAllowed() );
804 #else
805  textMod->EDA_TEXT::SetEffects( *text );
806  textMod->SetLocalCoord(); // using changed SetTexPos() via SetEffects()
807 #endif
808  converted = textMod;
809  break;
810  }
811 
812  case PCB_LINE_T:
813  {
814  DRAWSEGMENT* seg = static_cast<DRAWSEGMENT*>( item );
815  EDGE_MODULE* modSeg = new EDGE_MODULE( (MODULE*) parent );
816 
817  // Assignment operator also copies the item PCB_LINE_T type,
818  // so it cannot be added to a module which handles PCB_MODULE_EDGE_T
819  modSeg->SetWidth( seg->GetWidth() );
820  modSeg->SetStart( seg->GetStart() );
821  modSeg->SetEnd( seg->GetEnd() );
822  modSeg->SetAngle( seg->GetAngle() );
823  modSeg->SetShape( seg->GetShape() );
824  modSeg->SetType( seg->GetType() );
825  modSeg->SetBezControl1( seg->GetBezControl1() );
826  modSeg->SetBezControl2( seg->GetBezControl2() );
827  modSeg->SetBezierPoints( seg->GetBezierPoints() );
828  modSeg->SetPolyPoints( seg->GetPolyPoints() );
829  converted = modSeg;
830  break;
831  }
832 
833  default:
834  assert( false );
835  break;
836  }
837 
838  if( converted )
839  converted->SetLayer( static_cast<BOARD_ITEM*>( item )->GetLayer() );
840 
841  delete item;
842  item = converted;
843  }
844 
845  if( item )
846  commit.Add( item );
847  }
848 
849  commit.Push( _( "Place a DXF drawing" ) );
850  break;
851  }
852  }
853 
854  preview.Clear();
855  m_view->Remove( &preview );
856 
857  return 0;
858 }
859 
860 
862 {
863  assert( m_editModules );
864 
865  SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::ANCHOR );
866 
867  Activate();
868  m_frame->SetToolID( ID_MODEDIT_ANCHOR_TOOL, wxCURSOR_PENCIL,
869  _( "Place the footprint anchor" ) );
870 
871  m_controls->ShowCursor( true );
872  m_controls->SetSnapping( true );
873  m_controls->SetAutoPan( true );
874  m_controls->CaptureCursor( false );
875 
876  while( OPT_TOOL_EVENT evt = Wait() )
877  {
878  if( evt->IsClick( BUT_LEFT ) )
879  {
880  MODULE* module = (MODULE*) m_frame->GetModel();
881  BOARD_COMMIT commit( m_frame );
882  commit.Modify( module );
883 
884  // set the new relative internal local coordinates of footprint items
885  VECTOR2I cursorPos = m_controls->GetCursorPosition();
886  wxPoint moveVector = module->GetPosition() - wxPoint( cursorPos.x, cursorPos.y );
887  module->MoveAnchorPosition( moveVector );
888 
889  commit.Push( _( "Move the footprint reference anchor" ) );
890 
891  // Usually, we do not need to change twice the anchor position,
892  // so deselect the active tool
893  break;
894  }
895  else if( evt->IsClick( BUT_RIGHT ) )
896  {
898  }
899  else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) )
900  break;
901  }
902 
903  m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString );
904 
905  return 0;
906 }
907 
908 
909 bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic,
910  boost::optional<VECTOR2D> aStartingPoint )
911 {
912  // Only two shapes are currently supported
913  assert( aShape == S_SEGMENT || aShape == S_CIRCLE );
914 
915  DRAWSEGMENT line45;
916 
917  // Add a VIEW_GROUP that serves as a preview for the new item
918  SELECTION preview;
919  m_view->Add( &preview );
920 
922  m_controls->ShowCursor( true );
923  m_controls->SetSnapping( true );
924 
925  Activate();
926 
927  bool direction45 = false; // 45 degrees only mode
928  bool started = false;
929  VECTOR2I cursorPos = m_controls->GetCursorPosition();
930 
931  if( aStartingPoint )
932  {
933  // Init the new item attributes
934  aGraphic->SetShape( (STROKE_T) aShape );
935  aGraphic->SetWidth( m_lineWidth );
936  aGraphic->SetStart( wxPoint( aStartingPoint->x, aStartingPoint->y ) );
937  aGraphic->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
938  aGraphic->SetLayer( getDrawingLayer() );
939 
940  if( aShape == S_SEGMENT )
941  line45 = *aGraphic; // used only for direction 45 mode with lines
942 
943  preview.Add( aGraphic );
944  m_controls->SetAutoPan( true );
945  m_controls->CaptureCursor( true );
946 
947  started = true;
948  }
949 
950  // Main loop: keep receiving events
951  while( OPT_TOOL_EVENT evt = Wait() )
952  {
953  cursorPos = m_controls->GetCursorPosition();
954 
955  // 45 degree angle constraint enabled with an option and toggled with Ctrl
956  const bool limit45 = ( g_Segments_45_Only != !!( evt->Modifier( MD_CTRL ) ) );
957 
958  if( direction45 != limit45 && started && aShape == S_SEGMENT )
959  {
960  direction45 = limit45;
961 
962  if( direction45 )
963  {
964  preview.Add( &line45 );
965  make45DegLine( aGraphic, &line45 );
966  }
967  else
968  {
969  preview.Remove( &line45 );
970  aGraphic->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
971  }
972 
973  m_view->Update( &preview );
974  }
975 
977  {
978  preview.Clear();
979  m_view->Update( &preview );
980  delete aGraphic;
981  aGraphic = NULL;
982  break;
983  }
984  else if( evt->IsAction( &PCB_ACTIONS::layerChanged ) )
985  {
986  aGraphic->SetLayer( getDrawingLayer() );
987  m_view->Update( &preview );
988  }
989  else if( evt->IsClick( BUT_RIGHT ) )
990  {
992  }
993  else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) )
994  {
995  if( !started )
996  {
997  // Init the new item attributes
998  aGraphic->SetShape( (STROKE_T) aShape );
999  aGraphic->SetWidth( m_lineWidth );
1000  aGraphic->SetStart( wxPoint( cursorPos.x, cursorPos.y ) );
1001  aGraphic->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
1002  aGraphic->SetLayer( getDrawingLayer() );
1003 
1004  if( aShape == S_SEGMENT )
1005  line45 = *aGraphic; // used only for direction 45 mode with lines
1006 
1007  preview.Add( aGraphic );
1008  m_controls->SetAutoPan( true );
1009  m_controls->CaptureCursor( true );
1010 
1011  started = true;
1012  }
1013  else
1014  {
1015  if( aGraphic->GetEnd() == aGraphic->GetStart() ||
1016  ( evt->IsDblClick( BUT_LEFT ) && aShape == S_SEGMENT ) )
1017  // User has clicked twice in the same spot
1018  { // a clear sign that the current drawing is finished
1019  // Now we have to add the helper line as well
1020  if( direction45 )
1021  {
1022  BOARD_ITEM_CONTAINER* parent = m_frame->GetModel();
1023  DRAWSEGMENT* l = m_editModules ? new EDGE_MODULE( (MODULE*) parent )
1024  : new DRAWSEGMENT;
1025 
1026  // Copy coordinates, layer, etc.
1027  *static_cast<DRAWSEGMENT*>( l ) = line45;
1028  l->SetEnd( aGraphic->GetStart() );
1029 
1030  BOARD_COMMIT commit( m_frame );
1031  commit.Add( l );
1032  commit.Push( _( "Draw a line" ) );
1033  }
1034 
1035  delete aGraphic;
1036  aGraphic = NULL;
1037  }
1038 
1039  preview.Clear();
1040  break;
1041  }
1042  }
1043 
1044  else if( evt->IsMotion() )
1045  {
1046  // 45 degree lines
1047  if( direction45 && aShape == S_SEGMENT )
1048  make45DegLine( aGraphic, &line45 );
1049  else
1050  aGraphic->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
1051 
1052  m_view->Update( &preview );
1053  }
1054 
1055  else if( evt->IsAction( &PCB_ACTIONS::incWidth ) )
1056  {
1058  aGraphic->SetWidth( m_lineWidth );
1059  line45.SetWidth( m_lineWidth );
1060  m_view->Update( &preview );
1061  }
1062 
1063  else if( evt->IsAction( &PCB_ACTIONS::decWidth ) && ( m_lineWidth > WIDTH_STEP ) )
1064  {
1066  aGraphic->SetWidth( m_lineWidth );
1067  line45.SetWidth( m_lineWidth );
1068  m_view->Update( &preview );
1069  }
1070  }
1071 
1072  m_view->Remove( &preview );
1073  m_controls->SetAutoPan( false );
1074  m_controls->CaptureCursor( false );
1075 
1076  return started;
1077 }
1078 
1079 
1086  DRAWSEGMENT& aArc )
1087 {
1088  auto vec = aMgr.GetOrigin();
1089 
1090  aArc.SetCenter( { vec.x, vec.y } );
1091 
1092  vec = aMgr.GetStartRadiusEnd();
1093  aArc.SetArcStart( { vec.x, vec.y } );
1094 
1095  aArc.SetAngle( RAD2DECIDEG( -aMgr.GetSubtended() ) );
1096 }
1097 
1098 
1100 {
1102 
1103  // Arc geometric construction manager
1105 
1106  // Arc drawing assistant overlay
1107  KIGFX::PREVIEW::ARC_ASSISTANT arcAsst( arcManager );
1108 
1109  // Add a VIEW_GROUP that serves as a preview for the new item
1110  SELECTION preview;
1111  m_view->Add( &preview );
1112  m_view->Add( &arcAsst );
1113 
1114  m_controls->ShowCursor( true );
1115  m_controls->SetSnapping( true );
1116 
1117  Activate();
1118 
1119  bool firstPoint = false;
1120 
1121  // Main loop: keep receiving events
1122  while( OPT_TOOL_EVENT evt = Wait() )
1123  {
1124  const VECTOR2I cursorPos = m_controls->GetCursorPosition();
1125 
1126  if( evt->IsClick( BUT_LEFT ) )
1127  {
1128  if( !firstPoint )
1129  {
1130  m_controls->SetAutoPan( true );
1131  m_controls->CaptureCursor( true );
1132 
1133  LAYER_ID layer = getDrawingLayer();
1134 
1135  // Init the new item attributes
1136  // (non-geometric, those are handled by the manager)
1137  aGraphic->SetShape( S_ARC );
1138  aGraphic->SetWidth( m_lineWidth );
1139  aGraphic->SetLayer( layer );
1140 
1141  preview.Add( aGraphic );
1142  firstPoint = true;
1143  }
1144 
1145  arcManager.AddPoint( cursorPos, true );
1146  }
1147 
1148  else if( evt->IsAction( &deleteLastPoint ) )
1149  {
1150  arcManager.RemoveLastPoint();
1151  }
1152 
1153  else if( evt->IsMotion() )
1154  {
1155  // set angle snap
1156  arcManager.SetAngleSnap( evt->Modifier( MD_CTRL ) );
1157 
1158  // update, but don't step the manager state
1159  arcManager.AddPoint( cursorPos, false );
1160  }
1161 
1162  else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) )
1163  {
1164  preview.Clear();
1165  delete aGraphic;
1166  aGraphic = nullptr;
1167  break;
1168  }
1169  else if( evt->IsClick( BUT_RIGHT ) )
1170  {
1172  }
1173 
1174  else if( evt->IsAction( &PCB_ACTIONS::incWidth ) )
1175  {
1177  aGraphic->SetWidth( m_lineWidth );
1178  m_view->Update( &preview );
1179  }
1180 
1181  else if( evt->IsAction( &PCB_ACTIONS::decWidth ) && m_lineWidth > WIDTH_STEP )
1182  {
1184  aGraphic->SetWidth( m_lineWidth );
1185  m_view->Update( &preview );
1186  }
1187 
1188  else if( evt->IsAction( &PCB_ACTIONS::arcPosture ) )
1189  {
1190  arcManager.ToggleClockwise();
1191  }
1192 
1193  if( arcManager.IsComplete() )
1194  {
1195  break;
1196  }
1197  else if( arcManager.HasGeometryChanged() )
1198  {
1199  updateArcFromConstructionMgr( arcManager, *aGraphic );
1200  m_view->Update( &preview );
1201  m_view->Update( &arcAsst );
1202  }
1203  }
1204 
1205  preview.Remove( aGraphic );
1206  m_view->Remove( &arcAsst );
1207  m_view->Remove( &preview );
1208  m_controls->SetAutoPan( false );
1209  m_controls->CaptureCursor( false );
1210 
1211  return !arcManager.IsReset();
1212 }
1213 
1214 
1216 {
1217  aZone = nullptr;
1218 
1219  // not an action that needs a source zone
1220  if( aMode == ZONE_MODE::ADD )
1221  return true;
1222 
1224  const SELECTION& selection = selTool->GetSelection();
1225 
1226  if( selection.Empty() )
1228 
1229  // we want a single zone
1230  if( selection.Size() != 1 )
1231  return false;
1232 
1233  aZone = dyn_cast<ZONE_CONTAINER*>( selection[0] );
1234 
1235  // expected a zone, but didn't get one
1236  if( !aZone )
1237  return false;
1238 
1239  return true;
1240 }
1241 
1242 
1244 {
1245  auto& controls = *getViewControls();
1246  bool started = false;
1247 
1248  while( OPT_TOOL_EVENT evt = Wait() )
1249  {
1250  VECTOR2I cursorPos = controls.GetCursorPosition();
1251 
1253  {
1254  // pre-empted by another tool, give up
1255  // cancelled without an inprogress polygon, give up
1256  if( !polyGeomMgr.IsPolygonInProgress() || evt->IsActivate() )
1257  {
1258  break;
1259  }
1260 
1261  polyGeomMgr.Reset();
1262  // start again
1263  started = false;
1264 
1265  controls.SetAutoPan( false );
1266  controls.CaptureCursor( false );
1267  }
1268 
1269  else if( evt->IsClick( BUT_RIGHT ) )
1270  {
1272  }
1273 
1274  // events that lock in nodes
1275  else if( evt->IsClick( BUT_LEFT )
1276  || evt->IsDblClick( BUT_LEFT )
1277  || evt->IsAction( &closeZoneOutline ) )
1278  {
1279  // Check if it is double click / closing line (so we have to finish the zone)
1280  const bool endPolygon = evt->IsDblClick( BUT_LEFT )
1281  || evt->IsAction( &closeZoneOutline )
1282  || polyGeomMgr.NewPointClosesOutline( cursorPos );
1283 
1284  if( endPolygon )
1285  {
1286  polyGeomMgr.SetFinished();
1287  polyGeomMgr.Reset();
1288 
1289  // ready to start again
1290  started = false;
1291  controls.SetAutoPan( false );
1292  controls.CaptureCursor( false );
1293  }
1294  else // adding a corner
1295  {
1296  polyGeomMgr.AddPoint( cursorPos );
1297 
1298  if( !started )
1299  {
1300  started = true;
1301  controls.SetAutoPan( true );
1302  controls.CaptureCursor( true );
1303  }
1304  }
1305  }
1306 
1307  else if( evt->IsAction( &deleteLastPoint ) )
1308  {
1309  polyGeomMgr.DeleteLastCorner();
1310 
1311  if( !polyGeomMgr.IsPolygonInProgress() )
1312  {
1313  // report finished as an empty shape
1314  polyGeomMgr.SetFinished();
1315 
1316  // start again
1317  started = false;
1318  controls.SetAutoPan( false );
1319  controls.CaptureCursor( false );
1320  }
1321  }
1322 
1323  else if( polyGeomMgr.IsPolygonInProgress()
1324  && ( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) )
1325  {
1326  bool draw45 = evt->Modifier( MD_CTRL );
1329  polyGeomMgr.SetCursorPosition( cursorPos );
1330  }
1331  } // end while
1332 }
1333 
1334 
1335 int DRAWING_TOOL::drawZone( bool aKeepout, ZONE_MODE aMode )
1336 {
1337  // get a source zone, if we need one
1338  ZONE_CONTAINER* sourceZone = nullptr;
1339 
1340  if( !getSourceZoneForAction( aMode, sourceZone ) )
1341  return 0;
1342 
1344 
1345  params.m_keepout = aKeepout;
1346  params.m_mode = aMode;
1347  params.m_sourceZone = sourceZone;
1348 
1349  ZONE_CREATE_HELPER zoneTool( *this, params );
1350 
1351  // the geometry manager which handles the zone geometry, and
1352  // hands the calculated points over to the zone creator tool
1353  POLYGON_GEOM_MANAGER polyGeomMgr( zoneTool );
1354 
1355  Activate(); // register for events
1356 
1357  auto& controls = *getViewControls();
1358 
1360 
1361  controls.ShowCursor( true );
1362  controls.SetSnapping( true );
1363 
1364  runPolygonEventLoop( polyGeomMgr );
1365 
1366  m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString );
1367 
1368  return 0;
1369 }
1370 
1371 
1372 void DRAWING_TOOL::make45DegLine( DRAWSEGMENT* aSegment, DRAWSEGMENT* aHelper ) const
1373 {
1374  VECTOR2I cursorPos = m_controls->GetCursorPosition();
1375  VECTOR2I origin( aSegment->GetStart() );
1376  DIRECTION_45 direction( origin - cursorPos );
1377  SHAPE_LINE_CHAIN newChain = direction.BuildInitialTrace( origin, cursorPos );
1378 
1379  if( newChain.PointCount() > 2 )
1380  {
1381  aSegment->SetEnd( wxPoint( newChain.Point( -2 ).x, newChain.Point( -2 ).y ) );
1382  aHelper->SetStart( wxPoint( newChain.Point( -2 ).x, newChain.Point( -2 ).y ) );
1383  aHelper->SetEnd( wxPoint( newChain.Point( -1 ).x, newChain.Point( -1 ).y ) );
1384  }
1385  else
1386  {
1387  aSegment->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
1388  aHelper->SetStart( wxPoint( cursorPos.x, cursorPos.y ) );
1389  aHelper->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
1390  }
1391 }
1392 
1393 
1395 {
1407 }
1408 
1409 
1410 int DRAWING_TOOL::getSegmentWidth( unsigned int aLayer ) const
1411 {
1412  assert( m_board );
1413 
1414  if( aLayer == Edge_Cuts )
1416  else if( m_editModules )
1418  else
1420 }
1421 
1422 
1424 {
1425  LAYER_ID layer = m_frame->GetActiveLayer();
1426 
1427  if( IsCopperLayer( layer ) )
1428  {
1429  if( layer == F_Cu )
1430  layer = F_SilkS;
1431  else if( layer == B_Cu )
1432  layer = B_SilkS;
1433  else
1434  layer = Dwgs_User;
1435 
1436  m_frame->SetActiveLayer( layer );
1437  }
1438 
1439  return layer;
1440 }
1441 
1442 const unsigned int DRAWING_TOOL::WIDTH_STEP = 100000;
void SetMirrored(bool isMirrored)
Definition: eda_text.h:178
bool g_Segments_45_Only
Definition: pcbnew.cpp:75
static TOOL_ACTION selectionClear
Clears the current selection.
Definition: pcb_actions.h:53
virtual void ShowCursor(bool aEnabled)
Function ShowCursor() Enables or disables display of cursor.
static TOOL_ACTION drawLine
Activation of the drawing tool (line)
Definition: pcb_actions.h:119
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:78
int DrawKeepout(const TOOL_EVENT &aEvent)
Function DrawKeepout() Starts interactively drawing a keepout area.
Class ARC_GEOM_MANAGER.
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.
void SetShape(STROKE_T aShape)
virtual void Clear() override
Function Clear() Removes all the stored items from the group.
Definition: selection.h:81
virtual void SetToolID(int aId, int aCursor, const wxString &aToolMsg) override
Function SetToolID sets the tool command ID to aId and sets the cursor to aCursor.
const wxPoint & GetBezControl2() const
bool IsMultilineAllowed() const
Definition: eda_text.h:188
static TOOL_ACTION placeDXF
Activation of the drawing tool (placing a drawing from DXF file)
Definition: pcb_actions.h:152
void SetBezierPoints(const std::vector< wxPoint > &aPoints)
virtual LAYER_ID GetActiveLayer() const
Function GetActiveLayer returns the active layer.
TEXTE_PCB class definition.
const wxPoint & GetTextPos() const
Definition: eda_text.h:224
static TOOL_ACTION closeZoneOutline("pcbnew.InteractiveDrawing.closeZoneOutline", AS_CONTEXT, 0, _("Close Zone Outline"), _("Close the outline of a zone in progress"), checked_ok_xpm)
int DrawZone(const TOOL_EVENT &aEvent)
Function DrawZone() Starts interactively drawing a zone.
BOARD * m_board
Definition: drawing_tool.h:258
static TOOL_ACTION incWidth
Increase width of currently drawn line.
Definition: pcb_actions.h:158
bool IsItalic() const
Definition: eda_text.h:170
virtual void SetPosition(const wxPoint &aPos)=0
void SetArcStart(const wxPoint &aArcStartPoint)
Initialize the start arc point.
MODE GetDrawingMode() const
Function GetDrawingMode.
static TOOL_ACTION drawSimilarZone
Activation of the drawing tool (drawing a similar ZONE to another one)
Definition: pcb_actions.h:143
This file is part of the common library.
int drawZone(bool aKeepout, ZONE_MODE aMode)
Draws a polygon, that is added as a zone or a keepout area.
int m_ModuleTextWidth
Default footprint texts thickness.
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class...
static TOOL_ACTION drawArc
Activation of the drawing tool (arc)
Definition: pcb_actions.h:125
void SetType(int aType)
int m_ModuleSegmentWidth
Default width for all graphic lines.
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
int PointCount() const
Function PointCount()
VIEW_CONTROLS class definition.
int m_PcbTextWidth
current Pcb (not module) Text width
void RunMainStack(std::function< void()> aFunc)
Function RunMainStack()
bool IsBackLayer(LAYER_ID aLayerId)
Layer classification: check if it's a back layer.
int GetWidth() const
static TOOL_ACTION deleteLastPoint("pcbnew.InteractiveDrawing.deleteLastPoint", AS_CONTEXT, WXK_BACK, _("Delete Last Point"), _("Delete the last point added to the current item"), undo_xpm)
Class SELECTION_TOOL.
Class BOARD to handle a board.
const wxPoint & GetPosition() const override
Definition: class_module.h:143
Class that computes missing connections on a PCB.
CONDITIONAL_MENU & GetMenu()
Function GetMenu.
Definition: tool_menu.cpp:49
static const unsigned int WIDTH_STEP
Definition: drawing_tool.h:269
void SetItalic(bool isItalic)
Definition: eda_text.h:169
EDA_ITEM * Front() const
Definition: selection.h:137
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:220
virtual void SetLayer(LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
static TOOL_ACTION cancelInteractive
Definition: actions.h:45
void Remove(VIEW_ITEM *aItem)
Function Remove() Removes a VIEW_ITEM from the view.
Definition: view.cpp:340
void SetTextPos(const wxPoint &aPoint)
Definition: eda_text.h:223
void SetVisible(bool aVisible)
Definition: eda_text.h:175
OPT_TOOL_EVENT Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Function Wait()
virtual const wxPoint & GetPosition() const =0
class TEXTE_PCB, text on a layer
Definition: typeinfo.h:104
virtual void SetSnapping(bool aEnabled)
Function SetSnapping() Enables/disables snapping cursor to grid.
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Function RunAction() Runs the specified action.
Definition: tool_manager.h:125
double RAD2DECIDEG(double rad)
Definition: trigo.h:196
static int LegacyHotKey(int aHotKey)
Creates a hot key code that refers to a legacy hot key setting, instead of a particular key...
Definition: tool_action.h:174
Classes to handle copper zones.
void RemoveLastPoint()
Undo the last point, and move the manager back to the previous step.
usual segment : line with rounded ends
bool getSourceZoneForAction(ZONE_MODE aMode, ZONE_CONTAINER *&aZone)
Function getSourceZoneForAction()
static void updateArcFromConstructionMgr(const KIGFX::PREVIEW::ARC_GEOM_MANAGER &aMgr, DRAWSEGMENT &aArc)
Update an arc DRAWSEGMENT from the current state of an Arc Geoemetry Manager.
const std::vector< wxPoint > & GetPolyPoints() const
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:214
bool drawSegment(int aShape, DRAWSEGMENT *&aGraphic, boost::optional< VECTOR2D > aStartingPoint=boost::none)
Starts drawing a selected shape (i.e.
Parameters used to fully describe a zone creation process.
bool IsRotateToolEvt(const TOOL_EVENT &aEvt)
Function isRotateToolEvt()
wxSize m_ModuleTextSize
Default footprint texts size.
virtual void SetActiveLayer(LAYER_ID aLayer)
Function SetActiveLayer will change the currently active layer to aLayer.
void SetLeaderMode(LEADER_MODE aMode)
Set the leader mode to use when calculating the leader/returner lines.
void MoveAnchorPosition(const wxPoint &aMoveVector)
Function MoveAnchorPosition Move the reference point of the footprint It looks like a move footprint:...
double GetAngle() const
Function GetAngle Returns angle of the crossbar.
void SetCenter(const wxPoint &aCenterPoint)
For arcs and circles:
EDA_TEXT_HJUSTIFY_T GetHorizJustify() const
Definition: eda_text.h:190
static TOOL_ACTION setAnchor
Activation of the drawing tool (placing the footprint anchor)
Definition: pcb_actions.h:155
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Function Go()
void SetBezControl2(const wxPoint &aPoint)
static TOOL_ACTION placeText
Activation of the drawing tool (text)
Definition: pcb_actions.h:128
static const int delta[8][2]
Definition: solve.cpp:112
Casted dyn_cast(From aObject)
Function dyn_cast()
Definition: typeinfo.h:73
Add a new zone with the same settings as an existing one.
virtual void Push(const wxString &aMessage=wxT("A commit"), bool aCreateUndoEntry=true) override
Executes the changes.
bool IsBold() const
Definition: eda_text.h:173
double GetTextAngle() const
Definition: eda_text.h:164
void AddPoint(const VECTOR2I &aPt, bool aLockIn)
Add a point to the construction manager.
Pcbnew hotkeys.
int GetThickness() const
Function GetThickness returns pen width.
Definition: eda_text.h:154
static TOOL_ACTION decWidth
Decrease width of currently drawn line.
Definition: pcb_actions.h:161
virtual void Add(EDA_ITEM *aItem)
Definition: selection.h:71
int PlaceDXF(const TOOL_EVENT &aEvent)
Function PlaceDXF() Places a drawing imported from a DXF file in module editor.
KIGFX::VIEW * m_view
Definition: drawing_tool.h:256
int getSegmentWidth(unsigned int aLayer) const
Returns the appropriate width for a segment depending on the settings.
#define IS_NEW
New item, just created.
Definition: base_struct.h:113
DIMENSION class definition.
void SetTransitions() override
Sets up handlers for various events.
void SetLayer(LAYER_ID aLayer) override
Function SetLayer sets the layer this item is on.
int PlaceText(const TOOL_EVENT &aEvent)
Function PlaceText() Displays a dialog that allows to input text and its settings and then lets the u...
void AddStandardSubMenus(EDA_DRAW_FRAME &aFrame)
Function CreateBasicMenu.
Definition: tool_menu.cpp:95
STROKE_T GetShape() const
void FreeItems()
Function FreeItems() Frees all the items that were added to the group.
Definition: view_group.cpp:139
Unconstrained point-to-point
void SetOrigin(const wxPoint &aOrigin)
Function SetOrigin Sets a new origin of the crossbar line.
RAII class that sets an value at construction and resets it to the original value at destruction...
const wxPoint & GetEnd() const
Function GetEnd returns the ending point of the graphic.
void SetFlags(STATUS_FLAGS aMask)
Definition: base_struct.h:253
static TOOL_ACTION drawDimension
Activation of the drawing tool (dimension)
Definition: pcb_actions.h:131
const wxPoint & GetEnd()
Function GetEnd.
virtual VECTOR2D GetCursorPosition() const =0
Function GetCursorPosition() Returns the current cursor position in world coordinates.
virtual void CaptureCursor(bool aEnabled)
Function CaptureCursor() Forces the cursor to stay within the drawing panel area. ...
wxSize m_PcbTextSize
current Pcb (not module) Text size
Class DIRECTION_45.
Definition: direction45.h:33
const wxPoint & GetOrigin() const
Function GetOrigin.
void AddPoint(const VECTOR2I &aPt)
Lock in a polygon point.
const wxString & GetText() const
Function GetText returns the string associated with the text object.
Definition: eda_text.h:130
void SetEnd(const wxPoint &aEnd)
Function SetEnd Sets a new end of the crossbar line.
void Reset(RESET_REASON aReason) override
Function Reset() Brings the tool to a known, initial state.
int Clamp_Text_PenSize(int aPenSize, int aSize, bool aBold)
Function Clamp_Text_PenSize As a rule, pen width should not be >1/4em, otherwise the character will b...
Definition: drawtxt.cpp:67
void SetVertJustify(EDA_TEXT_VJUSTIFY_T aType)
Definition: eda_text.h:194
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)
Class TOOL_EVENT.
Definition: tool_event.h:162
unsigned int m_lineWidth
Stores the current line width for multisegment drawing.
Definition: drawing_tool.h:263
int m_DrawSegmentWidth
current graphic line width (not EDGE layer)
SELECTION & GetSelection()
Function GetSelection()
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:530
STROKE_T
Enum STROKE_T is the set of shapes for segments (graphic segments and tracks) which are often in the ...
static TOOL_ACTION drawKeepout
Activation of the drawing tool (drawing a keepout area)
Definition: pcb_actions.h:137
VIEW_GROUP extends VIEW_ITEM by possibility of grouping items into a single object.
virtual BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings returns the BOARD_DESIGN_SETTINGS for the BOARD owned by this frame...
const wxPoint & GetBezControl1() const
KIGFX::VIEW_CONTROLS * m_controls
Definition: drawing_tool.h:257
virtual void Rotate(const wxPoint &aRotCentre, double aAngle)
Function Rotate Rotate this object.
int GetType() const
bool IsCancelInteractive(const TOOL_EVENT &aEvt)
Function IsCancelInteractive()
All active tools
Definition: tool_event.h:138
Class PCB_TOOL.
Definition: pcb_tool.h:45
double GetSubtended() const
Get the angle of the vector leading to the end point (valid if step >= SET_ANGLE) ...
static TOOL_ACTION drawZoneCutout
Activation of the drawing tool (drawing a ZONE cutout)
Definition: pcb_actions.h:140
void Update(VIEW_ITEM *aItem)
Function Update() For dynamic VIEWs, informs the associated VIEW that the graphical representation of...
Definition: view.cpp:1378
void SetMultilineAllowed(bool aAllow)
Function SetMultiLineAllowed.
Definition: eda_text.h:187
int DrawZoneCutout(const TOOL_EVENT &aEvent)
Function DrawZoneCutout() Starts interactively drawing a zone cutout area of an existing zone...
virtual void SetAutoPan(bool aEnabled)
Function SetAutoPan Turns on/off auto panning (this feature is used when there is a tool active (eg...
KIGFX::VIEW_CONTROLS * getViewControls() const
Function getViewControls()
Definition: tool_base.cpp:36
void AdjustDimensionDetails(bool aDoNotChangeText=false)
Function AdjustDimensionDetails Calculate coordinates of segments used to draw the dimension...
void SetStart(const wxPoint &aStart)
DRAWING_TOOL::ZONE_MODE m_mode
The zone mode to operate in
PCB_BASE_EDIT_FRAME * m_frame
Definition: drawing_tool.h:259
bool m_editModules
Definition: pcb_tool.h:112
void DeleteLastCorner()
Remove the last-added point from the polygon.
void SetPolyPoints(const std::vector< wxPoint > &aPoints)
KIGFX::VIEW * getView() const
Function getView()
Definition: tool_base.cpp:30
static TOOL_ACTION drawCircle
Activation of the drawing tool (circle)
Definition: pcb_actions.h:122
virtual void Flip(const wxPoint &aCentre)
Function Flip Flip this object, i.e.
const std::vector< wxPoint > & GetBezierPoints() const
EDA_TEXT_VJUSTIFY_T GetVertJustify() const
Definition: eda_text.h:191
static TOOL_ACTION flip
Flipping of selected objects.
Definition: pcb_actions.h:90
MODE
The possible drawing modes of DRAWING_TOOL
Definition: drawing_tool.h:68
static TOOL_ACTION arcPosture
Switch posture when drawing arc.
Definition: pcb_actions.h:164
void SetLocalCoord()
Set relative coordinates.
static TOOL_ACTION layerChanged
Definition: pcb_actions.h:245
const std::list< BOARD_ITEM * > & GetImportedItems() const
Function GetImportedItems()
int SetAnchor(const TOOL_EVENT &aEvent)
Function SetAnchor() Places the footprint anchor (only in module editor).
double GetAngle() const
void ToggleClockwise()
Reverse the current are direction
LAYER_ID getDrawingLayer() const
Selects a non-copper layer for drawing
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Definition: eda_text.h:193
LAYER_ID
Enum LAYER_ID is the set of PCB layers.
void AddItem(const TOOL_ACTION &aAction, const SELECTION_CONDITION &aCondition=SELECTION_CONDITIONS::ShowAlways, int aOrder=ANY_ORDER)
Function AddItem()
bool IsMirrored() const
Definition: eda_text.h:179
Class SHAPE_LINE_CHAIN.
void SetHeight(int aHeight)
Function SetHeight Sets the length of feature lines.
bool NewPointClosesOutline(const VECTOR2I &aPt) const
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
TEXTE_PCB & Text()
Class TOOL_ACTION.
Definition: tool_action.h:46
This class is an adjuct helper to the DRAWING_TOOL interactive tool, which handles incoming geometry ...
Class SELECTION_AREA.
Definition: arc_assistant.h:38
void Reset()
Clear the manager state and start again.
int GetWidth() const
RESET_REASON
Determines the reason of reset for a tool
Definition: tool_base.h:80
void SetEnd(const wxPoint &aEnd)
static bool GetLayer(MODEL_VRML &aModel, LAYER_NUM layer, VRML_LAYER **vlayer)
void SetAngle(double aAngle)
Function SetAngle sets the angle for arcs, and normalizes it within the range 0 - 360 degrees...
bool IsCopperLayer(LAYER_NUM aLayerId)
Function IsCopperLayer tests whether a layer is a copper layer.
void ClearFlags(STATUS_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: base_struct.h:254
void Activate()
Function Activate() Runs the tool.
virtual BOARD_ITEM_CONTAINER * GetModel() const =0
Function GetModel() returns the primary data model.
VECTOR2I & Point(int aIndex)
Function Point()
void SetAngleSnap(bool aSnap)
Set angle snapping (for the next point)
void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Function Add() Adds a VIEW_ITEM to the view.
Definition: view.cpp:310
VECTOR2I GetOrigin() const
Get the centre point of the arc (valid when state > SET_ORIGIN)
Module description (excepted pads)
const wxSize & GetTextSize() const
Definition: eda_text.h:215
Abstract interface for BOARD_ITEMs capable of storing other items inside.
bool drawArc(DRAWSEGMENT *&aGraphic)
Starts drawing an arc.
const wxPoint & GetPosition() const override
int m_EdgeSegmentWidth
current graphic line width (EDGE layer only)
bool m_keepout
Should create a keepout zone?
void SetWidth(int aWidth)
EDGE_MODULE class definition.
class DRAWSEGMENT, a segment not on copper layers
Definition: typeinfo.h:103
Add a new zone/keepout with fresh settings.
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.
void SetCursorPosition(const VECTOR2I &aPos)
Set the current cursor position.
int DrawSimilarZone(const TOOL_EVENT &aEvent)
Function DrawSimilarZone() Starts interactively drawing a zone with same settings as an existing zone...
int GetEventRotationAngle(const PCB_BASE_EDIT_FRAME &aFrame, const TOOL_EVENT &aEvt)
Function getEventRotationAngle()
void SetBold(bool aBold)
Definition: eda_text.h:172
wxPoint m_featureLineDO
void runPolygonEventLoop(POLYGON_GEOM_MANAGER &aPolyGeomMgr)
Run the event loop for polygon creation, sending user input on to the given POLYGON_GEOM_MANAGER for ...
void SetFinished()
Mark the polygon finished and update the client.
int DrawArc(const TOOL_EVENT &aEvent)
Function DrawArc() Starts interactively drawing an arc.
Make a cutout to an existing zone.
void ShowContextMenu(SELECTION &aSelection)
Function ShowContextMenu.
Definition: tool_menu.cpp:62
static TOOL_ACTION drawZone
Activation of the drawing tool (drawing a ZONE)
Definition: pcb_actions.h:134
Class DIMENSION.
Class that handles the drawing of a polygon, including management of last corner deletion and drawing...
static TOOL_ACTION selectionCursor
Select a single item under the cursor position.
Definition: pcb_actions.h:50
VECTOR2I GetStartRadiusEnd() const
Get the coordinates of the arc start
TOOL_MENU m_menu
Menu model displayed by the tool.
Definition: drawing_tool.h:266
void SetThickness(int aNewThickness)
Function SetThickness sets pen width.
Definition: eda_text.h:148
void make45DegLine(DRAWSEGMENT *aSegment, DRAWSEGMENT *aHelper) const
Function make45DegLine() Forces a DRAWSEGMENT to be drawn at multiple of 45 degrees.
int DrawDimension(const TOOL_EVENT &aEvent)
Function DrawDimension() Starts interactively drawing a dimension.
Class BOARD_DESIGN_SETTINGS contains design settings for a BOARD object.
void SetBezControl1(const wxPoint &aPoint)
virtual void SetText(const wxString &aText)
Definition: eda_text.h:141
void SetWidth(int aWidth)
virtual void Remove(EDA_ITEM *aItem)
Definition: selection.h:76