KiCad PCB EDA Suite
Loading...
Searching...
No Matches
panel_fp_user_layer_names.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
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
21
22#include <pgm_base.h>
26#include <template_fieldnames.h>
28#include <grid_tricks.h>
31#include <bitmaps.h>
32#include <confirm.h>
33
34
35class LAYER_NAMES_GRID_TABLE : public wxGridTableBase
36{
37 std::vector<TEXT_ITEM_INFO> m_items;
38
39public:
41
42 int GetNumberRows() override { return m_items.size(); }
43 int GetNumberCols() override { return 2; }
44
45 wxString GetColLabelValue( int aCol ) override
46 {
47 switch( aCol )
48 {
49 case 0: return _( "Layer" );
50 case 1: return _( "Name" );
51 default: return wxEmptyString;
52 }
53 }
54
55 bool CanGetValueAs( int aRow, int aCol, const wxString& aTypeName ) override
56 {
57 switch( aCol )
58 {
59 case 0: return aTypeName == wxGRID_VALUE_NUMBER;
60 case 1: return aTypeName == wxGRID_VALUE_STRING;
61 default: wxFAIL; return false;
62 }
63 }
64
65 bool CanSetValueAs( int aRow, int aCol, const wxString& aTypeName ) override
66 {
67 return CanGetValueAs( aRow, aCol, aTypeName );
68 }
69
70 wxString GetValue( int row, int col ) override { return m_items[row].m_Text; }
71 void SetValue( int row, int col, const wxString& value ) override
72 {
73 if( col == 1 )
74 m_items[row].m_Text = value;
75 }
76
77 long GetValueAsLong( int row, int col ) override { return m_items[row].m_Layer; }
78 void SetValueAsLong( int row, int col, long value ) override
79 {
80 if( col == 0 )
81 m_items[row].m_Layer = static_cast<PCB_LAYER_ID>( value );
82 }
83
84 bool AppendRows( size_t aNumRows = 1 ) override
85 {
86 std::set<int> layers;
87 int layer = User_1;
88
89 for( const TEXT_ITEM_INFO& item : m_items )
90 layers.insert( item.m_Layer );
91
92 for( size_t i = 0; i < aNumRows; ++i )
93 {
94 while( layers.contains( layer ) )
95 layer = layer + 2;
96
97 if( IsUserLayer( static_cast<PCB_LAYER_ID>( layer ) ) )
98 {
99 layers.insert( layer );
100 m_items.emplace_back( wxT( "" ), true, static_cast<PCB_LAYER_ID>( layer ) );
101 }
102 else
103 {
104 return false;
105 }
106 }
107
108 if( GetView() )
109 {
110 wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, aNumRows );
111 GetView()->ProcessTableMessage( msg );
112 }
113
114 return true;
115 }
116
117 bool DeleteRows( size_t aPos, size_t aNumRows ) override
118 {
119 // aPos may be a large positive, e.g. size_t(-1), and the sum of
120 // aPos+aNumRows may wrap here, so both ends of the range are tested.
121 if( aPos < m_items.size() && aPos + aNumRows <= m_items.size() )
122 {
123 m_items.erase( m_items.begin() + aPos, m_items.begin() + aPos + aNumRows );
124
125 if( GetView() )
126 {
127 wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_DELETED, aPos, aNumRows );
128 GetView()->ProcessTableMessage( msg );
129 }
130
131 return true;
132 }
133
134 return false;
135 }
136};
137
138
143
144
147 m_designSettings( GetPgmSettings().m_DesignSettings )
148{
149 m_layerNamesGrid->SetDefaultRowSize( m_layerNamesGrid->GetDefaultRowSize() + 4 );
150
151 m_layerNamesGrid->SetTable( new LAYER_NAMES_GRID_TABLE(), true );
152 m_layerNamesGrid->PushEventHandler( new GRID_TRICKS( m_layerNamesGrid ) );
153 m_layerNamesGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
154
155 wxGridCellAttr* attr = new wxGridCellAttr;
156 attr->SetRenderer( new GRID_CELL_LAYER_RENDERER( nullptr ) );
157 LSET forbiddenLayers = LSET::AllCuMask() | LSET::AllTechMask();
158 forbiddenLayers.set( Edge_Cuts );
159 forbiddenLayers.set( Margin );
160 attr->SetEditor( new GRID_CELL_LAYER_SELECTOR( nullptr, forbiddenLayers ) );
161 m_layerNamesGrid->SetColAttr( 0, attr );
162
163 attr = new wxGridCellAttr;
164 m_layerNamesGrid->SetColAttr( 1, attr );
165
168}
169
170
175
176
178{
179 int userLayerCount = aCfg->m_DesignSettings.GetUserDefinedLayerCount();
180
181 if( userLayerCount >= 0 && userLayerCount < (int) m_choiceUserLayers->GetCount() )
182 m_choiceUserLayers->SetSelection( userLayerCount );
183 else
184 m_choiceUserLayers->SetSelection( 0 );
185
186 wxGridTableBase* table = m_layerNamesGrid->GetTable();
187 table->DeleteRows( 0, m_layerNamesGrid->GetNumberRows() );
188
189 for( const auto& [canonicalName, userName] : aCfg->m_DesignSettings.m_UserLayerNames )
190 {
191 wxString orig_name = canonicalName;
192 int layer = LSET::NameToLayer( orig_name );
193
194 if( !IsUserLayer( static_cast<PCB_LAYER_ID>( layer ) ) )
195 continue;
196
197 int row = m_layerNamesGrid->GetNumberRows();
198 table->AppendRows( 1 );
199 table->SetValueAsLong( row, 0, layer );
200 table->SetValue( row, 1, userName );
201 }
202
203 Layout();
204}
205
206
208{
210
211 loadFPSettings( &cfg );
212
213 return true;
214}
215
216
218{
219 bool retVal = wxPanel::Show( aShow );
220
221 if( aShow )
222 {
225 }
226
227 return retVal;
228}
229
230
232{
233 if( !m_layerNamesGrid->CommitPendingChanges() )
234 return false;
235
237
238 int userLayerCount = m_choiceUserLayers->GetSelection();
239 cfg.SetUserDefinedLayerCount( userLayerCount );
240
241 cfg.m_UserLayerNames.clear();
242 wxGridTableBase* table = m_layerNamesGrid->GetTable();
243
244 for( int i = 0; i < m_layerNamesGrid->GetNumberRows(); ++i )
245 {
246 PCB_LAYER_ID layer = static_cast<PCB_LAYER_ID>( table->GetValueAsLong( i, 0 ) );
247 wxString orig_name = LSET::Name( static_cast<PCB_LAYER_ID>( layer ) );
248 wxString name = table->GetValue( i, 1 );
249
250 if( layer >= 0 && IsUserLayer( layer ) && !name.IsEmpty() )
251 cfg.m_UserLayerNames.emplace( orig_name.ToStdString(), name );
252 }
253
254 return true;
255}
256
257
259{
260 // Nothing to do here - just update the selection. The value is saved in TransferDataFromWindow.
261}
262
263
265{
266 wxGridTableBase* table = m_layerNamesGrid->GetTable();
267
268 if( event.GetCol() == 0 )
269 {
270 int layer = static_cast<int>( table->GetValueAsLong( event.GetRow(), 0 ) );
271
272 for( int i = 0; i < m_layerNamesGrid->GetNumberRows(); ++i )
273 {
274 if( i != event.GetRow() && table->GetValueAsLong( i, 0 ) == layer )
275 {
276 table->SetValueAsLong( event.GetRow(), 0, getNextAvailableLayer() );
277 return;
278 }
279 }
280 }
281
282 for( int ii = 0; ii < m_layerNamesGrid->GetNumberRows(); ++ii )
283 {
284 wxString layerName = table->GetValue( ii, 1 );
285
286 if( ii != event.GetRow() && layerName == table->GetValue( event.GetRow(), 1 ) )
287 {
288 wxString msg = wxString::Format( _( "Layer name %s already in use." ), layerName );
289 PAGED_DIALOG::GetDialog( this )->SetError( msg, this, m_layerNamesGrid, ii, 1 );
290 return;
291 }
292 }
293}
294
295
297{
298 std::set<int> usedLayers;
299
300 for( int i = 0; i < m_layerNamesGrid->GetNumberRows(); ++i )
301 usedLayers.insert( (int) m_layerNamesGrid->GetTable()->GetValueAsLong( i, 0 ) );
302
303 for( int ii = User_1; ii < User_45; ++ii )
304 {
305 if( !usedLayers.contains( ii ) )
306 return ii;
307 }
308
309 return -1;
310}
311
312
313void PANEL_FP_USER_LAYER_NAMES::OnAddLayerItem( wxCommandEvent& event )
314{
315 m_layerNamesGrid->OnAddRow(
316 [&]() -> std::pair<int, int>
317 {
318 m_layerNamesGrid->GetTable()->AppendRows( 1 );
319 return { m_layerNamesGrid->GetNumberRows() - 1, -1 };
320 } );
321}
322
323
325{
326 m_layerNamesGrid->OnDeleteRows(
327 [&]( int row )
328 {
329 m_layerNamesGrid->GetTable()->DeleteRows( row, 1 );
330 } );
331}
332
333
335{
337 cfg.Load();
338
339 loadFPSettings( &cfg );
340}
const char * name
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:106
BASE_SET & set(size_t pos)
Definition base_set.h:116
Container for design settings for a BOARD object.
std::map< std::string, wxString > m_UserLayerNames
void SetUserDefinedLayerCount(int aNewLayerCount)
Set the number of user defined layers to aNewLayerCount.
BOARD_DESIGN_SETTINGS m_DesignSettings
Only some of these settings are actually used for footprint editing.
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
Definition grid_tricks.h:57
virtual void Load()
Updates the parameters of this object based on the current JSON document contents.
bool DeleteRows(size_t aPos, size_t aNumRows) override
void SetValue(int row, int col, const wxString &value) override
std::vector< TEXT_ITEM_INFO > m_items
bool CanGetValueAs(int aRow, int aCol, const wxString &aTypeName) override
wxString GetColLabelValue(int aCol) override
bool AppendRows(size_t aNumRows=1) override
wxString GetValue(int row, int col) override
bool CanSetValueAs(int aRow, int aCol, const wxString &aTypeName) override
void SetValueAsLong(int row, int col, long value) override
long GetValueAsLong(int row, int col) override
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
static const LSET & AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
Definition lset.cpp:604
static int NameToLayer(wxString &aName)
Return the layer number from a layer name.
Definition lset.cpp:113
static const LSET & AllTechMask()
Return a mask holding all technical layers (no CU layer) on both side.
Definition lset.cpp:672
static wxString Name(PCB_LAYER_ID aLayerId)
Return the fixed name association with aLayerId.
Definition lset.cpp:184
static PAGED_DIALOG * GetDialog(wxWindow *aWindow)
void SetError(const wxString &aMessage, const wxString &aPageName, int aCtrlId, int aRow=-1, int aCol=-1)
PANEL_FP_USER_LAYER_NAMES_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxTAB_TRAVERSAL, const wxString &name=wxEmptyString)
void onUserLayerCountChange(wxCommandEvent &event) override
BOARD_DESIGN_SETTINGS & m_designSettings
void ResetPanel() override
Reset the contents of this panel.
void onLayerChange(wxGridEvent &event) override
void OnAddLayerItem(wxCommandEvent &event) override
void loadFPSettings(const FOOTPRINT_EDITOR_SETTINGS *aCfg)
void OnDeleteLayerItem(wxCommandEvent &event) override
This file is part of the common library.
#define _(s)
bool IsUserLayer(PCB_LAYER_ID aLayerId)
Test whether a layer is a non copper and a non tech layer.
Definition layer_ids.h:757
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
@ User_45
Definition layer_ids.h:164
@ Edge_Cuts
Definition layer_ids.h:108
@ Margin
Definition layer_ids.h:109
@ User_1
Definition layer_ids.h:120
static FOOTPRINT_EDITOR_SETTINGS & GetPgmSettings()
static FOOTPRINT_EDITOR_SETTINGS & GetPgmSettings()
see class PGM_BASE
T * GetAppSettings(const char *aFilename)
std::vector< std::vector< std::string > > table