1 /*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
5 * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
6 * Copyright (C) 2012 Wayne Stambaugh <stambaughw@gmail.com>
7 * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, you may find one here:
21 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22 * or you may search the http://www.gnu.org website for the version 2 license,
23 * or you may write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 */
26
27 #include <memory>
28
29 #include <advanced_config.h>
30 #include <bitmaps.h>
31 #include <board.h>
32 #include <board_design_settings.h>
33 #include <kiface_base.h>
34 #include <macros.h>
35 #include <pcb_edit_frame.h>
36 #include <pcb_layer_box_selector.h>
37 #include <pcbnew_id.h>
38 #include <pcbnew_settings.h>
39 #include <pgm_base.h>
40 #include <router/pns_routing_settings.h>
41 #include <router/router_tool.h>
42 #include <settings/color_settings.h>
43 #include <tool/action_toolbar.h>
44 #include <tool/actions.h>
45 #include <tool/common_tools.h>
46 #include <tool/tool_manager.h>
47 #include <tools/pcb_actions.h>
48 #include <tools/pcb_selection_tool.h>
49 #include <widgets/appearance_controls.h>
50 #include <widgets/wx_aui_utils.h>
51 #include <wx/wupdlock.h>
52 #include <wx/dcmemory.h>
53 #include <wx/choice.h>
54
55 #include "../scripting/python_scripting.h"
56
57
58 /* Data to build the layer pair indicator button */
59 static std::unique_ptr<wxBitmap> LayerPairBitmap;
60
61 #define BM_LAYERICON_SIZE 24
62 static const char s_BitmapLayerIcon[BM_LAYERICON_SIZE][BM_LAYERICON_SIZE] =
63 {
64 // 0 = draw pixel with white
65 // 1 = draw pixel with black
66 // 2 = draw pixel with top layer from router pair
67 // 3 = draw pixel with bottom layer from router pair
68 { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3 },
69 { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3 },
70 { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3 },
71 { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3 },
72 { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3 },
73 { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3 },
74 { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3 },
75 { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3 },
76 { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
77 { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
78 { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
79 { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
80 { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
81 { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
82 { 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
83 { 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
84 { 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
85 { 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
86 { 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
87 { 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
88 { 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
89 { 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
90 { 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
91 { 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
92 };
93
94 static COLOR4D ICON_WHITE { 0.86, 0.86, 0.86, 1.0 };
95 static COLOR4D ICON_BLACK { 0.28, 0.28, 0.28, 1.0 };
96
97
PrepareLayerIndicator(bool aForceRebuild)98 void PCB_EDIT_FRAME::PrepareLayerIndicator( bool aForceRebuild )
99 {
100 int ii, jj;
101 COLOR4D top_color, bottom_color, background_color;
102 bool change = aForceRebuild;
103
104 int requested_scale = Pgm().GetCommonSettings()->m_Appearance.icon_scale;
105
106 if( m_prevIconVal.previous_requested_scale != requested_scale )
107 {
108 m_prevIconVal.previous_requested_scale = requested_scale;
109 change = true;
110 }
111
112 top_color = GetColorSettings()->GetColor( GetScreen()->m_Route_Layer_TOP );
113
114 if( m_prevIconVal.previous_Route_Layer_TOP_color != top_color )
115 {
116 m_prevIconVal.previous_Route_Layer_TOP_color = top_color;
117 change = true;
118 }
119
120 bottom_color = GetColorSettings()->GetColor( GetScreen()->m_Route_Layer_BOTTOM );
121
122 if( m_prevIconVal.previous_Route_Layer_BOTTOM_color != bottom_color )
123 {
124 m_prevIconVal.previous_Route_Layer_BOTTOM_color = bottom_color;
125 change = true;
126 }
127
128 background_color = GetColorSettings()->GetColor( LAYER_PCB_BACKGROUND );
129
130 if( m_prevIconVal.previous_background_color != background_color )
131 {
132 m_prevIconVal.previous_background_color = background_color;
133 change = true;
134 }
135
136 if( change || !LayerPairBitmap )
137 {
138 LayerPairBitmap = std::make_unique<wxBitmap>( 24, 24 );
139
140 // Draw the icon, with colors according to the router's layer pair
141 wxMemoryDC iconDC;
142 iconDC.SelectObject( *LayerPairBitmap );
143 wxBrush brush;
144 wxPen pen;
145 int buttonColor = -1;
146
147 brush.SetStyle( wxBRUSHSTYLE_SOLID );
148 brush.SetColour( background_color.WithAlpha(1.0).ToColour() );
149 iconDC.SetBrush( brush );
150 iconDC.DrawRectangle( 0, 0, BM_LAYERICON_SIZE, BM_LAYERICON_SIZE );
151
152 for( ii = 0; ii < BM_LAYERICON_SIZE; ii++ )
153 {
154 for( jj = 0; jj < BM_LAYERICON_SIZE; jj++ )
155 {
156 if( s_BitmapLayerIcon[ii][jj] != buttonColor )
157 {
158 switch( s_BitmapLayerIcon[ii][jj] )
159 {
160 default:
161 case 0: pen.SetColour( ICON_WHITE.ToColour() ); break;
162 case 1: pen.SetColour( ICON_BLACK.ToColour() ); break;
163 case 2: pen.SetColour( top_color.ToColour() ); break;
164 case 3: pen.SetColour( bottom_color.ToColour() ); break;
165 }
166
167 buttonColor = s_BitmapLayerIcon[ii][jj];
168 iconDC.SetPen( pen );
169 }
170
171 iconDC.DrawPoint( jj, ii );
172 }
173 }
174
175 // Deselect the bitmap from the DC in order to delete the MemoryDC safely without
176 // deleting the bitmap
177 iconDC.SelectObject( wxNullBitmap );
178
179 // Scale the bitmap
180 const int scale = ( requested_scale <= 0 ) ? KiIconScale( this ) : requested_scale;
181 wxImage image = LayerPairBitmap->ConvertToImage();
182
183 // "NEAREST" causes less mixing of colors
184 image.Rescale( scale * image.GetWidth() / 4, scale * image.GetHeight() / 4,
185 wxIMAGE_QUALITY_NEAREST );
186
187 LayerPairBitmap = std::make_unique<wxBitmap>( image );
188
189 if( m_mainToolBar )
190 {
191 m_mainToolBar->SetToolBitmap( PCB_ACTIONS::selectLayerPair, *LayerPairBitmap );
192 m_mainToolBar->Refresh();
193 }
194 }
195 }
196
197
ReCreateHToolbar()198 void PCB_EDIT_FRAME::ReCreateHToolbar()
199 {
200 // Note:
201 // To rebuild the aui toolbar, the more easy way is to clear ( calling m_mainToolBar.Clear() )
202 // all wxAuiToolBarItems.
203 // However the wxAuiToolBarItems are not the owners of controls managed by
204 // them and therefore do not delete them
205 // So we do not recreate them after clearing the tools.
206
207 wxWindowUpdateLocker dummy( this );
208
209 if( m_mainToolBar )
210 {
211 m_mainToolBar->ClearToolbar();
212 }
213 else
214 {
215 m_mainToolBar = new ACTION_TOOLBAR( this, ID_H_TOOLBAR, wxDefaultPosition, wxDefaultSize,
216 KICAD_AUI_TB_STYLE | wxAUI_TB_HORZ_LAYOUT |
217 wxAUI_TB_HORIZONTAL );
218 m_mainToolBar->SetAuiManager( &m_auimgr );
219
220 // The layer indicator is special, so we register a callback directly that will
221 // regenerate the bitmap instead of using the conditions system.
222 auto layerIndicatorUpdate =
223 [this] ( wxUpdateUIEvent& )
224 {
225 PrepareLayerIndicator();
226 };
227
228 Bind( wxEVT_UPDATE_UI, layerIndicatorUpdate, PCB_ACTIONS::selectLayerPair.GetUIId() );
229 }
230
231 // Set up toolbar
232 if( Kiface().IsSingle() )
233 {
234 m_mainToolBar->Add( ACTIONS::doNew );
235 m_mainToolBar->Add( ACTIONS::open );
236 }
237
238 m_mainToolBar->Add( ACTIONS::save );
239
240 m_mainToolBar->AddScaledSeparator( this );
241 m_mainToolBar->Add( PCB_ACTIONS::boardSetup );
242
243 m_mainToolBar->AddScaledSeparator( this );
244 m_mainToolBar->Add( ACTIONS::pageSettings );
245 m_mainToolBar->Add( ACTIONS::print );
246 m_mainToolBar->Add( ACTIONS::plot );
247
248 m_mainToolBar->AddScaledSeparator( this );
249 m_mainToolBar->Add( ACTIONS::undo );
250 m_mainToolBar->Add( ACTIONS::redo );
251
252 m_mainToolBar->AddScaledSeparator( this );
253 m_mainToolBar->Add( ACTIONS::find );
254
255 m_mainToolBar->AddScaledSeparator( this );
256 m_mainToolBar->Add( ACTIONS::zoomRedraw );
257 m_mainToolBar->Add( ACTIONS::zoomInCenter );
258 m_mainToolBar->Add( ACTIONS::zoomOutCenter );
259 m_mainToolBar->Add( ACTIONS::zoomFitScreen );
260 m_mainToolBar->Add( ACTIONS::zoomFitObjects );
261 m_mainToolBar->Add( ACTIONS::zoomTool, ACTION_TOOLBAR::TOGGLE, ACTION_TOOLBAR::CANCEL );
262
263 m_mainToolBar->AddScaledSeparator( this );
264 m_mainToolBar->Add( PCB_ACTIONS::rotateCcw );
265 m_mainToolBar->Add( PCB_ACTIONS::rotateCw );
266 m_mainToolBar->Add( PCB_ACTIONS::group );
267 m_mainToolBar->Add( PCB_ACTIONS::ungroup );
268 m_mainToolBar->Add( PCB_ACTIONS::lock );
269 m_mainToolBar->Add( PCB_ACTIONS::unlock );
270
271 m_mainToolBar->AddScaledSeparator( this );
272 m_mainToolBar->Add( ACTIONS::showFootprintEditor );
273 m_mainToolBar->Add( ACTIONS::showFootprintBrowser );
274
275 m_mainToolBar->AddScaledSeparator( this );
276
277 if( !Kiface().IsSingle() )
278 m_mainToolBar->Add( ACTIONS::updatePcbFromSchematic );
279 else
280 m_mainToolBar->Add( PCB_ACTIONS::importNetlist );
281
282 m_mainToolBar->Add( PCB_ACTIONS::runDRC );
283
284 m_mainToolBar->AddScaledSeparator( this );
285
286 if( m_SelLayerBox == nullptr )
287 {
288 m_SelLayerBox = new PCB_LAYER_BOX_SELECTOR( m_mainToolBar, ID_TOOLBARH_PCB_SELECT_LAYER );
289 m_SelLayerBox->SetBoardFrame( this );
290 }
291
292 ReCreateLayerBox( false );
293 m_mainToolBar->AddControl( m_SelLayerBox );
294
295 m_mainToolBar->Add( PCB_ACTIONS::selectLayerPair );
296 PrepareLayerIndicator( true ); // Force rebuild of the bitmap with the active layer colors
297
298 m_mainToolBar->AddScaledSeparator( this );
299 m_mainToolBar->Add( PCB_ACTIONS::showEeschema );
300
301 // Access to the scripting console
302 if( SCRIPTING::IsWxAvailable() )
303 {
304 m_mainToolBar->AddScaledSeparator( this );
305 m_mainToolBar->Add( PCB_ACTIONS::showPythonConsole, ACTION_TOOLBAR::TOGGLE );
306 AddActionPluginTools();
307 }
308
309 // Go through and ensure the comboboxes are the correct size, since the strings in the
310 // box could have changed widths.
311 m_mainToolBar->UpdateControlWidth( ID_TOOLBARH_PCB_SELECT_LAYER );
312
313 // after adding the buttons to the toolbar, must call Realize() to reflect the changes
314 m_mainToolBar->KiRealize();
315 }
316
317
ReCreateOptToolbar()318 void PCB_EDIT_FRAME::ReCreateOptToolbar()
319 {
320 // Note:
321 // To rebuild the aui toolbar, the more easy way is to clear ( calling m_mainToolBar.Clear() )
322 // all wxAuiToolBarItems.
323 // However the wxAuiToolBarItems are not the owners of controls managed by
324 // them and therefore do not delete them
325 // So we do not recreate them after clearing the tools.
326
327 wxWindowUpdateLocker dummy( this );
328
329 if( m_optionsToolBar )
330 {
331 m_optionsToolBar->ClearToolbar();
332 }
333 else
334 {
335 m_optionsToolBar = new ACTION_TOOLBAR( this, ID_OPT_TOOLBAR,
336 wxDefaultPosition, wxDefaultSize,
337 KICAD_AUI_TB_STYLE | wxAUI_TB_VERTICAL );
338 m_optionsToolBar->SetAuiManager( &m_auimgr );
339 }
340
341 m_optionsToolBar->Add( ACTIONS::toggleGrid, ACTION_TOOLBAR::TOGGLE );
342
343 m_optionsToolBar->Add( PCB_ACTIONS::togglePolarCoords, ACTION_TOOLBAR::TOGGLE );
344 m_optionsToolBar->Add( ACTIONS::inchesUnits, ACTION_TOOLBAR::TOGGLE );
345 m_optionsToolBar->Add( ACTIONS::milsUnits, ACTION_TOOLBAR::TOGGLE );
346 m_optionsToolBar->Add( ACTIONS::millimetersUnits, ACTION_TOOLBAR::TOGGLE );
347 m_optionsToolBar->Add( ACTIONS::toggleCursorStyle, ACTION_TOOLBAR::TOGGLE );
348
349 m_optionsToolBar->AddScaledSeparator( this );
350 m_optionsToolBar->Add( PCB_ACTIONS::showRatsnest, ACTION_TOOLBAR::TOGGLE );
351 m_optionsToolBar->Add( PCB_ACTIONS::ratsnestLineMode, ACTION_TOOLBAR::TOGGLE );
352
353 m_optionsToolBar->AddScaledSeparator( this );
354 m_optionsToolBar->Add( ACTIONS::highContrastMode, ACTION_TOOLBAR::TOGGLE );
355 m_optionsToolBar->Add( PCB_ACTIONS::toggleNetHighlight, ACTION_TOOLBAR::TOGGLE );
356
357 m_optionsToolBar->AddScaledSeparator( this );
358 m_optionsToolBar->Add( PCB_ACTIONS::zoneDisplayFilled, ACTION_TOOLBAR::TOGGLE );
359 m_optionsToolBar->Add( PCB_ACTIONS::zoneDisplayOutline, ACTION_TOOLBAR::TOGGLE );
360
361 if( ADVANCED_CFG::GetCfg().m_ExtraZoneDisplayModes )
362 {
363 m_optionsToolBar->Add( PCB_ACTIONS::zoneDisplayFractured, ACTION_TOOLBAR::TOGGLE );
364 m_optionsToolBar->Add( PCB_ACTIONS::zoneDisplayTriangulated, ACTION_TOOLBAR::TOGGLE );
365 }
366
367 m_optionsToolBar->AddScaledSeparator( this );
368 m_optionsToolBar->Add( PCB_ACTIONS::padDisplayMode, ACTION_TOOLBAR::TOGGLE );
369 m_optionsToolBar->Add( PCB_ACTIONS::viaDisplayMode, ACTION_TOOLBAR::TOGGLE );
370 m_optionsToolBar->Add( PCB_ACTIONS::trackDisplayMode, ACTION_TOOLBAR::TOGGLE );
371
372 // Tools to show/hide toolbars:
373 m_optionsToolBar->AddScaledSeparator( this );
374 m_optionsToolBar->Add( PCB_ACTIONS::showLayersManager, ACTION_TOOLBAR::TOGGLE );
375
376 PCB_SELECTION_TOOL* selTool = m_toolManager->GetTool<PCB_SELECTION_TOOL>();
377 std::unique_ptr<ACTION_MENU> gridMenu = std::make_unique<ACTION_MENU>( false, selTool );
378 gridMenu->Add( ACTIONS::gridProperties );
379 m_optionsToolBar->AddToolContextMenu( ACTIONS::toggleGrid, std::move( gridMenu ) );
380
381 m_optionsToolBar->KiRealize();
382 }
383
384
ReCreateVToolbar()385 void PCB_EDIT_FRAME::ReCreateVToolbar()
386 {
387 wxWindowUpdateLocker dummy( this );
388
389 if( m_drawToolBar )
390 {
391 m_drawToolBar->ClearToolbar();
392 }
393 else
394 {
395 m_drawToolBar = new ACTION_TOOLBAR( this, ID_V_TOOLBAR, wxDefaultPosition, wxDefaultSize,
396 KICAD_AUI_TB_STYLE | wxAUI_TB_VERTICAL );
397 m_drawToolBar->SetAuiManager( &m_auimgr );
398 }
399
400 // Groups contained on this toolbar
401 static ACTION_GROUP* dimensionGroup = nullptr;
402 static ACTION_GROUP* originGroup = nullptr;
403 static ACTION_GROUP* routingGroup = nullptr;
404 static ACTION_GROUP* tuneGroup = nullptr;
405
406 if( !dimensionGroup )
407 {
408 dimensionGroup = new ACTION_GROUP( "group.pcbDimensions",
409 { &PCB_ACTIONS::drawAlignedDimension,
410 &PCB_ACTIONS::drawOrthogonalDimension,
411 &PCB_ACTIONS::drawCenterDimension,
412 &PCB_ACTIONS::drawLeader } );
413 }
414
415 if( !originGroup )
416 {
417 originGroup = new ACTION_GROUP( "group.pcbOrigins",
418 { &PCB_ACTIONS::drillOrigin,
419 &PCB_ACTIONS::gridSetOrigin } );
420 }
421
422 if( !routingGroup )
423 {
424 routingGroup = new ACTION_GROUP( "group.pcbRouting",
425 { &PCB_ACTIONS::routeSingleTrack,
426 &PCB_ACTIONS::routeDiffPair } );
427 }
428
429 if( !tuneGroup )
430 {
431 tuneGroup = new ACTION_GROUP( "group.pcbTune",
432 { &PCB_ACTIONS::routerTuneSingleTrace,
433 &PCB_ACTIONS::routerTuneDiffPair,
434 &PCB_ACTIONS::routerTuneDiffPairSkew } );
435 }
436
437 m_drawToolBar->Add( ACTIONS::selectionTool, ACTION_TOOLBAR::TOGGLE );
438 m_drawToolBar->Add( PCB_ACTIONS::localRatsnestTool, ACTION_TOOLBAR::TOGGLE );
439
440 m_drawToolBar->AddScaledSeparator( this );
441 m_drawToolBar->Add( PCB_ACTIONS::placeFootprint, ACTION_TOOLBAR::TOGGLE );
442 m_drawToolBar->AddGroup( routingGroup, ACTION_TOOLBAR::TOGGLE );
443 m_drawToolBar->AddGroup( tuneGroup, ACTION_TOOLBAR::TOGGLE );
444 m_drawToolBar->Add( PCB_ACTIONS::drawVia, ACTION_TOOLBAR::TOGGLE );
445 m_drawToolBar->Add( PCB_ACTIONS::drawZone, ACTION_TOOLBAR::TOGGLE );
446 m_drawToolBar->Add( PCB_ACTIONS::drawRuleArea, ACTION_TOOLBAR::TOGGLE );
447
448 m_drawToolBar->AddScaledSeparator( this );
449 m_drawToolBar->Add( PCB_ACTIONS::drawLine, ACTION_TOOLBAR::TOGGLE );
450 m_drawToolBar->Add( PCB_ACTIONS::drawArc, ACTION_TOOLBAR::TOGGLE );
451 m_drawToolBar->Add( PCB_ACTIONS::drawRectangle, ACTION_TOOLBAR::TOGGLE );
452 m_drawToolBar->Add( PCB_ACTIONS::drawCircle, ACTION_TOOLBAR::TOGGLE );
453 m_drawToolBar->Add( PCB_ACTIONS::drawPolygon, ACTION_TOOLBAR::TOGGLE );
454 m_drawToolBar->Add( PCB_ACTIONS::placeText, ACTION_TOOLBAR::TOGGLE );
455 m_drawToolBar->AddGroup( dimensionGroup, ACTION_TOOLBAR::TOGGLE );
456 m_drawToolBar->Add( PCB_ACTIONS::placeTarget, ACTION_TOOLBAR::TOGGLE );
457 m_drawToolBar->Add( ACTIONS::deleteTool, ACTION_TOOLBAR::TOGGLE );
458
459 m_drawToolBar->AddScaledSeparator( this );
460 m_drawToolBar->AddGroup( originGroup, ACTION_TOOLBAR::TOGGLE );
461 m_drawToolBar->Add( ACTIONS::measureTool, ACTION_TOOLBAR::TOGGLE );
462
463 PCB_SELECTION_TOOL* selTool = m_toolManager->GetTool<PCB_SELECTION_TOOL>();
464
465 auto makeRouteMenu =
466 [&]()
467 {
468 std::unique_ptr<ACTION_MENU> routeMenu =
469 std::make_unique<ACTION_MENU>( false, selTool );
470
471 routeMenu->Add( PCB_ACTIONS::routerHighlightMode, ACTION_MENU::CHECK );
472 routeMenu->Add( PCB_ACTIONS::routerShoveMode, ACTION_MENU::CHECK );
473 routeMenu->Add( PCB_ACTIONS::routerWalkaroundMode, ACTION_MENU::CHECK );
474
475 routeMenu->AppendSeparator();
476 routeMenu->Add( PCB_ACTIONS::routerSettingsDialog );
477
478 return routeMenu;
479 };
480
481 m_drawToolBar->AddToolContextMenu( PCB_ACTIONS::routeSingleTrack, makeRouteMenu() );
482 m_drawToolBar->AddToolContextMenu( PCB_ACTIONS::routeDiffPair, makeRouteMenu() );
483
484 auto makeTuneMenu =
485 [&]()
486 {
487 std::unique_ptr<ACTION_MENU> tuneMenu = std::make_unique<ACTION_MENU>( false, selTool );
488 tuneMenu->Add( PCB_ACTIONS::lengthTunerSettingsDialog );
489 return tuneMenu;
490 };
491
492 m_drawToolBar->AddToolContextMenu( PCB_ACTIONS::routerTuneSingleTrace, makeTuneMenu() );
493 m_drawToolBar->AddToolContextMenu( PCB_ACTIONS::routerTuneDiffPair, makeTuneMenu() );
494 m_drawToolBar->AddToolContextMenu( PCB_ACTIONS::routerTuneDiffPairSkew, makeTuneMenu() );
495
496 std::unique_ptr<ACTION_MENU> zoneMenu = std::make_unique<ACTION_MENU>( false, selTool );
497 zoneMenu->Add( PCB_ACTIONS::zoneFillAll );
498 zoneMenu->Add( PCB_ACTIONS::zoneUnfillAll );
499 m_drawToolBar->AddToolContextMenu( PCB_ACTIONS::drawZone, std::move( zoneMenu ) );
500
501 std::unique_ptr<ACTION_MENU> lineMenu = std::make_unique<ACTION_MENU>( false, selTool );
502 m_drawToolBar->AddToolContextMenu( PCB_ACTIONS::drawLine, std::move( lineMenu ) );
503
504 m_drawToolBar->KiRealize();
505 }
506
507
ReCreateAuxiliaryToolbar()508 void PCB_EDIT_FRAME::ReCreateAuxiliaryToolbar()
509 {
510 wxWindowUpdateLocker dummy( this );
511
512 if( m_auxiliaryToolBar )
513 {
514 m_auxiliaryToolBar->ClearToolbar();
515 }
516 else
517 {
518 m_auxiliaryToolBar = new ACTION_TOOLBAR( this, ID_AUX_TOOLBAR, wxDefaultPosition,
519 wxDefaultSize,
520 KICAD_AUI_TB_STYLE | wxAUI_TB_HORZ_LAYOUT );
521 m_auxiliaryToolBar->SetAuiManager( &m_auimgr );
522 }
523
524 /* Set up toolbar items */
525
526 // Creates box to display and choose tracks widths:
527 if( m_SelTrackWidthBox == nullptr )
528 m_SelTrackWidthBox = new wxChoice( m_auxiliaryToolBar, ID_AUX_TOOLBAR_PCB_TRACK_WIDTH,
529 wxDefaultPosition, wxDefaultSize, 0, nullptr );
530
531 UpdateTrackWidthSelectBox( m_SelTrackWidthBox );
532 m_auxiliaryToolBar->AddControl( m_SelTrackWidthBox );
533 m_SelTrackWidthBox->SetToolTip( _( "Select the default width for new tracks. Note that this "
534 "width can be overridden by the board minimum width, or by "
535 "the width of an existing track if the 'Use Existing Track "
536 "Width' feature is enabled." ) );
537
538 m_auxiliaryToolBar->AddTool( ID_AUX_TOOLBAR_PCB_SELECT_AUTO_WIDTH, wxEmptyString,
539 KiScaledBitmap( BITMAPS::auto_track_width, this ),
540 _( "When routing from an existing track use its width instead "
541 "of the current width setting" ),
542 wxITEM_CHECK );
543
544 m_auxiliaryToolBar->AddScaledSeparator( this );
545
546 // Creates box to display and choose vias diameters:
547
548 if( m_SelViaSizeBox == nullptr )
549 m_SelViaSizeBox = new wxChoice( m_auxiliaryToolBar, ID_AUX_TOOLBAR_PCB_VIA_SIZE,
550 wxDefaultPosition, wxDefaultSize, 0, nullptr );
551
552 UpdateViaSizeSelectBox( m_SelViaSizeBox );
553 m_auxiliaryToolBar->AddControl( m_SelViaSizeBox );
554
555 // Add the box to display and select the current grid size:
556 m_auxiliaryToolBar->AddScaledSeparator( this );
557
558 if( m_gridSelectBox == nullptr )
559 m_gridSelectBox = new wxChoice( m_auxiliaryToolBar, ID_ON_GRID_SELECT,
560 wxDefaultPosition, wxDefaultSize, 0, nullptr );
561
562 UpdateGridSelectBox();
563
564 m_auxiliaryToolBar->AddControl( m_gridSelectBox );
565
566 // Add the box to display and select the current Zoom
567 m_auxiliaryToolBar->AddScaledSeparator( this );
568
569 if( m_zoomSelectBox == nullptr )
570 m_zoomSelectBox = new wxChoice( m_auxiliaryToolBar, ID_ON_ZOOM_SELECT,
571 wxDefaultPosition, wxDefaultSize, 0, nullptr );
572
573 UpdateZoomSelectBox();
574 m_auxiliaryToolBar->AddControl( m_zoomSelectBox );
575
576 // Go through and ensure the comboboxes are the correct size, since the strings in the
577 // box could have changed widths.
578 m_auxiliaryToolBar->UpdateControlWidth( ID_AUX_TOOLBAR_PCB_TRACK_WIDTH );
579 m_auxiliaryToolBar->UpdateControlWidth( ID_AUX_TOOLBAR_PCB_VIA_SIZE );
580 m_auxiliaryToolBar->UpdateControlWidth( ID_ON_ZOOM_SELECT );
581 m_auxiliaryToolBar->UpdateControlWidth( ID_ON_GRID_SELECT );
582
583 // after adding the buttons to the toolbar, must call Realize()
584 m_auxiliaryToolBar->KiRealize();
585 }
586
587
UpdateToolbarControlSizes()588 void PCB_EDIT_FRAME::UpdateToolbarControlSizes()
589 {
590 if( m_mainToolBar )
591 {
592 // Update the item widths
593 m_mainToolBar->UpdateControlWidth( ID_TOOLBARH_PCB_SELECT_LAYER );
594 }
595
596 if( m_auxiliaryToolBar )
597 {
598 // Update the item widths
599 m_auxiliaryToolBar->UpdateControlWidth( ID_AUX_TOOLBAR_PCB_TRACK_WIDTH );
600 m_auxiliaryToolBar->UpdateControlWidth( ID_AUX_TOOLBAR_PCB_VIA_SIZE );
601 m_auxiliaryToolBar->UpdateControlWidth( ID_ON_ZOOM_SELECT );
602 m_auxiliaryToolBar->UpdateControlWidth( ID_ON_GRID_SELECT );
603 }
604 }
605
606
ComboBoxUnits(EDA_UNITS aUnits,double aValue,bool aIncludeLabel=true)607 static wxString ComboBoxUnits( EDA_UNITS aUnits, double aValue, bool aIncludeLabel = true )
608 {
609 wxString text;
610 const wxChar* format;
611
612 switch( aUnits )
613 {
614 default: wxASSERT_MSG( false, "Invalid unit" ); KI_FALLTHROUGH;
615 case EDA_UNITS::UNSCALED: format = wxT( "%.0f" ); break;
616 case EDA_UNITS::MILLIMETRES: format = wxT( "%.3f" ); break;
617 case EDA_UNITS::MILS: format = wxT( "%.2f" ); break;
618 case EDA_UNITS::INCHES: format = wxT( "%.5f" ); break;
619 }
620
621 text.Printf( format, To_User_Unit( aUnits, aValue ) );
622
623 if( aIncludeLabel )
624 {
625 text += " ";
626 text += GetAbbreviatedUnitsLabel( aUnits, EDA_DATA_TYPE::DISTANCE );
627 }
628
629 return text;
630 }
631
632
UpdateTrackWidthSelectBox(wxChoice * aTrackWidthSelectBox,bool aEdit)633 void PCB_EDIT_FRAME::UpdateTrackWidthSelectBox( wxChoice* aTrackWidthSelectBox, bool aEdit )
634 {
635 if( aTrackWidthSelectBox == nullptr )
636 return;
637
638 EDA_UNITS primaryUnit;
639 EDA_UNITS secondaryUnit;
640
641 GetUnitPair( primaryUnit, secondaryUnit );
642
643 wxString msg;
644
645 aTrackWidthSelectBox->Clear();
646
647 aTrackWidthSelectBox->Append( _( "Track: use netclass width" ) );
648
649 for( unsigned ii = 1; ii < GetDesignSettings().m_TrackWidthList.size(); ii++ )
650 {
651 int size = GetDesignSettings().m_TrackWidthList[ii];
652
653 msg.Printf( _( "Track: %s (%s)" ), ComboBoxUnits( primaryUnit, size ),
654 ComboBoxUnits( secondaryUnit, size ) );
655
656 aTrackWidthSelectBox->Append( msg );
657 }
658
659 if( aEdit )
660 {
661 aTrackWidthSelectBox->Append( wxT( "---" ) );
662 aTrackWidthSelectBox->Append( _( "Edit Pre-defined Sizes..." ) );
663 }
664
665 if( GetDesignSettings().GetTrackWidthIndex() >= GetDesignSettings().m_TrackWidthList.size() )
666 GetDesignSettings().SetTrackWidthIndex( 0 );
667
668 aTrackWidthSelectBox->SetSelection( GetDesignSettings().GetTrackWidthIndex() );
669 }
670
671
UpdateViaSizeSelectBox(wxChoice * aViaSizeSelectBox,bool aEdit)672 void PCB_EDIT_FRAME::UpdateViaSizeSelectBox( wxChoice* aViaSizeSelectBox, bool aEdit )
673 {
674 if( aViaSizeSelectBox == nullptr )
675 return;
676
677 aViaSizeSelectBox->Clear();
678
679 COMMON_TOOLS* cmnTool = m_toolManager->GetTool<COMMON_TOOLS>();
680
681 EDA_UNITS primaryUnit = GetUserUnits();
682 EDA_UNITS secondaryUnit = EDA_UNITS::MILS;
683
684 if( EDA_UNIT_UTILS::IsImperialUnit( primaryUnit ) )
685 {
686 if( cmnTool )
687 secondaryUnit = cmnTool->GetLastMetricUnits();
688 else
689 secondaryUnit = EDA_UNITS::MILLIMETRES;
690 }
691 else
692 {
693 if( cmnTool )
694 secondaryUnit = cmnTool->GetLastImperialUnits();
695 else
696 secondaryUnit = EDA_UNITS::MILS;
697 }
698
699 aViaSizeSelectBox->Append( _( "Via: use netclass sizes" ) );
700
701 for( unsigned ii = 1; ii < GetDesignSettings().m_ViasDimensionsList.size(); ii++ )
702 {
703 VIA_DIMENSION viaDimension = GetDesignSettings().m_ViasDimensionsList[ii];
704 wxString msg, priStr, secStr;
705
706 double diam = viaDimension.m_Diameter;
707 double hole = viaDimension.m_Drill;
708
709 if( hole > 0 )
710 {
711 priStr = ComboBoxUnits( primaryUnit, diam, false ) + " / "
712 + ComboBoxUnits( primaryUnit, hole, true );
713 secStr = ComboBoxUnits( secondaryUnit, diam, false ) + " / "
714 + ComboBoxUnits( secondaryUnit, hole, true );
715 }
716 else
717 {
718 priStr = ComboBoxUnits( primaryUnit, diam, true );
719 secStr = ComboBoxUnits( secondaryUnit, diam, true );
720 }
721
722 msg.Printf( _( "Via: %s (%s)" ), priStr, secStr );
723
724 aViaSizeSelectBox->Append( msg );
725 }
726
727 if( aEdit )
728 {
729 aViaSizeSelectBox->Append( wxT( "---" ) );
730 aViaSizeSelectBox->Append( _( "Edit Pre-defined Sizes..." ) );
731 }
732
733 if( GetDesignSettings().GetViaSizeIndex() >= GetDesignSettings().m_ViasDimensionsList.size() )
734 GetDesignSettings().SetViaSizeIndex( 0 );
735
736 aViaSizeSelectBox->SetSelection( GetDesignSettings().GetViaSizeIndex() );
737 }
738
739
ReCreateLayerBox(bool aForceResizeToolbar)740 void PCB_EDIT_FRAME::ReCreateLayerBox( bool aForceResizeToolbar )
741 {
742 if( m_SelLayerBox == nullptr || m_mainToolBar == nullptr )
743 return;
744
745 m_SelLayerBox->SetToolTip( _( "+/- to switch" ) );
746 m_SelLayerBox->Resync();
747
748 if( aForceResizeToolbar )
749 UpdateToolbarControlSizes();
750 }
751
752
ToggleLayersManager()753 void PCB_EDIT_FRAME::ToggleLayersManager()
754 {
755 PCBNEW_SETTINGS* settings = GetPcbNewSettings();
756 wxAuiPaneInfo& layersManager = m_auimgr.GetPane( "LayersManager" );
757 wxAuiPaneInfo& selectionFilter = m_auimgr.GetPane( "SelectionFilter" );
758
759 // show auxiliary Vertical layers and visibility manager toolbar
760 m_show_layer_manager_tools = !m_show_layer_manager_tools;
761 layersManager.Show( m_show_layer_manager_tools );
762 selectionFilter.Show( m_show_layer_manager_tools );
763
764 if( m_show_layer_manager_tools )
765 {
766 SetAuiPaneSize( m_auimgr, layersManager, settings->m_AuiPanels.right_panel_width, -1 );
767 }
768 else
769 {
770 settings->m_AuiPanels.right_panel_width = m_appearancePanel->GetSize().x;
771 m_auimgr.Update();
772 }
773 }
774
775
OnUpdateSelectTrackWidth(wxUpdateUIEvent & aEvent)776 void PCB_EDIT_FRAME::OnUpdateSelectTrackWidth( wxUpdateUIEvent& aEvent )
777 {
778 if( aEvent.GetId() == ID_AUX_TOOLBAR_PCB_TRACK_WIDTH )
779 {
780 BOARD_DESIGN_SETTINGS& bds = GetDesignSettings();
781 int sel;
782
783 if( bds.UseCustomTrackViaSize() )
784 sel = wxNOT_FOUND;
785 else
786 sel = bds.GetTrackWidthIndex();
787
788 if( m_SelTrackWidthBox->GetSelection() != sel )
789 m_SelTrackWidthBox->SetSelection( sel );
790 }
791 }
792
793
OnUpdateSelectViaSize(wxUpdateUIEvent & aEvent)794 void PCB_EDIT_FRAME::OnUpdateSelectViaSize( wxUpdateUIEvent& aEvent )
795 {
796 if( aEvent.GetId() == ID_AUX_TOOLBAR_PCB_VIA_SIZE )
797 {
798 BOARD_DESIGN_SETTINGS& bds = GetDesignSettings();
799 int sel = 0;
800
801 if( bds.UseCustomTrackViaSize() )
802 sel = wxNOT_FOUND;
803 else
804 sel = bds.GetViaSizeIndex();
805
806 if( m_SelViaSizeBox->GetSelection() != sel )
807 m_SelViaSizeBox->SetSelection( sel );
808 }
809 }
810
811
OnUpdateSelectAutoWidth(wxUpdateUIEvent & aEvent)812 void PCB_EDIT_FRAME::OnUpdateSelectAutoWidth( wxUpdateUIEvent& aEvent )
813 {
814 BOARD_DESIGN_SETTINGS& bds = GetDesignSettings();
815
816 aEvent.Check( bds.m_UseConnectedTrackWidth );
817 }
818
819
OnUpdateLayerSelectBox(wxUpdateUIEvent & aEvent)820 void PCB_EDIT_FRAME::OnUpdateLayerSelectBox( wxUpdateUIEvent& aEvent )
821 {
822 if( m_SelLayerBox->GetLayerSelection() != GetActiveLayer() )
823 m_SelLayerBox->SetLayerSelection( GetActiveLayer() );
824 }
825