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 <kicad_string.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( auto col : aContent )
100  {
101  j = 0;
102 
103  if( i >= nbCols )
104  break;
105 
106  for( auto 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( auto col : aContent )
183  {
184  j = 0;
185 
186  if( i >= nbCols )
187  break;
188 
189  pos.y = origin.y + ymargin;
190 
191  for( auto 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(
212  wxPoint aOrigin, PCB_LAYER_ID aLayer, bool aDrawNow, wxPoint* tableSize )
213 {
214  BOARD_COMMIT commit( m_frame );
215  std::vector<std::vector<PCB_TEXT*>> texts;
216 
217  // Style : Header
218  PCB_TEXT* headStyle = new PCB_TEXT( static_cast<FOOTPRINT*>( m_frame->GetModel() ) );
219  headStyle->SetLayer( Eco1_User );
220  headStyle->SetTextSize( wxSize( Millimeter2iu( 1.5 ), Millimeter2iu( 1.5 ) ) );
221  headStyle->SetTextThickness( Millimeter2iu( 0.3 ) );
222  headStyle->SetItalic( false );
223  headStyle->SetTextPos( wxPoint( 0, 0 ) );
224  headStyle->SetText( "Layer" );
226  headStyle->SetVertJustify( GR_TEXT_VJUSTIFY_TOP );
227 
228  // Style : data
229  PCB_TEXT* dataStyle = new PCB_TEXT( static_cast<FOOTPRINT*>( m_frame->GetModel() ) );
230  dataStyle->SetLayer( Eco1_User );
231  dataStyle->SetTextSize( wxSize( Millimeter2iu( 1.5 ), Millimeter2iu( 1.5 ) ) );
232  dataStyle->SetTextThickness( Millimeter2iu( 0.1 ) );
233  dataStyle->SetItalic( false );
234  dataStyle->SetTextPos( wxPoint( 0, 0 ) );
235  dataStyle->SetText( "Layer" );
237  dataStyle->SetVertJustify( GR_TEXT_VJUSTIFY_TOP );
238 
239  //Get Layer names
241  BOARD_STACKUP& stackup = dsnSettings.GetStackupDescriptor();
242  stackup.SynchronizeWithBoard( &dsnSettings );
243 
244  std::vector<BOARD_STACKUP_ITEM*> layers = stackup.GetList();
245 
246  std::vector<PCB_TEXT*> colLayer;
247  std::vector<PCB_TEXT*> colType;
248  std::vector<PCB_TEXT*> colMaterial;
249  std::vector<PCB_TEXT*> colThickness;
250  std::vector<PCB_TEXT*> colColor;
251  std::vector<PCB_TEXT*> colEpsilon;
252  std::vector<PCB_TEXT*> colTanD;
253  PCB_TEXT* t;
254 
255  t = static_cast<PCB_TEXT*>( headStyle->Duplicate() );
256  t->SetText( _( "Layer Name" ) );
257  colLayer.push_back( t );
258 
259  t = static_cast<PCB_TEXT*>( headStyle->Duplicate() );
260  t->SetText( _( "Type" ) );
261  colType.push_back( t );
262 
263  t = static_cast<PCB_TEXT*>( headStyle->Duplicate() );
264  t->SetText( _( "Material" ) );
265  colMaterial.push_back( t );
266 
267  t = static_cast<PCB_TEXT*>( headStyle->Duplicate() );
268 
270  t->SetText( _( "Thickness (mm)" ) );
271 
272  else if( m_frame->GetUserUnits() == EDA_UNITS::INCHES )
273  t->SetText( _( "Thickness (mils)" ) );
274 
275  colThickness.push_back( t );
276 
277  t = static_cast<PCB_TEXT*>( headStyle->Duplicate() );
278  t->SetText( _( "Color" ) );
279  colColor.push_back( t );
280 
281  t = static_cast<PCB_TEXT*>( headStyle->Duplicate() );
282  t->SetText( _( "Epsilon R" ) );
283  colEpsilon.push_back( t );
284 
285  t = static_cast<PCB_TEXT*>( headStyle->Duplicate() );
286  t->SetText( _( "Loss Tangent" ) );
287  colTanD.push_back( t );
288 
289  int i, j;
290 
291  for( i = 0; i < stackup.GetCount(); i++ )
292  {
293  for( j = 0; j < layers.at( i )->GetSublayersCount(); j++ )
294  {
295  // Layer names are empty until we close at least once the board setup dialog.
296  // If the user did not open the dialog, then get the names from the board.
297  // But dielectric layer names will be missing.
298  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
299  if( layers.at( i )->GetLayerName().IsEmpty() )
300  {
301  t->SetText( m_frame->GetBoard()->GetLayerName( layers.at( i )->GetBrdLayerId() ) );
302  }
303  else
304  {
305  t->SetText( layers.at( i )->GetLayerName() );
306  }
307  colLayer.push_back( t );
308 
309  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
310  t->SetText( layers.at( i )->GetTypeName() );
311  colType.push_back( t );
312 
313  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
314  t->SetText( layers.at( i )->GetMaterial( j ) );
315  colMaterial.push_back( t );
316 
317  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
318  t->SetText( StringFromValue( m_frame->GetUserUnits(), layers.at( i )->GetThickness( j ),
319  true ) );
320  colThickness.push_back( t );
321 
322  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
323  t->SetText( layers.at( i )->GetColor() );
324  colColor.push_back( t );
325 
326  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
327  t->SetText( StringFromValue( EDA_UNITS::UNSCALED, layers.at( i )->GetEpsilonR( j ),
328  false ) );
329  colEpsilon.push_back( t );
330 
331  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
332  t->SetText( StringFromValue( EDA_UNITS::UNSCALED, layers.at( i )->GetLossTangent( j ),
333  false ) );
334  colTanD.push_back( t );
335  }
336  }
337 
338  texts.push_back( colLayer );
339  texts.push_back( colType );
340  texts.push_back( colMaterial );
341  texts.push_back( colThickness );
342  texts.push_back( colColor );
343  texts.push_back( colEpsilon );
344  texts.push_back( colTanD );
345  std::vector<BOARD_ITEM*> table =
346  initTextTable( texts, aOrigin, aLayer, tableSize, true );
347 
348  if( aDrawNow )
349  {
350 
351  for( auto item : table )
352  commit.Add( item );
353 
354  commit.Push( _( "Insert board stackup table" ) );
355  }
356 
357  return table;
358 }
359 
360 
361 std::vector<BOARD_ITEM*> DRAWING_TOOL::DrawBoardCharacteristics(
362  wxPoint aOrigin, PCB_LAYER_ID aLayer, bool aDrawNow, wxPoint* tableSize )
363 {
364  BOARD_COMMIT commit( m_frame );
365  std::vector<BOARD_ITEM*> objects;
367  BOARD_STACKUP& stackup = settings.GetStackupDescriptor();
368 
369  wxPoint cursorPos = aOrigin;
370 
371  // Style : Section header
372  PCB_TEXT* headStyle = new PCB_TEXT( static_cast<FOOTPRINT*>( m_frame->GetModel() ) );
373  headStyle->SetLayer( Eco1_User );
374  headStyle->SetTextSize( wxSize( Millimeter2iu( 2.0 ), Millimeter2iu( 2.0 ) ) );
375  headStyle->SetTextThickness( Millimeter2iu( 0.4 ) );
376  headStyle->SetItalic( false );
377  headStyle->SetTextPos( wxPoint( 0, 0 ) );
379  headStyle->SetVertJustify( GR_TEXT_VJUSTIFY_TOP );
380 
381  // Style : Data
382  PCB_TEXT* dataStyle = new PCB_TEXT( static_cast<FOOTPRINT*>( m_frame->GetModel() ) );
383  dataStyle->SetLayer( Eco1_User );
384  dataStyle->SetTextSize( wxSize( Millimeter2iu( 1.5 ), Millimeter2iu( 1.5 ) ) );
385  dataStyle->SetTextThickness( Millimeter2iu( 0.2 ) );
386  dataStyle->SetItalic( false );
387  dataStyle->SetTextPos( wxPoint( 0, 0 ) );
389  dataStyle->SetVertJustify( GR_TEXT_VJUSTIFY_TOP );
390 
391  PCB_TEXT* t;
392 
393  t = static_cast<PCB_TEXT*>( headStyle->Duplicate() );
394  t->SetText( _( "BOARD CHARACTERISTICS" ) );
395  t->SetPosition( cursorPos );
396  objects.push_back( t );
397 
398  cursorPos.y = cursorPos.y + t->GetBoundingBox().GetHeight()
400 
401  std::vector<std::vector<PCB_TEXT*>> texts;
402  std::vector<PCB_TEXT*> colLabel1;
403  std::vector<PCB_TEXT*> colData1;
404  std::vector<PCB_TEXT*> colbreak;
405  std::vector<PCB_TEXT*> colLabel2;
406  std::vector<PCB_TEXT*> colData2;
407  wxString text = wxString( "" );
408 
409  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
410  t->SetText( _( "Copper Layer Count: " ) );
411  colLabel1.push_back( t );
412 
413  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
415  colData1.push_back( t );
416 
417  EDA_RECT size = m_frame->GetBoard()->ComputeBoundingBox( true );
418  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
419  t->SetText( _( "Board overall dimensions: " ) );
420  colLabel1.push_back( t );
421 
422  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
423  t->SetText( wxString::Format( "%s x %s",
425  MessageTextFromValue( m_frame->GetUserUnits(), size.GetHeight(), true ) ) );
426  colData1.push_back( t );
427 
428  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
429  t->SetText( _( "Min track/spacing: " ) );
430  colLabel1.push_back( t );
431 
432  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
433  t->SetText( wxString::Format( "%s / %s",
435  MessageTextFromValue( m_frame->GetUserUnits(), settings.m_MinClearance, true ) ) );
436  colData1.push_back( t );
437 
438  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
439  t->SetText( _( "Copper Finish: " ) );
440  colLabel1.push_back( t );
441 
442  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
443  t->SetText( stackup.m_FinishType );
444  colData1.push_back( t );
445 
446  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
447  t->SetText( _( "Castellated pads: " ) );
448  colLabel1.push_back( t );
449 
450  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
451  t->SetText( stackup.m_CastellatedPads ? _( "Yes" ) : _( "No" ) );
452  colData1.push_back( t );
453 
454  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
455  t->SetText( _( "Board Thickness: " ) );
456  colLabel2.push_back( t );
457 
458  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
460 
461  t->SetText( text );
462  colData2.push_back( t );
463 
464  // some empty cells
465  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
466  colLabel2.push_back( t );
467  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
468  colData2.push_back( t );
469 
470  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
471  t->SetText( _( "Min hole diameter: " ) );
472  colLabel2.push_back( t );
473  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
474 
475  double holeSize = std::min( settings.m_MinThroughDrill, settings.m_ViasMinSize );
476  text = MessageTextFromValue( m_frame->GetUserUnits(), holeSize, true );
477  t->SetText( text );
478  colData2.push_back( t );
479 
480  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
481  t->SetText( _( "Impedance Control: " ) );
482  colLabel2.push_back( t );
483 
484  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
485  t->SetText( stackup.m_CastellatedPads ? _( "Yes" ) : _( "No" ) );
486  colData2.push_back( t );
487 
488  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
489  t->SetText( _( "Plated Board Edge: " ) );
490  colLabel2.push_back( t );
491  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
492  t->SetText( stackup.m_HasDielectricConstrains ? _( "Yes" ) : _( "No" ) );
493  colData2.push_back( t );
494 
495  texts.push_back( colLabel1 );
496  texts.push_back( colData1 );
497  texts.push_back( colbreak );
498  texts.push_back( colLabel2 );
499  texts.push_back( colData2 );
500  wxPoint tableSize2 = wxPoint();
501 
502  std::vector<BOARD_ITEM*> table = initTextTable( texts, cursorPos, Eco1_User, &tableSize2,
503  false );
504 
505  for( auto item : table )
506  objects.push_back( item );
507 
508  if( aDrawNow )
509  {
510  for( auto item : objects )
511  commit.Add( item );
512 
513  commit.Push( "Board Characteristics" );
514  }
515 
516  tableSize->x = tableSize2.x;
517  tableSize->y = cursorPos.y + tableSize2.y + From_User_Unit( EDA_UNITS::MILLIMETRES, 2.0 );
518 
519  return objects;
520 }
521 
522 
524  std::vector<BOARD_ITEM*>& aItems,
525  std::vector<BOARD_ITEM*>& aPreview,
526  LSET* aLayers )
527 {
529  return -1;
530 
531  bool cancelled = false;
532 
533  BOARD_COMMIT commit( m_frame );
534 
536  m_controls->ShowCursor( true );
537 
538  // do not capture or auto-pan until we start placing the table
539  SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::TEXT );
540 
541  std::string tool = aEvent.GetCommandStr().get();
542  m_frame->PushTool( tool );
543  Activate();
544 
545  // Prime the pump
546  if( aEvent.HasPosition() )
548 
549  // Main loop: keep receiving events
550  wxPoint wxCursorPosition = wxPoint();
551  wxPoint wxPreviousCursorPosition = wxPoint( 0, 0 );
552 
553  view()->ClearPreview();
554  view()->InitPreview();
555 
556  for( auto item : aPreview )
557  {
558  item->Move( wxCursorPosition - wxPreviousCursorPosition );
559  view()->AddToPreview( item );
560  }
561 
562  while( TOOL_EVENT* evt = Wait() )
563  {
566  wxCursorPosition.x = pos.x;
567  wxCursorPosition.y = pos.y;
568 
569  if( evt->IsCancelInteractive() )
570  {
571  m_frame->PopTool( tool );
572  cancelled = true;
573  break;
574  }
575 
576  if( evt->IsMotion() )
577  {
578  view()->ShowPreview( false );
579 
580  for( auto item : aPreview )
581  {
582  item->Move( wxCursorPosition - wxPreviousCursorPosition );
583  }
584 
585  view()->ShowPreview( true );
586 
587  wxPreviousCursorPosition.x = wxCursorPosition.x;
588  wxPreviousCursorPosition.y = wxCursorPosition.y;
589 
590  }
591  else if( evt->IsActivate() )
592  {
593 
594  if( evt->IsMoveTool() )
595  {
596  // leave ourselves on the stack so we come back after the move
597  cancelled = true;
598  break;
599  }
600  else
601  {
602  m_frame->PopTool( tool );
603  cancelled = true;
604  break;
605  }
606  }
607  else if( evt->IsClick( BUT_RIGHT ) )
608  {
610  }
611  else if( evt->IsClick( BUT_LEFT ) )
612  {
613  if( aLayers != nullptr )
614  {
615  PCB_LAYER_ID targetLayer = frame()->SelectOneLayer(
617  *aLayers, wxGetMousePosition() );
618 
619  view()->ClearPreview();
620 
621  if( targetLayer == PCB_LAYER_ID::UNDEFINED_LAYER )
622  {
623  // The user did not pick any layer.
624  m_frame->PopTool( tool );
625  cancelled = true;
626  break;
627  }
628 
629  for( auto item : aItems )
630  {
631  if( item->Type() == PCB_GROUP_T )
632  {
633  static_cast<PCB_GROUP*>( item )->SetLayerRecursive( targetLayer, 200 );
634  }
635  else
636  {
637  item->SetLayer( targetLayer );
638  }
639  }
640  }
641 
642  for( auto item : aItems )
643  {
644  item->Move( wxCursorPosition );
645 
646  if( item->Type() == PCB_GROUP_T )
647  {
648  static_cast<PCB_GROUP*>( item )->AddChildrenToCommit( commit );
649  }
650 
651  commit.Add( item );
652  }
653 
654  commit.Push( "Placing items" );
655  m_frame->PopTool( tool );
656 
657  break;
658  }
659  else
660  {
661  evt->SetPassEvent();
662  }
663  }
664 
665  view()->ClearPreview();
666  frame()->SetMsgPanel( board() );
667 
668  if( cancelled )
669  return -1;
670 
671  return 0;
672 }
673 
675 {
676  wxPoint tableSize = wxPoint();
677 
678  LSET layerSet = ( layerSet.AllCuMask() | layerSet.AllTechMask() );
679  layerSet = static_cast<LSET>( layerSet.set( Edge_Cuts ).set( Margin ) );
680  layerSet = static_cast<LSET>( layerSet.reset( F_Fab ).reset( B_Fab ) );
681 
683  PCB_LAYER_ID savedLayer = layer;
684 
685  if( ( layerSet & LSET( layer ) ).count() ) // if layer is a forbidden layer
686  {
688  layer = Cmts_User;
689  }
690 
691  std::vector<BOARD_ITEM*> table = DrawBoardCharacteristics(
692  wxPoint( 0, 0 ), m_frame->GetActiveLayer(), false, &tableSize );
693  std::vector<BOARD_ITEM*> preview;
694  std::vector<BOARD_ITEM*> items;
695 
696  PCB_SHAPE* line1 = new PCB_SHAPE;
697  PCB_SHAPE* line2 = new PCB_SHAPE;
698  PCB_SHAPE* line3 = new PCB_SHAPE;
699  PCB_SHAPE* line4 = new PCB_SHAPE;
700 
701  line1->SetStartX( 0 );
702  line1->SetStartY( 0 );
703  line1->SetEndX( tableSize.x );
704  line1->SetEndY( 0 );
705 
706  line2->SetStartX( 0 );
707  line2->SetStartY( 0 );
708  line2->SetEndX( 0 );
709  line2->SetEndY( tableSize.y );
710 
711  line3->SetStartX( tableSize.x );
712  line3->SetStartY( 0 );
713  line3->SetEndX( tableSize.x );
714  line3->SetEndY( tableSize.y );
715 
716  line4->SetStartX( 0 );
717  line4->SetStartY( tableSize.y );
718  line4->SetEndX( tableSize.x );
719  line4->SetEndY( tableSize.y );
720 
721  line1->SetLayer( m_frame->GetActiveLayer() );
722  line2->SetLayer( m_frame->GetActiveLayer() );
723  line3->SetLayer( m_frame->GetActiveLayer() );
724  line4->SetLayer( m_frame->GetActiveLayer() );
725 
726  preview.push_back( line1 );
727  preview.push_back( line2 );
728  preview.push_back( line3 );
729  preview.push_back( line4 );
730 
731  PCB_GROUP* group = new PCB_GROUP( m_board );
732  group->SetName("group-boardCharacteristics");
733 
734  for( auto item : table )
735  group->AddItem( static_cast<BOARD_ITEM*>( item ) );
736 
737  items.push_back( static_cast<BOARD_ITEM*>( group ) );
738 
739  if( InteractivePlaceWithPreview( aEvent, items, preview, &layerSet ) == -1 )
740  m_frame->SetActiveLayer( savedLayer );
741  else
742  m_frame->SetActiveLayer( table.front()->GetLayer() );
743 
744  return 0;
745 }
746 
748 {
749  wxPoint tableSize = wxPoint();
750 
751  LSET layerSet = ( layerSet.AllCuMask() | layerSet.AllTechMask() );
752  layerSet = static_cast<LSET>( layerSet.set( Edge_Cuts ).set( Margin ) );
753  layerSet = static_cast<LSET>( layerSet.reset( F_Fab ).reset( B_Fab ) );
754 
756  PCB_LAYER_ID savedLayer = layer;
757 
758  if( ( layerSet & LSET( layer ) ).count() ) // if layer is a forbidden layer
759  {
761  layer = Cmts_User;
762  }
763 
764  std::vector<BOARD_ITEM*> table = DrawSpecificationStackup(
765  wxPoint( 0, 0 ), m_frame->GetActiveLayer(), false, &tableSize );
766  std::vector<BOARD_ITEM*> preview;
767  std::vector<BOARD_ITEM*> items;
768 
769  PCB_SHAPE* line1 = new PCB_SHAPE;
770  PCB_SHAPE* line2 = new PCB_SHAPE;
771  PCB_SHAPE* line3 = new PCB_SHAPE;
772  PCB_SHAPE* line4 = new PCB_SHAPE;
773 
774  line1->SetStartX( 0 );
775  line1->SetStartY( 0 );
776  line1->SetEndX( tableSize.x );
777  line1->SetEndY( 0 );
778 
779  line2->SetStartX( 0 );
780  line2->SetStartY( 0 );
781  line2->SetEndX( 0 );
782  line2->SetEndY( tableSize.y );
783 
784  line3->SetStartX( tableSize.x );
785  line3->SetStartY( 0 );
786  line3->SetEndX( tableSize.x );
787  line3->SetEndY( tableSize.y );
788 
789  line4->SetStartX( 0 );
790  line4->SetStartY( tableSize.y );
791  line4->SetEndX( tableSize.x );
792  line4->SetEndY( tableSize.y );
793 
794  line1->SetLayer( m_frame->GetActiveLayer() );
795  line2->SetLayer( m_frame->GetActiveLayer() );
796  line3->SetLayer( m_frame->GetActiveLayer() );
797  line4->SetLayer( m_frame->GetActiveLayer() );
798 
799  preview.push_back( line1 );
800  preview.push_back( line2 );
801  preview.push_back( line3 );
802  preview.push_back( line4 );
803 
804  PCB_GROUP* group = new PCB_GROUP( m_board );
805  group->SetName("group-boardStackUp");
806 
807  for( auto item : table )
808  group->AddItem( item );
809 
810  items.push_back( static_cast<BOARD_ITEM*>( group ) );
811 
812  if( InteractivePlaceWithPreview( aEvent, items, preview, &layerSet ) == -1 )
813  m_frame->SetActiveLayer( savedLayer );
814  else
815  m_frame->SetActiveLayer( table.front()->GetLayer() );
816 
817  return 0;
818 }
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:59
void SetStartX(int x)
Definition: pcb_shape.h:129
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:231
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:360
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:269
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:192
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:1547
A set of BOARD_ITEMs (i.e., without duplicates).
Definition: pcb_group.h:50
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:179
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:214
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:246
int GetWidth() const
Definition: eda_rect.h:109
void InitPreview()
Definition: view.cpp:1540
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
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:237
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:588
bool SynchronizeWithBoard(BOARD_DESIGN_SETTINGS *aSettings)
Synchronize the BOARD_STACKUP_ITEM* list with the board.
void ShowPreview(bool aShow=true)
Definition: view.cpp:1561
PCB_BASE_EDIT_FRAME * frame() const
std::vector< BOARD_ITEM * > DrawSpecificationStackup(wxPoint origin, PCB_LAYER_ID aLayer, bool aDrawNow, wxPoint *tablesize)
Function DrawSpecificationStackup()
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()
PCB_LAYER_ID
A quick note on layer IDs:
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 PCB_SELECTION & selection() const
std::vector< BOARD_ITEM * > DrawBoardCharacteristics(wxPoint origin, PCB_LAYER_ID aLayer, bool aDrawNow, wxPoint *tablesize)
Function DrawBoardCharacteristics()
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:114
void SetEndY(int y)
Definition: pcb_shape.h:138
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
virtual void PopTool(const std::string &actionName)
void SetVertJustify(EDA_TEXT_VJUSTIFY_T aType)
Definition: eda_text.h:202
Generic, UI-independent tool event.
Definition: tool_event.h:152
void ClearPreview()
Definition: view.cpp:1525
KIGFX::PCB_VIEW * view() const
#define _(s)
int PlaceCharacteristics(const TOOL_EVENT &aEvent)
Function PlaceCharacteristics()
KIGFX::VIEW_CONTROLS * m_controls
Definition: drawing_tool.h:268
int GetCount() const
virtual void SetActiveLayer(PCB_LAYER_ID aLayer)
bool m_isFootprintEditor
void SetEndX(int x)
Definition: pcb_shape.h:139
int GetHeight() const
Definition: eda_rect.h:110
const std::vector< BOARD_STACKUP_ITEM * > & GetList() const
PCB_BASE_EDIT_FRAME * m_frame
Definition: drawing_tool.h:270
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
OPT< std::string > GetCommandStr() const
Definition: tool_event.h:455
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Definition: eda_text.h:201
int PlaceStackup(const TOOL_EVENT &aEvent)
Function PlaceStackup()
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:1104
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.
void SetStartY(int y)
Definition: pcb_shape.h:128
virtual BOARD_ITEM * Duplicate() const
Create a copy of this BOARD_ITEM.
Definition: board_item.h:200
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.h:159
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
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
Container for design settings for a BOARD object.