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 The 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
18 * along with this program. If not, see <https://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 <sstream>
27
28#include <bitmaps.h>
29#include <bitmap_store.h>
31#include <kiface_base.h>
32#include <kiway_mail.h>
33#include <tool/actions.h>
34#include <tool/tool_manager.h>
36#include <tool/common_control.h>
40
56#include "widgets/wx_menubar.h"
57
58
59BEGIN_EVENT_TABLE( PCB_CALCULATOR_FRAME, KIWAY_PLAYER )
62END_EVENT_TABLE()
63
64
65PCB_CALCULATOR_FRAME::PCB_CALCULATOR_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
66 KIWAY_PLAYER( aKiway, aParent, FRAME_CALC, _( "Calculator Tools" ), wxDefaultPosition,
67 wxDefaultSize,
68 wxDEFAULT_FRAME_STYLE|wxRESIZE_BORDER|wxFULL_REPAINT_ON_RESIZE|wxTAB_TRAVERSAL,
69 wxT( "calculator_tools" ), unityScale ),
71{
72 m_aboutTitle = _HKI( "KiCad Calculator Tools" );
73
74 SHAPE_POLY_SET dummy; // A ugly trick to force the linker to include
75 // some methods in code and avoid link errors
76
77 SetSizeHints( wxDefaultSize, wxDefaultSize );
78
79 m_mainSizer = new wxBoxSizer( wxVERTICAL );
80
81 m_treebook = new wxTreebook( this, wxID_ANY );
82 m_treebook->SetFont( KIUI::GetControlFont( this ) );
83 m_mainSizer->Add( m_treebook, 1, wxEXPAND | wxLEFT | wxTOP, 0 );
84
85 SetSizer( m_mainSizer );
86 Layout();
87 Centre( wxBOTH );
88
89 loadPages();
90
91 // Give an icon
92 wxIcon icon;
93 wxIconBundle icon_bundle;
94
95 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_pcbcalculator, 48 ) );
96 icon_bundle.AddIcon( icon );
97 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_pcbcalculator, 128 ) );
98 icon_bundle.AddIcon( icon );
99 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_pcbcalculator, 256 ) );
100 icon_bundle.AddIcon( icon );
101 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_pcbcalculator_32 ) );
102 icon_bundle.AddIcon( icon );
103 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_pcbcalculator_16 ) );
104 icon_bundle.AddIcon( icon );
105
106 SetIcons( icon_bundle );
107
109 m_toolManager->SetEnvironment( nullptr, nullptr, nullptr, config(), this );
110
112
113 // Register tools
114 m_toolManager->RegisterTool( new COMMON_CONTROL );
115 m_toolManager->InitTools();
116
119
120 GetSizer()->SetSizeHints( this );
121
122 // Set previous size and position
123 SetSize( m_framePos.x, m_framePos.y, m_frameSize.x, m_frameSize.y );
124
125 if( m_framePos == wxDefaultPosition )
126 Centre();
127
128 // Expand treebook to show all options:
129 for( size_t pageId = 0; pageId < m_treebook->GetPageCount(); pageId++ )
130 m_treebook->ExpandNode( pageId );
131
132 // Connect Events
133 Bind( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( PCB_CALCULATOR_FRAME::OnClosePcbCalc ), this );
134 Bind( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( PCB_CALCULATOR_FRAME::OnUpdateUI ), this );
135
136 Bind( wxEVT_SYS_COLOUR_CHANGED,
137 wxSysColourChangedEventHandler( PCB_CALCULATOR_FRAME::onThemeChanged ), this );
138
139 m_treebook->Connect( wxEVT_COMMAND_TREEBOOK_PAGE_CHANGED, wxTreebookEventHandler(
140 PCB_CALCULATOR_FRAME::OnPageChanged ), nullptr, this );
141}
142
143
145{
146 m_treebook->Disconnect( wxEVT_COMMAND_TREEBOOK_PAGE_CHANGED, wxTreebookEventHandler(
147 PCB_CALCULATOR_FRAME::OnPageChanged ), nullptr, this );
148 // This needed for OSX: avoids further OnDraw processing after this destructor and before
149 // the native window is destroyed
150 this->Freeze();
151
152 // Clean up the tool framework
153 delete m_toolManager;
154 delete m_toolDispatcher;
155}
156
157
158void PCB_CALCULATOR_FRAME::OnExit( wxCommandEvent& aEvent )
159{
160 Close( false );
161}
162
163
165{
166 m_treebook->AddPage( nullptr, _( "General system design" ) );
167
168 AddCalculator( new PANEL_REGULATOR( m_treebook ), _( "Regulators" ) );
169 AddCalculator( new PANEL_R_CALCULATOR( m_treebook ), _( "Resistor Calculator" ) );
170
171 m_treebook->AddPage( nullptr, _( "Footprint design" ) );
172
173 AddCalculator( new PANEL_PTH_SIZE( m_treebook ), _( "Through-hole Size" ) );
174
175 m_treebook->AddPage( nullptr, _( "Power, current and isolation" ) );
176
177 AddCalculator( new PANEL_ELECTRICAL_SPACING( m_treebook ), _( "Electrical Spacing" ) );
178 AddCalculator( new PANEL_VIA_SIZE( m_treebook ), _( "Via Size" ) );
179 AddCalculator( new PANEL_TRACK_WIDTH( m_treebook ), _( "Track Width" ) );
180 AddCalculator( new PANEL_FUSING_CURRENT( m_treebook ), _( "Fusing Current" ) );
181 AddCalculator( new PANEL_CABLE_SIZE( m_treebook ), _( "Cable Size" ) );
182
183 m_treebook->AddPage( nullptr, _( "High Speed" ) );
184
185 AddCalculator( new PANEL_WAVELENGTH( m_treebook ), _( "Wavelength" ) );
186 AddCalculator( new PANEL_RF_ATTENUATORS( m_treebook ), _( "RF Attenuators" ) );
187 AddCalculator( new PANEL_TRANSLINE( m_treebook ), _( "Transmission Lines") );
188
189 m_treebook->AddPage( nullptr, _( "Memo" ) );
190
191 AddCalculator( new PANEL_ESERIES_DISPLAY( m_treebook ), _( "E-Series" ) );
192 AddCalculator( new PANEL_COLOR_CODE( m_treebook ), _( "Color Code" ) );
193 AddCalculator( new PANEL_BOARD_CLASS( m_treebook ), _( "Board Classes" ) );
194 AddCalculator( new PANEL_GALVANIC_CORROSION( m_treebook ), _( "Galvanic Corrosion" ) );
195
196 LoadSettings( config() );
197
199 regPanel->ReadDataFile();
200}
201
202
204{
205 COMMON_CONTROL* tool = m_toolManager->GetTool<COMMON_CONTROL>();
206 EDA_BASE_FRAME* base_frame = dynamic_cast<EDA_BASE_FRAME*>( this );
207
208 // base_frame == nullptr should not happen, but it makes Coverity happy
209 wxCHECK( base_frame, /* void */ );
210
211 // wxWidgets handles the OSX Application menu behind the scenes, but that means
212 // we always have to start from scratch with a new wxMenuBar.
213 wxMenuBar* oldMenuBar = base_frame->GetMenuBar();
214 WX_MENUBAR* menuBar = new WX_MENUBAR();
215
216 //-- File menu -----------------------------------------------------------
217 //
218 ACTION_MENU* fileMenu = new ACTION_MENU( false, tool );
219
220 fileMenu->AddClose( _( "Calculator Tools" ) );
221 fileMenu->AddQuit( _( "Calculator Tools" ) );
222
223 //-- Preferences menu -----------------------------------------------
224 //
225 ACTION_MENU* prefsMenu = new ACTION_MENU( false, tool );
226
227 prefsMenu->Add( ACTIONS::openPreferences );
228
229 prefsMenu->AppendSeparator();
230 AddMenuLanguageList( prefsMenu, tool );
231
232
233 //-- Menubar -------------------------------------------------------------
234 //
235 menuBar->Append( fileMenu, _( "&File" ) );
236 menuBar->Append( prefsMenu, _( "&Preferences" ) );
237 base_frame->AddStandardHelpMenu( menuBar );
238
239 base_frame->SetMenuBar( menuBar );
240 delete oldMenuBar;
241}
242
243
245{
247
248 SetTitle( _( "Calculator Tools" ) );
249
250 SaveSettings( config() );
251 Freeze();
252
253 int page = m_treebook->GetSelection();
254 m_treebook->DeleteAllPages();
255 m_panels.clear();
256
257 loadPages();
258 Layout();
259
260 m_treebook->SetSelection( page );
261 LoadSettings( config() );
262
263 Thaw();
264 Refresh();
265}
266
267
268void PCB_CALCULATOR_FRAME::OnPageChanged ( wxTreebookEvent& aEvent )
269{
270 int page = aEvent.GetSelection();
271
272 // If the selected page is a top level page
273 if ( m_treebook->GetPageParent( page ) == wxNOT_FOUND )
274 {
275 m_treebook->ExpandNode( page );
276
277 // Select the first child
278 if( page + 1 < m_treebook->GetPageCount() )
279 m_treebook->ChangeSelection( page + 1 );
280 }
281}
282
283
284void PCB_CALCULATOR_FRAME::AddCalculator( CALCULATOR_PANEL *aPanel, const wxString& panelUIName )
285{
286 // Update internal structures
287 m_panels.push_back( aPanel );
288 m_panelTypes[ typeid( *aPanel ).hash_code() ] = aPanel;
289
290 m_treebook->AddSubPage( aPanel, panelUIName );
291}
292
293
295{
296 for( size_t i = 0; i < m_treebook->GetPageCount(); ++i )
297 {
298 if( m_treebook->GetPage( i ) == aPage )
299 {
300 const int pageIndex = static_cast<int>( i );
301 const int parentIndex = m_treebook->GetPageParent( pageIndex );
302
303 if( parentIndex != wxNOT_FOUND )
304 m_treebook->ExpandNode( parentIndex );
305
306 m_treebook->SetSelection( pageIndex );
307 break;
308 }
309 }
310}
311
312
314{
315 if( aEvent.Command() != MAIL_CALC_SHOW )
316 return;
317
318
319 // Decode trhe payload: JSON
320 const std::string& payloadStr = aEvent.GetPayload();
321 nlohmann::json payload = nlohmann::json::parse( payloadStr, nullptr, false );
322
323 const std::string pageName = payload.value( "page", "" );
324
325 if( pageName.empty() )
326 return;
327
328 wxWindow* shownPanel = nullptr;
329
330 if( pageName == "pth_size" )
331 {
333 // Any dedicated setup would be here
334 shownPanel = pthPanel;
335 }
336 else
337 {
338 // Unknown page name, do nothing
339 }
340
341 if( shownPanel )
342 showCalculatorPage( shownPanel );
343}
344
345
346void PCB_CALCULATOR_FRAME::onThemeChanged( wxSysColourChangedEvent& aEvent )
347{
348 // Force the bitmaps to refresh
350
351 // Update the panels
352 for( auto& panel : m_panels )
353 panel->ThemeChanged();
354
355 aEvent.Skip();
356}
357
358
359void PCB_CALCULATOR_FRAME::OnUpdateUI( wxUpdateUIEvent& event )
360{
361 if( m_treebook->GetSelection() != m_lastNotebookPage )
362 {
363 // Kick all the things that wxWidgets can't seem to redraw on its own.
364 // This is getting seriously ridiculous....
369
370 wxASSERT( translinePanel );
371 wxASSERT( attenPanel );
372 wxASSERT( viaSizePanel );
373 wxASSERT( regulPanel );
374
375 {
376 wxCommandEvent event2( wxEVT_RADIOBUTTON );
377 event2.SetEventObject( translinePanel->GetTranslineSelector() );
378 event2.SetInt( translinePanel->GetCurrTransLineType() );
379
380 translinePanel->GetTranslineSelector()->Command( event2 );
381 }
382
383 for( int i = 0; i < attenPanel->m_AttenuatorList.size(); ++i )
384 {
385 if( attenPanel->m_AttenuatorList[i] == attenPanel->m_CurrAttenuator )
386 {
387 wxCommandEvent event2( wxEVT_RADIOBUTTON );
388 event2.SetEventObject( attenPanel->GetAttenuatorsSelector() );
389 event2.SetInt( i );
390
391 attenPanel->GetAttenuatorsSelector()->Command( event2 );
392 break;
393 }
394 }
395
396 attenPanel->UpdateUI();
397 viaSizePanel->Layout();
398 regulPanel->Layout();
399
400 // Until it's shown on screen the above won't work; but doing it anyway at least keeps
401 // putting new OnUpdateUI events into the queue until it *is* shown on screen.
402 if( m_treebook->IsShownOnScreen() )
403 m_lastNotebookPage = m_treebook->GetSelection();
404 }
405}
406
407
408void PCB_CALCULATOR_FRAME::OnClosePcbCalc( wxCloseEvent& event )
409{
411
412 wxASSERT( regPanel );
413
414 if( regPanel->m_RegulatorListChanged )
415 {
416 wxString msg;
417 wxString title = _( "Write Data Failed" );
418
419 if( regPanel->GetDataFilename().IsEmpty() )
420 {
421 msg = _( "No data filename to save modifications.\n"
422 "Do you want to exit and abandon your changes?" );
423
424 if( wxMessageBox( msg, title, wxYES_NO | wxICON_QUESTION ) == wxNO )
425 return;
426 }
427 else
428 {
429 if( !regPanel->WriteDataFile() )
430 {
431 msg.Printf( _( "Unable to write file '%s'\n"
432 "Do you want to exit and abandon your changes?"),
433 regPanel->GetDataFilename() );
434
435 if( wxMessageBox( msg, title, wxYES_NO | wxICON_ERROR ) == wxNO )
436 return;
437 }
438 }
439 }
440
441 event.Skip();
442}
443
444
446{
447 if( aCfg == nullptr )
448 return;
449
451
452 PCB_CALCULATOR_SETTINGS* cfg = static_cast<PCB_CALCULATOR_SETTINGS*>( aCfg );
453
454 m_treebook->ChangeSelection( cfg->m_LastPage );
455
456 for( CALCULATOR_PANEL* panel : m_panels )
457 panel->LoadSettings( cfg );
458}
459
460
462{
463 if( aCfg == nullptr )
464 return;
465
467
468 // Save current parameters values in config.
469 auto cfg = dynamic_cast<PCB_CALCULATOR_SETTINGS*>( Kiface().KifaceSettings() );
470
471 if( cfg )
472 {
473 cfg->m_LastPage = m_treebook->GetSelection();
474
475 for( CALCULATOR_PANEL* panel : m_panels )
476 panel->SaveSettings( cfg );
477 }
478
479}
constexpr EDA_IU_SCALE unityScale
Definition base_units.h:124
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:100
BITMAP_STORE * GetBitmapStore()
Definition bitmap.cpp:88
@ icon_pcbcalculator_16
@ icon_pcbcalculator_32
@ icon_pcbcalculator
static TOOL_ACTION openPreferences
Definition actions.h:278
Define the structure of a menu based on ACTIONs.
Definition action_menu.h:43
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.
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.
virtual APP_SETTINGS_BASE * config() const
Return 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.
virtual void setupUIConditions()
Setup the UI conditions for the various actions and their controls in this frame.
EDA_BASE_FRAME(wxWindow *aParent, FRAME_T aFrameType, const wxString &aTitle, const wxPoint &aPos, const wxSize &aSize, long aStyle, const wxString &aFrameName, KIWAY *aKiway, const EDA_IU_SCALE &aIuScale)
void AddMenuLanguageList(ACTION_MENU *aMasterMenu, TOOL_INTERACTIVE *aControlTool)
Create a menu list for language choice, and add it as submenu to MasterMenu.
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.
wxString m_aboutTitle
void ReCreateMenuBar()
Recreate the menu bar.
APP_SETTINGS_BASE * KifaceSettings() const
Definition kiface_base.h:91
Carry a payload from one KIWAY_PLAYER to another within a PROJECT.
Definition kiway_mail.h:34
std::string & GetPayload()
Return the payload, which can be any text but it typically self identifying s-expression.
Definition kiway_mail.h:52
MAIL_T Command()
Returns the MAIL_T associated with this mail.
Definition kiway_mail.h:44
A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of a KiCad project.
KIWAY_PLAYER(KIWAY *aKiway, wxWindow *aParent, FRAME_T aFrameType, const wxString &aTitle, const wxPoint &aPos, const wxSize &aSize, long aStyle, const wxString &aFrameName, const EDA_IU_SCALE &aIuScale)
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
Definition kiway.h:340
const wxString GetDataFilename()
std::vector< ATTENUATOR * > m_AttenuatorList
wxRadioBox * GetAttenuatorsSelector()
wxRadioBox * GetTranslineSelector()
TRANSLINE_TYPE_ID GetCurrTransLineType()
PCB calculator the main frame.
void OnPageChanged(wxTreebookEvent &aEvent)
void KiwayMailIn(KIWAY_MAIL_EVENT &aEvent) override
Receive #KIWAY_ROUTED_EVENT messages from other players.
PCB_CALCULATOR_FRAME(KIWAY *aKiway, wxWindow *aParent)
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 showCalculatorPage(wxWindow *aPage)
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
TOOL_DISPATCHER * m_toolDispatcher
Master controller class:
Wrapper around a wxMenuBar object that prevents the accelerator table from being used.
Definition wx_menubar.h:43
#define _(s)
@ FRAME_CALC
Definition frame_type.h:59
EVT_MENU(ID_COMPARE_PROJECT_BRANCHES, KICAD_MANAGER_FRAME::OnCompareProjectBranches) KICAD_MANAGER_FRAME
@ MAIL_CALC_SHOW
Definition mail_type.h:58
KICOMMON_API wxFont GetControlFont(wxWindow *aWindow)
#define _HKI(x)
Definition page_info.cpp:40
std::vector< FAB_LAYER_COLOR > dummy