You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

830 lines
31 KiB

7 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
11 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
7 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
  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-2022 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. #include <memory>
  27. #include <advanced_config.h>
  28. #include <bitmaps.h>
  29. #include <board.h>
  30. #include <board_design_settings.h>
  31. #include <kiface_base.h>
  32. #include <macros.h>
  33. #include <pcb_edit_frame.h>
  34. #include <pcb_layer_box_selector.h>
  35. #include <pcbnew_id.h>
  36. #include <pcbnew_settings.h>
  37. #include <pgm_base.h>
  38. #include <router/pns_routing_settings.h>
  39. #include <router/router_tool.h>
  40. #include <settings/color_settings.h>
  41. #include <tool/action_toolbar.h>
  42. #include <tool/actions.h>
  43. #include <tool/common_tools.h>
  44. #include <tool/tool_manager.h>
  45. #include <tools/pcb_actions.h>
  46. #include <tools/pcb_selection_tool.h>
  47. #include <widgets/appearance_controls.h>
  48. #include <widgets/wx_aui_utils.h>
  49. #include <wx/wupdlock.h>
  50. #include <wx/dcmemory.h>
  51. #include <wx/choice.h>
  52. #include "../scripting/python_scripting.h"
  53. /* Data to build the layer pair indicator button */
  54. static std::unique_ptr<wxBitmap> LayerPairBitmap;
  55. #define BM_LAYERICON_SIZE 24
  56. static const char s_BitmapLayerIcon[BM_LAYERICON_SIZE][BM_LAYERICON_SIZE] =
  57. {
  58. // 0 = draw pixel with white
  59. // 1 = draw pixel with black
  60. // 2 = draw pixel with top layer from router pair
  61. // 3 = draw pixel with bottom layer from router pair
  62. { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3 },
  63. { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3 },
  64. { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3 },
  65. { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3 },
  66. { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3 },
  67. { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3 },
  68. { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3 },
  69. { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3 },
  70. { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
  71. { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
  72. { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
  73. { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
  74. { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
  75. { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
  76. { 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
  77. { 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
  78. { 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
  79. { 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
  80. { 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
  81. { 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
  82. { 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
  83. { 2, 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
  84. { 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
  85. { 2, 2, 2, 2, 2, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
  86. };
  87. static COLOR4D ICON_WHITE { 0.86, 0.86, 0.86, 1.0 };
  88. static COLOR4D ICON_BLACK { 0.28, 0.28, 0.28, 1.0 };
  89. void PCB_EDIT_FRAME::PrepareLayerIndicator( bool aForceRebuild )
  90. {
  91. int ii, jj;
  92. COLOR4D top_color, bottom_color, background_color;
  93. bool change = aForceRebuild;
  94. int requested_scale = Pgm().GetCommonSettings()->m_Appearance.icon_scale;
  95. if( m_prevIconVal.previous_requested_scale != requested_scale )
  96. {
  97. m_prevIconVal.previous_requested_scale = requested_scale;
  98. change = true;
  99. }
  100. top_color = GetColorSettings()->GetColor( GetScreen()->m_Route_Layer_TOP );
  101. if( m_prevIconVal.previous_Route_Layer_TOP_color != top_color )
  102. {
  103. m_prevIconVal.previous_Route_Layer_TOP_color = top_color;
  104. change = true;
  105. }
  106. bottom_color = GetColorSettings()->GetColor( GetScreen()->m_Route_Layer_BOTTOM );
  107. if( m_prevIconVal.previous_Route_Layer_BOTTOM_color != bottom_color )
  108. {
  109. m_prevIconVal.previous_Route_Layer_BOTTOM_color = bottom_color;
  110. change = true;
  111. }
  112. background_color = GetColorSettings()->GetColor( LAYER_PCB_BACKGROUND );
  113. if( m_prevIconVal.previous_background_color != background_color )
  114. {
  115. m_prevIconVal.previous_background_color = background_color;
  116. change = true;
  117. }
  118. if( change || !LayerPairBitmap )
  119. {
  120. LayerPairBitmap = std::make_unique<wxBitmap>( 24, 24 );
  121. // Draw the icon, with colors according to the router's layer pair
  122. wxMemoryDC iconDC;
  123. iconDC.SelectObject( *LayerPairBitmap );
  124. wxBrush brush;
  125. wxPen pen;
  126. int buttonColor = -1;
  127. brush.SetStyle( wxBRUSHSTYLE_SOLID );
  128. brush.SetColour( background_color.WithAlpha(1.0).ToColour() );
  129. iconDC.SetBrush( brush );
  130. iconDC.DrawRectangle( 0, 0, BM_LAYERICON_SIZE, BM_LAYERICON_SIZE );
  131. for( ii = 0; ii < BM_LAYERICON_SIZE; ii++ )
  132. {
  133. for( jj = 0; jj < BM_LAYERICON_SIZE; jj++ )
  134. {
  135. if( s_BitmapLayerIcon[ii][jj] != buttonColor )
  136. {
  137. switch( s_BitmapLayerIcon[ii][jj] )
  138. {
  139. default:
  140. case 0: pen.SetColour( ICON_WHITE.ToColour() ); break;
  141. case 1: pen.SetColour( ICON_BLACK.ToColour() ); break;
  142. case 2: pen.SetColour( top_color.ToColour() ); break;
  143. case 3: pen.SetColour( bottom_color.ToColour() ); break;
  144. }
  145. buttonColor = s_BitmapLayerIcon[ii][jj];
  146. iconDC.SetPen( pen );
  147. }
  148. iconDC.DrawPoint( jj, ii );
  149. }
  150. }
  151. // Deselect the bitmap from the DC in order to delete the MemoryDC safely without
  152. // deleting the bitmap
  153. iconDC.SelectObject( wxNullBitmap );
  154. // Scale the bitmap
  155. const int scale = ( requested_scale <= 0 ) ? KiIconScale( this ) : requested_scale;
  156. wxImage image = LayerPairBitmap->ConvertToImage();
  157. // "NEAREST" causes less mixing of colors
  158. image.Rescale( scale * image.GetWidth() / 4, scale * image.GetHeight() / 4,
  159. wxIMAGE_QUALITY_NEAREST );
  160. LayerPairBitmap = std::make_unique<wxBitmap>( image );
  161. if( m_mainToolBar )
  162. {
  163. m_mainToolBar->SetToolBitmap( PCB_ACTIONS::selectLayerPair, *LayerPairBitmap );
  164. m_mainToolBar->Refresh();
  165. }
  166. }
  167. }
  168. void PCB_EDIT_FRAME::ReCreateHToolbar()
  169. {
  170. // Note:
  171. // To rebuild the aui toolbar, the more easy way is to clear ( calling m_mainToolBar.Clear() )
  172. // all wxAuiToolBarItems.
  173. // However the wxAuiToolBarItems are not the owners of controls managed by
  174. // them and therefore do not delete them
  175. // So we do not recreate them after clearing the tools.
  176. wxWindowUpdateLocker dummy( this );
  177. if( m_mainToolBar )
  178. {
  179. m_mainToolBar->ClearToolbar();
  180. }
  181. else
  182. {
  183. m_mainToolBar = new ACTION_TOOLBAR( this, ID_H_TOOLBAR, wxDefaultPosition, wxDefaultSize,
  184. KICAD_AUI_TB_STYLE | wxAUI_TB_HORZ_LAYOUT |
  185. wxAUI_TB_HORIZONTAL );
  186. m_mainToolBar->SetAuiManager( &m_auimgr );
  187. // The layer indicator is special, so we register a callback directly that will
  188. // regenerate the bitmap instead of using the conditions system.
  189. auto layerIndicatorUpdate =
  190. [this] ( wxUpdateUIEvent& )
  191. {
  192. PrepareLayerIndicator();
  193. };
  194. Bind( wxEVT_UPDATE_UI, layerIndicatorUpdate, PCB_ACTIONS::selectLayerPair.GetUIId() );
  195. }
  196. // Set up toolbar
  197. if( Kiface().IsSingle() )
  198. {
  199. m_mainToolBar->Add( ACTIONS::doNew );
  200. m_mainToolBar->Add( ACTIONS::open );
  201. }
  202. m_mainToolBar->Add( ACTIONS::save );
  203. m_mainToolBar->AddScaledSeparator( this );
  204. m_mainToolBar->Add( PCB_ACTIONS::boardSetup );
  205. m_mainToolBar->AddScaledSeparator( this );
  206. m_mainToolBar->Add( ACTIONS::pageSettings );
  207. m_mainToolBar->Add( ACTIONS::print );
  208. m_mainToolBar->Add( ACTIONS::plot );
  209. m_mainToolBar->AddScaledSeparator( this );
  210. m_mainToolBar->Add( ACTIONS::undo );
  211. m_mainToolBar->Add( ACTIONS::redo );
  212. m_mainToolBar->AddScaledSeparator( this );
  213. m_mainToolBar->Add( ACTIONS::find );
  214. m_mainToolBar->AddScaledSeparator( this );
  215. m_mainToolBar->Add( ACTIONS::zoomRedraw );
  216. m_mainToolBar->Add( ACTIONS::zoomInCenter );
  217. m_mainToolBar->Add( ACTIONS::zoomOutCenter );
  218. m_mainToolBar->Add( ACTIONS::zoomFitScreen );
  219. m_mainToolBar->Add( ACTIONS::zoomFitObjects );
  220. m_mainToolBar->Add( ACTIONS::zoomTool, ACTION_TOOLBAR::TOGGLE, ACTION_TOOLBAR::CANCEL );
  221. m_mainToolBar->AddScaledSeparator( this );
  222. m_mainToolBar->Add( PCB_ACTIONS::rotateCcw );
  223. m_mainToolBar->Add( PCB_ACTIONS::rotateCw );
  224. m_mainToolBar->Add( PCB_ACTIONS::group );
  225. m_mainToolBar->Add( PCB_ACTIONS::ungroup );
  226. m_mainToolBar->Add( PCB_ACTIONS::lock );
  227. m_mainToolBar->Add( PCB_ACTIONS::unlock );
  228. m_mainToolBar->AddScaledSeparator( this );
  229. m_mainToolBar->Add( ACTIONS::showFootprintEditor );
  230. m_mainToolBar->Add( ACTIONS::showFootprintBrowser );
  231. m_mainToolBar->AddScaledSeparator( this );
  232. if( !Kiface().IsSingle() )
  233. m_mainToolBar->Add( ACTIONS::updatePcbFromSchematic );
  234. else
  235. m_mainToolBar->Add( PCB_ACTIONS::importNetlist );
  236. m_mainToolBar->Add( PCB_ACTIONS::runDRC );
  237. m_mainToolBar->AddScaledSeparator( this );
  238. if( m_SelLayerBox == nullptr )
  239. {
  240. m_SelLayerBox = new PCB_LAYER_BOX_SELECTOR( m_mainToolBar, ID_TOOLBARH_PCB_SELECT_LAYER );
  241. m_SelLayerBox->SetBoardFrame( this );
  242. }
  243. ReCreateLayerBox( false );
  244. m_mainToolBar->AddControl( m_SelLayerBox );
  245. m_mainToolBar->Add( PCB_ACTIONS::selectLayerPair );
  246. PrepareLayerIndicator( true ); // Force rebuild of the bitmap with the active layer colors
  247. m_mainToolBar->AddScaledSeparator( this );
  248. m_mainToolBar->Add( PCB_ACTIONS::showEeschema );
  249. // Access to the scripting console
  250. if( SCRIPTING::IsWxAvailable() )
  251. {
  252. m_mainToolBar->AddScaledSeparator( this );
  253. m_mainToolBar->Add( PCB_ACTIONS::showPythonConsole, ACTION_TOOLBAR::TOGGLE );
  254. AddActionPluginTools();
  255. }
  256. // Go through and ensure the comboboxes are the correct size, since the strings in the
  257. // box could have changed widths.
  258. m_mainToolBar->UpdateControlWidth( ID_TOOLBARH_PCB_SELECT_LAYER );
  259. // after adding the buttons to the toolbar, must call Realize() to reflect the changes
  260. m_mainToolBar->KiRealize();
  261. }
  262. void PCB_EDIT_FRAME::ReCreateOptToolbar()
  263. {
  264. // Note:
  265. // To rebuild the aui toolbar, the more easy way is to clear ( calling m_mainToolBar.Clear() )
  266. // all wxAuiToolBarItems.
  267. // However the wxAuiToolBarItems are not the owners of controls managed by
  268. // them and therefore do not delete them
  269. // So we do not recreate them after clearing the tools.
  270. wxWindowUpdateLocker dummy( this );
  271. if( m_optionsToolBar )
  272. {
  273. m_optionsToolBar->ClearToolbar();
  274. }
  275. else
  276. {
  277. m_optionsToolBar = new ACTION_TOOLBAR( this, ID_OPT_TOOLBAR,
  278. wxDefaultPosition, wxDefaultSize,
  279. KICAD_AUI_TB_STYLE | wxAUI_TB_VERTICAL );
  280. m_optionsToolBar->SetAuiManager( &m_auimgr );
  281. }
  282. m_optionsToolBar->Add( ACTIONS::toggleGrid, ACTION_TOOLBAR::TOGGLE );
  283. m_optionsToolBar->Add( PCB_ACTIONS::togglePolarCoords, ACTION_TOOLBAR::TOGGLE );
  284. m_optionsToolBar->Add( ACTIONS::inchesUnits, ACTION_TOOLBAR::TOGGLE );
  285. m_optionsToolBar->Add( ACTIONS::milsUnits, ACTION_TOOLBAR::TOGGLE );
  286. m_optionsToolBar->Add( ACTIONS::millimetersUnits, ACTION_TOOLBAR::TOGGLE );
  287. m_optionsToolBar->Add( ACTIONS::toggleCursorStyle, ACTION_TOOLBAR::TOGGLE );
  288. m_optionsToolBar->AddScaledSeparator( this );
  289. m_optionsToolBar->Add( PCB_ACTIONS::toggleHV45Mode, ACTION_TOOLBAR::TOGGLE );
  290. m_optionsToolBar->AddScaledSeparator( this );
  291. m_optionsToolBar->Add( PCB_ACTIONS::showRatsnest, ACTION_TOOLBAR::TOGGLE );
  292. m_optionsToolBar->Add( PCB_ACTIONS::ratsnestLineMode, ACTION_TOOLBAR::TOGGLE );
  293. m_optionsToolBar->AddScaledSeparator( this );
  294. m_optionsToolBar->Add( ACTIONS::highContrastMode, ACTION_TOOLBAR::TOGGLE );
  295. m_optionsToolBar->Add( PCB_ACTIONS::toggleNetHighlight, ACTION_TOOLBAR::TOGGLE );
  296. m_optionsToolBar->AddScaledSeparator( this );
  297. m_optionsToolBar->Add( PCB_ACTIONS::zoneDisplayFilled, ACTION_TOOLBAR::TOGGLE );
  298. m_optionsToolBar->Add( PCB_ACTIONS::zoneDisplayOutline, ACTION_TOOLBAR::TOGGLE );
  299. if( ADVANCED_CFG::GetCfg().m_ExtraZoneDisplayModes )
  300. {
  301. m_optionsToolBar->Add( PCB_ACTIONS::zoneDisplayFractured, ACTION_TOOLBAR::TOGGLE );
  302. m_optionsToolBar->Add( PCB_ACTIONS::zoneDisplayTriangulated, ACTION_TOOLBAR::TOGGLE );
  303. }
  304. m_optionsToolBar->AddScaledSeparator( this );
  305. m_optionsToolBar->Add( PCB_ACTIONS::padDisplayMode, ACTION_TOOLBAR::TOGGLE );
  306. m_optionsToolBar->Add( PCB_ACTIONS::viaDisplayMode, ACTION_TOOLBAR::TOGGLE );
  307. m_optionsToolBar->Add( PCB_ACTIONS::trackDisplayMode, ACTION_TOOLBAR::TOGGLE );
  308. if( ADVANCED_CFG::GetCfg().m_DrawBoundingBoxes )
  309. m_optionsToolBar->Add( ACTIONS::toggleBoundingBoxes, ACTION_TOOLBAR::TOGGLE );
  310. // Tools to show/hide toolbars:
  311. m_optionsToolBar->AddScaledSeparator( this );
  312. m_optionsToolBar->Add( PCB_ACTIONS::showLayersManager, ACTION_TOOLBAR::TOGGLE );
  313. PCB_SELECTION_TOOL* selTool = m_toolManager->GetTool<PCB_SELECTION_TOOL>();
  314. std::unique_ptr<ACTION_MENU> gridMenu = std::make_unique<ACTION_MENU>( false, selTool );
  315. gridMenu->Add( ACTIONS::gridProperties );
  316. m_optionsToolBar->AddToolContextMenu( ACTIONS::toggleGrid, std::move( gridMenu ) );
  317. m_optionsToolBar->KiRealize();
  318. }
  319. void PCB_EDIT_FRAME::ReCreateVToolbar()
  320. {
  321. wxWindowUpdateLocker dummy( this );
  322. if( m_drawToolBar )
  323. {
  324. m_drawToolBar->ClearToolbar();
  325. }
  326. else
  327. {
  328. m_drawToolBar = new ACTION_TOOLBAR( this, ID_V_TOOLBAR, wxDefaultPosition, wxDefaultSize,
  329. KICAD_AUI_TB_STYLE | wxAUI_TB_VERTICAL );
  330. m_drawToolBar->SetAuiManager( &m_auimgr );
  331. }
  332. // Groups contained on this toolbar
  333. static ACTION_GROUP* dimensionGroup = nullptr;
  334. static ACTION_GROUP* originGroup = nullptr;
  335. static ACTION_GROUP* routingGroup = nullptr;
  336. static ACTION_GROUP* tuneGroup = nullptr;
  337. if( !dimensionGroup )
  338. {
  339. dimensionGroup = new ACTION_GROUP( "group.pcbDimensions",
  340. { &PCB_ACTIONS::drawAlignedDimension,
  341. &PCB_ACTIONS::drawOrthogonalDimension,
  342. &PCB_ACTIONS::drawCenterDimension,
  343. &PCB_ACTIONS::drawRadialDimension,
  344. &PCB_ACTIONS::drawLeader } );
  345. }
  346. if( !originGroup )
  347. {
  348. originGroup = new ACTION_GROUP( "group.pcbOrigins",
  349. { &PCB_ACTIONS::drillOrigin,
  350. &PCB_ACTIONS::gridSetOrigin } );
  351. }
  352. if( !routingGroup )
  353. {
  354. routingGroup = new ACTION_GROUP( "group.pcbRouting",
  355. { &PCB_ACTIONS::routeSingleTrack,
  356. &PCB_ACTIONS::routeDiffPair } );
  357. }
  358. if( !tuneGroup )
  359. {
  360. tuneGroup = new ACTION_GROUP( "group.pcbTune",
  361. { &PCB_ACTIONS::routerTuneSingleTrace,
  362. &PCB_ACTIONS::routerTuneDiffPair,
  363. &PCB_ACTIONS::routerTuneDiffPairSkew } );
  364. }
  365. m_drawToolBar->Add( ACTIONS::selectionTool, ACTION_TOOLBAR::TOGGLE );
  366. m_drawToolBar->Add( PCB_ACTIONS::localRatsnestTool, ACTION_TOOLBAR::TOGGLE );
  367. m_drawToolBar->AddScaledSeparator( this );
  368. m_drawToolBar->Add( PCB_ACTIONS::placeFootprint, ACTION_TOOLBAR::TOGGLE );
  369. m_drawToolBar->AddGroup( routingGroup, ACTION_TOOLBAR::TOGGLE );
  370. m_drawToolBar->AddGroup( tuneGroup, ACTION_TOOLBAR::TOGGLE );
  371. m_drawToolBar->Add( PCB_ACTIONS::drawVia, ACTION_TOOLBAR::TOGGLE );
  372. m_drawToolBar->Add( PCB_ACTIONS::drawZone, ACTION_TOOLBAR::TOGGLE );
  373. m_drawToolBar->Add( PCB_ACTIONS::drawRuleArea, ACTION_TOOLBAR::TOGGLE );
  374. m_drawToolBar->AddScaledSeparator( this );
  375. m_drawToolBar->Add( PCB_ACTIONS::drawLine, ACTION_TOOLBAR::TOGGLE );
  376. m_drawToolBar->Add( PCB_ACTIONS::drawArc, ACTION_TOOLBAR::TOGGLE );
  377. m_drawToolBar->Add( PCB_ACTIONS::drawRectangle, ACTION_TOOLBAR::TOGGLE );
  378. m_drawToolBar->Add( PCB_ACTIONS::drawCircle, ACTION_TOOLBAR::TOGGLE );
  379. m_drawToolBar->Add( PCB_ACTIONS::drawPolygon, ACTION_TOOLBAR::TOGGLE );
  380. m_drawToolBar->Add( PCB_ACTIONS::placeText, ACTION_TOOLBAR::TOGGLE );
  381. m_drawToolBar->Add( PCB_ACTIONS::drawTextBox, ACTION_TOOLBAR::TOGGLE );
  382. m_drawToolBar->AddGroup( dimensionGroup, ACTION_TOOLBAR::TOGGLE );
  383. m_drawToolBar->Add( ACTIONS::deleteTool, ACTION_TOOLBAR::TOGGLE );
  384. m_drawToolBar->AddScaledSeparator( this );
  385. m_drawToolBar->AddGroup( originGroup, ACTION_TOOLBAR::TOGGLE );
  386. m_drawToolBar->Add( ACTIONS::measureTool, ACTION_TOOLBAR::TOGGLE );
  387. PCB_SELECTION_TOOL* selTool = m_toolManager->GetTool<PCB_SELECTION_TOOL>();
  388. auto makeRouteMenu =
  389. [&]()
  390. {
  391. std::unique_ptr<ACTION_MENU> routeMenu =
  392. std::make_unique<ACTION_MENU>( false, selTool );
  393. routeMenu->Add( PCB_ACTIONS::routerHighlightMode, ACTION_MENU::CHECK );
  394. routeMenu->Add( PCB_ACTIONS::routerShoveMode, ACTION_MENU::CHECK );
  395. routeMenu->Add( PCB_ACTIONS::routerWalkaroundMode, ACTION_MENU::CHECK );
  396. routeMenu->AppendSeparator();
  397. routeMenu->Add( PCB_ACTIONS::routerSettingsDialog );
  398. return routeMenu;
  399. };
  400. m_drawToolBar->AddToolContextMenu( PCB_ACTIONS::routeSingleTrack, makeRouteMenu() );
  401. m_drawToolBar->AddToolContextMenu( PCB_ACTIONS::routeDiffPair, makeRouteMenu() );
  402. auto makeTuneMenu =
  403. [&]()
  404. {
  405. std::unique_ptr<ACTION_MENU> tuneMenu = std::make_unique<ACTION_MENU>( false, selTool );
  406. tuneMenu->Add( PCB_ACTIONS::lengthTunerSettingsDialog );
  407. return tuneMenu;
  408. };
  409. m_drawToolBar->AddToolContextMenu( PCB_ACTIONS::routerTuneSingleTrace, makeTuneMenu() );
  410. m_drawToolBar->AddToolContextMenu( PCB_ACTIONS::routerTuneDiffPair, makeTuneMenu() );
  411. m_drawToolBar->AddToolContextMenu( PCB_ACTIONS::routerTuneDiffPairSkew, makeTuneMenu() );
  412. std::unique_ptr<ACTION_MENU> zoneMenu = std::make_unique<ACTION_MENU>( false, selTool );
  413. zoneMenu->Add( PCB_ACTIONS::zoneFillAll );
  414. zoneMenu->Add( PCB_ACTIONS::zoneUnfillAll );
  415. m_drawToolBar->AddToolContextMenu( PCB_ACTIONS::drawZone, std::move( zoneMenu ) );
  416. std::unique_ptr<ACTION_MENU> lineMenu = std::make_unique<ACTION_MENU>( false, selTool );
  417. m_drawToolBar->AddToolContextMenu( PCB_ACTIONS::drawLine, std::move( lineMenu ) );
  418. m_drawToolBar->KiRealize();
  419. }
  420. void PCB_EDIT_FRAME::ReCreateAuxiliaryToolbar()
  421. {
  422. wxWindowUpdateLocker dummy( this );
  423. if( m_auxiliaryToolBar )
  424. {
  425. m_auxiliaryToolBar->ClearToolbar();
  426. }
  427. else
  428. {
  429. m_auxiliaryToolBar = new ACTION_TOOLBAR( this, ID_AUX_TOOLBAR, wxDefaultPosition,
  430. wxDefaultSize,
  431. KICAD_AUI_TB_STYLE | wxAUI_TB_HORZ_LAYOUT );
  432. m_auxiliaryToolBar->SetAuiManager( &m_auimgr );
  433. }
  434. /* Set up toolbar items */
  435. // Creates box to display and choose tracks widths:
  436. if( m_SelTrackWidthBox == nullptr )
  437. m_SelTrackWidthBox = new wxChoice( m_auxiliaryToolBar, ID_AUX_TOOLBAR_PCB_TRACK_WIDTH,
  438. wxDefaultPosition, wxDefaultSize, 0, nullptr );
  439. UpdateTrackWidthSelectBox( m_SelTrackWidthBox );
  440. m_auxiliaryToolBar->AddControl( m_SelTrackWidthBox );
  441. m_SelTrackWidthBox->SetToolTip( _( "Select the default width for new tracks. Note that this "
  442. "width can be overridden by the board minimum width, or by "
  443. "the width of an existing track if the 'Use Existing Track "
  444. "Width' feature is enabled." ) );
  445. m_auxiliaryToolBar->AddTool( ID_AUX_TOOLBAR_PCB_SELECT_AUTO_WIDTH, wxEmptyString,
  446. KiScaledBitmap( BITMAPS::auto_track_width, this ),
  447. _( "When routing from an existing track use its width instead "
  448. "of the current width setting" ),
  449. wxITEM_CHECK );
  450. m_auxiliaryToolBar->AddScaledSeparator( this );
  451. // Creates box to display and choose vias diameters:
  452. if( m_SelViaSizeBox == nullptr )
  453. m_SelViaSizeBox = new wxChoice( m_auxiliaryToolBar, ID_AUX_TOOLBAR_PCB_VIA_SIZE,
  454. wxDefaultPosition, wxDefaultSize, 0, nullptr );
  455. UpdateViaSizeSelectBox( m_SelViaSizeBox );
  456. m_auxiliaryToolBar->AddControl( m_SelViaSizeBox );
  457. // Add the box to display and select the current grid size:
  458. m_auxiliaryToolBar->AddScaledSeparator( this );
  459. if( m_gridSelectBox == nullptr )
  460. m_gridSelectBox = new wxChoice( m_auxiliaryToolBar, ID_ON_GRID_SELECT,
  461. wxDefaultPosition, wxDefaultSize, 0, nullptr );
  462. UpdateGridSelectBox();
  463. m_auxiliaryToolBar->AddControl( m_gridSelectBox );
  464. // Add the box to display and select the current Zoom
  465. m_auxiliaryToolBar->AddScaledSeparator( this );
  466. if( m_zoomSelectBox == nullptr )
  467. m_zoomSelectBox = new wxChoice( m_auxiliaryToolBar, ID_ON_ZOOM_SELECT,
  468. wxDefaultPosition, wxDefaultSize, 0, nullptr );
  469. UpdateZoomSelectBox();
  470. m_auxiliaryToolBar->AddControl( m_zoomSelectBox );
  471. // Go through and ensure the comboboxes are the correct size, since the strings in the
  472. // box could have changed widths.
  473. m_auxiliaryToolBar->UpdateControlWidth( ID_AUX_TOOLBAR_PCB_TRACK_WIDTH );
  474. m_auxiliaryToolBar->UpdateControlWidth( ID_AUX_TOOLBAR_PCB_VIA_SIZE );
  475. m_auxiliaryToolBar->UpdateControlWidth( ID_ON_ZOOM_SELECT );
  476. m_auxiliaryToolBar->UpdateControlWidth( ID_ON_GRID_SELECT );
  477. // after adding the buttons to the toolbar, must call Realize()
  478. m_auxiliaryToolBar->KiRealize();
  479. }
  480. void PCB_EDIT_FRAME::UpdateToolbarControlSizes()
  481. {
  482. if( m_mainToolBar )
  483. {
  484. // Update the item widths
  485. m_mainToolBar->UpdateControlWidth( ID_TOOLBARH_PCB_SELECT_LAYER );
  486. }
  487. if( m_auxiliaryToolBar )
  488. {
  489. // Update the item widths
  490. m_auxiliaryToolBar->UpdateControlWidth( ID_AUX_TOOLBAR_PCB_TRACK_WIDTH );
  491. m_auxiliaryToolBar->UpdateControlWidth( ID_AUX_TOOLBAR_PCB_VIA_SIZE );
  492. m_auxiliaryToolBar->UpdateControlWidth( ID_ON_ZOOM_SELECT );
  493. m_auxiliaryToolBar->UpdateControlWidth( ID_ON_GRID_SELECT );
  494. }
  495. }
  496. static wxString ComboBoxUnits( EDA_UNITS aUnits, double aValue, bool aIncludeLabel = true )
  497. {
  498. wxString text;
  499. const wxChar* format;
  500. switch( aUnits )
  501. {
  502. default:
  503. wxASSERT_MSG( false, wxT( "Invalid unit" ) );
  504. KI_FALLTHROUGH;
  505. case EDA_UNITS::UNSCALED: format = wxT( "%.0f" ); break;
  506. case EDA_UNITS::MILLIMETRES: format = wxT( "%.3f" ); break;
  507. case EDA_UNITS::MILS: format = wxT( "%.2f" ); break;
  508. case EDA_UNITS::INCHES: format = wxT( "%.5f" ); break;
  509. }
  510. text.Printf( format, To_User_Unit( aUnits, aValue ) );
  511. if( aIncludeLabel )
  512. text += GetAbbreviatedUnitsLabel( aUnits, EDA_DATA_TYPE::DISTANCE );
  513. return text;
  514. }
  515. void PCB_EDIT_FRAME::UpdateTrackWidthSelectBox( wxChoice* aTrackWidthSelectBox, bool aEdit )
  516. {
  517. if( aTrackWidthSelectBox == nullptr )
  518. return;
  519. EDA_UNITS primaryUnit;
  520. EDA_UNITS secondaryUnit;
  521. GetUnitPair( primaryUnit, secondaryUnit );
  522. wxString msg;
  523. aTrackWidthSelectBox->Clear();
  524. aTrackWidthSelectBox->Append( _( "Track: use netclass width" ) );
  525. for( unsigned ii = 1; ii < GetDesignSettings().m_TrackWidthList.size(); ii++ )
  526. {
  527. int size = GetDesignSettings().m_TrackWidthList[ii];
  528. msg.Printf( _( "Track: %s (%s)" ), ComboBoxUnits( primaryUnit, size ),
  529. ComboBoxUnits( secondaryUnit, size ) );
  530. aTrackWidthSelectBox->Append( msg );
  531. }
  532. if( aEdit )
  533. {
  534. aTrackWidthSelectBox->Append( wxT( "---" ) );
  535. aTrackWidthSelectBox->Append( _( "Edit Pre-defined Sizes..." ) );
  536. }
  537. if( GetDesignSettings().GetTrackWidthIndex() >= GetDesignSettings().m_TrackWidthList.size() )
  538. GetDesignSettings().SetTrackWidthIndex( 0 );
  539. aTrackWidthSelectBox->SetSelection( GetDesignSettings().GetTrackWidthIndex() );
  540. }
  541. void PCB_EDIT_FRAME::UpdateViaSizeSelectBox( wxChoice* aViaSizeSelectBox, bool aEdit )
  542. {
  543. if( aViaSizeSelectBox == nullptr )
  544. return;
  545. aViaSizeSelectBox->Clear();
  546. COMMON_TOOLS* cmnTool = m_toolManager->GetTool<COMMON_TOOLS>();
  547. EDA_UNITS primaryUnit = GetUserUnits();
  548. EDA_UNITS secondaryUnit = EDA_UNITS::MILS;
  549. if( EDA_UNIT_UTILS::IsImperialUnit( primaryUnit ) )
  550. {
  551. if( cmnTool )
  552. secondaryUnit = cmnTool->GetLastMetricUnits();
  553. else
  554. secondaryUnit = EDA_UNITS::MILLIMETRES;
  555. }
  556. else
  557. {
  558. if( cmnTool )
  559. secondaryUnit = cmnTool->GetLastImperialUnits();
  560. else
  561. secondaryUnit = EDA_UNITS::MILS;
  562. }
  563. aViaSizeSelectBox->Append( _( "Via: use netclass sizes" ) );
  564. for( unsigned ii = 1; ii < GetDesignSettings().m_ViasDimensionsList.size(); ii++ )
  565. {
  566. VIA_DIMENSION viaDimension = GetDesignSettings().m_ViasDimensionsList[ii];
  567. wxString msg, priStr, secStr;
  568. double diam = viaDimension.m_Diameter;
  569. double hole = viaDimension.m_Drill;
  570. if( hole > 0 )
  571. {
  572. priStr = ComboBoxUnits( primaryUnit, diam, false ) + wxT( " / " )
  573. + ComboBoxUnits( primaryUnit, hole, true );
  574. secStr = ComboBoxUnits( secondaryUnit, diam, false ) + wxT( " / " )
  575. + ComboBoxUnits( secondaryUnit, hole, true );
  576. }
  577. else
  578. {
  579. priStr = ComboBoxUnits( primaryUnit, diam, true );
  580. secStr = ComboBoxUnits( secondaryUnit, diam, true );
  581. }
  582. msg.Printf( _( "Via: %s (%s)" ), priStr, secStr );
  583. aViaSizeSelectBox->Append( msg );
  584. }
  585. if( aEdit )
  586. {
  587. aViaSizeSelectBox->Append( wxT( "---" ) );
  588. aViaSizeSelectBox->Append( _( "Edit Pre-defined Sizes..." ) );
  589. }
  590. if( GetDesignSettings().GetViaSizeIndex() >= GetDesignSettings().m_ViasDimensionsList.size() )
  591. GetDesignSettings().SetViaSizeIndex( 0 );
  592. aViaSizeSelectBox->SetSelection( GetDesignSettings().GetViaSizeIndex() );
  593. }
  594. void PCB_EDIT_FRAME::ReCreateLayerBox( bool aForceResizeToolbar )
  595. {
  596. if( m_SelLayerBox == nullptr || m_mainToolBar == nullptr )
  597. return;
  598. m_SelLayerBox->SetToolTip( _( "+/- to switch" ) );
  599. m_SelLayerBox->Resync();
  600. if( aForceResizeToolbar )
  601. UpdateToolbarControlSizes();
  602. }
  603. void PCB_EDIT_FRAME::ToggleLayersManager()
  604. {
  605. PCBNEW_SETTINGS* settings = GetPcbNewSettings();
  606. wxAuiPaneInfo& layersManager = m_auimgr.GetPane( "LayersManager" );
  607. wxAuiPaneInfo& selectionFilter = m_auimgr.GetPane( "SelectionFilter" );
  608. // show auxiliary Vertical layers and visibility manager toolbar
  609. m_show_layer_manager_tools = !m_show_layer_manager_tools;
  610. layersManager.Show( m_show_layer_manager_tools );
  611. selectionFilter.Show( m_show_layer_manager_tools );
  612. if( m_show_layer_manager_tools )
  613. {
  614. SetAuiPaneSize( m_auimgr, layersManager, settings->m_AuiPanels.right_panel_width, -1 );
  615. }
  616. else
  617. {
  618. settings->m_AuiPanels.right_panel_width = m_appearancePanel->GetSize().x;
  619. m_auimgr.Update();
  620. }
  621. }
  622. void PCB_EDIT_FRAME::OnUpdateSelectTrackWidth( wxUpdateUIEvent& aEvent )
  623. {
  624. if( aEvent.GetId() == ID_AUX_TOOLBAR_PCB_TRACK_WIDTH )
  625. {
  626. BOARD_DESIGN_SETTINGS& bds = GetDesignSettings();
  627. int sel;
  628. if( bds.UseCustomTrackViaSize() )
  629. sel = wxNOT_FOUND;
  630. else
  631. sel = bds.GetTrackWidthIndex();
  632. if( m_SelTrackWidthBox->GetSelection() != sel )
  633. m_SelTrackWidthBox->SetSelection( sel );
  634. }
  635. }
  636. void PCB_EDIT_FRAME::OnUpdateSelectViaSize( wxUpdateUIEvent& aEvent )
  637. {
  638. if( aEvent.GetId() == ID_AUX_TOOLBAR_PCB_VIA_SIZE )
  639. {
  640. BOARD_DESIGN_SETTINGS& bds = GetDesignSettings();
  641. int sel = 0;
  642. if( bds.UseCustomTrackViaSize() )
  643. sel = wxNOT_FOUND;
  644. else
  645. sel = bds.GetViaSizeIndex();
  646. if( m_SelViaSizeBox->GetSelection() != sel )
  647. m_SelViaSizeBox->SetSelection( sel );
  648. }
  649. }
  650. void PCB_EDIT_FRAME::OnUpdateSelectAutoWidth( wxUpdateUIEvent& aEvent )
  651. {
  652. BOARD_DESIGN_SETTINGS& bds = GetDesignSettings();
  653. aEvent.Check( bds.m_UseConnectedTrackWidth );
  654. }
  655. void PCB_EDIT_FRAME::OnUpdateLayerSelectBox( wxUpdateUIEvent& aEvent )
  656. {
  657. if( m_SelLayerBox->GetLayerSelection() != GetActiveLayer() )
  658. m_SelLayerBox->SetLayerSelection( GetActiveLayer() );
  659. }