2022-09-14 02:59:57 +00:00
|
|
|
/*
|
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
|
|
*
|
2025-01-01 13:30:11 -08:00
|
|
|
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
2022-09-14 02:59:57 +00:00
|
|
|
*
|
|
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2024-11-02 01:30:45 +08:00
|
|
|
#include "widgets/search_pane.h"
|
|
|
|
|
2025-08-02 22:56:24 +01:00
|
|
|
#include <memory>
|
2024-11-02 01:30:45 +08:00
|
|
|
#include <tool/action_menu.h>
|
2025-07-24 13:13:42 -07:00
|
|
|
#include <tool/tool_dispatcher.h>
|
|
|
|
#include <tool/tool_manager.h>
|
2024-11-02 01:30:45 +08:00
|
|
|
#include <settings/app_settings.h>
|
2022-09-14 02:59:57 +00:00
|
|
|
#include <eda_draw_frame.h>
|
2024-11-02 01:30:45 +08:00
|
|
|
#include <bitmaps.h>
|
2022-09-14 02:59:57 +00:00
|
|
|
#include <kiway.h>
|
2024-11-02 01:30:45 +08:00
|
|
|
#include <widgets/search_pane_tab.h>
|
2025-02-02 20:29:36 +00:00
|
|
|
#include <widgets/std_bitmap_button.h>
|
2024-11-02 01:30:45 +08:00
|
|
|
|
|
|
|
|
2025-04-07 17:00:27 +01:00
|
|
|
#define ID_TOGGLE_ZOOM_TO_SELECTION 14000
|
|
|
|
#define ID_TOGGLE_PAN_TO_SELECTION 14001
|
|
|
|
#define ID_TOGGLE_SEARCH_HIDDEN_FIELDS 14002
|
2024-11-02 01:30:45 +08:00
|
|
|
|
|
|
|
|
|
|
|
class SEARCH_PANE_MENU : public ACTION_MENU
|
|
|
|
{
|
|
|
|
public:
|
2025-04-07 17:00:27 +01:00
|
|
|
SEARCH_PANE_MENU( SEARCH_PANE* aSearchPane, EDA_DRAW_FRAME& aFrame ) :
|
2025-02-02 20:09:28 +00:00
|
|
|
ACTION_MENU( true, nullptr ),
|
2025-04-07 17:00:27 +01:00
|
|
|
m_frame( aFrame ),
|
|
|
|
m_searchPane( aSearchPane )
|
2024-11-02 01:30:45 +08:00
|
|
|
{
|
|
|
|
Add( _( "Zoom to Selection" ), _( "Toggle zooming to selections in the search pane" ),
|
|
|
|
ID_TOGGLE_ZOOM_TO_SELECTION, BITMAPS::zoom_fit_to_objects, true );
|
|
|
|
Add( _( "Pan to Selection" ), _( "Toggle panning to selections in the search pane" ),
|
|
|
|
ID_TOGGLE_PAN_TO_SELECTION, BITMAPS::zoom_center_on_screen, true );
|
|
|
|
|
2025-04-07 17:00:27 +01:00
|
|
|
AppendSeparator();
|
|
|
|
Add( _( "Search Hidden Fields" ), wxEmptyString,
|
|
|
|
ID_TOGGLE_SEARCH_HIDDEN_FIELDS, BITMAPS::invisible_text, true );
|
|
|
|
|
2024-11-02 01:30:45 +08:00
|
|
|
updateZoomPanCheckboxes();
|
|
|
|
}
|
|
|
|
|
|
|
|
OPT_TOOL_EVENT eventHandler( const wxMenuEvent& aEvent ) override
|
|
|
|
{
|
|
|
|
APP_SETTINGS_BASE::SEARCH_PANE& settings = m_frame.config()->m_SearchPane;
|
|
|
|
const int id = aEvent.GetId();
|
|
|
|
const wxMenuItem* item = FindItem( id );
|
|
|
|
|
|
|
|
switch( id )
|
|
|
|
{
|
|
|
|
case ID_TOGGLE_ZOOM_TO_SELECTION:
|
2025-03-20 12:25:58 +00:00
|
|
|
settings.selection_zoom = item->IsChecked() ? APP_SETTINGS_BASE::SEARCH_PANE::SELECTION_ZOOM::ZOOM
|
|
|
|
: APP_SETTINGS_BASE::SEARCH_PANE::SELECTION_ZOOM::NONE;
|
2024-11-02 01:30:45 +08:00
|
|
|
updateZoomPanCheckboxes();
|
|
|
|
break;
|
2025-04-07 17:00:27 +01:00
|
|
|
|
2024-11-02 01:30:45 +08:00
|
|
|
case ID_TOGGLE_PAN_TO_SELECTION:
|
2025-03-20 12:25:58 +00:00
|
|
|
settings.selection_zoom = item->IsChecked() ? APP_SETTINGS_BASE::SEARCH_PANE::SELECTION_ZOOM::PAN
|
|
|
|
: APP_SETTINGS_BASE::SEARCH_PANE::SELECTION_ZOOM::NONE;
|
2024-11-02 01:30:45 +08:00
|
|
|
updateZoomPanCheckboxes();
|
|
|
|
break;
|
2025-04-07 17:00:27 +01:00
|
|
|
|
|
|
|
case ID_TOGGLE_SEARCH_HIDDEN_FIELDS:
|
|
|
|
settings.search_hidden_fields = item->IsChecked();
|
|
|
|
updateZoomPanCheckboxes();
|
|
|
|
m_searchPane->RefreshSearch();
|
|
|
|
break;
|
2024-11-02 01:30:45 +08:00
|
|
|
}
|
2025-04-07 17:00:27 +01:00
|
|
|
|
2024-11-02 01:30:45 +08:00
|
|
|
return OPT_TOOL_EVENT();
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
void updateZoomPanCheckboxes()
|
|
|
|
{
|
|
|
|
APP_SETTINGS_BASE::SEARCH_PANE& settings = m_frame.config()->m_SearchPane;
|
|
|
|
|
|
|
|
wxMenuItem* zoomCb = FindItem( ID_TOGGLE_ZOOM_TO_SELECTION );
|
|
|
|
wxMenuItem* panCb = FindItem( ID_TOGGLE_PAN_TO_SELECTION );
|
2025-04-07 17:00:27 +01:00
|
|
|
wxMenuItem* hiddenFieldsCb = FindItem( ID_TOGGLE_SEARCH_HIDDEN_FIELDS );
|
2024-11-02 01:30:45 +08:00
|
|
|
|
2025-03-20 12:25:58 +00:00
|
|
|
zoomCb->Check( settings.selection_zoom == APP_SETTINGS_BASE::SEARCH_PANE::SELECTION_ZOOM::ZOOM );
|
|
|
|
panCb->Check( settings.selection_zoom == APP_SETTINGS_BASE::SEARCH_PANE::SELECTION_ZOOM::PAN );
|
2025-04-07 17:00:27 +01:00
|
|
|
hiddenFieldsCb->Check( settings.search_hidden_fields );
|
2024-11-02 01:30:45 +08:00
|
|
|
}
|
|
|
|
|
2025-02-02 20:29:36 +00:00
|
|
|
private:
|
2024-11-02 01:30:45 +08:00
|
|
|
EDA_DRAW_FRAME& m_frame;
|
2025-04-07 17:00:27 +01:00
|
|
|
SEARCH_PANE* m_searchPane;
|
2024-11-02 01:30:45 +08:00
|
|
|
};
|
2022-09-14 02:59:57 +00:00
|
|
|
|
|
|
|
|
|
|
|
SEARCH_PANE::SEARCH_PANE( EDA_DRAW_FRAME* aFrame ) :
|
2025-03-20 12:25:58 +00:00
|
|
|
SEARCH_PANE_BASE( aFrame ),
|
|
|
|
m_frame( aFrame )
|
2022-09-14 02:59:57 +00:00
|
|
|
{
|
2024-03-03 10:57:26 -05:00
|
|
|
m_frame->Bind( EDA_LANG_CHANGED, &SEARCH_PANE::OnLanguageChange, this );
|
2024-11-02 01:30:45 +08:00
|
|
|
|
2025-04-07 17:00:27 +01:00
|
|
|
m_menu = new SEARCH_PANE_MENU( this, *m_frame );
|
2024-11-02 01:30:45 +08:00
|
|
|
|
|
|
|
m_menuButton->SetBitmap( KiBitmapBundle( BITMAPS::config ) );
|
|
|
|
m_menuButton->Bind( wxEVT_LEFT_DOWN,
|
|
|
|
[&]( wxMouseEvent& event )
|
|
|
|
{
|
|
|
|
PopupMenu( m_menu );
|
|
|
|
} );
|
2025-03-11 22:37:29 -04:00
|
|
|
|
|
|
|
m_frame->Bind( wxEVT_AUI_PANE_CLOSE, &SEARCH_PANE::OnClosed, this );
|
2025-07-24 13:13:42 -07:00
|
|
|
Bind( wxEVT_CHAR_HOOK, &SEARCH_PANE::OnCharHook, this );
|
2022-09-14 02:59:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SEARCH_PANE::~SEARCH_PANE()
|
|
|
|
{
|
2025-03-11 22:37:29 -04:00
|
|
|
m_frame->Unbind( wxEVT_AUI_PANE_CLOSE, &SEARCH_PANE::OnClosed, this );
|
2024-03-03 10:57:26 -05:00
|
|
|
m_frame->Unbind( EDA_LANG_CHANGED, &SEARCH_PANE::OnLanguageChange, this );
|
2025-07-24 13:13:42 -07:00
|
|
|
Unbind( wxEVT_CHAR_HOOK, &SEARCH_PANE::OnCharHook, this );
|
2024-11-02 01:30:45 +08:00
|
|
|
|
2025-08-02 20:11:12 +01:00
|
|
|
m_handlers.clear();
|
|
|
|
|
2024-11-02 01:30:45 +08:00
|
|
|
delete m_menu;
|
2022-09-14 02:59:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-03-03 10:57:26 -05:00
|
|
|
void SEARCH_PANE::OnLanguageChange( wxCommandEvent& aEvent )
|
2022-09-14 02:59:57 +00:00
|
|
|
{
|
2024-01-28 11:42:27 +00:00
|
|
|
m_searchCtrl1->SetDescriptiveText( _( "Search" ) );
|
|
|
|
|
2022-09-14 02:59:57 +00:00
|
|
|
for( size_t i = 0; i < m_notebook->GetPageCount(); ++i )
|
|
|
|
{
|
|
|
|
wxWindow* page = m_notebook->GetPage( i );
|
|
|
|
SEARCH_PANE_TAB* tab = dynamic_cast<SEARCH_PANE_TAB*>( page );
|
|
|
|
|
2023-03-02 09:04:37 -05:00
|
|
|
wxCHECK( tab, /* void */ );
|
|
|
|
|
2022-09-14 02:59:57 +00:00
|
|
|
tab->RefreshColumnNames();
|
2022-12-10 23:37:23 +00:00
|
|
|
m_notebook->SetPageText( i, wxGetTranslation( tab->GetSearchHandler()->GetName() ) );
|
2022-09-14 02:59:57 +00:00
|
|
|
}
|
2024-03-03 10:57:26 -05:00
|
|
|
|
|
|
|
aEvent.Skip();
|
2022-09-14 02:59:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2025-08-02 22:02:39 +01:00
|
|
|
void SEARCH_PANE::AddSearcher( const std::shared_ptr<SEARCH_HANDLER>& aHandler )
|
2022-09-14 02:59:57 +00:00
|
|
|
{
|
|
|
|
SEARCH_PANE_TAB* tab = new SEARCH_PANE_TAB( aHandler, m_notebook );
|
|
|
|
|
2022-12-10 23:37:23 +00:00
|
|
|
m_notebook->AddPage( tab, wxGetTranslation( aHandler->GetName() ) );
|
2022-09-14 02:59:57 +00:00
|
|
|
m_handlers.push_back( aHandler );
|
|
|
|
m_tabs.push_back( tab );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SEARCH_PANE::RefreshSearch()
|
2022-09-20 23:38:06 -04:00
|
|
|
{
|
|
|
|
SEARCH_PANE_TAB* tab = GetCurrentTab();
|
|
|
|
|
|
|
|
if( tab )
|
|
|
|
tab->Search( m_lastQuery );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SEARCH_PANE::ClearAllResults()
|
2022-09-14 02:59:57 +00:00
|
|
|
{
|
|
|
|
for( SEARCH_PANE_TAB* tab : m_tabs )
|
2022-09-20 23:38:06 -04:00
|
|
|
tab->Clear();
|
2022-09-14 02:59:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SEARCH_PANE::OnSearchTextEntry( wxCommandEvent& aEvent )
|
|
|
|
{
|
|
|
|
wxString query = m_searchCtrl1->GetValue();
|
|
|
|
m_lastQuery = query;
|
|
|
|
|
|
|
|
RefreshSearch();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SEARCH_PANE::FocusSearch()
|
|
|
|
{
|
|
|
|
m_searchCtrl1->SetFocus();
|
2022-09-20 23:38:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SEARCH_PANE::OnNotebookPageChanged( wxBookCtrlEvent& aEvent )
|
|
|
|
{
|
|
|
|
SEARCH_PANE_TAB* tab = GetCurrentTab();
|
|
|
|
|
|
|
|
if( tab )
|
|
|
|
tab->Search( m_lastQuery );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2025-03-11 22:37:29 -04:00
|
|
|
void SEARCH_PANE::OnClosed( wxAuiManagerEvent& aEvent )
|
2025-02-10 11:15:53 +00:00
|
|
|
{
|
|
|
|
if( APP_SETTINGS_BASE* cfg = m_frame->config() )
|
|
|
|
m_frame->SaveSettings( cfg );
|
|
|
|
|
|
|
|
aEvent.Skip();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-09-20 23:38:06 -04:00
|
|
|
SEARCH_PANE_TAB* SEARCH_PANE::GetCurrentTab() const
|
|
|
|
{
|
|
|
|
return dynamic_cast<SEARCH_PANE_TAB*>( m_notebook->GetCurrentPage() );
|
2023-03-02 09:04:37 -05:00
|
|
|
}
|
2025-07-24 13:13:42 -07:00
|
|
|
|
|
|
|
|
|
|
|
void SEARCH_PANE::OnCharHook( wxKeyEvent& aEvent )
|
|
|
|
{
|
|
|
|
// Check if the event is from a child window of the search pane
|
|
|
|
wxWindow* eventObject = dynamic_cast<wxWindow*>( aEvent.GetEventObject() );
|
|
|
|
|
|
|
|
if( !eventObject || !IsDescendant( eventObject ) )
|
|
|
|
{
|
|
|
|
aEvent.Skip();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try to let the tool framework handle the event
|
|
|
|
if( m_frame->GetToolDispatcher() )
|
|
|
|
{
|
|
|
|
m_frame->GetToolDispatcher()->DispatchWxEvent( aEvent );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
aEvent.Skip();
|
|
|
|
}
|