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.

477 lines
17 KiB

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