diff --git a/common/base_struct.cpp b/common/base_struct.cpp index 52e7a4360e..5064b742bf 100644 --- a/common/base_struct.cpp +++ b/common/base_struct.cpp @@ -194,6 +194,16 @@ bool EDA_ITEM::Matches( const wxString& aText, wxFindReplaceData& aSearchData ) } +bool EDA_ITEM::Replace( wxFindReplaceData& aSearchData, wxString& aText ) +{ + wxCHECK_MSG( IsReplaceable(), false, + wxT( "Attempt to replace text in <" ) + GetClass() + wxT( "> item." ) ); + + return aText.Replace( aSearchData.GetFindString(), + aSearchData.GetReplaceString(), false ) != 0; +} + + bool EDA_ITEM::operator<( const EDA_ITEM& aItem ) const { wxFAIL_MSG( wxString::Format( wxT( "Less than operator not defined for item type %s." ), diff --git a/common/sch_item_struct.cpp b/common/sch_item_struct.cpp index 9a1c2af65a..e39b4f9bad 100644 --- a/common/sch_item_struct.cpp +++ b/common/sch_item_struct.cpp @@ -42,6 +42,8 @@ const wxString traceFindReplace( wxT( "KicadFindReplace" ) ); +const wxString traceFindItem( wxT( "KicadFindItem" ) ); + bool sort_schematic_items( const SCH_ITEM* aItem1, const SCH_ITEM* aItem2 ) { diff --git a/eeschema/dialogs/dialog_sch_find.fbp b/eeschema/dialogs/dialog_sch_find.fbp index eedab154d4..36fd85f943 100644 --- a/eeschema/dialogs/dialog_sch_find.fbp +++ b/eeschema/dialogs/dialog_sch_find.fbp @@ -1047,8 +1047,8 @@ - 5 - wxALL + 6 + wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT 0 @@ -1104,8 +1104,8 @@ - 5 - wxALL + 6 + wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT 0 diff --git a/eeschema/dialogs/dialog_schematic_find.cpp b/eeschema/dialogs/dialog_schematic_find.cpp index 9f221664af..89aac3c7b3 100644 --- a/eeschema/dialogs/dialog_schematic_find.cpp +++ b/eeschema/dialogs/dialog_schematic_find.cpp @@ -17,6 +17,8 @@ DIALOG_SCH_FIND::DIALOG_SCH_FIND( wxWindow* aParent, wxFindReplaceData* aData, if( aStyle & wxFR_REPLACEDIALOG ) { SetTitle( _( "Find and Replace" ) ); + m_buttonReplace->Show( true ); + m_buttonReplaceAll->Show( true ); m_staticReplace->Show( true ); m_comboReplace->Show( true ); m_checkWildcardMatch->Show( false ); // Wildcard replace is not implemented. @@ -60,7 +62,7 @@ void DIALOG_SCH_FIND::OnUpdateFindUI( wxUpdateUIEvent& aEvent ) void DIALOG_SCH_FIND::OnUpdateReplaceUI( wxUpdateUIEvent& aEvent ) { aEvent.Enable( HasFlag( wxFR_REPLACEDIALOG ) && !m_comboFind->GetValue().empty() && - (m_findReplaceData->GetFlags() | FR_REPLACE_ITEM_FOUND) ); + (m_findReplaceData->GetFlags() & FR_REPLACE_ITEM_FOUND) ); } @@ -114,7 +116,10 @@ void DIALOG_SCH_FIND::OnReplace( wxCommandEvent& aEvent ) m_comboReplace->SetSelection( 0 ); } - SendEvent( wxEVT_COMMAND_FIND ); + if( aEvent.GetId() == wxID_REPLACE ) + SendEvent( wxEVT_COMMAND_FIND_REPLACE ); + else if( aEvent.GetId() == wxID_REPLACE_ALL ) + SendEvent( wxEVT_COMMAND_FIND_REPLACE_ALL ); } diff --git a/eeschema/dialogs/dialog_schematic_find.h b/eeschema/dialogs/dialog_schematic_find.h index 0c17a37453..90a56966d4 100644 --- a/eeschema/dialogs/dialog_schematic_find.h +++ b/eeschema/dialogs/dialog_schematic_find.h @@ -53,6 +53,14 @@ enum SchematicFindReplaceFlags }; +/** + * Definition FR_MASK_NON_SEARCH_FLAGS + * is used to mask find/replace flag bits that do not effect the search results. + */ +#define FR_MASK_NON_SEARCH_FLAGS ~( wxFR_DOWN | FR_SEARCH_WRAP | FR_NO_WARP_CURSOR | \ + FR_REPLACE_ITEM_FOUND ) + + /** * Class SCH_FIND_REPLACE_DATA * adds missing useful comparison and assignment operators to the wxFindReplaceData object. @@ -84,6 +92,32 @@ public: { return !( *this == aFindReplaceData ); } + + + /** + * Function ChangesSearch + * tests \a aFindReplaceData to see if it would result in a change in the search + * results. + * + * @param aFindReplaceData A reference to a #SCH_FIND_REPLACE_DATA object to compare + * against. + * @return True if \a aFindReplaceData would result in a search and/or replace change, + * otherwise false. + */ + bool ChangesSearch( SCH_FIND_REPLACE_DATA& aFindReplaceData ) + { + return ( (GetFindString() != aFindReplaceData.GetFindString()) + || (GetSearchFlags() != aFindReplaceData.GetSearchFlags()) ); + } + + bool IsReplacing() const { return (GetFlags() & FR_SEARCH_REPLACE) != 0; } + +private: + /** + * Function GetSearchFlags + * @return The flags that only effect the search result. + */ + wxUint32 GetSearchFlags() const { return GetFlags() & FR_MASK_NON_SEARCH_FLAGS; } }; diff --git a/eeschema/dialogs/dialog_schematic_find_base.cpp b/eeschema/dialogs/dialog_schematic_find_base.cpp index c2c47caa98..312e74e6d8 100644 --- a/eeschema/dialogs/dialog_schematic_find_base.cpp +++ b/eeschema/dialogs/dialog_schematic_find_base.cpp @@ -104,12 +104,12 @@ DIALOG_SCH_FIND_BASE::DIALOG_SCH_FIND_BASE( wxWindow* parent, wxWindowID id, con m_buttonReplace = new wxButton( this, wxID_REPLACE, _("&Replace"), wxDefaultPosition, wxDefaultSize, 0 ); m_buttonReplace->Hide(); - rightSizer->Add( m_buttonReplace, 0, wxALL, 5 ); + rightSizer->Add( m_buttonReplace, 0, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT, 6 ); m_buttonReplaceAll = new wxButton( this, wxID_REPLACE_ALL, _("Replace &All"), wxDefaultPosition, wxDefaultSize, 0 ); m_buttonReplaceAll->Hide(); - rightSizer->Add( m_buttonReplaceAll, 0, wxALL, 5 ); + rightSizer->Add( m_buttonReplaceAll, 0, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT, 6 ); m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0 ); rightSizer->Add( m_buttonCancel, 0, wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND, 6 ); diff --git a/eeschema/eeschema_config.cpp b/eeschema/eeschema_config.cpp index 492ab900e7..467b3079eb 100644 --- a/eeschema/eeschema_config.cpp +++ b/eeschema/eeschema_config.cpp @@ -24,8 +24,7 @@ #include "dialogs/dialog_color_config.h" #include "dialogs/dialog_eeschema_config.h" #include "dialogs/dialog_eeschema_options.h" - -#include +#include "dialogs/dialog_schematic_find.h" #define HOTKEY_FILENAME wxT( "eeschema" ) @@ -565,7 +564,7 @@ void SCH_EDIT_FRAME::LoadSettings() wxASSERT_MSG( m_findReplaceData, wxT( "Find dialog data settings object not created. Bad programmer!" ) ); cfg->Read( FindReplaceFlagsEntry, &tmp, (long) wxFR_DOWN ); - m_findReplaceData->SetFlags( (wxUint32) tmp ); + m_findReplaceData->SetFlags( (wxUint32) tmp & ~FR_REPLACE_ITEM_FOUND ); m_findReplaceData->SetFindString( cfg->Read( FindStringEntry, wxEmptyString ) ); m_findReplaceData->SetReplaceString( cfg->Read( ReplaceStringEntry, wxEmptyString ) ); @@ -643,7 +642,8 @@ void SCH_EDIT_FRAME::SaveSettings() cfg->Write( FindDialogHeightEntry, m_findDialogSize.GetHeight() ); wxASSERT_MSG( m_findReplaceData, wxT( "Find dialog data settings object not created. Bad programmer!" ) ); - cfg->Write( FindReplaceFlagsEntry, (long) m_findReplaceData->GetFlags() ); + cfg->Write( FindReplaceFlagsEntry, + (long) m_findReplaceData->GetFlags() & ~FR_REPLACE_ITEM_FOUND ); cfg->Write( FindStringEntry, m_findReplaceData->GetFindString() ); cfg->Write( ReplaceStringEntry, m_findReplaceData->GetReplaceString() ); diff --git a/eeschema/find.cpp b/eeschema/find.cpp index 92aba74db2..4b4a1edb24 100644 --- a/eeschema/find.cpp +++ b/eeschema/find.cpp @@ -303,12 +303,13 @@ void SCH_EDIT_FRAME::OnFindSchematicItem( wxFindDialogEvent& aEvent ) wxString msg; SCH_FIND_REPLACE_DATA searchCriteria; bool warpCursor = !( aEvent.GetFlags() & FR_NO_WARP_CURSOR ); + SCH_FIND_COLLECTOR_DATA data; searchCriteria.SetFlags( aEvent.GetFlags() ); searchCriteria.SetFindString( aEvent.GetFindString() ); searchCriteria.SetReplaceString( aEvent.GetReplaceString() ); - if( searchCriteria != m_foundItems.GetFindReplaceData() ) + if( m_foundItems.GetFindReplaceData().ChangesSearch( searchCriteria ) ) { if( aEvent.GetEventType() == wxEVT_COMMAND_FIND_CLOSE ) { @@ -316,69 +317,62 @@ void SCH_EDIT_FRAME::OnFindSchematicItem( wxFindDialogEvent& aEvent ) } else if( aEvent.GetFlags() & FR_CURRENT_SHEET_ONLY && g_RootSheet->CountSheets() > 1 ) { - m_foundItemIndex = 0; m_foundItems.Collect( searchCriteria, m_CurrentSheet ); } else { - m_foundItemIndex = 0; m_foundItems.Collect( searchCriteria ); } } else { - if( searchCriteria.GetFlags() & wxFR_DOWN ) - { - if( !(searchCriteria.GetFlags() & FR_SEARCH_WRAP) - && (m_foundItemIndex == (m_foundItems.GetCount() - 1)) ) - return; + EDA_ITEM* currentItem = m_foundItems.GetItem( data ); - m_foundItemIndex += 1; + if( currentItem != NULL ) + currentItem->SetForceVisible( false ); - if( (m_foundItemIndex >= m_foundItems.GetCount()) - && (searchCriteria.GetFlags() & FR_SEARCH_WRAP) ) - m_foundItemIndex = 0; - } - else - { - if( !(searchCriteria.GetFlags() & FR_SEARCH_WRAP) && (m_foundItemIndex == 0) ) - return; - - m_foundItemIndex -= 1; - - if( (m_foundItemIndex < 0) && (searchCriteria.GetFlags() & FR_SEARCH_WRAP) ) - m_foundItemIndex = m_foundItems.GetCount() - 1; - } + m_foundItems.UpdateIndex(); } - if( m_foundItems.GetCount() != 0 ) + if( m_foundItems.GetItem( data ) != NULL ) { - SCH_FIND_COLLECTOR_DATA data = m_foundItems.GetFindData( m_foundItemIndex ); - - wxLogTrace( traceFindReplace, wxT( "Found " ) + m_foundItems.GetText( m_foundItemIndex ) ); + wxLogTrace( traceFindReplace, wxT( "Found " ) + m_foundItems.GetText() ); SCH_SHEET_PATH* sheet = schematic.GetSheet( data.GetSheetPath() ); wxCHECK_RET( sheet != NULL, wxT( "Could not find sheet path " ) + data.GetSheetPath() ); + // Make the item temporarily visible just in case it's hide flag is set. This + // has no effect on objects that don't support hiding. If this is a close find + // dialog event, clear the temporary visibility flag. + if( aEvent.GetEventType() == wxEVT_COMMAND_FIND_CLOSE ) + m_foundItems.GetItem( data )->SetForceVisible( false ); + else + m_foundItems.GetItem( data )->SetForceVisible( true ); + if( sheet->PathHumanReadable() != m_CurrentSheet->PathHumanReadable() ) { sheet->LastScreen()->SetZoom( GetScreen()->GetZoom() ); *m_CurrentSheet = *sheet; m_CurrentSheet->UpdateAllScreenReferences(); + SetScreen( sheet->LastScreen() ); } sheet->LastScreen()->SetCrossHairPosition( data.GetPosition() ); RedrawScreen( data.GetPosition(), warpCursor ); - aEvent.SetFlags( aEvent.GetFlags() | FR_REPLACE_ITEM_FOUND ); - msg = m_foundItems.GetText( m_foundItemIndex ); + msg = m_foundItems.GetText(); + + if( aEvent.GetFlags() & FR_SEARCH_REPLACE ) + aEvent.SetFlags( aEvent.GetFlags() | FR_REPLACE_ITEM_FOUND ); } else { - aEvent.SetFlags( aEvent.GetFlags() & ~FR_REPLACE_ITEM_FOUND ); + if( aEvent.GetFlags() & FR_SEARCH_REPLACE ) + aEvent.SetFlags( aEvent.GetFlags() & ~FR_REPLACE_ITEM_FOUND ); + msg.Printf( _( "No item found matching %s." ), GetChars( aEvent.GetFindString() ) ); } @@ -388,23 +382,57 @@ void SCH_EDIT_FRAME::OnFindSchematicItem( wxFindDialogEvent& aEvent ) void SCH_EDIT_FRAME::OnFindReplace( wxFindDialogEvent& aEvent ) { - wxCHECK_RET( m_foundItems.IsValidIndex( m_foundItemIndex ), - wxT( "No last find item to replace text." ) ); + SCH_FIND_COLLECTOR_DATA data; - SCH_FIND_COLLECTOR_DATA data = m_foundItems.GetFindData( m_foundItemIndex ); + bool warpCursor = !( aEvent.GetFlags() & FR_NO_WARP_CURSOR ); + SCH_ITEM* item = (SCH_ITEM*) m_foundItems.GetItem( data ); + + wxCHECK_RET( item != NULL, wxT( "Invalid replace item in find collector list." ) ); wxLogTrace( traceFindReplace, wxT( "Replacing %s with %s in item %s" ), GetChars( aEvent.GetFindString() ), GetChars( aEvent.GetReplaceString() ), - GetChars( m_foundItems.GetText( m_foundItemIndex ) ) ); + GetChars( m_foundItems.GetText() ) ); + + SCH_ITEM* undoItem = data.GetParent(); + + if( undoItem == NULL ) + undoItem = item; + + SetUndoItem( undoItem ); + + if( m_foundItems.ReplaceItem() ) + { + SaveUndoItemInUndoList( undoItem ); + RedrawScreen( data.GetPosition(), warpCursor ); + } OnFindSchematicItem( aEvent ); if( aEvent.GetEventType() == wxEVT_COMMAND_FIND_REPLACE_ALL ) { - wxLogTrace( traceFindReplace, wxT( "Replacing %s with %s in item %s" ), - GetChars( aEvent.GetFindString() ), GetChars( aEvent.GetReplaceString() ), - GetChars( m_foundItems.GetText( m_foundItemIndex ) ) ); + item = (SCH_ITEM*) m_foundItems.GetItem( data ); - OnFindSchematicItem( aEvent ); + while( item != NULL ) + { + wxLogTrace( traceFindReplace, wxT( "Replacing %s with %s in item %s" ), + GetChars( aEvent.GetFindString() ), GetChars( aEvent.GetReplaceString() ), + GetChars( m_foundItems.GetText() ) ); + + SCH_ITEM* undoItem = data.GetParent(); + + // Don't save child items in undo list. + if( undoItem == NULL ) + undoItem = item; + + SetUndoItem( undoItem ); + + if( m_foundItems.ReplaceItem() ) + { + SaveUndoItemInUndoList( undoItem ); + RedrawScreen( data.GetPosition(), warpCursor ); + } + + OnFindSchematicItem( aEvent ); + } } } diff --git a/eeschema/lib_pin.cpp b/eeschema/lib_pin.cpp index 41be9db0b0..5e7b2c9e7a 100644 --- a/eeschema/lib_pin.cpp +++ b/eeschema/lib_pin.cpp @@ -2138,13 +2138,15 @@ wxString LIB_PIN::GetSelectMenuText() const bool LIB_PIN::Matches( wxFindReplaceData& aSearchData, void* aAuxData, wxPoint* aFindLocation ) { - wxLogTrace( traceFindReplace, wxT( " item " ) + GetSelectMenuText() ); + wxLogTrace( traceFindItem, wxT( " item " ) + GetSelectMenuText() ); + // Note: this will have to be modified if we add find and replace capability to the + // compoment library editor. Otherwise, you wont be able to replace pin text. if( !( aSearchData.GetFlags() & FR_SEARCH_ALL_PINS ) - && !( aSearchData.GetFlags() & FR_SEARCH_REPLACE ) ) + || ( aSearchData.GetFlags() & FR_SEARCH_REPLACE ) ) return false; - wxLogTrace( traceFindReplace, wxT( " child item " ) + GetSelectMenuText() ); + wxLogTrace( traceFindItem, wxT( " child item " ) + GetSelectMenuText() ); if( EDA_ITEM::Matches( GetName(), aSearchData ) || EDA_ITEM::Matches( GetNumberString(), aSearchData ) ) diff --git a/eeschema/menubar.cpp b/eeschema/menubar.cpp index 58e8d4ea8f..0126a261bd 100644 --- a/eeschema/menubar.cpp +++ b/eeschema/menubar.cpp @@ -218,8 +218,8 @@ void SCH_EDIT_FRAME::ReCreateMenuBar() AddMenuItem( editMenu, ID_FIND_ITEMS, text, HELP_FIND, KiBitmap( find_xpm ) ); // Find/Replace - // AddMenuItem( editMenu, wxID_REPLACE, _( "Find and Re&place\tCtrl+Shift+F" ), HELP_REPLACE, - // KiBitmap( find_replace_xpm ) ); + AddMenuItem( editMenu, wxID_REPLACE, _( "Find and Re&place\tCtrl+Shift+F" ), HELP_REPLACE, + KiBitmap( find_replace_xpm ) ); // Backannotate editMenu->AppendSeparator(); diff --git a/eeschema/sch_collectors.cpp b/eeschema/sch_collectors.cpp index 2cbded5d93..5dd9cb6ac3 100644 --- a/eeschema/sch_collectors.cpp +++ b/eeschema/sch_collectors.cpp @@ -26,6 +26,8 @@ * @file sch_collectors.cpp */ +#include "macros.h" + #include "general.h" #include "transform.h" #include "sch_collectors.h" @@ -316,6 +318,79 @@ bool SCH_COLLECTOR::IsDraggableJunction() const } +bool SCH_FIND_COLLECTOR::atEnd() const +{ + bool retv = false; + + wxUint32 flags = m_findReplaceData.GetFlags(); + + if( GetCount() == 0 ) + return true; + + if( !(flags & FR_SEARCH_WRAP) ) + { + if( flags & wxFR_DOWN ) + { + if( m_foundIndex >= (GetCount() - 1) ) + retv = true; + } + else + { + if( m_foundIndex == 0 ) + retv = true; + } + } + + return retv; +} + + +#if defined(DEBUG) + +void SCH_FIND_COLLECTOR::dump() +{ + int tmp = m_foundIndex; + + wxLogTrace( traceFindReplace, wxT( "%d items found to replace %s with %s." ), + GetCount(), GetChars( m_findReplaceData.GetFindString() ), + GetChars( m_findReplaceData.GetReplaceString() ) ); + + for( m_foundIndex = 0; m_foundIndex < GetCount(); m_foundIndex++ ) + wxLogTrace( traceFindReplace, wxT( " " ) + GetText() ); + + m_foundIndex = tmp; +} + +#endif + + +void SCH_FIND_COLLECTOR::UpdateIndex() +{ + wxUint32 flags = m_findReplaceData.GetFlags(); + + if( flags & wxFR_DOWN ) + { + if( !(flags & FR_SEARCH_WRAP) && (m_foundIndex == (GetCount() - 1)) ) + return; + + m_foundIndex += 1; + + if( (m_foundIndex >= GetCount()) && (flags & FR_SEARCH_WRAP) ) + m_foundIndex = 0; + } + else + { + if( !(flags & FR_SEARCH_WRAP) && (m_foundIndex == 0) ) + return; + + m_foundIndex -= 1; + + if( (m_foundIndex < 0) && (flags & FR_SEARCH_WRAP) ) + m_foundIndex = GetCount() - 1; + } +} + + SCH_FIND_COLLECTOR_DATA SCH_FIND_COLLECTOR::GetFindData( int aIndex ) { wxCHECK_MSG( (unsigned) aIndex < m_data.size(), SCH_FIND_COLLECTOR_DATA(), @@ -325,13 +400,13 @@ SCH_FIND_COLLECTOR_DATA SCH_FIND_COLLECTOR::GetFindData( int aIndex ) } -wxString SCH_FIND_COLLECTOR::GetText( int aIndex ) +wxString SCH_FIND_COLLECTOR::GetText() { - wxCHECK_MSG( IsValidIndex( aIndex ), wxEmptyString, + wxCHECK_MSG( (GetCount() != 0) && IsValidIndex( m_foundIndex ), wxEmptyString, wxT( "Cannot get found item at invalid index." ) ); - SCH_FIND_COLLECTOR_DATA data = m_data[ aIndex ]; - EDA_ITEM* foundItem = m_List[ aIndex ]; + SCH_FIND_COLLECTOR_DATA data = m_data[ m_foundIndex ]; + EDA_ITEM* foundItem = m_List[ m_foundIndex ]; wxCHECK_MSG( foundItem != NULL, wxEmptyString, wxT( "Inavalid found item pointer." ) ); @@ -353,6 +428,40 @@ wxString SCH_FIND_COLLECTOR::GetText( int aIndex ) } +EDA_ITEM* SCH_FIND_COLLECTOR::GetItem( SCH_FIND_COLLECTOR_DATA& aData ) +{ + if( atEnd() ) + return NULL; + + aData = m_data[ m_foundIndex ]; + return m_List[ m_foundIndex ]; +} + + +bool SCH_FIND_COLLECTOR::ReplaceItem() +{ + if( atEnd() ) + return false; + + wxCHECK_MSG( IsValidIndex( m_foundIndex ), false, + wxT( "Invalid replace list index in SCH_FIND_COLLECTOR." ) ); + + EDA_ITEM* item = m_List[ m_foundIndex ]; + + bool replaced = item->Replace( m_findReplaceData ); + + // If the replace was successful, remove the item from the find list to prevent + // iterating back over it again. + if( replaced ) + { + Remove( m_foundIndex ); + m_data.erase( m_data.begin() + m_foundIndex ); + } + + return replaced; +} + + SEARCH_RESULT SCH_FIND_COLLECTOR::Inspect( EDA_ITEM* aItem, const void* aTestData ) { wxPoint position; @@ -364,8 +473,9 @@ SEARCH_RESULT SCH_FIND_COLLECTOR::Inspect( EDA_ITEM* aItem, const void* aTestDat wxCHECK_MSG( aTestData && ( (EDA_ITEM*) aTestData )->Type() == SCH_COMPONENT_T, SEARCH_CONTINUE, wxT( "Cannot inspect invalid data. Bad programmer!" ) ); - // Pin hit testing is relative to the components position and orientation in the - // schematic. The hit test position must be converted to library coordinates. + // Pin positions are relative to their parent component's position and + // orientation in the schematic. The pin's position must be converted + // schematic coordinates. SCH_COMPONENT* component = (SCH_COMPONENT*) aTestData; TRANSFORM transform = component->GetTransform(); position.y = -position.y; @@ -384,12 +494,13 @@ SEARCH_RESULT SCH_FIND_COLLECTOR::Inspect( EDA_ITEM* aItem, const void* aTestDat void SCH_FIND_COLLECTOR::Collect( SCH_FIND_REPLACE_DATA& aFindReplaceData, SCH_SHEET_PATH* aSheetPath ) { - if( m_findReplaceData == aFindReplaceData ) + if( !m_findReplaceData.ChangesSearch( aFindReplaceData ) ) return; m_findReplaceData = aFindReplaceData; Empty(); // empty the collection just in case m_data.clear(); + m_foundIndex = 0; if( aSheetPath ) { @@ -408,15 +519,14 @@ void SCH_FIND_COLLECTOR::Collect( SCH_FIND_REPLACE_DATA& aFindReplaceData, } } +#if defined(DEBUG) + dump(); +#endif + if( m_List.size() != m_data.size() ) { wxFAIL_MSG( wxT( "List size mismatch." ) ); m_List.clear(); m_data.clear(); } - - for( unsigned i = 0; i < m_List.size(); i++ ) - { - wxLogTrace( traceFindReplace, GetText( i ) ); - } } diff --git a/eeschema/sch_collectors.h b/eeschema/sch_collectors.h index 4136561842..1db5b0dfda 100644 --- a/eeschema/sch_collectors.h +++ b/eeschema/sch_collectors.h @@ -218,6 +218,26 @@ class SCH_FIND_COLLECTOR : public COLLECTOR /// The path of the sheet currently being iterated over. SCH_SHEET_PATH* m_sheetPath; + /// The current found item list index. + int m_foundIndex; + + /** + * Function atEnd + * tests if #m_foundIndex is at the end of the list give the current find/replace + * criterial in #m_findReplaceData. + * + * @return True if #m_foundIndex is at the end of the found item list. + */ + bool atEnd() const; + + /** + * Function dump + * is a helper to dump the items in the find list for debugging purposes. + */ +#if defined(DEBUG) + void dump(); +#endif + public: /** @@ -226,8 +246,15 @@ public: SCH_FIND_COLLECTOR( const KICAD_T* aScanTypes = SCH_COLLECTOR::AllItems ) { SetScanTypes( aScanTypes ); + m_foundIndex = 0; } + /** + * Function UpdateIndex + * updates the list index according to the current find and replace criteria. + */ + void UpdateIndex(); + /** * Function GetFindData * returns the data associated with the item found at \a aIndex. @@ -246,7 +273,33 @@ public: */ SCH_FIND_REPLACE_DATA& GetFindReplaceData() { return m_findReplaceData; } - wxString GetText( int aIndex ); + /** + * Function GetText() + * @return A wxString object containing the description of the item found at the + * current index or a wxEmptyString if the list is empty or the index is + * invalid. + */ + wxString GetText(); + + /** + * Function GetItem + * returns the item and associated data of the current index. + * + * @param aFindData A reference to a #SCH_FIND_COLLECTOR_DATA object to place the + * associated data for the current item into if the current item + * index is valid. + * @return A pointer to the current #EDA_ITEM in the list if the list index is valid + * Otherwise NULL is returned and the \a aFindData object is not updated. + */ + EDA_ITEM* GetItem( SCH_FIND_COLLECTOR_DATA& aFindData ); + + /** + * Function ReplaceItem + * performs a string replace of the item at the current index. + * + * @return True if the text replace occurred otherwise false. + */ + bool ReplaceItem(); /** * @copydoc INSPECTOR::Inspect() diff --git a/eeschema/sch_component.cpp b/eeschema/sch_component.cpp index 23f4043470..a3bcb2fd08 100644 --- a/eeschema/sch_component.cpp +++ b/eeschema/sch_component.cpp @@ -1557,7 +1557,7 @@ void SCH_COMPONENT::Rotate( wxPoint rotationPoint ) bool SCH_COMPONENT::Matches( wxFindReplaceData& aSearchData, void* aAuxData, wxPoint* aFindLocation ) { - wxLogTrace( traceFindReplace, wxT( " item " ) + GetSelectMenuText() ); + wxLogTrace( traceFindItem, wxT( " item " ) + GetSelectMenuText() ); // Components are searchable via the child field and pin item text. return false; diff --git a/eeschema/sch_component.h b/eeschema/sch_component.h index 8c98bef1ae..c3ea06a82d 100644 --- a/eeschema/sch_component.h +++ b/eeschema/sch_component.h @@ -365,14 +365,7 @@ public: virtual void Rotate( wxPoint rotationPoint ); /** - * Function Matches - * compares component reference and value fields against \a aSearchData. - * - * @param aSearchData Criteria to search against. - * @param aAuxData Pointer to auxiliary data, if needed. - * Used when searching string in REFERENCE field we must know the sheet path - * @param aFindLocation - a wxPoint where to put the location of matched item. can be NULL. - * @return True if this component reference or value field matches the search criteria. + * @copydoc EDA_ITEM::Matches() */ virtual bool Matches( wxFindReplaceData& aSearchData, void* aAuxData, wxPoint* aFindLocation ); diff --git a/eeschema/sch_field.cpp b/eeschema/sch_field.cpp index 1096fa496f..173573205c 100644 --- a/eeschema/sch_field.cpp +++ b/eeschema/sch_field.cpp @@ -147,13 +147,12 @@ void SCH_FIELD::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, // Clip pen size for small texts: LineWidth = Clamp_Text_PenSize( LineWidth, m_Size, m_Bold ); - if( ( m_Attributs & TEXT_NO_VISIBLE ) || IsVoid() ) + if( ((m_Attributs & TEXT_NO_VISIBLE) && !m_forceVisible) || IsVoid() ) return; GRSetDrawMode( DC, DrawMode ); - /* Calculate the text orientation, according to the component - * orientation/mirror */ + // Calculate the text orientation according to the component orientation. orient = m_Orient; if( parentComponent->GetTransform().y1 ) // Rotate component 90 degrees. @@ -178,12 +177,19 @@ void SCH_FIELD::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, EDA_RECT boundaryBox = GetBoundingBox(); textpos = boundaryBox.Centre(); - if( m_id == REFERENCE ) - color = ReturnLayerColor( LAYER_REFERENCEPART ); - else if( m_id == VALUE ) - color = ReturnLayerColor( LAYER_VALUEPART ); + if( m_forceVisible ) + { + color = DARKGRAY; + } else - color = ReturnLayerColor( LAYER_FIELDS ); + { + if( m_id == REFERENCE ) + color = ReturnLayerColor( LAYER_REFERENCEPART ); + else if( m_id == VALUE ) + color = ReturnLayerColor( LAYER_VALUEPART ); + else + color = ReturnLayerColor( LAYER_FIELDS ); + } DrawGraphicText( panel, DC, textpos, color, GetText(), orient, m_Size, GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER, @@ -361,7 +367,7 @@ bool SCH_FIELD::Matches( wxFindReplaceData& aSearchData, void* aAuxData, wxPoint if( (m_id > VALUE) && !(aSearchData.GetFlags() & FR_SEARCH_ALL_FIELDS) ) return false; - wxLogTrace( traceFindReplace, wxT( " child item " ) + GetSelectMenuText() ); + wxLogTrace( traceFindItem, wxT( " child item " ) + GetSelectMenuText() ); // Take sheet path into account which effects the reference field and the unit for // components with multiple parts. diff --git a/eeschema/sch_field.h b/eeschema/sch_field.h index 4c085057bf..1e4beed139 100644 --- a/eeschema/sch_field.h +++ b/eeschema/sch_field.h @@ -202,6 +202,14 @@ public: virtual bool Matches( wxFindReplaceData& aSearchData, void* aAuxData, wxPoint* aFindLocation ); + /** + * @copydoc EDA_ITEM::Replace(wxFindReplaceData&) + */ + virtual bool Replace( wxFindReplaceData& aSearchData ) + { + return EDA_ITEM::Replace( aSearchData, m_Text ); + } + virtual wxString GetSelectMenuText() const; virtual BITMAP_DEF GetMenuImage() const; diff --git a/eeschema/sch_sheet.cpp b/eeschema/sch_sheet.cpp index 11bc4e4e6a..23f672185d 100644 --- a/eeschema/sch_sheet.cpp +++ b/eeschema/sch_sheet.cpp @@ -931,9 +931,11 @@ void SCH_SHEET::Resize( const wxSize& aSize ) bool SCH_SHEET::Matches( wxFindReplaceData& aSearchData, void* aAuxData, wxPoint* aFindLocation ) { - wxLogTrace( traceFindReplace, wxT( " item " ) + GetSelectMenuText() ); + wxLogTrace( traceFindItem, wxT( " item " ) + GetSelectMenuText() ); - if( SCH_ITEM::Matches( m_fileName, aSearchData ) ) + // Ignore the sheet file name if searching to replace. + if( !(aSearchData.GetFlags() & FR_SEARCH_REPLACE) + && SCH_ITEM::Matches( m_fileName, aSearchData ) ) { if( aFindLocation ) *aFindLocation = GetFileNamePosition(); @@ -953,6 +955,12 @@ bool SCH_SHEET::Matches( wxFindReplaceData& aSearchData, void* aAuxData, wxPoint } +bool SCH_SHEET::Replace( wxFindReplaceData& aSearchData ) +{ + return EDA_ITEM::Replace( aSearchData, m_name ); +} + + void SCH_SHEET::renumberPins() { int id = 2; diff --git a/eeschema/sch_sheet.h b/eeschema/sch_sheet.h index d579e7837c..204b0bfb2b 100644 --- a/eeschema/sch_sheet.h +++ b/eeschema/sch_sheet.h @@ -208,6 +208,19 @@ public: */ virtual bool Matches( wxFindReplaceData& aSearchData, void* aAuxData, wxPoint* aFindLocation ); + /** + * @copydoc EDA_ITEM::Replace(wxFindReplaceData&) + */ + virtual bool Replace( wxFindReplaceData& aSearchData ) + { + return EDA_ITEM::Replace( aSearchData, m_Text ); + } + + /** + * @copydoc EDA_ITEM::IsReplaceable() + */ + virtual bool IsReplaceable() const { return true; } + virtual void GetEndPoints( std::vector< DANGLING_END_ITEM >& aItemList ); virtual bool IsConnectable() const { return true; } @@ -568,6 +581,16 @@ public: */ virtual bool Matches( wxFindReplaceData& aSearchData, void* aAuxData, wxPoint* aFindLocation ); + /** + * @copydoc EDA_ITEM::Replace(wxFindReplaceData&) + */ + virtual bool Replace( wxFindReplaceData& aSearchData ); + + /** + * @copydoc EDA_ITEM::IsReplaceable() + */ + virtual bool IsReplaceable() const { return true; } + /** * Resize this sheet to aSize and adjust all of the labels accordingly. * @@ -609,11 +632,6 @@ public: virtual void GetNetListItem( vector& aNetListItems, SCH_SHEET_PATH* aSheetPath ); - /** - * @copydoc EDA_ITEM::IsReplaceable() - */ - virtual bool IsReplaceable() const { return true; } - #if defined(DEBUG) // comment inherited by Doxygen from Base_Struct diff --git a/eeschema/sch_sheet_pin.cpp b/eeschema/sch_sheet_pin.cpp index 294af7a7b3..1dfde15e0f 100644 --- a/eeschema/sch_sheet_pin.cpp +++ b/eeschema/sch_sheet_pin.cpp @@ -399,7 +399,7 @@ bool SCH_SHEET_PIN::Matches( wxFindReplaceData& aSearchData, wxCHECK_MSG( GetParent() != NULL, false, wxT( "Sheet pin " ) + m_Text + wxT( " does not have a parent sheet!" ) ); - wxLogTrace( traceFindReplace, wxT( " child item " ) + GetSelectMenuText() ); + wxLogTrace( traceFindItem, wxT( " child item " ) + GetSelectMenuText() ); if( SCH_ITEM::Matches( m_Text, aSearchData ) ) { diff --git a/eeschema/sch_text.cpp b/eeschema/sch_text.cpp index e8eca4e3a8..a2e4fcc124 100644 --- a/eeschema/sch_text.cpp +++ b/eeschema/sch_text.cpp @@ -167,7 +167,7 @@ wxPoint SCH_TEXT::GetSchematicTextOffset() const bool SCH_TEXT::Matches( wxFindReplaceData& aSearchData, void* aAuxData, wxPoint * aFindLocation ) { - wxLogTrace( traceFindReplace, wxT( " item " ) + GetSelectMenuText() ); + wxLogTrace( traceFindItem, wxT( " item " ) + GetSelectMenuText() ); if( SCH_ITEM::Matches( m_Text, aSearchData ) ) { diff --git a/eeschema/sch_text.h b/eeschema/sch_text.h index c67a805eea..7ed820a04f 100644 --- a/eeschema/sch_text.h +++ b/eeschema/sch_text.h @@ -206,6 +206,19 @@ public: */ virtual bool Matches( wxFindReplaceData& aSearchData, void* aAuxData, wxPoint* aFindLocation ); + /** + * @copydoc EDA_ITEM::Replace(wxFindReplaceData&) + */ + virtual bool Replace( wxFindReplaceData& aSearchData ) + { + return EDA_ITEM::Replace( aSearchData, m_Text ); + } + + /** + * @copydoc EDA_ITEM::IsReplaceable() + */ + virtual bool IsReplaceable() const { return true; } + virtual void GetEndPoints( std::vector< DANGLING_END_ITEM >& aItemList ); virtual bool IsDanglingStateChanged( std::vector< DANGLING_END_ITEM >& aItemList ); diff --git a/eeschema/schframe.cpp b/eeschema/schframe.cpp index a2410d0aa8..ad5e8da5b7 100644 --- a/eeschema/schframe.cpp +++ b/eeschema/schframe.cpp @@ -204,7 +204,6 @@ SCH_EDIT_FRAME::SCH_EDIT_FRAME( wxWindow* father, m_findReplaceData = new wxFindReplaceData( wxFR_DOWN ); m_undoItem = NULL; m_hasAutoSave = true; - m_foundItemIndex = 0; CreateScreens(); diff --git a/eeschema/tool_sch.cpp b/eeschema/tool_sch.cpp index 52fe06a97d..f76a0a31fa 100644 --- a/eeschema/tool_sch.cpp +++ b/eeschema/tool_sch.cpp @@ -77,9 +77,9 @@ void SCH_EDIT_FRAME::ReCreateHToolbar() msg = AddHotkeyName( HELP_FIND, s_Schematic_Hokeys_Descr, HK_FIND_ITEM, IS_COMMENT ); m_HToolBar->AddTool( ID_FIND_ITEMS, wxEmptyString, KiBitmap( find_xpm ), msg ); - // m_HToolBar->AddTool( wxID_REPLACE, wxEmptyString, KiBitmap( find_replace_xpm ), - // wxNullBitmap, wxITEM_NORMAL, _( "Find and replace text" ), - // HELP_REPLACE, NULL ); + m_HToolBar->AddTool( wxID_REPLACE, wxEmptyString, KiBitmap( find_replace_xpm ), + wxNullBitmap, wxITEM_NORMAL, _( "Find and replace text" ), + HELP_REPLACE, NULL ); m_HToolBar->AddSeparator(); diff --git a/include/base_struct.h b/include/base_struct.h index f1952b9608..fb356741d8 100644 --- a/include/base_struct.h +++ b/include/base_struct.h @@ -374,6 +374,9 @@ protected: EDA_ITEM* m_Son; /* Linked list: Link (son struct) */ unsigned long m_TimeStamp; ///< Time stamp used for logical links + /// Set to true to override the visibility setting of the item. + bool m_forceVisible; + public: int m_Flags; // flags for editing and other uses. @@ -465,6 +468,16 @@ public: void ClearFlags( int aMask = EDA_ITEM_ALL_FLAGS ) { m_Flags &= ~aMask; } int GetFlags() const { return m_Flags; } + /** + * Function SetForceVisible + * is used to set and cleag force visible flag used to force the item to be drawn + * even if it's draw attribute is set to not visible. + * + * @param aEnable True forces the item to be drawn. False uses the item's visibility + * setting to determine if the item is to be drawn. + */ + void SetForceVisible( bool aEnable ) { m_forceVisible = aEnable; } + /** * Function DisplayInfo * has knowledge about the frame and how and where to put status @@ -546,7 +559,7 @@ public: * but it may also be used to collect output. * @param scanTypes A KICAD_T array that is EOT terminated, and provides both * the order and interest level of of the types of objects to - * be iterated over. + * be iterated over. * @return SEARCH_RESULT SEARCH_QUIT if the called INSPECTOR returned * SEARCH_QUIT, else SCAN_CONTINUE; */ @@ -614,9 +627,8 @@ public: * @param aAuxData A pointer to optional data required for the search or NULL * if not used. * @param aFindLocation A pointer to a wxPoint object to store the location of - * matched item. The pointer can be NULL is not used. - * @return True if this schematic text item matches the search criteria in - * \a aSearchData. + * matched item. The pointer can be NULL if it is not used. + * @return True if the item's text matches the search criteria in \a aSearchData. */ virtual bool Matches( wxFindReplaceData& aSearchData, void* aAuxData, wxPoint* aFindLocation ) { @@ -633,6 +645,32 @@ public: */ bool Matches( const wxString& aText, wxFindReplaceData& aSearchData ); + /** + * Function Replace + * performs a text replace on \a aText using the find and replace criteria in + * \a aSearchData on items that support text find and replace. + * + * @param aSearchData A reference to a wxFindReplaceData object containing the + * search and replace criteria. + * @param aText A reference to a wxString object containing the text to be + * replaced. + * @return True if \a aText was modified, otherwise false. + */ + bool Replace( wxFindReplaceData& aSearchData, wxString& aText ); + + /** + * Function Replace + * performs a text replace using the find and replace criteria in \a aSearchData + * on items that support text find and replace. + * + * This function must be overridden for items that support text replace. + * + * @param aSearchData A reference to a wxFindReplaceData object containing the + * search and replace criteria. + * @return True if the item text was modified, otherwise false. + */ + virtual bool Replace( wxFindReplaceData& aSearchData ) { return false; } + /** * Function IsReplaceable *

diff --git a/include/sch_item_struct.h b/include/sch_item_struct.h index d82d2de86a..e459759588 100644 --- a/include/sch_item_struct.h +++ b/include/sch_item_struct.h @@ -64,6 +64,10 @@ typedef vector< SCH_ITEMS_ITR > SCH_ITEMS_ITRS; /// Flag to enable find and replace tracing using the WXTRACE environment variable. extern const wxString traceFindReplace; +/// Flag to enable find item tracing using the WXTRACE environment variable. This +/// flag generates a lot of debug output. +extern const wxString traceFindItem; + enum DANGLING_END_T { UNKNOWN = 0,