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.

318 lines
10 KiB

14 years ago
14 years ago
14 years ago
14 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2007-2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
  5. * Copyright (C) 1992-2016 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. /**
  25. * @file edit_track_width.cpp
  26. * @brief Functions to modify sizes of segment, track, net, all vias and/or all tracks.
  27. */
  28. #include <fctsys.h>
  29. #include <gr_basic.h>
  30. #include <class_drawpanel.h>
  31. #include <pcb_edit_frame.h>
  32. #include <class_board.h>
  33. #include <class_track.h>
  34. #include <pcbnew.h>
  35. #include <drc.h>
  36. bool PCB_EDIT_FRAME::SetTrackSegmentWidth( TRACK* aTrackItem,
  37. PICKED_ITEMS_LIST* aItemsListPicker,
  38. bool aUseNetclassValue )
  39. {
  40. /* Modify one track segment width or one via diameter and drill (using DRC control).
  41. * Basic function used by other routines when editing tracks or vias
  42. * aTrackItem = the track segment or via to modify
  43. * aItemsListPicker = the list picker to use for an undo command (can be NULL)
  44. * aUseNetclassValue = true to use NetClass value, false to use BOARD::m_designSettings value
  45. * return true if done, false if no not change (due to DRC error)
  46. */
  47. int initial_width, new_width;
  48. int initial_drill = -1,new_drill = -1;
  49. bool change_ok = false;
  50. NETINFO_ITEM* net = NULL;
  51. if( aUseNetclassValue )
  52. net = aTrackItem->GetNet();
  53. initial_width = aTrackItem->GetWidth();
  54. if( net )
  55. new_width = net->GetTrackWidth();
  56. else
  57. new_width = GetDesignSettings().GetCurrentTrackWidth();
  58. if( aTrackItem->Type() == PCB_VIA_T )
  59. {
  60. const VIA *via = static_cast<const VIA *>( aTrackItem );
  61. // Micro vias have a size only defined in their netclass
  62. // (no specific values defined by a table of specific value)
  63. // Ensure the netclass is accessible:
  64. if( via->GetViaType() == VIA_MICROVIA && net == NULL )
  65. net = aTrackItem->GetNet();
  66. // Get the draill value, regardless it is default or specific
  67. initial_drill = via->GetDrillValue();
  68. if( net )
  69. {
  70. new_width = net->GetViaSize();
  71. new_drill = net->GetViaDrillSize();
  72. }
  73. else
  74. {
  75. new_width = GetDesignSettings().GetCurrentViaSize();
  76. new_drill = GetDesignSettings().GetCurrentViaDrill();
  77. }
  78. if( via->GetViaType() == VIA_MICROVIA )
  79. {
  80. if( net )
  81. {
  82. new_width = net->GetMicroViaSize();
  83. new_drill = net->GetMicroViaDrillSize();
  84. }
  85. else
  86. {
  87. // Should not occur
  88. }
  89. }
  90. // Old versions set a drill value <= 0, when the default netclass it used
  91. // but it could be better to set the drill value to the actual value
  92. // to avoid issues for existing vias, if the default drill value is modified
  93. // in the netclass, and not in current vias.
  94. if( via->GetDrill() <= 0 ) // means default netclass drill value used
  95. {
  96. initial_drill = -1; // Force drill vias re-initialization
  97. }
  98. }
  99. aTrackItem->SetWidth( new_width );
  100. // make a DRC test because the new size is bigger than the old size
  101. if( initial_width < new_width )
  102. {
  103. int diagdrc = OK_DRC;
  104. if( Settings().m_legacyDrcOn )
  105. diagdrc = m_drc->Drc( aTrackItem, GetBoard()->m_Track );
  106. if( diagdrc == OK_DRC )
  107. change_ok = true;
  108. }
  109. else if( initial_width > new_width )
  110. {
  111. change_ok = true;
  112. }
  113. else if( (aTrackItem->Type() == PCB_VIA_T) )
  114. {
  115. // if a via has its drill value changed, force change
  116. if( initial_drill != new_drill )
  117. change_ok = true;
  118. }
  119. if( change_ok )
  120. {
  121. OnModify();
  122. if( aItemsListPicker )
  123. {
  124. aTrackItem->SetWidth( initial_width );
  125. ITEM_PICKER picker( aTrackItem, UR_CHANGED );
  126. picker.SetLink( aTrackItem->Clone() );
  127. aItemsListPicker->PushItem( picker );
  128. aTrackItem->SetWidth( new_width );
  129. if( aTrackItem->Type() == PCB_VIA_T )
  130. {
  131. // Set new drill value. Note: currently microvias have only a default drill value
  132. VIA *via = static_cast<VIA *>( aTrackItem );
  133. if( new_drill > 0 )
  134. via->SetDrill( new_drill );
  135. else
  136. via->SetDrillDefault();
  137. }
  138. }
  139. }
  140. else
  141. {
  142. aTrackItem->SetWidth( initial_width );
  143. }
  144. return change_ok;
  145. }
  146. /**
  147. * Function Edit_TrackSegm_Width
  148. * Modify one track segment width or one via diameter (using DRC control).
  149. * @param aDC = the curred device context (can be NULL)
  150. * @param aTrackItem = the track segment or via to modify
  151. */
  152. void PCB_EDIT_FRAME::Edit_TrackSegm_Width( wxDC* aDC, TRACK* aTrackItem )
  153. {
  154. PICKED_ITEMS_LIST itemsListPicker;
  155. bool change = SetTrackSegmentWidth( aTrackItem, &itemsListPicker, false );
  156. if( change == 0 || aTrackItem->GetFlags() )
  157. return; // No change
  158. // The segment has changed: redraw it and save it in undo list
  159. if( aDC )
  160. {
  161. TRACK* oldsegm = (TRACK*) itemsListPicker.GetPickedItemLink( 0 );
  162. wxASSERT( oldsegm );
  163. m_canvas->CrossHairOff( aDC ); // Erase cursor shape
  164. oldsegm->Draw( m_canvas, aDC, GR_XOR ); // Erase old track shape
  165. aTrackItem->Draw( m_canvas, aDC, GR_OR ); // Display new track shape
  166. m_canvas->CrossHairOn( aDC ); // Display cursor shape
  167. }
  168. SaveCopyInUndoList( itemsListPicker, UR_CHANGED );
  169. }
  170. void PCB_EDIT_FRAME::Edit_Track_Width( wxDC* aDC, TRACK* aTrackSegment )
  171. {
  172. /* Modify a full track (a trace) width (using DRC control).
  173. * a full track is the set of track segments between 2 nodes: pads or a node that has
  174. * more than 2 segments connected
  175. * aDC = the curred device context (can be NULL)
  176. * aTrackSegment = a via or a track belonging to the trace to change
  177. */
  178. TRACK* pt_track;
  179. int nb_segm;
  180. if( aTrackSegment == NULL )
  181. return;
  182. pt_track = GetBoard()->MarkTrace( aTrackSegment, &nb_segm, NULL, NULL, true );
  183. PICKED_ITEMS_LIST itemsListPicker;
  184. bool change = false;
  185. for( int ii = 0; ii < nb_segm; ii++, pt_track = pt_track->Next() )
  186. {
  187. pt_track->SetState( BUSY, false );
  188. if( SetTrackSegmentWidth( pt_track, &itemsListPicker, false ) )
  189. change = true;
  190. }
  191. if( !change )
  192. return;
  193. // Some segment have changed: redraw them and save in undo list
  194. if( aDC )
  195. {
  196. m_canvas->CrossHairOff( aDC ); // Erase cursor shape
  197. for( unsigned ii = 0; ii < itemsListPicker.GetCount(); ii++ )
  198. {
  199. TRACK* segm = (TRACK*) itemsListPicker.GetPickedItemLink( ii );
  200. segm->Draw( m_canvas, aDC, GR_XOR ); // Erase old track shape
  201. segm = (TRACK*) itemsListPicker.GetPickedItem( ii );
  202. segm->Draw( m_canvas, aDC, GR_OR ); // Display new track shape
  203. // fixme: commit!
  204. // segm->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
  205. }
  206. m_canvas->CrossHairOn( aDC ); // Display cursor shape
  207. }
  208. SaveCopyInUndoList( itemsListPicker, UR_CHANGED );
  209. }
  210. bool PCB_EDIT_FRAME::Change_Net_Tracks_And_Vias_Sizes( int aNetcode, bool aUseNetclassValue )
  211. {
  212. /* Reset all tracks width and vias diameters and drill
  213. * to their default Netclass value or current values
  214. * aNetcode : the netcode of the net to edit
  215. * aUseNetclassValue = true to use netclass values, false to use current values
  216. */
  217. TRACK* pt_segm;
  218. if( aNetcode <= 0 )
  219. return false;
  220. // Examine segments
  221. PICKED_ITEMS_LIST itemsListPicker;
  222. bool change = false;
  223. for( pt_segm = GetBoard()->m_Track; pt_segm != NULL; pt_segm = pt_segm->Next() )
  224. {
  225. if( aNetcode != pt_segm->GetNetCode() ) // not in net
  226. continue;
  227. // we have found a item member of the net
  228. if( SetTrackSegmentWidth( pt_segm, &itemsListPicker, aUseNetclassValue ) )
  229. change = true;
  230. }
  231. if( !change )
  232. return false;
  233. // Some segment have changed: save them in undo list
  234. SaveCopyInUndoList( itemsListPicker, UR_CHANGED );
  235. return true;
  236. }
  237. bool PCB_EDIT_FRAME::Reset_All_Tracks_And_Vias_To_Netclass_Values( bool aTrack, bool aVia )
  238. {
  239. TRACK* pt_segm;
  240. // read and edit tracks and vias if required
  241. PICKED_ITEMS_LIST itemsListPicker;
  242. bool change = false;
  243. for( pt_segm = GetBoard()->m_Track; pt_segm != NULL; pt_segm = pt_segm->Next() )
  244. {
  245. if( (pt_segm->Type() == PCB_VIA_T ) && aVia )
  246. {
  247. if( SetTrackSegmentWidth( pt_segm, &itemsListPicker, true ) )
  248. change = true;
  249. }
  250. if( (pt_segm->Type() == PCB_TRACE_T ) && aTrack )
  251. {
  252. if( SetTrackSegmentWidth( pt_segm, &itemsListPicker, true ) )
  253. change = true;
  254. }
  255. }
  256. if( !change )
  257. return false;
  258. // Some segment have changed: save them in undo list
  259. SaveCopyInUndoList( itemsListPicker, UR_CHANGED );
  260. return true;
  261. }