KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_generators.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 (C) 2023 Alex Shvartzkop <[email protected]>
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25#include "dialog_generators.h"
26
27#include <pcb_edit_frame.h>
28#include <board.h>
29#include <pcb_generator.h>
30#include <tool/tool_manager.h>
31#include <tools/pcb_actions.h>
33
34
36{
37 for( auto& [name, ptr] : m_dataModels )
38 {
39 if( ptr )
40 ptr->DecRef();
41 }
42
43 m_dataModels.clear();
44 m_columnNameTypes.clear();
45 m_dataViews.clear();
46}
47
48
49void DIALOG_GENERATORS::clearModel( const wxString& aName )
50{
51 if( m_dataModels[aName] )
52 {
53 m_dataModels[aName]->DeleteAllItems();
54 m_dataModels[aName]->ClearColumns();
55 }
56
57 m_columnNameTypes[aName].clear();
58}
59
60
61void DIALOG_GENERATORS::deleteModel( const wxString& aName )
62{
63 if( m_dataModels[aName] )
64 m_dataModels[aName]->DecRef();
65
66 for( size_t i = 0; i < m_Notebook->GetPageCount(); i++ )
67 {
68 wxWindow* page = m_Notebook->GetPage( i );
69 if( page->GetName() == aName )
70 {
71 m_Notebook->DeletePage( i );
72 break;
73 }
74 }
75
76 m_dataViews.erase( aName );
77 m_dataModels.erase( aName );
78 m_columnNameTypes.erase( aName );
79}
80
81
83{
84 wxString lastPageName;
85 std::set<wxString> lastUUIDs;
86
87 if( auto page = m_Notebook->GetCurrentPage() )
88 {
89 lastPageName = page->GetName();
90 wxDataViewCtrl* dataView = m_dataViews[lastPageName];
91
92 int uuidCol = dataView->GetColumnCount() - 1;
93
94 wxDataViewItemArray selections;
95 dataView->GetSelections( selections );
96
97 for( wxDataViewItem& item : selections )
98 {
99 wxVariant var;
100 dataView->GetModel()->GetValue( var, item, uuidCol );
101 lastUUIDs.emplace( var.GetString() );
102 }
103 }
104
105 int newPageId = -1;
106
107 std::map<wxString, std::map<KIID, std::vector<std::pair<wxString, wxVariant>>>> dataMap;
108
109 for( PCB_GENERATOR* gen : m_currentBoard->Generators() )
110 {
111 std::vector<std::pair<wxString, wxVariant>> rowData = gen->GetRowData();
112
113 const KIID uuid = gen->m_Uuid;
114 rowData.emplace_back( wxS( "UUID" ), uuid.AsString() );
115
116 dataMap[gen->GetName()][uuid] = rowData;
117 }
118
119 std::vector<wxString> toDelete;
120 for( size_t i = 0; i < m_Notebook->GetPageCount(); i++ )
121 {
122 wxWindow* page = m_Notebook->GetPage( i );
123
124 if( dataMap.find(page->GetName()) == dataMap.end() )
125 {
126 toDelete.emplace_back( page->GetName() );
127 }
128 }
129
130 for( const wxString& name : toDelete )
131 deleteModel( name );
132
133 for( auto& [typeName, uuidToRowMap] : dataMap )
134 {
135 bool exists = false;
136 for( size_t i = 0; i < m_Notebook->GetPageCount(); i++ )
137 {
138 if( m_Notebook->GetPage( i )->GetName() == typeName )
139 {
140 exists = true;
141 break;
142 }
143 }
144
145 if( exists )
146 {
147 clearModel( typeName );
148 }
149 else
150 {
151 wxString title = typeName + wxString::Format( " (%d)", int( uuidToRowMap.size() ) );
152 addPage( typeName, title );
153 }
154 }
155
156 for( auto& [typeName, uuidToRowMap] : dataMap )
157 {
158 std::vector<std::pair<wxString, wxString>>& thisColNameTypes = m_columnNameTypes[typeName];
159 std::map<wxString, int> nameToColIdMap;
160 std::set<wxString> columnsSet;
161
162 for( auto& [uuid, rowMap] : uuidToRowMap )
163 {
164 for( auto& [colName, value] : rowMap )
165 {
166 if( columnsSet.find( colName ) == columnsSet.end() )
167 {
168 int colId = columnsSet.size();
169 columnsSet.emplace( colName );
170
171 nameToColIdMap[colName] = colId;
172 thisColNameTypes.emplace_back( colName, "string" );
173 }
174 }
175 }
176
177 wxDataViewListStore* store = new wxDataViewListStore();
178
179 for( auto& [name, type] : thisColNameTypes )
180 store->AppendColumn( type );
181
182 int colCount = thisColNameTypes.size();
183
184 for( auto& [uuid, rowMap] : uuidToRowMap )
185 {
186 wxVector<wxVariant> values( colCount );
187
188 for( auto& [dataName, value] : rowMap )
189 {
190 values[nameToColIdMap[dataName]] = value;
191 }
192
193 store->AppendItem( values );
194 }
195
196 m_dataModels[typeName] = store;
197 }
198
199 m_Notebook->DeleteAllPages();
200
201 int pageId = 0;
202 for( auto& [typeName, model] : m_dataModels )
203 {
204 wxString title = typeName + wxString::Format( " (%d)", model->GetItemCount() );
205 wxDataViewCtrl* dataView = addPage( typeName, title );
206
207 if( typeName == lastPageName )
208 newPageId = pageId;
209
210 dataView->AssociateModel( model );
211
212 int colId = 0;
213 for( auto& [name, type] : m_columnNameTypes[typeName] )
214 {
215 int flags = wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE;
216
217 if( name == wxS( "UUID" ) )
218 flags |= wxDATAVIEW_COL_HIDDEN;
219
220 dataView->AppendTextColumn( name, colId, wxDATAVIEW_CELL_INERT, wxCOL_WIDTH_AUTOSIZE,
221 wxALIGN_LEFT, flags );
222
223 colId++;
224 }
225
226 m_dataViews[typeName] = dataView;
227
228 pageId++;
229 }
230
231 if( newPageId != -1 )
232 {
233 m_Notebook->SetSelection( newPageId );
234
235 wxDataViewCtrl* dataView = m_dataViews[lastPageName];
236 int uuidCol = dataView->GetColumnCount() - 1;
237 wxDataViewListStore* model = m_dataModels[lastPageName];
238 size_t itemCount = model->GetItemCount();
239 wxDataViewItemArray newSelections;
240
241 for( size_t itemId = 0; itemId < itemCount; itemId++ )
242 {
243 wxVariant var;
244 model->GetValueByRow( var, itemId, uuidCol );
245
246 if( lastUUIDs.find( var.GetString() ) != lastUUIDs.end() )
247 newSelections.push_back( model->GetItem( itemId ) );
248 }
249
250 dataView->SetSelections( newSelections );
251 }
252}
253
254
255wxDataViewCtrl* DIALOG_GENERATORS::addPage( const wxString& aName, const wxString& aTitle )
256{
257 wxPanel* panelPage =
258 new wxPanel( m_Notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
259
260 panelPage->SetName( aName );
261
262 wxBoxSizer* bSizerPage1;
263 bSizerPage1 = new wxBoxSizer( wxVERTICAL );
264
265 bSizerPage1->SetMinSize( wxSize( -1, 320 ) );
266 wxDataViewCtrl* dataView = new wxDataViewCtrl( panelPage, wxID_ANY, wxDefaultPosition,
267 wxDefaultSize, wxDV_MULTIPLE | wxDV_ROW_LINES );
268
269 dataView->Bind( wxEVT_DATAVIEW_SELECTION_CHANGED, &DIALOG_GENERATORS::OnItemSelected, this );
270 dataView->SetLayoutDirection( wxLayout_LeftToRight );
271
272 bSizerPage1->Add( dataView, 1, wxEXPAND | wxALL, 5 );
273
274
275 bSizerPage1->Add( 0, 8, 0, wxEXPAND, 5 );
276
277
278 panelPage->SetSizer( bSizerPage1 );
279 panelPage->Layout();
280 bSizerPage1->Fit( panelPage );
281 m_Notebook->AddPage( panelPage, aTitle, false );
282
283 return dataView;
284}
285
286
287void DIALOG_GENERATORS::onUnitsChanged( wxCommandEvent& event )
288{
289 m_units = m_frame->GetUserUnits();
290
292
293 event.Skip();
294}
295
296
297void DIALOG_GENERATORS::onBoardChanged( wxCommandEvent& event )
298{
299 m_currentBoard = m_frame->GetBoard();
300
301 if( m_currentBoard != nullptr )
302 m_currentBoard->AddListener( this );
303
305
306 event.Skip();
307}
308
309
311{
313}
314
315
316void DIALOG_GENERATORS::OnBoardItemsAdded( BOARD& aBoard, std::vector<BOARD_ITEM*>& aBoardItems )
317{
319}
320
321
323{
325}
326
327
328void DIALOG_GENERATORS::OnBoardItemsRemoved( BOARD& aBoard, std::vector<BOARD_ITEM*>& aBoardItems )
329{
331}
332
333
335{
337}
338
339
340void DIALOG_GENERATORS::OnBoardItemsChanged( BOARD& aBoard, std::vector<BOARD_ITEM*>& aBoardItems )
341{
343}
344
345
347 std::vector<BOARD_ITEM*>& aAddedItems,
348 std::vector<BOARD_ITEM*>& aRemovedItems,
349 std::vector<BOARD_ITEM*>& aChangedItems )
350{
352}
353
354
355DIALOG_GENERATORS::DIALOG_GENERATORS( PCB_EDIT_FRAME* aEditorFrame, wxWindow* aParent ) :
356 DIALOG_GENERATORS_BASE( aParent )
357{
359
360 m_frame = aEditorFrame;
361 m_currentBoard = m_frame->GetBoard();
362
363 m_Notebook->DeleteAllPages();
364
366
367 Bind( EDA_EVT_UNITS_CHANGED, &DIALOG_GENERATORS::onUnitsChanged, this );
368 Bind( EDA_EVT_BOARD_CHANGED, &DIALOG_GENERATORS::onBoardChanged, this );
369
370 if( m_currentBoard != nullptr )
371 {
372 m_currentBoard->AddListener( this );
373 }
374}
375
376
378{
379 clearModels();
380
381 if( m_currentBoard != nullptr )
382 m_currentBoard->RemoveListener( this );
383}
384
385
387{
388 wxString pageName = m_Notebook->GetCurrentPage()->GetName();
389 return m_dataModels[pageName];
390}
391
392
393void DIALOG_GENERATORS::OnItemSelected( wxDataViewEvent& aEvent )
394{
395 wxDataViewListStore* model = getCurrentModel();
396 wxString pageName = m_Notebook->GetCurrentPage()->GetName();
397 wxDataViewCtrl* dataView = m_dataViews[pageName];
398
399 if( !model )
400 return;
401
402 int uuidCol = dataView->GetColumnCount() - 1;
403 std::vector<BOARD_ITEM*> boardItems;
404 EDA_ITEMS edaItems;
405
406 wxDataViewItemArray selections;
407 dataView->GetSelections( selections );
408
409 for( wxDataViewItem& viewItem : selections )
410 {
411 wxVariant var;
412 model->GetValue( var, viewItem, uuidCol );
413
414 BOARD_ITEM* brdItem = m_currentBoard->ResolveItem( var.GetString() );
415
416 if( !brdItem || brdItem->Type() != KICAD_T::PCB_GENERATOR_T )
417 continue;
418
419 boardItems.push_back( brdItem );
420 edaItems.push_back( brdItem );
421 }
422
423 m_frame->GetToolManager()->RunAction( ACTIONS::selectionClear );
424 m_frame->GetToolManager()->RunAction<EDA_ITEMS*>( ACTIONS::selectItems, &edaItems );
425 m_frame->FocusOnItems( boardItems );
426}
427
428
429void DIALOG_GENERATORS::OnRebuildSelectedClick( wxCommandEvent& event )
430{
432}
433
434
435void DIALOG_GENERATORS::OnRebuildTypeClick( wxCommandEvent& event )
436{
437 wxDataViewListStore* model = getCurrentModel();
438 wxString pageName = m_Notebook->GetCurrentPage()->GetName();
439
440 if( !model )
441 return;
442
443 int uuidCol = m_columnNameTypes[pageName].size() - 1;
444 EDA_ITEMS items;
445
446 for( size_t row = 0; row < model->GetItemCount(); row++ )
447 {
448 wxVariant var;
449 model->GetValueByRow( var, row, uuidCol );
450
451 BOARD_ITEM* item = m_currentBoard->ResolveItem( var.GetString() );
452
453 if( !item || item->Type() != KICAD_T::PCB_GENERATOR_T )
454 continue;
455
456 items.push_back( item );
457 }
458
459 m_frame->GetToolManager()->RunAction( ACTIONS::selectionClear );
460 m_frame->GetToolManager()->RunAction<EDA_ITEMS*>( ACTIONS::selectItems, &items );
461 m_frame->GetToolManager()->RunAction( PCB_ACTIONS::regenerateSelected );
463}
464
465
466void DIALOG_GENERATORS::OnRebuildAllClick( wxCommandEvent& event )
467{
468 m_frame->GetToolManager()->RunAction( PCB_ACTIONS::regenerateAll );
470}
471
472
473void DIALOG_GENERATORS::OnCancelClick( wxCommandEvent& event )
474{
475 GENERATOR_TOOL* genTool = m_frame->GetToolManager()->GetTool<GENERATOR_TOOL>();
476 genTool->DestroyManagerDialog();
477}
const char * name
static TOOL_ACTION selectionClear
Clear the current selection.
Definition actions.h:224
static TOOL_ACTION selectItems
Select a list of items (specified as the event parameter)
Definition actions.h:232
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:83
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:322
DIALOG_GENERATORS_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Generator Objects"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
PCB_EDIT_FRAME * m_frame
void OnRebuildTypeClick(wxCommandEvent &event) override
virtual void OnBoardItemsChanged(BOARD &aBoard, std::vector< BOARD_ITEM * > &aBoardItems) override
DIALOG_GENERATORS(PCB_EDIT_FRAME *aEditorFrame, wxWindow *aParent)
void OnRebuildSelectedClick(wxCommandEvent &event) override
wxDataViewCtrl * addPage(const wxString &aName, const wxString &aTitle)
virtual void OnBoardCompositeUpdate(BOARD &aBoard, std::vector< BOARD_ITEM * > &aAddedItems, std::vector< BOARD_ITEM * > &aRemovedItems, std::vector< BOARD_ITEM * > &aChangedItems) override
void OnItemSelected(wxDataViewEvent &aEvent)
void deleteModel(const wxString &aName)
std::map< wxString, wxDataViewListStore * > m_dataModels
void OnCancelClick(wxCommandEvent &aEvent) override
void clearModel(const wxString &aName)
void OnRebuildAllClick(wxCommandEvent &event) override
virtual void OnBoardItemRemoved(BOARD &aBoard, BOARD_ITEM *aBoardItem) override
virtual void OnBoardItemAdded(BOARD &aBoard, BOARD_ITEM *aBoardItem) override
wxDataViewListStore * getCurrentModel()
std::map< wxString, wxDataViewCtrl * > m_dataViews
void onUnitsChanged(wxCommandEvent &event)
std::map< wxString, std::vector< std::pair< wxString, wxString > > > m_columnNameTypes
virtual void OnBoardItemsAdded(BOARD &aBoard, std::vector< BOARD_ITEM * > &aBoardItems) override
virtual void OnBoardItemsRemoved(BOARD &aBoard, std::vector< BOARD_ITEM * > &aBoardItems) override
virtual void OnBoardItemChanged(BOARD &aBoard, BOARD_ITEM *aBoardItem) override
void onBoardChanged(wxCommandEvent &event)
EDA_UNITS m_units
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
Handle actions specific to filling copper zones.
Definition kiid.h:49
wxString AsString() const
Definition kiid.cpp:247
static TOOL_ACTION regenerateAll
static TOOL_ACTION regenerateSelected
The main frame for Pcbnew.
#define DIALOG_GENERATORS_WINDOW_NAME
std::vector< EDA_ITEM * > EDA_ITEMS
KIBIS_MODEL * model
@ PCB_GENERATOR_T
class PCB_GENERATOR, generator on a layer
Definition typeinfo.h:91