diff --git a/eeschema/annotate.cpp b/eeschema/annotate.cpp index 3fccb8e1f9..f041fe39a5 100644 --- a/eeschema/annotate.cpp +++ b/eeschema/annotate.cpp @@ -38,6 +38,7 @@ #include #include +#include void SCH_EDIT_FRAME::DeleteAnnotation( bool aCurrentSheetOnly ) { @@ -62,7 +63,8 @@ void SCH_EDIT_FRAME::AnnotateComponents( bool aAnnotateSchematic, ANNOTATE_ORDER_T aSortOption, ANNOTATE_OPTION_T aAlgoOption, bool aResetAnnotation, - bool aRepairTimestamps ) + bool aRepairTimestamps, + bool aLockUnits ) { SCH_REFERENCE_LIST references; @@ -73,6 +75,9 @@ void SCH_EDIT_FRAME::AnnotateComponents( bool aAnnotateSchematic, // Build the sheet list. SCH_SHEET_LIST sheets; + // Map of locked components + SCH_MULTI_UNIT_REFERENCE_MAP lockedComponents; + // Test for and replace duplicate time stamps in components and sheets. Duplicate // time stamps can happen with old schematics, schematic conversions, or manual // editing of files. @@ -88,6 +93,19 @@ void SCH_EDIT_FRAME::AnnotateComponents( bool aAnnotateSchematic, } } + // If units must be locked, collect all the sets that must be annotated together. + if( aLockUnits ) + { + if( aAnnotateSchematic ) + { + sheets.GetMultiUnitComponents( Prj().SchLibs(), lockedComponents ); + } + else + { + m_CurrentSheet->GetMultiUnitComponents( Prj().SchLibs(), lockedComponents ); + } + } + // If it is an annotation for all the components, reset previous annotation. if( aResetAnnotation ) DeleteAnnotation( !aAnnotateSchematic ); @@ -141,7 +159,7 @@ void SCH_EDIT_FRAME::AnnotateComponents( bool aAnnotateSchematic, } // Recalculate and update reference numbers in schematic - references.Annotate( useSheetNum, idStep ); + references.Annotate( useSheetNum, idStep, lockedComponents ); references.UpdateAnnotation(); wxArrayString errors; diff --git a/eeschema/component_references_lister.cpp b/eeschema/component_references_lister.cpp index 15eb9e6dca..6796ef398a 100644 --- a/eeschema/component_references_lister.cpp +++ b/eeschema/component_references_lister.cpp @@ -39,6 +39,8 @@ #include #include +#include + //#define USE_OLD_ALGO @@ -283,7 +285,8 @@ int SCH_REFERENCE_LIST::CreateFirstFreeRefId( std::vector& aIdList, int aFi } -void SCH_REFERENCE_LIST::Annotate( bool aUseSheetNum, int aSheetIntervalId ) +void SCH_REFERENCE_LIST::Annotate( bool aUseSheetNum, int aSheetIntervalId, + SCH_MULTI_UNIT_REFERENCE_MAP aLockedUnitMap ) { if ( componentFlatList.size() == 0 ) return; @@ -327,6 +330,24 @@ void SCH_REFERENCE_LIST::Annotate( bool aUseSheetNum, int aSheetIntervalId ) if( componentFlatList[ii].m_Flag ) continue; + // Check whether this component is in aLockedUnitMap. + SCH_REFERENCE_LIST* lockedList = NULL; + BOOST_FOREACH( SCH_MULTI_UNIT_REFERENCE_MAP::value_type& pair, aLockedUnitMap ) + { + unsigned n_refs = pair.second.GetCount(); + for( unsigned thisRefI = 0; thisRefI < n_refs; ++thisRefI ) + { + SCH_REFERENCE &thisRef = pair.second[thisRefI]; + + if( thisRef.IsSameInstance( componentFlatList[ii] ) ) + { + lockedList = &pair.second; + break; + } + } + if( lockedList != NULL ) break; + } + if( ( componentFlatList[first].CompareRef( componentFlatList[ii] ) != 0 ) || ( aUseSheetNum && ( componentFlatList[first].m_SheetNum != componentFlatList[ii].m_SheetNum ) ) ) { @@ -388,50 +409,83 @@ void SCH_REFERENCE_LIST::Annotate( bool aUseSheetNum, int aSheetIntervalId ) componentFlatList[ii].m_Flag = 1; } - /* search for others units of this component. - * we search for others parts that have the same value and the same - * reference prefix (ref without ref number) - */ - for( Unit = 1; Unit <= NumberOfUnits; Unit++ ) + // If this component is in aLockedUnitMap, copy the annotation to all + // components that are not it + if( lockedList != NULL ) { - if( componentFlatList[ii].m_Unit == Unit ) - continue; - - int found = FindUnit( ii, Unit ); - - if( found >= 0 ) - continue; // this unit exists for this reference (unit already annotated) - - // Search a component to annotate ( same prefix, same value, not annotated) - for( unsigned jj = ii + 1; jj < componentFlatList.size(); jj++ ) + unsigned n_refs = lockedList->GetCount(); + for( unsigned thisRefI = 0; thisRefI < n_refs; ++thisRefI ) { - if( componentFlatList[jj].m_Flag ) // already tested - continue; - - if( componentFlatList[ii].CompareRef( componentFlatList[jj] ) != 0 ) - continue; - - if( componentFlatList[jj].CompareValue( componentFlatList[ii] ) != 0 ) - continue; - - if( componentFlatList[jj].CompareLibName( componentFlatList[ii] ) != 0 ) - continue; - - if( !componentFlatList[jj].m_IsNew ) - continue; - - // Component without reference number found, annotate it if possible - if( !componentFlatList[jj].IsUnitsLocked() - || ( componentFlatList[jj].m_Unit == Unit ) ) + SCH_REFERENCE &thisRef = (*lockedList)[thisRefI]; + if( thisRef.IsSameInstance( componentFlatList[ii] ) ) { + // This is the component we're currently annotating. Hold the unit! + componentFlatList[ii].m_Unit = thisRef.m_Unit; + } + + if( thisRef.CompareValue( componentFlatList[ii] ) != 0 ) continue; + if( thisRef.CompareLibName( componentFlatList[ii] ) != 0 ) continue; + + // Find the matching component + for( unsigned jj = ii + 1; jj < componentFlatList.size(); jj++ ) + { + if( ! thisRef.IsSameInstance( componentFlatList[jj] ) ) continue; componentFlatList[jj].m_NumRef = componentFlatList[ii].m_NumRef; - componentFlatList[jj].m_Unit = Unit; - componentFlatList[jj].m_Flag = 1; - componentFlatList[jj].m_IsNew = false; + componentFlatList[jj].m_Unit = thisRef.m_Unit; + componentFlatList[jj].m_IsNew = false; + componentFlatList[jj].m_Flag = 1; break; } } } + + else + { + /* search for others units of this component. + * we search for others parts that have the same value and the same + * reference prefix (ref without ref number) + */ + for( Unit = 1; Unit <= NumberOfUnits; Unit++ ) + { + if( componentFlatList[ii].m_Unit == Unit ) + continue; + + int found = FindUnit( ii, Unit ); + + if( found >= 0 ) + continue; // this unit exists for this reference (unit already annotated) + + // Search a component to annotate ( same prefix, same value, not annotated) + for( unsigned jj = ii + 1; jj < componentFlatList.size(); jj++ ) + { + if( componentFlatList[jj].m_Flag ) // already tested + continue; + + if( componentFlatList[ii].CompareRef( componentFlatList[jj] ) != 0 ) + continue; + + if( componentFlatList[jj].CompareValue( componentFlatList[ii] ) != 0 ) + continue; + + if( componentFlatList[jj].CompareLibName( componentFlatList[ii] ) != 0 ) + continue; + + if( !componentFlatList[jj].m_IsNew ) + continue; + + // Component without reference number found, annotate it if possible + if( !componentFlatList[jj].IsUnitsLocked() + || ( componentFlatList[jj].m_Unit == Unit ) ) + { + componentFlatList[jj].m_NumRef = componentFlatList[ii].m_NumRef; + componentFlatList[jj].m_Unit = Unit; + componentFlatList[jj].m_Flag = 1; + componentFlatList[jj].m_IsNew = false; + break; + } + } + } + } } } diff --git a/eeschema/dialogs/dialog_annotate.cpp b/eeschema/dialogs/dialog_annotate.cpp index 8cf2c1dac5..55ab3a4034 100644 --- a/eeschema/dialogs/dialog_annotate.cpp +++ b/eeschema/dialogs/dialog_annotate.cpp @@ -67,6 +67,7 @@ private: // User functions: bool GetLevel(); bool GetResetItems(); + bool GetLockUnits(); /** * Function GetSortOrder @@ -212,7 +213,7 @@ void DIALOG_ANNOTATE::OnApplyClick( wxCommandEvent& event ) m_Parent->AnnotateComponents( GetLevel(), (ANNOTATE_ORDER_T) GetSortOrder(), (ANNOTATE_OPTION_T) GetAnnotateAlgo(), - GetResetItems() , true ); + GetResetItems() , true, GetLockUnits() ); m_Parent->GetCanvas()->Refresh(); m_btnClear->Enable(); @@ -273,9 +274,13 @@ bool DIALOG_ANNOTATE::GetLevel() bool DIALOG_ANNOTATE::GetResetItems() { - return m_rbResetAnnotation->GetValue(); + return m_rbResetAnnotation->GetValue() || m_rbResetButLock->GetValue(); } +bool DIALOG_ANNOTATE::GetLockUnits() +{ + return m_rbResetButLock->GetValue(); +} int DIALOG_ANNOTATE::GetSortOrder() { diff --git a/eeschema/dialogs/dialog_annotate_base.cpp b/eeschema/dialogs/dialog_annotate_base.cpp index 83fb59b599..8209403c8c 100644 --- a/eeschema/dialogs/dialog_annotate_base.cpp +++ b/eeschema/dialogs/dialog_annotate_base.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Jun 6 2014) +// C++ code generated with wxFormBuilder (version Mar 13 2015) // http://www.wxformbuilder.org/ // // PLEASE DO "NOT" EDIT THIS FILE! @@ -43,6 +43,9 @@ DIALOG_ANNOTATE_BASE::DIALOG_ANNOTATE_BASE( wxWindow* parent, wxWindowID id, con m_rbResetAnnotation = new wxRadioButton( this, ID_RESET_ANNOTATION, _("&Reset existing annotation"), wxDefaultPosition, wxDefaultSize, 0 ); bscopeOptSizer->Add( m_rbResetAnnotation, 0, wxALL, 3 ); + m_rbResetButLock = new wxRadioButton( this, ID_RESET_BUT_LOCK, _("R&eset, but do not swap any annotated multi-unit parts"), wxDefaultPosition, wxDefaultSize, 0 ); + bscopeOptSizer->Add( m_rbResetButLock, 0, wxALL, 3 ); + bupperSizer->Add( bscopeOptSizer, 0, wxEXPAND|wxLEFT|wxALIGN_RIGHT, 25 ); diff --git a/eeschema/dialogs/dialog_annotate_base.fbp b/eeschema/dialogs/dialog_annotate_base.fbp index ebf4f0fd9d..b836390bd8 100644 --- a/eeschema/dialogs/dialog_annotate_base.fbp +++ b/eeschema/dialogs/dialog_annotate_base.fbp @@ -627,6 +627,94 @@ + + 3 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + ID_RESET_BUT_LOCK + R&eset, but do not swap any annotated multi-unit parts + + 0 + + + 0 + + 1 + m_rbResetButLock + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/eeschema/dialogs/dialog_annotate_base.h b/eeschema/dialogs/dialog_annotate_base.h index a6161ee3b4..3fce47b4ee 100644 --- a/eeschema/dialogs/dialog_annotate_base.h +++ b/eeschema/dialogs/dialog_annotate_base.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Jun 6 2014) +// C++ code generated with wxFormBuilder (version Mar 13 2015) // http://www.wxformbuilder.org/ // // PLEASE DO "NOT" EDIT THIS FILE! @@ -37,9 +37,10 @@ class DIALOG_SHIM; #define ID_CURRENT_PAGE 1001 #define ID_KEEP_ANNOTATION 1002 #define ID_RESET_ANNOTATION 1003 -#define ID_SORT_BY_X_POSITION 1004 -#define ID_SORT_BY_Y_POSITION 1005 -#define ID_CLEAR_ANNOTATION_CMP 1006 +#define ID_RESET_BUT_LOCK 1004 +#define ID_SORT_BY_X_POSITION 1005 +#define ID_SORT_BY_Y_POSITION 1006 +#define ID_CLEAR_ANNOTATION_CMP 1007 /////////////////////////////////////////////////////////////////////////////// /// Class DIALOG_ANNOTATE_BASE @@ -55,6 +56,7 @@ class DIALOG_ANNOTATE_BASE : public DIALOG_SHIM wxStaticLine* m_staticline1; wxRadioButton* m_rbKeepAnnotation; wxRadioButton* m_rbResetAnnotation; + wxRadioButton* m_rbResetButLock; wxStaticLine* m_staticline2; wxStaticText* m_staticTextOrder; wxRadioButton* m_rbSortBy_X_Position; diff --git a/eeschema/dialogs/dialog_edit_one_field.cpp b/eeschema/dialogs/dialog_edit_one_field.cpp index 60ef3a6aee..13bd957b95 100644 --- a/eeschema/dialogs/dialog_edit_one_field.cpp +++ b/eeschema/dialogs/dialog_edit_one_field.cpp @@ -62,6 +62,7 @@ void DIALOG_EDIT_ONE_FIELD::initDlg_base() m_Invisible->SetValue( m_text_invisible ); m_TextShapeOpt->SetSelection( m_textshape ); + SetPowerWarning( false ); switch ( m_textHjustify ) { @@ -97,8 +98,15 @@ void DIALOG_EDIT_ONE_FIELD::initDlg_base() m_TextSizeText->SetLabel( msg ); m_sdbSizerButtonsOK->SetDefault(); + } +void DIALOG_EDIT_ONE_FIELD::SetPowerWarning( bool aWarn ) +{ + m_PowerComponentValues->Show( aWarn ); + m_TextValue->Enable( ! aWarn ); + Fit(); +} void DIALOG_EDIT_ONE_FIELD::OnTextValueSelectButtonClick( wxCommandEvent& aEvent ) { @@ -159,8 +167,11 @@ wxString DIALOG_LIB_EDIT_ONE_FIELD::GetTextField() } -void DIALOG_EDIT_ONE_FIELD::TransfertDataToField() +void DIALOG_EDIT_ONE_FIELD::TransfertDataToField( bool aIncludeText ) { + // This method doesn't transfer text anyway. + (void) aIncludeText; + m_textorient = m_Orient->GetValue() ? TEXT_ORIENT_VERT : TEXT_ORIENT_HORIZ; wxString msg = m_TextSize->GetValue(); m_textsize = ValueFromString( g_UserUnit, msg ); @@ -197,11 +208,12 @@ void DIALOG_EDIT_ONE_FIELD::TransfertDataToField() } -void DIALOG_LIB_EDIT_ONE_FIELD::TransfertDataToField() +void DIALOG_LIB_EDIT_ONE_FIELD::TransfertDataToField( bool aIncludeText ) { - DIALOG_EDIT_ONE_FIELD::TransfertDataToField(); + DIALOG_EDIT_ONE_FIELD::TransfertDataToField( aIncludeText ); - m_field->SetText( GetTextField() ); + if( aIncludeText ) + m_field->SetText( GetTextField() ); m_field->SetSize( wxSize( m_textsize, m_textsize ) ); m_field->SetOrientation( m_textorient ); @@ -255,11 +267,12 @@ wxString DIALOG_SCH_EDIT_ONE_FIELD::GetTextField() }; -void DIALOG_SCH_EDIT_ONE_FIELD::TransfertDataToField() +void DIALOG_SCH_EDIT_ONE_FIELD::TransfertDataToField( bool aIncludeText ) { - DIALOG_EDIT_ONE_FIELD::TransfertDataToField(); + DIALOG_EDIT_ONE_FIELD::TransfertDataToField( aIncludeText ); - m_field->SetText( GetTextField() ); + if( aIncludeText ) + m_field->SetText( GetTextField() ); m_field->SetSize( wxSize( m_textsize, m_textsize ) ); m_field->SetOrientation( m_textorient ); diff --git a/eeschema/dialogs/dialog_edit_one_field.h b/eeschema/dialogs/dialog_edit_one_field.h index 7edd99b1bf..c52d4efd15 100644 --- a/eeschema/dialogs/dialog_edit_one_field.h +++ b/eeschema/dialogs/dialog_edit_one_field.h @@ -74,14 +74,27 @@ public: /** * Function TransfertDataToField * Converts fields from dialog window to variables to be used by child classes + * + * @param aIncludeText Whether the valies transferred should include the actual + * item text. If this is false, formatting will be transferred, but text will + * not. */ - virtual void TransfertDataToField(); + virtual void TransfertDataToField( bool aIncludeText = true ); void SetTextField( const wxString& aText ) { m_TextValue->SetValue( aText ); } + /** + * Function SetPowerWarning + * Disables the Text field and displays the "Power component values cannot + * be modified!" warning, if aWarn is true. Performs the inverse if aWarn + * is false (this, however, is the default). + * + * @param aWarn whether or not to produce the warning + */ + void SetPowerWarning( bool aWarn ); protected: /** @@ -143,7 +156,7 @@ public: ~DIALOG_LIB_EDIT_ONE_FIELD() {}; - void TransfertDataToField(); + void TransfertDataToField( bool aIncludeText = true ); /** * Function GetTextField @@ -186,7 +199,7 @@ public: // ~DIALOG_SCH_EDIT_ONE_FIELD() {}; - void TransfertDataToField(); + void TransfertDataToField( bool aIncludeText = true ); /** * Function GetTextField diff --git a/eeschema/dialogs/dialog_lib_edit_text_base.cpp b/eeschema/dialogs/dialog_lib_edit_text_base.cpp index 70324cc052..3a3f4ca441 100644 --- a/eeschema/dialogs/dialog_lib_edit_text_base.cpp +++ b/eeschema/dialogs/dialog_lib_edit_text_base.cpp @@ -64,6 +64,12 @@ DIALOG_LIB_EDIT_TEXT_BASE::DIALOG_LIB_EDIT_TEXT_BASE( wxWindow* parent, wxWindow bPropertiesSizer->Add( bUpperBoxSizer, 0, wxEXPAND, 5 ); + m_PowerComponentValues = new wxStaticText( this, wxID_ANY, _("Power component value text cannot be modified!"), wxDefaultPosition, wxDefaultSize, 0 ); + m_PowerComponentValues->Wrap( -1 ); + m_PowerComponentValues->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); + + bPropertiesSizer->Add( m_PowerComponentValues, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + wxBoxSizer* bBottomtBoxSizer; bBottomtBoxSizer = new wxBoxSizer( wxHORIZONTAL ); @@ -91,7 +97,7 @@ DIALOG_LIB_EDIT_TEXT_BASE::DIALOG_LIB_EDIT_TEXT_BASE( wxWindow* parent, wxWindow wxString m_TextShapeOptChoices[] = { _("Normal"), _("Italic"), _("Bold"), _("Bold Italic") }; int m_TextShapeOptNChoices = sizeof( m_TextShapeOptChoices ) / sizeof( wxString ); m_TextShapeOpt = new wxRadioBox( this, wxID_ANY, _("Style"), wxDefaultPosition, wxDefaultSize, m_TextShapeOptNChoices, m_TextShapeOptChoices, 1, wxRA_SPECIFY_COLS ); - m_TextShapeOpt->SetSelection( 3 ); + m_TextShapeOpt->SetSelection( 0 ); bBottomtBoxSizer->Add( m_TextShapeOpt, 1, wxALL|wxEXPAND, 5 ); wxString m_TextHJustificationOptChoices[] = { _("Align left"), _("Align center"), _("Align right") }; @@ -130,7 +136,6 @@ DIALOG_LIB_EDIT_TEXT_BASE::DIALOG_LIB_EDIT_TEXT_BASE( wxWindow* parent, wxWindow this->SetSizer( bMainSizer ); this->Layout(); - bMainSizer->Fit( this ); // Connect Events this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_LIB_EDIT_TEXT_BASE::OnCloseDialog ) ); diff --git a/eeschema/dialogs/dialog_lib_edit_text_base.fbp b/eeschema/dialogs/dialog_lib_edit_text_base.fbp index 66f66954f1..fd885ec994 100644 --- a/eeschema/dialogs/dialog_lib_edit_text_base.fbp +++ b/eeschema/dialogs/dialog_lib_edit_text_base.fbp @@ -44,7 +44,7 @@ DIALOG_LIB_EDIT_TEXT_BASE - -1,-1 + 615,343 wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER DIALOG_SHIM; dialog_shim.h Library Text Properties @@ -395,11 +395,11 @@ - + 5 0 - + bTextSizeSizer wxVERTICAL @@ -582,6 +582,89 @@ + + 5 + wxBOTTOM|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + ,90,92,-1,70,0 + 0 + 0 + wxID_ANY + Power component value text cannot be modified! + + 0 + + + 0 + + 1 + m_PowerComponentValues + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + 5 wxALIGN_CENTER|wxEXPAND @@ -1088,7 +1171,7 @@ 1 Resizable - 3 + 0 1 wxRA_SPECIFY_COLS diff --git a/eeschema/dialogs/dialog_lib_edit_text_base.h b/eeschema/dialogs/dialog_lib_edit_text_base.h index e935857cb3..1580543e55 100644 --- a/eeschema/dialogs/dialog_lib_edit_text_base.h +++ b/eeschema/dialogs/dialog_lib_edit_text_base.h @@ -44,6 +44,7 @@ class DIALOG_LIB_EDIT_TEXT_BASE : public DIALOG_SHIM wxButton* m_TextValueSelectButton; wxStaticText* m_TextSizeText; wxTextCtrl* m_TextSize; + wxStaticText* m_PowerComponentValues; wxCheckBox* m_Orient; wxStaticLine* m_staticline1; wxCheckBox* m_CommonUnit; @@ -65,7 +66,7 @@ class DIALOG_LIB_EDIT_TEXT_BASE : public DIALOG_SHIM public: - DIALOG_LIB_EDIT_TEXT_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Library Text Properties"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + DIALOG_LIB_EDIT_TEXT_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Library Text Properties"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 615,343 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); ~DIALOG_LIB_EDIT_TEXT_BASE(); }; diff --git a/eeschema/edit_component_in_schematic.cpp b/eeschema/edit_component_in_schematic.cpp index 67c374f26e..3b9104ae47 100644 --- a/eeschema/edit_component_in_schematic.cpp +++ b/eeschema/edit_component_in_schematic.cpp @@ -60,16 +60,6 @@ void SCH_EDIT_FRAME::EditComponentFieldText( SCH_FIELD* aField ) fieldNdx = aField->GetId(); - if( fieldNdx == VALUE && part->IsPower() ) - { - wxString msg = wxString::Format( _( - "%s is a power component and it's value cannot be modified!\n\n" - "You must create a new power component with the new value." ), - GetChars( part->GetName() ) - ); - DisplayInfoMessage( this, msg ); - return; - } // Save old component in undo list if not already in edit, or moving. if( aField->GetFlags() == 0 ) @@ -84,6 +74,13 @@ void SCH_EDIT_FRAME::EditComponentFieldText( SCH_FIELD* aField ) DIALOG_SCH_EDIT_ONE_FIELD dlg( this, title, aField ); + // Value fields of power components cannot be modified. This will grey out + // the text box and display an explanation. + if( fieldNdx == VALUE && part->IsPower() ) + { + dlg.SetPowerWarning( true ); + } + //The diag may invoke a kiway player for footprint fields //so we must use a quasimodal int response = dlg.ShowQuasiModal(); @@ -120,12 +117,17 @@ void SCH_EDIT_FRAME::EditComponentFieldText( SCH_FIELD* aField ) DisplayError( this, _( "The reference field cannot be empty! No change" ) ); can_update = false; } - else if( fieldNdx == VALUE ) + else if( fieldNdx == VALUE && ! part->IsPower() ) { + // Note that power components also should not have empty value fields - but + // since the user is forbidden from changing the value field here, if it + // were to happen somehow, it'd be awfully confusing if an error were to + // be displayed! + DisplayError( this, _( "The value field cannot be empty! No change" ) ); can_update = false; } - else + else if ( !( fieldNdx == VALUE && part->IsPower() ) ) { dlg.SetTextField( wxT( "~" ) ); } @@ -133,7 +135,7 @@ void SCH_EDIT_FRAME::EditComponentFieldText( SCH_FIELD* aField ) if( can_update ) { - dlg.TransfertDataToField(); + dlg.TransfertDataToField( /* aIncludeText = */ !( fieldNdx == VALUE && part->IsPower() ) ); OnModify(); m_canvas->Refresh(); } diff --git a/eeschema/sch_reference_list.h b/eeschema/sch_reference_list.h index 7133d4bc47..d5048cbf71 100644 --- a/eeschema/sch_reference_list.h +++ b/eeschema/sch_reference_list.h @@ -39,6 +39,10 @@ #include #include +#include + +class SCH_REFERENCE; +class SCH_REFERENCE_LIST; /** * Class SCH_REFERENCE @@ -151,6 +155,16 @@ public: return Cmp_KEEPCASE( m_RootCmp->GetPartName(), item.m_RootCmp->GetPartName() ); } + /** + * Function IsSameInstance + * returns whether this reference refers to the same component instance + * (component and sheet) as another. + */ + bool IsSameInstance( const SCH_REFERENCE& other ) const + { + return GetComp() == other.GetComp() && GetSheetPath().Path() == other.GetSheetPath().Path(); + } + bool IsUnitsLocked() { return m_Entry->UnitsLocked(); @@ -272,6 +286,9 @@ public: * @param aUseSheetNum Set to true to start annotation for each sheet at the sheet number * times \a aSheetIntervalId. Otherwise annotate incrementally. * @param aSheetIntervalId The per sheet reference designator multiplier. + * @param aLockedUnitMap A SCH_MULTI_UNIT_REFERENCE_MAP of reference designator wxStrings + * to SCH_REFERENCE_LISTs. May be an empty map. If not empty, any multi-unit parts + * found in this map will be annotated as a group rather than individually. *

* If a the sheet number is 2 and \a aSheetIntervalId is 100, then the first reference * designator would be 201 and the last reference designator would be 299 when no overlap @@ -279,7 +296,7 @@ public: * referenced U201 to U351, and items in sheet 3 start from U352 *

*/ - void Annotate( bool aUseSheetNum, int aSheetIntervalId ); + void Annotate( bool aUseSheetNum, int aSheetIntervalId, SCH_MULTI_UNIT_REFERENCE_MAP aLockedUnitMap ); /** * Function CheckAnnotation @@ -449,5 +466,4 @@ private: int CreateFirstFreeRefId( std::vector& aIdList, int aFirstValue ); }; - #endif // _SCH_REFERENCE_LIST_H_ diff --git a/eeschema/sch_sheet_path.cpp b/eeschema/sch_sheet_path.cpp index 28900e4b30..de309de11d 100644 --- a/eeschema/sch_sheet_path.cpp +++ b/eeschema/sch_sheet_path.cpp @@ -44,6 +44,8 @@ #include +#include + SCH_SHEET_PATH::SCH_SHEET_PATH() { @@ -299,11 +301,12 @@ void SCH_SHEET_PATH::GetComponents( PART_LIBS* aLibs, SCH_REFERENCE_LIST& aRefer SCH_COMPONENT* component = (SCH_COMPONENT*) item; // Skip pseudo components, which have a reference starting with #. This mainly - // effects power symbols. + // affects power symbols. if( !aIncludePowerSymbols && component->GetRef( this )[0] == wxT( '#' ) ) continue; - if( LIB_PART* part = aLibs->FindLibPart( component->GetPartName() ) ) + LIB_PART* part = aLibs->FindLibPart( component->GetPartName() ); + if( part ) { SCH_REFERENCE reference = SCH_REFERENCE( component, part, *this ); reference.SetSheetNumber( sheetnumber ); @@ -313,6 +316,45 @@ void SCH_SHEET_PATH::GetComponents( PART_LIBS* aLibs, SCH_REFERENCE_LIST& aRefer } } +void SCH_SHEET_PATH::GetMultiUnitComponents( PART_LIBS* aLibs, SCH_MULTI_UNIT_REFERENCE_MAP &aRefList, + bool aIncludePowerSymbols ) +{ + // Find sheet path number + int sheetnumber = 1; // 1 = root + + SCH_SHEET_LIST sheetList; + + for( SCH_SHEET_PATH* path = sheetList.GetFirst(); path; path = sheetList.GetNext(), sheetnumber++ ) + { + if( Cmp( *path ) == 0 ) + break; + } + + for( SCH_ITEM* item = LastDrawList(); item; item = item->Next() ) + { + if( item->Type() != SCH_COMPONENT_T ) continue; + SCH_COMPONENT* component = (SCH_COMPONENT*) item; + + // Skip pseudo components, which have a reference starting with #. This mainly + // affects power symbols. + if( !aIncludePowerSymbols && component->GetRef( this )[0] == wxT( '#' ) ) + continue; + + LIB_PART* part = aLibs->FindLibPart( component->GetPartName() ); + if( part && part->GetUnitCount() > 1 ) + { + SCH_REFERENCE reference = SCH_REFERENCE( component, part, *this ); + reference.SetSheetNumber( sheetnumber ); + wxString reference_str = reference.GetRef(); + + // Never lock unassigned references + if( reference_str[reference_str.Len() - 1] == '?' ) continue; + + aRefList[reference_str].AddItem( reference ); + } + } +} + SCH_ITEM* SCH_SHEET_PATH::FindNextItem( KICAD_T aType, SCH_ITEM* aLastItem, bool aWrap ) const { @@ -606,6 +648,25 @@ void SCH_SHEET_LIST::GetComponents( PART_LIBS* aLibs, SCH_REFERENCE_LIST& aRefer path->GetComponents( aLibs, aReferences, aIncludePowerSymbols ); } +void SCH_SHEET_LIST::GetMultiUnitComponents( PART_LIBS* aLibs, + SCH_MULTI_UNIT_REFERENCE_MAP &aRefList, bool aIncludePowerSymbols ) +{ + for( SCH_SHEET_PATH* path = GetFirst(); path; path = GetNext() ) + { + SCH_MULTI_UNIT_REFERENCE_MAP tempMap; + path->GetMultiUnitComponents( aLibs, tempMap ); + BOOST_FOREACH( SCH_MULTI_UNIT_REFERENCE_MAP::value_type& pair, tempMap ) + { + // Merge this list into the main one + unsigned n_refs = pair.second.GetCount(); + for( unsigned thisRef = 0; thisRef < n_refs; ++thisRef ) + { + aRefList[pair.first].AddItem( pair.second[thisRef] ); + } + } + } +} + SCH_ITEM* SCH_SHEET_LIST::FindNextItem( KICAD_T aType, SCH_SHEET_PATH** aSheetFoundIn, SCH_ITEM* aLastItem, bool aWrap ) diff --git a/eeschema/sch_sheet_path.h b/eeschema/sch_sheet_path.h index d5bb231d83..98b4f0dad8 100644 --- a/eeschema/sch_sheet_path.h +++ b/eeschema/sch_sheet_path.h @@ -85,6 +85,11 @@ class SCH_ITEM; class SCH_REFERENCE_LIST; class PART_LIBS; +/** + * Type SCH_MULTI_UNIT_REFERENCE_MAP + * is used to create a map of reference designators for multi-unit parts. + */ +typedef std::map SCH_MULTI_UNIT_REFERENCE_MAP; /** * Class SCH_SHEET_PATH @@ -229,6 +234,18 @@ public: void GetComponents( PART_LIBS* aLibs, SCH_REFERENCE_LIST& aReferences, bool aIncludePowerSymbols = true ); + /** + * Function GetMultiUnitComponents + * adds a SCH_REFERENCE_LIST object to \a aRefList for each same-reference set of + * multi-unit parts in the sheet. The map key for each element will be the + * reference designator. + * @param aLibs the library list to use + * @param aRefList Map of reference designators to reference lists + * @param aIncludePowerSymbols : false to only get normal components. + */ + void GetMultiUnitComponents( PART_LIBS* aLibs, SCH_MULTI_UNIT_REFERENCE_MAP &aRefList, + bool aIncludePowerSymbols = true ); + /** * Function SetFootprintField * searches last sheet in the path for a component with \a aReference and set the footprint @@ -414,6 +431,18 @@ public: */ void GetComponents( PART_LIBS* aLibs, SCH_REFERENCE_LIST& aReferences, bool aIncludePowerSymbols = true ); + /** + * Function GetMultiUnitComponents + * adds a SCH_REFERENCE_LIST object to \a aRefList for each same-reference set of + * multi-unit parts in the list of sheets. The map key for each element will be the + * reference designator. + * @param aLibs the library list to use + * @param aRefList Map of reference designators to reference lists + * @param aIncludePowerSymbols Set to false to only get normal components. + */ + void GetMultiUnitComponents( PART_LIBS* aLibs, SCH_MULTI_UNIT_REFERENCE_MAP &aRefList, + bool aIncludePowerSymbols = true ); + /** * Function FindNextItem * searches the entire schematic for the next schematic object. diff --git a/eeschema/schframe.h b/eeschema/schframe.h index c09f0c3d16..d1702e0ba5 100644 --- a/eeschema/schframe.h +++ b/eeschema/schframe.h @@ -30,7 +30,6 @@ #ifndef WX_EESCHEMA_STRUCT_H #define WX_EESCHEMA_STRUCT_H - #include #include #include @@ -522,8 +521,8 @@ public: /** * Function DeleteAnnotation * clears the current component annotation. - * @param aCurrentSheetOnly Clear the entire schematic annotation if true. Otherwise - * only clear the annotation for the current sheet. + * @param aCurrentSheetOnly Clear only the annotation for the current sheet if true. + * Otherwise clear the entire schematic annotation. */ void DeleteAnnotation( bool aCurrentSheetOnly ); @@ -542,6 +541,14 @@ public: * Otherwise, keep the existing time stamps. This option * could change previous annotation because time stamps are * used to handle annotation in complex hierarchies. + * @param aLockUnits When both aLockUnits and aResetAnnotation are true, all unit + * associations should be kept when reannotating. That is, if + * two components were R8A and R8B, they may become R3A and R3B, + * but not R3A and R3C or R3C and R4D. + * When aResetAnnotation is true but aLockUnits is false, the + * usual behavior of annotating each part individually is + * performed. + * When aResetAnnotation is false, this option has no effect. * * When the sheet number is used in annotation, each sheet annotation starts from sheet * number * 100. In other words the first sheet uses 100 to 199, the second sheet uses @@ -549,7 +556,7 @@ public: */ void AnnotateComponents( bool aAnnotateSchematic, ANNOTATE_ORDER_T aSortOption, ANNOTATE_OPTION_T aAlgoOption, bool aResetAnnotation, - bool aRepairTimestamps ); + bool aRepairTimestamps, bool aLockUnits ); /** * Function CheckAnnotate diff --git a/pcbnew/pad_edition_functions.cpp b/pcbnew/pad_edition_functions.cpp index ce2599463b..733104e09d 100644 --- a/pcbnew/pad_edition_functions.cpp +++ b/pcbnew/pad_edition_functions.cpp @@ -193,28 +193,19 @@ void PCB_BASE_FRAME::AddPad( MODULE* aModule, bool draw ) } -/** - * Function DeletePad - * Delete the pad aPad. - * Refresh the modified screen area - * Refresh modified parameters of the parent module (bounding box, last date) - * @param aPad = the pad to delete - * @param aQuery = true to promt for confirmation, false to delete silently - */ void PCB_BASE_FRAME::DeletePad( D_PAD* aPad, bool aQuery ) { - MODULE* module; - if( aPad == NULL ) return; - module = (MODULE*) aPad->GetParent(); + MODULE* module = (MODULE*) aPad->GetParent(); module->SetLastEditTime(); + // aQuery = true to prompt for confirmation, false to delete silently if( aQuery ) { wxString msg; - msg.Printf( _( "Delete Pad (module %s %s) " ), + msg.Printf( _( "Delete Pad (footprint %s %s) ?" ), GetChars( module->GetReference() ), GetChars( module->GetValue() ) ); @@ -224,7 +215,10 @@ void PCB_BASE_FRAME::DeletePad( D_PAD* aPad, bool aQuery ) m_Pcb->m_Status_Pcb = 0; aPad->DeleteStructure(); + // Refresh the modified screen area, using the initial bounding box + // which is perhaps larger than the new bounding box m_canvas->RefreshDrawingRect( module->GetBoundingBox() ); + // Update the bounding box module->CalculateBoundingBox(); OnModify();