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.

481 lines
17 KiB

8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months 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 The 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. #include <toolbars_gerber.h>
  36. std::optional<TOOLBAR_CONFIGURATION> GERBVIEW_TOOLBAR_SETTINGS::DefaultToolbarConfig( TOOLBAR_LOC aToolbar )
  37. {
  38. TOOLBAR_CONFIGURATION config;
  39. // clang-format off
  40. switch( aToolbar )
  41. {
  42. // No right toolbar
  43. case TOOLBAR_LOC::RIGHT:
  44. return std::nullopt;
  45. case TOOLBAR_LOC::LEFT:
  46. config.AppendAction( ACTIONS::selectionTool )
  47. .AppendAction( ACTIONS::measureTool );
  48. config.AppendSeparator()
  49. .AppendAction( ACTIONS::toggleGrid )
  50. .AppendAction( ACTIONS::togglePolarCoords )
  51. .AppendGroup( TOOLBAR_GROUP_CONFIG( _( "Units" ) )
  52. .AddAction( ACTIONS::millimetersUnits )
  53. .AddAction( ACTIONS::inchesUnits )
  54. .AddAction( ACTIONS::milsUnits ) )
  55. .AppendGroup( TOOLBAR_GROUP_CONFIG( _( "Crosshair modes" ) )
  56. .AddAction( ACTIONS::cursorSmallCrosshairs )
  57. .AddAction( ACTIONS::cursorFullCrosshairs )
  58. .AddAction( ACTIONS::cursor45Crosshairs ) );
  59. config.AppendSeparator()
  60. .AppendAction( GERBVIEW_ACTIONS::flashedDisplayOutlines )
  61. .AppendAction( GERBVIEW_ACTIONS::linesDisplayOutlines )
  62. .AppendAction( GERBVIEW_ACTIONS::polygonsDisplayOutlines )
  63. .AppendAction( GERBVIEW_ACTIONS::negativeObjectDisplay )
  64. .AppendAction( GERBVIEW_ACTIONS::dcodeDisplay );
  65. config.AppendSeparator()
  66. .AppendAction( GERBVIEW_ACTIONS::toggleForceOpacityMode )
  67. .AppendAction( GERBVIEW_ACTIONS::toggleXORMode )
  68. .AppendAction( ACTIONS::highContrastMode )
  69. .AppendAction( GERBVIEW_ACTIONS::flipGerberView );
  70. config.AppendSeparator()
  71. .AppendAction( GERBVIEW_ACTIONS::toggleLayerManager );
  72. break;
  73. case TOOLBAR_LOC::TOP_MAIN:
  74. config.AppendAction( GERBVIEW_ACTIONS::clearAllLayers )
  75. .AppendAction( GERBVIEW_ACTIONS::reloadAllLayers )
  76. .AppendAction( GERBVIEW_ACTIONS::openAutodetected )
  77. .AppendAction( GERBVIEW_ACTIONS::openGerber )
  78. .AppendAction( GERBVIEW_ACTIONS::openDrillFile );
  79. config.AppendSeparator()
  80. .AppendAction( ACTIONS::print );
  81. config.AppendSeparator()
  82. .AppendAction( ACTIONS::zoomRedraw )
  83. .AppendAction( ACTIONS::zoomInCenter )
  84. .AppendAction( ACTIONS::zoomOutCenter )
  85. .AppendAction( ACTIONS::zoomFitScreen )
  86. .AppendAction( ACTIONS::zoomTool );
  87. config.AppendSeparator()
  88. .AppendControl( ACTION_TOOLBAR_CONTROLS::layerSelector )
  89. .AppendControl( GERBVIEW_ACTION_TOOLBAR_CONTROLS::textInfo );
  90. break;
  91. case TOOLBAR_LOC::TOP_AUX:
  92. config.AppendControl( GERBVIEW_ACTION_TOOLBAR_CONTROLS::componentHighlight )
  93. .AppendSpacer( 5 )
  94. .AppendControl( GERBVIEW_ACTION_TOOLBAR_CONTROLS::netHighlight )
  95. .AppendSpacer( 5 )
  96. .AppendControl( GERBVIEW_ACTION_TOOLBAR_CONTROLS::appertureHighlight )
  97. .AppendSpacer( 5 )
  98. .AppendControl( GERBVIEW_ACTION_TOOLBAR_CONTROLS::dcodeSelector )
  99. .AppendSeparator()
  100. .AppendControl( ACTION_TOOLBAR_CONTROLS::gridSelect )
  101. .AppendSeparator()
  102. .AppendControl( ACTION_TOOLBAR_CONTROLS::zoomSelect );
  103. break;
  104. }
  105. // clang-format on
  106. return config;
  107. }
  108. void GERBVIEW_FRAME::configureToolbars()
  109. {
  110. // Base class loads the default settings
  111. EDA_DRAW_FRAME::configureToolbars();
  112. // Register factories for the various toolbar controls
  113. auto layerBoxFactory =
  114. [this]( ACTION_TOOLBAR* aToolbar )
  115. {
  116. if( !m_SelLayerBox )
  117. {
  118. m_SelLayerBox = new GBR_LAYER_BOX_SELECTOR( aToolbar,
  119. ID_TOOLBARH_GERBVIEW_SELECT_ACTIVE_LAYER,
  120. wxDefaultPosition, wxDefaultSize, 0, nullptr );
  121. }
  122. m_SelLayerBox->Resync();
  123. aToolbar->Add( m_SelLayerBox );
  124. // UI update handler for the control
  125. aToolbar->Bind( wxEVT_UPDATE_UI,
  126. [this]( wxUpdateUIEvent& aEvent )
  127. {
  128. if( m_SelLayerBox->GetCount() )
  129. {
  130. if( m_SelLayerBox->GetSelection() != GetActiveLayer() )
  131. m_SelLayerBox->SetSelection( GetActiveLayer() );
  132. }
  133. },
  134. m_SelLayerBox->GetId() );
  135. };
  136. RegisterCustomToolbarControlFactory( ACTION_TOOLBAR_CONTROLS::layerSelector, layerBoxFactory );
  137. auto textInfoFactory =
  138. [this]( ACTION_TOOLBAR* aToolbar )
  139. {
  140. if( !m_TextInfo )
  141. {
  142. m_TextInfo = new wxTextCtrl( aToolbar, ID_TOOLBARH_GERBER_DATA_TEXT_BOX, wxEmptyString,
  143. wxDefaultPosition, wxDefaultSize, wxTE_READONLY );
  144. }
  145. aToolbar->Add( m_TextInfo );
  146. };
  147. RegisterCustomToolbarControlFactory( GERBVIEW_ACTION_TOOLBAR_CONTROLS::textInfo, textInfoFactory );
  148. // Creates box to display and choose components:
  149. // (note, when the m_tbTopAux is recreated, tools are deleted, but controls
  150. // are not deleted: they are just no longer managed by the toolbar
  151. auto componentBoxFactory =
  152. [this]( ACTION_TOOLBAR* aToolbar )
  153. {
  154. if( !m_SelComponentBox )
  155. m_SelComponentBox = new wxChoice( aToolbar, ID_GBR_AUX_TOOLBAR_PCB_CMP_CHOICE );
  156. if( !m_cmpText )
  157. m_cmpText = new wxStaticText( aToolbar, wxID_ANY, _( "Cmp:" ) + wxS( " " ) );
  158. m_SelComponentBox->SetToolTip( _("Highlight items belonging to this component") );
  159. m_cmpText->SetLabel( _( "Cmp:" ) + wxS( " " ) ); // can change when changing the language
  160. updateComponentListSelectBox();
  161. aToolbar->Add( m_cmpText );
  162. aToolbar->Add( m_SelComponentBox );
  163. };
  164. RegisterCustomToolbarControlFactory( GERBVIEW_ACTION_TOOLBAR_CONTROLS::componentHighlight, componentBoxFactory );
  165. // Creates choice box to display net names and highlight selected:
  166. auto netBoxFactory =
  167. [this]( ACTION_TOOLBAR* aToolbar )
  168. {
  169. if( !m_SelNetnameBox )
  170. m_SelNetnameBox = new wxChoice( aToolbar, ID_GBR_AUX_TOOLBAR_PCB_NET_CHOICE );
  171. if( !m_netText )
  172. m_netText = new wxStaticText( aToolbar, wxID_ANY, _( "Net:" ) );
  173. m_SelNetnameBox->SetToolTip( _("Highlight items belonging to this net") );
  174. m_netText->SetLabel( _( "Net:" ) ); // can change when changing the language
  175. updateNetnameListSelectBox();
  176. aToolbar->Add( m_netText );
  177. aToolbar->Add( m_SelNetnameBox );
  178. };
  179. RegisterCustomToolbarControlFactory( GERBVIEW_ACTION_TOOLBAR_CONTROLS::netHighlight, netBoxFactory );
  180. // Creates choice box to display aperture attributes and highlight selected:
  181. auto appertureBoxFactory =
  182. [this]( ACTION_TOOLBAR* aToolbar )
  183. {
  184. if( !m_SelAperAttributesBox )
  185. {
  186. m_SelAperAttributesBox = new wxChoice( aToolbar,
  187. ID_GBR_AUX_TOOLBAR_PCB_APERATTRIBUTES_CHOICE );
  188. }
  189. if( !m_apertText )
  190. m_apertText = new wxStaticText( aToolbar, wxID_ANY, _( "Attr:" ) );
  191. m_SelAperAttributesBox->SetToolTip( _( "Highlight items with this aperture attribute" ) );
  192. m_apertText->SetLabel( _( "Attr:" ) ); // can change when changing the language
  193. updateAperAttributesSelectBox();
  194. aToolbar->Add( m_apertText );
  195. aToolbar->Add( m_SelAperAttributesBox );
  196. };
  197. RegisterCustomToolbarControlFactory( GERBVIEW_ACTION_TOOLBAR_CONTROLS::appertureHighlight, appertureBoxFactory );
  198. // D-code selection
  199. auto dcodeSelectorFactory =
  200. [this]( ACTION_TOOLBAR* aToolbar )
  201. {
  202. if( !m_DCodeSelector )
  203. {
  204. m_DCodeSelector = new DCODE_SELECTION_BOX( aToolbar,
  205. ID_TOOLBARH_GERBER_SELECT_ACTIVE_DCODE,
  206. wxDefaultPosition, wxSize( 150, -1 ) );
  207. }
  208. if( !m_dcodeText )
  209. m_dcodeText = new wxStaticText( aToolbar, wxID_ANY, _( "DCode:" ) );
  210. m_dcodeText->SetLabel( _( "DCode:" ) );
  211. updateDCodeSelectBox();
  212. aToolbar->Add( m_dcodeText );
  213. aToolbar->Add( m_DCodeSelector );
  214. };
  215. RegisterCustomToolbarControlFactory( GERBVIEW_ACTION_TOOLBAR_CONTROLS::dcodeSelector, dcodeSelectorFactory );
  216. }
  217. ACTION_TOOLBAR_CONTROL GERBVIEW_ACTION_TOOLBAR_CONTROLS::textInfo( "control.TextInfo", _( "Text info entry" ),
  218. _( "Text info entry" ) );
  219. ACTION_TOOLBAR_CONTROL GERBVIEW_ACTION_TOOLBAR_CONTROLS::componentHighlight( "control.ComponentHighlight",
  220. _( "Component highlight" ),
  221. _( "Highlight items belonging to this component" ) );
  222. ACTION_TOOLBAR_CONTROL GERBVIEW_ACTION_TOOLBAR_CONTROLS::netHighlight( "control.NetHighlight", _( "Net highlight" ),
  223. _( "Highlight items belonging to this net" ) );
  224. ACTION_TOOLBAR_CONTROL GERBVIEW_ACTION_TOOLBAR_CONTROLS::appertureHighlight( "control.AppertureHighlight", _( "Aperture highlight" ),
  225. _( "Highlight items with this aperture attribute" ));
  226. ACTION_TOOLBAR_CONTROL GERBVIEW_ACTION_TOOLBAR_CONTROLS::dcodeSelector( "control.GerberDcodeSelector", _( "DCode Selector" ),
  227. _( "Select all items with the selected DCode" ) );
  228. #define NO_SELECTION_STRING _("<No selection>")
  229. void GERBVIEW_FRAME::updateDCodeSelectBox()
  230. {
  231. m_DCodeSelector->Clear();
  232. // Add an empty string to deselect net highlight
  233. m_DCodeSelector->Append( NO_SELECTION_STRING );
  234. int layer = GetActiveLayer();
  235. GERBER_FILE_IMAGE* gerber = GetGbrImage( layer );
  236. if( !gerber || gerber->GetDcodesCount() == 0 )
  237. {
  238. if( m_DCodeSelector->GetSelection() != 0 )
  239. m_DCodeSelector->SetSelection( 0 );
  240. return;
  241. }
  242. // Build the aperture list of the current layer, and add it to the combo box:
  243. wxArrayString dcode_list;
  244. wxString msg;
  245. double scale = 1.0;
  246. wxString units;
  247. switch( GetUserUnits() )
  248. {
  249. case EDA_UNITS::MM:
  250. scale = gerbIUScale.IU_PER_MM;
  251. units = wxT( "mm" );
  252. break;
  253. case EDA_UNITS::INCH:
  254. scale = gerbIUScale.IU_PER_MILS * 1000;
  255. units = wxT( "in" );
  256. break;
  257. case EDA_UNITS::MILS:
  258. scale = gerbIUScale.IU_PER_MILS;
  259. units = wxT( "mil" );
  260. break;
  261. default:
  262. wxASSERT_MSG( false, wxT( "Invalid units" ) );
  263. }
  264. for( const auto& [_, dcode] : gerber->m_ApertureList )
  265. {
  266. wxCHECK2( dcode,continue );
  267. if( !dcode->m_InUse && !dcode->m_Defined )
  268. continue;
  269. msg.Printf( wxT( "tool %d [%.3fx%.3f %s] %s" ),
  270. dcode->m_Num_Dcode,
  271. dcode->m_Size.x / scale, dcode->m_Size.y / scale,
  272. units,
  273. D_CODE::ShowApertureType( dcode->m_ApertType ) );
  274. if( !dcode->m_AperFunction.IsEmpty() )
  275. msg << wxT( ", " ) << dcode->m_AperFunction;
  276. dcode_list.Add( msg );
  277. }
  278. m_DCodeSelector->AppendDCodeList( dcode_list );
  279. if( dcode_list.size() > 1 )
  280. {
  281. wxSize size = m_DCodeSelector->GetBestSize();
  282. size.x = std::max( size.x, 100 );
  283. m_DCodeSelector->SetMinSize( size );
  284. m_auimgr.Update();
  285. }
  286. }
  287. void GERBVIEW_FRAME::updateComponentListSelectBox()
  288. {
  289. m_SelComponentBox->Clear();
  290. // Build the full list of component names from the partial lists stored in each file image
  291. std::map<wxString, int> full_list;
  292. for( unsigned layer = 0; layer < GetImagesList()->ImagesMaxCount(); ++layer )
  293. {
  294. GERBER_FILE_IMAGE* gerber = GetImagesList()->GetGbrImage( layer );
  295. if( gerber == nullptr ) // Graphic layer not yet used
  296. continue;
  297. full_list.insert( gerber->m_ComponentsList.begin(), gerber->m_ComponentsList.end() );
  298. }
  299. // Add an empty string to deselect net highlight
  300. m_SelComponentBox->Append( NO_SELECTION_STRING );
  301. // Now copy the list to the choice box
  302. for( const std::pair<const wxString, int>& entry : full_list )
  303. m_SelComponentBox->Append( entry.first );
  304. m_SelComponentBox->SetSelection( 0 );
  305. }
  306. void GERBVIEW_FRAME::updateNetnameListSelectBox()
  307. {
  308. m_SelNetnameBox->Clear();
  309. // Build the full list of netnames from the partial lists stored in each file image
  310. std::map<wxString, int> full_list;
  311. for( unsigned layer = 0; layer < GetImagesList()->ImagesMaxCount(); ++layer )
  312. {
  313. GERBER_FILE_IMAGE* gerber = GetImagesList()->GetGbrImage( layer );
  314. if( gerber == nullptr ) // Graphic layer not yet used
  315. continue;
  316. full_list.insert( gerber->m_NetnamesList.begin(), gerber->m_NetnamesList.end() );
  317. }
  318. // Add an empty string to deselect net highlight
  319. m_SelNetnameBox->Append( NO_SELECTION_STRING );
  320. // Now copy the list to the choice box
  321. for( const std::pair<const wxString, int>& entry : full_list )
  322. m_SelNetnameBox->Append( UnescapeString( entry.first ) );
  323. m_SelNetnameBox->SetSelection( 0 );
  324. }
  325. void GERBVIEW_FRAME::updateAperAttributesSelectBox()
  326. {
  327. m_SelAperAttributesBox->Clear();
  328. // Build the full list of netnames from the partial lists stored in each file image
  329. std::map<wxString, int> full_list;
  330. for( unsigned layer = 0; layer < GetImagesList()->ImagesMaxCount(); ++layer )
  331. {
  332. GERBER_FILE_IMAGE* gerber = GetImagesList()->GetGbrImage( layer );
  333. if( gerber == nullptr ) // Graphic layer not yet used
  334. continue;
  335. if( gerber->GetDcodesCount() == 0 )
  336. continue;
  337. for( const auto &[_, aperture] : gerber->m_ApertureList )
  338. {
  339. if( aperture == nullptr )
  340. continue;
  341. if( !aperture->m_InUse && !aperture->m_Defined )
  342. continue;
  343. if( !aperture->m_AperFunction.IsEmpty() )
  344. full_list.insert( std::make_pair( aperture->m_AperFunction, 0 ) );
  345. }
  346. }
  347. // Add an empty string to deselect net highlight
  348. m_SelAperAttributesBox->Append( NO_SELECTION_STRING );
  349. // Now copy the list to the choice box
  350. for( const std::pair<const wxString, int>& entry : full_list )
  351. m_SelAperAttributesBox->Append( entry.first );
  352. m_SelAperAttributesBox->SetSelection( 0 );
  353. }
  354. void GERBVIEW_FRAME::OnUpdateSelectDCode( wxUpdateUIEvent& aEvent )
  355. {
  356. if( !m_DCodeSelector )
  357. return;
  358. int layer = GetActiveLayer();
  359. GERBER_FILE_IMAGE* gerber = GetGbrImage( layer );
  360. int selected = gerber ? gerber->m_Selected_Tool : 0;
  361. aEvent.Enable( gerber != nullptr );
  362. if( m_DCodeSelector->GetSelectedDCodeId() != selected )
  363. {
  364. m_DCodeSelector->SetDCodeSelection( selected );
  365. // Be sure the selection can be made. If no, set to
  366. // a correct value
  367. if( gerber )
  368. gerber->m_Selected_Tool = m_DCodeSelector->GetSelectedDCodeId();
  369. }
  370. }