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.

484 lines
18 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 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, jp.charras at wanadoo.fr
  5. * Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors.
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * as published by the Free Software Foundation; either version 2
  10. * of the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, you may find one here:
  19. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  20. * or you may search the http://www.gnu.org website for the version 2 license,
  21. * or you may write to the Free Software Foundation, Inc.,
  22. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  23. */
  24. #include <string_utils.h>
  25. #include <board_commit.h>
  26. #include <pcb_edit_frame.h>
  27. #include <pcb_layer_box_selector.h>
  28. #include <pcbnew.h>
  29. #include <board.h>
  30. #include <board_design_settings.h>
  31. #include <footprint.h>
  32. #include <pcb_group.h>
  33. #include <pcb_dimension.h>
  34. #include <fp_shape.h>
  35. #include <pcb_text.h>
  36. #include <widgets/unit_binder.h>
  37. #include <tool/tool_manager.h>
  38. #include <tools/global_edit_tool.h>
  39. #include <dialog_global_edit_text_and_graphics_base.h>
  40. // Columns of layer classes grid
  41. enum
  42. {
  43. COL_CLASS_NAME = 0,
  44. COL_LINE_THICKNESS,
  45. COL_TEXT_WIDTH,
  46. COL_TEXT_HEIGHT,
  47. COL_TEXT_THICKNESS,
  48. COL_TEXT_ITALIC,
  49. COL_TEXT_UPRIGHT
  50. };
  51. enum
  52. {
  53. ROW_HEADER = 0,
  54. ROW_SILK,
  55. ROW_COPPER,
  56. ROW_EDGES,
  57. ROW_COURTYARD,
  58. ROW_FAB,
  59. ROW_OTHERS
  60. };
  61. static bool g_modifyReferences;
  62. static bool g_modifyValues;
  63. static bool g_modifyOtherFields;
  64. static bool g_modifyFootprintGraphics;
  65. static bool g_modifyBoardText;
  66. static bool g_modifyBoardGraphics;
  67. static bool g_filterByLayer;
  68. static LAYER_NUM g_layerFilter;
  69. static bool g_filterByReference;
  70. static wxString g_referenceFilter;
  71. static bool g_filterByFootprint;
  72. static wxString g_footprintFilter;
  73. static bool g_filterSelected = false;
  74. class DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS : public DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS_BASE
  75. {
  76. PCB_EDIT_FRAME* m_parent;
  77. BOARD_DESIGN_SETTINGS* m_brdSettings;
  78. PCB_SELECTION m_selection;
  79. UNIT_BINDER m_lineWidth;
  80. UNIT_BINDER m_textWidth;
  81. UNIT_BINDER m_textHeight;
  82. UNIT_BINDER m_thickness;
  83. public:
  84. DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS( PCB_EDIT_FRAME* parent );
  85. ~DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS() override;
  86. protected:
  87. void onActionButtonChange( wxCommandEvent& event ) override;
  88. void onSpecifiedValueUpdateUI( wxUpdateUIEvent& event ) override;
  89. void OnLayerFilterSelect( wxCommandEvent& event ) override
  90. {
  91. m_layerFilterOpt->SetValue( true );
  92. }
  93. void OnReferenceFilterText( wxCommandEvent& event ) override
  94. {
  95. m_referenceFilterOpt->SetValue( true );
  96. }
  97. void OnFootprintFilterText( wxCommandEvent& event ) override
  98. {
  99. m_footprintFilterOpt->SetValue( true );
  100. }
  101. bool TransferDataToWindow() override;
  102. bool TransferDataFromWindow() override;
  103. void visitItem( BOARD_COMMIT& aCommit, BOARD_ITEM* aItem );
  104. void processItem( BOARD_COMMIT& aCommit, BOARD_ITEM* aItem );
  105. };
  106. DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS( PCB_EDIT_FRAME* parent ) :
  107. DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS_BASE( parent ),
  108. m_lineWidth( parent, m_lineWidthLabel, m_LineWidthCtrl, m_lineWidthUnits ),
  109. m_textWidth( parent, m_SizeXlabel, m_SizeXCtrl, m_SizeXunit ),
  110. m_textHeight( parent, m_SizeYlabel, m_SizeYCtrl, m_SizeYunit ),
  111. m_thickness( parent, m_ThicknessLabel, m_ThicknessCtrl, m_ThicknessUnit )
  112. {
  113. m_parent = parent;
  114. m_brdSettings = &m_parent->GetDesignSettings();
  115. m_layerFilter->SetBoardFrame( m_parent );
  116. m_layerFilter->SetLayersHotkeys( false );
  117. m_layerFilter->Resync();
  118. m_LayerCtrl->SetBoardFrame( m_parent );
  119. m_LayerCtrl->SetLayersHotkeys( false );
  120. m_LayerCtrl->SetUndefinedLayerName( INDETERMINATE_ACTION );
  121. m_LayerCtrl->Resync();
  122. m_grid->SetCellHighlightPenWidth( 0 );
  123. m_grid->SetDefaultCellFont( KIUI::GetInfoFont( this ) );
  124. m_sdbSizerButtonsOK->SetDefault();
  125. finishDialogSettings();
  126. }
  127. DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::~DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS()
  128. {
  129. g_modifyReferences = m_references->GetValue();
  130. g_modifyValues = m_values->GetValue();
  131. g_modifyOtherFields = m_otherFields->GetValue();
  132. g_modifyFootprintGraphics = m_footprintGraphics->GetValue();
  133. g_modifyBoardText = m_boardText->GetValue();
  134. g_modifyBoardGraphics = m_boardGraphics->GetValue();
  135. g_filterByLayer = m_layerFilterOpt->GetValue();
  136. g_layerFilter = m_layerFilter->GetLayerSelection();
  137. g_filterByReference = m_referenceFilterOpt->GetValue();
  138. g_referenceFilter = m_referenceFilter->GetValue();
  139. g_filterByFootprint = m_footprintFilterOpt->GetValue();
  140. g_footprintFilter = m_footprintFilter->GetValue();
  141. g_filterSelected = m_selectedItemsFilter->GetValue();
  142. }
  143. bool DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::TransferDataToWindow()
  144. {
  145. PCB_SELECTION_TOOL* selTool = m_parent->GetToolManager()->GetTool<PCB_SELECTION_TOOL>();
  146. m_selection = selTool->GetSelection();
  147. m_references->SetValue( g_modifyReferences );
  148. m_values->SetValue( g_modifyValues );
  149. m_otherFields->SetValue( g_modifyOtherFields );
  150. m_footprintGraphics->SetValue( g_modifyFootprintGraphics );
  151. m_boardText->SetValue( g_modifyBoardText );
  152. m_boardGraphics->SetValue( g_modifyBoardGraphics );
  153. if( m_layerFilter->SetLayerSelection( g_layerFilter ) != wxNOT_FOUND )
  154. m_layerFilterOpt->SetValue( g_filterByLayer );
  155. // SetValue() generates events, ChangeValue() does not
  156. m_referenceFilter->ChangeValue( g_referenceFilter );
  157. m_referenceFilterOpt->SetValue( g_filterByReference );
  158. m_footprintFilter->ChangeValue( g_footprintFilter );
  159. m_footprintFilterOpt->SetValue( g_filterByFootprint );
  160. m_selectedItemsFilter->SetValue( g_filterSelected );
  161. m_lineWidth.SetValue( INDETERMINATE_ACTION );
  162. m_textWidth.SetValue( INDETERMINATE_ACTION );
  163. m_textHeight.SetValue( INDETERMINATE_ACTION );
  164. m_thickness.SetValue( INDETERMINATE_ACTION );
  165. m_Italic->Set3StateValue( wxCHK_UNDETERMINED );
  166. m_keepUpright->Set3StateValue( wxCHK_UNDETERMINED );
  167. m_Visible->Set3StateValue( wxCHK_UNDETERMINED );
  168. m_LayerCtrl->SetLayerSelection( UNDEFINED_LAYER );
  169. #define SET_INT_VALUE( aRow, aCol, aValue ) \
  170. m_grid->SetCellValue( aRow, aCol, StringFromValue( GetUserUnits(), aValue, true ) )
  171. #define SET_BOOL_VALUE( aRow, aCol, aValue ) \
  172. attr = new wxGridCellAttr; \
  173. attr->SetRenderer( new wxGridCellBoolRenderer() ); \
  174. attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER ); \
  175. attr->SetReadOnly(); \
  176. m_grid->SetAttr( aRow, aCol, attr ); \
  177. m_grid->SetCellValue( aRow, aCol, ( aValue ) ? "1" : "" )
  178. const BOARD_DESIGN_SETTINGS& bds = m_parent->GetBoard()->GetDesignSettings();
  179. wxGridCellAttr* attr;
  180. m_grid->SetCellValue( ROW_SILK, COL_CLASS_NAME, _( "Silk Layers" ) );
  181. m_grid->SetCellValue( ROW_COPPER, COL_CLASS_NAME, _( "Copper Layers" ) );
  182. m_grid->SetCellValue( ROW_EDGES, COL_CLASS_NAME, _( "Edge Cuts" ) );
  183. m_grid->SetCellValue( ROW_COURTYARD, COL_CLASS_NAME, _( "Courtyards" ) );
  184. m_grid->SetCellValue( ROW_FAB, COL_CLASS_NAME, _( "Fab Layers" ) );
  185. m_grid->SetCellValue( ROW_OTHERS, COL_CLASS_NAME, _( "Other Layers" ) );
  186. m_grid->SetCellValue( ROW_HEADER, COL_LINE_THICKNESS, _( "Line Thickness" ) );
  187. SET_INT_VALUE( ROW_SILK, COL_LINE_THICKNESS, bds.m_LineThickness[ LAYER_CLASS_SILK ] );
  188. SET_INT_VALUE( ROW_COPPER, COL_LINE_THICKNESS, bds.m_LineThickness[ LAYER_CLASS_COPPER ] );
  189. SET_INT_VALUE( ROW_EDGES, COL_LINE_THICKNESS, bds.m_LineThickness[ LAYER_CLASS_EDGES ] );
  190. SET_INT_VALUE( ROW_COURTYARD, COL_LINE_THICKNESS, bds.m_LineThickness[ LAYER_CLASS_COURTYARD ] );
  191. SET_INT_VALUE( ROW_FAB, COL_LINE_THICKNESS, bds.m_LineThickness[ LAYER_CLASS_FAB ] );
  192. SET_INT_VALUE( ROW_OTHERS, COL_LINE_THICKNESS, bds.m_LineThickness[ LAYER_CLASS_OTHERS ] );
  193. m_grid->SetCellValue( ROW_HEADER, COL_TEXT_WIDTH, _( "Text Width" ) );
  194. SET_INT_VALUE( ROW_SILK, COL_TEXT_WIDTH, bds.m_TextSize[ LAYER_CLASS_SILK ].x );
  195. SET_INT_VALUE( ROW_COPPER, COL_TEXT_WIDTH, bds.m_TextSize[ LAYER_CLASS_COPPER ].x );
  196. SET_INT_VALUE( ROW_FAB, COL_TEXT_WIDTH, bds.m_TextSize[ LAYER_CLASS_FAB ].x );
  197. SET_INT_VALUE( ROW_OTHERS, COL_TEXT_WIDTH, bds.m_TextSize[ LAYER_CLASS_OTHERS ].x );
  198. m_grid->SetCellValue( ROW_HEADER, COL_TEXT_HEIGHT, _( "Text Height" ) );
  199. SET_INT_VALUE( ROW_SILK, COL_TEXT_HEIGHT, bds.m_TextSize[ LAYER_CLASS_SILK ].y );
  200. SET_INT_VALUE( ROW_COPPER, COL_TEXT_HEIGHT, bds.m_TextSize[ LAYER_CLASS_COPPER ].y );
  201. SET_INT_VALUE( ROW_FAB, COL_TEXT_HEIGHT, bds.m_TextSize[ LAYER_CLASS_FAB ].y );
  202. SET_INT_VALUE( ROW_OTHERS, COL_TEXT_HEIGHT, bds.m_TextSize[ LAYER_CLASS_OTHERS ].y );
  203. m_grid->SetCellValue( ROW_HEADER, COL_TEXT_THICKNESS, _( "Text Thickness" ) );
  204. SET_INT_VALUE( ROW_SILK, COL_TEXT_THICKNESS, bds.m_TextThickness[ LAYER_CLASS_SILK ] );
  205. SET_INT_VALUE( ROW_COPPER, COL_TEXT_THICKNESS, bds.m_TextThickness[ LAYER_CLASS_COPPER ] );
  206. SET_INT_VALUE( ROW_FAB, COL_TEXT_THICKNESS, bds.m_TextThickness[ LAYER_CLASS_FAB ] );
  207. SET_INT_VALUE( ROW_OTHERS, COL_TEXT_THICKNESS, bds.m_TextThickness[ LAYER_CLASS_OTHERS ] );
  208. m_grid->SetCellValue( ROW_HEADER, COL_TEXT_ITALIC, _( "Italic" ) );
  209. SET_BOOL_VALUE( ROW_SILK, COL_TEXT_ITALIC, bds.m_TextItalic[ LAYER_CLASS_SILK ] );
  210. SET_BOOL_VALUE( ROW_COPPER, COL_TEXT_ITALIC, bds.m_TextItalic[ LAYER_CLASS_COPPER ] );
  211. SET_BOOL_VALUE( ROW_FAB, COL_TEXT_ITALIC, bds.m_TextItalic[ LAYER_CLASS_FAB ] );
  212. SET_BOOL_VALUE( ROW_OTHERS, COL_TEXT_ITALIC, bds.m_TextItalic[ LAYER_CLASS_OTHERS ] );
  213. m_grid->SetCellValue( ROW_HEADER, COL_TEXT_UPRIGHT, _( "Upright" ) );
  214. SET_BOOL_VALUE( ROW_SILK, COL_TEXT_UPRIGHT, bds.m_TextUpright[ LAYER_CLASS_SILK ] );
  215. SET_BOOL_VALUE( ROW_COPPER, COL_TEXT_UPRIGHT, bds.m_TextUpright[ LAYER_CLASS_COPPER ] );
  216. SET_BOOL_VALUE( ROW_FAB, COL_TEXT_UPRIGHT, bds.m_TextUpright[ LAYER_CLASS_FAB ] );
  217. SET_BOOL_VALUE( ROW_OTHERS, COL_TEXT_UPRIGHT, bds.m_TextUpright[ LAYER_CLASS_OTHERS ] );
  218. return true;
  219. #undef SET_INT_VALUE
  220. #undef SET_BOOL_VALUE
  221. }
  222. void DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::onActionButtonChange( wxCommandEvent& event )
  223. {
  224. // Update the UNIT_BINDER controls if the action to take is changed
  225. bool enable = m_setToSpecifiedValues->GetValue();
  226. m_lineWidth.Enable( enable );
  227. m_textWidth.Enable( enable );
  228. m_textHeight.Enable( enable );
  229. m_thickness.Enable( enable );
  230. }
  231. void DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::onSpecifiedValueUpdateUI( wxUpdateUIEvent& event )
  232. {
  233. // Update the UI for the elements inside the use specified values sizer
  234. event.Enable( m_setToSpecifiedValues->GetValue() );
  235. }
  236. void DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::processItem( BOARD_COMMIT& aCommit, BOARD_ITEM* aItem )
  237. {
  238. aCommit.Modify( aItem );
  239. EDA_TEXT* textItem = dynamic_cast<EDA_TEXT*>( aItem );
  240. FP_TEXT* fpTextItem = dynamic_cast<FP_TEXT*>( aItem );
  241. PCB_SHAPE* drawItem = dynamic_cast<PCB_SHAPE*>( aItem );
  242. PCB_DIMENSION_BASE* dimension = dynamic_cast<PCB_DIMENSION_BASE*>( aItem );
  243. if( dimension )
  244. textItem = &dimension->Text();
  245. if( m_setToSpecifiedValues->GetValue() )
  246. {
  247. if( m_LayerCtrl->GetLayerSelection() != UNDEFINED_LAYER )
  248. aItem->SetLayer( ToLAYER_ID( m_LayerCtrl->GetLayerSelection() ) );
  249. if( !m_textWidth.IsIndeterminate() && textItem )
  250. textItem->SetTextSize( wxSize( m_textWidth.GetValue(), textItem->GetTextSize().y ) );
  251. if( !m_textHeight.IsIndeterminate() && textItem )
  252. textItem->SetTextSize( wxSize( textItem->GetTextSize().x, m_textHeight.GetValue() ) );
  253. if( !m_thickness.IsIndeterminate() && textItem )
  254. textItem->SetTextThickness( m_thickness.GetValue() );
  255. if( m_Italic->Get3StateValue() != wxCHK_UNDETERMINED && textItem )
  256. textItem->SetItalic( m_Italic->GetValue() );
  257. if( m_Visible->Get3StateValue() != wxCHK_UNDETERMINED && textItem )
  258. textItem->SetVisible( m_Visible->GetValue() );
  259. if( m_keepUpright->Get3StateValue() != wxCHK_UNDETERMINED && fpTextItem )
  260. fpTextItem->SetKeepUpright( m_keepUpright->GetValue() );
  261. if( !m_lineWidth.IsIndeterminate() )
  262. {
  263. if( drawItem )
  264. drawItem->SetWidth( m_lineWidth.GetValue() );
  265. if( dimension )
  266. dimension->SetLineThickness( m_lineWidth.GetValue() );
  267. }
  268. }
  269. else
  270. {
  271. PCB_LAYER_ID layer = aItem->GetLayer();
  272. if( textItem )
  273. {
  274. textItem->SetTextSize( m_brdSettings->GetTextSize( layer ) );
  275. textItem->SetTextThickness( m_brdSettings->GetTextThickness( layer ) );
  276. textItem->SetItalic( m_brdSettings->GetTextItalic( layer ) );
  277. }
  278. if( fpTextItem )
  279. fpTextItem->SetKeepUpright( m_brdSettings->GetTextUpright( layer ) );
  280. if( drawItem )
  281. drawItem->SetWidth( m_brdSettings->GetLineThickness( layer ) );
  282. if( dimension )
  283. dimension->SetLineThickness( m_brdSettings->GetLineThickness( layer ) );
  284. }
  285. }
  286. void DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::visitItem( BOARD_COMMIT& aCommit, BOARD_ITEM* aItem )
  287. {
  288. if( m_selectedItemsFilter->GetValue() )
  289. {
  290. BOARD_ITEM* candidate = aItem;
  291. if( !candidate->IsSelected() )
  292. {
  293. if( candidate->GetParent() && candidate->GetParent()->Type() == PCB_FOOTPRINT_T )
  294. candidate = candidate->GetParent();
  295. }
  296. if( !candidate->IsSelected() )
  297. {
  298. candidate = candidate->GetParentGroup();
  299. while( candidate && !candidate->IsSelected() )
  300. candidate = candidate->GetParentGroup();
  301. if( !candidate )
  302. return;
  303. }
  304. }
  305. if( m_layerFilterOpt->GetValue() && m_layerFilter->GetLayerSelection() != UNDEFINED_LAYER )
  306. {
  307. if( aItem->GetLayer() != m_layerFilter->GetLayerSelection() )
  308. return;
  309. }
  310. if( m_referenceFilterOpt->GetValue() && !m_referenceFilter->GetValue().IsEmpty() )
  311. {
  312. FOOTPRINT* fp = dynamic_cast<FOOTPRINT*>( aItem->GetParent() );
  313. if( fp )
  314. {
  315. if( !WildCompareString( m_referenceFilter->GetValue(), fp->GetReference(), false ) )
  316. return;
  317. }
  318. }
  319. if( m_footprintFilterOpt->GetValue() && !m_footprintFilter->GetValue().IsEmpty() )
  320. {
  321. FOOTPRINT* fp = dynamic_cast<FOOTPRINT*>( aItem->GetParent() );
  322. if( fp )
  323. {
  324. if( !WildCompareString( m_footprintFilter->GetValue(), fp->GetFPID().Format(), false ) )
  325. return;
  326. }
  327. }
  328. processItem( aCommit, aItem );
  329. }
  330. bool DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::TransferDataFromWindow()
  331. {
  332. if( !m_textWidth.Validate( TEXTS_MIN_SIZE, TEXTS_MAX_SIZE )
  333. || !m_textHeight.Validate( TEXTS_MIN_SIZE, TEXTS_MAX_SIZE ) )
  334. {
  335. return false;
  336. }
  337. BOARD_COMMIT commit( m_parent );
  338. // Go through the footprints
  339. for( FOOTPRINT* fp : m_parent->GetBoard()->Footprints() )
  340. {
  341. if( m_references->GetValue() )
  342. visitItem( commit, &fp->Reference() );
  343. if( m_values->GetValue() )
  344. visitItem( commit, &fp->Value() );
  345. // Go through all other footprint items
  346. for( BOARD_ITEM* boardItem : fp->GraphicalItems() )
  347. {
  348. if( boardItem->Type() == PCB_FP_TEXT_T )
  349. {
  350. // We are guaranteed to always get an EDA_TEXT in this statement, but we must
  351. // use the dynamic_cast to move through the type tree anyway.
  352. const wxString text = dynamic_cast<EDA_TEXT*>( boardItem )->GetText();
  353. if( m_references->GetValue() && text == wxT( "${REFERENCE}" ) )
  354. visitItem( commit, boardItem );
  355. else if( m_values->GetValue() && text == wxT( "${VALUE}" ) )
  356. visitItem( commit, boardItem );
  357. else if( m_otherFields->GetValue() )
  358. visitItem( commit, boardItem );
  359. }
  360. else if( boardItem->Type() == PCB_FP_SHAPE_T )
  361. {
  362. if( m_footprintGraphics->GetValue() )
  363. visitItem( commit, boardItem );
  364. }
  365. }
  366. }
  367. // Go through the PCB text & graphic items
  368. for( BOARD_ITEM* boardItem : m_parent->GetBoard()->Drawings() )
  369. {
  370. KICAD_T itemType = boardItem->Type();
  371. if( itemType == PCB_TEXT_T )
  372. {
  373. if( m_boardText->GetValue() )
  374. visitItem( commit, boardItem );
  375. }
  376. else if( itemType == PCB_SHAPE_T || BaseType( itemType ) == PCB_DIMENSION_T )
  377. {
  378. if( m_boardGraphics->GetValue() )
  379. visitItem( commit, boardItem );
  380. }
  381. }
  382. commit.Push( "Edit text and graphics properties" );
  383. m_parent->GetCanvas()->Refresh();
  384. return true;
  385. }
  386. int GLOBAL_EDIT_TOOL::EditTextAndGraphics( const TOOL_EVENT& aEvent )
  387. {
  388. PCB_EDIT_FRAME* editFrame = getEditFrame<PCB_EDIT_FRAME>();
  389. DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS dlg( editFrame );
  390. dlg.ShowModal();
  391. return 0;
  392. }