KiCad PCB EDA Suite
Loading...
Searching...
No Matches
search_pane_tab.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
21#include <widgets/search_pane.h>
22#include <vector>
23#include <string_utils.h>
24#include <wx/clipbrd.h>
25#include <wx/menu.h>
26#include <wx/wupdlock.h>
27#include <core/kicad_algo.h>
28
29SEARCH_PANE_LISTVIEW::SEARCH_PANE_LISTVIEW( const std::shared_ptr<SEARCH_HANDLER>& aHandler, wxWindow* parent,
30 wxWindowID winid, const wxPoint& pos, const wxSize& size ) :
31 wxListView( parent, winid, pos, size, wxLC_REPORT | wxLC_VIRTUAL ),
32 m_handler( aHandler ),
33 m_sortCol( -1 ),
34 m_sortAscending( true ),
35 m_selectionDirty( false )
36{
37 SetItemCount( 0 );
38
40
41 Bind( wxEVT_LIST_ITEM_SELECTED, &SEARCH_PANE_LISTVIEW::OnItemSelected, this );
42 Bind( wxEVT_LIST_ITEM_ACTIVATED, &SEARCH_PANE_LISTVIEW::OnItemActivated, this );
43 Bind( wxEVT_LIST_ITEM_FOCUSED, &SEARCH_PANE_LISTVIEW::OnItemSelected, this );
44 Bind( wxEVT_LIST_ITEM_DESELECTED, &SEARCH_PANE_LISTVIEW::OnItemDeselected, this );
45 Bind( wxEVT_LIST_COL_CLICK, &SEARCH_PANE_LISTVIEW::OnColClicked, this );
46 Bind( wxEVT_UPDATE_UI, &SEARCH_PANE_LISTVIEW::OnUpdateUI, this );
47 Bind( wxEVT_CHAR, &SEARCH_PANE_LISTVIEW::OnChar, this );
48 Bind( wxEVT_CONTEXT_MENU, &SEARCH_PANE_LISTVIEW::OnContextMenu, this );
49 Bind( wxEVT_MENU, &SEARCH_PANE_LISTVIEW::OnCopyMenu, this, wxID_COPY );
50}
51
52
54{
55 Unbind( wxEVT_LIST_ITEM_SELECTED, &SEARCH_PANE_LISTVIEW::OnItemSelected, this );
56 Unbind( wxEVT_LIST_ITEM_ACTIVATED, &SEARCH_PANE_LISTVIEW::OnItemActivated, this );
57 Unbind( wxEVT_LIST_ITEM_FOCUSED, &SEARCH_PANE_LISTVIEW::OnItemSelected, this );
58 Unbind( wxEVT_LIST_ITEM_DESELECTED, &SEARCH_PANE_LISTVIEW::OnItemDeselected, this );
59 Unbind( wxEVT_LIST_COL_CLICK, &SEARCH_PANE_LISTVIEW::OnColClicked, this );
60 Unbind( wxEVT_UPDATE_UI, &SEARCH_PANE_LISTVIEW::OnUpdateUI, this );
61 Unbind( wxEVT_CHAR, &SEARCH_PANE_LISTVIEW::OnChar, this );
62 Unbind( wxEVT_CONTEXT_MENU, &SEARCH_PANE_LISTVIEW::OnContextMenu, this );
63 Unbind( wxEVT_MENU, &SEARCH_PANE_LISTVIEW::OnCopyMenu, this, wxID_COPY );
64}
65
66
67void SEARCH_PANE_LISTVIEW::GetSelectRowsList( std::vector<long>& aSelectedList )
68{
69 long idx = GetFirstSelected();
70
71 if( idx < 0 ) // Nothing selected
72 return;
73
74 aSelectedList.emplace_back( idx );
75
76 idx = GetNextSelected( idx );
77
78 while( idx >= 0 )
79 {
80 aSelectedList.emplace_back( idx );
81 idx = GetNextSelected( idx );
82 }
83}
84
85
86void SEARCH_PANE_LISTVIEW::OnItemActivated( wxListEvent& aEvent )
87{
88 long item = aEvent.GetIndex();
89
90 CallAfter(
91 [this, item]()
92 {
93 m_handler->ActivateItem( item );
94 } );
95
96 m_selectionDirty = true;
97 aEvent.Skip();
98}
99
100
101void SEARCH_PANE_LISTVIEW::OnItemSelected( wxListEvent& aEvent )
102{
103 m_selectionDirty = true;
104 aEvent.Skip();
105}
106
107
108void SEARCH_PANE_LISTVIEW::OnItemDeselected( wxListEvent& aEvent )
109{
110 m_selectionDirty = true;
111 aEvent.Skip();
112}
113
114
115void SEARCH_PANE_LISTVIEW::OnUpdateUI( wxUpdateUIEvent& aEvent )
116{
117 if( m_selectionDirty )
118 {
119 m_selectionDirty = false;
120
121 std::vector<long> list;
122 GetSelectRowsList( list );
123 m_handler->SelectItems( list );
124 }
125}
126
127
128void SEARCH_PANE_LISTVIEW::OnColClicked( wxListEvent& aEvent )
129{
130 if( aEvent.GetColumn() == m_sortCol )
131 {
133 }
134 else
135 {
136 m_sortAscending = true;
137 m_sortCol = aEvent.GetColumn();
138 }
139
140 ShowSortIndicator( m_sortCol, m_sortAscending );
141
142 std::vector<long> selection = Sort();
143
144 for( long row = 0; row < GetItemCount(); row++ )
145 {
146 if( alg::contains( selection, row ) )
147 SetItemState( row, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED );
148 else
149 SetItemState( row, 0, wxLIST_STATE_SELECTED );
150 }
151
152 Refresh();
153}
154
155
156void SEARCH_PANE_LISTVIEW::OnChar( wxKeyEvent& aEvent )
157{
158 bool handled = false;
159
160 switch( aEvent.GetKeyCode() )
161 {
162 case WXK_CONTROL_A:
163 {
164 // Select All
165 for( int row = 0; row < GetItemCount(); row++ )
166 SetItemState( row, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED );
167
168 handled = true;
169 break;
170 }
171
172 case WXK_CONTROL_C:
173 {
175
176 handled = true;
177 break;
178 }
179
180 case WXK_DOWN:
181 case WXK_NUMPAD_DOWN:
182 {
183 // Move selection down
184 long focused = GetFocusedItem();
185 if( focused < 0 )
186 focused = 0;
187
188 if( focused < GetItemCount() - 1 )
189 {
190 if( !(aEvent.GetModifiers() & wxMOD_SHIFT) )
191 {
192 int next = -1;
193
194 while( ( next = GetNextSelected( next ) ) != wxNOT_FOUND )
195 Select( next, false );
196 }
197
198 ++focused;
199 Focus( focused );
200 Select( focused );
201 }
202
203 handled = true;
204 break;
205 }
206 case WXK_UP:
207 case WXK_NUMPAD_UP:
208 {
209 // Move selection up
210 long focused = GetFocusedItem();
211
212 if( focused < 0 )
213 focused = 0;
214
215 if( focused > 0 )
216 {
217 if( !(aEvent.GetModifiers() & wxMOD_SHIFT) )
218 {
219 int next = -1;
220
221 while( ( next = GetNextSelected( next ) ) != wxNOT_FOUND )
222 Select( next, false );
223 }
224
225 --focused;
226 Focus( focused );
227 Select( focused );
228 }
229
230 handled = true;
231 break;
232 }
233 }
234
235 if( !handled )
236 aEvent.Skip();
237}
238
239
240void SEARCH_PANE_LISTVIEW::OnContextMenu( wxContextMenuEvent& aEvent )
241{
242 wxMenu menu;
243 menu.Append( wxID_COPY, _( "Copy" ) );
244 PopupMenu( &menu );
245}
246
247
248void SEARCH_PANE_LISTVIEW::OnCopyMenu( wxCommandEvent& aEvent )
249{
251}
252
253
255{
256 if( !wxTheClipboard->Open() )
257 return;
258
259 wxString txt;
260
261 for( int row = 0; row < GetItemCount(); row++ )
262 {
263 if( GetItemState( row, wxLIST_STATE_SELECTED ) != wxLIST_STATE_SELECTED )
264 continue;
265
266 bool firstCol = true;
267
268 for( int col = 0; col < GetColumnCount(); col++ )
269 {
270 if( GetColumnWidth( col ) <= 0 )
271 continue;
272
273 if( !firstCol )
274 txt += wxT( "\t" );
275
276 txt += GetItemText( row, col );
277 firstCol = false;
278 }
279
280 txt += wxT( "\n" );
281 }
282
283 wxTheClipboard->SetData( new wxTextDataObject( txt ) );
284 wxTheClipboard->Close();
285}
286
287
288std::vector<long> SEARCH_PANE_LISTVIEW::Sort()
289{
290 std::vector<long> selection;
291 GetSelectRowsList( selection );
292
293 m_handler->Sort( m_sortCol, m_sortAscending, &selection );
294
295 return selection;
296}
297
298
300{
301 wxWindowUpdateLocker updateLock( this );
302
303 DeleteAllColumns();
304
305 std::vector<std::tuple<wxString, int, wxListColumnFormat>> columns = m_handler->GetColumns();
306
307 for( auto& [ columnName, colProportion, colAlign ] : columns )
308 AppendColumn( wxGetTranslation( columnName ), colAlign );
309
310 int widthUnit = GetClientSize().GetWidth() / 10;
311
312 for( int ii = 0; ii < (int) columns.size(); ++ii )
313 SetColumnWidth( ii, widthUnit * std::get<1>( columns[ ii ] ) );
314}
315
316
317wxString SEARCH_PANE_LISTVIEW::OnGetItemText( long item, long column ) const
318{
319 return m_handler->GetResultCell( (int) item, (int) column );
320}
321
322
323SEARCH_PANE_TAB::SEARCH_PANE_TAB( const std::shared_ptr<SEARCH_HANDLER>& aHandler, wxWindow* parent, wxWindowID aId,
324 const wxPoint& aLocation, const wxSize& aSize ) :
325 wxPanel( parent, aId, aLocation, aSize ),
326 m_handler( aHandler )
327{
328 wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
329
330 m_listView = new SEARCH_PANE_LISTVIEW( aHandler, this );
331 sizer->Add( m_listView, 5, wxRIGHT | wxBOTTOM | wxEXPAND, 1 );
332
333 SetSizer( sizer );
334
335 Layout();
336 sizer->Fit( this );
337}
338
339
340void SEARCH_PANE_TAB::Search( wxString& query )
341{
342 int results = m_handler->Search( query );
343 m_listView->SetItemCount( results );
344 m_listView->Sort();
345 m_listView->Refresh();
346}
347
348
350{
351 m_listView->SetItemCount( 0 );
352 m_listView->Refresh();
353}
354
355
357{
358 m_listView->RefreshColumnNames();
359}
void OnItemDeselected(wxListEvent &aEvent)
void GetSelectRowsList(std::vector< long > &aSelectedList)
void OnColClicked(wxListEvent &aEvent)
void OnChar(wxKeyEvent &aEvent)
SEARCH_PANE_LISTVIEW(const std::shared_ptr< SEARCH_HANDLER > &aHandler, wxWindow *parent, wxWindowID winid=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize)
void OnCopyMenu(wxCommandEvent &aEvent)
void OnContextMenu(wxContextMenuEvent &aEvent)
std::shared_ptr< SEARCH_HANDLER > m_handler
void OnItemSelected(wxListEvent &aEvent)
void OnItemActivated(wxListEvent &aEvent)
std::vector< long > Sort()
void OnUpdateUI(wxUpdateUIEvent &aEvent)
wxString OnGetItemText(long item, long column) const override
std::shared_ptr< SEARCH_HANDLER > m_handler
void Search(wxString &query)
SEARCH_PANE_TAB(const std::shared_ptr< SEARCH_HANDLER > &aHandler, wxWindow *parent, wxWindowID aId=wxID_ANY, const wxPoint &aLocation=wxDefaultPosition, const wxSize &aSize=wxDefaultSize)
SEARCH_PANE_LISTVIEW * m_listView
#define _(s)
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition kicad_algo.h:100
void Refresh()
Update the board display after modifying it by a python script (note: it is automatically called by a...
CITER next(CITER it)
Definition ptree.cpp:124