2020-02-04 08:40:25 +00:00
|
|
|
/*
|
|
|
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2020 CERN
|
2022-12-03 22:34:47 +00:00
|
|
|
* Copyright (C) 2021-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
2020-02-04 08:40:25 +00:00
|
|
|
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
|
|
|
*
|
|
|
|
* 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 "pcb_properties_panel.h"
|
|
|
|
|
|
|
|
#include <pcb_edit_frame.h>
|
|
|
|
#include <tool/tool_manager.h>
|
|
|
|
#include <tools/pcb_selection_tool.h>
|
2022-11-03 02:50:49 +00:00
|
|
|
#include <properties/property_mgr.h>
|
|
|
|
#include <properties/pg_editors.h>
|
2020-02-04 08:40:25 +00:00
|
|
|
#include <board_commit.h>
|
|
|
|
#include <board_connected_item.h>
|
2022-11-03 02:50:49 +00:00
|
|
|
#include <properties/pg_properties.h>
|
2020-02-04 08:40:25 +00:00
|
|
|
#include <pcb_shape.h>
|
2022-11-25 01:34:40 +00:00
|
|
|
#include <pcb_text.h>
|
2022-05-12 18:16:11 +00:00
|
|
|
#include <pcb_track.h>
|
2021-08-22 15:59:02 +00:00
|
|
|
#include <settings/color_settings.h>
|
2022-11-25 18:15:46 +00:00
|
|
|
#include <string_utils.h>
|
2020-02-04 08:40:25 +00:00
|
|
|
|
|
|
|
|
2022-12-05 02:07:45 +00:00
|
|
|
PCB_PROPERTIES_PANEL::PCB_PROPERTIES_PANEL( wxWindow* aParent, PCB_EDIT_FRAME* aFrame ) :
|
|
|
|
PROPERTIES_PANEL( aParent, aFrame ),
|
|
|
|
m_frame( aFrame ),
|
|
|
|
m_propMgr( PROPERTY_MANAGER::Instance() )
|
2020-02-04 08:40:25 +00:00
|
|
|
{
|
|
|
|
m_propMgr.Rebuild();
|
2022-11-29 16:31:00 +00:00
|
|
|
bool found = false;
|
|
|
|
|
2022-12-08 12:55:57 +00:00
|
|
|
wxASSERT( wxPGGlobalVars );
|
|
|
|
|
|
|
|
auto it = wxPGGlobalVars->m_mapEditorClasses.find( PG_UNIT_EDITOR::EDITOR_NAME );
|
|
|
|
|
|
|
|
if( it != wxPGGlobalVars->m_mapEditorClasses.end() )
|
2022-11-29 16:31:00 +00:00
|
|
|
{
|
2022-12-08 12:55:57 +00:00
|
|
|
m_editor = static_cast<PG_UNIT_EDITOR*>( it->second );
|
|
|
|
m_editor->UpdateFrame( m_frame );
|
|
|
|
found = true;
|
2022-11-29 16:31:00 +00:00
|
|
|
}
|
|
|
|
|
2022-12-04 18:25:57 +00:00
|
|
|
if( !found )
|
|
|
|
{
|
|
|
|
PG_UNIT_EDITOR* new_editor = new PG_UNIT_EDITOR( m_frame );
|
2022-11-29 16:31:00 +00:00
|
|
|
m_editor = static_cast<PG_UNIT_EDITOR*>( wxPropertyGrid::RegisterEditorClass( new_editor ) );
|
2022-12-04 18:25:57 +00:00
|
|
|
}
|
2022-11-22 00:34:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PCB_PROPERTIES_PANEL::~PCB_PROPERTIES_PANEL()
|
|
|
|
{
|
2022-11-29 16:31:00 +00:00
|
|
|
m_editor->UpdateFrame( nullptr );
|
2020-02-04 08:40:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-03-30 15:27:17 +00:00
|
|
|
void PCB_PROPERTIES_PANEL::UpdateData()
|
2020-02-04 08:40:25 +00:00
|
|
|
{
|
|
|
|
PCB_SELECTION_TOOL* selectionTool = m_frame->GetToolManager()->GetTool<PCB_SELECTION_TOOL>();
|
|
|
|
const SELECTION& selection = selectionTool->GetSelection();
|
|
|
|
|
|
|
|
// TODO perhaps it could be called less often? use PROPERTIES_TOOL and catch MODEL_RELOAD?
|
|
|
|
updateLists( static_cast<PCB_EDIT_FRAME*>( m_frame )->GetBoard() );
|
|
|
|
update( selection );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-12-09 03:24:13 +00:00
|
|
|
void PCB_PROPERTIES_PANEL::AfterCommit()
|
|
|
|
{
|
|
|
|
PCB_SELECTION_TOOL* selectionTool = m_frame->GetToolManager()->GetTool<PCB_SELECTION_TOOL>();
|
|
|
|
const SELECTION& selection = selectionTool->GetSelection();
|
|
|
|
BOARD_ITEM* firstItem = static_cast<BOARD_ITEM*>( selection.Front() );
|
|
|
|
|
|
|
|
for( wxPropertyGridIterator it = m_grid->GetIterator(); !it.AtEnd(); it.Next() )
|
|
|
|
{
|
|
|
|
wxPGProperty* pgProp = it.GetProperty();
|
|
|
|
|
|
|
|
PROPERTY_BASE* property = m_propMgr.GetProperty( TYPE_HASH( *firstItem ),
|
|
|
|
pgProp->GetName() );
|
2022-12-26 19:04:53 +00:00
|
|
|
wxCHECK2( property, continue );
|
2022-12-09 03:24:13 +00:00
|
|
|
|
|
|
|
bool writeable = true;
|
|
|
|
|
|
|
|
for( EDA_ITEM* edaItem : selection )
|
|
|
|
writeable &= property->Writeable( edaItem );
|
|
|
|
|
|
|
|
pgProp->Enable( writeable );
|
|
|
|
}
|
2022-12-26 21:45:20 +00:00
|
|
|
|
|
|
|
CallAfter( [&]()
|
|
|
|
{
|
|
|
|
static_cast<PCB_EDIT_FRAME*>( m_frame )->GetCanvas()->SetFocus();
|
|
|
|
} );
|
2022-12-09 03:24:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-02-04 08:40:25 +00:00
|
|
|
wxPGProperty* PCB_PROPERTIES_PANEL::createPGProperty( const PROPERTY_BASE* aProperty ) const
|
|
|
|
{
|
2021-08-22 15:59:02 +00:00
|
|
|
if( aProperty->TypeHash() == TYPE_HASH( PCB_LAYER_ID ) )
|
|
|
|
{
|
|
|
|
wxASSERT( aProperty->HasChoices() );
|
|
|
|
|
2022-12-03 22:34:47 +00:00
|
|
|
auto ret = new PGPROPERTY_COLORENUM( wxPG_LABEL, wxPG_LABEL,
|
|
|
|
const_cast<wxPGChoices&>( aProperty->Choices() ) );
|
2021-08-22 15:59:02 +00:00
|
|
|
|
|
|
|
ret->SetColorFunc(
|
|
|
|
[&]( const wxString& aChoice ) -> wxColour
|
|
|
|
{
|
|
|
|
PCB_LAYER_ID l = ENUM_MAP<PCB_LAYER_ID>::Instance().ToEnum( aChoice );
|
|
|
|
wxASSERT( IsPcbLayer( l ) );
|
|
|
|
return m_frame->GetColorSettings()->GetColor( l ).ToColour();
|
|
|
|
} );
|
|
|
|
|
2022-12-21 23:03:15 +00:00
|
|
|
ret->SetLabel( wxGetTranslation( aProperty->Name() ) );
|
2021-08-22 15:59:02 +00:00
|
|
|
ret->SetName( aProperty->Name() );
|
2022-12-22 22:44:14 +00:00
|
|
|
ret->SetHelpString( wxGetTranslation( aProperty->Name() ) );
|
2021-08-22 15:59:02 +00:00
|
|
|
ret->SetClientData( const_cast<PROPERTY_BASE*>( aProperty ) );
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2020-02-04 08:40:25 +00:00
|
|
|
return PGPropertyFactory( aProperty );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PCB_PROPERTIES_PANEL::valueChanged( wxPropertyGridEvent& aEvent )
|
|
|
|
{
|
|
|
|
PCB_SELECTION_TOOL* selectionTool = m_frame->GetToolManager()->GetTool<PCB_SELECTION_TOOL>();
|
|
|
|
const SELECTION& selection = selectionTool->GetSelection();
|
|
|
|
BOARD_ITEM* firstItem = static_cast<BOARD_ITEM*>( selection.Front() );
|
2023-01-06 01:32:35 +00:00
|
|
|
|
|
|
|
wxCHECK( firstItem, /* void */ );
|
|
|
|
|
2022-11-25 21:29:56 +00:00
|
|
|
PROPERTY_BASE* property = m_propMgr.GetProperty( TYPE_HASH( *firstItem ),
|
|
|
|
aEvent.GetPropertyName() );
|
2020-02-04 08:40:25 +00:00
|
|
|
wxVariant newValue = aEvent.GetPropertyValue();
|
|
|
|
BOARD_COMMIT changes( m_frame );
|
|
|
|
|
|
|
|
for( EDA_ITEM* edaItem : selection )
|
|
|
|
{
|
|
|
|
BOARD_ITEM* item = static_cast<BOARD_ITEM*>( edaItem );
|
|
|
|
changes.Modify( item );
|
|
|
|
item->Set( property, newValue );
|
|
|
|
}
|
|
|
|
|
2022-11-27 19:28:59 +00:00
|
|
|
// Pushing the commit will result in a SelectedItemsModified event, which we want to skip
|
|
|
|
m_skipNextUpdate = true;
|
|
|
|
|
2020-02-04 08:40:25 +00:00
|
|
|
changes.Push( _( "Change property" ) );
|
|
|
|
m_frame->Refresh();
|
2022-12-09 03:24:13 +00:00
|
|
|
|
|
|
|
// Perform grid updates as necessary based on value change
|
|
|
|
AfterCommit();
|
2020-02-04 08:40:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PCB_PROPERTIES_PANEL::updateLists( const BOARD* aBoard )
|
|
|
|
{
|
2022-05-12 18:16:11 +00:00
|
|
|
wxPGChoices layersAll, layersCu, nets;
|
2020-02-04 08:40:25 +00:00
|
|
|
|
|
|
|
// Regenerate all layers
|
2022-05-12 18:16:11 +00:00
|
|
|
for( LSEQ seq = aBoard->GetEnabledLayers().UIOrder(); seq; ++seq )
|
|
|
|
layersAll.Add( LSET::Name( *seq ), *seq );
|
2020-02-04 08:40:25 +00:00
|
|
|
|
2022-05-12 18:16:11 +00:00
|
|
|
for( LSEQ seq = LSET( aBoard->GetEnabledLayers() & LSET::AllCuMask() ).UIOrder(); seq; ++seq )
|
|
|
|
layersCu.Add( LSET::Name( *seq ), *seq );
|
2022-05-05 18:48:58 +00:00
|
|
|
|
2022-05-12 18:16:11 +00:00
|
|
|
m_propMgr.GetProperty( TYPE_HASH( BOARD_ITEM ), _HKI( "Layer" ) )->SetChoices( layersAll );
|
|
|
|
m_propMgr.GetProperty( TYPE_HASH( PCB_SHAPE ), _HKI( "Layer" ) )->SetChoices( layersAll );
|
2022-05-05 18:48:58 +00:00
|
|
|
|
2022-05-12 18:16:11 +00:00
|
|
|
// Copper only properties
|
2022-11-25 21:29:56 +00:00
|
|
|
m_propMgr.GetProperty( TYPE_HASH( BOARD_CONNECTED_ITEM ),
|
|
|
|
_HKI( "Layer" ) )->SetChoices( layersCu );
|
2022-05-12 18:16:11 +00:00
|
|
|
m_propMgr.GetProperty( TYPE_HASH( PCB_VIA ), _HKI( "Layer Top" ) )->SetChoices( layersCu );
|
|
|
|
m_propMgr.GetProperty( TYPE_HASH( PCB_VIA ), _HKI( "Layer Bottom" ) )->SetChoices( layersCu );
|
2020-02-04 08:40:25 +00:00
|
|
|
|
|
|
|
// Regenerate nets
|
2022-12-03 22:34:47 +00:00
|
|
|
for( const auto& [ netCode, netInfo ] : aBoard->GetNetInfo().NetsByNetcode() )
|
|
|
|
nets.Add( UnescapeString( netInfo->GetNetname() ), netCode );
|
2020-02-04 08:40:25 +00:00
|
|
|
|
2022-12-03 22:34:47 +00:00
|
|
|
auto netProperty = m_propMgr.GetProperty( TYPE_HASH( BOARD_CONNECTED_ITEM ), _HKI( "Net" ) );
|
2020-02-04 08:40:25 +00:00
|
|
|
netProperty->SetChoices( nets );
|
|
|
|
}
|