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
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 PANEL_GAL_OPTIONS( this, aAppSettings );
154 m_galOptionsSizer->Add( m_galOptsPanel, 1, wxEXPAND|wxRIGHT, 5 );
155
156 m_optionsBook->SetSelection( m_isPCBEdit ? 1 : 0 );
157
158 m_layerNameitemsGrid->SetTable( new LAYER_NAMES_GRID_TABLE(), true );
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
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
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.
240 Layout();
241 }
242
243 return retVal;
244}
245
246
248{
249 if( m_isPCBEdit )
251 else
253
254 m_galOptsPanel->TransferDataToWindow();
255
256 return true;
257}
258
259
261{
262 std::set<int> usedLayers;
263
264 for( int i = 0; i < m_layerNameitemsGrid->GetNumberRows(); ++i )
265 usedLayers.insert( (int) m_layerNameitemsGrid->GetTable()->GetValueAsLong( i, 0 ) );
266
267 for( int ii = User_1; ii < User_45; ++ii )
268 {
269 if( !usedLayers.contains( ii ) )
270 return ii;
271 }
272
273 return -1;
274}
275
276
277void PANEL_DISPLAY_OPTIONS::onLayerChange( wxGridEvent& event )
278{
279 wxGridTableBase* table = m_layerNameitemsGrid->GetTable();
280
281 if( event.GetCol() == 0 )
282 {
283 int layer = static_cast<int>( table->GetValueAsLong( event.GetRow(), 0 ) );
284
285 for( int i = 0; i < m_layerNameitemsGrid->GetNumberRows(); ++i )
286 {
287 if( i != event.GetRow() && table->GetValueAsLong( i, 0 ) == layer )
288 {
289 table->SetValueAsLong( event.GetRow(), 0, getNextAvailableLayer() );
290 return;
291 }
292 }
293 }
294
295 for( int ii = 0; ii < m_layerNameitemsGrid->GetNumberRows(); ++ii )
296 {
297 wxString layerName = table->GetValue( ii, 1 );
298
299 if( ii != event.GetRow() && layerName == table->GetValue( event.GetRow(), 1 ) )
300 {
301 wxString msg = wxString::Format( _( "Layer name %s already in use." ), layerName );
302 PAGED_DIALOG::GetDialog( this )->SetError( msg, this, m_layerNameitemsGrid, ii, 1 );
303 return;
304 }
305 }
306}
307
308
309void PANEL_DISPLAY_OPTIONS::OnAddLayerItem( wxCommandEvent& event )
310{
311 m_layerNameitemsGrid->OnAddRow(
312 [&]() -> std::pair<int, int>
313 {
314 m_layerNameitemsGrid->GetTable()->AppendRows( 1 );
315 return { m_layerNameitemsGrid->GetNumberRows() - 1, -1 };
316 } );
317}
318
319
320void PANEL_DISPLAY_OPTIONS::OnDeleteLayerItem( wxCommandEvent& event )
321{
322 m_layerNameitemsGrid->OnDeleteRows(
323 [&]( int row )
324 {
325 m_layerNameitemsGrid->GetTable()->DeleteRows( row, 1 );
326 } );
327}
328
329
330/*
331 * Update variables with new options
332 */
334{
335 if( !m_layerNameitemsGrid->CommitPendingChanges() )
336 return false;
337
338 m_galOptsPanel->TransferDataFromWindow();
339
340 if( m_isPCBEdit )
341 {
342 if( PCBNEW_SETTINGS* cfg = GetAppSettings<PCBNEW_SETTINGS>( "pcbnew" ) )
343 {
344 int i = m_OptDisplayTracksClearance->GetSelection();
345 cfg->m_Display.m_TrackClearance = UTIL::GetValFromConfig( clearanceModeMap, i );
346
347 cfg->m_Display.m_PadClearance = m_OptDisplayPadClearence->GetValue();
348 cfg->m_Display.m_UseViaColorForNormalTHPadstacks = m_OptUseViaColorForNormalTHPadstacks->GetValue();
349 cfg->m_ViewersDisplay.m_DisplayPadNumbers = m_OptDisplayPadNumber->GetValue();
350 cfg->m_Display.m_NetNames = m_ShowNetNamesOption->GetSelection();
351 cfg->m_Display.m_ForceShowFieldsWhenFPSelected = m_checkForceShowFieldsWhenFPSelected->GetValue();
352 cfg->m_Display.m_Live3DRefresh = m_live3Drefresh->GetValue();
353 cfg->m_CrossProbing.on_selection = m_checkCrossProbeOnSelection->GetValue();
354 cfg->m_CrossProbing.center_on_items = m_checkCrossProbeCenter->GetValue();
355 cfg->m_CrossProbing.zoom_to_fit = m_checkCrossProbeZoom->GetValue();
356 cfg->m_CrossProbing.auto_highlight = m_checkCrossProbeAutoHighlight->GetValue();
357 cfg->m_CrossProbing.flash_selection = m_checkCrossProbeFlash->GetValue();
358 }
359 }
360 else
361 {
363 {
364 cfg->m_DesignSettings.m_UserLayerNames.clear();
365 wxGridTableBase* table = m_layerNameitemsGrid->GetTable();
366
367 for( int i = 0; i < m_layerNameitemsGrid->GetNumberRows(); ++i )
368 {
369 PCB_LAYER_ID layer = static_cast<PCB_LAYER_ID>( table->GetValueAsLong( i, 0 ) );
370 wxString orig_name = LSET::Name( static_cast<PCB_LAYER_ID>( layer ) );
371 wxString name = table->GetValue( i, 1 );
372
373 if( layer >= 0 && IsUserLayer( layer ) && !name.IsEmpty() )
374 cfg->m_DesignSettings.m_UserLayerNames.emplace( orig_name.ToStdString(), name );
375 }
376 }
377 }
378
379 return true;
380}
381
382
384{
385 if( m_isPCBEdit )
386 {
387 PCBNEW_SETTINGS cfg;
388 cfg.Load(); // Loading without a file will init to defaults
389
390 loadPCBSettings( &cfg );
391 m_galOptsPanel->ResetPanel( &cfg );
392 }
393 else
394 {
396 cfg.Load(); // Loading without a file will init to defaults
397
398 loadFPSettings( &cfg );
399 m_galOptsPanel->ResetPanel( &cfg );
400 }
401}
402
403
const char * name
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.
CROSS_PROBING_SETTINGS m_CrossProbing
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.
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)
PANEL_DISPLAY_OPTIONS_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 OnDeleteLayerItem(wxCommandEvent &event) override
void loadPCBSettings(PCBNEW_SETTINGS *aCfg)
PANEL_DISPLAY_OPTIONS(wxWindow *aParent, APP_SETTINGS_BASE *aAppSettings)
PANEL_GAL_OPTIONS * m_galOptsPanel
void OnAddLayerItem(wxCommandEvent &event) override
void loadFPSettings(const FOOTPRINT_EDITOR_SETTINGS *aCfg)
bool Show(bool aShow) override
void ResetPanel() override
Reset the contents of this panel.
void onLayerChange(wxGridEvent &event) override
DISPLAY_OPTIONS m_Display
VIEWERS_DISPLAY_OPTIONS m_ViewersDisplay
#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:755
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
T * GetAppSettings(const char *aFilename)
bool flash_selection
Flash newly cross-probed selection (visual attention aid).
bool on_selection
Synchronize the selection for multiple items too.
bool zoom_to_fit
Zoom to fit items (ignored if center_on_items is off).
bool center_on_items
Automatically pan to cross-probed items.
bool auto_highlight
Automatically turn on highlight mode in the target frame.
TRACK_CLEARANCE_MODE m_TrackClearance