KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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, 5 );
155
156 m_optionsBook->SetSelection( m_isPCBEdit ? 1 : 0 );
157
159 m_layerNameitemsGrid->PushEventHandler( new GRID_TRICKS( m_layerNameitemsGrid ) );
160 m_layerNameitemsGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
161
162 wxGridCellAttr* attr = new wxGridCellAttr;
163 attr->SetRenderer( new GRID_CELL_LAYER_RENDERER( nullptr ) );
164 LSET forbiddenLayers = LSET::AllCuMask() | LSET::AllTechMask();
165 forbiddenLayers.set( Edge_Cuts );
166 forbiddenLayers.set( Margin );
167 attr->SetEditor( new GRID_CELL_LAYER_SELECTOR( nullptr, forbiddenLayers ) );
168 m_layerNameitemsGrid->SetColAttr( 0, attr );
169
170 m_bpAddLayer->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
171 m_bpDeleteLayer->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
172
173 // I wish I knew why these were needed here and not anywhere else. Something to do with being
174 // inside a notebook page that starts off hidden? Anyway: no hacky code -> no worky.
175 m_bpAddLayer->SetSize( m_bpAddLayer->GetMinSize() );
176 m_bpDeleteLayer->SetSize( m_bpDeleteLayer->GetMinSize() );
177 Layout();
178}
179
180
182{
183 // destroy GRID_TRICKS before grids.
184 m_layerNameitemsGrid->PopEventHandler( true );
185}
186
187
189{
190 wxGridTableBase* table = m_layerNameitemsGrid->GetTable();
191
192 for( const auto& [canonicalName, userName] : aCfg->m_DesignSettings.m_UserLayerNames )
193 {
194 wxString orig_name = canonicalName;
195 int layer = LSET::NameToLayer( orig_name );
196
197 if( !IsUserLayer( static_cast<PCB_LAYER_ID>( layer ) ) )
198 continue;
199
200 int row = m_layerNameitemsGrid->GetNumberRows();
201 table->AppendRows( 1 );
202 table->SetValueAsLong( row, 0, layer );
203 table->SetValue( row, 1, userName );
204 }
205
206 Layout();
207}
208
209
211{
213 m_OptDisplayTracksClearance->SetSelection( i );
214
217 m_ShowNetNamesOption->SetSelection( aCfg->m_Display.m_NetNames );
219 m_live3Drefresh->SetValue( aCfg->m_Display.m_Live3DRefresh );
224}
225
226
228{
229 bool retVal = wxPanel::Show( aShow );
230
231 if( aShow )
232 {
233 // These *should* work in the constructor, and indeed they do if this panel is the
234 // first displayed. However, on OSX 3.0.5 (at least), if another panel is displayed
235 // first then the icons will be blank unless they're set here.
236 m_bpAddLayer->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
237 m_bpDeleteLayer->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
238 Layout();
239 }
240
241 return retVal;
242}
243
244
246{
247 if( m_isPCBEdit )
248 loadPCBSettings( GetAppSettings<PCBNEW_SETTINGS>( "pcbnew" ) );
249 else
250 loadFPSettings( GetAppSettings<FOOTPRINT_EDITOR_SETTINGS>( "fpedit" ) );
251
253
254 return true;
255}
256
257
259{
260 std::set<int> usedLayers;
261
262 for( int i = 0; i < m_layerNameitemsGrid->GetNumberRows(); ++i )
263 usedLayers.insert( (int) m_layerNameitemsGrid->GetTable()->GetValueAsLong( i, 0 ) );
264
265 for( int ii = User_1; ii < User_45; ++ii )
266 {
267 if( !usedLayers.contains( ii ) )
268 return ii;
269 }
270
271 return -1;
272}
273
274
275void PANEL_DISPLAY_OPTIONS::onLayerChange( wxGridEvent& event )
276{
277 wxGridTableBase* table = m_layerNameitemsGrid->GetTable();
278
279 if( event.GetCol() == 0 )
280 {
281 int layer = static_cast<int>( table->GetValueAsLong( event.GetRow(), 0 ) );
282
283 for( int i = 0; i < m_layerNameitemsGrid->GetNumberRows(); ++i )
284 {
285 if( i != event.GetRow() && table->GetValueAsLong( i, 0 ) == layer )
286 {
287 table->SetValueAsLong( event.GetRow(), 0, getNextAvailableLayer() );
288 return;
289 }
290 }
291 }
292
293 for( int ii = 0; ii < m_layerNameitemsGrid->GetNumberRows(); ++ii )
294 {
295 wxString layerName = table->GetValue( ii, 1 );
296
297 if( ii != event.GetRow() && layerName == table->GetValue( event.GetRow(), 1 ) )
298 {
299 wxString msg = wxString::Format( _( "Layer name %s already in use." ), layerName );
300 PAGED_DIALOG::GetDialog( this )->SetError( msg, this, m_layerNameitemsGrid, ii, 1 );
301 return;
302 }
303 }
304}
305
306
307void PANEL_DISPLAY_OPTIONS::OnAddLayerItem( wxCommandEvent& event )
308{
310 [&]() -> std::pair<int, int>
311 {
312 m_layerNameitemsGrid->GetTable()->AppendRows( 1 );
313 return { m_layerNameitemsGrid->GetNumberRows() - 1, -1 };
314 } );
315}
316
317
318void PANEL_DISPLAY_OPTIONS::OnDeleteLayerItem( wxCommandEvent& event )
319{
321 [&]( int row )
322 {
323 m_layerNameitemsGrid->GetTable()->DeleteRows( row, 1 );
324 } );
325}
326
327
328/*
329 * Update variables with new options
330 */
332{
334 return false;
335
337
338 if( m_isPCBEdit )
339 {
340 if( PCBNEW_SETTINGS* cfg = GetAppSettings<PCBNEW_SETTINGS>( "pcbnew" ) )
341 {
342 int i = m_OptDisplayTracksClearance->GetSelection();
343 cfg->m_Display.m_TrackClearance = UTIL::GetValFromConfig( clearanceModeMap, i );
344
345 cfg->m_Display.m_PadClearance = m_OptDisplayPadClearence->GetValue();
346 cfg->m_ViewersDisplay.m_DisplayPadNumbers = m_OptDisplayPadNumber->GetValue();
347 cfg->m_Display.m_NetNames = m_ShowNetNamesOption->GetSelection();
348 cfg->m_Display.m_ForceShowFieldsWhenFPSelected = m_checkForceShowFieldsWhenFPSelected->GetValue();
349 cfg->m_Display.m_Live3DRefresh = m_live3Drefresh->GetValue();
350 cfg->m_CrossProbing.on_selection = m_checkCrossProbeOnSelection->GetValue();
351 cfg->m_CrossProbing.center_on_items = m_checkCrossProbeCenter->GetValue();
352 cfg->m_CrossProbing.zoom_to_fit = m_checkCrossProbeZoom->GetValue();
353 cfg->m_CrossProbing.auto_highlight = m_checkCrossProbeAutoHighlight->GetValue();
354 }
355 }
356 else
357 {
358 if( FOOTPRINT_EDITOR_SETTINGS* cfg = GetAppSettings<FOOTPRINT_EDITOR_SETTINGS>( "fpedit" ) )
359 {
360 cfg->m_DesignSettings.m_UserLayerNames.clear();
361 wxGridTableBase* table = m_layerNameitemsGrid->GetTable();
362
363 for( int i = 0; i < m_layerNameitemsGrid->GetNumberRows(); ++i )
364 {
365 PCB_LAYER_ID layer = static_cast<PCB_LAYER_ID>( table->GetValueAsLong( i, 0 ) );
366 wxString orig_name = LSET::Name( static_cast<PCB_LAYER_ID>( layer ) );
367 wxString name = table->GetValue( i, 1 );
368
369 if( layer >= 0 && IsUserLayer( layer ) && !name.IsEmpty() )
370 cfg->m_DesignSettings.m_UserLayerNames.emplace( orig_name.ToStdString(), name );
371 }
372 }
373 }
374
375 return true;
376}
377
378
380{
381 if( m_isPCBEdit )
382 {
383 PCBNEW_SETTINGS cfg;
384 cfg.Load(); // Loading without a file will init to defaults
385
386 loadPCBSettings( &cfg );
387 m_galOptsPanel->ResetPanel( &cfg );
388 }
389 else
390 {
392 cfg.Load(); // Loading without a file will init to defaults
393
394 loadFPSettings( &cfg );
395 m_galOptsPanel->ResetPanel( &cfg );
396 }
397}
398
399
const char * name
Definition: DXF_plotter.cpp:62
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:108
CROSS_PROBING_SETTINGS m_CrossProbing
Definition: app_settings.h:213
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 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:659
static LSET AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
Definition: lset.cpp:591
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
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:273
void OnDeleteRows(const std::function< void(int row)> &aDeleter)
Handles a row deletion event.
Definition: wx_grid.cpp:704
void OnAddRow(const std::function< std::pair< int, int >()> &aAdder)
Definition: wx_grid.cpp:684
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:632
#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:746
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
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