KiCad PCB EDA Suite
pcb_calculator_frame.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) 1992-2015 jean-pierre.charras
5  * Copyright (C) 1992-2021 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 3
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 along
18  * with this program. If not, see <http://www.gnu.org/licenses/>.
19  */
20 #include <wx/menu.h>
21 #include <wx/msgdlg.h>
22 #include <wx/notebook.h>
23 #include <wx/sizer.h>
24 
25 #include <typeinfo>
26 
27 #include <bitmaps.h>
28 #include <bitmap_store.h>
30 #include <kiface_base.h>
31 
33 #include <pcb_calculator_frame.h>
35 
45 
46 
47 PCB_CALCULATOR_FRAME::PCB_CALCULATOR_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
48  KIWAY_PLAYER( aParent, wxID_ANY,
49  _( "PCB Calculator" ), // Window title
50  wxDefaultPosition,
51  wxSize( 646,361 ), // Default size
52  wxDEFAULT_FRAME_STYLE | wxRESIZE_BORDER | wxFULL_REPAINT_ON_RESIZE | wxTAB_TRAVERSAL,
53  wxT( "pcb_calculator" ) ), // Window name
54  m_lastNotebookPage( -1 ),
55  m_macHack( true )
56 {
57  SHAPE_POLY_SET dummy; // A ugly trick to force the linker to include
58  // some methods in code and avoid link errors
59 
60  SetKiway( this, aKiway );
61 
62  SetSizeHints( wxDefaultSize, wxDefaultSize );
63 
64  m_menubar = new wxMenuBar( 0 );
65  SetMenuBar( m_menubar );
66 
67  m_mainSizer = new wxBoxSizer( wxVERTICAL );
68  m_notebook = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
69 
70  m_mainSizer->Add( m_notebook, 1, wxEXPAND, 5 );
71 
72  SetSizer( m_mainSizer );
73  Layout();
74  Centre( wxBOTH );
75 
76  AddCalculator( new PANEL_REGULATOR( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ),
77  _( "Regulators" ) );
78  AddCalculator( new PANEL_ATTENUATORS( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ),
79  _( "RF Attenuators" ) );
80  AddCalculator( new PANEL_E_SERIE( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ),
81  _( "E-Series" ) );
82  AddCalculator( new PANEL_COLOR_CODE( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ),
83  _( "Color Code" ) );
84  AddCalculator( new PANEL_TRANSLINE( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ),
85  _( "TransLine ") );
86  AddCalculator( new PANEL_VIA_SIZE( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ),
87  _( "Via Size" ) );
88  AddCalculator( new PANEL_TRACK_WIDTH( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ),
89  _( "Track Width" ) );
90  AddCalculator( new PANEL_ELECTRICAL_SPACING( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ),
91  _( "Electrical Spacing" ) );
92  AddCalculator( new PANEL_BOARD_CLASS( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ),
93  _("Board Classes") );
94 
95  LoadSettings( config() );
96 
97  if( PANEL_REGULATOR* regPanel = GetCalculator<PANEL_REGULATOR>() )
98  regPanel->ReadDataFile();
99 
100  // Give an icon
101  wxIcon icon;
102  wxIconBundle icon_bundle;
103 
104  icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_pcbcalculator ) );
105  icon_bundle.AddIcon( icon );
106  icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_pcbcalculator_32 ) );
107  icon_bundle.AddIcon( icon );
108  icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_pcbcalculator_16 ) );
109  icon_bundle.AddIcon( icon );
110 
111  SetIcons( icon_bundle );
112 
113  GetSizer()->SetSizeHints( this );
114 
115  // Set previous size and position
116  SetSize( m_framePos.x, m_framePos.y, m_frameSize.x, m_frameSize.y );
117 
118  if( m_framePos == wxDefaultPosition )
119  Centre();
120 
121  // Connect Events
122  Bind( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( PCB_CALCULATOR_FRAME::OnClosePcbCalc ), this );
123  Bind( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( PCB_CALCULATOR_FRAME::OnUpdateUI ), this );
124 
125  Bind( wxEVT_SYS_COLOUR_CHANGED,
126  wxSysColourChangedEventHandler( PCB_CALCULATOR_FRAME::onThemeChanged ), this );
127 }
128 
129 
131 {
132  // This needed for OSX: avoids further OnDraw processing after this destructor and before
133  // the native window is destroyed
134  this->Freeze();
135 }
136 
137 
138 void PCB_CALCULATOR_FRAME::AddCalculator( CALCULATOR_PANEL *aPanel, const wxString& panelUIName )
139 {
140  // Update internal structures
141  m_panels.push_back( aPanel );
142  m_panelTypes[ typeid( *aPanel ).hash_code() ] = aPanel;
143 
144  m_notebook->AddPage( aPanel, panelUIName, false );
145 }
146 
147 
148 void PCB_CALCULATOR_FRAME::onThemeChanged( wxSysColourChangedEvent& aEvent )
149 {
150  // Force the bitmaps to refresh
152 
153  // Update the panels
154  for( auto& panel : m_panels )
155  panel->ThemeChanged();
156 
157  aEvent.Skip();
158 }
159 
160 
161 void PCB_CALCULATOR_FRAME::OnUpdateUI( wxUpdateUIEvent& event )
162 {
163  if( m_notebook->GetSelection() != m_lastNotebookPage )
164  {
165  // Kick all the things that wxWidgets can't seem to redraw on its own.
166  // This is getting seriously ridiculous....
167  PANEL_TRANSLINE* translinePanel = GetCalculator<PANEL_TRANSLINE>();
168  PANEL_ATTENUATORS* attenPanel = GetCalculator<PANEL_ATTENUATORS>();
169  PANEL_VIA_SIZE* viaSizePanel = GetCalculator<PANEL_VIA_SIZE>();
170  PANEL_REGULATOR* regulPanel = GetCalculator<PANEL_REGULATOR>();
171  PANEL_ELECTRICAL_SPACING* elecSpacingPanel = GetCalculator<PANEL_ELECTRICAL_SPACING>();
172 
173  wxASSERT( translinePanel );
174  wxASSERT( attenPanel );
175  wxASSERT( viaSizePanel );
176  wxASSERT( regulPanel );
177  wxASSERT( elecSpacingPanel );
178 
179  {
180  wxCommandEvent event2( wxEVT_RADIOBUTTON );
181  event2.SetEventObject( translinePanel->GetTranslineSelector() );
182  event2.SetInt( translinePanel->GetCurrTransLineType() );
183 
184  translinePanel->GetTranslineSelector()->Command( event2 );
185  }
186 
187  for( int i = 0; i < attenPanel->m_AttenuatorList.size(); ++i )
188  {
189  if( attenPanel->m_AttenuatorList[i] == attenPanel->m_CurrAttenuator )
190  {
191  wxCommandEvent event2( wxEVT_RADIOBUTTON );
192  event2.SetEventObject( attenPanel->GetAttenuatorsSelector() );
193  event2.SetInt( i );
194 
195  attenPanel->GetAttenuatorsSelector()->Command( event2 );
196  break;
197  }
198  }
199 
200  attenPanel->UpdateUI();
201  viaSizePanel->Layout();
202  regulPanel->Layout();
203 
204  // Until it's shown on screen the above won't work; but doing it anyway at least keeps
205  // putting new OnUpdateUI events into the queue until it *is* shown on screen.
206  if( m_notebook->IsShownOnScreen() )
207  {
208  // Work around an OSX bug where the wxGrid children don't get placed correctly until
209  // the first resize event.
210 #ifdef __WXMAC__
211  if( m_macHack )
212  {
213  wxSize pageSize = elecSpacingPanel->GetSize();
214 
215  pageSize.x -= 100;
216  elecSpacingPanel->SetSize( pageSize );
217  elecSpacingPanel->Layout();
218 
219  pageSize.x += 100;
220  elecSpacingPanel->SetSize( pageSize );
221  elecSpacingPanel->Layout();
222 
223  m_macHack = false;
224  }
225 #endif
226 
227  m_lastNotebookPage = m_notebook->GetSelection();
228  }
229  }
230 }
231 
232 
233 void PCB_CALCULATOR_FRAME::OnClosePcbCalc( wxCloseEvent& event )
234 {
235  PANEL_REGULATOR* regPanel = GetCalculator<PANEL_REGULATOR>();
236 
237  wxASSERT( regPanel );
238 
239  if( regPanel->m_RegulatorListChanged )
240  {
241  wxString msg;
242  wxString title = _( "Write Data Failed" );
243 
244  if( regPanel->GetDataFilename().IsEmpty() )
245  {
246  msg = _( "No data filename to save modifications.\n"
247  "Do you want to exit and abandon your changes?" );
248 
249  if( wxMessageBox( msg, title, wxYES_NO | wxICON_QUESTION ) == wxNO )
250  return;
251  }
252  else
253  {
254  if( !regPanel->WriteDataFile() )
255  {
256  msg.Printf( _( "Unable to write file '%s'\n"
257  "Do you want to exit and abandon your changes?"),
258  regPanel->GetDataFilename() );
259 
260  if( wxMessageBox( msg, title, wxYES_NO | wxICON_ERROR ) == wxNO )
261  return;
262  }
263  }
264  }
265 
266  event.Skip();
267 }
268 
269 
271 {
272  if( aCfg == nullptr )
273  return;
274 
276 
277  PCB_CALCULATOR_SETTINGS* cfg = static_cast<PCB_CALCULATOR_SETTINGS*>( aCfg );
278 
279  m_notebook->ChangeSelection( cfg->m_LastPage );
280 
281  for( auto& panel : m_panels )
282  panel->LoadSettings( cfg );
283 }
284 
285 
287 {
288  if( aCfg == nullptr )
289  return;
290 
292 
293  // Save current parameters values in config.
294  auto cfg = dynamic_cast<PCB_CALCULATOR_SETTINGS*>( Kiface().KifaceSettings() );
295 
296  if( cfg )
297  {
298  cfg->m_LastPage = m_notebook->GetSelection();
299 
300  for( auto& panel : m_panels )
301  panel->SaveSettings( cfg );
302  }
303 
304 }
A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of a KiCad project.
Definition: kiway_player.h:64
void SetKiway(wxWindow *aDest, KIWAY *aKiway)
It is only used for debugging, since "this" is not a wxWindow*.
void AddCalculator(CALCULATOR_PANEL *aPanel, const wxString &panelUIName)
virtual APP_SETTINGS_BASE * config() const
Returns the settings object used in SaveSettings(), and is overloaded in KICAD_MANAGER_FRAME.
void OnClosePcbCalc(wxCloseEvent &event)
virtual void SaveSettings(APP_SETTINGS_BASE *aCfg)
Save common frame parameters to a configuration data file.
PCB_CALCULATOR_FRAME(KIWAY *aKiway, wxWindow *aParent)
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
std::map< std::size_t, CALCULATOR_PANEL * > m_panelTypes
std::vector< CALCULATOR_PANEL * > m_panels
std::vector< ATTENUATOR * > m_AttenuatorList
static LIB_SYMBOL * dummy()
Used to draw a dummy shape when a LIB_SYMBOL is not found in library.
Definition: sch_symbol.cpp:72
APP_SETTINGS_BASE is a settings class that should be derived for each standalone KiCad application.
Definition: app_settings.h:99
Represent a set of closed polygons.
void SaveSettings(APP_SETTINGS_BASE *aCfg) override
Save common frame parameters to a configuration data file.
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
Definition: kiway.h:260
const wxString GetDataFilename()
#define _(s)
void ThemeChanged()
Notifies the store that the icon theme has been changed by the user, so caches must be invalidated.
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:105
void OnUpdateUI(wxUpdateUIEvent &event)
void LoadSettings(APP_SETTINGS_BASE *aCfg) override
Load common frame parameters from a configuration file.
TRANSLINE_TYPE_ID GetCurrTransLineType()
wxRadioBox * GetTranslineSelector()
ATTENUATOR * m_CurrAttenuator
void onThemeChanged(wxSysColourChangedEvent &aEvent)
wxRadioBox * GetAttenuatorsSelector()
virtual void LoadSettings(APP_SETTINGS_BASE *aCfg)
Load common frame parameters from a configuration file.
BITMAP_STORE * GetBitmapStore()
Definition: bitmap.cpp:93