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.

516 lines
18 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr
  5. * Copyright (C) 2013 Wayne Stambaugh <stambaughw@gmail.com>
  6. * Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
  7. *
  8. * This program is free software: you can redistribute it and/or modify it
  9. * under the terms of the GNU General Public License as published by the
  10. * Free Software Foundation, either version 3 of the License, or (at your
  11. * option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful, but
  14. * WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License along
  19. * with this program. If not, see <http://www.gnu.org/licenses/>.
  20. */
  21. #include <wx/wupdlock.h>
  22. #include <wx/stattext.h>
  23. #include <gerbview.h>
  24. #include <gerbview_frame.h>
  25. #include <bitmaps.h>
  26. #include <gerbview_id.h>
  27. #include <gerber_file_image.h>
  28. #include <gerber_file_image_list.h>
  29. #include <string_utils.h>
  30. #include <tool/actions.h>
  31. #include <tool/action_toolbar.h>
  32. #include <tools/gerbview_actions.h>
  33. #include "widgets/gbr_layer_box_selector.h"
  34. #include "widgets/dcode_selection_box.h"
  35. void GERBVIEW_FRAME::ReCreateHToolbar()
  36. {
  37. // Note:
  38. // To rebuild the aui toolbar, the more easy way is to clear ( calling m_mainToolBar.Clear() )
  39. // all wxAuiToolBarItems.
  40. // However the wxAuiToolBarItems are not the owners of controls managed by
  41. // them ( m_TextInfo and m_SelLayerBox ), and therefore do not delete them
  42. // So we do not recreate them after clearing the tools.
  43. if( m_mainToolBar )
  44. {
  45. m_mainToolBar->ClearToolbar();
  46. }
  47. else
  48. {
  49. m_mainToolBar = new ACTION_TOOLBAR( this, ID_H_TOOLBAR, wxDefaultPosition, wxDefaultSize,
  50. KICAD_AUI_TB_STYLE | wxAUI_TB_HORZ_LAYOUT |
  51. wxAUI_TB_HORIZONTAL );
  52. m_mainToolBar->SetAuiManager( &m_auimgr );
  53. }
  54. // Set up toolbar
  55. m_mainToolBar->Add( GERBVIEW_ACTIONS::clearAllLayers );
  56. m_mainToolBar->Add( GERBVIEW_ACTIONS::reloadAllLayers );
  57. m_mainToolBar->Add( GERBVIEW_ACTIONS::openAutodetected );
  58. m_mainToolBar->Add( GERBVIEW_ACTIONS::openGerber );
  59. m_mainToolBar->Add( GERBVIEW_ACTIONS::openDrillFile );
  60. m_mainToolBar->AddScaledSeparator( this );
  61. m_mainToolBar->Add( ACTIONS::print );
  62. m_mainToolBar->AddScaledSeparator( this );
  63. m_mainToolBar->Add( ACTIONS::zoomRedraw );
  64. m_mainToolBar->Add( ACTIONS::zoomInCenter );
  65. m_mainToolBar->Add( ACTIONS::zoomOutCenter );
  66. m_mainToolBar->Add( ACTIONS::zoomFitScreen );
  67. m_mainToolBar->Add( ACTIONS::zoomTool, ACTION_TOOLBAR::TOGGLE, ACTION_TOOLBAR::CANCEL );
  68. m_mainToolBar->AddScaledSeparator( this );
  69. if( !m_SelLayerBox )
  70. {
  71. m_SelLayerBox = new GBR_LAYER_BOX_SELECTOR( m_mainToolBar,
  72. ID_TOOLBARH_GERBVIEW_SELECT_ACTIVE_LAYER,
  73. wxDefaultPosition, wxDefaultSize, 0, nullptr );
  74. }
  75. m_SelLayerBox->Resync();
  76. m_mainToolBar->AddControl( m_SelLayerBox );
  77. if( !m_TextInfo )
  78. {
  79. m_TextInfo = new wxTextCtrl( m_mainToolBar, ID_TOOLBARH_GERBER_DATA_TEXT_BOX, wxEmptyString,
  80. wxDefaultPosition, wxDefaultSize, wxTE_READONLY );
  81. }
  82. m_mainToolBar->AddControl( m_TextInfo );
  83. m_mainToolBar->UpdateControlWidth( ID_TOOLBARH_GERBVIEW_SELECT_ACTIVE_LAYER );
  84. m_mainToolBar->UpdateControlWidth( ID_TOOLBARH_GERBER_DATA_TEXT_BOX );
  85. // after adding the buttons to the toolbar, must call Realize() to reflect the changes
  86. m_mainToolBar->KiRealize();
  87. }
  88. void GERBVIEW_FRAME::ReCreateAuxiliaryToolbar()
  89. {
  90. wxWindowUpdateLocker dummy( this );
  91. if( m_auxiliaryToolBar )
  92. {
  93. m_auxiliaryToolBar->ClearToolbar();
  94. }
  95. else
  96. {
  97. m_auxiliaryToolBar = new ACTION_TOOLBAR( this, ID_AUX_TOOLBAR, wxDefaultPosition,
  98. wxDefaultSize,
  99. KICAD_AUI_TB_STYLE | wxAUI_TB_HORZ_LAYOUT );
  100. m_auxiliaryToolBar->SetAuiManager( &m_auimgr );
  101. }
  102. // Creates box to display and choose components:
  103. // (note, when the m_auxiliaryToolBar is recreated, tools are deleted, but controls
  104. // are not deleted: they are just no longer managed by the toolbar
  105. if( !m_SelComponentBox )
  106. m_SelComponentBox = new wxChoice( m_auxiliaryToolBar, ID_GBR_AUX_TOOLBAR_PCB_CMP_CHOICE );
  107. if( !m_cmpText )
  108. m_cmpText = new wxStaticText( m_auxiliaryToolBar, wxID_ANY, _( "Cmp:" ) + wxS( " " ) );
  109. m_SelComponentBox->SetToolTip( _("Highlight items belonging to this component") );
  110. m_cmpText->SetLabel( _( "Cmp:" ) + wxS( " " ) ); // can change when changing the language
  111. m_auxiliaryToolBar->AddControl( m_cmpText );
  112. m_auxiliaryToolBar->AddControl( m_SelComponentBox );
  113. m_auxiliaryToolBar->AddSpacer( 5 );
  114. // Creates choice box to display net names and highlight selected:
  115. if( !m_SelNetnameBox )
  116. m_SelNetnameBox = new wxChoice( m_auxiliaryToolBar, ID_GBR_AUX_TOOLBAR_PCB_NET_CHOICE );
  117. if( !m_netText )
  118. m_netText = new wxStaticText( m_auxiliaryToolBar, wxID_ANY, _( "Net:" ) );
  119. m_SelNetnameBox->SetToolTip( _("Highlight items belonging to this net") );
  120. m_netText->SetLabel( _( "Net:" ) ); // can change when changing the language
  121. m_auxiliaryToolBar->AddControl( m_netText );
  122. m_auxiliaryToolBar->AddControl( m_SelNetnameBox );
  123. m_auxiliaryToolBar->AddSpacer( 5 );
  124. // Creates choice box to display aperture attributes and highlight selected:
  125. if( !m_SelAperAttributesBox )
  126. {
  127. m_SelAperAttributesBox = new wxChoice( m_auxiliaryToolBar,
  128. ID_GBR_AUX_TOOLBAR_PCB_APERATTRIBUTES_CHOICE );
  129. }
  130. if( !m_apertText )
  131. m_apertText = new wxStaticText( m_auxiliaryToolBar, wxID_ANY, _( "Attr:" ) );
  132. m_SelAperAttributesBox->SetToolTip( _( "Highlight items with this aperture attribute" ) );
  133. m_apertText->SetLabel( _( "Attr:" ) ); // can change when changing the language
  134. m_auxiliaryToolBar->AddControl( m_apertText );
  135. m_auxiliaryToolBar->AddControl( m_SelAperAttributesBox );
  136. m_auxiliaryToolBar->AddSpacer( 5 );
  137. if( !m_DCodeSelector )
  138. {
  139. m_DCodeSelector = new DCODE_SELECTION_BOX( m_auxiliaryToolBar,
  140. ID_TOOLBARH_GERBER_SELECT_ACTIVE_DCODE,
  141. wxDefaultPosition, wxSize( 150, -1 ) );
  142. }
  143. if( !m_dcodeText )
  144. m_dcodeText = new wxStaticText( m_auxiliaryToolBar, wxID_ANY, _( "DCode:" ) );
  145. m_dcodeText->SetLabel( _( "DCode:" ) );
  146. m_auxiliaryToolBar->AddControl( m_dcodeText );
  147. m_auxiliaryToolBar->AddControl( m_DCodeSelector );
  148. if( !m_gridSelectBox )
  149. {
  150. m_gridSelectBox = new wxChoice( m_auxiliaryToolBar, ID_ON_GRID_SELECT, wxDefaultPosition,
  151. wxDefaultSize, 0, nullptr );
  152. }
  153. m_auxiliaryToolBar->AddScaledSeparator( this );
  154. m_auxiliaryToolBar->AddControl( m_gridSelectBox );
  155. if( !m_zoomSelectBox )
  156. {
  157. m_zoomSelectBox = new wxChoice( m_auxiliaryToolBar, ID_ON_ZOOM_SELECT, wxDefaultPosition,
  158. wxDefaultSize, 0, nullptr );
  159. }
  160. m_auxiliaryToolBar->AddScaledSeparator( this );
  161. m_auxiliaryToolBar->AddControl( m_zoomSelectBox );
  162. updateComponentListSelectBox();
  163. updateNetnameListSelectBox();
  164. updateAperAttributesSelectBox();
  165. updateDCodeSelectBox();
  166. UpdateGridSelectBox();
  167. UpdateZoomSelectBox();
  168. // Go through and ensure the comboboxes are the correct size, since the strings in the
  169. // box could have changed widths.
  170. m_auxiliaryToolBar->UpdateControlWidth( ID_GBR_AUX_TOOLBAR_PCB_CMP_CHOICE );
  171. m_auxiliaryToolBar->UpdateControlWidth( ID_GBR_AUX_TOOLBAR_PCB_NET_CHOICE );
  172. m_auxiliaryToolBar->UpdateControlWidth( ID_GBR_AUX_TOOLBAR_PCB_APERATTRIBUTES_CHOICE );
  173. m_auxiliaryToolBar->UpdateControlWidth( ID_ON_GRID_SELECT );
  174. m_auxiliaryToolBar->UpdateControlWidth( ID_ON_ZOOM_SELECT );
  175. // after adding the buttons to the toolbar, must call Realize()
  176. m_auxiliaryToolBar->KiRealize();
  177. }
  178. void GERBVIEW_FRAME::ReCreateVToolbar()
  179. {
  180. // This toolbar isn't used currently
  181. }
  182. void GERBVIEW_FRAME::ReCreateOptToolbar()
  183. {
  184. if( m_optionsToolBar )
  185. {
  186. m_optionsToolBar->ClearToolbar();
  187. }
  188. else
  189. {
  190. m_optionsToolBar = new ACTION_TOOLBAR( this, ID_OPT_TOOLBAR, wxDefaultPosition,
  191. wxDefaultSize,
  192. KICAD_AUI_TB_STYLE | wxAUI_TB_VERTICAL );
  193. m_optionsToolBar->SetAuiManager( &m_auimgr );
  194. }
  195. // TODO: these can be moved to the 'proper' vertical toolbar if and when there are
  196. // actual tools to put there. That, or I'll get around to implementing configurable
  197. // toolbars.
  198. m_optionsToolBar->Add( ACTIONS::selectionTool, ACTION_TOOLBAR::TOGGLE );
  199. m_optionsToolBar->Add( ACTIONS::measureTool, ACTION_TOOLBAR::TOGGLE );
  200. m_optionsToolBar->AddScaledSeparator( this );
  201. m_optionsToolBar->Add( ACTIONS::toggleGrid, ACTION_TOOLBAR::TOGGLE );
  202. m_optionsToolBar->Add( ACTIONS::togglePolarCoords, ACTION_TOOLBAR::TOGGLE );
  203. m_optionsToolBar->Add( ACTIONS::inchesUnits, ACTION_TOOLBAR::TOGGLE );
  204. m_optionsToolBar->Add( ACTIONS::milsUnits, ACTION_TOOLBAR::TOGGLE );
  205. m_optionsToolBar->Add( ACTIONS::millimetersUnits, ACTION_TOOLBAR::TOGGLE );
  206. m_optionsToolBar->Add( ACTIONS::toggleCursorStyle, ACTION_TOOLBAR::TOGGLE );
  207. m_optionsToolBar->AddScaledSeparator( this );
  208. m_optionsToolBar->Add( GERBVIEW_ACTIONS::flashedDisplayOutlines, ACTION_TOOLBAR::TOGGLE );
  209. m_optionsToolBar->Add( GERBVIEW_ACTIONS::linesDisplayOutlines, ACTION_TOOLBAR::TOGGLE );
  210. m_optionsToolBar->Add( GERBVIEW_ACTIONS::polygonsDisplayOutlines, ACTION_TOOLBAR::TOGGLE );
  211. m_optionsToolBar->Add( GERBVIEW_ACTIONS::negativeObjectDisplay, ACTION_TOOLBAR::TOGGLE );
  212. m_optionsToolBar->Add( GERBVIEW_ACTIONS::dcodeDisplay, ACTION_TOOLBAR::TOGGLE );
  213. m_optionsToolBar->AddScaledSeparator( this );
  214. m_optionsToolBar->Add( GERBVIEW_ACTIONS::toggleDiffMode, ACTION_TOOLBAR::TOGGLE );
  215. m_optionsToolBar->Add( GERBVIEW_ACTIONS::toggleXORMode, ACTION_TOOLBAR::TOGGLE );
  216. m_optionsToolBar->Add( ACTIONS::highContrastMode, ACTION_TOOLBAR::TOGGLE );
  217. m_optionsToolBar->Add( GERBVIEW_ACTIONS::flipGerberView, ACTION_TOOLBAR::TOGGLE );
  218. m_optionsToolBar->AddScaledSeparator( this );
  219. m_optionsToolBar->Add( GERBVIEW_ACTIONS::toggleLayerManager, ACTION_TOOLBAR::TOGGLE );
  220. m_optionsToolBar->KiRealize();
  221. }
  222. void GERBVIEW_FRAME::UpdateToolbarControlSizes()
  223. {
  224. if( m_mainToolBar )
  225. {
  226. // Update the item widths
  227. m_mainToolBar->UpdateControlWidth( ID_TOOLBARH_GERBVIEW_SELECT_ACTIVE_LAYER );
  228. m_mainToolBar->UpdateControlWidth( ID_TOOLBARH_GERBER_DATA_TEXT_BOX );
  229. }
  230. if( m_auxiliaryToolBar )
  231. {
  232. // Update the item widths
  233. m_auxiliaryToolBar->UpdateControlWidth( ID_GBR_AUX_TOOLBAR_PCB_CMP_CHOICE );
  234. m_auxiliaryToolBar->UpdateControlWidth( ID_GBR_AUX_TOOLBAR_PCB_NET_CHOICE );
  235. m_auxiliaryToolBar->UpdateControlWidth( ID_GBR_AUX_TOOLBAR_PCB_APERATTRIBUTES_CHOICE );
  236. m_auxiliaryToolBar->UpdateControlWidth( ID_ON_GRID_SELECT );
  237. m_auxiliaryToolBar->UpdateControlWidth( ID_ON_ZOOM_SELECT );
  238. }
  239. }
  240. #define NO_SELECTION_STRING _("<No selection>")
  241. void GERBVIEW_FRAME::updateDCodeSelectBox()
  242. {
  243. m_DCodeSelector->Clear();
  244. // Add an empty string to deselect net highlight
  245. m_DCodeSelector->Append( NO_SELECTION_STRING );
  246. int layer = GetActiveLayer();
  247. GERBER_FILE_IMAGE* gerber = GetGbrImage( layer );
  248. if( !gerber || gerber->GetDcodesCount() == 0 )
  249. {
  250. if( m_DCodeSelector->GetSelection() != 0 )
  251. m_DCodeSelector->SetSelection( 0 );
  252. return;
  253. }
  254. // Build the aperture list of the current layer, and add it to the combo box:
  255. wxArrayString dcode_list;
  256. wxString msg;
  257. double scale = 1.0;
  258. wxString units;
  259. switch( GetUserUnits() )
  260. {
  261. case EDA_UNITS::MILLIMETRES:
  262. scale = gerbIUScale.IU_PER_MM;
  263. units = wxT( "mm" );
  264. break;
  265. case EDA_UNITS::INCHES:
  266. scale = gerbIUScale.IU_PER_MILS * 1000;
  267. units = wxT( "in" );
  268. break;
  269. case EDA_UNITS::MILS:
  270. scale = gerbIUScale.IU_PER_MILS;
  271. units = wxT( "mil" );
  272. break;
  273. default:
  274. wxASSERT_MSG( false, wxT( "Invalid units" ) );
  275. }
  276. for( int ii = 0; ii < TOOLS_MAX_COUNT; ii++ )
  277. {
  278. D_CODE* dcode = gerber->GetDCODE( ii + FIRST_DCODE );
  279. if( dcode == nullptr )
  280. continue;
  281. if( !dcode->m_InUse && !dcode->m_Defined )
  282. continue;
  283. msg.Printf( wxT( "tool %d [%.3fx%.3f %s] %s" ),
  284. dcode->m_Num_Dcode,
  285. dcode->m_Size.x / scale, dcode->m_Size.y / scale,
  286. units,
  287. D_CODE::ShowApertureType( dcode->m_Shape ) );
  288. if( !dcode->m_AperFunction.IsEmpty() )
  289. msg << wxT( ", " ) << dcode->m_AperFunction;
  290. dcode_list.Add( msg );
  291. }
  292. m_DCodeSelector->AppendDCodeList( dcode_list );
  293. if( dcode_list.size() > 1 )
  294. {
  295. wxSize size = m_DCodeSelector->GetBestSize();
  296. size.x = std::max( size.x, 100 );
  297. m_DCodeSelector->SetMinSize( size );
  298. m_auimgr.Update();
  299. }
  300. }
  301. void GERBVIEW_FRAME::updateComponentListSelectBox()
  302. {
  303. m_SelComponentBox->Clear();
  304. // Build the full list of component names from the partial lists stored in each file image
  305. std::map<wxString, int> full_list;
  306. for( unsigned layer = 0; layer < GetImagesList()->ImagesMaxCount(); ++layer )
  307. {
  308. GERBER_FILE_IMAGE* gerber = GetImagesList()->GetGbrImage( layer );
  309. if( gerber == nullptr ) // Graphic layer not yet used
  310. continue;
  311. full_list.insert( gerber->m_ComponentsList.begin(), gerber->m_ComponentsList.end() );
  312. }
  313. // Add an empty string to deselect net highlight
  314. m_SelComponentBox->Append( NO_SELECTION_STRING );
  315. // Now copy the list to the choice box
  316. for( const std::pair<const wxString, int>& entry : full_list )
  317. m_SelComponentBox->Append( entry.first );
  318. m_SelComponentBox->SetSelection( 0 );
  319. }
  320. void GERBVIEW_FRAME::updateNetnameListSelectBox()
  321. {
  322. m_SelNetnameBox->Clear();
  323. // Build the full list of netnames from the partial lists stored in each file image
  324. std::map<wxString, int> full_list;
  325. for( unsigned layer = 0; layer < GetImagesList()->ImagesMaxCount(); ++layer )
  326. {
  327. GERBER_FILE_IMAGE* gerber = GetImagesList()->GetGbrImage( layer );
  328. if( gerber == nullptr ) // Graphic layer not yet used
  329. continue;
  330. full_list.insert( gerber->m_NetnamesList.begin(), gerber->m_NetnamesList.end() );
  331. }
  332. // Add an empty string to deselect net highlight
  333. m_SelNetnameBox->Append( NO_SELECTION_STRING );
  334. // Now copy the list to the choice box
  335. for( const std::pair<const wxString, int>& entry : full_list )
  336. m_SelNetnameBox->Append( UnescapeString( entry.first ) );
  337. m_SelNetnameBox->SetSelection( 0 );
  338. }
  339. void GERBVIEW_FRAME::updateAperAttributesSelectBox()
  340. {
  341. m_SelAperAttributesBox->Clear();
  342. // Build the full list of netnames from the partial lists stored in each file image
  343. std::map<wxString, int> full_list;
  344. for( unsigned layer = 0; layer < GetImagesList()->ImagesMaxCount(); ++layer )
  345. {
  346. GERBER_FILE_IMAGE* gerber = GetImagesList()->GetGbrImage( layer );
  347. if( gerber == nullptr ) // Graphic layer not yet used
  348. continue;
  349. if( gerber->GetDcodesCount() == 0 )
  350. continue;
  351. for( int ii = 0; ii < TOOLS_MAX_COUNT; ii++ )
  352. {
  353. D_CODE* aperture = gerber->GetDCODE( ii + FIRST_DCODE );
  354. if( aperture == nullptr )
  355. continue;
  356. if( !aperture->m_InUse && !aperture->m_Defined )
  357. continue;
  358. if( !aperture->m_AperFunction.IsEmpty() )
  359. full_list.insert( std::make_pair( aperture->m_AperFunction, 0 ) );
  360. }
  361. }
  362. // Add an empty string to deselect net highlight
  363. m_SelAperAttributesBox->Append( NO_SELECTION_STRING );
  364. // Now copy the list to the choice box
  365. for( const std::pair<const wxString, int>& entry : full_list )
  366. m_SelAperAttributesBox->Append( entry.first );
  367. m_SelAperAttributesBox->SetSelection( 0 );
  368. }
  369. void GERBVIEW_FRAME::OnUpdateDrawMode( wxUpdateUIEvent& aEvent )
  370. {
  371. switch( aEvent.GetId() )
  372. {
  373. case ID_TB_OPTIONS_SHOW_GBR_MODE_0: aEvent.Check( GetDisplayMode() == 0 ); break;
  374. case ID_TB_OPTIONS_SHOW_GBR_MODE_1: aEvent.Check( GetDisplayMode() == 1 ); break;
  375. case ID_TB_OPTIONS_SHOW_GBR_MODE_2: aEvent.Check( GetDisplayMode() == 2 ); break;
  376. default: break;
  377. }
  378. }
  379. void GERBVIEW_FRAME::OnUpdateSelectDCode( wxUpdateUIEvent& aEvent )
  380. {
  381. if( !m_DCodeSelector )
  382. return;
  383. int layer = GetActiveLayer();
  384. GERBER_FILE_IMAGE* gerber = GetGbrImage( layer );
  385. int selected = gerber ? gerber->m_Selected_Tool : 0;
  386. aEvent.Enable( gerber != nullptr );
  387. if( m_DCodeSelector->GetSelectedDCodeId() != selected )
  388. {
  389. m_DCodeSelector->SetDCodeSelection( selected );
  390. // Be sure the selection can be made. If no, set to
  391. // a correct value
  392. if( gerber )
  393. gerber->m_Selected_Tool = m_DCodeSelector->GetSelectedDCodeId();
  394. }
  395. }
  396. void GERBVIEW_FRAME::OnUpdateLayerSelectBox( wxUpdateUIEvent& aEvent )
  397. {
  398. if( m_SelLayerBox->GetCount() )
  399. {
  400. if( m_SelLayerBox->GetSelection() != GetActiveLayer() )
  401. m_SelLayerBox->SetSelection( GetActiveLayer() );
  402. }
  403. }