2014-10-21 11:48:00 -04:00
|
|
|
/*
|
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2010 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
2025-01-01 13:30:11 -08:00
|
|
|
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
2014-10-21 11:48:00 -04:00
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
|
2017-02-20 20:20:39 +08:00
|
|
|
#include <bitmaps.h>
|
2018-10-18 13:25:46 +01:00
|
|
|
#include <sch_painter.h>
|
2020-10-31 01:27:16 +00:00
|
|
|
#include <symbol_edit_frame.h>
|
2024-04-20 10:44:34 +01:00
|
|
|
#include <sch_pin.h>
|
2020-08-03 22:12:29 +01:00
|
|
|
#include <dialog_pin_properties.h>
|
2018-05-23 18:41:37 +01:00
|
|
|
#include <confirm.h>
|
2021-12-16 17:39:58 +03:00
|
|
|
#include <kiplatform/ui.h>
|
2019-08-22 10:53:50 +01:00
|
|
|
#include <widgets/tab_traversal.h>
|
2020-08-21 16:54:24 +01:00
|
|
|
#include <widgets/wx_grid.h>
|
|
|
|
#include <grid_tricks.h>
|
|
|
|
#include <widgets/grid_icon_text_helpers.h>
|
2022-12-13 20:47:28 +00:00
|
|
|
#include <widgets/std_bitmap_button.h>
|
2022-03-26 15:15:36 +00:00
|
|
|
#include <wx/hyperlink.h>
|
2025-02-03 15:15:15 +00:00
|
|
|
#include <symbol_preview_widget.h>
|
2020-08-21 16:54:24 +01:00
|
|
|
|
2025-07-24 17:55:00 +01:00
|
|
|
class ALT_PIN_DATA_MODEL : public WX_GRID_TABLE_BASE, public std::vector<SCH_PIN::ALT>
|
2020-08-21 16:54:24 +01:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
ALT_PIN_DATA_MODEL( EDA_UNITS aUserUnits )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
int GetNumberRows() override { return (int) size(); }
|
|
|
|
int GetNumberCols() override { return COL_COUNT; }
|
|
|
|
|
|
|
|
wxString GetColLabelValue( int aCol ) override
|
|
|
|
{
|
|
|
|
switch( aCol )
|
|
|
|
{
|
|
|
|
case COL_NAME: return _( "Alternate Pin Name" );
|
|
|
|
case COL_TYPE: return _( "Electrical Type" );
|
|
|
|
case COL_SHAPE: return _( "Graphic Style" );
|
|
|
|
default: wxFAIL; return wxEmptyString;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsEmptyCell( int row, int col ) override
|
|
|
|
{
|
|
|
|
return false; // don't allow adjacent cell overflow, even if we are actually empty
|
|
|
|
}
|
|
|
|
|
|
|
|
wxString GetValue( int aRow, int aCol ) override
|
|
|
|
{
|
|
|
|
switch( aCol )
|
|
|
|
{
|
|
|
|
case COL_NAME: return at( aRow ).m_Name;
|
|
|
|
case COL_TYPE: return PinTypeNames()[static_cast<int>( at( aRow ).m_Type )];
|
|
|
|
case COL_SHAPE: return PinShapeNames()[static_cast<int>( at( aRow ).m_Shape )];
|
|
|
|
default: wxFAIL; return wxEmptyString;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetValue( int aRow, int aCol, const wxString &aValue ) override
|
|
|
|
{
|
|
|
|
switch( aCol )
|
|
|
|
{
|
|
|
|
case COL_NAME:
|
|
|
|
at( aRow ).m_Name = aValue;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case COL_TYPE:
|
|
|
|
if( PinTypeNames().Index( aValue ) != wxNOT_FOUND )
|
|
|
|
at( aRow ).m_Type = (ELECTRICAL_PINTYPE) PinTypeNames().Index( aValue );
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case COL_SHAPE:
|
|
|
|
if( PinShapeNames().Index( aValue ) != wxNOT_FOUND )
|
|
|
|
at( aRow ).m_Shape = (GRAPHIC_PINSHAPE) PinShapeNames().Index( aValue );
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
wxFAIL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-20 10:44:34 +01:00
|
|
|
void AppendRow( const SCH_PIN::ALT& aAlt )
|
2020-08-21 16:54:24 +01:00
|
|
|
{
|
|
|
|
push_back( aAlt );
|
|
|
|
|
|
|
|
if ( GetView() )
|
|
|
|
{
|
|
|
|
wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
|
|
|
|
GetView()->ProcessTableMessage( msg );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void RemoveRow( int aRow )
|
|
|
|
{
|
|
|
|
erase( begin() + aRow );
|
|
|
|
|
|
|
|
if ( GetView() )
|
|
|
|
{
|
|
|
|
wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_DELETED, aRow, 1 );
|
|
|
|
GetView()->ProcessTableMessage( msg );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-05-23 18:41:37 +01:00
|
|
|
|
2025-01-18 10:32:42 -05:00
|
|
|
DIALOG_PIN_PROPERTIES::DIALOG_PIN_PROPERTIES( SYMBOL_EDIT_FRAME* parent, SCH_PIN* aPin,
|
|
|
|
bool aFocusPinNumber ) :
|
2025-06-19 14:11:04 +01:00
|
|
|
DIALOG_PIN_PROPERTIES_BASE( parent ),
|
|
|
|
m_frame( parent ),
|
|
|
|
m_pin( aPin ),
|
|
|
|
m_posX( parent, m_posXLabel, m_posXCtrl, m_posXUnits ),
|
|
|
|
m_posY( parent, m_posYLabel, m_posYCtrl, m_posYUnits ),
|
|
|
|
m_pinLength( parent, m_pinLengthLabel, m_pinLengthCtrl, m_pinLengthUnits ),
|
|
|
|
m_nameSize( parent, m_nameSizeLabel, m_nameSizeCtrl, m_nameSizeUnits ),
|
|
|
|
m_numberSize( parent, m_numberSizeLabel, m_numberSizeCtrl, m_numberSizeUnits ),
|
|
|
|
m_delayedFocusRow( -1 ),
|
|
|
|
m_delayedFocusColumn( -1 ),
|
|
|
|
m_initialized( false )
|
2012-09-22 13:19:37 +02:00
|
|
|
{
|
2025-02-03 15:15:15 +00:00
|
|
|
// Create a dummy symbol with a single pin for the preview widget:
|
2024-04-05 08:16:29 -04:00
|
|
|
m_dummyParent = new LIB_SYMBOL( *static_cast<LIB_SYMBOL*>( m_pin->GetParentSymbol() ) );
|
2025-02-03 15:15:15 +00:00
|
|
|
|
|
|
|
// Move everything in the copied symbol to unit 1; we'll use unit 2 for the dummy pin:
|
|
|
|
m_dummyParent->SetUnitCount( 2, false );
|
|
|
|
m_dummyParent->RunOnChildren( [&]( SCH_ITEM* child )
|
|
|
|
{
|
|
|
|
child->SetUnit( 1 );
|
2025-03-27 13:11:07 -04:00
|
|
|
},
|
|
|
|
RECURSE_MODE::NO_RECURSE );
|
2025-02-03 15:15:15 +00:00
|
|
|
|
2024-04-20 10:44:34 +01:00
|
|
|
m_dummyPin = new SCH_PIN( *m_pin );
|
2025-02-03 15:15:15 +00:00
|
|
|
m_dummyPin->SetUnit( 2 );
|
|
|
|
m_dummyParent->AddDrawItem( m_dummyPin, false );
|
|
|
|
|
2021-12-31 14:07:24 +00:00
|
|
|
m_dummyParent->SetShowPinNames( true );
|
|
|
|
m_dummyParent->SetShowPinNumbers( true );
|
2012-09-22 13:19:37 +02:00
|
|
|
|
2025-02-03 15:15:15 +00:00
|
|
|
m_previewWidget = new SYMBOL_PREVIEW_WIDGET( m_panelShowPin, &m_frame->Kiway(), false,
|
|
|
|
m_frame->GetCanvas()->GetBackend() );
|
2012-09-22 13:19:37 +02:00
|
|
|
|
2025-02-03 15:15:15 +00:00
|
|
|
m_previewWidget->SetLayoutDirection( wxLayout_LeftToRight );
|
|
|
|
m_previewWidget->DisplayPart( m_dummyParent, m_dummyPin->GetUnit(), 0 );
|
|
|
|
|
|
|
|
wxBoxSizer* previewSizer = new wxBoxSizer( wxHORIZONTAL );
|
|
|
|
previewSizer->Add( m_previewWidget, 1, wxEXPAND, 5 );
|
|
|
|
m_panelShowPin->SetSizer( previewSizer );
|
|
|
|
|
|
|
|
const wxArrayString& orientationNames = PinOrientationNames();
|
2021-03-07 21:59:07 -05:00
|
|
|
const std::vector<BITMAPS>& orientationIcons = PinOrientationIcons();
|
2018-05-23 18:41:37 +01:00
|
|
|
|
|
|
|
for ( unsigned ii = 0; ii < orientationNames.GetCount(); ii++ )
|
2025-06-19 14:11:04 +01:00
|
|
|
m_choiceOrientation->Insert( orientationNames[ii], KiBitmapBundle( orientationIcons[ii] ), ii );
|
2018-05-23 18:41:37 +01:00
|
|
|
|
2019-08-24 17:12:59 +01:00
|
|
|
// We can't set the tab order through wxWidgets due to shortcomings in their mnemonics
|
|
|
|
// implementation on MSW
|
2019-08-26 18:36:35 +01:00
|
|
|
m_tabOrder = {
|
2019-08-22 10:53:50 +01:00
|
|
|
m_textPinName,
|
|
|
|
m_textPinNumber,
|
|
|
|
m_choiceElectricalType,
|
|
|
|
m_choiceStyle,
|
|
|
|
m_posXCtrl,
|
|
|
|
m_posYCtrl,
|
|
|
|
m_choiceOrientation,
|
|
|
|
m_pinLengthCtrl,
|
|
|
|
m_nameSizeCtrl,
|
2019-08-23 22:14:12 +01:00
|
|
|
m_numberSizeCtrl,
|
|
|
|
m_checkApplyToAllParts,
|
2024-01-26 08:35:11 -08:00
|
|
|
m_checkApplyToAllBodyStyles,
|
2019-08-24 17:12:59 +01:00
|
|
|
m_checkShow,
|
2019-08-26 18:36:35 +01:00
|
|
|
m_sdbSizerButtonsOK,
|
|
|
|
m_sdbSizerButtonsCancel
|
2019-08-22 21:16:40 +01:00
|
|
|
};
|
2019-08-22 10:53:50 +01:00
|
|
|
|
2025-01-18 10:32:42 -05:00
|
|
|
// Default alternates turndown to whether or not alternates exist, or if we've had it open
|
|
|
|
// before
|
2025-06-19 14:11:04 +01:00
|
|
|
m_alternatesTurndown->Collapse( m_pin->GetAlternates().size() == 0 && !s_alternatesTurndownOpen );
|
2022-11-04 12:04:32 +00:00
|
|
|
|
|
|
|
// wxwidgets doesn't call the OnCollapseChange even at init, so we update this value if
|
|
|
|
// the alternates pane defaults to open
|
|
|
|
if ( m_pin->GetAlternates().size() > 0 )
|
|
|
|
s_alternatesTurndownOpen = true;
|
2020-08-21 16:54:24 +01:00
|
|
|
|
|
|
|
m_alternatesDataModel = new ALT_PIN_DATA_MODEL( GetUserUnits() );
|
|
|
|
|
|
|
|
// Save original columns widths so we can do proportional sizing.
|
|
|
|
for( int i = 0; i < COL_COUNT; ++i )
|
|
|
|
m_originalColWidths[ i ] = m_alternatesGrid->GetColSize( i );
|
|
|
|
|
|
|
|
m_alternatesGrid->SetTable( m_alternatesDataModel );
|
2022-09-09 12:18:05 +01:00
|
|
|
m_alternatesGrid->PushEventHandler( new GRID_TRICKS( m_alternatesGrid,
|
|
|
|
[this]( wxCommandEvent& aEvent )
|
|
|
|
{
|
|
|
|
OnAddAlternate( aEvent );
|
|
|
|
} ) );
|
2025-07-24 17:55:00 +01:00
|
|
|
m_alternatesGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
|
2020-08-21 16:54:24 +01:00
|
|
|
|
2024-04-02 18:28:17 +01:00
|
|
|
if( aPin->GetParentSymbol()->HasAlternateBodyStyle() )
|
2021-01-04 15:56:50 -08:00
|
|
|
{
|
|
|
|
m_alternatesTurndown->Collapse();
|
|
|
|
m_alternatesTurndown->Disable();
|
2021-11-16 19:39:58 +00:00
|
|
|
m_alternatesTurndown->SetToolTip( _( "Alternate pin assignments are not available for "
|
|
|
|
"De Morgan symbols." ) );
|
2021-01-04 15:56:50 -08:00
|
|
|
}
|
|
|
|
|
2020-08-21 16:54:24 +01:00
|
|
|
// Set special attributes
|
|
|
|
wxGridCellAttr* attr;
|
|
|
|
|
|
|
|
attr = new wxGridCellAttr;
|
|
|
|
attr->SetRenderer( new GRID_CELL_ICON_TEXT_RENDERER( PinTypeIcons(), PinTypeNames() ) );
|
|
|
|
attr->SetEditor( new GRID_CELL_ICON_TEXT_POPUP( PinTypeIcons(), PinTypeNames() ) );
|
|
|
|
m_alternatesGrid->SetColAttr( COL_TYPE, attr );
|
|
|
|
|
|
|
|
attr = new wxGridCellAttr;
|
|
|
|
attr->SetRenderer( new GRID_CELL_ICON_TEXT_RENDERER( PinShapeIcons(), PinShapeNames() ) );
|
|
|
|
attr->SetEditor( new GRID_CELL_ICON_TEXT_POPUP( PinShapeIcons(), PinShapeNames() ) );
|
|
|
|
m_alternatesGrid->SetColAttr( COL_SHAPE, attr );
|
|
|
|
|
2023-10-21 14:56:19 -04:00
|
|
|
m_addAlternate->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
|
|
|
|
m_deleteAlternate->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
|
2021-10-29 20:27:24 +01:00
|
|
|
m_addAlternate->GetParent()->Layout();
|
2020-08-21 16:54:24 +01:00
|
|
|
|
2021-11-16 19:39:58 +00:00
|
|
|
SetupStandardButtons();
|
2024-10-24 23:46:27 +08:00
|
|
|
|
|
|
|
SetInitialFocus( aFocusPinNumber ? m_textPinNumber : m_textPinName );
|
2018-05-23 18:41:37 +01:00
|
|
|
|
2025-06-29 10:06:32 +02:00
|
|
|
// We should call FinishDialogSettings() when all widgets have the size fixed.
|
|
|
|
// However m_infoBar is not yet initialized, so it will called later
|
|
|
|
// See TransferDataToWindow()
|
2015-03-14 12:50:39 +01:00
|
|
|
|
2019-08-24 17:12:59 +01:00
|
|
|
// On some window managers (Unity, XFCE) the dialog is not always raised, depending on
|
2021-06-09 19:32:58 +00:00
|
|
|
// how it is run.
|
2015-03-14 17:47:25 +01:00
|
|
|
Raise();
|
2020-08-21 16:54:24 +01:00
|
|
|
|
|
|
|
m_initialized = true;
|
2012-09-22 13:19:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-08-03 22:12:29 +01:00
|
|
|
DIALOG_PIN_PROPERTIES::~DIALOG_PIN_PROPERTIES()
|
2012-09-22 13:19:37 +02:00
|
|
|
{
|
2021-12-31 14:07:24 +00:00
|
|
|
delete m_dummyParent;
|
2020-08-21 16:54:24 +01:00
|
|
|
|
|
|
|
// Prevents crash bug in wxGrid's d'tor
|
|
|
|
m_alternatesGrid->DestroyTable( m_alternatesDataModel );
|
|
|
|
|
|
|
|
// Delete the GRID_TRICKS.
|
|
|
|
m_alternatesGrid->PopEventHandler( true );
|
2012-09-22 13:19:37 +02:00
|
|
|
}
|
|
|
|
|
2018-05-23 18:41:37 +01:00
|
|
|
|
2020-08-03 22:12:29 +01:00
|
|
|
bool DIALOG_PIN_PROPERTIES::TransferDataToWindow()
|
2015-09-13 18:43:38 -04:00
|
|
|
{
|
2018-05-23 18:41:37 +01:00
|
|
|
if( !DIALOG_SHIM::TransferDataToWindow() )
|
|
|
|
return false;
|
|
|
|
|
2020-07-03 02:11:21 +01:00
|
|
|
m_origPos = m_pin->GetPosition();
|
|
|
|
|
2020-08-21 16:54:24 +01:00
|
|
|
m_choiceOrientation->SetSelection( PinOrientationIndex( m_pin->GetOrientation() ) );
|
2018-05-23 18:41:37 +01:00
|
|
|
m_choiceStyle->SetSelection( m_pin->GetShape() );
|
|
|
|
m_choiceElectricalType->SetSelection( m_pin->GetType() );
|
|
|
|
m_textPinName->SetValue( m_pin->GetName() );
|
|
|
|
m_nameSize.SetValue( m_pin->GetNameTextSize() );
|
2020-07-03 02:11:21 +01:00
|
|
|
m_posX.SetValue( m_origPos.x );
|
2024-08-14 20:07:06 -06:00
|
|
|
m_posY.SetValue( m_origPos.y );
|
2018-05-23 18:41:37 +01:00
|
|
|
m_textPinNumber->SetValue( m_pin->GetNumber() );
|
|
|
|
m_numberSize.SetValue( m_pin->GetNumberTextSize() );
|
|
|
|
m_pinLength.SetValue( m_pin->GetLength() );
|
2024-04-02 18:28:17 +01:00
|
|
|
m_checkApplyToAllParts->Enable( m_pin->GetParentSymbol()->IsMulti() );
|
2025-06-19 14:11:04 +01:00
|
|
|
m_checkApplyToAllParts->SetValue( m_pin->GetParentSymbol()->IsMulti() && m_pin->GetUnit() == 0 );
|
2024-01-26 16:16:13 +00:00
|
|
|
m_checkApplyToAllBodyStyles->SetValue( m_pin->GetBodyStyle() == 0 );
|
2018-05-23 18:41:37 +01:00
|
|
|
m_checkShow->SetValue( m_pin->IsVisible() );
|
|
|
|
|
2019-02-15 15:59:37 -08:00
|
|
|
m_dummyPin->SetVisible( m_pin->IsVisible() );
|
|
|
|
|
2022-03-26 15:15:36 +00:00
|
|
|
wxString commonUnitsToolTip;
|
2021-08-12 21:19:27 -04:00
|
|
|
|
2022-03-26 15:15:36 +00:00
|
|
|
if( m_frame->m_SyncPinEdit )
|
|
|
|
{
|
2025-06-19 14:11:04 +01:00
|
|
|
wxHyperlinkCtrl* button = new wxHyperlinkCtrl( m_infoBar, wxID_ANY, _( "Exit sync pins mode" ),
|
2022-03-26 15:15:36 +00:00
|
|
|
wxEmptyString );
|
|
|
|
|
|
|
|
button->Bind( wxEVT_COMMAND_HYPERLINK,
|
|
|
|
std::function<void( wxHyperlinkEvent& aEvent )>(
|
|
|
|
[&]( wxHyperlinkEvent& aEvent )
|
|
|
|
{
|
|
|
|
m_frame->m_SyncPinEdit = false;
|
|
|
|
m_infoBar->Dismiss();
|
|
|
|
} ) );
|
|
|
|
|
|
|
|
m_infoBar->RemoveAllButtons();
|
|
|
|
m_infoBar->AddButton( button );
|
|
|
|
m_infoBar->ShowMessage( getSyncPinsMessage() );
|
|
|
|
|
|
|
|
commonUnitsToolTip = _( "Synchronized pins mode is enabled.\n"
|
|
|
|
"Similar pins will be edited regardless of this option." );
|
|
|
|
}
|
2021-08-14 10:15:18 +02:00
|
|
|
else
|
2022-03-26 15:15:36 +00:00
|
|
|
{
|
|
|
|
commonUnitsToolTip = _( "If checked, this pin will exist in all units." );
|
|
|
|
}
|
2021-08-12 21:19:27 -04:00
|
|
|
|
2024-04-02 18:28:17 +01:00
|
|
|
if( !m_pin->GetParentSymbol()->IsMulti() )
|
2022-03-26 15:15:36 +00:00
|
|
|
commonUnitsToolTip = _( "This symbol only has one unit. This control has no effect." );
|
|
|
|
|
|
|
|
m_checkApplyToAllParts->SetToolTip( commonUnitsToolTip );
|
2021-08-12 21:19:27 -04:00
|
|
|
|
2024-04-20 10:44:34 +01:00
|
|
|
for( const std::pair<const wxString, SCH_PIN::ALT>& alt : m_pin->GetAlternates() )
|
2020-08-21 16:54:24 +01:00
|
|
|
m_alternatesDataModel->AppendRow( alt.second );
|
|
|
|
|
2025-06-29 10:06:32 +02:00
|
|
|
// We can call FinishDialogSettings() now all widgets have the size fixed.
|
|
|
|
finishDialogSettings();
|
|
|
|
|
2018-05-23 18:41:37 +01:00
|
|
|
return true;
|
|
|
|
}
|
2016-07-16 12:54:55 +02:00
|
|
|
|
2018-05-23 18:41:37 +01:00
|
|
|
|
2020-08-03 22:12:29 +01:00
|
|
|
bool DIALOG_PIN_PROPERTIES::TransferDataFromWindow()
|
2018-05-23 18:41:37 +01:00
|
|
|
{
|
2020-08-21 16:54:24 +01:00
|
|
|
if( !m_alternatesGrid->CommitPendingChanges() )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Check for missing alternate names.
|
|
|
|
for( size_t i = 0; i < m_alternatesDataModel->size(); ++i )
|
|
|
|
{
|
|
|
|
if( m_alternatesDataModel->at( i ).m_Name.IsEmpty() )
|
|
|
|
{
|
|
|
|
DisplayErrorMessage( this, _( "Alternate pin definitions must have a name." ) );
|
|
|
|
|
|
|
|
m_delayedFocusColumn = COL_NAME;
|
|
|
|
m_delayedFocusRow = i;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-23 18:41:37 +01:00
|
|
|
if( !DIALOG_SHIM::TransferDataFromWindow() )
|
|
|
|
return false;
|
|
|
|
|
2024-08-14 20:07:06 -06:00
|
|
|
VECTOR2I newPos( m_posX.GetIntValue(), m_posY.GetIntValue() );
|
2020-07-03 02:11:21 +01:00
|
|
|
|
2022-09-27 11:09:43 +01:00
|
|
|
const int standard_grid = 50;
|
2018-05-23 18:41:37 +01:00
|
|
|
|
2020-07-03 02:11:21 +01:00
|
|
|
// Only show the warning if the position has been changed
|
|
|
|
if( ( m_origPos != newPos )
|
2025-01-18 10:32:42 -05:00
|
|
|
&& ( ( m_posX.GetValue() % standard_grid ) || ( m_posY.GetValue() % standard_grid ) ) )
|
2018-05-23 18:41:37 +01:00
|
|
|
{
|
2022-09-27 11:09:43 +01:00
|
|
|
wxString msg = wxString::Format( _( "This pin is not on a %d mils grid which will make it "
|
|
|
|
"difficult to connect to in the schematic.\n"
|
|
|
|
"Do you wish to continue?" ),
|
|
|
|
standard_grid );
|
2018-05-23 18:41:37 +01:00
|
|
|
if( !IsOK( this, msg ) )
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_pin->SetName( m_textPinName->GetValue() );
|
|
|
|
m_pin->SetNumber( m_textPinNumber->GetValue() );
|
2024-04-02 18:28:17 +01:00
|
|
|
m_pin->SetNameTextSize( m_nameSize.GetIntValue() );
|
|
|
|
m_pin->SetNumberTextSize( m_numberSize.GetIntValue() );
|
2020-08-21 16:54:24 +01:00
|
|
|
m_pin->SetOrientation( PinOrientationCode( m_choiceOrientation->GetSelection() ) );
|
2020-08-03 22:12:29 +01:00
|
|
|
m_pin->SetPosition( newPos );
|
2024-04-02 18:28:17 +01:00
|
|
|
m_pin->ChangeLength( m_pinLength.GetIntValue() );
|
2018-05-23 18:41:37 +01:00
|
|
|
m_pin->SetType( m_choiceElectricalType->GetPinTypeSelection() );
|
|
|
|
m_pin->SetShape( m_choiceStyle->GetPinShapeSelection() );
|
2024-01-26 16:16:13 +00:00
|
|
|
m_pin->SetBodyStyle( m_checkApplyToAllBodyStyles->GetValue() ? 0 : m_frame->GetBodyStyle() );
|
2020-08-03 22:12:29 +01:00
|
|
|
m_pin->SetUnit( m_checkApplyToAllParts->GetValue() ? 0 : m_frame->GetUnit() );
|
2018-05-23 18:41:37 +01:00
|
|
|
m_pin->SetVisible( m_checkShow->GetValue() );
|
|
|
|
|
2024-04-20 10:44:34 +01:00
|
|
|
std::map<wxString, SCH_PIN::ALT>& alternates = m_pin->GetAlternates();
|
2020-08-21 16:54:24 +01:00
|
|
|
alternates.clear();
|
|
|
|
|
2024-04-20 10:44:34 +01:00
|
|
|
for( const SCH_PIN::ALT& alt : *m_alternatesDataModel )
|
2020-08-21 16:54:24 +01:00
|
|
|
alternates[ alt.m_Name ] = alt;
|
|
|
|
|
2018-05-23 18:41:37 +01:00
|
|
|
return true;
|
2015-09-13 18:43:38 -04:00
|
|
|
}
|
2012-09-22 13:19:37 +02:00
|
|
|
|
2018-05-23 18:41:37 +01:00
|
|
|
|
2020-08-03 22:12:29 +01:00
|
|
|
void DIALOG_PIN_PROPERTIES::OnPropertiesChange( wxCommandEvent& event )
|
2012-09-22 13:19:37 +02:00
|
|
|
{
|
2021-08-19 22:28:54 +01:00
|
|
|
if( !IsShownOnScreen() ) // do nothing at init time
|
2012-09-22 13:19:37 +02:00
|
|
|
return;
|
|
|
|
|
2018-05-23 18:41:37 +01:00
|
|
|
m_dummyPin->SetName( m_textPinName->GetValue() );
|
|
|
|
m_dummyPin->SetNumber( m_textPinNumber->GetValue() );
|
2024-04-02 18:28:17 +01:00
|
|
|
m_dummyPin->SetNameTextSize( m_nameSize.GetIntValue() );
|
|
|
|
m_dummyPin->SetNumberTextSize( m_numberSize.GetIntValue() );
|
2020-08-21 16:54:24 +01:00
|
|
|
m_dummyPin->SetOrientation( PinOrientationCode( m_choiceOrientation->GetSelection() ) );
|
2024-04-02 18:28:17 +01:00
|
|
|
m_dummyPin->SetLength( m_pinLength.GetIntValue() );
|
2018-05-23 18:41:37 +01:00
|
|
|
m_dummyPin->SetType( m_choiceElectricalType->GetPinTypeSelection() );
|
|
|
|
m_dummyPin->SetShape( m_choiceStyle->GetPinShapeSelection() );
|
|
|
|
m_dummyPin->SetVisible( m_checkShow->GetValue() );
|
2012-09-22 13:19:37 +02:00
|
|
|
|
2022-03-26 15:15:36 +00:00
|
|
|
if( event.GetEventObject() == m_checkApplyToAllParts && m_frame->m_SyncPinEdit )
|
2025-06-29 10:06:32 +02:00
|
|
|
{
|
2022-03-26 15:15:36 +00:00
|
|
|
m_infoBar->ShowMessage( getSyncPinsMessage() );
|
2025-06-29 10:06:32 +02:00
|
|
|
m_infoBar->GetSizer()->Layout();
|
|
|
|
}
|
2022-03-26 15:15:36 +00:00
|
|
|
|
2025-02-03 15:15:15 +00:00
|
|
|
m_previewWidget->DisplayPart( m_dummyParent, m_dummyPin->GetUnit(), 0 );
|
2012-09-22 13:19:37 +02:00
|
|
|
}
|
2020-08-21 16:54:24 +01:00
|
|
|
|
2025-01-18 10:32:42 -05:00
|
|
|
|
2022-03-26 15:15:36 +00:00
|
|
|
wxString DIALOG_PIN_PROPERTIES::getSyncPinsMessage()
|
|
|
|
{
|
|
|
|
if( m_checkApplyToAllParts->GetValue() )
|
|
|
|
return _( "Synchronized Pins Mode." );
|
|
|
|
else if( m_pin->IsNew() )
|
|
|
|
return _( "Synchronized Pins Mode. New pin will be added to all units." );
|
|
|
|
else
|
|
|
|
return _( "Synchronized Pins Mode. Matching pins in other units will be updated." );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-08-21 16:54:24 +01:00
|
|
|
void DIALOG_PIN_PROPERTIES::OnAddAlternate( wxCommandEvent& event )
|
|
|
|
{
|
|
|
|
if( !m_alternatesGrid->CommitPendingChanges() )
|
|
|
|
return;
|
|
|
|
|
2024-04-20 10:44:34 +01:00
|
|
|
SCH_PIN::ALT newAlt;
|
2020-08-21 16:54:24 +01:00
|
|
|
newAlt.m_Name = wxEmptyString;
|
|
|
|
newAlt.m_Type = m_pin->GetType();
|
|
|
|
newAlt.m_Shape = m_pin->GetShape();
|
|
|
|
|
|
|
|
m_alternatesDataModel->AppendRow( newAlt );
|
|
|
|
|
|
|
|
m_alternatesGrid->MakeCellVisible( m_alternatesGrid->GetNumberRows() - 1, 0 );
|
|
|
|
m_alternatesGrid->SetGridCursor( m_alternatesGrid->GetNumberRows() - 1, 0 );
|
|
|
|
|
|
|
|
m_alternatesGrid->EnableCellEditControl( true );
|
|
|
|
m_alternatesGrid->ShowCellEditControl();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DIALOG_PIN_PROPERTIES::OnDeleteAlternate( wxCommandEvent& event )
|
|
|
|
{
|
2025-07-24 17:55:00 +01:00
|
|
|
m_alternatesGrid->OnDeleteRows(
|
|
|
|
[&]( int row )
|
|
|
|
{
|
|
|
|
m_alternatesDataModel->RemoveRow( row );
|
|
|
|
} );
|
2020-08-21 16:54:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-12-16 17:39:58 +03:00
|
|
|
void DIALOG_PIN_PROPERTIES::adjustGridColumns()
|
2020-08-21 16:54:24 +01:00
|
|
|
{
|
2021-12-16 17:39:58 +03:00
|
|
|
// Account for scroll bars
|
|
|
|
int width = KIPLATFORM::UI::GetUnobscuredSize( m_alternatesGrid ).x;
|
2020-08-21 16:54:24 +01:00
|
|
|
|
|
|
|
wxGridUpdateLocker deferRepaintsTillLeavingScope;
|
|
|
|
|
2021-12-16 17:39:58 +03:00
|
|
|
m_alternatesGrid->SetColSize( COL_TYPE, m_originalColWidths[COL_TYPE] );
|
|
|
|
m_alternatesGrid->SetColSize( COL_SHAPE, m_originalColWidths[COL_SHAPE] );
|
2020-08-21 16:54:24 +01:00
|
|
|
|
2025-06-19 14:11:04 +01:00
|
|
|
m_alternatesGrid->SetColSize( COL_NAME, width - m_originalColWidths[COL_TYPE] - m_originalColWidths[COL_SHAPE] );
|
2020-08-21 16:54:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DIALOG_PIN_PROPERTIES::OnSize( wxSizeEvent& event )
|
|
|
|
{
|
2021-12-17 07:00:24 +03:00
|
|
|
auto new_size = event.GetSize();
|
2020-08-21 16:54:24 +01:00
|
|
|
|
2021-12-17 07:00:24 +03:00
|
|
|
if( m_initialized && m_size != new_size )
|
2021-12-16 17:39:58 +03:00
|
|
|
{
|
2021-12-17 07:00:24 +03:00
|
|
|
m_size = new_size;
|
2021-12-16 17:39:58 +03:00
|
|
|
|
|
|
|
adjustGridColumns();
|
|
|
|
}
|
2020-08-21 16:54:24 +01:00
|
|
|
|
|
|
|
// Always propagate for a grid repaint (needed if the height changes, as well as width)
|
|
|
|
event.Skip();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DIALOG_PIN_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& event )
|
|
|
|
{
|
|
|
|
// Handle a delayed focus
|
|
|
|
if( m_delayedFocusRow >= 0 )
|
|
|
|
{
|
|
|
|
m_alternatesTurndown->Collapse( false );
|
|
|
|
|
|
|
|
m_alternatesGrid->SetFocus();
|
|
|
|
m_alternatesGrid->MakeCellVisible( m_delayedFocusRow, m_delayedFocusColumn );
|
|
|
|
m_alternatesGrid->SetGridCursor( m_delayedFocusRow, m_delayedFocusColumn );
|
|
|
|
|
|
|
|
m_alternatesGrid->EnableCellEditControl( true );
|
|
|
|
m_alternatesGrid->ShowCellEditControl();
|
|
|
|
|
|
|
|
m_delayedFocusRow = -1;
|
|
|
|
m_delayedFocusColumn = -1;
|
|
|
|
}
|
|
|
|
}
|
2025-01-18 10:32:42 -05:00
|
|
|
|
|
|
|
|
2023-01-26 10:46:03 -05:00
|
|
|
void DIALOG_PIN_PROPERTIES::OnCollapsiblePaneChange( wxCollapsiblePaneEvent& event )
|
|
|
|
{
|
|
|
|
if( !event.GetCollapsed() )
|
|
|
|
{
|
|
|
|
wxTopLevelWindow* tlw = dynamic_cast<wxTopLevelWindow*>( wxGetTopLevelParent( this ) );
|
|
|
|
|
|
|
|
if( tlw )
|
|
|
|
{
|
|
|
|
tlw->InvalidateBestSize();
|
|
|
|
wxSize bestSize = tlw->GetBestSize();
|
|
|
|
wxSize currentSize = tlw->GetSize();
|
|
|
|
tlw->SetSize( wxMax( bestSize.GetWidth(), currentSize.GetWidth() ),
|
|
|
|
wxMax( bestSize.GetHeight(), currentSize.GetHeight() ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|