kicad/pcb_calculator/calculator_panels/panel_eseries_display.cpp

444 lines
15 KiB
C++

/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 2023 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 <math.h>
#include <calculator_panels/panel_eseries_display.h>
#include <pcb_calculator_settings.h>
#include <string_utils.h>
#include <wx/msgdlg.h>
#include <wx/settings.h> // for IsDark
#include <eseries.h>
#include <i18n_utility.h> // For _HKI definition in eseries_display_help.h
wxString eseries_display_help =
#include "eseries_display_help.h"
PANEL_ESERIES_DISPLAY::PANEL_ESERIES_DISPLAY( wxWindow * parent, wxWindowID id,
const wxPoint& pos, const wxSize& size,
long style, const wxString& name ) :
PANEL_ESERIES_DISPLAY_BASE( parent, id, pos, size, style, name )
{
// show markdown stuff in lower help panel
wxString msg;
ConvertMarkdown2Html( wxGetTranslation( eseries_display_help ), msg );
m_panelESeriesHelp->SetPage( msg );
// Calculate E1,E3,E6,E12,E24,E48,E96 column background colours
// Get appearances. Note that I believe these panels will not be
// re-constructed on a mode change so this only works if you open
// the window *after* you set your dark mode.
const wxSystemAppearance appearances = wxSystemSettings::GetAppearance();
const bool selectDark = appearances.IsDark();
recalculateColumnColours( selectDark );
// Lay out the smaller tree containing E1,E3,E6, and E12
populateE112Tree();
// Set colours of smaller tree.
recolourE112Tree();
// Lay out the larger tree containing E24, R48 and E96
populateE2496Tree();
// Set colours of larger tree.
recolourE2496Tree();
// Needed on wxWidgets 3.0 to ensure sizers are correctly set
GetSizer()->SetSizeHints( this );
// Make the grid lines disappear into the window background
// making the value boxes appear to be separated from each other.
wxColour gridLineColour = parent->GetBackgroundColour();
m_GridEseries112->SetGridLineColour( gridLineColour );
m_GridEseries112->EnableGridLines( true );
m_GridEseries112->SetColLabelSize( wxGRID_AUTOSIZE );
m_GridEseries112->AutoSize();
m_GridEseries2496->SetGridLineColour( gridLineColour );
m_GridEseries2496->EnableGridLines( true );
m_GridEseries2496->SetColLabelSize( wxGRID_AUTOSIZE );
m_GridEseries2496->AutoSize();
Layout();
}
PANEL_ESERIES_DISPLAY::~PANEL_ESERIES_DISPLAY()
{
}
void PANEL_ESERIES_DISPLAY::ThemeChanged()
{
// Calculate E1,E3,E6,E12,E24,E48,E96 column background colours
// Get appearances.
const wxSystemAppearance appearances = wxSystemSettings::GetAppearance();
const bool selectDark = appearances.IsDark();
recalculateColumnColours( selectDark );
// Set colours of smaller tree.
recolourE112Tree();
// Set colours of larger tree.
recolourE2496Tree();
}
void PANEL_ESERIES_DISPLAY::SaveSettings( PCB_CALCULATOR_SETTINGS* aCfg )
{
}
void PANEL_ESERIES_DISPLAY::LoadSettings( PCB_CALCULATOR_SETTINGS* aCfg )
{
}
void PANEL_ESERIES_DISPLAY::recalculateColumnColours( bool aDarkModeOn )
{
// if in a dark mode then darken colors significantly so that
// the white numerals on top stand out better
const int colourAdjust = aDarkModeOn ? s_darkAdjustValue : 100;
m_colourE1Column = wxColour( s_cE1BGR ).ChangeLightness( colourAdjust );
const wxColour colourE3Column( wxColour( s_cE3BGR ).ChangeLightness( colourAdjust ) );
const wxColour colourE6Column( wxColour( s_cE6BGR ).ChangeLightness( colourAdjust ) );
const wxColour colourE12Column( wxColour( s_cE12BGR ).ChangeLightness( colourAdjust ) );
const wxColour colourE24Column( wxColour( s_cE24BGR ).ChangeLightness( colourAdjust ) );
const wxColour colourE48Column( wxColour( s_cE48BGR ).ChangeLightness( colourAdjust ) );
const wxColour colourE96Column( wxColour( s_cE96BGR ).ChangeLightness( colourAdjust ) );
m_colourE3Pair[0] = colourE3Column;
m_colourE3Pair[1] = colourE3Column.ChangeLightness( s_altAdjustValue );
m_colourE6Pair[0] = colourE6Column;
m_colourE6Pair[1] = colourE6Column.ChangeLightness( s_altAdjustValue );
m_colourE12Pair[0] = colourE12Column;
m_colourE12Pair[1] = colourE12Column.ChangeLightness( s_altAdjustValue );
m_colourE24Pair[0] = colourE24Column;
m_colourE24Pair[1] = colourE24Column.ChangeLightness( s_altAdjustValue );
m_colourE48Pair[0] = colourE48Column;
m_colourE48Pair[1] = colourE48Column.ChangeLightness( s_altAdjustValue );
m_colourE96Pair[0] = colourE96Column;
m_colourE96Pair[1] = colourE96Column.ChangeLightness( s_altAdjustValue );
s_colourMatching = m_GridEseries2496->GetLabelBackgroundColour();
}
void PANEL_ESERIES_DISPLAY::populateE112Tree()
{
// Lay out E1, R3, E6, E12 tree.
ESERIES::ESERIES_VALUES eSeries12 = ESERIES::ESERIES_VALUES( ESERIES::E12 );
int row = 0;
wxString value;
m_GridEseries112->BeginBatch();
m_GridEseries112->DeleteCols( 0, m_GridEseries112->GetNumberCols() );
m_GridEseries112->DeleteRows( 0, m_GridEseries112->GetNumberRows() );
m_GridEseries112->AppendCols( 4 ); // E1, E3, E6, E12
m_GridEseries112->AppendRows( 12 ); // Sufficient rows for all of E12
m_GridEseries112->SetColLabelValue( 0, "E1" );
m_GridEseries112->SetColLabelValue( 1, "E3" );
m_GridEseries112->SetColLabelValue( 2, "E6" );
m_GridEseries112->SetColLabelValue( 3, "E12" );
value = wxString( "" ) << eSeries12[0];
m_GridEseries112->SetCellValue( 0, 0, value );
m_GridEseries112->SetCellSize( 0, 0, 12, 1 );
for( const uint16_t& seriesEntry : eSeries12 )
{
value = wxString( "" ) << seriesEntry;
if( 0 == row % 4 )
{
// Set E3 column
m_GridEseries112->SetCellValue( row, 1, value );
m_GridEseries112->SetCellSize( row, 1, 4, 1 );
}
if( 0 == row % 2 )
{
// Set E6 column
m_GridEseries112->SetCellValue( row, 2, value );
m_GridEseries112->SetCellSize( row, 2, 2, 1 );
}
// Set E12 column
m_GridEseries112->SetCellValue( row, 3, value );
++row;
}
for( int i = 0; i < 3; ++i )
{
// Resize data columns to fit data and set as minimum size
m_GridEseries112->AutoSizeColumn( i, true );
}
m_GridEseries112->EndBatch();
}
void PANEL_ESERIES_DISPLAY::populateE2496Tree()
{
// Lay out E24, E48, E96 tree.
ESERIES::ESERIES_VALUES eSeries24 = ESERIES::ESERIES_VALUES( ESERIES::E24 );
ESERIES::ESERIES_VALUES eSeries96 = ESERIES::ESERIES_VALUES( ESERIES::E96 );
// This is the number of times the table is wrapped around into another
// column. Like in a newspaper. The term column is not used since
// the grid already has columns. The 96 in the second calculation
// is the number of entries in the largest series displayed (E96)
constexpr unsigned int numStripes = 4;
constexpr unsigned int stripeHeight = 96 / numStripes;
int idx = 0;
int stripe = 0;
wxString value;
m_GridEseries2496->BeginBatch();
m_GridEseries2496->DeleteCols( 0, m_GridEseries2496->GetNumberCols() );
m_GridEseries2496->DeleteRows( 0, m_GridEseries2496->GetNumberRows() );
// Column headers are E24, E48, E96, -
// repeated numStripes times over. And the last - is omitted.
m_GridEseries2496->AppendCols( numStripes * 4 - 1 );
m_GridEseries2496->AppendRows( stripeHeight );
m_GridEseries2496->SetColLabelValue( 0 + 0, "E24" );
m_GridEseries2496->SetColLabelValue( 1 + 0, "E48" );
m_GridEseries2496->SetColLabelValue( 2 + 0, "E96" );
m_GridEseries2496->SetColLabelValue( 3 + 0, "-" );
m_GridEseries2496->SetColLabelValue( 0 + 4, "E24" );
m_GridEseries2496->SetColLabelValue( 1 + 4, "E48" );
m_GridEseries2496->SetColLabelValue( 2 + 4, "E96" );
m_GridEseries2496->SetColLabelValue( 3 + 4, "-" );
m_GridEseries2496->SetColLabelValue( 0 + 8, "E24" );
m_GridEseries2496->SetColLabelValue( 1 + 8, "E48" );
m_GridEseries2496->SetColLabelValue( 2 + 8, "E96" );
m_GridEseries2496->SetColLabelValue( 3 + 8, "-" );
m_GridEseries2496->SetColLabelValue( 0 + 12, "E24" );
m_GridEseries2496->SetColLabelValue( 1 + 12, "E48" );
m_GridEseries2496->SetColLabelValue( 2 + 12, "E96" );
for( const uint16_t& seriesEntry : eSeries24 )
{
value = wxString( "" ) << seriesEntry;
int row = ( idx * 4 ) % stripeHeight;
int colOffset = ( ( idx * 4 ) / stripeHeight ) * 4;
m_GridEseries2496->SetCellValue( row, colOffset, value );
m_GridEseries2496->SetCellSize( row, colOffset, 4, 1 );
++idx;
}
idx = 0;
for( const uint16_t& seriesEntry : eSeries96 )
{
value = wxString( "" ) << seriesEntry;
int row = idx % stripeHeight;
int colOffset = ( idx / stripeHeight ) * 4;
if( 0 == row % 2 )
{
// Set E48 column
m_GridEseries2496->SetCellValue( row, colOffset + 1, value );
m_GridEseries2496->SetCellSize( row, colOffset + 1, 2, 1 );
}
// Set E96 column
m_GridEseries2496->SetCellValue( row, colOffset + 2, value );
++idx;
}
// cause the areas between stripes to appear more empty
// by making them a single cell the height of the stripe
// this causes the horizontal row lines rows to disappear
for( unsigned int stripeGap = 1; stripeGap < numStripes; ++stripeGap )
{
const int stripeColumn = -1 + stripeGap * 4;
m_GridEseries2496->SetCellSize( 0, stripeColumn, stripeHeight, 1 );
}
for( int i = 0; i < numStripes * 4 - 1; ++i )
{
// Resize the column to fit data and set as minimum size
m_GridEseries2496->AutoSizeColumn( i, true );
}
m_GridEseries2496->EndBatch();
}
void PANEL_ESERIES_DISPLAY::recolourE112Tree()
{
const unsigned int numRows = m_GridEseries112->GetNumberRows();
m_GridEseries112->BeginBatch();
// Colouring E1 is easy. There is only one item.
m_GridEseries112->SetCellBackgroundColour( 0, 0, m_colourE1Column );
bool alternateColour = false;
int cellWidth = 0, cellHeight = 0;
// Colour E3 column
for( int row = 0; row < numRows; row += cellHeight )
{
m_GridEseries112->SetCellBackgroundColour( row, 1, m_colourE3Pair[alternateColour] );
// get height for iteration above
m_GridEseries112->GetCellSize( row, 1, &cellHeight, &cellWidth );
alternateColour = !alternateColour;
if( cellHeight < 1 )
cellHeight = 1; // Do not loop forever, always make progress.
}
// Colour E6 column
alternateColour = false;
for( int row = 0; row < numRows; row += cellHeight )
{
m_GridEseries112->SetCellBackgroundColour( row, 2, m_colourE6Pair[alternateColour] );
// get height for iteration above
m_GridEseries112->GetCellSize( row, 2, &cellHeight, &cellWidth );
alternateColour = !alternateColour;
if( cellHeight < 1 )
cellHeight = 1; // Do not loop forever, always make progress.
}
// Colour E12 column
alternateColour = false;
for( int row = 0; row < numRows; row += cellHeight )
{
m_GridEseries112->SetCellBackgroundColour( row, 3, m_colourE12Pair[alternateColour] );
// get height for iteration above
m_GridEseries112->GetCellSize( row, 3, &cellHeight, &cellWidth );
alternateColour = !alternateColour;
if( cellHeight < 1 )
cellHeight = 1; // Do not loop forever, always make progress.
}
m_GridEseries112->EndBatch();
}
void PANEL_ESERIES_DISPLAY::recolourE2496Tree()
{
const unsigned int numRows = m_GridEseries2496->GetNumberRows();
constexpr unsigned int numStripes = 4;
constexpr unsigned int stripeHeight = 96 / numStripes;
m_GridEseries2496->BeginBatch();
bool alternateColour = false;
int cellWidth = 0, cellHeight = 0;
// Colour E24 columns
for( int row = 0; row < numRows; row += cellHeight )
{
for( int stripe = 0; stripe < numStripes; ++stripe )
{
m_GridEseries2496->SetCellBackgroundColour( row, 0 + 4 * stripe,
m_colourE24Pair[alternateColour] );
}
// get height for iteration above
m_GridEseries2496->GetCellSize( row, 0, &cellHeight, &cellWidth );
alternateColour = !alternateColour;
if( cellHeight < 1 )
cellHeight = 1; // Do not loop forever, always make progress.
}
// Colour E48 columns
alternateColour = false;
for( int row = 0; row < numRows; row += cellHeight )
{
for( int stripe = 0; stripe < numStripes; ++stripe )
{
m_GridEseries2496->SetCellBackgroundColour( row, 1 + 4 * stripe,
m_colourE48Pair[alternateColour] );
}
// get height for iteration above
m_GridEseries2496->GetCellSize( row, 1, &cellHeight, &cellWidth );
alternateColour = !alternateColour;
if( cellHeight < 1 )
cellHeight = 1; // Do not loop forever, always make progress.
}
// Colour E96 columns
alternateColour = false;
for( int row = 0; row < numRows; row += cellHeight )
{
for( int stripe = 0; stripe < numStripes; ++stripe )
{
m_GridEseries2496->SetCellBackgroundColour( row, 2 + 4 * stripe,
m_colourE96Pair[alternateColour] );
}
// get height for iteration above
m_GridEseries2496->GetCellSize( row, 2, &cellHeight, &cellWidth );
alternateColour = !alternateColour;
if( cellHeight < 1 )
cellHeight = 1; // Do not loop forever, always make progress.
}
// recolour empty areas between columns to match label background
// to make them less eye-catching
for( unsigned int stripeGap = 1; stripeGap < numStripes; ++stripeGap )
{
const int stripeColumn = -1 + stripeGap * 4;
m_GridEseries2496->SetCellBackgroundColour( 0, stripeColumn, s_colourMatching );
}
m_GridEseries2496->EndBatch();
}