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.

238 lines
7.8 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2019 KiCad Developers, see AUTHORS.TXT for contributors.
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version 2
  9. * of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, you may find one here:
  18. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  19. * or you may search the http://www.gnu.org website for the version 2 license,
  20. * or you may write to the Free Software Foundation, Inc.,
  21. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  22. */
  23. #include <bitmaps.h>
  24. #include <class_zone.h>
  25. #include <tool/tool_manager.h>
  26. #include <tools/pcb_actions.h>
  27. #include <tools/selection_tool.h>
  28. #include <tools/edit_tool.h>
  29. #include <dialogs/dialog_track_via_properties.h>
  30. #include <dialogs/dialog_exchange_footprints.h>
  31. #include <dialogs/dialog_swap_layers.h>
  32. #include <tools/global_edit_tool.h>
  33. #include <board_commit.h>
  34. TOOL_ACTION PCB_ACTIONS::updateFootprint( "pcbnew.GlobalEdit.updateFootprint",
  35. AS_GLOBAL, 0,
  36. _( "Update Footprint..." ),
  37. _( "Update footprint to include any changes from the library" ),
  38. reload_xpm );
  39. TOOL_ACTION PCB_ACTIONS::updateFootprints( "pcbnew.GlobalEdit.updateFootprints",
  40. AS_GLOBAL, 0,
  41. _( "Update Footprints from Library..." ),
  42. _( "Update footprints to include any changes from the library" ),
  43. reload_xpm );
  44. TOOL_ACTION PCB_ACTIONS::changeFootprint( "pcbnew.GlobalEdit.changeFootprint",
  45. AS_GLOBAL, 0,
  46. _( "Change Footprint..." ), _( "Assign a different footprint from the library" ),
  47. exchange_xpm );
  48. TOOL_ACTION PCB_ACTIONS::changeFootprints( "pcbnew.GlobalEdit.changeFootprints",
  49. AS_GLOBAL, 0,
  50. _( "Change Footprints..." ), _( "Assign different footprints from the library" ),
  51. exchange_xpm );
  52. TOOL_ACTION PCB_ACTIONS::swapLayers( "pcbnew.GlobalEdit.swapLayers",
  53. AS_GLOBAL, 0,
  54. _( "Swap Layers..." ), _( "Move tracks or drawings from one layer to another" ),
  55. swap_layer_xpm );
  56. TOOL_ACTION PCB_ACTIONS::editTracksAndVias( "pcbnew.GlobalEdit.editTracksAndVias",
  57. AS_GLOBAL, 0,
  58. _( "Edit Track && Via Properties..." ), "",
  59. width_track_via_xpm );
  60. TOOL_ACTION PCB_ACTIONS::editTextAndGraphics( "pcbnew.GlobalEdit.editTextAndGraphics",
  61. AS_GLOBAL, 0,
  62. _( "Edit Text && Graphic Properties..." ), "",
  63. reset_text_xpm );
  64. TOOL_ACTION PCB_ACTIONS::globalDeletions( "pcbnew.GlobalEdit.globalDeletions",
  65. AS_GLOBAL, 0,
  66. _( "Global Deletions..." ),
  67. _( "Delete tracks, footprints and graphic items from board" ),
  68. general_deletions_xpm );
  69. TOOL_ACTION PCB_ACTIONS::cleanupTracksAndVias( "pcbnew.GlobalEdit.cleanupTracksAndVias",
  70. AS_GLOBAL, 0,
  71. _( "Cleanup Tracks && Vias..." ),
  72. _( "Clean stubs, vias, delete break points or unconnected tracks" ),
  73. delete_xpm );
  74. GLOBAL_EDIT_TOOL::GLOBAL_EDIT_TOOL() :
  75. PCB_TOOL_BASE( "pcbnew.GlobalEdit" )
  76. {
  77. }
  78. void GLOBAL_EDIT_TOOL::Reset( RESET_REASON aReason )
  79. {
  80. if( aReason != RUN )
  81. m_commit.reset( new BOARD_COMMIT( this ) );
  82. }
  83. bool GLOBAL_EDIT_TOOL::Init()
  84. {
  85. // Find the selection tool, so they can cooperate
  86. m_selectionTool = static_cast<SELECTION_TOOL*>( m_toolMgr->FindTool( "pcbnew.InteractiveSelection" ) );
  87. wxASSERT_MSG( m_selectionTool, "pcbnew.InteractiveSelection tool is not available" );
  88. return true;
  89. }
  90. int GLOBAL_EDIT_TOOL::ExchangeFootprints( const TOOL_EVENT& aEvent )
  91. {
  92. SELECTION& selection = m_selectionTool->RequestSelection( EDIT_TOOL::FootprintFilter );
  93. MODULE* mod = (selection.Empty() ? nullptr : selection.FirstOfKind<MODULE> () );
  94. bool updateMode = false;
  95. bool currentMode = false;
  96. if( aEvent.IsAction( &PCB_ACTIONS::updateFootprint ) )
  97. {
  98. updateMode = true;
  99. currentMode = true;
  100. }
  101. else if( aEvent.IsAction( &PCB_ACTIONS::updateFootprints ) )
  102. {
  103. updateMode = true;
  104. currentMode = false;
  105. }
  106. else if( aEvent.IsAction( &PCB_ACTIONS::changeFootprint ) )
  107. {
  108. updateMode = false;
  109. currentMode = true;
  110. }
  111. else if( aEvent.IsAction( &PCB_ACTIONS::changeFootprints ) )
  112. {
  113. updateMode = false;
  114. currentMode = false;
  115. }
  116. else
  117. wxFAIL_MSG( "ExchangeFootprints: unexpected action" );
  118. // Footprint exchange could remove modules, so they have to be
  119. // removed from the selection first
  120. m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
  121. // invoke the exchange dialog process
  122. {
  123. DIALOG_EXCHANGE_FOOTPRINTS dialog( frame(), mod, updateMode, currentMode );
  124. dialog.ShowQuasiModal();
  125. }
  126. return 0;
  127. }
  128. bool GLOBAL_EDIT_TOOL::swapBoardItem( BOARD_ITEM* aItem, PCB_LAYER_ID* new_layer )
  129. {
  130. if( new_layer[ aItem->GetLayer() ] != aItem->GetLayer() )
  131. {
  132. m_commit->Modify( aItem );
  133. aItem->SetLayer( new_layer[ aItem->GetLayer() ] );
  134. frame()->GetGalCanvas()->GetView()->Update( aItem, KIGFX::GEOMETRY );
  135. return true;
  136. }
  137. return false;
  138. }
  139. int GLOBAL_EDIT_TOOL::SwapLayers( const TOOL_EVENT& aEvent )
  140. {
  141. PCB_LAYER_ID new_layer[PCB_LAYER_ID_COUNT];
  142. DIALOG_SWAP_LAYERS dlg( frame(), new_layer );
  143. if( dlg.ShowModal() != wxID_OK )
  144. return 0;
  145. bool hasChanges = false;
  146. // Change tracks.
  147. for( auto segm : frame()->GetBoard()->Tracks() )
  148. {
  149. if( segm->Type() == PCB_VIA_T )
  150. {
  151. VIA* via = (VIA*) segm;
  152. PCB_LAYER_ID top_layer, bottom_layer;
  153. if( via->GetViaType() == VIA_THROUGH )
  154. continue;
  155. via->LayerPair( &top_layer, &bottom_layer );
  156. if( new_layer[bottom_layer] != bottom_layer || new_layer[top_layer] != top_layer )
  157. {
  158. m_commit->Modify( via );
  159. via->SetLayerPair( new_layer[top_layer], new_layer[bottom_layer] );
  160. frame()->GetGalCanvas()->GetView()->Update( via, KIGFX::GEOMETRY );
  161. hasChanges = true;
  162. }
  163. }
  164. else
  165. {
  166. hasChanges |= swapBoardItem( segm, new_layer );
  167. }
  168. }
  169. for( BOARD_ITEM* zone : frame()->GetBoard()->Zones() )
  170. hasChanges |= swapBoardItem( zone, new_layer );
  171. for( BOARD_ITEM* drawing : frame()->GetBoard()->Drawings() )
  172. hasChanges |= swapBoardItem( drawing, new_layer );
  173. if( hasChanges )
  174. {
  175. frame()->OnModify();
  176. m_commit->Push( "Layers moved" );
  177. frame()->GetGalCanvas()->Refresh();
  178. }
  179. return 0;
  180. }
  181. void GLOBAL_EDIT_TOOL::setTransitions()
  182. {
  183. Go( &GLOBAL_EDIT_TOOL::ExchangeFootprints, PCB_ACTIONS::updateFootprint.MakeEvent() );
  184. Go( &GLOBAL_EDIT_TOOL::ExchangeFootprints, PCB_ACTIONS::updateFootprints.MakeEvent() );
  185. Go( &GLOBAL_EDIT_TOOL::ExchangeFootprints, PCB_ACTIONS::changeFootprint.MakeEvent() );
  186. Go( &GLOBAL_EDIT_TOOL::ExchangeFootprints, PCB_ACTIONS::changeFootprints.MakeEvent() );
  187. Go( &GLOBAL_EDIT_TOOL::SwapLayers, PCB_ACTIONS::swapLayers.MakeEvent() );
  188. Go( &GLOBAL_EDIT_TOOL::EditTracksAndVias, PCB_ACTIONS::editTracksAndVias.MakeEvent() );
  189. Go( &GLOBAL_EDIT_TOOL::EditTextAndGraphics, PCB_ACTIONS::editTextAndGraphics.MakeEvent() );
  190. Go( &GLOBAL_EDIT_TOOL::GlobalDeletions, PCB_ACTIONS::globalDeletions.MakeEvent() );
  191. Go( &GLOBAL_EDIT_TOOL::CleanupTracksAndVias, PCB_ACTIONS::cleanupTracksAndVias.MakeEvent() );
  192. }