KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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-2023 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/msgdlg.h>
21#include <wx/treebook.h>
22#include <wx/sizer.h>
23
24#include <typeinfo>
25
26#include <bitmaps.h>
27#include <bitmap_store.h>
29#include <kiface_base.h>
30#include <tool/actions.h>
31#include <tool/tool_manager.h>
33#include <tool/common_control.h>
38
53#include "widgets/wx_menubar.h"
54
55
56BEGIN_EVENT_TABLE( PCB_CALCULATOR_FRAME, EDA_BASE_FRAME )
57 EVT_MENU( wxID_CLOSE, PCB_CALCULATOR_FRAME::OnExit )
58 EVT_MENU( wxID_EXIT, PCB_CALCULATOR_FRAME::OnExit )
59END_EVENT_TABLE()
60
61
62PCB_CALCULATOR_FRAME::PCB_CALCULATOR_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
63 KIWAY_PLAYER( aKiway, aParent, FRAME_CALC, _( "Calculator Tools" ), wxDefaultPosition,
64 wxDefaultSize,
65 wxDEFAULT_FRAME_STYLE|wxRESIZE_BORDER|wxFULL_REPAINT_ON_RESIZE|wxTAB_TRAVERSAL,
66 wxT( "calculator_tools" ), unityScale ),
67 m_lastNotebookPage( -1 )
68{
69 m_aboutTitle = _HKI( "KiCad Calculator Tools" );
70
71 SHAPE_POLY_SET dummy; // A ugly trick to force the linker to include
72 // some methods in code and avoid link errors
73
74 SetSizeHints( wxDefaultSize, wxDefaultSize );
75
76 m_mainSizer = new wxBoxSizer( wxVERTICAL );
77
78 m_treebook = new wxTreebook( this, wxID_ANY );
79 m_treebook->SetFont( KIUI::GetControlFont( this ) );
80 m_mainSizer->Add( m_treebook, 1, wxEXPAND | wxLEFT | wxTOP, 0 );
81
82 SetSizer( m_mainSizer );
83 Layout();
84 Centre( wxBOTH );
85
86 loadPages();
87
88 // Give an icon
89 wxIcon icon;
90 wxIconBundle icon_bundle;
91
92 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_pcbcalculator, 48 ) );
93 icon_bundle.AddIcon( icon );
94 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_pcbcalculator, 128 ) );
95 icon_bundle.AddIcon( icon );
96 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_pcbcalculator, 256 ) );
97 icon_bundle.AddIcon( icon );
98 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_pcbcalculator_32 ) );
99 icon_bundle.AddIcon( icon );
100 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_pcbcalculator_16 ) );
101 icon_bundle.AddIcon( icon );
102
103 SetIcons( icon_bundle );
104
105 m_toolManager = new TOOL_MANAGER;
106 m_toolManager->SetEnvironment( nullptr, nullptr, nullptr, config(), this );
107
108 m_toolDispatcher = new TOOL_DISPATCHER( m_toolManager );
109
110 // Register tools
111 m_toolManager->RegisterTool( new COMMON_CONTROL );
112 m_toolManager->RegisterTool( new PCB_CALCULATOR_CONTROL );
113 m_toolManager->InitTools();
114
115 ReCreateMenuBar();
116
117 GetSizer()->SetSizeHints( this );
118
119 // Set previous size and position
120 SetSize( m_framePos.x, m_framePos.y, m_frameSize.x, m_frameSize.y );
121
122 if( m_framePos == wxDefaultPosition )
123 Centre();
124
125 // Expand treebook to show all options:
126 for( size_t pageId = 0; pageId < m_treebook->GetPageCount(); pageId++ )
127 m_treebook->ExpandNode( pageId );
128
129 // Connect Events
130 Bind( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( PCB_CALCULATOR_FRAME::OnClosePcbCalc ), this );
131 Bind( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( PCB_CALCULATOR_FRAME::OnUpdateUI ), this );
132
133 Bind( wxEVT_SYS_COLOUR_CHANGED,
134 wxSysColourChangedEventHandler( PCB_CALCULATOR_FRAME::onThemeChanged ), this );
135
136 m_treebook->Connect( wxEVT_COMMAND_TREEBOOK_PAGE_CHANGED, wxTreebookEventHandler(
137 PCB_CALCULATOR_FRAME::OnPageChanged ), nullptr, this );
138}
139
140
142{
143 m_treebook->Disconnect( wxEVT_COMMAND_TREEBOOK_PAGE_CHANGED, wxTreebookEventHandler(
144 PCB_CALCULATOR_FRAME::OnPageChanged ), nullptr, this );
145 // This needed for OSX: avoids further OnDraw processing after this destructor and before
146 // the native window is destroyed
147 this->Freeze();
148}
149
150
151void PCB_CALCULATOR_FRAME::OnExit( wxCommandEvent& aEvent )
152{
153 if( aEvent.GetId() == wxID_EXIT )
154 Kiway().OnKiCadExit();
155
156 if( aEvent.GetId() == wxID_CLOSE || Kiface().IsSingle() )
157 Close( false );
158}
159
160
162{
163 m_treebook->AddPage( nullptr, _( "General system design" ) );
164
165 AddCalculator( new PANEL_REGULATOR( m_treebook ), _( "Regulators" ) );
166 AddCalculator( new PANEL_R_CALCULATOR( m_treebook ), _( "Resistor Calculator" ) );
167
168 m_treebook->AddPage( nullptr, _( "Power, current and isolation" ) );
169
170 AddCalculator( new PANEL_ELECTRICAL_SPACING( m_treebook ), _( "Electrical Spacing" ) );
171 AddCalculator( new PANEL_VIA_SIZE( m_treebook ), _( "Via Size" ) );
172 AddCalculator( new PANEL_TRACK_WIDTH( m_treebook ), _( "Track Width" ) );
173 AddCalculator( new PANEL_FUSING_CURRENT( m_treebook ), _( "Fusing Current" ) );
174 AddCalculator( new PANEL_CABLE_SIZE( m_treebook ), _( "Cable Size" ) );
175
176 m_treebook->AddPage( nullptr, _( "High Speed" ) );
177
178 AddCalculator( new PANEL_WAVELENGTH( m_treebook ), _( "Wavelength" ) );
179 AddCalculator( new PANEL_RF_ATTENUATORS( m_treebook ), _( "RF Attenuators" ) );
180 AddCalculator( new PANEL_TRANSLINE( m_treebook ), _( "Transmission Lines") );
181
182 m_treebook->AddPage( nullptr, _( "Memo" ) );
183
184 AddCalculator( new PANEL_ESERIES_DISPLAY( m_treebook ), _( "E-Series" ) );
185 AddCalculator( new PANEL_COLOR_CODE( m_treebook ), _( "Color Code" ) );
186 AddCalculator( new PANEL_BOARD_CLASS( m_treebook ), _( "Board Classes" ) );
187 AddCalculator( new PANEL_GALVANIC_CORROSION( m_treebook ), _( "Galvanic Corrosion" ) );
188
189 LoadSettings( config() );
190
191 if( PANEL_REGULATOR* regPanel = GetCalculator<PANEL_REGULATOR>() )
192 regPanel->ReadDataFile();
193}
194
195
197{
199 EDA_BASE_FRAME* base_frame = dynamic_cast<EDA_BASE_FRAME*>( this );
200
201 // base_frame == nullptr should not happen, but it makes Coverity happy
202 wxCHECK( base_frame, /* void */ );
203
204 // wxWidgets handles the OSX Application menu behind the scenes, but that means
205 // we always have to start from scratch with a new wxMenuBar.
206 wxMenuBar* oldMenuBar = base_frame->GetMenuBar();
207 WX_MENUBAR* menuBar = new WX_MENUBAR();
208
209 //-- File menu -----------------------------------------------------------
210 //
211 ACTION_MENU* fileMenu = new ACTION_MENU( false, tool );
212
213 fileMenu->AddClose( _( "Calculator Tools" ) );
214 fileMenu->AddQuit( _( "Calculator Tools" ) );
215
216 //-- Preferences menu -----------------------------------------------
217 //
218 ACTION_MENU* prefsMenu = new ACTION_MENU( false, tool );
219
220 prefsMenu->Add( ACTIONS::openPreferences );
221
222 prefsMenu->AppendSeparator();
223 AddMenuLanguageList( prefsMenu, tool );
224
225
226 //-- Menubar -------------------------------------------------------------
227 //
228 menuBar->Append( fileMenu, _( "&File" ) );
229 menuBar->Append( prefsMenu, _( "&Preferences" ) );
230 base_frame->AddStandardHelpMenu( menuBar );
231
232 base_frame->SetMenuBar( menuBar );
233 delete oldMenuBar;
234}
235
236
238{
240
241 SetTitle( _( "Calculator Tools" ) );
242
243 SaveSettings( config() );
244 Freeze();
245
246 int page = m_treebook->GetSelection();
247 m_treebook->DeleteAllPages();
248 m_panels.clear();
249
250 loadPages();
251 Layout();
252
253 m_treebook->SetSelection( page );
254 LoadSettings( config() );
255
256 Thaw();
257 Refresh();
258}
259
260
261void PCB_CALCULATOR_FRAME::OnPageChanged ( wxTreebookEvent& aEvent )
262{
263 int page = aEvent.GetSelection();
264
265 // If the selected page is a top level page
266 if ( m_treebook->GetPageParent( page ) == wxNOT_FOUND )
267 {
268 m_treebook->ExpandNode( page );
269
270 // Select the first child
271 if( page + 1 < m_treebook->GetPageCount() )
272 m_treebook->ChangeSelection( page + 1 );
273 }
274}
275
276
277void PCB_CALCULATOR_FRAME::AddCalculator( CALCULATOR_PANEL *aPanel, const wxString& panelUIName )
278{
279 // Update internal structures
280 m_panels.push_back( aPanel );
281 m_panelTypes[ typeid( *aPanel ).hash_code() ] = aPanel;
282
283 m_treebook->AddSubPage( aPanel, panelUIName );
284}
285
286
287void PCB_CALCULATOR_FRAME::onThemeChanged( wxSysColourChangedEvent& aEvent )
288{
289 // Force the bitmaps to refresh
291
292 // Update the panels
293 for( auto& panel : m_panels )
294 panel->ThemeChanged();
295
296 aEvent.Skip();
297}
298
299
300void PCB_CALCULATOR_FRAME::OnUpdateUI( wxUpdateUIEvent& event )
301{
302 if( m_treebook->GetSelection() != m_lastNotebookPage )
303 {
304 // Kick all the things that wxWidgets can't seem to redraw on its own.
305 // This is getting seriously ridiculous....
306 PANEL_TRANSLINE* translinePanel = GetCalculator<PANEL_TRANSLINE>();
307 PANEL_RF_ATTENUATORS* attenPanel = GetCalculator<PANEL_RF_ATTENUATORS>();
308 PANEL_VIA_SIZE* viaSizePanel = GetCalculator<PANEL_VIA_SIZE>();
309 PANEL_REGULATOR* regulPanel = GetCalculator<PANEL_REGULATOR>();
310 PANEL_ELECTRICAL_SPACING* elecSpacingPanel = GetCalculator<PANEL_ELECTRICAL_SPACING>();
311
312 wxASSERT( translinePanel );
313 wxASSERT( attenPanel );
314 wxASSERT( viaSizePanel );
315 wxASSERT( regulPanel );
316 wxASSERT( elecSpacingPanel );
317
318 {
319 wxCommandEvent event2( wxEVT_RADIOBUTTON );
320 event2.SetEventObject( translinePanel->GetTranslineSelector() );
321 event2.SetInt( translinePanel->GetCurrTransLineType() );
322
323 translinePanel->GetTranslineSelector()->Command( event2 );
324 }
325
326 for( int i = 0; i < attenPanel->m_AttenuatorList.size(); ++i )
327 {
328 if( attenPanel->m_AttenuatorList[i] == attenPanel->m_CurrAttenuator )
329 {
330 wxCommandEvent event2( wxEVT_RADIOBUTTON );
331 event2.SetEventObject( attenPanel->GetAttenuatorsSelector() );
332 event2.SetInt( i );
333
334 attenPanel->GetAttenuatorsSelector()->Command( event2 );
335 break;
336 }
337 }
338
339 attenPanel->UpdateUI();
340 viaSizePanel->Layout();
341 regulPanel->Layout();
342
343 // Until it's shown on screen the above won't work; but doing it anyway at least keeps
344 // putting new OnUpdateUI events into the queue until it *is* shown on screen.
345 if( m_treebook->IsShownOnScreen() )
346 m_lastNotebookPage = m_treebook->GetSelection();
347 }
348}
349
350
351void PCB_CALCULATOR_FRAME::OnClosePcbCalc( wxCloseEvent& event )
352{
353 PANEL_REGULATOR* regPanel = GetCalculator<PANEL_REGULATOR>();
354
355 wxASSERT( regPanel );
356
357 if( regPanel->m_RegulatorListChanged )
358 {
359 wxString msg;
360 wxString title = _( "Write Data Failed" );
361
362 if( regPanel->GetDataFilename().IsEmpty() )
363 {
364 msg = _( "No data filename to save modifications.\n"
365 "Do you want to exit and abandon your changes?" );
366
367 if( wxMessageBox( msg, title, wxYES_NO | wxICON_QUESTION ) == wxNO )
368 return;
369 }
370 else
371 {
372 if( !regPanel->WriteDataFile() )
373 {
374 msg.Printf( _( "Unable to write file '%s'\n"
375 "Do you want to exit and abandon your changes?"),
376 regPanel->GetDataFilename() );
377
378 if( wxMessageBox( msg, title, wxYES_NO | wxICON_ERROR ) == wxNO )
379 return;
380 }
381 }
382 }
383
384 event.Skip();
385}
386
387
389{
390 if( aCfg == nullptr )
391 return;
392
394
395 PCB_CALCULATOR_SETTINGS* cfg = static_cast<PCB_CALCULATOR_SETTINGS*>( aCfg );
396
397 m_treebook->ChangeSelection( cfg->m_LastPage );
398
399 for( CALCULATOR_PANEL* panel : m_panels )
400 panel->LoadSettings( cfg );
401}
402
403
405{
406 if( aCfg == nullptr )
407 return;
408
410
411 // Save current parameters values in config.
412 auto cfg = dynamic_cast<PCB_CALCULATOR_SETTINGS*>( Kiface().KifaceSettings() );
413
414 if( cfg )
415 {
416 cfg->m_LastPage = m_treebook->GetSelection();
417
418 for( CALCULATOR_PANEL* panel : m_panels )
419 panel->SaveSettings( cfg );
420 }
421
422}
constexpr EDA_IU_SCALE unityScale
Definition: base_units.h:112
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
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:104
BITMAP_STORE * GetBitmapStore()
Definition: bitmap.cpp:92
@ icon_pcbcalculator_16
@ icon_pcbcalculator_32
@ icon_pcbcalculator
static TOOL_ACTION openPreferences
Definition: actions.h:211
Defines the structure of a menu based on ACTIONs.
Definition: action_menu.h:49
void AddClose(const wxString &aAppname="")
Add a standard close item to the menu with the accelerator key CTRL-W.
void AddQuit(const wxString &aAppname="")
Add a standard Quit item to the menu.
wxMenuItem * Add(const wxString &aLabel, int aId, BITMAPS aIcon)
Add a wxWidgets-style entry to the menu.
APP_SETTINGS_BASE is a settings class that should be derived for each standalone KiCad application.
Definition: app_settings.h:92
void ThemeChanged()
Notifies the store that the icon theme has been changed by the user, so caches must be invalidated.
Handle actions that are shared between different applications.
The base frame for deriving all KiCad main window classes.
virtual APP_SETTINGS_BASE * config() const
Returns the settings object used in SaveSettings(), and is overloaded in KICAD_MANAGER_FRAME.
void ShowChangedLanguage() override
Redraw the menus and what not in current language.
void AddMenuLanguageList(ACTION_MENU *aMasterMenu, TOOL_INTERACTIVE *aControlTool)
Function AddMenuLanguageList creates a menu list for language choice, and add it as submenu to Master...
virtual void LoadSettings(APP_SETTINGS_BASE *aCfg)
Load common frame parameters from a configuration file.
virtual void SaveSettings(APP_SETTINGS_BASE *aCfg)
Save common frame parameters to a configuration data file.
APP_SETTINGS_BASE * KifaceSettings() const
Definition: kiface_base.h:95
KIWAY & Kiway() const
Return a reference to the KIWAY that this object has an opportunity to participate in.
Definition: kiway_holder.h:53
A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of a KiCad project.
Definition: kiway_player.h:67
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
Definition: kiway.h:279
void OnKiCadExit()
Definition: kiway.cpp:743
const wxString GetDataFilename()
std::vector< ATTENUATOR * > m_AttenuatorList
wxRadioBox * GetAttenuatorsSelector()
wxRadioBox * GetTranslineSelector()
TRANSLINE_TYPE_ID GetCurrTransLineType()
Handle actions for the various symbol editor and viewers.
PCB calculator the main frame.
void doReCreateMenuBar() override
void OnPageChanged(wxTreebookEvent &aEvent)
void ShowChangedLanguage() override
Redraw the menus and what not in current language.
std::vector< CALCULATOR_PANEL * > m_panels
void OnUpdateUI(wxUpdateUIEvent &event)
void onThemeChanged(wxSysColourChangedEvent &aEvent)
void LoadSettings(APP_SETTINGS_BASE *aCfg) override
Load common frame parameters from a configuration file.
void OnExit(wxCommandEvent &aEvent)
Event handler for the wxID_EXIT and wxID_CLOSE events.
void OnClosePcbCalc(wxCloseEvent &event)
void AddCalculator(CALCULATOR_PANEL *aPanel, const wxString &panelUIName)
void SaveSettings(APP_SETTINGS_BASE *aCfg) override
Save common frame parameters to a configuration data file.
std::map< std::size_t, CALCULATOR_PANEL * > m_panelTypes
Represent a set of closed polygons.
TOOL_MANAGER * m_toolManager
Definition: tools_holder.h:167
Master controller class:
Definition: tool_manager.h:57
void SetEnvironment(EDA_ITEM *aModel, KIGFX::VIEW *aView, KIGFX::VIEW_CONTROLS *aViewControls, APP_SETTINGS_BASE *aSettings, TOOLS_HOLDER *aFrame)
Set the work environment (model, view, view controls and the parent window).
Wrapper around a wxMenuBar object that prevents the accelerator table from being used.
Definition: wx_menubar.h:47
#define _HKI(x)
#define _(s)
@ FRAME_CALC
Definition: frame_type.h:63
wxFont GetControlFont(wxWindow *aWindow)
Definition: ui_common.cpp:157
void Refresh()
Update the board display after modifying it by a python script (note: it is automatically called by a...
std::vector< FAB_LAYER_COLOR > dummy