mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-04-21 00:21:25 +00:00
Separate generic aspects of NET_SELECTOR_COMBOPOPUP
Lots of this class is reusable, and it's a fiddly one that can be useful elsewhere.
This commit is contained in:
parent
5f69a5779f
commit
a090b86b87
@ -402,6 +402,7 @@ set( COMMON_WIDGET_SRCS
|
||||
widgets/bitmap_toggle.cpp
|
||||
widgets/button_row_panel.cpp
|
||||
widgets/color_swatch.cpp
|
||||
widgets/filter_combobox.cpp
|
||||
widgets/font_choice.cpp
|
||||
widgets/footprint_choice.cpp
|
||||
widgets/footprint_diff_widget.cpp
|
||||
|
445
common/widgets/filter_combobox.cpp
Normal file
445
common/widgets/filter_combobox.cpp
Normal file
@ -0,0 +1,445 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 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
|
||||
*/
|
||||
|
||||
|
||||
#include "widgets/filter_combobox.h"
|
||||
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/listbox.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/valtext.h>
|
||||
|
||||
#include <kiplatform/ui.h>
|
||||
#include <widgets/ui_common.h>
|
||||
|
||||
wxDEFINE_EVENT( FILTERED_ITEM_SELECTED, wxCommandEvent );
|
||||
|
||||
#if defined( __WXOSX_MAC__ )
|
||||
#define POPUP_PADDING 2
|
||||
#define LIST_ITEM_PADDING 5
|
||||
#define LIST_PADDING 5
|
||||
#elif defined( __WXMSW__ )
|
||||
#define POPUP_PADDING 0
|
||||
#define LIST_ITEM_PADDING 2
|
||||
#define LIST_PADDING 5
|
||||
#else
|
||||
#define POPUP_PADDING 0
|
||||
#define LIST_ITEM_PADDING 6
|
||||
#define LIST_PADDING 5
|
||||
#endif
|
||||
|
||||
|
||||
FILTER_COMBOPOPUP::FILTER_COMBOPOPUP() :
|
||||
m_filterValidator( nullptr ),
|
||||
m_filterCtrl( nullptr ),
|
||||
m_listBox( nullptr ),
|
||||
m_minPopupWidth( -1 ),
|
||||
m_maxPopupHeight( 1000 ),
|
||||
m_focusHandler( nullptr )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool FILTER_COMBOPOPUP::Create( wxWindow* aParent )
|
||||
{
|
||||
wxPanel::Create( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER );
|
||||
|
||||
wxBoxSizer* mainSizer;
|
||||
mainSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxStaticText* filterLabel = new wxStaticText( this, wxID_ANY, _( "Filter:" ) );
|
||||
mainSizer->Add( filterLabel, 0, wxEXPAND, 0 );
|
||||
|
||||
m_filterCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
|
||||
wxTE_PROCESS_ENTER );
|
||||
m_filterValidator = new wxTextValidator( wxFILTER_EXCLUDE_CHAR_LIST );
|
||||
m_filterValidator->SetCharExcludes( " " );
|
||||
m_filterCtrl->SetValidator( *m_filterValidator );
|
||||
mainSizer->Add( m_filterCtrl, 0, wxEXPAND, 0 );
|
||||
|
||||
m_listBox = new wxListBox( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, nullptr,
|
||||
wxLB_SINGLE | wxLB_NEEDED_SB );
|
||||
mainSizer->Add( m_listBox, 0, wxEXPAND | wxTOP, 2 );
|
||||
|
||||
SetSizer( mainSizer );
|
||||
Layout();
|
||||
|
||||
Connect( wxEVT_IDLE, wxIdleEventHandler( FILTER_COMBOPOPUP::onIdle ), nullptr, this );
|
||||
Connect( wxEVT_CHAR_HOOK, wxKeyEventHandler( FILTER_COMBOPOPUP::onKeyDown ), nullptr, this );
|
||||
Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( FILTER_COMBOPOPUP::onMouseClick ), nullptr,
|
||||
this );
|
||||
m_listBox->Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( FILTER_COMBOPOPUP::onMouseClick ),
|
||||
nullptr, this );
|
||||
m_filterCtrl->Connect( wxEVT_TEXT, wxCommandEventHandler( FILTER_COMBOPOPUP::onFilterEdit ),
|
||||
nullptr, this );
|
||||
m_filterCtrl->Connect( wxEVT_TEXT_ENTER, wxCommandEventHandler( FILTER_COMBOPOPUP::onEnter ),
|
||||
nullptr, this );
|
||||
|
||||
// <enter> in a ListBox comes in as a double-click on GTK
|
||||
m_listBox->Connect( wxEVT_COMMAND_LISTBOX_DOUBLECLICKED,
|
||||
wxCommandEventHandler( FILTER_COMBOPOPUP::onEnter ), nullptr, this );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void FILTER_COMBOPOPUP::SetStringValue( const wxString& aNetName )
|
||||
{
|
||||
// shouldn't be here (combo is read-only)
|
||||
}
|
||||
|
||||
|
||||
void FILTER_COMBOPOPUP::OnPopup()
|
||||
{
|
||||
// While it can sometimes be useful to keep the filter, it's always unexpected.
|
||||
// Better to clear it.
|
||||
m_filterCtrl->Clear();
|
||||
|
||||
m_listBox->SetStringSelection( GetStringValue() );
|
||||
m_filterCtrl->SetFocus();
|
||||
|
||||
// The updateSize() call in GetAdjustedSize() leaves the height off-by-one for
|
||||
// some reason, so do it again.
|
||||
updateSize();
|
||||
}
|
||||
|
||||
|
||||
void FILTER_COMBOPOPUP:: OnStartingKey( wxKeyEvent& aEvent )
|
||||
{
|
||||
doSetFocus( m_filterCtrl );
|
||||
doStartingKey( aEvent );
|
||||
}
|
||||
|
||||
|
||||
wxSize FILTER_COMBOPOPUP::GetAdjustedSize( int aMinWidth, int aPrefHeight, int aMaxHeight )
|
||||
{
|
||||
// Called when the popup is first shown. Stash the minWidth and maxHeight so we
|
||||
// can use them later when refreshing the sizes after filter changes.
|
||||
m_minPopupWidth = aMinWidth;
|
||||
m_maxPopupHeight = aMaxHeight;
|
||||
|
||||
return updateSize();
|
||||
}
|
||||
|
||||
|
||||
void FILTER_COMBOPOPUP::rebuildList()
|
||||
{
|
||||
wxArrayString newList;
|
||||
getListContent( newList );
|
||||
|
||||
m_listBox->Set( newList );
|
||||
}
|
||||
|
||||
|
||||
std::optional<wxString> FILTER_COMBOPOPUP::getSelectedValue() const
|
||||
{
|
||||
int selection = m_listBox->GetSelection();
|
||||
|
||||
if( selection >= 0 )
|
||||
return m_listBox->GetString( selection );
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
|
||||
wxString FILTER_COMBOPOPUP::getFilterValue() const
|
||||
{
|
||||
return m_filterCtrl->GetValue().Trim( true ).Trim( false );
|
||||
}
|
||||
|
||||
|
||||
wxSize FILTER_COMBOPOPUP::updateSize()
|
||||
{
|
||||
int listTop = m_listBox->GetRect().y;
|
||||
int itemHeight = KIUI::GetTextSize( wxT( "Xy" ), this ).y + LIST_ITEM_PADDING;
|
||||
int listHeight = m_listBox->GetCount() * itemHeight + LIST_PADDING;
|
||||
|
||||
if( listTop + listHeight >= m_maxPopupHeight )
|
||||
listHeight = m_maxPopupHeight - listTop - 1;
|
||||
|
||||
int listWidth = m_minPopupWidth;
|
||||
|
||||
for( size_t i = 0; i < m_listBox->GetCount(); ++i )
|
||||
{
|
||||
int itemWidth = KIUI::GetTextSize( m_listBox->GetString( i ), m_listBox ).x;
|
||||
listWidth = std::max( listWidth, itemWidth + LIST_PADDING * 3 );
|
||||
}
|
||||
|
||||
wxSize listSize( listWidth, listHeight );
|
||||
wxSize popupSize( listWidth, listTop + listHeight );
|
||||
|
||||
SetSize( popupSize ); // us
|
||||
GetParent()->SetSize( popupSize ); // the window that wxComboCtrl put us in
|
||||
|
||||
m_listBox->SetMinSize( listSize );
|
||||
m_listBox->SetSize( listSize );
|
||||
|
||||
return popupSize;
|
||||
}
|
||||
|
||||
|
||||
void FILTER_COMBOPOPUP::onIdle( wxIdleEvent& aEvent )
|
||||
{
|
||||
// Generate synthetic (but reliable) MouseMoved events
|
||||
static wxPoint lastPos;
|
||||
wxPoint screenPos = KIPLATFORM::UI::GetMousePosition();
|
||||
|
||||
if( screenPos != lastPos )
|
||||
{
|
||||
lastPos = screenPos;
|
||||
onMouseMoved( screenPos );
|
||||
}
|
||||
|
||||
if( m_focusHandler )
|
||||
{
|
||||
m_filterCtrl->PushEventHandler( m_focusHandler );
|
||||
m_focusHandler = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Hot-track the mouse (for focus and listbox selection)
|
||||
void FILTER_COMBOPOPUP::onMouseMoved( const wxPoint aScreenPos )
|
||||
{
|
||||
if( m_listBox->GetScreenRect().Contains( aScreenPos ) )
|
||||
{
|
||||
doSetFocus( m_listBox );
|
||||
|
||||
wxPoint relativePos = m_listBox->ScreenToClient( aScreenPos );
|
||||
int item = m_listBox->HitTest( relativePos );
|
||||
|
||||
if( item >= 0 )
|
||||
m_listBox->SetSelection( item );
|
||||
}
|
||||
else if( m_filterCtrl->GetScreenRect().Contains( aScreenPos ) )
|
||||
{
|
||||
doSetFocus( m_filterCtrl );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FILTER_COMBOPOPUP::onMouseClick( wxMouseEvent& aEvent )
|
||||
{
|
||||
// Accept a click event from anywhere. Different platform implementations have
|
||||
// different foibles with regard to transient popups and their children.
|
||||
|
||||
if( aEvent.GetEventObject() == m_listBox )
|
||||
{
|
||||
m_listBox->SetSelection( m_listBox->HitTest( aEvent.GetPosition() ) );
|
||||
Accept();
|
||||
return;
|
||||
}
|
||||
|
||||
wxWindow* window = dynamic_cast<wxWindow*>( aEvent.GetEventObject() );
|
||||
|
||||
if( window )
|
||||
{
|
||||
wxPoint screenPos = window->ClientToScreen( aEvent.GetPosition() );
|
||||
|
||||
if( m_listBox->GetScreenRect().Contains( screenPos ) )
|
||||
{
|
||||
wxPoint localPos = m_listBox->ScreenToClient( screenPos );
|
||||
|
||||
m_listBox->SetSelection( m_listBox->HitTest( localPos ) );
|
||||
Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FILTER_COMBOPOPUP::onKeyDown( wxKeyEvent& aEvent )
|
||||
{
|
||||
switch( aEvent.GetKeyCode() )
|
||||
{
|
||||
// Control keys go to the parent combobox
|
||||
case WXK_TAB:
|
||||
Dismiss();
|
||||
|
||||
m_parent->NavigateIn( ( aEvent.ShiftDown() ? 0 : wxNavigationKeyEvent::IsForward ) |
|
||||
( aEvent.ControlDown() ? wxNavigationKeyEvent::WinChange : 0 ) );
|
||||
break;
|
||||
|
||||
case WXK_ESCAPE:
|
||||
Dismiss();
|
||||
break;
|
||||
|
||||
case WXK_RETURN:
|
||||
case WXK_NUMPAD_ENTER:
|
||||
Accept();
|
||||
break;
|
||||
|
||||
// Arrows go to the list box
|
||||
case WXK_DOWN:
|
||||
case WXK_NUMPAD_DOWN:
|
||||
doSetFocus( m_listBox );
|
||||
m_listBox->SetSelection( std::min( m_listBox->GetSelection() + 1, (int) m_listBox->GetCount() - 1 ) );
|
||||
break;
|
||||
|
||||
case WXK_UP:
|
||||
case WXK_NUMPAD_UP:
|
||||
doSetFocus( m_listBox );
|
||||
m_listBox->SetSelection( std::max( m_listBox->GetSelection() - 1, 0 ) );
|
||||
break;
|
||||
|
||||
// Everything else goes to the filter textbox
|
||||
default:
|
||||
if( !m_filterCtrl->HasFocus() )
|
||||
{
|
||||
doSetFocus( m_filterCtrl );
|
||||
|
||||
// Because we didn't have focus we missed our chance to have the native widget
|
||||
// handle the keystroke. We'll have to do the first character ourselves.
|
||||
doStartingKey( aEvent );
|
||||
}
|
||||
else
|
||||
{
|
||||
// On some platforms a wxComboFocusHandler will have been pushed which
|
||||
// unhelpfully gives the event right back to the popup. Make sure the filter
|
||||
// control is going to get the event.
|
||||
if( m_filterCtrl->GetEventHandler() != m_filterCtrl )
|
||||
m_focusHandler = m_filterCtrl->PopEventHandler();
|
||||
|
||||
aEvent.Skip();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FILTER_COMBOPOPUP::onEnter( wxCommandEvent& aEvent )
|
||||
{
|
||||
Accept();
|
||||
}
|
||||
|
||||
|
||||
void FILTER_COMBOPOPUP::onFilterEdit( wxCommandEvent& aEvent )
|
||||
{
|
||||
rebuildList();
|
||||
updateSize();
|
||||
|
||||
if( m_listBox->GetCount() > 0 )
|
||||
m_listBox->SetSelection( 0 );
|
||||
}
|
||||
|
||||
|
||||
void FILTER_COMBOPOPUP::doStartingKey( wxKeyEvent& aEvent )
|
||||
{
|
||||
if( aEvent.GetKeyCode() == WXK_BACK )
|
||||
{
|
||||
const long pos = m_filterCtrl->GetLastPosition();
|
||||
m_filterCtrl->Remove( pos - 1, pos );
|
||||
}
|
||||
else
|
||||
{
|
||||
bool isPrintable;
|
||||
int ch = aEvent.GetUnicodeKey();
|
||||
|
||||
if( ch != WXK_NONE )
|
||||
isPrintable = true;
|
||||
else
|
||||
{
|
||||
ch = aEvent.GetKeyCode();
|
||||
isPrintable = ch > WXK_SPACE && ch < WXK_START;
|
||||
}
|
||||
|
||||
if( isPrintable )
|
||||
{
|
||||
wxString text( static_cast<wxChar>( ch ) );
|
||||
|
||||
// wxCHAR_HOOK chars have been converted to uppercase.
|
||||
if( !aEvent.ShiftDown() )
|
||||
text.MakeLower();
|
||||
|
||||
m_filterCtrl->AppendText( text );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FILTER_COMBOPOPUP::doSetFocus( wxWindow* aWindow )
|
||||
{
|
||||
#ifndef __WXGTK__ // Cannot focus in non-toplevel windows on GTK
|
||||
KIPLATFORM::UI::ForceFocus( aWindow );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
FILTER_COMBOBOX::FILTER_COMBOBOX( wxWindow *parent, wxWindowID id, const wxPoint &pos,
|
||||
const wxSize &size, long style ) :
|
||||
wxComboCtrl( parent, id, wxEmptyString, pos, size, style|wxCB_READONLY|wxTE_PROCESS_ENTER )
|
||||
{
|
||||
UseAltPopupWindow();
|
||||
Connect( wxEVT_CHAR_HOOK, wxKeyEventHandler( FILTER_COMBOBOX::onKeyDown ), nullptr, this );
|
||||
}
|
||||
|
||||
|
||||
FILTER_COMBOBOX::~FILTER_COMBOBOX()
|
||||
{
|
||||
Disconnect( wxEVT_CHAR_HOOK, wxKeyEventHandler( FILTER_COMBOBOX::onKeyDown ), nullptr, this );
|
||||
}
|
||||
|
||||
|
||||
void FILTER_COMBOBOX::setFilterPopup( std::unique_ptr<FILTER_COMBOPOPUP> aPopup )
|
||||
{
|
||||
m_filterPopup = aPopup.get();
|
||||
SetPopupControl( aPopup.release() );
|
||||
}
|
||||
|
||||
|
||||
void FILTER_COMBOBOX::onKeyDown( wxKeyEvent& aEvt )
|
||||
{
|
||||
int key = aEvt.GetKeyCode();
|
||||
|
||||
if( IsPopupShown() )
|
||||
{
|
||||
// If the popup is shown then it's CHAR_HOOK should be eating these before they
|
||||
// even get to us. But just to be safe, we go ahead and skip.
|
||||
aEvt.Skip();
|
||||
}
|
||||
|
||||
// Shift-return accepts dialog
|
||||
else if( ( key == WXK_RETURN || key == WXK_NUMPAD_ENTER ) && aEvt.ShiftDown() )
|
||||
{
|
||||
wxPostEvent( m_parent, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
|
||||
}
|
||||
|
||||
// Return, arrow-down and space-bar all open popup
|
||||
else if( key == WXK_RETURN || key == WXK_NUMPAD_ENTER || key == WXK_DOWN
|
||||
|| key == WXK_NUMPAD_DOWN || key == WXK_SPACE )
|
||||
{
|
||||
Popup();
|
||||
}
|
||||
|
||||
// Non-control characters go to filterbox in popup
|
||||
else if( key > WXK_SPACE && key < WXK_START )
|
||||
{
|
||||
Popup();
|
||||
m_filterPopup->OnStartingKey( aEvt );
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
aEvt.Skip();
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2018 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2018-2024 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
|
||||
@ -21,103 +21,27 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <string_utils.h>
|
||||
#include <kiplatform/ui.h>
|
||||
#include "widgets/net_selector.h"
|
||||
|
||||
#include <widgets/ui_common.h>
|
||||
#include <widgets/net_selector.h>
|
||||
#include <string_utils.h>
|
||||
|
||||
#include <board.h>
|
||||
#include <netinfo.h>
|
||||
#include <wx/arrstr.h>
|
||||
#include <wx/display.h>
|
||||
#include <wx/valtext.h>
|
||||
#include <wx/listbox.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/panel.h>
|
||||
|
||||
|
||||
wxDEFINE_EVENT( NET_SELECTED, wxCommandEvent );
|
||||
|
||||
#if defined( __WXOSX_MAC__ )
|
||||
#define POPUP_PADDING 2
|
||||
#define LIST_ITEM_PADDING 5
|
||||
#define LIST_PADDING 5
|
||||
#elif defined( __WXMSW__ )
|
||||
#define POPUP_PADDING 0
|
||||
#define LIST_ITEM_PADDING 2
|
||||
#define LIST_PADDING 5
|
||||
#else
|
||||
#define POPUP_PADDING 0
|
||||
#define LIST_ITEM_PADDING 6
|
||||
#define LIST_PADDING 5
|
||||
#endif
|
||||
|
||||
#define NO_NET _( "<no net>" )
|
||||
#define CREATE_NET _( "<create net>" )
|
||||
|
||||
|
||||
class NET_SELECTOR_COMBOPOPUP : public wxPanel, public wxComboPopup
|
||||
class NET_SELECTOR_COMBOPOPUP : public FILTER_COMBOPOPUP
|
||||
{
|
||||
public:
|
||||
NET_SELECTOR_COMBOPOPUP() :
|
||||
m_filterValidator( nullptr ),
|
||||
m_filterCtrl( nullptr ),
|
||||
m_listBox( nullptr ),
|
||||
m_minPopupWidth( -1 ),
|
||||
m_maxPopupHeight( 1000 ),
|
||||
m_netinfoList( nullptr ),
|
||||
m_board( nullptr ),
|
||||
m_selectedNetcode( 0 ),
|
||||
m_focusHandler( nullptr )
|
||||
m_selectedNetcode( 0 )
|
||||
{ }
|
||||
|
||||
bool Create(wxWindow* aParent) override
|
||||
{
|
||||
wxPanel::Create( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER );
|
||||
|
||||
wxBoxSizer* mainSizer;
|
||||
mainSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxStaticText* filterLabel = new wxStaticText( this, wxID_ANY, _( "Filter:" ) );
|
||||
mainSizer->Add( filterLabel, 0, wxEXPAND, 0 );
|
||||
|
||||
m_filterCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition,
|
||||
wxDefaultSize, wxTE_PROCESS_ENTER );
|
||||
m_filterValidator = new wxTextValidator( wxFILTER_EXCLUDE_CHAR_LIST );
|
||||
m_filterValidator->SetCharExcludes( " " );
|
||||
m_filterCtrl->SetValidator( *m_filterValidator );
|
||||
mainSizer->Add( m_filterCtrl, 0, wxEXPAND, 0 );
|
||||
|
||||
m_listBox = new wxListBox( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, nullptr,
|
||||
wxLB_SINGLE|wxLB_NEEDED_SB );
|
||||
mainSizer->Add( m_listBox, 0, wxEXPAND|wxTOP, 2 );
|
||||
|
||||
SetSizer( mainSizer );
|
||||
Layout();
|
||||
|
||||
Connect( wxEVT_IDLE, wxIdleEventHandler( NET_SELECTOR_COMBOPOPUP::onIdle ), nullptr, this );
|
||||
Connect( wxEVT_CHAR_HOOK, wxKeyEventHandler( NET_SELECTOR_COMBOPOPUP::onKeyDown ), nullptr, this );
|
||||
Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( NET_SELECTOR_COMBOPOPUP::onMouseClick ), nullptr, this );
|
||||
m_listBox->Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( NET_SELECTOR_COMBOPOPUP::onMouseClick ), nullptr, this );
|
||||
m_filterCtrl->Connect( wxEVT_TEXT, wxCommandEventHandler( NET_SELECTOR_COMBOPOPUP::onFilterEdit ), nullptr, this );
|
||||
m_filterCtrl->Connect( wxEVT_TEXT_ENTER, wxCommandEventHandler( NET_SELECTOR_COMBOPOPUP::onEnter ), nullptr, this );
|
||||
|
||||
// <enter> in a ListBox comes in as a double-click on GTK
|
||||
m_listBox->Connect( wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, wxCommandEventHandler( NET_SELECTOR_COMBOPOPUP::onEnter ), nullptr, this );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
wxWindow *GetControl() override { return this; }
|
||||
|
||||
void SetStringValue( const wxString& aNetName ) override
|
||||
{
|
||||
// shouldn't be here (combo is read-only)
|
||||
}
|
||||
|
||||
wxString GetStringValue() const override
|
||||
{
|
||||
if( m_selectedNetcode == -1 )
|
||||
@ -168,45 +92,11 @@ public:
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
wxSize GetAdjustedSize( int aMinWidth, int aPrefHeight, int aMaxHeight ) override
|
||||
void Accept() override
|
||||
{
|
||||
// Called when the popup is first shown. Stash the minWidth and maxHeight so we
|
||||
// can use them later when refreshing the sizes after filter changes.
|
||||
m_minPopupWidth = aMinWidth;
|
||||
m_maxPopupHeight = aMaxHeight;
|
||||
|
||||
return updateSize();
|
||||
}
|
||||
|
||||
void OnPopup() override
|
||||
{
|
||||
// While it can sometimes be useful to keep the filter, it's always unexpected.
|
||||
// Better to clear it.
|
||||
m_filterCtrl->Clear();
|
||||
|
||||
m_listBox->SetStringSelection( GetStringValue() );
|
||||
m_filterCtrl->SetFocus();
|
||||
|
||||
// The updateSize() call in GetAdjustedSize() leaves the height off-by-one for
|
||||
// some reason, so do it again.
|
||||
updateSize();
|
||||
}
|
||||
|
||||
void OnStartingKey( wxKeyEvent& aEvent )
|
||||
{
|
||||
doSetFocus( m_filterCtrl );
|
||||
doStartingKey( aEvent );
|
||||
}
|
||||
|
||||
void Accept()
|
||||
{
|
||||
wxString selectedNetName;
|
||||
wxString escapedNetName;
|
||||
wxString remainingName;
|
||||
int selection = m_listBox->GetSelection();
|
||||
|
||||
if( selection >= 0 )
|
||||
selectedNetName = m_listBox->GetString( (unsigned) selection );
|
||||
wxString selectedNetName = getSelectedValue().value_or( wxEmptyString );
|
||||
|
||||
auto it = m_unescapedNetNameMap.find( selectedNetName );
|
||||
|
||||
@ -274,44 +164,14 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
wxCommandEvent changeEvent( NET_SELECTED );
|
||||
wxCommandEvent changeEvent( FILTERED_ITEM_SELECTED );
|
||||
wxPostEvent( GetComboCtrl(), changeEvent );
|
||||
}
|
||||
|
||||
protected:
|
||||
wxSize updateSize()
|
||||
void getListContent( wxArrayString& aNetnames ) override
|
||||
{
|
||||
int listTop = m_listBox->GetRect().y;
|
||||
int itemHeight = KIUI::GetTextSize( wxT( "Xy" ), this ).y + LIST_ITEM_PADDING;
|
||||
int listHeight = m_listBox->GetCount() * itemHeight + LIST_PADDING;
|
||||
|
||||
if( listTop + listHeight >= m_maxPopupHeight )
|
||||
listHeight = m_maxPopupHeight - listTop - 1;
|
||||
|
||||
int listWidth = m_minPopupWidth;
|
||||
|
||||
for( size_t i = 0; i < m_listBox->GetCount(); ++i )
|
||||
{
|
||||
int itemWidth = KIUI::GetTextSize( m_listBox->GetString( i ), m_listBox ).x;
|
||||
listWidth = std::max( listWidth, itemWidth + LIST_PADDING * 3 );
|
||||
}
|
||||
|
||||
wxSize listSize( listWidth, listHeight );
|
||||
wxSize popupSize( listWidth, listTop + listHeight );
|
||||
|
||||
SetSize( popupSize ); // us
|
||||
GetParent()->SetSize( popupSize ); // the window that wxComboCtrl put us in
|
||||
|
||||
m_listBox->SetMinSize( listSize );
|
||||
m_listBox->SetSize( listSize );
|
||||
|
||||
return popupSize;
|
||||
}
|
||||
|
||||
void rebuildList()
|
||||
{
|
||||
wxArrayString netNames;
|
||||
wxString netstring = m_filterCtrl->GetValue().Trim().Trim( false );
|
||||
wxString netstring = getFilterValue();
|
||||
wxString filter = netstring.Lower();
|
||||
|
||||
m_unescapedNetNameMap.clear();
|
||||
@ -327,220 +187,32 @@ protected:
|
||||
|
||||
if( filter.IsEmpty() || wxString( netname ).MakeLower().Matches( filter ) )
|
||||
{
|
||||
netNames.push_back( netname );
|
||||
aNetnames.push_back( netname );
|
||||
m_unescapedNetNameMap[ netname ] = netinfo->GetNetname();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::sort( netNames.begin(), netNames.end(),
|
||||
std::sort( aNetnames.begin(), aNetnames.end(),
|
||||
[]( const wxString& lhs, const wxString& rhs )
|
||||
{
|
||||
return StrNumCmp( lhs, rhs, true /* ignore case */ ) < 0;
|
||||
} );
|
||||
|
||||
|
||||
// Special handling for <no net>
|
||||
if( filter.IsEmpty() || wxString( NO_NET ).MakeLower().Matches( filter ) )
|
||||
netNames.insert( netNames.begin(), NO_NET );
|
||||
aNetnames.insert( aNetnames.begin(), NO_NET );
|
||||
|
||||
if( !filter.IsEmpty() && !m_netinfoList->GetNetItem( netstring ) )
|
||||
{
|
||||
wxString newnet = wxString::Format( "%s: %s", CREATE_NET, netstring );
|
||||
netNames.insert( netNames.end(), newnet );
|
||||
aNetnames.insert( aNetnames.end(), newnet );
|
||||
}
|
||||
|
||||
if( !m_indeterminateLabel.IsEmpty() )
|
||||
netNames.push_back( m_indeterminateLabel );
|
||||
|
||||
m_listBox->Set( netNames );
|
||||
aNetnames.push_back( m_indeterminateLabel );
|
||||
}
|
||||
|
||||
void onIdle( wxIdleEvent& aEvent )
|
||||
{
|
||||
// Generate synthetic (but reliable) MouseMoved events
|
||||
static wxPoint lastPos;
|
||||
wxPoint screenPos = KIPLATFORM::UI::GetMousePosition();
|
||||
|
||||
if( screenPos != lastPos )
|
||||
{
|
||||
lastPos = screenPos;
|
||||
onMouseMoved( screenPos );
|
||||
}
|
||||
|
||||
if( m_focusHandler )
|
||||
{
|
||||
m_filterCtrl->PushEventHandler( m_focusHandler );
|
||||
m_focusHandler = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Hot-track the mouse (for focus and listbox selection)
|
||||
void onMouseMoved( const wxPoint aScreenPos )
|
||||
{
|
||||
if( m_listBox->GetScreenRect().Contains( aScreenPos ) )
|
||||
{
|
||||
doSetFocus( m_listBox );
|
||||
|
||||
wxPoint relativePos = m_listBox->ScreenToClient( aScreenPos );
|
||||
int item = m_listBox->HitTest( relativePos );
|
||||
|
||||
if( item >= 0 )
|
||||
m_listBox->SetSelection( item );
|
||||
}
|
||||
else if( m_filterCtrl->GetScreenRect().Contains( aScreenPos ) )
|
||||
{
|
||||
doSetFocus( m_filterCtrl );
|
||||
}
|
||||
}
|
||||
|
||||
void onMouseClick( wxMouseEvent& aEvent )
|
||||
{
|
||||
// Accept a click event from anywhere. Different platform implementations have
|
||||
// different foibles with regard to transient popups and their children.
|
||||
|
||||
if( aEvent.GetEventObject() == m_listBox )
|
||||
{
|
||||
m_listBox->SetSelection( m_listBox->HitTest( aEvent.GetPosition() ) );
|
||||
Accept();
|
||||
return;
|
||||
}
|
||||
|
||||
wxWindow* window = dynamic_cast<wxWindow*>( aEvent.GetEventObject() );
|
||||
|
||||
if( window )
|
||||
{
|
||||
wxPoint screenPos = window->ClientToScreen( aEvent.GetPosition() );
|
||||
|
||||
if( m_listBox->GetScreenRect().Contains( screenPos ) )
|
||||
{
|
||||
wxPoint localPos = m_listBox->ScreenToClient( screenPos );
|
||||
|
||||
m_listBox->SetSelection( m_listBox->HitTest( localPos ) );
|
||||
Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void onKeyDown( wxKeyEvent& aEvent )
|
||||
{
|
||||
switch( aEvent.GetKeyCode() )
|
||||
{
|
||||
// Control keys go to the parent combobox
|
||||
case WXK_TAB:
|
||||
Dismiss();
|
||||
|
||||
m_parent->NavigateIn( ( aEvent.ShiftDown() ? 0 : wxNavigationKeyEvent::IsForward ) |
|
||||
( aEvent.ControlDown() ? wxNavigationKeyEvent::WinChange : 0 ) );
|
||||
break;
|
||||
|
||||
case WXK_ESCAPE:
|
||||
Dismiss();
|
||||
break;
|
||||
|
||||
case WXK_RETURN:
|
||||
case WXK_NUMPAD_ENTER:
|
||||
Accept();
|
||||
break;
|
||||
|
||||
// Arrows go to the list box
|
||||
case WXK_DOWN:
|
||||
case WXK_NUMPAD_DOWN:
|
||||
doSetFocus( m_listBox );
|
||||
m_listBox->SetSelection( std::min( m_listBox->GetSelection() + 1, (int) m_listBox->GetCount() - 1 ) );
|
||||
break;
|
||||
|
||||
case WXK_UP:
|
||||
case WXK_NUMPAD_UP:
|
||||
doSetFocus( m_listBox );
|
||||
m_listBox->SetSelection( std::max( m_listBox->GetSelection() - 1, 0 ) );
|
||||
break;
|
||||
|
||||
// Everything else goes to the filter textbox
|
||||
default:
|
||||
if( !m_filterCtrl->HasFocus() )
|
||||
{
|
||||
doSetFocus( m_filterCtrl );
|
||||
|
||||
// Because we didn't have focus we missed our chance to have the native widget
|
||||
// handle the keystroke. We'll have to do the first character ourselves.
|
||||
doStartingKey( aEvent );
|
||||
}
|
||||
else
|
||||
{
|
||||
// On some platforms a wxComboFocusHandler will have been pushed which
|
||||
// unhelpfully gives the event right back to the popup. Make sure the filter
|
||||
// control is going to get the event.
|
||||
if( m_filterCtrl->GetEventHandler() != m_filterCtrl )
|
||||
m_focusHandler = m_filterCtrl->PopEventHandler();
|
||||
|
||||
aEvent.Skip();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void onEnter( wxCommandEvent& aEvent )
|
||||
{
|
||||
Accept();
|
||||
}
|
||||
|
||||
void onFilterEdit( wxCommandEvent& aEvent )
|
||||
{
|
||||
rebuildList();
|
||||
updateSize();
|
||||
|
||||
if( m_listBox->GetCount() > 0 )
|
||||
m_listBox->SetSelection( 0 );
|
||||
}
|
||||
|
||||
void doStartingKey( wxKeyEvent& aEvent )
|
||||
{
|
||||
if( aEvent.GetKeyCode() == WXK_BACK )
|
||||
{
|
||||
const long pos = m_filterCtrl->GetLastPosition();
|
||||
m_filterCtrl->Remove( pos - 1, pos );
|
||||
}
|
||||
else
|
||||
{
|
||||
bool isPrintable;
|
||||
int ch = aEvent.GetUnicodeKey();
|
||||
|
||||
if( ch != WXK_NONE )
|
||||
isPrintable = true;
|
||||
else
|
||||
{
|
||||
ch = aEvent.GetKeyCode();
|
||||
isPrintable = ch > WXK_SPACE && ch < WXK_START;
|
||||
}
|
||||
|
||||
if( isPrintable )
|
||||
{
|
||||
wxString text( static_cast<wxChar>( ch ) );
|
||||
|
||||
// wxCHAR_HOOK chars have been converted to uppercase.
|
||||
if( !aEvent.ShiftDown() )
|
||||
text.MakeLower();
|
||||
|
||||
m_filterCtrl->AppendText( text );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void doSetFocus( wxWindow* aWindow )
|
||||
{
|
||||
#ifndef __WXGTK__ // Cannot focus in non-toplevel windows on GTK
|
||||
KIPLATFORM::UI::ForceFocus( aWindow );
|
||||
#endif
|
||||
}
|
||||
|
||||
protected:
|
||||
wxTextValidator* m_filterValidator;
|
||||
wxTextCtrl* m_filterCtrl;
|
||||
wxListBox* m_listBox;
|
||||
int m_minPopupWidth;
|
||||
int m_maxPopupHeight;
|
||||
|
||||
const NETINFO_LIST* m_netinfoList;
|
||||
wxString m_indeterminateLabel;
|
||||
BOARD* m_board;
|
||||
@ -548,65 +220,16 @@ protected:
|
||||
int m_selectedNetcode;
|
||||
|
||||
std::map<wxString, wxString> m_unescapedNetNameMap;
|
||||
|
||||
wxEvtHandler* m_focusHandler;
|
||||
};
|
||||
|
||||
|
||||
NET_SELECTOR::NET_SELECTOR( wxWindow *parent, wxWindowID id, const wxPoint &pos,
|
||||
const wxSize &size, long style ) :
|
||||
wxComboCtrl( parent, id, wxEmptyString, pos, size, style|wxCB_READONLY|wxTE_PROCESS_ENTER )
|
||||
NET_SELECTOR::NET_SELECTOR( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
|
||||
long style ) :
|
||||
FILTER_COMBOBOX( parent, id, pos, size, style )
|
||||
{
|
||||
UseAltPopupWindow();
|
||||
|
||||
m_netSelectorPopup = new NET_SELECTOR_COMBOPOPUP();
|
||||
SetPopupControl( m_netSelectorPopup );
|
||||
|
||||
Connect( wxEVT_CHAR_HOOK, wxKeyEventHandler( NET_SELECTOR::onKeyDown ), nullptr, this );
|
||||
}
|
||||
|
||||
|
||||
NET_SELECTOR::~NET_SELECTOR()
|
||||
{
|
||||
Disconnect( wxEVT_CHAR_HOOK, wxKeyEventHandler( NET_SELECTOR::onKeyDown ), nullptr, this );
|
||||
}
|
||||
|
||||
|
||||
void NET_SELECTOR::onKeyDown( wxKeyEvent& aEvt )
|
||||
{
|
||||
int key = aEvt.GetKeyCode();
|
||||
|
||||
if( IsPopupShown() )
|
||||
{
|
||||
// If the popup is shown then it's CHAR_HOOK should be eating these before they
|
||||
// even get to us. But just to be safe, we go ahead and skip.
|
||||
aEvt.Skip();
|
||||
}
|
||||
|
||||
// Shift-return accepts dialog
|
||||
else if( ( key == WXK_RETURN || key == WXK_NUMPAD_ENTER ) && aEvt.ShiftDown() )
|
||||
{
|
||||
wxPostEvent( m_parent, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
|
||||
}
|
||||
|
||||
// Return, arrow-down and space-bar all open popup
|
||||
else if( key == WXK_RETURN || key == WXK_NUMPAD_ENTER || key == WXK_DOWN
|
||||
|| key == WXK_NUMPAD_DOWN || key == WXK_SPACE )
|
||||
{
|
||||
Popup();
|
||||
}
|
||||
|
||||
// Non-control characters go to filterbox in popup
|
||||
else if( key > WXK_SPACE && key < WXK_START )
|
||||
{
|
||||
Popup();
|
||||
m_netSelectorPopup->OnStartingKey( aEvt );
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
aEvt.Skip();
|
||||
}
|
||||
std::unique_ptr<NET_SELECTOR_COMBOPOPUP> popup = std::make_unique<NET_SELECTOR_COMBOPOPUP>();
|
||||
m_netSelectorPopup = popup.get();
|
||||
setFilterPopup( std::move( popup ) );
|
||||
}
|
||||
|
||||
|
||||
|
128
include/widgets/filter_combobox.h
Normal file
128
include/widgets/filter_combobox.h
Normal file
@ -0,0 +1,128 @@
|
||||
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#include <wx/panel.h>
|
||||
#include <wx/combo.h>
|
||||
#include <wx/listbox.h>
|
||||
|
||||
|
||||
class wxTextValidator;
|
||||
class wxTextCtrl;
|
||||
class wxListBox;
|
||||
|
||||
|
||||
class FILTER_COMBOPOPUP : public wxPanel, public wxComboPopup
|
||||
{
|
||||
public:
|
||||
FILTER_COMBOPOPUP();
|
||||
|
||||
bool Create( wxWindow* aParent ) override;
|
||||
|
||||
wxWindow* GetControl() override { return this; }
|
||||
|
||||
void SetStringValue( const wxString& aNetName ) override;
|
||||
|
||||
void OnPopup() override;
|
||||
|
||||
void OnStartingKey( wxKeyEvent& aEvent );
|
||||
|
||||
wxSize GetAdjustedSize( int aMinWidth, int aPrefHeight, int aMaxHeight ) override;
|
||||
|
||||
virtual void Accept() = 0;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Get the currently selected value in the list, or std::nullopt
|
||||
*/
|
||||
std::optional<wxString> getSelectedValue() const;
|
||||
|
||||
/**
|
||||
* Get the current value of the filter control. Can be empty.
|
||||
*/
|
||||
wxString getFilterValue() const;
|
||||
|
||||
/**
|
||||
* Call this to rebuild the list from the getListContent() method.
|
||||
*/
|
||||
void rebuildList();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Implement this to fill in the given list.
|
||||
*/
|
||||
virtual void getListContent( wxArrayString& aListToFill ) = 0;
|
||||
|
||||
wxSize updateSize();
|
||||
|
||||
void onIdle( wxIdleEvent& aEvent );
|
||||
|
||||
// Hot-track the mouse (for focus and listbox selection)
|
||||
void onMouseMoved( const wxPoint aScreenPos );
|
||||
void onMouseClick( wxMouseEvent& aEvent );
|
||||
void onKeyDown( wxKeyEvent& aEvent );
|
||||
void onEnter( wxCommandEvent& aEvent );
|
||||
void onFilterEdit( wxCommandEvent& aEvent );
|
||||
void doStartingKey( wxKeyEvent& aEvent );
|
||||
void doSetFocus( wxWindow* aWindow );
|
||||
|
||||
protected:
|
||||
wxTextValidator* m_filterValidator;
|
||||
wxTextCtrl* m_filterCtrl;
|
||||
wxListBox* m_listBox;
|
||||
int m_minPopupWidth;
|
||||
int m_maxPopupHeight;
|
||||
|
||||
wxEvtHandler* m_focusHandler;
|
||||
};
|
||||
|
||||
|
||||
wxDECLARE_EVENT( FILTERED_ITEM_SELECTED, wxCommandEvent );
|
||||
|
||||
/**
|
||||
* A combobox that has a filterable popup.
|
||||
*
|
||||
* Useful when the list of items is long and you want the user to
|
||||
* be able to filter it by typing.
|
||||
*/
|
||||
class FILTER_COMBOBOX : public wxComboCtrl
|
||||
{
|
||||
public:
|
||||
FILTER_COMBOBOX( wxWindow* parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition,
|
||||
const wxSize& size = wxDefaultSize, long style = 0 );
|
||||
|
||||
~FILTER_COMBOBOX();
|
||||
|
||||
protected:
|
||||
|
||||
void setFilterPopup( std::unique_ptr<FILTER_COMBOPOPUP> aPopup );
|
||||
|
||||
void onKeyDown( wxKeyEvent& aEvt );
|
||||
|
||||
FILTER_COMBOPOPUP* m_filterPopup;
|
||||
};
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2018 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2018-2024 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
|
||||
@ -21,10 +21,9 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef __WIDGET_NET_SELECTOR_H
|
||||
#define __WIDGET_NET_SELECTOR_H
|
||||
#pragma once
|
||||
|
||||
#include <wx/combo.h>
|
||||
#include <widgets/filter_combobox.h>
|
||||
|
||||
|
||||
class BOARD;
|
||||
@ -32,10 +31,7 @@ class NETINFO_LIST;
|
||||
class NET_SELECTOR_COMBOPOPUP;
|
||||
|
||||
|
||||
wxDECLARE_EVENT( NET_SELECTED, wxCommandEvent );
|
||||
|
||||
|
||||
class NET_SELECTOR : public wxComboCtrl
|
||||
class NET_SELECTOR : public FILTER_COMBOBOX
|
||||
{
|
||||
public:
|
||||
// Note: this list of arguments is here because it keeps us from having to customize
|
||||
@ -44,8 +40,6 @@ public:
|
||||
const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize,
|
||||
long style = 0 );
|
||||
|
||||
~NET_SELECTOR() override;
|
||||
|
||||
void SetNetInfo( const NETINFO_LIST* aNetInfoList );
|
||||
|
||||
// Set to wxEmptyString to disallow indeterminate settings
|
||||
@ -62,11 +56,8 @@ public:
|
||||
wxString GetSelectedNetname();
|
||||
|
||||
protected:
|
||||
void onKeyDown( wxKeyEvent& aEvt );
|
||||
|
||||
NET_SELECTOR_COMBOPOPUP* m_netSelectorPopup;
|
||||
wxString m_indeterminateString;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -60,7 +60,7 @@ DIALOG_CLEANUP_TRACKS_AND_VIAS::DIALOG_CLEANUP_TRACKS_AND_VIAS( PCB_EDIT_FRAME*
|
||||
|
||||
setupOKButtonLabel();
|
||||
|
||||
m_netFilter->Connect( NET_SELECTED,
|
||||
m_netFilter->Connect( FILTERED_ITEM_SELECTED,
|
||||
wxCommandEventHandler( DIALOG_CLEANUP_TRACKS_AND_VIAS::OnNetFilterSelect ),
|
||||
nullptr, this );
|
||||
|
||||
|
@ -175,7 +175,7 @@ DIALOG_GLOBAL_EDIT_TEARDROPS::DIALOG_GLOBAL_EDIT_TEARDROPS( PCB_EDIT_FRAME* aPar
|
||||
|
||||
SetupStandardButtons();
|
||||
|
||||
m_netFilter->Connect( NET_SELECTED,
|
||||
m_netFilter->Connect( FILTERED_ITEM_SELECTED,
|
||||
wxCommandEventHandler( DIALOG_GLOBAL_EDIT_TEARDROPS::OnNetFilterSelect ),
|
||||
nullptr, this );
|
||||
|
||||
@ -207,7 +207,7 @@ DIALOG_GLOBAL_EDIT_TEARDROPS::~DIALOG_GLOBAL_EDIT_TEARDROPS()
|
||||
else
|
||||
g_action = ADD_TEARDROPS_DEFAULT;
|
||||
|
||||
m_netFilter->Disconnect( NET_SELECTED,
|
||||
m_netFilter->Disconnect( FILTERED_ITEM_SELECTED,
|
||||
wxCommandEventHandler( DIALOG_GLOBAL_EDIT_TEARDROPS::OnNetFilterSelect ),
|
||||
nullptr, this );
|
||||
}
|
||||
|
@ -149,7 +149,7 @@ DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS( PCB_EDIT
|
||||
|
||||
SetupStandardButtons();
|
||||
|
||||
m_netFilter->Connect( NET_SELECTED,
|
||||
m_netFilter->Connect( FILTERED_ITEM_SELECTED,
|
||||
wxCommandEventHandler( DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::OnNetFilterSelect ),
|
||||
nullptr, this );
|
||||
|
||||
@ -176,7 +176,7 @@ DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::~DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS()
|
||||
g_viaSizeFilter = m_viaSizeFilter.GetIntValue();
|
||||
g_filterSelected = m_selectedItemsFilter->GetValue();
|
||||
|
||||
m_netFilter->Disconnect( NET_SELECTED,
|
||||
m_netFilter->Disconnect( FILTERED_ITEM_SELECTED,
|
||||
wxCommandEventHandler( DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::OnNetFilterSelect ),
|
||||
nullptr, this );
|
||||
|
||||
|
@ -294,7 +294,7 @@ DIALOG_PAD_PROPERTIES::DIALOG_PAD_PROPERTIES( PCB_BASE_FRAME* aParent, PAD* aPad
|
||||
SetupStandardButtons();
|
||||
m_initialized = true;
|
||||
|
||||
m_padNetSelector->Connect( NET_SELECTED,
|
||||
m_padNetSelector->Connect( FILTERED_ITEM_SELECTED,
|
||||
wxCommandEventHandler( DIALOG_PAD_PROPERTIES::OnValuesChanged ),
|
||||
nullptr, this );
|
||||
|
||||
@ -319,7 +319,7 @@ DIALOG_PAD_PROPERTIES::DIALOG_PAD_PROPERTIES( PCB_BASE_FRAME* aParent, PAD* aPad
|
||||
|
||||
DIALOG_PAD_PROPERTIES::~DIALOG_PAD_PROPERTIES()
|
||||
{
|
||||
m_padNetSelector->Disconnect( NET_SELECTED,
|
||||
m_padNetSelector->Disconnect( FILTERED_ITEM_SELECTED,
|
||||
wxCommandEventHandler( DIALOG_PAD_PROPERTIES::OnValuesChanged ),
|
||||
nullptr, this );
|
||||
|
||||
|
@ -476,7 +476,7 @@ DIALOG_TRACK_VIA_PROPERTIES::DIALOG_TRACK_VIA_PROPERTIES( PCB_BASE_FRAME* aParen
|
||||
SetupStandardButtons();
|
||||
|
||||
m_frame->Bind( EDA_EVT_UNITS_CHANGED, &DIALOG_TRACK_VIA_PROPERTIES::onUnitsChanged, this );
|
||||
m_netSelector->Bind( NET_SELECTED, &DIALOG_TRACK_VIA_PROPERTIES::onNetSelector, this );
|
||||
m_netSelector->Bind( FILTERED_ITEM_SELECTED, &DIALOG_TRACK_VIA_PROPERTIES::onNetSelector, this );
|
||||
|
||||
// Now all widgets have the size fixed, call FinishDialogSettings
|
||||
finishDialogSettings();
|
||||
|
Loading…
Reference in New Issue
Block a user