KiCad PCB EDA Suite
drawing_stackup_table_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-2021 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include "drawing_tool.h"
26 #include "pcb_actions.h"
27 #include <pcb_edit_frame.h>
28 #include <view/view.h>
29 #include <tool/tool_manager.h>
30 #include <tools/pcb_actions.h>
31 #include <tools/tool_event_utils.h>
32 #include <tools/drawing_tool.h>
33 #include <board_commit.h>
34 #include <scoped_set_reset.h>
35 #include <bitmaps.h>
36 #include <painter.h>
37 #include <board.h>
38 #include <board_design_settings.h>
39 #include <footprint.h>
40 #include <fp_shape.h>
41 #include <pcb_group.h>
42 #include <pcb_text.h>
43 #include <string_utils.h>
44 #include <wx/utils.h>
45 
46 
48 
49 
50 static std::vector<BOARD_ITEM*> initTextTable( std::vector<std::vector<PCB_TEXT*>> aContent,
51  wxPoint origin, PCB_LAYER_ID aLayer,
52  wxPoint* aTableSize,
53  bool aDrawFrame = true )
54 {
55  int i;
56  int j;
57 
58  int nbCols = aContent.size();
59  int nbRows = 0;
60 
61  for( auto col : aContent )
62  nbRows = std::max( nbRows, static_cast<int>( col.size() ) );
63 
64  // Limit the number of cells
65  nbCols = std::min( nbCols, 99 );
66  nbRows = std::min( nbRows, 99 );
67 
68  int rowHeight[99];
69  int colWidth[99];
70 
71  std::vector<BOARD_ITEM*> table;
72 
73  // xmargin and ymargin are margins between the text and the table lines.
74  //
75  // +--------------------------------+
76  // | ^ |
77  // | | ymargin |
78  // | v |
79  // |<------->TEXT_TEXT_TEXT<------->|
80  // | xmargin ^ xmargin |
81  // | | ymargin |
82  // | v |
83  // +--------------------------------+
84  //
85 
86  int xmargin = Millimeter2iu( 0.75 );
87  int ymargin = Millimeter2iu( 0.75 );
88 
89  // Init table
90  for( i = 0; i < nbRows; i++ )
91  rowHeight[i] = 0;
92 
93  for( i = 0; i < nbCols; i++ )
94  colWidth[i] = 0;
95 
96  // First, we determine what the height/Width should be for every cell
97  i = 0;
98 
99  for( const std::vector<PCB_TEXT*>& col : aContent )
100  {
101  j = 0;
102 
103  if( i >= nbCols )
104  break;
105 
106  for( const PCB_TEXT* cell : col )
107  {
108 
109  if( j >= nbRows )
110  break;
111 
112  int height = cell->GetBoundingBox().GetHeight() + 2 * ymargin;
113  int width = cell->GetBoundingBox().GetWidth() + 2 * xmargin;
114  rowHeight[j] = rowHeight[j] > height ? rowHeight[j] : height;
115  colWidth[i] = colWidth[i] > width ? colWidth[i] : width;
116  j++;
117 
118  }
119 
120  i++;
121  }
122 
123  // get table size
124  int height = std::accumulate( rowHeight, rowHeight + nbRows, 0 );
125  int width = std::accumulate( colWidth, colWidth + nbCols, 0 );
126 
127  aTableSize->x = width;
128  aTableSize->y = height;
129  // Draw the frame
130 
131  if( aDrawFrame )
132  {
133  int y = origin.y;
134  PCB_SHAPE* line;
135 
136  for( i = 0; i < nbRows; i++ )
137  {
138  line = new PCB_SHAPE;
139  line->SetLayer( aLayer );
140  line->SetStartX( origin.x );
141  line->SetStartY( y );
142  line->SetEndX( origin.x + width );
143  line->SetEndY( y );
144  y += rowHeight[i];
145  table.push_back( line );
146  }
147 
148  line = new PCB_SHAPE;
149  line->SetLayer( aLayer );
150  line->SetStartX( origin.x );
151  line->SetStartY( y );
152  line->SetEndX( origin.x + width );
153  line->SetEndY( y );
154  table.push_back( line );
155  int x = origin.x;
156 
157  for( i = 0; i < nbCols; i++ )
158  {
159  line = new PCB_SHAPE;
160  line->SetLayer( aLayer );
161  line->SetStartX( x );
162  line->SetStartY( origin.y );
163  line->SetEndX( x );
164  line->SetEndY( origin.y + height );
165  x += colWidth[i];
166  table.push_back( line );
167  }
168 
169  line = new PCB_SHAPE;
170  line->SetLayer( aLayer );
171  line->SetStartX( x );
172  line->SetStartY( origin.y );
173  line->SetEndX( x );
174  line->SetEndY( origin.y + height );
175  table.push_back( line );
176  }
177 
178  //Now add the text
179  i = 0;
180  wxPoint pos = wxPoint( origin.x + xmargin, origin.y + ymargin );
181 
182  for( std::vector<PCB_TEXT*>& col : aContent )
183  {
184  j = 0;
185 
186  if( i >= nbCols )
187  break;
188 
189  pos.y = origin.y + ymargin;
190 
191  for( PCB_TEXT* cell : col )
192  {
193 
194  if( j >= nbRows )
195  break;
196 
197  cell->SetTextPos( pos );
198  cell->SetLayer( aLayer );
199  pos.y = pos.y + rowHeight[j];
200  table.push_back( cell );
201  j++;
202  }
203 
204  pos.x = pos.x + colWidth[i];
205  i++;
206  }
207  return table;
208 }
209 
210 
211 std::vector<BOARD_ITEM*> DRAWING_TOOL::DrawSpecificationStackup( const wxPoint& aOrigin,
212  PCB_LAYER_ID aLayer,
213  bool aDrawNow,
214  wxPoint* tableSize )
215 {
216  BOARD_COMMIT commit( m_frame );
217  std::vector<std::vector<PCB_TEXT*>> texts;
218 
219  // Style : Header
220  PCB_TEXT* headStyle = new PCB_TEXT( static_cast<FOOTPRINT*>( m_frame->GetModel() ) );
221  headStyle->SetLayer( Eco1_User );
222  headStyle->SetTextSize( wxSize( Millimeter2iu( 1.5 ), Millimeter2iu( 1.5 ) ) );
223  headStyle->SetTextThickness( Millimeter2iu( 0.3 ) );
224  headStyle->SetItalic( false );
225  headStyle->SetTextPos( wxPoint( 0, 0 ) );
226  headStyle->SetText( "Layer" );
228  headStyle->SetVertJustify( GR_TEXT_VJUSTIFY_TOP );
229 
230  // Style : data
231  PCB_TEXT* dataStyle = new PCB_TEXT( static_cast<FOOTPRINT*>( m_frame->GetModel() ) );
232  dataStyle->SetLayer( Eco1_User );
233  dataStyle->SetTextSize( wxSize( Millimeter2iu( 1.5 ), Millimeter2iu( 1.5 ) ) );
234  dataStyle->SetTextThickness( Millimeter2iu( 0.1 ) );
235  dataStyle->SetItalic( false );
236  dataStyle->SetTextPos( wxPoint( 0, 0 ) );
237  dataStyle->SetText( "Layer" );
239  dataStyle->SetVertJustify( GR_TEXT_VJUSTIFY_TOP );
240 
241  //Get Layer names
243  BOARD_STACKUP& stackup = dsnSettings.GetStackupDescriptor();
244  stackup.SynchronizeWithBoard( &dsnSettings );
245 
246  std::vector<BOARD_STACKUP_ITEM*> layers = stackup.GetList();
247 
248  std::vector<PCB_TEXT*> colLayer;
249  std::vector<PCB_TEXT*> colType;
250  std::vector<PCB_TEXT*> colMaterial;
251  std::vector<PCB_TEXT*> colThickness;
252  std::vector<PCB_TEXT*> colColor;
253  std::vector<PCB_TEXT*> colEpsilon;
254  std::vector<PCB_TEXT*> colTanD;
255  PCB_TEXT* t;
256 
257  t = static_cast<PCB_TEXT*>( headStyle->Duplicate() );
258  t->SetText( _( "Layer Name" ) );
259  colLayer.push_back( t );
260 
261  t = static_cast<PCB_TEXT*>( headStyle->Duplicate() );
262  t->SetText( _( "Type" ) );
263  colType.push_back( t );
264 
265  t = static_cast<PCB_TEXT*>( headStyle->Duplicate() );
266  t->SetText( _( "Material" ) );
267  colMaterial.push_back( t );
268 
269  t = static_cast<PCB_TEXT*>( headStyle->Duplicate() );
270 
271  switch( m_frame->GetUserUnits() )
272  {
273  case EDA_UNITS::MILLIMETRES: t->SetText( _( "Thickness (mm)" ) ); break;
274  case EDA_UNITS::INCHES: t->SetText( _( "Thickness (inches)" ) ); break;
275  case EDA_UNITS::MILS: t->SetText( _( "Thickness (mils)" ) ); break;
276  default: wxFAIL_MSG( "Unhandled unit type" );
277  }
278 
279  colThickness.push_back( t );
280 
281  t = static_cast<PCB_TEXT*>( headStyle->Duplicate() );
282  t->SetText( _( "Color" ) );
283  colColor.push_back( t );
284 
285  t = static_cast<PCB_TEXT*>( headStyle->Duplicate() );
286  t->SetText( _( "Epsilon R" ) );
287  colEpsilon.push_back( t );
288 
289  t = static_cast<PCB_TEXT*>( headStyle->Duplicate() );
290  t->SetText( _( "Loss Tangent" ) );
291  colTanD.push_back( t );
292 
293  for( int i = 0; i < stackup.GetCount(); i++ )
294  {
295  BOARD_STACKUP_ITEM* stackup_item = layers.at( i );
296 
297  for( int j = 0; j < stackup_item->GetSublayersCount(); j++ )
298  {
299  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
300 
301  // Layer names are empty until we close at least once the board setup dialog.
302  // If the user did not open the dialog, then get the names from the board.
303  // But dielectric layer names will be missing.
304  // In this case, for dielectric, a dummy name will be used
305  if( stackup_item->GetLayerName().IsEmpty() )
306  {
307  wxString ly_name;
308 
309  if( IsValidLayer( stackup_item->GetBrdLayerId() ) )
310  ly_name = m_frame->GetBoard()->GetLayerName( stackup_item->GetBrdLayerId() );
311 
312  if( ly_name.IsEmpty() && stackup_item->GetType() == BS_ITEM_TYPE_DIELECTRIC )
313  ly_name = _( "Dielectric" );
314 
315  t->SetText( ly_name );
316  }
317  else
318  t->SetText( stackup_item->GetLayerName() );
319 
320  colLayer.push_back( t );
321 
322  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
323  t->SetText( stackup_item->GetTypeName() );
324  colType.push_back( t );
325 
326  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
327  t->SetText( stackup_item->GetMaterial( j ) );
328  colMaterial.push_back( t );
329 
330  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
331  t->SetText( StringFromValue( m_frame->GetUserUnits(), stackup_item->GetThickness( j ),
332  true ) );
333  colThickness.push_back( t );
334 
335  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
336  t->SetText( stackup_item->GetColor() );
337  colColor.push_back( t );
338 
339  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
340  t->SetText( StringFromValue( EDA_UNITS::UNSCALED, stackup_item->GetEpsilonR( j ),
341  false ) );
342  colEpsilon.push_back( t );
343 
344  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
346  false ) );
347  colTanD.push_back( t );
348  }
349  }
350 
351  texts.push_back( colLayer );
352  texts.push_back( colType );
353  texts.push_back( colMaterial );
354  texts.push_back( colThickness );
355  texts.push_back( colColor );
356  texts.push_back( colEpsilon );
357  texts.push_back( colTanD );
358  std::vector<BOARD_ITEM*> table = initTextTable( texts, aOrigin, aLayer, tableSize, true );
359 
360  if( aDrawNow )
361  {
362  for( BOARD_ITEM* item : table )
363  commit.Add( item );
364 
365  commit.Push( _( "Insert board stackup table" ) );
366  }
367 
368  return table;
369 }
370 
371 
372 std::vector<BOARD_ITEM*> DRAWING_TOOL::DrawBoardCharacteristics( const wxPoint& aOrigin,
373  PCB_LAYER_ID aLayer,
374  bool aDrawNow,
375  wxPoint* tableSize )
376 {
377  BOARD_COMMIT commit( m_frame );
378  std::vector<BOARD_ITEM*> objects;
380  BOARD_STACKUP& stackup = settings.GetStackupDescriptor();
381 
382  wxPoint cursorPos = aOrigin;
383 
384  // Style : Section header
385  PCB_TEXT* headStyle = new PCB_TEXT( static_cast<FOOTPRINT*>( m_frame->GetModel() ) );
386  headStyle->SetLayer( Eco1_User );
387  headStyle->SetTextSize( wxSize( Millimeter2iu( 2.0 ), Millimeter2iu( 2.0 ) ) );
388  headStyle->SetTextThickness( Millimeter2iu( 0.4 ) );
389  headStyle->SetItalic( false );
390  headStyle->SetTextPos( wxPoint( 0, 0 ) );
392  headStyle->SetVertJustify( GR_TEXT_VJUSTIFY_TOP );
393 
394  // Style : Data
395  PCB_TEXT* dataStyle = new PCB_TEXT( static_cast<FOOTPRINT*>( m_frame->GetModel() ) );
396  dataStyle->SetLayer( Eco1_User );
397  dataStyle->SetTextSize( wxSize( Millimeter2iu( 1.5 ), Millimeter2iu( 1.5 ) ) );
398  dataStyle->SetTextThickness( Millimeter2iu( 0.2 ) );
399  dataStyle->SetItalic( false );
400  dataStyle->SetTextPos( wxPoint( 0, 0 ) );
402  dataStyle->SetVertJustify( GR_TEXT_VJUSTIFY_TOP );
403 
404  PCB_TEXT* t;
405 
406  t = static_cast<PCB_TEXT*>( headStyle->Duplicate() );
407  t->SetText( _( "BOARD CHARACTERISTICS" ) );
408  t->SetPosition( cursorPos );
409  objects.push_back( t );
410 
411  cursorPos.y = cursorPos.y + t->GetBoundingBox().GetHeight()
413 
414  std::vector<std::vector<PCB_TEXT*>> texts;
415  std::vector<PCB_TEXT*> colLabel1;
416  std::vector<PCB_TEXT*> colData1;
417  std::vector<PCB_TEXT*> colbreak;
418  std::vector<PCB_TEXT*> colLabel2;
419  std::vector<PCB_TEXT*> colData2;
420  wxString text = wxString( "" );
421 
422  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
423  t->SetText( _( "Copper Layer Count: " ) );
424  colLabel1.push_back( t );
425 
426  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
428  colData1.push_back( t );
429 
430  EDA_RECT size = m_frame->GetBoard()->ComputeBoundingBox( true );
431  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
432  t->SetText( _( "Board overall dimensions: " ) );
433  colLabel1.push_back( t );
434 
435  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
436  t->SetText( wxString::Format( "%s x %s",
438  MessageTextFromValue( m_frame->GetUserUnits(), size.GetHeight(), true ) ) );
439  colData1.push_back( t );
440 
441  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
442  t->SetText( _( "Min track/spacing: " ) );
443  colLabel1.push_back( t );
444 
445  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
446  t->SetText( wxString::Format( "%s / %s",
448  MessageTextFromValue( m_frame->GetUserUnits(), settings.m_MinClearance, true ) ) );
449  colData1.push_back( t );
450 
451  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
452  t->SetText( _( "Copper Finish: " ) );
453  colLabel1.push_back( t );
454 
455  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
456  t->SetText( stackup.m_FinishType );
457  colData1.push_back( t );
458 
459  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
460  t->SetText( _( "Castellated pads: " ) );
461  colLabel1.push_back( t );
462 
463  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
464  t->SetText( stackup.m_CastellatedPads ? _( "Yes" ) : _( "No" ) );
465  colData1.push_back( t );
466 
467  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
468  t->SetText( _( "Board Thickness: " ) );
469  colLabel2.push_back( t );
470 
471  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
473 
474  t->SetText( text );
475  colData2.push_back( t );
476 
477  // some empty cells
478  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
479  colLabel2.push_back( t );
480  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
481  colData2.push_back( t );
482 
483  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
484  t->SetText( _( "Min hole diameter: " ) );
485  colLabel2.push_back( t );
486  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
487 
488  double holeSize = std::min( settings.m_MinThroughDrill, settings.m_ViasMinSize );
489  text = MessageTextFromValue( m_frame->GetUserUnits(), holeSize, true );
490  t->SetText( text );
491  colData2.push_back( t );
492 
493  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
494  t->SetText( _( "Impedance Control: " ) );
495  colLabel2.push_back( t );
496 
497  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
498  t->SetText( stackup.m_HasDielectricConstrains ? _( "Yes" ) : _( "No" ) );
499  colData2.push_back( t );
500 
501  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
502  t->SetText( _( "Plated Board Edge: " ) );
503  colLabel2.push_back( t );
504 
505  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
506  t->SetText( stackup.m_EdgePlating ? _( "Yes" ) : _( "No" ) );
507  colData2.push_back( t );
508 
509  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
510  t->SetText( _( "Edge card connectors: " ) );
511  colLabel1.push_back( t );
512 
513  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
514  switch( stackup.m_EdgeConnectorConstraints )
515  {
516  case BS_EDGE_CONNECTOR_NONE: t->SetText( _( "No" ) ); break;
517  case BS_EDGE_CONNECTOR_IN_USE: t->SetText( _( "Yes" ) ); break;
518  case BS_EDGE_CONNECTOR_BEVELLED: t->SetText( _( "Yes, Bevelled" ) ); break;
519  }
520  colData1.push_back( t );
521 
522  texts.push_back( colLabel1 );
523  texts.push_back( colData1 );
524  texts.push_back( colbreak );
525  texts.push_back( colLabel2 );
526  texts.push_back( colData2 );
527  wxPoint tableSize2 = wxPoint();
528 
529  std::vector<BOARD_ITEM*> table = initTextTable( texts, cursorPos, Eco1_User, &tableSize2,
530  false );
531 
532  for( BOARD_ITEM* item : table )
533  objects.push_back( item );
534 
535  if( aDrawNow )
536  {
537  for( auto item : objects )
538  commit.Add( item );
539 
540  commit.Push( "Board Characteristics" );
541  }
542 
543  tableSize->x = tableSize2.x;
544  tableSize->y = cursorPos.y + tableSize2.y + From_User_Unit( EDA_UNITS::MILLIMETRES, 2.0 );
545 
546  return objects;
547 }
548 
549 
551  std::vector<BOARD_ITEM*>& aItems,
552  std::vector<BOARD_ITEM*>& aPreview,
553  LSET* aLayers )
554 {
556  return -1;
557 
558  bool cancelled = false;
559 
560  BOARD_COMMIT commit( m_frame );
561 
563 
564  // do not capture or auto-pan until we start placing the table
565  SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::TEXT );
566 
567  std::string tool = aEvent.GetCommandStr().get();
568  m_frame->PushTool( tool );
569 
570  Activate();
571  // Must be done after Activate() so that it gets set into the correct context
572  m_controls->ShowCursor( true );
573 
574  // Prime the pump
575  if( aEvent.HasPosition() )
577 
578  // Main loop: keep receiving events
579  wxPoint wxCursorPosition = wxPoint();
580  wxPoint wxPreviousCursorPosition = wxPoint( 0, 0 );
581 
582  view()->ClearPreview();
583  view()->InitPreview();
584 
585  for( BOARD_ITEM* item : aPreview )
586  {
587  item->Move( wxCursorPosition - wxPreviousCursorPosition );
588  view()->AddToPreview( item );
589  }
590 
591  while( TOOL_EVENT* evt = Wait() )
592  {
595  wxCursorPosition.x = pos.x;
596  wxCursorPosition.y = pos.y;
597 
598  if( evt->IsCancelInteractive() )
599  {
600  m_frame->PopTool( tool );
601  cancelled = true;
602  break;
603  }
604 
605  if( evt->IsMotion() )
606  {
607  view()->ShowPreview( false );
608 
609  for( auto item : aPreview )
610  {
611  item->Move( wxCursorPosition - wxPreviousCursorPosition );
612  }
613 
614  view()->ShowPreview( true );
615 
616  wxPreviousCursorPosition.x = wxCursorPosition.x;
617  wxPreviousCursorPosition.y = wxCursorPosition.y;
618 
619  }
620  else if( evt->IsActivate() )
621  {
622 
623  if( evt->IsMoveTool() )
624  {
625  // leave ourselves on the stack so we come back after the move
626  cancelled = true;
627  break;
628  }
629  else
630  {
631  m_frame->PopTool( tool );
632  cancelled = true;
633  break;
634  }
635  }
636  else if( evt->IsClick( BUT_RIGHT ) )
637  {
639  }
640  else if( evt->IsClick( BUT_LEFT ) )
641  {
642  if( aLayers != nullptr )
643  {
645  *aLayers, wxGetMousePosition() );
646 
647  view()->ClearPreview();
648 
649  if( destLayer == PCB_LAYER_ID::UNDEFINED_LAYER )
650  {
651  // The user did not pick any layer.
652  m_frame->PopTool( tool );
653  cancelled = true;
654  break;
655  }
656 
657  for( BOARD_ITEM* item : aItems )
658  {
659  if( item->Type() == PCB_GROUP_T )
660  static_cast<PCB_GROUP*>( item )->SetLayerRecursive( destLayer, 200 );
661  else
662  item->SetLayer( destLayer );
663  }
664  }
665 
666  for( BOARD_ITEM* item : aItems )
667  {
668  item->Move( wxCursorPosition );
669 
670  if( item->Type() == PCB_GROUP_T )
671  static_cast<PCB_GROUP*>( item )->AddChildrenToCommit( commit );
672 
673  commit.Add( item );
674  }
675 
676  commit.Push( "Placing items" );
677  m_frame->PopTool( tool );
678 
679  break;
680  }
681  else
682  {
683  evt->SetPassEvent();
684  }
685  }
686 
687  view()->ClearPreview();
688  frame()->SetMsgPanel( board() );
689 
690  if( cancelled )
691  return -1;
692 
693  return 0;
694 }
695 
696 
698 {
699  wxPoint tableSize = wxPoint();
700 
701  LSET layerSet = ( layerSet.AllCuMask() | layerSet.AllTechMask() );
702  layerSet = static_cast<LSET>( layerSet.set( Edge_Cuts ).set( Margin ) );
703  layerSet = static_cast<LSET>( layerSet.reset( F_Fab ).reset( B_Fab ) );
704 
706  PCB_LAYER_ID savedLayer = layer;
707 
708  if( ( layerSet & LSET( layer ) ).count() ) // if layer is a forbidden layer
709  {
711  layer = Cmts_User;
712  }
713 
714  std::vector<BOARD_ITEM*> table = DrawBoardCharacteristics( wxPoint( 0, 0 ),
715  m_frame->GetActiveLayer(), false,
716  &tableSize );
717  std::vector<BOARD_ITEM*> preview;
718  std::vector<BOARD_ITEM*> items;
719 
720  PCB_SHAPE* line1 = new PCB_SHAPE;
721  PCB_SHAPE* line2 = new PCB_SHAPE;
722  PCB_SHAPE* line3 = new PCB_SHAPE;
723  PCB_SHAPE* line4 = new PCB_SHAPE;
724 
725  line1->SetStartX( 0 );
726  line1->SetStartY( 0 );
727  line1->SetEndX( tableSize.x );
728  line1->SetEndY( 0 );
729 
730  line2->SetStartX( 0 );
731  line2->SetStartY( 0 );
732  line2->SetEndX( 0 );
733  line2->SetEndY( tableSize.y );
734 
735  line3->SetStartX( tableSize.x );
736  line3->SetStartY( 0 );
737  line3->SetEndX( tableSize.x );
738  line3->SetEndY( tableSize.y );
739 
740  line4->SetStartX( 0 );
741  line4->SetStartY( tableSize.y );
742  line4->SetEndX( tableSize.x );
743  line4->SetEndY( tableSize.y );
744 
745  line1->SetLayer( m_frame->GetActiveLayer() );
746  line2->SetLayer( m_frame->GetActiveLayer() );
747  line3->SetLayer( m_frame->GetActiveLayer() );
748  line4->SetLayer( m_frame->GetActiveLayer() );
749 
750  preview.push_back( line1 );
751  preview.push_back( line2 );
752  preview.push_back( line3 );
753  preview.push_back( line4 );
754 
755  PCB_GROUP* group = new PCB_GROUP( m_board );
756  group->SetName("group-boardCharacteristics");
757 
758  for( auto item : table )
759  group->AddItem( static_cast<BOARD_ITEM*>( item ) );
760 
761  items.push_back( static_cast<BOARD_ITEM*>( group ) );
762 
763  if( InteractivePlaceWithPreview( aEvent, items, preview, &layerSet ) == -1 )
764  m_frame->SetActiveLayer( savedLayer );
765  else
766  m_frame->SetActiveLayer( table.front()->GetLayer() );
767 
768  return 0;
769 }
770 
771 
773 {
774  wxPoint tableSize = wxPoint();
775 
776  LSET layerSet = ( layerSet.AllCuMask() | layerSet.AllTechMask() );
777  layerSet = static_cast<LSET>( layerSet.set( Edge_Cuts ).set( Margin ) );
778  layerSet = static_cast<LSET>( layerSet.reset( F_Fab ).reset( B_Fab ) );
779 
781  PCB_LAYER_ID savedLayer = layer;
782 
783  if( ( layerSet & LSET( layer ) ).count() ) // if layer is a forbidden layer
784  {
786  layer = Cmts_User;
787  }
788 
789  std::vector<BOARD_ITEM*> table = DrawSpecificationStackup(
790  wxPoint( 0, 0 ), m_frame->GetActiveLayer(), false, &tableSize );
791  std::vector<BOARD_ITEM*> preview;
792  std::vector<BOARD_ITEM*> items;
793 
794  PCB_SHAPE* line1 = new PCB_SHAPE;
795  PCB_SHAPE* line2 = new PCB_SHAPE;
796  PCB_SHAPE* line3 = new PCB_SHAPE;
797  PCB_SHAPE* line4 = new PCB_SHAPE;
798 
799  line1->SetStartX( 0 );
800  line1->SetStartY( 0 );
801  line1->SetEndX( tableSize.x );
802  line1->SetEndY( 0 );
803 
804  line2->SetStartX( 0 );
805  line2->SetStartY( 0 );
806  line2->SetEndX( 0 );
807  line2->SetEndY( tableSize.y );
808 
809  line3->SetStartX( tableSize.x );
810  line3->SetStartY( 0 );
811  line3->SetEndX( tableSize.x );
812  line3->SetEndY( tableSize.y );
813 
814  line4->SetStartX( 0 );
815  line4->SetStartY( tableSize.y );
816  line4->SetEndX( tableSize.x );
817  line4->SetEndY( tableSize.y );
818 
819  line1->SetLayer( m_frame->GetActiveLayer() );
820  line2->SetLayer( m_frame->GetActiveLayer() );
821  line3->SetLayer( m_frame->GetActiveLayer() );
822  line4->SetLayer( m_frame->GetActiveLayer() );
823 
824  preview.push_back( line1 );
825  preview.push_back( line2 );
826  preview.push_back( line3 );
827  preview.push_back( line4 );
828 
829  PCB_GROUP* group = new PCB_GROUP( m_board );
830  group->SetName("group-boardStackUp");
831 
832  for( BOARD_ITEM* item : table )
833  group->AddItem( item );
834 
835  items.push_back( static_cast<BOARD_ITEM*>( group ) );
836 
837  if( InteractivePlaceWithPreview( aEvent, items, preview, &layerSet ) == -1 )
838  m_frame->SetActiveLayer( savedLayer );
839  else
840  m_frame->SetActiveLayer( table.front()->GetLayer() );
841 
842  return 0;
843 }
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:59
BOARD_STACKUP_ITEM_TYPE GetType() const
PCB_LAYER_ID SelectOneLayer(PCB_LAYER_ID aDefaultLayer, LSET aNotAllowedLayersMask=LSET(), wxPoint aDlgPosition=wxDefaultPosition)
Show the dialog box for a layer selection.
Definition: sel_layer.cpp:274
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:750
virtual void ShowCursor(bool aEnabled)
Enable or disables display of cursor.
wxString MessageTextFromValue(EDA_UNITS aUnits, int aValue, bool aAddUnitLabel, EDA_DATA_TYPE aType)
Convert a value to a string using double notation.
Definition: base_units.cpp:104
int InteractivePlaceWithPreview(const TOOL_EVENT &aEvent, std::vector< BOARD_ITEM * > &aItems, std::vector< BOARD_ITEM * > &aPreview, LSET *aLayers)
Interactively place a set of BOARD_ITEM.
TOOL_MENU m_menu
The functions below are not yet implemented - their interface may change.
virtual BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Returns the BOARD_DESIGN_SETTINGS for the open project.
void SetCurrentCursor(KICURSOR aCursor)
Set the current cursor shape for this panel.
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:362
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Suspend execution of the tool until an event specified in aEventList arrives.
BOARD * board() const
BOARD * m_board
Definition: drawing_tool.h:268
virtual void SetPosition(const wxPoint &aPos) override
Definition: pcb_text.h:81
Manage layers needed to make a physical board.
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:161
int GetSublayersCount() const
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:49
std::vector< BOARD_ITEM * > DrawBoardCharacteristics(const wxPoint &origin, PCB_LAYER_ID aLayer, bool aDrawNow, wxPoint *tablesize)
class PCB_GROUP, a set of BOARD_ITEMs
Definition: typeinfo.h:108
wxString m_FinishType
The name of external copper finish.
COMMIT & Add(EDA_ITEM *aItem)
Notify observers that aItem has been added.
Definition: commit.h:78
void AddToPreview(EDA_ITEM *aItem, bool aTakeOwnership=true)
Definition: view.cpp:1556
A set of BOARD_ITEMs (i.e., without duplicates).
Definition: pcb_group.h:50
bool m_EdgePlating
True if the edge board is plated.
void SetStartY(int y)
Definition: eda_shape.h:107
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
void SetItalic(bool isItalic)
Definition: eda_text.h:200
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:214
BS_EDGE_CONNECTOR_CONSTRAINTS m_EdgeConnectorConstraints
If the board has edge connector cards, some constrains can be specified in job file: BS_EDGE_CONNECTO...
virtual void PushTool(const std::string &actionName)
NB: the definition of "tool" is different at the user level.
void SetTextPos(const wxPoint &aPoint)
Definition: eda_text.h:267
int GetWidth() const
Definition: eda_rect.h:109
void InitPreview()
Definition: view.cpp:1549
bool m_CastellatedPads
True if castellated pads exist.
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:143
wxString GetColor() const
void SetEndY(int y)
Definition: eda_shape.h:132
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:258
static LSET AllTechMask()
Return a mask holding all technical layers (no CU layer) on both side.
Definition: lset.cpp:820
static std::vector< BOARD_ITEM * > initTextTable(std::vector< std::vector< PCB_TEXT * >> aContent, wxPoint origin, PCB_LAYER_ID aLayer, wxPoint *aTableSize, bool aDrawFrame=true)
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:590
double GetLossTangent(int aDielectricSubLayer=0) const
bool SynchronizeWithBoard(BOARD_DESIGN_SETTINGS *aSettings)
Synchronize the BOARD_STACKUP_ITEM* list with the board.
void ShowPreview(bool aShow=true)
Definition: view.cpp:1570
PCB_BASE_EDIT_FRAME * frame() const
virtual PCB_LAYER_ID GetActiveLayer() const
bool m_HasDielectricConstrains
True if some layers have impedance controlled tracks or have specific constrains for micro-wave appli...
BOARD_STACKUP & GetStackupDescriptor()
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:504
RAII class that sets an value at construction and resets it to the original value at destruction.
const PCB_SELECTION & selection() const
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:124
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
int GetThickness(int aDielectricSubLayer=0) const
virtual void PopTool(const std::string &actionName)
void SetVertJustify(EDA_TEXT_VJUSTIFY_T aType)
Definition: eda_text.h:223
Generic, UI-independent tool event.
Definition: tool_event.h:152
double GetEpsilonR(int aDielectricSubLayer=0) const
void ClearPreview()
Definition: view.cpp:1534
KIGFX::PCB_VIEW * view() const
wxString GetTypeName() const
#define _(s)
int PlaceCharacteristics(const TOOL_EVENT &aEvent)
KIGFX::VIEW_CONTROLS * m_controls
Definition: drawing_tool.h:267
std::vector< BOARD_ITEM * > DrawSpecificationStackup(const wxPoint &origin, PCB_LAYER_ID aLayer, bool aDrawNow, wxPoint *tablesize)
int GetCount() const
virtual void SetActiveLayer(PCB_LAYER_ID aLayer)
bool m_isFootprintEditor
Manage one layer needed to make a physical board.
Definition: board_stackup.h:89
int GetHeight() const
Definition: eda_rect.h:110
const std::vector< BOARD_STACKUP_ITEM * > & GetList() const
PCB_LAYER_ID GetBrdLayerId() const
PCB_BASE_EDIT_FRAME * m_frame
Definition: drawing_tool.h:269
virtual BOARD_ITEM_CONTAINER * GetModel() const =0
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
wxString GetLayerName() const
OPT< std::string > GetCommandStr() const
Definition: tool_event.h:460
void SetEndX(int x)
Definition: eda_shape.h:138
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Definition: eda_text.h:222
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:65
int PlaceStackup(const TOOL_EVENT &aEvent)
Handle the component boundary box.
Definition: eda_rect.h:42
virtual void Push(const wxString &aMessage=wxT("A commit"), bool aCreateUndoEntry=true, bool aSetDirtyBit=true) override
Revert the commit by restoring the modified items state.
EDA_RECT ComputeBoundingBox(bool aBoardEdgesOnly=false) const
Calculate the bounding box containing all board items (or board edge segments).
Definition: board.cpp:1082
wxString StringFromValue(EDA_UNITS aUnits, double aValue, bool aAddUnitSymbol, EDA_DATA_TYPE aType)
Convert a value to a string using double notation.
Definition: base_units.cpp:204
void Activate()
Run the tool.
bool IsValidLayer(LAYER_NUM aLayerId)
Test whether a given integer is a valid layer index, i.e.
Definition: layer_ids.h:774
virtual BOARD_ITEM * Duplicate() const
Create a copy of this BOARD_ITEM.
Definition: board_item.h:169
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.h:180
bool HasPosition() const
Definition: tool_event.h:240
const EDA_RECT GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: pcb_text.cpp:132
BOARD * GetBoard() const
static constexpr int Millimeter2iu(double mm)
void ShowContextMenu(SELECTION &aSelection)
Helper function to set and immediately show a CONDITIONAL_MENU in concert with the given SELECTION.
Definition: tool_menu.cpp:59
wxString GetMaterial(int aDielectricSubLayer=0) const
double From_User_Unit(EDA_UNITS aUnits, double aValue)
Return in internal units the value "val" given in a real unit such as "in", "mm" or "deg".
Definition: base_units.cpp:282
EDA_UNITS GetUserUnits() const
Return the user units currently in use.
VECTOR2D GetCursorPosition() const
Return the current cursor position in world coordinates.
static TOOL_ACTION cursorClick
Definition: actions.h:123
void SetStartX(int x)
Definition: eda_shape.h:113
Container for design settings for a BOARD object.