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 <fp_shape.h>
39 #include <pcb_text.h>
40 #include <kicad_string.h>
41 #include <wx/utils.h>
42 
43 
45 
46 static std::vector<BOARD_ITEM*> initTextTable( std::vector<std::vector<PCB_TEXT*>> aContent,
47  wxPoint origin, PCB_LAYER_ID aLayer, wxPoint* aTableSize,
48  bool aDrawFrame = true )
49 {
50  int i;
51  int j;
52 
53  int nbCols = aContent.size();
54  int nbRows = 0;
55 
56  for( auto col : aContent )
57  nbRows = std::max( nbRows, static_cast<int>( col.size() ) );
58 
59  // Limit the number of cells
60  nbCols = std::min( nbCols, 99 );
61  nbRows = std::min( nbRows, 99 );
62 
63  int rowHeight[99];
64  int colWidth[99];
65 
66  std::vector<BOARD_ITEM*> table;
67 
68  // xmargin and ymargin are margins between the text and the the table lines.
69  //
70  // +--------------------------------+
71  // | ^ |
72  // | | ymargin |
73  // | v |
74  // |<------->TEXT_TEXT_TEXT<------->|
75  // | xmargin ^ xmargin |
76  // | | ymargin |
77  // | v |
78  // +--------------------------------+
79  //
80 
81  int xmargin = Millimeter2iu( 0.75 );
82  int ymargin = Millimeter2iu( 0.75 );
83 
84  // Init table
85  for( i = 0; i < nbRows; i++ )
86  rowHeight[i] = 0;
87 
88  for( i = 0; i < nbCols; i++ )
89  colWidth[i] = 0;
90 
91  // First, we determine what the height/Width should be for every cell
92  i = 0;
93 
94  for( auto col : aContent )
95  {
96  j = 0;
97 
98  if( i >= nbCols )
99  break;
100 
101  for( auto cell : col )
102  {
103 
104  if( j >= nbRows )
105  break;
106 
107  int height = cell->GetBoundingBox().GetHeight() + 2 * ymargin;
108  int width = cell->GetBoundingBox().GetWidth() + 2 * xmargin;
109  rowHeight[j] = rowHeight[j] > height ? rowHeight[j] : height;
110  colWidth[i] = colWidth[i] > width ? colWidth[i] : width;
111  j++;
112 
113  }
114 
115  i++;
116  }
117 
118  // get table size
119  int height = std::accumulate( rowHeight, rowHeight + nbRows, 0 );
120  int width = std::accumulate( colWidth, colWidth + nbCols, 0 );
121 
122  aTableSize->x = width;
123  aTableSize->y = height;
124  // Draw the frame
125 
126  if( aDrawFrame )
127  {
128  int y = origin.y;
129  PCB_SHAPE* line;
130 
131  for( i = 0; i < nbRows; i++ )
132  {
133  line = new PCB_SHAPE;
134  line->SetLayer( aLayer );
135  line->SetStartX( origin.x );
136  line->SetStartY( y );
137  line->SetEndX( origin.x + width );
138  line->SetEndY( y );
139  y += rowHeight[i];
140  table.push_back( line );
141  }
142 
143  line = new PCB_SHAPE;
144  line->SetLayer( aLayer );
145  line->SetStartX( origin.x );
146  line->SetStartY( y );
147  line->SetEndX( origin.x + width );
148  line->SetEndY( y );
149  table.push_back( line );
150  int x = origin.x;
151 
152  for( i = 0; i < nbCols; i++ )
153  {
154  line = new PCB_SHAPE;
155  line->SetLayer( aLayer );
156  line->SetStartX( x );
157  line->SetStartY( origin.y );
158  line->SetEndX( x );
159  line->SetEndY( origin.y + height );
160  x += colWidth[i];
161  table.push_back( line );
162  }
163 
164  line = new PCB_SHAPE;
165  line->SetLayer( aLayer );
166  line->SetStartX( x );
167  line->SetStartY( origin.y );
168  line->SetEndX( x );
169  line->SetEndY( origin.y + height );
170  table.push_back( line );
171  }
172  //Now add the text
173  i = 0;
174  wxPoint pos = wxPoint( origin.x + xmargin, origin.y + ymargin );
175 
176  for( auto col : aContent )
177  {
178  j = 0;
179 
180  if( i >= nbCols )
181  break;
182 
183  pos.y = origin.y + ymargin;
184 
185  for( auto cell : col )
186  {
187 
188  if( j >= nbRows )
189  break;
190 
191  cell->SetTextPos( pos );
192  cell->SetLayer( aLayer );
193  pos.y = pos.y + rowHeight[j];
194  table.push_back( cell );
195  j++;
196  }
197 
198  pos.x = pos.x + colWidth[i];
199  i++;
200  }
201  return table;
202 }
203 
204 
205 std::vector<BOARD_ITEM*> DRAWING_TOOL::DrawSpecificationStackup(
206  wxPoint aOrigin, PCB_LAYER_ID aLayer, bool aDrawNow, wxPoint* tableSize )
207 {
208  BOARD_COMMIT commit( m_frame );
209  std::vector<std::vector<PCB_TEXT*>> texts;
210 
211  // Style : Header
212  PCB_TEXT* headStyle = new PCB_TEXT( static_cast<FOOTPRINT*>( m_frame->GetModel() ) );
213  headStyle->SetLayer( Eco1_User );
214  headStyle->SetTextSize( wxSize( Millimeter2iu( 1.5 ), Millimeter2iu( 1.5 ) ) );
215  headStyle->SetTextThickness( Millimeter2iu( 0.3 ) );
216  headStyle->SetItalic( false );
217  headStyle->SetTextPos( wxPoint( 0, 0 ) );
218  headStyle->SetText( "Layer" );
220  headStyle->SetVertJustify( GR_TEXT_VJUSTIFY_TOP );
221 
222  // Style : data
223  PCB_TEXT* dataStyle = new PCB_TEXT( static_cast<FOOTPRINT*>( m_frame->GetModel() ) );
224  dataStyle->SetLayer( Eco1_User );
225  dataStyle->SetTextSize( wxSize( Millimeter2iu( 1.5 ), Millimeter2iu( 1.5 ) ) );
226  dataStyle->SetTextThickness( Millimeter2iu( 0.1 ) );
227  dataStyle->SetItalic( false );
228  dataStyle->SetTextPos( wxPoint( 0, 0 ) );
229  dataStyle->SetText( "Layer" );
231  dataStyle->SetVertJustify( GR_TEXT_VJUSTIFY_TOP );
232 
233  //Get Layer names
235  BOARD_STACKUP& stackup = dsnSettings.GetStackupDescriptor();
236  std::vector<BOARD_STACKUP_ITEM*> layers = stackup.GetList();
237 
238  std::vector<PCB_TEXT*> colLayer;
239  std::vector<PCB_TEXT*> colType;
240  std::vector<PCB_TEXT*> colMaterial;
241  std::vector<PCB_TEXT*> colThickness;
242  std::vector<PCB_TEXT*> colColor;
243  std::vector<PCB_TEXT*> colEpsilon;
244  std::vector<PCB_TEXT*> colTanD;
245  PCB_TEXT* t;
246 
247  t = static_cast<PCB_TEXT*>( headStyle->Duplicate() );
248  t->SetText( _( "Layer Name" ) );
249  colLayer.push_back( t );
250 
251  t = static_cast<PCB_TEXT*>( headStyle->Duplicate() );
252  t->SetText( _( "Type" ) );
253  colType.push_back( t );
254 
255  t = static_cast<PCB_TEXT*>( headStyle->Duplicate() );
256  t->SetText( _( "Material" ) );
257  colMaterial.push_back( t );
258 
259  t = static_cast<PCB_TEXT*>( headStyle->Duplicate() );
260 
262  t->SetText( _( "Thickness (mm)" ) );
263 
264  else if( m_frame->GetUserUnits() == EDA_UNITS::INCHES )
265  t->SetText( _( "Thickness (mils)" ) );
266 
267  colThickness.push_back( t );
268 
269  t = static_cast<PCB_TEXT*>( headStyle->Duplicate() );
270  t->SetText( _( "Color" ) );
271  colColor.push_back( t );
272 
273  t = static_cast<PCB_TEXT*>( headStyle->Duplicate() );
274  t->SetText( _( "Epsilon R" ) );
275  colEpsilon.push_back( t );
276 
277  t = static_cast<PCB_TEXT*>( headStyle->Duplicate() );
278  t->SetText( _( "Loss Tangent" ) );
279  colTanD.push_back( t );
280 
281  int i;
282 
283  for( i = 0; i < stackup.GetCount(); i++ )
284  {
285  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
286  t->SetText( layers.at( i )->GetLayerName() );
287  colLayer.push_back( t );
288 
289  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
290  t->SetText( layers.at( i )->GetTypeName() );
291  colType.push_back( t );
292 
293  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
294  t->SetText( layers.at( i )->GetMaterial() );
295  colMaterial.push_back( t );
296 
297  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
298  t->SetText(
299  StringFromValue( m_frame->GetUserUnits(), layers.at( i )->GetThickness(), true ) );
300  colThickness.push_back( t );
301 
302  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
303  t->SetText( layers.at( i )->GetColor() );
304  colColor.push_back( t );
305 
306  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
307  t->SetText( StringFromValue( EDA_UNITS::UNSCALED, layers.at( i )->GetEpsilonR(), false ) );
308  colEpsilon.push_back( t );
309 
310  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
311  t->SetText(
312  StringFromValue( EDA_UNITS::UNSCALED, layers.at( i )->GetLossTangent(), false ) );
313  colTanD.push_back( t );
314  }
315 
316  texts.push_back( colLayer );
317  texts.push_back( colType );
318  texts.push_back( colMaterial );
319  texts.push_back( colThickness );
320  texts.push_back( colColor );
321  texts.push_back( colEpsilon );
322  texts.push_back( colTanD );
323  std::vector<BOARD_ITEM*> table =
324  initTextTable( texts, aOrigin, aLayer, tableSize, true );
325 
326  if( aDrawNow )
327  {
328 
329  for( auto item : table )
330  commit.Add( item );
331 
332  commit.Push( _( "Insert board stackup table" ) );
333  }
334 
335  return table;
336 }
337 
338 std::vector<BOARD_ITEM*> DRAWING_TOOL::DrawBoardCharacteristics(
339  wxPoint aOrigin, PCB_LAYER_ID aLayer, bool aDrawNow, wxPoint* tableSize )
340 {
341  BOARD_COMMIT commit( m_frame );
342  std::vector<BOARD_ITEM*> objects;
344  BOARD_STACKUP& stackup = settings.GetStackupDescriptor();
345 
346  wxPoint cursorPos = aOrigin;
347 
348  // Style : Section header
349  PCB_TEXT* headStyle = new PCB_TEXT( static_cast<FOOTPRINT*>( m_frame->GetModel() ) );
350  headStyle->SetLayer( Eco1_User );
351  headStyle->SetTextSize( wxSize( Millimeter2iu( 2.0 ), Millimeter2iu( 2.0 ) ) );
352  headStyle->SetTextThickness( Millimeter2iu( 0.4 ) );
353  headStyle->SetItalic( false );
354  headStyle->SetTextPos( wxPoint( 0, 0 ) );
356  headStyle->SetVertJustify( GR_TEXT_VJUSTIFY_TOP );
357 
358  // Style : Data
359  PCB_TEXT* dataStyle = new PCB_TEXT( static_cast<FOOTPRINT*>( m_frame->GetModel() ) );
360  dataStyle->SetLayer( Eco1_User );
361  dataStyle->SetTextSize( wxSize( Millimeter2iu( 1.5 ), Millimeter2iu( 1.5 ) ) );
362  dataStyle->SetTextThickness( Millimeter2iu( 0.2 ) );
363  dataStyle->SetItalic( false );
364  dataStyle->SetTextPos( wxPoint( 0, 0 ) );
366  dataStyle->SetVertJustify( GR_TEXT_VJUSTIFY_TOP );
367 
368  PCB_TEXT* t;
369 
370  t = static_cast<PCB_TEXT*>( headStyle->Duplicate() );
371  t->SetText( _( "BOARD CHARACTERISTICS" ) );
372  t->SetPosition( cursorPos );
373  objects.push_back( t );
374 
375  cursorPos.y = cursorPos.y + t->GetBoundingBox().GetHeight()
377 
378  std::vector<std::vector<PCB_TEXT*>> texts;
379  std::vector<PCB_TEXT*> colLabel1;
380  std::vector<PCB_TEXT*> colData1;
381  std::vector<PCB_TEXT*> colbreak;
382  std::vector<PCB_TEXT*> colLabel2;
383  std::vector<PCB_TEXT*> colData2;
384  wxString text = wxString( "" );
385 
386  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
387  t->SetText( _( "Copper Layer Count: " ) );
388  colLabel1.push_back( t );
389 
390  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
392  colData1.push_back( t );
393 
394  EDA_RECT size = m_frame->GetBoard()->ComputeBoundingBox( true );
395  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
396  t->SetText( _( "Board overall dimensions: " ) );
397  colLabel1.push_back( t );
398 
399  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
400  t->SetText( wxString::Format( "%s x %s",
402  MessageTextFromValue( m_frame->GetUserUnits(), size.GetHeight(), true ) ) );
403  colData1.push_back( t );
404 
405  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
406  t->SetText( _( "Min track/spacing: " ) );
407  colLabel1.push_back( t );
408 
409  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
410  t->SetText( wxString::Format( "%s / %s",
412  MessageTextFromValue( m_frame->GetUserUnits(), settings.m_MinClearance, true ) ) );
413  colData1.push_back( t );
414 
415  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
416  t->SetText( _( "Copper Finish: " ) );
417  colLabel1.push_back( t );
418 
419  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
420  t->SetText( stackup.m_FinishType );
421  colData1.push_back( t );
422 
423  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
424  t->SetText( _( "Castellated pads: " ) );
425  colLabel1.push_back( t );
426 
427  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
428  t->SetText( stackup.m_CastellatedPads ? _( "Yes" ) : _( "No" ) );
429  colData1.push_back( t );
430 
431  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
432  t->SetText( _( "Board Thickness: " ) );
433  colLabel2.push_back( t );
434 
435  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
437 
438  t->SetText( text );
439  colData2.push_back( t );
440 
441  // some empty cells
442  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
443  colLabel2.push_back( t );
444  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
445  colData2.push_back( t );
446 
447  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
448  t->SetText( _( "Min hole diameter: " ) );
449  colLabel2.push_back( t );
450  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
451 
452  double holeSize = std::min( settings.m_MinThroughDrill, settings.m_ViasMinSize );
453  text = MessageTextFromValue( m_frame->GetUserUnits(), holeSize, true );
454  t->SetText( text );
455  colData2.push_back( t );
456 
457  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
458  t->SetText( _( "Impedance Control: " ) );
459  colLabel2.push_back( t );
460 
461  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
462  t->SetText( stackup.m_CastellatedPads ? _( "Yes" ) : _( "No" ) );
463  colData2.push_back( t );
464 
465  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
466  t->SetText( _( "Plated Board Edge: " ) );
467  colLabel2.push_back( t );
468  t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
469  t->SetText( stackup.m_HasDielectricConstrains ? _( "Yes" ) : _( "No" ) );
470  colData2.push_back( t );
471 
472  texts.push_back( colLabel1 );
473  texts.push_back( colData1 );
474  texts.push_back( colbreak );
475  texts.push_back( colLabel2 );
476  texts.push_back( colData2 );
477  wxPoint tableSize2 = wxPoint();
478 
479  std::vector<BOARD_ITEM*> table = initTextTable( texts, cursorPos, Eco1_User, &tableSize2,
480  false );
481 
482  for( auto item : table )
483  objects.push_back( item );
484 
485  if( aDrawNow )
486  {
487  for( auto item : objects )
488  commit.Add( item );
489 
490  commit.Push( "Board Characteristics" );
491  }
492 
493  tableSize->x = tableSize2.x;
494  tableSize->y = cursorPos.y + tableSize2.y + From_User_Unit( EDA_UNITS::MILLIMETRES, 2.0 );
495 
496  return objects;
497 }
498 
499 
501  std::vector<BOARD_ITEM*>& aItems,
502  std::vector<BOARD_ITEM*>& aPreview,
503  LSET* aLayers )
504 {
506  return -1;
507 
508  bool cancelled = false;
509 
510  BOARD_COMMIT commit( m_frame );
511 
513  m_controls->ShowCursor( true );
514  // do not capture or auto-pan until we start placing the table
515 
516  SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::TEXT );
517 
518  std::string tool = aEvent.GetCommandStr().get();
519  m_frame->PushTool( tool );
520  Activate();
521 
522  // Prime the pump
523  if( aEvent.HasPosition() )
525 
526  // Main loop: keep receiving events
527  wxPoint wxCursorPosition = wxPoint();
528  wxPoint wxPreviousCursorPosition = wxPoint( 0, 0 );
529 
530  view()->ClearPreview();
531  view()->InitPreview();
532 
533  for( auto item : aPreview )
534  {
535  item->Move( wxCursorPosition - wxPreviousCursorPosition );
536  view()->AddToPreview( item );
537  }
538 
539  while( TOOL_EVENT* evt = Wait() )
540  {
543  wxCursorPosition.x = pos.x;
544  wxCursorPosition.y = pos.y;
545 
546  if( evt->IsCancelInteractive() )
547  {
548  m_frame->PopTool( tool );
549  cancelled = true;
550  break;
551  }
552 
553  if( evt->IsMotion() )
554  {
555  view()->ShowPreview( false );
556 
557  for( auto item : aPreview )
558  {
559  item->Move( wxCursorPosition - wxPreviousCursorPosition );
560  }
561 
562  view()->ShowPreview( true );
563 
564  wxPreviousCursorPosition.x = wxCursorPosition.x;
565  wxPreviousCursorPosition.y = wxCursorPosition.y;
566 
567  }
568  else if( evt->IsActivate() )
569  {
570 
571  if( evt->IsMoveTool() )
572  {
573  // leave ourselves on the stack so we come back after the move
574  cancelled = true;
575  break;
576  }
577  else
578  {
579  m_frame->PopTool( tool );
580  cancelled = true;
581  break;
582  }
583  }
584  else if( evt->IsClick( BUT_RIGHT ) )
585  {
587  }
588  else if( evt->IsClick( BUT_LEFT ) )
589  {
590  if( aLayers != NULL )
591  {
592  PCB_LAYER_ID targetLayer = frame()->SelectOneLayer(
594  *aLayers, wxGetMousePosition() );
595 
596  view()->ClearPreview();
597 
598  if( targetLayer == PCB_LAYER_ID::UNDEFINED_LAYER )
599  {
600  // The user did not pick any layer.
601  m_frame->PopTool( tool );
602  cancelled = true;
603  break;
604  }
605 
606  for( auto item : aItems )
607  {
608  if( item->Type() == PCB_GROUP_T )
609  {
610  static_cast<PCB_GROUP*>( item )->SetLayerRecursive( targetLayer, 200 );
611  }
612  else
613  {
614  item->SetLayer( targetLayer );
615  }
616  }
617  }
618 
619  for( auto item : aItems )
620  {
621  item->Move( wxCursorPosition );
622 
623  if( item->Type() == PCB_GROUP_T )
624  {
625  static_cast<PCB_GROUP*>( item )->AddChildrenToCommit( commit );
626  }
627 
628  commit.Add( item );
629  }
630 
631  commit.Push( "Placing items" );
632  m_frame->PopTool( tool );
633 
634  break;
635  }
636 
637  else
638  evt->SetPassEvent();
639  }
640 
641  view()->ClearPreview();
642  frame()->SetMsgPanel( board() );
643 
644  if( cancelled )
645  return -1;
646 
647  return 0;
648 }
649 
651 {
652  wxPoint tableSize = wxPoint();
653 
654  LSET layerSet = ( layerSet.AllCuMask() | layerSet.AllTechMask() );
655  layerSet = static_cast<LSET>( layerSet.set( Edge_Cuts ).set( Margin ) );
656  layerSet = static_cast<LSET>( layerSet.reset( F_Fab ).reset( B_Fab ) );
657 
659  PCB_LAYER_ID savedLayer = layer;
660 
661  if( ( layerSet & LSET( layer ) ).count() ) // if layer is a forbidden layer
662  {
664  layer = Cmts_User;
665  }
666 
667  std::vector<BOARD_ITEM*> table = DrawBoardCharacteristics(
668  wxPoint( 0, 0 ), m_frame->GetActiveLayer(), false, &tableSize );
669  std::vector<BOARD_ITEM*> preview;
670  std::vector<BOARD_ITEM*> items;
671 
672  PCB_SHAPE* line1 = new PCB_SHAPE;
673  PCB_SHAPE* line2 = new PCB_SHAPE;
674  PCB_SHAPE* line3 = new PCB_SHAPE;
675  PCB_SHAPE* line4 = new PCB_SHAPE;
676 
677  line1->SetStartX( 0 );
678  line1->SetStartY( 0 );
679  line1->SetEndX( tableSize.x );
680  line1->SetEndY( 0 );
681 
682  line2->SetStartX( 0 );
683  line2->SetStartY( 0 );
684  line2->SetEndX( 0 );
685  line2->SetEndY( tableSize.y );
686 
687  line3->SetStartX( tableSize.x );
688  line3->SetStartY( 0 );
689  line3->SetEndX( tableSize.x );
690  line3->SetEndY( tableSize.y );
691 
692  line4->SetStartX( 0 );
693  line4->SetStartY( tableSize.y );
694  line4->SetEndX( tableSize.x );
695  line4->SetEndY( tableSize.y );
696 
697  line1->SetLayer( m_frame->GetActiveLayer() );
698  line2->SetLayer( m_frame->GetActiveLayer() );
699  line3->SetLayer( m_frame->GetActiveLayer() );
700  line4->SetLayer( m_frame->GetActiveLayer() );
701 
702  preview.push_back( line1 );
703  preview.push_back( line2 );
704  preview.push_back( line3 );
705  preview.push_back( line4 );
706 
707  PCB_GROUP* group = new PCB_GROUP( m_board );
708  group->SetName("group-boardCharacteristics");
709 
710  for( auto item : table )
711  group->AddItem( static_cast<BOARD_ITEM*>( item ) );
712 
713  items.push_back( static_cast<BOARD_ITEM*>( group ) );
714 
715  if( InteractivePlaceWithPreview( aEvent, items, preview, &layerSet ) == -1 )
716  m_frame->SetActiveLayer( savedLayer );
717  else
718  m_frame->SetActiveLayer( table.front()->GetLayer() );
719 
720  return 0;
721 }
722 
724 {
725  wxPoint tableSize = wxPoint();
726 
727  LSET layerSet = ( layerSet.AllCuMask() | layerSet.AllTechMask() );
728  layerSet = static_cast<LSET>( layerSet.set( Edge_Cuts ).set( Margin ) );
729  layerSet = static_cast<LSET>( layerSet.reset( F_Fab ).reset( B_Fab ) );
730 
732  PCB_LAYER_ID savedLayer = layer;
733 
734  if( ( layerSet & LSET( layer ) ).count() ) // if layer is a forbidden layer
735  {
737  layer = Cmts_User;
738  }
739 
740  std::vector<BOARD_ITEM*> table = DrawSpecificationStackup(
741  wxPoint( 0, 0 ), m_frame->GetActiveLayer(), false, &tableSize );
742  std::vector<BOARD_ITEM*> preview;
743  std::vector<BOARD_ITEM*> items;
744 
745  PCB_SHAPE* line1 = new PCB_SHAPE;
746  PCB_SHAPE* line2 = new PCB_SHAPE;
747  PCB_SHAPE* line3 = new PCB_SHAPE;
748  PCB_SHAPE* line4 = new PCB_SHAPE;
749 
750  line1->SetStartX( 0 );
751  line1->SetStartY( 0 );
752  line1->SetEndX( tableSize.x );
753  line1->SetEndY( 0 );
754 
755  line2->SetStartX( 0 );
756  line2->SetStartY( 0 );
757  line2->SetEndX( 0 );
758  line2->SetEndY( tableSize.y );
759 
760  line3->SetStartX( tableSize.x );
761  line3->SetStartY( 0 );
762  line3->SetEndX( tableSize.x );
763  line3->SetEndY( tableSize.y );
764 
765  line4->SetStartX( 0 );
766  line4->SetStartY( tableSize.y );
767  line4->SetEndX( tableSize.x );
768  line4->SetEndY( tableSize.y );
769 
770  line1->SetLayer( m_frame->GetActiveLayer() );
771  line2->SetLayer( m_frame->GetActiveLayer() );
772  line3->SetLayer( m_frame->GetActiveLayer() );
773  line4->SetLayer( m_frame->GetActiveLayer() );
774 
775  preview.push_back( line1 );
776  preview.push_back( line2 );
777  preview.push_back( line3 );
778  preview.push_back( line4 );
779 
780  PCB_GROUP* group = new PCB_GROUP( m_board );
781  group->SetName("group-boardStackUp");
782 
783  for( auto item : table )
784  group->AddItem( item );
785 
786  items.push_back( static_cast<BOARD_ITEM*>( group ) );
787 
788  if( InteractivePlaceWithPreview( aEvent, items, preview, &layerSet ) == -1 )
789  m_frame->SetActiveLayer( savedLayer );
790  else
791  m_frame->SetActiveLayer( table.front()->GetLayer() );
792 
793  return 0;
794 }
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:63
void SetStartX(int x)
Definition: pcb_shape.h:150
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:225
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:90
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.
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:77
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:194
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:186
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:215
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:253
int GetWidth() const
Definition: eda_rect.h:114
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:141
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.h:593
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:244
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)
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:121
void SetEndY(int y)
Definition: pcb_shape.h:160
#define NULL
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:209
Generic, UI-independent tool event.
Definition: tool_event.h:173
void ClearPreview()
Definition: view.cpp:1525
KIGFX::PCB_VIEW * view() const
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:161
int GetHeight() const
Definition: eda_rect.h:115
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:471
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Definition: eda_text.h:208
#define _(s)
Definition: 3d_actions.cpp:33
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:1050
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:190
void Activate()
Run the tool.
void SetStartY(int y)
Definition: pcb_shape.h:149
virtual BOARD_ITEM * Duplicate() const
Create a copy of this BOARD_ITEM.
Definition: board_item.h:202
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.h:166
bool HasPosition() const
Definition: tool_event.h:261
const EDA_RECT GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: pcb_text.cpp:130
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:268
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:126
Container for design settings for a BOARD object.