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.

239 lines
8.0 KiB

5 years ago
5 years ago
4 months ago
4 months ago
4 months ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
  5. * Copyright (C) 2008 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
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version 2
  11. * of the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, you may find one here:
  20. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  21. * or you may search the http://www.gnu.org website for the version 2 license,
  22. * or you may write to the Free Software Foundation, Inc.,
  23. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  24. */
  25. #include <pgm_base.h>
  26. #include <symbol_library.h>
  27. #include <settings/settings_manager.h>
  28. #include <project/project_file.h>
  29. #include <core/kicad_algo.h>
  30. #include <symbol_library_common.h>
  31. #include <confirm.h>
  32. #include <sch_tool_utils.h>
  33. #include <eeschema_id.h>
  34. #include <general.h>
  35. #include <kidialog.h>
  36. #include <kiway.h>
  37. #include <symbol_viewer_frame.h>
  38. #include <symbol_tree_model_adapter.h>
  39. #include <symbol_editor/symbol_editor_settings.h>
  40. #include <sch_symbol.h>
  41. #include <sch_commit.h>
  42. #include <sch_edit_frame.h>
  43. #include <symbol_lib_table.h>
  44. #include <tool/tool_manager.h>
  45. #include <tools/sch_actions.h>
  46. #include <project_sch.h>
  47. #include <dialog_symbol_chooser.h>
  48. PICKED_SYMBOL SCH_BASE_FRAME::PickSymbolFromLibrary( const SYMBOL_LIBRARY_FILTER* aFilter,
  49. std::vector<PICKED_SYMBOL>& aHistoryList,
  50. std::vector<PICKED_SYMBOL>& aAlreadyPlaced,
  51. bool aShowFootprints, const LIB_ID* aHighlight,
  52. bool aAllowFields )
  53. {
  54. std::unique_lock<std::mutex> dialogLock( DIALOG_SYMBOL_CHOOSER::g_Mutex, std::defer_lock );
  55. // One DIALOG_SYMBOL_CHOOSER dialog at a time. User probably can't handle more anyway.
  56. if( !dialogLock.try_lock() )
  57. return PICKED_SYMBOL();
  58. bool aCancelled = false;
  59. DIALOG_SYMBOL_CHOOSER dlg( this, aHighlight, aFilter, aHistoryList, aAlreadyPlaced,
  60. aAllowFields, aShowFootprints, aCancelled );
  61. if( aCancelled || dlg.ShowModal() == wxID_CANCEL )
  62. return PICKED_SYMBOL();
  63. PICKED_SYMBOL sel;
  64. LIB_ID id = dlg.GetSelectedLibId( &sel.Unit );
  65. if( !id.IsValid() )
  66. return PICKED_SYMBOL();
  67. if( sel.Unit == 0 )
  68. sel.Unit = 1;
  69. sel.Fields = dlg.GetFields();
  70. sel.LibId = id;
  71. if( sel.LibId.IsValid() )
  72. {
  73. alg::delete_if( aHistoryList, [&sel]( PICKED_SYMBOL const& i )
  74. {
  75. return i.LibId == sel.LibId;
  76. } );
  77. aHistoryList.insert( aHistoryList.begin(), sel );
  78. }
  79. return sel;
  80. }
  81. void SCH_EDIT_FRAME::SelectUnit( SCH_SYMBOL* aSymbol, int aUnit )
  82. {
  83. SCH_COMMIT commit( m_toolManager );
  84. LIB_SYMBOL* symbol = GetLibSymbol( aSymbol->GetLibId() );
  85. if( !symbol )
  86. return;
  87. const int unitCount = symbol->GetUnitCount();
  88. const int currentUnit = aSymbol->GetUnit();
  89. if( unitCount <= 1 || currentUnit == aUnit )
  90. return;
  91. if( aUnit > unitCount )
  92. aUnit = unitCount;
  93. const SCH_SHEET_PATH& sheetPath = GetCurrentSheet();
  94. bool swapWithOther = false;
  95. std::optional<SCH_REFERENCE> otherSymbolRef = FindSymbolByRefAndUnit( *aSymbol->Schematic(),
  96. aSymbol->GetRef( &sheetPath, false ),
  97. aUnit );
  98. if( otherSymbolRef )
  99. {
  100. const wxString targetUnitName = symbol->GetUnitDisplayName( aUnit );
  101. const wxString currUnitName = symbol->GetUnitDisplayName( currentUnit );
  102. wxString otherSheetName = otherSymbolRef->GetSheetPath().PathHumanReadable( true, true );
  103. if( otherSheetName.IsEmpty() )
  104. otherSheetName = _( "Root" );
  105. const wxString msg = wxString::Format( _( "Symbol unit '%s' is already placed (on sheet '%s')" ),
  106. targetUnitName, otherSheetName );
  107. KIDIALOG dlg( this, msg, _( "Unit Already Placed" ), wxYES_NO | wxCANCEL | wxICON_WARNING );
  108. dlg.SetYesNoLabels( wxString::Format( _( "&Swap '%s' and '%s'" ), targetUnitName, currUnitName ),
  109. wxString::Format( _( "&Duplicate '%s'" ), targetUnitName ) );
  110. dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
  111. int ret = dlg.ShowModal();
  112. if( ret == wxID_CANCEL )
  113. return;
  114. if( ret == wxID_YES )
  115. swapWithOther = true;
  116. }
  117. if( swapWithOther )
  118. {
  119. // We were reliably informed this would exist.
  120. wxASSERT( otherSymbolRef );
  121. SCH_SYMBOL* otherSymbol = otherSymbolRef->GetSymbol();
  122. if( !otherSymbol->GetEditFlags() )
  123. commit.Modify( otherSymbol, otherSymbolRef->GetSheetPath().LastScreen() );
  124. // Give that symbol the unit we used to have
  125. otherSymbol->SetUnitSelection( &otherSymbolRef->GetSheetPath(), currentUnit );
  126. otherSymbol->SetUnit( currentUnit );
  127. }
  128. if( !aSymbol->GetEditFlags() ) // No command in progress: save in undo list
  129. commit.Modify( aSymbol, GetScreen() );
  130. // Update the unit number.
  131. aSymbol->SetUnit( aUnit );
  132. aSymbol->SetUnitSelection( &sheetPath, aUnit );
  133. if( !commit.Empty() )
  134. {
  135. if( eeconfig()->m_AutoplaceFields.enable )
  136. {
  137. AUTOPLACE_ALGO fieldsAutoplaced = aSymbol->GetFieldsAutoplaced();
  138. if( fieldsAutoplaced == AUTOPLACE_AUTO || fieldsAutoplaced == AUTOPLACE_MANUAL )
  139. aSymbol->AutoplaceFields( GetScreen(), fieldsAutoplaced );
  140. }
  141. if( swapWithOther )
  142. commit.Push( _( "Swap Units" ) );
  143. else
  144. commit.Push( _( "Change Unit" ) );
  145. }
  146. }
  147. void SCH_EDIT_FRAME::FlipBodyStyle( SCH_SYMBOL* aSymbol )
  148. {
  149. if( !aSymbol || !aSymbol->GetLibSymbolRef() )
  150. return;
  151. SCH_COMMIT commit( m_toolManager );
  152. wxString msg;
  153. if( !aSymbol->GetLibSymbolRef()->HasAlternateBodyStyle() )
  154. {
  155. LIB_ID id = aSymbol->GetLibSymbolRef()->GetLibId();
  156. msg.Printf( _( "No alternate body style found for symbol '%s' in library '%s'." ),
  157. id.GetLibItemName().wx_str(),
  158. id.GetLibNickname().wx_str() );
  159. DisplayError( this, msg );
  160. return;
  161. }
  162. commit.Modify( aSymbol, GetScreen() );
  163. aSymbol->SetBodyStyle( aSymbol->GetBodyStyle() + 1 );
  164. // ensure m_bodyStyle = 1 or 2
  165. // 1 = shape 1 = first (base DeMorgan) alternate body style
  166. // 2 = shape 2 = second (DeMorgan conversion) alternate body style
  167. // > 2 is not currently supported
  168. // When m_bodyStyle = val max, return to the first shape
  169. if( aSymbol->GetBodyStyle() > BODY_STYLE::DEMORGAN )
  170. aSymbol->SetBodyStyle( BODY_STYLE::BASE );
  171. // If selected make sure all the now-included pins are selected
  172. if( aSymbol->IsSelected() )
  173. m_toolManager->RunAction<EDA_ITEM*>( ACTIONS::selectItem, aSymbol );
  174. commit.Push( _( "Change Body Style" ) );
  175. }
  176. void SCH_EDIT_FRAME::SetAltPinFunction( SCH_PIN* aPin, const wxString& aFunction )
  177. {
  178. if( !aPin )
  179. return;
  180. SCH_COMMIT commit( m_toolManager );
  181. commit.Modify( aPin, GetScreen() );
  182. if( aFunction == aPin->GetName() )
  183. aPin->SetAlt( wxEmptyString );
  184. else
  185. aPin->SetAlt( aFunction );
  186. commit.Push( _( "Set Pin Function" ) );
  187. }