7
mirror of https://gitlab.com/kicad/code/kicad.git synced 2024-11-21 22:35:00 +00:00
kicad/common/dialogs/dialog_multi_unit_entry.cpp
John Beard 95beedb612 Dogbones: add slots for acute angles
It's actually not as hard as I thought, though
surely has wierd edge cases which users might need to
handle manually.
2024-09-22 13:45:19 +01:00

177 lines
7.1 KiB
C++

/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2024 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 2
* 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, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "dialogs/dialog_multi_unit_entry.h"
#include <eda_draw_frame.h>
#include <widgets/unit_binder.h>
#include <core/type_helpers.h>
#include <wx/button.h>
#include <wx/checkbox.h>
#include <wx/gbsizer.h>
#include <wx/stattext.h>
WX_MULTI_ENTRY_DIALOG::WX_MULTI_ENTRY_DIALOG( EDA_DRAW_FRAME* aParent, const wxString& aCaption,
std::vector<ENTRY> aEntries ) :
DIALOG_SHIM( aParent, wxID_ANY, aCaption ), m_entries( std::move( aEntries ) )
{
SetSizeHints( wxDefaultSize, wxDefaultSize );
wxBoxSizer* bSizerMain = new wxBoxSizer( wxVERTICAL );
wxGridBagSizer* bSizerContent;
bSizerContent = new wxGridBagSizer( 0, 0 );
bSizerContent->SetFlexibleDirection( wxHORIZONTAL );
bSizerContent->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_ALL );
bSizerMain->Add( bSizerContent, 1, wxEXPAND | wxRIGHT | wxLEFT, 5 );
int gbRow = 0;
for( const ENTRY& entry : m_entries )
{
std::visit(
[&]( const auto& aValue )
{
using EntryType = std::decay_t<decltype( aValue )>;
if constexpr( std::is_same_v<EntryType, UNIT_BOUND> )
{
// Label / Entry / Unit
// and a binder
wxStaticText* label =
new wxStaticText( this, wxID_ANY, entry.m_label, wxDefaultPosition,
wxDefaultSize, 0 );
label->Wrap( -1 );
bSizerContent->Add( label, wxGBPosition( gbRow, 0 ), wxGBSpan( 1, 1 ),
wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM | wxLEFT,
5 );
wxTextCtrl* textCtrl =
new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition,
wxDefaultSize, 0 );
bSizerContent->Add( textCtrl, wxGBPosition( gbRow, 1 ), wxGBSpan( 1, 1 ),
wxALIGN_CENTER_VERTICAL | wxALL | wxEXPAND, 5 );
wxStaticText* unit_label = new wxStaticText(
this, wxID_ANY, _( "unit" ), wxDefaultPosition, wxDefaultSize, 0 );
unit_label->Wrap( -1 );
bSizerContent->Add( unit_label, wxGBPosition( gbRow, 2 ), wxGBSpan( 1, 1 ),
wxTOP | wxBOTTOM | wxRIGHT | wxALIGN_CENTER_VERTICAL,
5 );
if( !entry.m_tooltip.IsEmpty() )
textCtrl->SetToolTip( entry.m_tooltip );
m_controls.push_back( textCtrl );
m_unit_binders.push_back( std::make_unique<UNIT_BINDER>(
aParent, label, textCtrl, unit_label ) );
m_unit_binders.back()->SetValue( aValue.m_default );
}
else if constexpr( std::is_same_v<EntryType, CHECKBOX> )
{
// Checkbox across all 3 cols
wxCheckBox* checkBox =
new wxCheckBox( this, wxID_ANY, wxEmptyString, wxDefaultPosition,
wxDefaultSize, 0 );
bSizerContent->Add( checkBox, wxGBPosition( gbRow, 0 ), wxGBSpan( 1, 3 ),
wxALIGN_CENTER_VERTICAL | wxALL, 5 );
checkBox->SetLabel( entry.m_label );
checkBox->SetValue( aValue.m_default );
if( !entry.m_tooltip.IsEmpty() )
checkBox->SetToolTip( entry.m_tooltip );
m_controls.push_back( checkBox );
m_unit_binders.push_back( nullptr );
}
else
{
static_assert( always_false<EntryType>::value, "non-exhaustive visitor" );
}
},
entry.m_value );
gbRow++;
}
// Grow the value column (now it knows it has a col 1)
bSizerContent->AddGrowableCol( 1 );
wxStdDialogButtonSizer* sdbSizer1 = new wxStdDialogButtonSizer();
wxButton* sdbSizer1OK = new wxButton( this, wxID_OK );
sdbSizer1->AddButton( sdbSizer1OK );
wxButton* sdbSizer1Cancel = new wxButton( this, wxID_CANCEL );
sdbSizer1->AddButton( sdbSizer1Cancel );
sdbSizer1->Realize();
bSizerMain->Add( sdbSizer1, 0, wxALL | wxEXPAND, 5 );
SetSizer( bSizerMain );
SetupStandardButtons();
Layout();
// Now all widgets have the size fixed, call FinishDialogSettings
finishDialogSettings();
}
std::vector<WX_MULTI_ENTRY_DIALOG::RESULT> WX_MULTI_ENTRY_DIALOG::GetValues() const
{
std::vector<RESULT> results;
for( size_t ii = 0; ii < m_entries.size(); ++ii )
{
wxWindow* const control = m_controls[ii];
// Visit the value definitons to look up the right control type
std::visit(
[&]( const auto& aValueDef )
{
using ArgType = std::decay_t<decltype( aValueDef )>;
if constexpr( std::is_same_v<ArgType, UNIT_BOUND> )
{
UNIT_BINDER* binder = m_unit_binders[ii].get();
wxASSERT( binder );
results.push_back( binder ? binder->GetValue() : 0 );
}
else if constexpr( std::is_same_v<ArgType, CHECKBOX> )
{
wxCheckBox* checkBox = static_cast<wxCheckBox*>( control );
results.push_back( checkBox->GetValue() );
}
else
{
static_assert( always_false<ArgType>::value, "non-exhaustive visitor" );
}
},
m_entries[ii].m_value );
}
return results;
}