diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt index d5181d76b2..ce1e60577f 100644 --- a/eeschema/CMakeLists.txt +++ b/eeschema/CMakeLists.txt @@ -229,6 +229,8 @@ set( EESCHEMA_WIDGETS widgets/pin_shape_combobox.cpp widgets/pin_type_combobox.cpp widgets/symbol_diff_widget.cpp + widgets/sch_search_pane.cpp + widgets/search_handlers.cpp widgets/symbol_preview_widget.cpp widgets/symbol_tree_pane.cpp ) diff --git a/eeschema/eeschema_config.cpp b/eeschema/eeschema_config.cpp index 337a3f93c3..f949419fce 100644 --- a/eeschema/eeschema_config.cpp +++ b/eeschema/eeschema_config.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -172,37 +173,41 @@ void SCH_EDIT_FRAME::SaveProjectLocalSettings() void SCH_EDIT_FRAME::LoadSettings( APP_SETTINGS_BASE* aCfg ) { // For now, axes are forced off in Eeschema even if turned on in config - eeconfig()->m_Window.grid.axes_enabled = false; + EESCHEMA_SETTINGS* cfg = eeconfig(); + cfg->m_Window.grid.axes_enabled = false; - SCH_BASE_FRAME::LoadSettings( eeconfig() ); + SCH_BASE_FRAME::LoadSettings( cfg ); SCH_SEARCH_DATA* searchData = dynamic_cast( m_findReplaceData.get() ); if( searchData ) { - searchData->replaceReferences = eeconfig()->m_FindReplaceExtra.replace_references; - searchData->searchAllFields = eeconfig()->m_FindReplaceExtra.search_all_fields; - searchData->searchAllPins = eeconfig()->m_FindReplaceExtra.search_all_pins; - searchData->searchCurrentSheetOnly = eeconfig()->m_FindReplaceExtra.search_current_sheet_only; - searchData->searchSelectedOnly = eeconfig()->m_FindReplaceExtra.search_selected_only; + searchData->replaceReferences = cfg->m_FindReplaceExtra.replace_references; + searchData->searchAllFields = cfg->m_FindReplaceExtra.search_all_fields; + searchData->searchAllPins = cfg->m_FindReplaceExtra.search_all_pins; + searchData->searchCurrentSheetOnly = cfg->m_FindReplaceExtra.search_current_sheet_only; + searchData->searchSelectedOnly = cfg->m_FindReplaceExtra.search_selected_only; } + m_show_search = cfg->m_AuiPanels.show_search; + GetRenderSettings()->m_ShowPinsElectricalType = false; GetRenderSettings()->m_ShowPinNumbers = false; - GetRenderSettings()->SetDefaultFont( eeconfig()->m_Appearance.default_font ); + GetRenderSettings()->SetDefaultFont( cfg->m_Appearance.default_font ); } void SCH_EDIT_FRAME::SaveSettings( APP_SETTINGS_BASE* aCfg ) { - SCH_BASE_FRAME::SaveSettings( eeconfig() ); + EESCHEMA_SETTINGS* cfg = eeconfig(); + SCH_BASE_FRAME::SaveSettings( cfg ); wxAuiPaneInfo& hierarchy_pane = m_auimgr.GetPane( SchematicHierarchyPaneName() ); - if( eeconfig() ) + if( cfg ) { - eeconfig()->m_System.units = static_cast( GetUserUnits() ); - eeconfig()->m_AuiPanels.show_schematic_hierarchy = hierarchy_pane.IsShown(); - eeconfig()->m_AuiPanels.schematic_hierarchy_float = hierarchy_pane.IsFloating(); + cfg->m_System.units = static_cast( GetUserUnits() ); + cfg->m_AuiPanels.show_schematic_hierarchy = hierarchy_pane.IsShown(); + cfg->m_AuiPanels.schematic_hierarchy_float = hierarchy_pane.IsFloating(); // Other parameters (hierarchy_panel_float_width, hierarchy_panel_float_height, // and hierarchy_panel_docked_width should have been updated when resizing the // hierarchy panel @@ -211,13 +216,17 @@ void SCH_EDIT_FRAME::SaveSettings( APP_SETTINGS_BASE* aCfg ) if( searchData ) { - eeconfig()->m_FindReplaceExtra.replace_references = searchData->replaceReferences; - eeconfig()->m_FindReplaceExtra.search_all_fields = searchData->searchAllFields; - eeconfig()->m_FindReplaceExtra.search_all_pins = searchData->searchAllPins; - eeconfig()->m_FindReplaceExtra.search_current_sheet_only = + cfg->m_FindReplaceExtra.replace_references = searchData->replaceReferences; + cfg->m_FindReplaceExtra.search_all_fields = searchData->searchAllFields; + cfg->m_FindReplaceExtra.search_all_pins = searchData->searchAllPins; + cfg->m_FindReplaceExtra.search_current_sheet_only = searchData->searchCurrentSheetOnly; - eeconfig()->m_FindReplaceExtra.search_selected_only = searchData->searchSelectedOnly; + cfg->m_FindReplaceExtra.search_selected_only = searchData->searchSelectedOnly; } + + m_show_search = m_auimgr.GetPane( SearchPaneName() ).IsShown(); + cfg->m_AuiPanels.show_search = m_show_search; + cfg->m_AuiPanels.search_panel_height = m_searchPane->GetSize().y; } } diff --git a/eeschema/eeschema_settings.cpp b/eeschema/eeschema_settings.cpp index 2038e8315d..d7e686146b 100644 --- a/eeschema/eeschema_settings.cpp +++ b/eeschema/eeschema_settings.cpp @@ -170,6 +170,12 @@ EESCHEMA_SETTINGS::EESCHEMA_SETTINGS() : m_params.emplace_back( new PARAM( "aui.schematic_hierarchy_float", &m_AuiPanels.schematic_hierarchy_float, false ) ); + m_params.emplace_back( new PARAM( "aui.search_panel_height", + &m_AuiPanels.search_panel_height, -1 ) ); + + m_params.emplace_back( new PARAM( "aui.show_search", + &m_AuiPanels.show_search, false ) ); + m_params.emplace_back( new PARAM( "autoplace_fields.enable", &m_AutoplaceFields.enable, true ) ); diff --git a/eeschema/eeschema_settings.h b/eeschema/eeschema_settings.h index 74f5e3f9ea..0a72cec92d 100644 --- a/eeschema/eeschema_settings.h +++ b/eeschema/eeschema_settings.h @@ -77,8 +77,10 @@ public: int hierarchy_panel_docked_width; // width of hierarchy tree panel and pane when docked int hierarchy_panel_float_width; // width of hierarchy tree panel when floating int hierarchy_panel_float_height; // height of hierarchy tree panel when floating + int search_panel_height; // height of the search panel bool schematic_hierarchy_float; // show hierarchy tree panel as floating bool show_schematic_hierarchy; // show hierarchy tree pane + bool show_search; // show the search panel }; struct AUTOPLACE_FIELDS diff --git a/eeschema/menubar.cpp b/eeschema/menubar.cpp index 38d9df2c33..e4c1451888 100644 --- a/eeschema/menubar.cpp +++ b/eeschema/menubar.cpp @@ -171,6 +171,7 @@ void SCH_EDIT_FRAME::doReCreateMenuBar() ACTION_MENU* viewMenu = new ACTION_MENU( false, selTool ); viewMenu->Add( ACTIONS::showSymbolBrowser ); + viewMenu->Add( ACTIONS::showSearch, ACTION_MENU::CHECK ); viewMenu->Add( EE_ACTIONS::showHierarchy, ACTION_MENU::CHECK ); viewMenu->Add( EE_ACTIONS::navigateBack ); viewMenu->Add( EE_ACTIONS::navigateUp ); diff --git a/eeschema/sch_edit_frame.cpp b/eeschema/sch_edit_frame.cpp index 98881ac4aa..3b11432a1a 100644 --- a/eeschema/sch_edit_frame.cpp +++ b/eeschema/sch_edit_frame.cpp @@ -80,6 +80,7 @@ #include #include #include +#include #include #include #include @@ -115,6 +116,7 @@ BEGIN_EVENT_TABLE( SCH_EDIT_FRAME, SCH_BASE_FRAME ) EVT_DROP_FILES( SCH_EDIT_FRAME::OnDropFiles ) END_EVENT_TABLE() +wxDEFINE_EVENT( EDA_EVT_SCHEMATIC_CHANGED, wxCommandEvent ); SCH_EDIT_FRAME::SCH_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : SCH_BASE_FRAME( aKiway, aParent, FRAME_SCH, wxT( "Eeschema" ), wxDefaultPosition, @@ -130,6 +132,7 @@ SCH_EDIT_FRAME::SCH_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : m_supportsAutoSave = true; m_syncingPcbToSchSelection = false; m_aboutTitle = _HKI( "KiCad Schematic Editor" ); + m_show_search = false; m_findReplaceDialog = nullptr; @@ -169,6 +172,8 @@ SCH_EDIT_FRAME::SCH_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : m_pageSetupData.GetPrintData().SetBin( wxPRINTBIN_AUTO ); m_pageSetupData.GetPrintData().SetNoCopies( 1 ); + m_searchPane = new SCH_SEARCH_PANE( this ); + m_auimgr.SetManagedWindow( this ); CreateInfoBar(); @@ -201,6 +206,19 @@ SCH_EDIT_FRAME::SCH_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : m_auimgr.AddPane( GetCanvas(), EDA_PANE().Canvas().Name( wxS( "DrawFrame" ) ) .Center() ); + m_auimgr.AddPane( m_searchPane, EDA_PANE() + .Name( SearchPaneName() ) + .Bottom() + .Caption( _( "Search" ) ) + .PaneBorder( false ) + .MinSize( 180, -1 ) + .BestSize( 180, -1 ) + .FloatingSize( 480, 200 ) + .CloseButton( true ) + .DestroyOnClose( false ) + .Show( m_show_search ) ); + + FinishAUIInitialization(); resolveCanvasType(); @@ -227,6 +245,12 @@ SCH_EDIT_FRAME::SCH_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : if( cfg->m_AuiPanels.schematic_hierarchy_float ) hierarchy_pane.Float(); + if( cfg->m_AuiPanels.search_panel_height > 0 ) + { + wxAuiPaneInfo& searchPane = m_auimgr.GetPane( SearchPaneName() ); + SetAuiPaneSize( m_auimgr, searchPane, -1, cfg->m_AuiPanels.search_panel_height ); + } + if( cfg->m_AuiPanels.hierarchy_panel_docked_width > 0 ) { SetAuiPaneSize( m_auimgr, hierarchy_pane, @@ -721,6 +745,24 @@ void SCH_EDIT_FRAME::CreateScreens() SCH_SCREEN* screen = new SCH_SCREEN( m_schematic ); SetScreen( screen ); } + + wxCommandEvent e( EDA_EVT_SCHEMATIC_CHANGED ); + ProcessEventLocally( e ); + + + for( wxEvtHandler* listener : m_schematicChangeListeners ) + { + wxCHECK2( listener, continue ); + + // Use the windows variant when handling event messages in case there is any special + // event handler pre and/or post processing specific to windows. + wxWindow* win = dynamic_cast( listener ); + + if( win ) + win->HandleWindowEvent( e ); + else + listener->SafelyProcessEvent( e ); + } } @@ -933,6 +975,9 @@ void SCH_EDIT_FRAME::doCloseWindow() Schematic().Reset(); + // Prevents any rouge events from continuing (i.e. search panel tries to redraw) + Show( false ); + Destroy(); } @@ -2238,3 +2283,25 @@ void SCH_EDIT_FRAME::onCloseErcDialog( wxCommandEvent& aEvent ) m_ercDialog = nullptr; } } + + +void SCH_EDIT_FRAME::AddSchematicChangeListener( wxEvtHandler* aListener ) +{ + auto it = std::find( m_schematicChangeListeners.begin(), m_schematicChangeListeners.end(), + aListener ); + + // Don't add duplicate listeners. + if( it == m_schematicChangeListeners.end() ) + m_schematicChangeListeners.push_back( aListener ); +} + + +void SCH_EDIT_FRAME::RemoveSchematicChangeListener( wxEvtHandler* aListener ) +{ + auto it = std::find( m_schematicChangeListeners.begin(), m_schematicChangeListeners.end(), + aListener ); + + // Don't add duplicate listeners. + if( it != m_schematicChangeListeners.end() ) + m_schematicChangeListeners.erase( it ); +} \ No newline at end of file diff --git a/eeschema/sch_edit_frame.h b/eeschema/sch_edit_frame.h index 0b62c6871a..b178a3d67e 100644 --- a/eeschema/sch_edit_frame.h +++ b/eeschema/sch_edit_frame.h @@ -93,6 +93,8 @@ enum SCH_CLEANUP_FLAGS }; +wxDECLARE_EVENT( EDA_EVT_SCHEMATIC_CHANGED, wxCommandEvent ); + /** * Schematic editor (Eeschema) main window. */ @@ -817,6 +819,11 @@ public: */ void ToggleSchematicHierarchy(); + /** + * Toggle the show/hide state of Search pane + */ + void ToggleSearch(); + DIALOG_BOOK_REPORTER* GetSymbolDiffDialog(); DIALOG_ERC* GetErcDialog(); @@ -829,6 +836,27 @@ public: return wxT( "SchematicHierarchy" ); } + /** + * @return the name of the wxAuiPaneInfo managing the Search panel + */ + static const wxString SearchPaneName() { return wxT( "Search" ); } + + /** + * Add \a aListener to post #EDA_EVT_SCHEMATIC_CHANGED command events to. + * + * @warning The caller is reponsible for removing any listeners that are no long valid. + * + * @note This only gets called when the schematic editor is in stand alone mode. Changing + * projects in the project manager closes the schematic editor when a new project is + * loaded. + */ + void AddSchematicChangeListener( wxEvtHandler* aListener ); + + /** + * Remove \a aListener to from the schematic changed listener list. + */ + void RemoveSchematicChangeListener( wxEvtHandler* aListener ); + DECLARE_EVENT_TABLE() protected: @@ -948,6 +976,10 @@ private: HIERARCHY_PANE* m_hierarchy; bool m_syncingPcbToSchSelection; // Recursion guard when synchronizing selection from PCB + + bool m_show_search; + + std::vector m_schematicChangeListeners; }; diff --git a/eeschema/toolbars_sch_editor.cpp b/eeschema/toolbars_sch_editor.cpp index 07eebf43ac..9920b91e74 100644 --- a/eeschema/toolbars_sch_editor.cpp +++ b/eeschema/toolbars_sch_editor.cpp @@ -37,6 +37,7 @@ #include #include #include +#include /* Create the main Horizontal Toolbar for the schematic editor */ @@ -225,6 +226,31 @@ void SCH_EDIT_FRAME::ReCreateOptToolbar() } +void SCH_EDIT_FRAME::ToggleSearch() +{ + EESCHEMA_SETTINGS* cfg = eeconfig(); + + // Ensure m_show_search is up to date (the pane can be closed outside the menu) + m_show_search = m_auimgr.GetPane( SearchPaneName() ).IsShown(); + + m_show_search = !m_show_search; + + wxAuiPaneInfo& searchPaneInfo = m_auimgr.GetPane( SearchPaneName() ); + searchPaneInfo.Show( m_show_search ); + + if( m_show_search ) + { + SetAuiPaneSize( m_auimgr, searchPaneInfo, -1, cfg->m_AuiPanels.search_panel_height ); + m_searchPane->FocusSearch(); + } + else + { + cfg->m_AuiPanels.search_panel_height = m_searchPane->GetSize().y; + m_auimgr.Update(); + } +} + + void SCH_EDIT_FRAME::ToggleSchematicHierarchy() { EESCHEMA_SETTINGS* cfg = eeconfig(); diff --git a/eeschema/tools/sch_editor_control.cpp b/eeschema/tools/sch_editor_control.cpp index d0d2b19e4d..1a2f9e9236 100644 --- a/eeschema/tools/sch_editor_control.cpp +++ b/eeschema/tools/sch_editor_control.cpp @@ -2061,6 +2061,13 @@ int SCH_EDITOR_CONTROL::DrawSheetOnClipboard( const TOOL_EVENT& aEvent ) } +int SCH_EDITOR_CONTROL::ShowSearch( const TOOL_EVENT& aEvent ) +{ + getEditFrame()->ToggleSearch(); + return 0; +} + + int SCH_EDITOR_CONTROL::ShowHierarchy( const TOOL_EVENT& aEvent ) { getEditFrame()->ToggleSchematicHierarchy(); @@ -2351,6 +2358,7 @@ void SCH_EDITOR_CONTROL::setTransitions() Go( &SCH_EDITOR_CONTROL::GenerateBOM, EE_ACTIONS::generateBOM.MakeEvent() ); Go( &SCH_EDITOR_CONTROL::DrawSheetOnClipboard, EE_ACTIONS::drawSheetOnClipboard.MakeEvent() ); + Go( &SCH_EDITOR_CONTROL::ShowSearch, EE_ACTIONS::showSearch.MakeEvent() ); Go( &SCH_EDITOR_CONTROL::ShowHierarchy, EE_ACTIONS::showHierarchy.MakeEvent() ); Go( &SCH_EDITOR_CONTROL::ToggleHiddenPins, EE_ACTIONS::toggleHiddenPins.MakeEvent() ); diff --git a/eeschema/tools/sch_editor_control.h b/eeschema/tools/sch_editor_control.h index ff2f7451bf..98b5d1f183 100644 --- a/eeschema/tools/sch_editor_control.h +++ b/eeschema/tools/sch_editor_control.h @@ -123,6 +123,7 @@ public: int GenerateBOM( const TOOL_EVENT& aEvent ); int DrawSheetOnClipboard( const TOOL_EVENT& aEvent ); + int ShowSearch( const TOOL_EVENT& aEvent ); int ShowHierarchy( const TOOL_EVENT& aEvent ); int ToggleHiddenPins( const TOOL_EVENT& aEvent ); diff --git a/eeschema/widgets/sch_search_pane.cpp b/eeschema/widgets/sch_search_pane.cpp new file mode 100644 index 0000000000..5e182e13be --- /dev/null +++ b/eeschema/widgets/sch_search_pane.cpp @@ -0,0 +1,102 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include +#include "sch_search_pane.h" +#include "search_handlers.h" + + +SCH_SEARCH_PANE::SCH_SEARCH_PANE( SCH_EDIT_FRAME* aFrame ) : + SEARCH_PANE( aFrame ), m_schFrame( aFrame ) +{ + m_sch = &(m_schFrame->Schematic()); + + if( m_sch != nullptr ) + m_sch->AddListener( this ); + + m_schFrame->Connect( EDA_EVT_UNITS_CHANGED, + wxCommandEventHandler( SCH_SEARCH_PANE::onUnitsChanged ), nullptr, this ); + + m_schFrame->Connect( EDA_EVT_SCHEMATIC_CHANGED, + wxCommandEventHandler( SCH_SEARCH_PANE::onSchChanged ), nullptr, this ); + + wxFont infoFont = KIUI::GetDockedPaneFont( this ); + SetFont( infoFont ); + m_notebook->SetFont( infoFont ); + + AddSearcher( new SYMBOL_SEARCH_HANDLER( aFrame ) ); + AddSearcher( new TEXT_SEARCH_HANDLER( aFrame ) ); + AddSearcher( new LABEL_SEARCH_HANDLER( aFrame ) ); +} + + +SCH_SEARCH_PANE::~SCH_SEARCH_PANE() +{ + m_schFrame->Disconnect( EDA_EVT_UNITS_CHANGED, + wxCommandEventHandler( SCH_SEARCH_PANE::onUnitsChanged ), nullptr, + this ); + m_schFrame->Disconnect( EDA_EVT_SCHEMATIC_CHANGED, + wxCommandEventHandler( SCH_SEARCH_PANE::onSchChanged ), nullptr, + this ); +} + + +void SCH_SEARCH_PANE::onUnitsChanged( wxCommandEvent& event ) +{ + ClearAllResults(); + RefreshSearch(); + + event.Skip(); +} + + +void SCH_SEARCH_PANE::onSchChanged( wxCommandEvent& event ) +{ + ClearAllResults(); + RefreshSearch(); + + event.Skip(); +} + + +void SCH_SEARCH_PANE::OnSchItemsAdded( SCHEMATIC& aBoard, std::vector& aBoardItems ) +{ + if( !IsShown() ) + return; + + RefreshSearch(); +} + + +void SCH_SEARCH_PANE::OnSchItemsRemoved( SCHEMATIC& aBoard, std::vector& aBoardItems ) +{ + if( !IsShown() ) + return; + + RefreshSearch(); +} + + +void SCH_SEARCH_PANE::OnSchItemsChanged( SCHEMATIC& aBoard, std::vector& aBoardItems ) +{ + if( !IsShown() ) + return; + + RefreshSearch(); +} \ No newline at end of file diff --git a/eeschema/widgets/sch_search_pane.h b/eeschema/widgets/sch_search_pane.h new file mode 100644 index 0000000000..7fbc98c966 --- /dev/null +++ b/eeschema/widgets/sch_search_pane.h @@ -0,0 +1,48 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#ifndef SCH_SEARCH_PANE_H +#define SCH_SEARCH_PANE_H + +#include +#include + +class SCH_EDIT_FRAME; + +class SCH_SEARCH_PANE : public SEARCH_PANE, public SCHEMATIC_LISTENER +{ +public: + SCH_SEARCH_PANE( SCH_EDIT_FRAME* aFrame ); + virtual ~SCH_SEARCH_PANE(); + + virtual void OnSchItemsAdded( SCHEMATIC& aBoard, std::vector& aBoardItems ) override; + virtual void OnSchItemsRemoved( SCHEMATIC& aBoard, + std::vector& aBoardItems ) override; + virtual void OnSchItemsChanged( SCHEMATIC& aBoard, + std::vector& aBoardItems ) override; + +private: + void onUnitsChanged( wxCommandEvent& event ); + void onSchChanged( wxCommandEvent& event ); + + SCH_EDIT_FRAME* m_schFrame; + SCHEMATIC* m_sch; +}; + +#endif \ No newline at end of file diff --git a/eeschema/widgets/search_handlers.cpp b/eeschema/widgets/search_handlers.cpp new file mode 100644 index 0000000000..998c485ac0 --- /dev/null +++ b/eeschema/widgets/search_handlers.cpp @@ -0,0 +1,352 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "search_handlers.h" + + +SCH_SEARCH_HANDLER::SCH_SEARCH_HANDLER( wxString aName, SCH_EDIT_FRAME* aFrame ) : + SEARCH_HANDLER( aName ), m_frame( aFrame ) +{ +} + + +void SCH_SEARCH_HANDLER::ActivateItem( long aItemRow ) +{ + std::vector item = { aItemRow }; + SelectItems( item ); +} + + +void SCH_SEARCH_HANDLER::FindAll( const std::function& aCollector ) +{ + SCH_SCREENS screens( m_frame->Schematic().Root() ); + std::vector paths; + + m_hitlist.clear(); + + screens.BuildClientSheetPathList(); + + for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() ) + { + for( SCH_SHEET_PATH& sheet : screen->GetClientSheetPaths() ) + paths.push_back( &sheet ); + } + + for( SCH_SHEET_PATH* sheet : paths ) + { + for( SCH_ITEM* item : sheet->LastScreen()->Items() ) + { + if( aCollector( item, sheet ) ) + { + m_hitlist.push_back( { item, sheet } ); + } + } + } +} + + +void SCH_SEARCH_HANDLER::SelectItems( std::vector& aItemRows ) +{ + EDA_ITEMS selectedItems; + std::vector selectedHits; + + for( long row : aItemRows ) + { + if( row >= 0 && row < (long) m_hitlist.size() ) + { + selectedHits.emplace_back( m_hitlist[row] ); + selectedItems.emplace_back( m_hitlist[row].item ); + } + } + + bool allHitsOnSamePage = std::all_of( selectedHits.begin() + 1, selectedHits.end(), + [&]( const SCH_SEARCH_HIT& r ) + { + return r.sheetPath == selectedHits.front().sheetPath; + } ); + + m_frame->GetToolManager()->RunAction( EE_ACTIONS::clearSelection, true ); + + if( allHitsOnSamePage ) + { + m_frame->SetCurrentSheet( *selectedHits.front().sheetPath ); + m_frame->DisplayCurrentSheet(); + + if( selectedItems.size() ) + m_frame->GetToolManager()->RunAction( EE_ACTIONS::addItemsToSel, true, &selectedItems ); + + m_frame->GetCanvas()->Refresh( false ); + } +} + + +SYMBOL_SEARCH_HANDLER::SYMBOL_SEARCH_HANDLER( SCH_EDIT_FRAME* aFrame ) : + SCH_SEARCH_HANDLER( wxT( "Symbols" ), aFrame ) +{ + m_columns.emplace_back( wxT( "Reference" ), 1 ); + m_columns.emplace_back( wxT( "Value" ), 3 ); + m_columns.emplace_back( wxT( "Footprint" ), 3 ); + m_columns.emplace_back( wxT( "Page" ), 1 ); + m_columns.emplace_back( wxT( "X" ), 2 ); + m_columns.emplace_back( wxT( "Y" ), 2 ); +} + + +int SYMBOL_SEARCH_HANDLER::Search( const wxString& aQuery ) +{ + m_hitlist.clear(); + SCHEMATIC& sch = m_frame->Schematic(); + + SCH_SEARCH_DATA frp; + frp.findString = aQuery; + frp.matchMode = EDA_SEARCH_MATCH_MODE::WILDCARD; + frp.searchCurrentSheetOnly = false; + + auto search = [frp]( SCH_ITEM* item, SCH_SHEET_PATH* sheet ) + { + if( item->Type() == SCH_SYMBOL_T ) + { + SCH_SYMBOL* sym = dynamic_cast( item ); + if( sym->IsPower() ) + return false; + + bool hit = false; + for( SCH_FIELD& field : sym->GetFields() ) + { + if( field.Matches( frp, sheet ) ) + { + hit = true; + } + } + + if( hit ) + { + return true; + } + } + + return false; + }; + + FindAll( search ); + + return (int) m_hitlist.size(); +} + + +wxString SYMBOL_SEARCH_HANDLER::GetResultCell( int aRow, int aCol ) +{ + SCH_SEARCH_HIT hit = m_hitlist[aRow]; + SCH_SYMBOL* sym = dynamic_cast( hit.item ); + + if( !sym ) + return wxEmptyString; + + if( aCol == 0 ) + return sym->GetRef( hit.sheetPath, true ); + else if( aCol == 1 ) + return sym->GetField( VALUE_FIELD )->GetShownText( hit.sheetPath, false ); + else if( aCol == 2 ) + return sym->GetField( FOOTPRINT_FIELD )->GetShownText( hit.sheetPath, false ); + else if( aCol == 3 ) + return hit.sheetPath->GetPageNumber(); + else if( aCol == 4 ) + return m_frame->MessageTextFromValue( sym->GetPosition().x ); + else if( aCol == 5 ) + return m_frame->MessageTextFromValue( sym->GetPosition().y ); + + + return wxEmptyString; +} + + +TEXT_SEARCH_HANDLER::TEXT_SEARCH_HANDLER( SCH_EDIT_FRAME* aFrame ) : + SCH_SEARCH_HANDLER( wxT( "Text" ), aFrame ) +{ + m_columns.emplace_back( wxT( "Type" ), 1 ); + m_columns.emplace_back( wxT( "Text" ), 5 ); + m_columns.emplace_back( wxT( "Page" ), 1 ); + m_columns.emplace_back( wxT( "X" ), 2 ); + m_columns.emplace_back( wxT( "Y" ), 2 ); +} + + +int TEXT_SEARCH_HANDLER::Search( const wxString& aQuery ) +{ + m_hitlist.clear(); + + SCH_SEARCH_DATA frp; + frp.findString = aQuery; + frp.matchMode = EDA_SEARCH_MATCH_MODE::WILDCARD; + frp.searchCurrentSheetOnly = false; + + auto search = [frp]( SCH_ITEM* item, SCH_SHEET_PATH* sheet ) + { + if( item->Type() == SCH_TEXT_T ) + { + SCH_TEXT* text = dynamic_cast( item ); + if( text->Matches( frp, sheet ) ) + { + return true; + } + } + else if( item->Type() == SCH_TEXTBOX_T ) + { + SCH_TEXTBOX* text = dynamic_cast( item ); + if( text->Matches( frp, sheet ) ) + { + return true; + } + } + + return false; + }; + + FindAll( search ); + + return (int) m_hitlist.size(); +} + + +wxString TEXT_SEARCH_HANDLER::GetResultCell( int aRow, int aCol ) +{ + SCH_SEARCH_HIT hit = m_hitlist[aRow]; + + if( hit.item->Type() == SCH_TEXT_T ) + { + SCH_TEXT* txt = dynamic_cast( hit.item ); + + if( !txt ) + return wxEmptyString; + + if( aCol == 0 ) + return wxS( "Text" ); + else if( aCol == 1 ) + return txt->GetShownText( false ); + else if( aCol == 2 ) + return hit.sheetPath->GetPageNumber(); + else if( aCol == 3 ) + return m_frame->MessageTextFromValue( txt->GetPosition().x ); + else if( aCol == 4 ) + return m_frame->MessageTextFromValue( txt->GetPosition().y ); + } + else if( hit.item->Type() == SCH_TEXTBOX_T ) + { + SCH_TEXTBOX* txt = dynamic_cast( hit.item ); + + if( !txt ) + return wxEmptyString; + + if( aCol == 0 ) + return wxS( "Text" ); + else if( aCol == 1 ) + return txt->GetShownText( false ); + else if( aCol == 2 ) + return hit.sheetPath->GetPageNumber(); + else if( aCol == 3 ) + return m_frame->MessageTextFromValue( txt->GetPosition().x ); + else if( aCol == 4 ) + return m_frame->MessageTextFromValue( txt->GetPosition().y ); + } + + + return wxEmptyString; +} + + +LABEL_SEARCH_HANDLER::LABEL_SEARCH_HANDLER( SCH_EDIT_FRAME* aFrame ) : + SCH_SEARCH_HANDLER( wxT( "Labels" ), aFrame ) +{ + m_columns.emplace_back( wxT( "Type" ), 1 ); + m_columns.emplace_back( wxT( "Name" ), 4 ); + m_columns.emplace_back( wxT( "Page" ), 1 ); + m_columns.emplace_back( wxT( "X" ), 2 ); + m_columns.emplace_back( wxT( "Y" ), 2 ); +} + + +int LABEL_SEARCH_HANDLER::Search( const wxString& aQuery ) +{ + m_hitlist.clear(); + + SCH_SEARCH_DATA frp; + frp.findString = aQuery; + frp.matchMode = EDA_SEARCH_MATCH_MODE::WILDCARD; + frp.searchCurrentSheetOnly = false; + + auto search = [frp]( SCH_ITEM* item, SCH_SHEET_PATH* sheet ) + { + if( item->Type() == SCH_LABEL_T || item->Type() == SCH_GLOBAL_LABEL_T + || item->Type() == SCH_HIER_LABEL_T ) + { + SCH_LABEL_BASE* lbl = dynamic_cast( item ); + if( lbl->Matches( frp, sheet ) ) + { + return true; + } + } + + return false; + }; + + FindAll( search ); + + return (int) m_hitlist.size(); +} + + +wxString LABEL_SEARCH_HANDLER::GetResultCell( int aRow, int aCol ) +{ + SCH_SEARCH_HIT hit = m_hitlist[aRow]; + + SCH_LABEL_BASE* lbl = dynamic_cast( hit.item ); + + if( !lbl ) + return wxEmptyString; + + if (aCol == 0) + { + if(lbl->Type() == SCH_LABEL_T) + return wxS( "Local" ); + else if( lbl->Type() == SCH_GLOBAL_LABEL_T ) + return wxS( "Global" ); + else if( lbl->Type() == SCH_HIER_LABEL_T ) + return wxS( "Hierarchal" ); + } + else if( aCol == 1 ) + return lbl->GetShownText( false ); + else if( aCol == 2 ) + return hit.sheetPath->GetPageNumber(); + else if( aCol == 3 ) + return m_frame->MessageTextFromValue( lbl->GetPosition().x ); + else if( aCol == 4 ) + return m_frame->MessageTextFromValue( lbl->GetPosition().y ); + + return wxEmptyString; +} \ No newline at end of file diff --git a/eeschema/widgets/search_handlers.h b/eeschema/widgets/search_handlers.h new file mode 100644 index 0000000000..fc9c7dfb57 --- /dev/null +++ b/eeschema/widgets/search_handlers.h @@ -0,0 +1,84 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef SEARCH_HANDLERS_H +#define SEARCH_HANDLERS_H + +#include +#include + +class SCH_ITEM; +class SCH_TEXT; +class SCH_EDIT_FRAME; + +struct SCH_SEARCH_HIT +{ + SCH_ITEM* item; + SCH_SHEET_PATH* sheetPath; +}; + +class SCH_SEARCH_HANDLER : public SEARCH_HANDLER +{ +public: + SCH_SEARCH_HANDLER( wxString aName, SCH_EDIT_FRAME* aFrame ); + void ActivateItem( long aItemRow ) override; + + void FindAll( const std::function& aCollector ); + void SelectItems( std::vector& aItemRows ) override; + +protected: + SCH_EDIT_FRAME* m_frame; + std::vector m_hitlist; +}; + +class SYMBOL_SEARCH_HANDLER : public SCH_SEARCH_HANDLER +{ +public: + SYMBOL_SEARCH_HANDLER( SCH_EDIT_FRAME* aFrame ); + + int Search( const wxString& aQuery ) override; + wxString GetResultCell( int aRow, int aCol ) override; + +}; + +class TEXT_SEARCH_HANDLER : public SCH_SEARCH_HANDLER +{ +public: + TEXT_SEARCH_HANDLER( SCH_EDIT_FRAME* aFrame ); + + int Search( const wxString& aQuery ) override; + wxString GetResultCell( int aRow, int aCol ) override; + +}; + +class LABEL_SEARCH_HANDLER : public SCH_SEARCH_HANDLER +{ +public: + LABEL_SEARCH_HANDLER( SCH_EDIT_FRAME* aFrame ); + + int Search( const wxString& aQuery ) override; + wxString GetResultCell( int aRow, int aCol ) override; + +}; + +#endif