mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2024-11-22 00:15:01 +00:00
8abbae9dc2
Implemented as a "TRICKS" class that could wrap any wxListBox with similar effects.
311 lines
9.1 KiB
C++
311 lines
9.1 KiB
C++
/*
|
|
* 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/listbox_tricks.h"
|
|
|
|
#include <wx/clipbrd.h>
|
|
#include <wx/listbox.h>
|
|
#include <wx/menu.h>
|
|
#include <wx/window.h>
|
|
|
|
#include <bitmaps.h>
|
|
#include <bitmaps/bitmaps_list.h>
|
|
#include <widgets/ui_common.h>
|
|
|
|
|
|
wxDEFINE_EVENT( EDA_EVT_LISTBOX_COPY, wxCommandEvent );
|
|
wxDEFINE_EVENT( EDA_EVT_LISTBOX_CUT, wxCommandEvent );
|
|
wxDEFINE_EVENT( EDA_EVT_LISTBOX_PASTE, wxCommandEvent );
|
|
wxDEFINE_EVENT( EDA_EVT_LISTBOX_DELETE, wxCommandEvent );
|
|
wxDEFINE_EVENT( EDA_EVT_LISTBOX_DUPLICATE, wxCommandEvent );
|
|
|
|
wxDEFINE_EVENT( EDA_EVT_LISTBOX_CHANGED, wxCommandEvent );
|
|
|
|
|
|
LISTBOX_TRICKS::LISTBOX_TRICKS( wxWindow& aParent, wxListBox& aListBox ) :
|
|
m_parent( aParent ), m_listBox( aListBox )
|
|
{
|
|
// Init default menu labels
|
|
m_menuStrings = { {
|
|
{ ID_COPY, _( "Copy" ) },
|
|
{ ID_PASTE, _( "Paste" ) },
|
|
{ ID_CUT, _( "Cut" ) },
|
|
{ ID_DUPLICATE, _( "Duplicate" ) },
|
|
{ ID_DELETE, _( "Delete" ) },
|
|
} };
|
|
|
|
|
|
m_listBox.Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( LISTBOX_TRICKS::OnListBoxRDown ),
|
|
nullptr, this );
|
|
m_listBox.Connect( wxEVT_KEY_DOWN, wxKeyEventHandler( LISTBOX_TRICKS::OnListBoxKeyDown ),
|
|
nullptr, this );
|
|
|
|
Connect( EDA_EVT_LISTBOX_DELETE, wxCommandEventHandler( LISTBOX_TRICKS::OnListBoxDelete ) );
|
|
Connect( EDA_EVT_LISTBOX_COPY, wxCommandEventHandler( LISTBOX_TRICKS::OnListBoxCopy ) );
|
|
Connect( EDA_EVT_LISTBOX_CUT, wxCommandEventHandler( LISTBOX_TRICKS::OnListBoxCut ) );
|
|
Connect( EDA_EVT_LISTBOX_PASTE, wxCommandEventHandler( LISTBOX_TRICKS::OnListBoxPaste ) );
|
|
Connect( EDA_EVT_LISTBOX_DUPLICATE, wxCommandEventHandler( LISTBOX_TRICKS::OnListBoxDuplicate ) );
|
|
}
|
|
|
|
|
|
LISTBOX_TRICKS::~LISTBOX_TRICKS()
|
|
{
|
|
m_listBox.Disconnect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( LISTBOX_TRICKS::OnListBoxRDown ),
|
|
nullptr, this );
|
|
m_listBox.Disconnect( wxEVT_KEY_DOWN, wxKeyEventHandler( LISTBOX_TRICKS::OnListBoxKeyDown ),
|
|
nullptr, this );
|
|
|
|
Disconnect( EDA_EVT_LISTBOX_DELETE, wxCommandEventHandler( LISTBOX_TRICKS::OnListBoxDelete ) );
|
|
Disconnect( EDA_EVT_LISTBOX_COPY, wxCommandEventHandler( LISTBOX_TRICKS::OnListBoxCopy ) );
|
|
Disconnect( EDA_EVT_LISTBOX_CUT, wxCommandEventHandler( LISTBOX_TRICKS::OnListBoxCut ) );
|
|
Disconnect( EDA_EVT_LISTBOX_PASTE, wxCommandEventHandler( LISTBOX_TRICKS::OnListBoxPaste ) );
|
|
Disconnect( EDA_EVT_LISTBOX_DUPLICATE, wxCommandEventHandler( LISTBOX_TRICKS::OnListBoxDuplicate ) );
|
|
}
|
|
|
|
|
|
void LISTBOX_TRICKS::SetMenuLabels( const std::map<MENU_ID, wxString>& aItems )
|
|
{
|
|
for( const auto& [id, string] : aItems )
|
|
{
|
|
m_menuStrings[id] = string;
|
|
}
|
|
}
|
|
|
|
|
|
wxArrayInt LISTBOX_TRICKS::listBoxDeleteSelected()
|
|
{
|
|
wxArrayInt selections;
|
|
m_listBox.GetSelections( selections );
|
|
|
|
std::sort( selections.begin(), selections.end() );
|
|
|
|
for( int ii = selections.GetCount() - 1; ii >= 0; ii-- )
|
|
m_listBox.Delete( selections[ii] );
|
|
|
|
m_listBox.SetSelection( wxNOT_FOUND );
|
|
if( m_listBox.GetCount() > 0 )
|
|
m_listBox.SetSelection( std::max( 0, selections[0] - 1 ) );
|
|
|
|
wxPostEvent( &m_listBox, wxCommandEvent( EDA_EVT_LISTBOX_CHANGED ) );
|
|
return selections;
|
|
}
|
|
|
|
|
|
wxArrayString LISTBOX_TRICKS::listBoxGetSelected() const
|
|
{
|
|
wxArrayInt selections;
|
|
m_listBox.GetSelections( selections );
|
|
|
|
wxArrayString result;
|
|
for( size_t ii = 0; ii < selections.GetCount(); ii++ )
|
|
result.Add( m_listBox.GetString( selections[ii] ) );
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
void LISTBOX_TRICKS::listBoxDuplicateSelected()
|
|
{
|
|
wxArrayInt selections;
|
|
m_listBox.GetSelections( selections );
|
|
|
|
int insertAt = selections.GetCount() > 0 ? selections.back() + 1 : m_listBox.GetCount();
|
|
|
|
m_listBox.SetSelection( wxNOT_FOUND );
|
|
|
|
for( size_t ii = 0; ii < selections.GetCount(); ii++ )
|
|
{
|
|
wxString filter = m_listBox.GetString( selections[ii] );
|
|
m_listBox.Insert( filter, insertAt );
|
|
m_listBox.SetSelection( insertAt );
|
|
insertAt++;
|
|
}
|
|
|
|
wxPostEvent( &m_listBox, wxCommandEvent( EDA_EVT_LISTBOX_CHANGED ) );
|
|
}
|
|
|
|
|
|
void LISTBOX_TRICKS::listBoxCopy()
|
|
{
|
|
wxArrayString filters = listBoxGetSelected();
|
|
|
|
wxString result;
|
|
for( const wxString& filter : filters )
|
|
{
|
|
result += filter + wxT( "\n" );
|
|
}
|
|
|
|
if( wxTheClipboard->Open() )
|
|
{
|
|
wxTheClipboard->SetData( new wxTextDataObject( result ) );
|
|
wxTheClipboard->Close();
|
|
}
|
|
}
|
|
|
|
|
|
void LISTBOX_TRICKS::listBoxPaste()
|
|
{
|
|
wxArrayString lines;
|
|
if( wxTheClipboard->Open() )
|
|
{
|
|
wxTextDataObject data;
|
|
wxTheClipboard->GetData( data );
|
|
|
|
wxString text = data.GetText();
|
|
text.Trim( false );
|
|
text.Trim( true );
|
|
lines = wxSplit( text, '\n' );
|
|
|
|
wxTheClipboard->Close();
|
|
}
|
|
|
|
wxArrayInt selections;
|
|
m_listBox.GetSelections( selections );
|
|
int insertAt = selections.GetCount() > 0 ? selections.back() + 1 : m_listBox.GetCount();
|
|
|
|
for( wxString& line : lines )
|
|
{
|
|
line.Trim( false );
|
|
line.Trim( true );
|
|
}
|
|
|
|
m_listBox.InsertItems( lines, insertAt );
|
|
|
|
m_listBox.SetSelection( wxNOT_FOUND );
|
|
for( size_t ii = insertAt; ii < insertAt + lines.GetCount(); ii++ )
|
|
m_listBox.SetSelection( ii );
|
|
|
|
wxPostEvent( &m_listBox, wxCommandEvent( EDA_EVT_LISTBOX_CHANGED ) );
|
|
}
|
|
|
|
|
|
void LISTBOX_TRICKS::listBoxCut()
|
|
{
|
|
listBoxCopy();
|
|
wxArrayInt deleted = listBoxDeleteSelected();
|
|
|
|
size_t select = deleted.GetCount() > 0 ? deleted[0] : m_listBox.GetCount();
|
|
|
|
m_listBox.SetSelection( wxNOT_FOUND );
|
|
m_listBox.SetSelection( std::min( select, (size_t) m_listBox.GetCount() - 1 ) );
|
|
}
|
|
|
|
|
|
void LISTBOX_TRICKS::OnListBoxRDown( wxMouseEvent& aEvent )
|
|
{
|
|
wxMenu menu;
|
|
|
|
const auto mstr = [&]( const MENU_ID& id )
|
|
{
|
|
return m_menuStrings[id];
|
|
};
|
|
|
|
// clang-format off
|
|
KIUI::AddMenuItem( &menu, ID_COPY,
|
|
mstr( ID_COPY ) + "\tCtrl+C",
|
|
KiBitmap( BITMAPS::copy ) );
|
|
KIUI::AddMenuItem( &menu, ID_CUT,
|
|
mstr( ID_CUT ) + "\tCtrl+X",
|
|
KiBitmap( BITMAPS::cut ) );
|
|
KIUI::AddMenuItem( &menu, ID_PASTE,
|
|
mstr( ID_PASTE ) + "\tCtrl+V",
|
|
KiBitmap( BITMAPS::paste ) );
|
|
KIUI::AddMenuItem( &menu, ID_DUPLICATE,
|
|
mstr( ID_DUPLICATE ) + "\tCtrl+D",
|
|
KiBitmap( BITMAPS::duplicate ) );
|
|
KIUI::AddMenuItem( &menu, ID_DELETE,
|
|
mstr( ID_DELETE ) + "\tDel",
|
|
KiBitmap( BITMAPS::trash ) );
|
|
// clang-format on
|
|
|
|
menu.Bind( wxEVT_COMMAND_MENU_SELECTED,
|
|
[&]( wxCommandEvent& aCmd )
|
|
{
|
|
switch( aEvent.GetId() )
|
|
{
|
|
case ID_COPY: listBoxCopy(); break;
|
|
case ID_PASTE: listBoxPaste(); break;
|
|
case ID_CUT: listBoxCut(); break;
|
|
case ID_DELETE: listBoxDeleteSelected(); break;
|
|
case ID_DUPLICATE: listBoxDuplicateSelected(); break;
|
|
default: aEvent.Skip();
|
|
}
|
|
} );
|
|
|
|
m_parent.PopupMenu( &menu );
|
|
}
|
|
|
|
|
|
void LISTBOX_TRICKS::OnListBoxKeyDown( wxKeyEvent& aEvent )
|
|
{
|
|
if( aEvent.GetKeyCode() == WXK_DELETE )
|
|
{
|
|
listBoxDeleteSelected();
|
|
}
|
|
else
|
|
{
|
|
if( aEvent.ControlDown() )
|
|
{
|
|
switch( aEvent.GetKeyCode() )
|
|
{
|
|
case 'C': listBoxCopy(); break;
|
|
case 'V': listBoxPaste(); break;
|
|
case 'X': listBoxCut(); break;
|
|
case 'D': listBoxDuplicateSelected(); break;
|
|
default: aEvent.Skip();
|
|
}
|
|
}
|
|
else
|
|
aEvent.Skip();
|
|
}
|
|
}
|
|
|
|
|
|
void LISTBOX_TRICKS::OnListBoxDelete( wxCommandEvent& aEvent )
|
|
{
|
|
listBoxDeleteSelected();
|
|
}
|
|
|
|
|
|
void LISTBOX_TRICKS::OnListBoxCopy( wxCommandEvent& aEvent )
|
|
{
|
|
listBoxCopy();
|
|
}
|
|
|
|
|
|
void LISTBOX_TRICKS::OnListBoxCut( wxCommandEvent& aEvent )
|
|
{
|
|
listBoxCut();
|
|
}
|
|
|
|
|
|
void LISTBOX_TRICKS::OnListBoxPaste( wxCommandEvent& aEvent )
|
|
{
|
|
listBoxPaste();
|
|
}
|
|
|
|
|
|
void LISTBOX_TRICKS::OnListBoxDuplicate( wxCommandEvent& aEvent )
|
|
{
|
|
listBoxDuplicateSelected();
|
|
} |