KiCad PCB EDA Suite
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
panel_display_options.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) 2015 Jean-Pierre Charras, jean-pierre.charras at wanadoo.fr
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include <pgm_base.h>
23#include <pcbnew_settings.h>
24#include <config_map.h>
29#include <grid_tricks.h>
33
34
36{
37 { SHOW_WITH_VIA_WHILE_ROUTING, 2 }, // Default
39 { SHOW_WHILE_ROUTING, 1 },
42};
43
44
45class LAYER_NAMES_GRID_TABLE : public wxGridTableBase
46{
47 std::vector<TEXT_ITEM_INFO> m_items;
48
49public:
51
52 int GetNumberRows() override { return m_items.size(); }
53 int GetNumberCols() override { return 2; }
54
55 wxString GetColLabelValue( int aCol ) override
56 {
57 switch( aCol )
58 {
59 case 0: return _( "Layer" );
60 case 1: return _( "Name" );
61 default: return wxEmptyString;
62 }
63 }
64
65 bool CanGetValueAs( int aRow, int aCol, const wxString& aTypeName ) override
66 {
67 switch( aCol )
68 {
69 case 0: return aTypeName == wxGRID_VALUE_NUMBER;
70 case 1: return aTypeName == wxGRID_VALUE_STRING;
71 default: wxFAIL; return false;
72 }
73 }
74
75 bool CanSetValueAs( int aRow, int aCol, const wxString& aTypeName ) override
76 {
77 return CanGetValueAs( aRow, aCol, aTypeName );
78 }
79
80 wxString GetValue( int row, int col ) override { return m_items[row].m_Text; }
81 void SetValue( int row, int col, const wxString& value ) override
82 {
83 if( col == 1 )
84 m_items[row].m_Text = value;
85 }
86
87 long GetValueAsLong( int row, int col ) override { return m_items[row].m_Layer; }
88 void SetValueAsLong( int row, int col, long value ) override
89 {
90 if( col == 0 )
91 m_items[row].m_Layer = static_cast<PCB_LAYER_ID>( value );
92 }
93
94 bool AppendRows( size_t aNumRows = 1 ) override
95 {
96 std::set<int> layers;
97 int layer = User_1;
98
99 for( const TEXT_ITEM_INFO& item : m_items )
100 layers.insert( item.m_Layer );
101
102
103 for( size_t i = 0; i < aNumRows; ++i )
104 {
105 while( layers.contains( layer ) )
106 layer = layer + 2;
107
108 if( IsUserLayer( static_cast<PCB_LAYER_ID>( layer ) ) )
109 {
110 layers.insert( layer );
111 m_items.emplace_back( wxT( "" ), true, static_cast<PCB_LAYER_ID>( layer ) );
112 }
113 else
114 {
115 return false;
116 }
117 }
118
119 if( GetView() )
120 {
121 wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, aNumRows );
122 GetView()->ProcessTableMessage( msg );
123 }
124
125 return true;
126 }
127
128 bool DeleteRows( size_t aPos, size_t aNumRows ) override
129 {
130 // aPos may be a large positive, e.g. size_t(-1), and the sum of
131 // aPos+aNumRows may wrap here, so both ends of the range are tested.
132 if( aPos < m_items.size() && aPos + aNumRows <= m_items.size() )
133 {
134 m_items.erase( m_items.begin() + aPos, m_items.begin() + aPos + aNumRows );
135
136 if( GetView() )
137 {
138 wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_DELETED, aPos, aNumRows );
139 GetView()->ProcessTableMessage( msg );
140 }
141 return true;
142 }
143
144 return false;
145 }
146};
147
148
151 m_isPCBEdit( dynamic_cast<PCBNEW_SETTINGS*>( aAppSettings ) != nullptr )
152{
153 m_galOptsPanel = new GAL_OPTIONS_PANEL( this, aAppSettings );
154 m_galOptionsSizer->Add( m_galOptsPanel, 1, wxEXPAND|wxRIGHT, 15 );
155
156 m_optionsBook->SetSelection( m_isPCBEdit ? 1 : 0 );
157
158 m_layerNameitemsGrid->SetDefaultRowSize( m_layerNameitemsGrid->GetDefaultRowSize() + 4 );
159
161 m_layerNameitemsGrid->PushEventHandler( new GRID_TRICKS( m_layerNameitemsGrid ) );
162 m_layerNameitemsGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
163
164 wxGridCellAttr* attr = new wxGridCellAttr;
165 attr->SetRenderer( new GRID_CELL_LAYER_RENDERER( nullptr ) );
166 LSET forbiddenLayers = LSET::AllCuMask() | LSET::AllTechMask();
167 forbiddenLayers.set( Edge_Cuts );
168 forbiddenLayers.set( Margin );
169 attr->SetEditor( new GRID_CELL_LAYER_SELECTOR( nullptr, forbiddenLayers ) );
170 m_layerNameitemsGrid->SetColAttr( 0, attr );
171
172 m_bpAddLayer->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
173 m_bpDeleteLayer->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
174
175 // I wish I knew why these were needed here and not anywhere else. Something to do with being
176 // inside a notebook page that starts off hidden? Anyway: no hacky code -> no worky.
177 m_bpAddLayer->SetSize( m_bpAddLayer->GetMinSize() );
178 m_bpDeleteLayer->SetSize( m_bpDeleteLayer->GetMinSize() );
179 Layout();
180}
181
182
184{
185 // destroy GRID_TRICKS before grids.
186 m_layerNameitemsGrid->PopEventHandler( true );
187}
188
189
191{
192 wxGridTableBase* table = m_layerNameitemsGrid->GetTable();
193
194 for( auto& item : aCfg->m_DesignSettings.m_UserLayerNames )
195 {
196 wxString orig_name = item.first;
197 int layer = LSET::NameToLayer( orig_name );
198
199 if( !IsUserLayer( static_cast<PCB_LAYER_ID>( layer ) ) )
200 continue;
201
202 int row = m_layerNameitemsGrid->GetNumberRows();
203 table->AppendRows( 1 );
204 table->SetValueAsLong( row, 0, layer );
205 table->SetValue( row, 1, item.second );
206 }
207
208 Layout();
209}
210
211
213{
215 m_OptDisplayTracksClearance->SetSelection( i );
216
219 m_ShowNetNamesOption->SetSelection( aCfg->m_Display.m_NetNames );
221 m_live3Drefresh->SetValue( aCfg->m_Display.m_Live3DRefresh );
226}
227
228
230{
231 bool retVal = wxPanel::Show( aShow );
232
233 if( aShow )
234 {
235 // These *should* work in the constructor, and indeed they do if this panel is the
236 // first displayed. However, on OSX 3.0.5 (at least), if another panel is displayed
237 // first then the icons will be blank unless they're set here.
238 m_bpAddLayer->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
239 m_bpDeleteLayer->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
240 Layout();
241 }
242
243 return retVal;
244}
245
246
248{
250
251 if( m_isPCBEdit )
252 {
253 PCBNEW_SETTINGS* cfg = mgr.GetAppSettings<PCBNEW_SETTINGS>( "pcbnew" );
254
255 loadPCBSettings( cfg );
256 }
257 else
258 {
260
261 loadFPSettings( cfg );
262 }
263
265
266 return true;
267}
268
269
271{
272 std::set<int> usedLayers;
273
274 for( int i = 0; i < m_layerNameitemsGrid->GetNumberRows(); ++i )
275 usedLayers.insert( (int) m_layerNameitemsGrid->GetTable()->GetValueAsLong( i, 0 ) );
276
277 for( int ii = User_1; ii < User_45; ++ii )
278 {
279 if( !usedLayers.contains( ii ) )
280 return ii;
281 }
282
283 return -1;
284}
285
286
287void PANEL_DISPLAY_OPTIONS::onLayerChange( wxGridEvent& event )
288{
289 wxGridTableBase* table = m_layerNameitemsGrid->GetTable();
290
291 if( event.GetCol() == 0 )
292 {
293 int layer = static_cast<int>( table->GetValueAsLong( event.GetRow(), 0 ) );
294
295 for( int i = 0; i < m_layerNameitemsGrid->GetNumberRows(); ++i )
296 {
297 if( i != event.GetRow()
298 && table->GetValueAsLong( i, 0 ) == layer )
299 {
300 table->SetValueAsLong( event.GetRow(), 0, getNextAvailableLayer() );
301 return;
302 }
303 }
304 }
305
306 for( int ii = 0; ii < m_layerNameitemsGrid->GetNumberRows(); ++ii )
307 {
308 wxString layerName = table->GetValue( ii, 1 );
309
310 if( ii != event.GetRow() && layerName == table->GetValue( event.GetRow(), 1 ) )
311 {
312 wxString msg = wxString::Format( _( "Layer name %s already in use." ), layerName );
313 PAGED_DIALOG::GetDialog( this )->SetError( msg, this, m_layerNameitemsGrid, ii, 1 );
314 return;
315 }
316 }
317}
318
319
320void PANEL_DISPLAY_OPTIONS::OnAddLayerItem( wxCommandEvent& event )
321{
323 return;
324
325 wxGridTableBase* table = m_layerNameitemsGrid->GetTable();
326
327 int newRow = m_layerNameitemsGrid->GetNumberRows();
328 table->AppendRows( 1 );
329
330 m_layerNameitemsGrid->MakeCellVisible( newRow, 0 );
331 m_layerNameitemsGrid->SetGridCursor( newRow, 0 );
332}
333
334
335void PANEL_DISPLAY_OPTIONS::OnDeleteLayerItem( wxCommandEvent& event )
336{
337 wxArrayInt selectedRows = m_layerNameitemsGrid->GetSelectedRows();
338
339 if( selectedRows.empty() && m_layerNameitemsGrid->GetGridCursorRow() >= 0 )
340 selectedRows.push_back( m_layerNameitemsGrid->GetGridCursorRow() );
341
342 if( selectedRows.empty() )
343 return;
344
346 return;
347
348 // Reverse sort so deleting a row doesn't change the indexes of the other rows.
349 selectedRows.Sort(
350 []( int* first, int* second )
351 {
352 return *second - *first;
353 } );
354
355 for( int row : selectedRows )
356 {
357 m_layerNameitemsGrid->GetTable()->DeleteRows( row, 1 );
358
359 if( m_layerNameitemsGrid->GetNumberRows() > 0 )
360 {
361 m_layerNameitemsGrid->MakeCellVisible( std::max( 0, row - 1 ),
362 m_layerNameitemsGrid->GetGridCursorCol() );
363 m_layerNameitemsGrid->SetGridCursor( std::max( 0, row - 1 ),
364 m_layerNameitemsGrid->GetGridCursorCol() );
365 }
366 }
367}
368
369
370/*
371 * Update variables with new options
372 */
374{
376 return false;
377
379
381
382 if( m_isPCBEdit )
383 {
384 PCBNEW_SETTINGS* cfg = mgr.GetAppSettings<PCBNEW_SETTINGS>( "pcbnew" );
385
386 int i = m_OptDisplayTracksClearance->GetSelection();
388
391 cfg->m_Display.m_NetNames = m_ShowNetNamesOption->GetSelection();
393 cfg->m_Display.m_Live3DRefresh = m_live3Drefresh->GetValue();
398 }
399 else
400 {
402
404 wxGridTableBase* table = m_layerNameitemsGrid->GetTable();
405
406 for( int i = 0; i < m_layerNameitemsGrid->GetNumberRows(); ++i )
407 {
408 PCB_LAYER_ID layer = static_cast<PCB_LAYER_ID>( table->GetValueAsLong( i, 0 ) );
409 wxString orig_name = LSET::Name( static_cast<PCB_LAYER_ID>( layer ) );
410 wxString name = table->GetValue( i, 1 );
411
412 if( layer >= 0 && IsUserLayer( layer ) && !name.IsEmpty() )
413 cfg->m_DesignSettings.m_UserLayerNames.emplace( orig_name.ToStdString(), name );
414 }
415 }
416
417 return true;
418}
419
420
422{
423 if( m_isPCBEdit )
424 {
425 PCBNEW_SETTINGS cfg;
426 cfg.Load(); // Loading without a file will init to defaults
427
428 loadPCBSettings( &cfg );
429 m_galOptsPanel->ResetPanel( &cfg );
430 }
431 else
432 {
434 cfg.Load(); // Loading without a file will init to defaults
435
436 loadFPSettings( &cfg );
437 m_galOptsPanel->ResetPanel( &cfg );
438 }
439}
440
441
const char * name
Definition: DXF_plotter.cpp:59
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition: bitmap.cpp:110
APP_SETTINGS_BASE is a settings class that should be derived for each standalone KiCad application.
Definition: app_settings.h:92
CROSS_PROBING_SETTINGS m_CrossProbing
Definition: app_settings.h:193
BASE_SET & set(size_t pos)
Definition: base_set.h:116
std::map< std::string, wxString > m_UserLayerNames
BOARD_DESIGN_SETTINGS m_DesignSettings
Only some of these settings are actually used for footprint editing.
bool ResetPanel(APP_SETTINGS_BASE *aAppSettings)
bool TransferDataToWindow() override
Load the panel controls from the given opt.
bool TransferDataFromWindow() override
Read the options set in the UI into the given options object.
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
Definition: grid_tricks.h:61
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 LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:572
static int NameToLayer(wxString &aName)
Return the layer number from a layer name.
Definition: lset.cpp:117
static const LSET & AllTechMask()
Return a mask holding all technical layers (no CU layer) on both side.
Definition: lset.cpp:636
static wxString Name(PCB_LAYER_ID aLayerId)
Return the fixed name association with aLayerId.
Definition: lset.cpp:188
static PAGED_DIALOG * GetDialog(wxWindow *aWindow)
void SetError(const wxString &aMessage, const wxString &aPageName, int aCtrlId, int aRow=-1, int aCol=-1)
Class PANEL_DISPLAY_OPTIONS_BASE.
void OnDeleteLayerItem(wxCommandEvent &event) override
void loadPCBSettings(PCBNEW_SETTINGS *aCfg)
PANEL_DISPLAY_OPTIONS(wxWindow *aParent, APP_SETTINGS_BASE *aAppSettings)
void OnAddLayerItem(wxCommandEvent &event) override
void loadFPSettings(const FOOTPRINT_EDITOR_SETTINGS *aCfg)
bool Show(bool aShow) override
GAL_OPTIONS_PANEL * m_galOptsPanel
void ResetPanel() override
Reset the contents of this panel.
void onLayerChange(wxGridEvent &event) override
bool TransferDataFromWindow() override
bool TransferDataToWindow() override
DISPLAY_OPTIONS m_Display
VIEWERS_DISPLAY_OPTIONS m_ViewersDisplay
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition: pgm_base.h:125
T * GetAppSettings(const char *aFilename)
Return a handle to the a given settings by type.
void SetBitmap(const wxBitmapBundle &aBmp)
void SetTable(wxGridTableBase *table, bool aTakeOwnership=false)
Hide wxGrid's SetTable() method with one which doesn't mess up the grid column widths when setting th...
Definition: wx_grid.cpp:275
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:644
#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:744
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ User_45
Definition: layer_ids.h:168
@ Edge_Cuts
Definition: layer_ids.h:112
@ Margin
Definition: layer_ids.h:113
@ User_1
Definition: layer_ids.h:124
std::vector< std::pair< T, long > > CFG_MAP
A config value table is a list of native values (usually enums) to a different set of values,...
Definition: config_map.h:49
static long GetConfigForVal(const MAP &aMap, CFG_NATIVE_VAL< MAP > aVal)
Get the mapped config value (the one to write to file, or use in an index) from the given native (pro...
Definition: config_map.h:69
static CFG_NATIVE_VAL< MAP > GetValFromConfig(const MAP &aMap, long aConf)
Get the native value corresponding to the config value (read from file or UI, probably) and find it i...
Definition: config_map.h:96
static const UTIL::CFG_MAP< TRACK_CLEARANCE_MODE > clearanceModeMap
@ SHOW_WITH_VIA_WHILE_ROUTING_OR_DRAGGING
@ DO_NOT_SHOW_CLEARANCE
@ SHOW_WHILE_ROUTING
@ SHOW_WITH_VIA_ALWAYS
@ SHOW_WITH_VIA_WHILE_ROUTING
PGM_BASE & Pgm()
The global program "get" accessor.
Definition: pgm_base.cpp:1071
see class PGM_BASE
bool on_selection
Synchronize the selection for multiple items too.
Definition: app_settings.h:33
bool zoom_to_fit
Zoom to fit items (ignored if center_on_items is off).
Definition: app_settings.h:35
bool center_on_items
Automatically pan to cross-probed items.
Definition: app_settings.h:34
bool auto_highlight
Automatically turn on highlight mode in the target frame.
Definition: app_settings.h:36
TRACK_CLEARANCE_MODE m_TrackClearance