kicad/pcb_calculator/pcb_calculator_frame.cpp

305 lines
10 KiB
C++

/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 1992-2015 jean-pierre.charras
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <wx/menu.h>
#include <wx/msgdlg.h>
#include <wx/notebook.h>
#include <wx/sizer.h>
#include <typeinfo>
#include <bitmaps.h>
#include <bitmap_store.h>
#include <geometry/shape_poly_set.h>
#include <kiface_base.h>
#include <attenuators/attenuator_classes.h>
#include <pcb_calculator_frame.h>
#include <pcb_calculator_settings.h>
#include <calculator_panels/panel_attenuators.h>
#include <calculator_panels/panel_board_class.h>
#include <calculator_panels/panel_color_code.h>
#include <calculator_panels/panel_electrical_spacing.h>
#include <calculator_panels/panel_eserie.h>
#include <calculator_panels/panel_regulator.h>
#include <calculator_panels/panel_track_width.h>
#include <calculator_panels/panel_transline.h>
#include <calculator_panels/panel_via_size.h>
PCB_CALCULATOR_FRAME::PCB_CALCULATOR_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
KIWAY_PLAYER( aParent, wxID_ANY,
_( "PCB Calculator" ), // Window title
wxDefaultPosition,
wxSize( 646,361 ), // Default size
wxDEFAULT_FRAME_STYLE | wxRESIZE_BORDER | wxFULL_REPAINT_ON_RESIZE | wxTAB_TRAVERSAL,
wxT( "pcb_calculator" ) ), // Window name
m_lastNotebookPage( -1 ),
m_macHack( true )
{
SHAPE_POLY_SET dummy; // A ugly trick to force the linker to include
// some methods in code and avoid link errors
SetKiway( this, aKiway );
SetSizeHints( wxDefaultSize, wxDefaultSize );
m_menubar = new wxMenuBar( 0 );
SetMenuBar( m_menubar );
m_mainSizer = new wxBoxSizer( wxVERTICAL );
m_notebook = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
m_mainSizer->Add( m_notebook, 1, wxEXPAND, 5 );
SetSizer( m_mainSizer );
Layout();
Centre( wxBOTH );
AddCalculator( new PANEL_REGULATOR( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ),
_( "Regulators" ) );
AddCalculator( new PANEL_ATTENUATORS( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ),
_( "RF Attenuators" ) );
AddCalculator( new PANEL_E_SERIE( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ),
_( "E-Series" ) );
AddCalculator( new PANEL_COLOR_CODE( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ),
_( "Color Code" ) );
AddCalculator( new PANEL_TRANSLINE( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ),
_( "TransLine ") );
AddCalculator( new PANEL_VIA_SIZE( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ),
_( "Via Size" ) );
AddCalculator( new PANEL_TRACK_WIDTH( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ),
_( "Track Width" ) );
AddCalculator( new PANEL_ELECTRICAL_SPACING( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ),
_( "Electrical Spacing" ) );
AddCalculator( new PANEL_BOARD_CLASS( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ),
_("Board Classes") );
LoadSettings( config() );
if( PANEL_REGULATOR* regPanel = GetCalculator<PANEL_REGULATOR>() )
regPanel->ReadDataFile();
// Give an icon
wxIcon icon;
wxIconBundle icon_bundle;
icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_pcbcalculator ) );
icon_bundle.AddIcon( icon );
icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_pcbcalculator_32 ) );
icon_bundle.AddIcon( icon );
icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_pcbcalculator_16 ) );
icon_bundle.AddIcon( icon );
SetIcons( icon_bundle );
GetSizer()->SetSizeHints( this );
// Set previous size and position
SetSize( m_framePos.x, m_framePos.y, m_frameSize.x, m_frameSize.y );
if( m_framePos == wxDefaultPosition )
Centre();
// Connect Events
Bind( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( PCB_CALCULATOR_FRAME::OnClosePcbCalc ), this );
Bind( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( PCB_CALCULATOR_FRAME::OnUpdateUI ), this );
Bind( wxEVT_SYS_COLOUR_CHANGED,
wxSysColourChangedEventHandler( PCB_CALCULATOR_FRAME::onThemeChanged ), this );
}
PCB_CALCULATOR_FRAME::~PCB_CALCULATOR_FRAME()
{
// This needed for OSX: avoids further OnDraw processing after this destructor and before
// the native window is destroyed
this->Freeze();
}
void PCB_CALCULATOR_FRAME::AddCalculator( CALCULATOR_PANEL *aPanel, const wxString& panelUIName )
{
// Update internal structures
m_panels.push_back( aPanel );
m_panelTypes[ typeid( *aPanel ).hash_code() ] = aPanel;
m_notebook->AddPage( aPanel, panelUIName, false );
}
void PCB_CALCULATOR_FRAME::onThemeChanged( wxSysColourChangedEvent& aEvent )
{
// Force the bitmaps to refresh
GetBitmapStore()->ThemeChanged();
// Update the panels
for( auto& panel : m_panels )
panel->ThemeChanged();
aEvent.Skip();
}
void PCB_CALCULATOR_FRAME::OnUpdateUI( wxUpdateUIEvent& event )
{
if( m_notebook->GetSelection() != m_lastNotebookPage )
{
// Kick all the things that wxWidgets can't seem to redraw on its own.
// This is getting seriously ridiculous....
PANEL_TRANSLINE* translinePanel = GetCalculator<PANEL_TRANSLINE>();
PANEL_ATTENUATORS* attenPanel = GetCalculator<PANEL_ATTENUATORS>();
PANEL_VIA_SIZE* viaSizePanel = GetCalculator<PANEL_VIA_SIZE>();
PANEL_REGULATOR* regulPanel = GetCalculator<PANEL_REGULATOR>();
PANEL_ELECTRICAL_SPACING* elecSpacingPanel = GetCalculator<PANEL_ELECTRICAL_SPACING>();
wxASSERT( translinePanel );
wxASSERT( attenPanel );
wxASSERT( viaSizePanel );
wxASSERT( regulPanel );
wxASSERT( elecSpacingPanel );
{
wxCommandEvent event2( wxEVT_RADIOBUTTON );
event2.SetEventObject( translinePanel->GetTranslineSelector() );
event2.SetInt( translinePanel->GetCurrTransLineType() );
translinePanel->GetTranslineSelector()->Command( event2 );
}
for( int i = 0; i < attenPanel->m_AttenuatorList.size(); ++i )
{
if( attenPanel->m_AttenuatorList[i] == attenPanel->m_CurrAttenuator )
{
wxCommandEvent event2( wxEVT_RADIOBUTTON );
event2.SetEventObject( attenPanel->GetAttenuatorsSelector() );
event2.SetInt( i );
attenPanel->GetAttenuatorsSelector()->Command( event2 );
break;
}
}
attenPanel->UpdateUI();
viaSizePanel->Layout();
regulPanel->Layout();
// Until it's shown on screen the above won't work; but doing it anyway at least keeps
// putting new OnUpdateUI events into the queue until it *is* shown on screen.
if( m_notebook->IsShownOnScreen() )
{
// Work around an OSX bug where the wxGrid children don't get placed correctly until
// the first resize event.
#ifdef __WXMAC__
if( m_macHack )
{
wxSize pageSize = elecSpacingPanel->GetSize();
pageSize.x -= 100;
elecSpacingPanel->SetSize( pageSize );
elecSpacingPanel->Layout();
pageSize.x += 100;
elecSpacingPanel->SetSize( pageSize );
elecSpacingPanel->Layout();
m_macHack = false;
}
#endif
m_lastNotebookPage = m_notebook->GetSelection();
}
}
}
void PCB_CALCULATOR_FRAME::OnClosePcbCalc( wxCloseEvent& event )
{
PANEL_REGULATOR* regPanel = GetCalculator<PANEL_REGULATOR>();
wxASSERT( regPanel );
if( regPanel->m_RegulatorListChanged )
{
wxString msg;
wxString title = _( "Write Data Failed" );
if( regPanel->GetDataFilename().IsEmpty() )
{
msg = _( "No data filename to save modifications.\n"
"Do you want to exit and abandon your changes?" );
if( wxMessageBox( msg, title, wxYES_NO | wxICON_QUESTION ) == wxNO )
return;
}
else
{
if( !regPanel->WriteDataFile() )
{
msg.Printf( _( "Unable to write file '%s'\n"
"Do you want to exit and abandon your changes?"),
regPanel->GetDataFilename() );
if( wxMessageBox( msg, title, wxYES_NO | wxICON_ERROR ) == wxNO )
return;
}
}
}
event.Skip();
}
void PCB_CALCULATOR_FRAME::LoadSettings( APP_SETTINGS_BASE* aCfg )
{
if( aCfg == nullptr )
return;
EDA_BASE_FRAME::LoadSettings( aCfg );
PCB_CALCULATOR_SETTINGS* cfg = static_cast<PCB_CALCULATOR_SETTINGS*>( aCfg );
m_notebook->ChangeSelection( cfg->m_LastPage );
for( auto& panel : m_panels )
panel->LoadSettings( cfg );
}
void PCB_CALCULATOR_FRAME::SaveSettings( APP_SETTINGS_BASE* aCfg )
{
if( aCfg == nullptr )
return;
EDA_BASE_FRAME::SaveSettings( aCfg );
// Save current parameters values in config.
auto cfg = dynamic_cast<PCB_CALCULATOR_SETTINGS*>( Kiface().KifaceSettings() );
if( cfg )
{
cfg->m_LastPage = m_notebook->GetSelection();
for( auto& panel : m_panels )
panel->SaveSettings( cfg );
}
}