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.

277 lines
9.1 KiB

18 years ago
18 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2004-2020 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 <algorithm>
  24. #include <sch_draw_panel.h>
  25. #include <confirm.h>
  26. #include <reporter.h>
  27. #include <sch_edit_frame.h>
  28. #include <schematic.h>
  29. #include <sch_reference_list.h>
  30. #include <class_library.h>
  31. void SCH_EDIT_FRAME::mapExistingAnnotation( std::map<wxString, wxString>& aMap )
  32. {
  33. SCH_REFERENCE_LIST references;
  34. Schematic().GetSheets().GetSymbols( references );
  35. for( size_t i = 0; i < references.GetCount(); i++ )
  36. {
  37. SCH_COMPONENT* comp = references[ i ].GetSymbol();
  38. SCH_SHEET_PATH* curr_sheetpath = &references[ i ].GetSheetPath();
  39. KIID_PATH curr_full_uuid = curr_sheetpath->Path();
  40. curr_full_uuid.push_back( comp->m_Uuid );
  41. wxString ref = comp->GetRef( curr_sheetpath );
  42. if( comp->GetUnitCount() > 1 )
  43. ref << LIB_PART::SubReference( comp->GetUnitSelection( curr_sheetpath ) );
  44. if( comp->IsAnnotated( curr_sheetpath ) )
  45. aMap[ curr_full_uuid.AsString() ] = ref;
  46. }
  47. }
  48. void SCH_EDIT_FRAME::DeleteAnnotation( bool aCurrentSheetOnly, bool* aAppendUndo )
  49. {
  50. auto clearAnnotation =
  51. [&]( SCH_SCREEN* aScreen, SCH_SHEET_PATH* aSheet )
  52. {
  53. for( SCH_ITEM* item : aScreen->Items().OfType( SCH_COMPONENT_T ) )
  54. {
  55. SCH_COMPONENT* component = static_cast<SCH_COMPONENT*>( item );
  56. SaveCopyInUndoList( aScreen, component, UNDO_REDO::CHANGED, *aAppendUndo );
  57. *aAppendUndo = true;
  58. component->ClearAnnotation( aSheet );
  59. }
  60. };
  61. if( aCurrentSheetOnly )
  62. {
  63. clearAnnotation( GetScreen(), &GetCurrentSheet() );
  64. }
  65. else
  66. {
  67. for( const SCH_SHEET_PATH& sheet : Schematic().GetSheets() )
  68. clearAnnotation( sheet.LastScreen(), nullptr );
  69. }
  70. // Update the references for the sheet that is currently being displayed.
  71. GetCurrentSheet().UpdateAllScreenReferences();
  72. SyncView();
  73. GetCanvas()->Refresh();
  74. OnModify();
  75. // Must go after OnModify() so the connectivity graph has been updated
  76. UpdateNetHighlightStatus();
  77. }
  78. void SCH_EDIT_FRAME::AnnotateComponents( bool aAnnotateSchematic,
  79. ANNOTATE_ORDER_T aSortOption,
  80. ANNOTATE_OPTION_T aAlgoOption,
  81. int aStartNumber,
  82. bool aResetAnnotation,
  83. bool aRepairTimestamps,
  84. bool aLockUnits,
  85. REPORTER& aReporter )
  86. {
  87. SCH_REFERENCE_LIST references;
  88. SCH_SCREENS screens( Schematic().Root() );
  89. SCH_SHEET_LIST sheets = Schematic().GetSheets();
  90. bool appendUndo = false;
  91. // Map of locked components
  92. SCH_MULTI_UNIT_REFERENCE_MAP lockedComponents;
  93. // Map of previous annotation for building info messages
  94. std::map<wxString, wxString> previousAnnotation;
  95. // Test for and replace duplicate time stamps in components and sheets. Duplicate
  96. // time stamps can happen with old schematics, schematic conversions, or manual
  97. // editing of files.
  98. if( aRepairTimestamps )
  99. {
  100. int count = screens.ReplaceDuplicateTimeStamps();
  101. if( count )
  102. {
  103. wxString msg;
  104. msg.Printf( _( "%d duplicate time stamps were found and replaced." ), count );
  105. aReporter.ReportTail( msg, RPT_SEVERITY_WARNING );
  106. }
  107. }
  108. // If units must be locked, collect all the sets that must be annotated together.
  109. if( aLockUnits )
  110. {
  111. if( aAnnotateSchematic )
  112. sheets.GetMultiUnitSymbols( lockedComponents );
  113. else
  114. GetCurrentSheet().GetMultiUnitComponents( lockedComponents );
  115. }
  116. // Store previous annotations for building info messages
  117. mapExistingAnnotation( previousAnnotation );
  118. // If it is an annotation for all the components, reset previous annotation.
  119. if( aResetAnnotation )
  120. DeleteAnnotation( !aAnnotateSchematic, &appendUndo );
  121. // Set sheet number and number of sheets.
  122. SetSheetNumberAndCount();
  123. // Build component list
  124. if( aAnnotateSchematic )
  125. sheets.GetSymbols( references );
  126. else
  127. GetCurrentSheet().GetSymbols( references );
  128. // Break full components reference in name (prefix) and number:
  129. // example: IC1 become IC, and 1
  130. references.SplitReferences();
  131. switch( aSortOption )
  132. {
  133. default:
  134. case SORT_BY_X_POSITION: references.SortByXCoordinate(); break;
  135. case SORT_BY_Y_POSITION: references.SortByYCoordinate(); break;
  136. }
  137. bool useSheetNum = false;
  138. int idStep = 100;
  139. switch( aAlgoOption )
  140. {
  141. default:
  142. case INCREMENTAL_BY_REF:
  143. break;
  144. case SHEET_NUMBER_X_100:
  145. useSheetNum = true;
  146. break;
  147. case SHEET_NUMBER_X_1000:
  148. useSheetNum = true;
  149. idStep = 1000;
  150. break;
  151. }
  152. // Recalculate and update reference numbers in schematic
  153. references.Annotate( useSheetNum, idStep, aStartNumber, lockedComponents );
  154. for( size_t i = 0; i < references.GetCount(); i++ )
  155. {
  156. SCH_REFERENCE& ref = references[i];
  157. SCH_COMPONENT* symbol = ref.GetSymbol();
  158. SCH_SHEET_PATH* sheet = &ref.GetSheetPath();
  159. SaveCopyInUndoList( sheet->LastScreen(), symbol, UNDO_REDO::CHANGED, appendUndo );
  160. appendUndo = true;
  161. ref.Annotate();
  162. KIID_PATH full_uuid = sheet->Path();
  163. full_uuid.push_back( symbol->m_Uuid );
  164. wxString prevRef = previousAnnotation[ full_uuid.AsString() ];
  165. wxString newRef = symbol->GetRef( sheet );
  166. if( symbol->GetUnitCount() > 1 )
  167. newRef << LIB_PART::SubReference( symbol->GetUnitSelection( sheet ) );
  168. wxString msg;
  169. if( prevRef.Length() )
  170. {
  171. if( newRef == prevRef )
  172. continue;
  173. if( symbol->GetUnitCount() > 1 )
  174. msg.Printf( _( "Updated %s (unit %s) from %s to %s" ),
  175. symbol->GetValue( sheet, true ),
  176. LIB_PART::SubReference( symbol->GetUnit(), false ),
  177. prevRef,
  178. newRef );
  179. else
  180. msg.Printf( _( "Updated %s from %s to %s" ),
  181. symbol->GetValue( sheet, true ),
  182. prevRef,
  183. newRef );
  184. }
  185. else
  186. {
  187. if( symbol->GetUnitCount() > 1 )
  188. msg.Printf( _( "Annotated %s (unit %s) as %s" ),
  189. symbol->GetValue( sheet, true ),
  190. LIB_PART::SubReference( symbol->GetUnit(), false ),
  191. newRef );
  192. else
  193. msg.Printf( _( "Annotated %s as %s" ),
  194. symbol->GetValue( sheet, true ),
  195. newRef );
  196. }
  197. aReporter.Report( msg, RPT_SEVERITY_ACTION );
  198. }
  199. // Final control (just in case ... ).
  200. if( !CheckAnnotate( aReporter, !aAnnotateSchematic ) )
  201. aReporter.ReportTail( _( "Annotation complete." ), RPT_SEVERITY_ACTION );
  202. // Update on screen references, that can be modified by previous calculations:
  203. GetCurrentSheet().UpdateAllScreenReferences();
  204. SetSheetNumberAndCount();
  205. SyncView();
  206. GetCanvas()->Refresh();
  207. OnModify();
  208. // Must go after OnModify() so the connectivity graph has been updated
  209. UpdateNetHighlightStatus();
  210. }
  211. int SCH_EDIT_FRAME::CheckAnnotate( REPORTER& aReporter, bool aOneSheetOnly )
  212. {
  213. SCH_REFERENCE_LIST referenceList;
  214. constexpr bool includePowerSymbols = false;
  215. // Build the list of symbols
  216. if( !aOneSheetOnly )
  217. Schematic().GetSheets().GetSymbols( referenceList, includePowerSymbols );
  218. else
  219. GetCurrentSheet().GetSymbols( referenceList );
  220. // Empty schematic does not need annotation
  221. if( referenceList.GetCount() == 0 )
  222. return 0;
  223. return referenceList.CheckAnnotation( aReporter );
  224. }