/* * This program source code file is part of KICAD, a free EDA CAD application. * * Copyright (C) 2020 CERN * Copyright (C) 2021-2022 KiCad Developers, see AUTHORS.txt for contributors. * @author Maciej Suminski * * 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 . */ #include "pcb_properties_panel.h" #include #include #include #include #include #include #include #include #include #include #include #include #include PCB_PROPERTIES_PANEL::PCB_PROPERTIES_PANEL( wxWindow* aParent, PCB_EDIT_FRAME* aFrame ) : PROPERTIES_PANEL( aParent, aFrame ), m_frame( aFrame ), m_propMgr( PROPERTY_MANAGER::Instance() ) { m_propMgr.Rebuild(); bool found = false; wxASSERT( wxPGGlobalVars ); auto it = wxPGGlobalVars->m_mapEditorClasses.find( PG_UNIT_EDITOR::EDITOR_NAME ); if( it != wxPGGlobalVars->m_mapEditorClasses.end() ) { m_editor = static_cast( it->second ); m_editor->UpdateFrame( m_frame ); found = true; } if( !found ) { PG_UNIT_EDITOR* new_editor = new PG_UNIT_EDITOR( m_frame ); m_editor = static_cast( wxPropertyGrid::RegisterEditorClass( new_editor ) ); } } PCB_PROPERTIES_PANEL::~PCB_PROPERTIES_PANEL() { m_editor->UpdateFrame( nullptr ); } void PCB_PROPERTIES_PANEL::UpdateData() { PCB_SELECTION_TOOL* selectionTool = m_frame->GetToolManager()->GetTool(); const SELECTION& selection = selectionTool->GetSelection(); // TODO perhaps it could be called less often? use PROPERTIES_TOOL and catch MODEL_RELOAD? updateLists( static_cast( m_frame )->GetBoard() ); update( selection ); } void PCB_PROPERTIES_PANEL::AfterCommit() { PCB_SELECTION_TOOL* selectionTool = m_frame->GetToolManager()->GetTool(); const SELECTION& selection = selectionTool->GetSelection(); BOARD_ITEM* firstItem = static_cast( 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() ); wxCHECK2( property, continue ); bool writeable = true; for( EDA_ITEM* edaItem : selection ) writeable &= property->Writeable( edaItem ); pgProp->Enable( writeable ); } CallAfter( [&]() { static_cast( m_frame )->GetCanvas()->SetFocus(); } ); } wxPGProperty* PCB_PROPERTIES_PANEL::createPGProperty( const PROPERTY_BASE* aProperty ) const { if( aProperty->TypeHash() == TYPE_HASH( PCB_LAYER_ID ) ) { wxASSERT( aProperty->HasChoices() ); auto ret = new PGPROPERTY_COLORENUM( wxPG_LABEL, wxPG_LABEL, const_cast( aProperty->Choices() ) ); ret->SetColorFunc( [&]( const wxString& aChoice ) -> wxColour { PCB_LAYER_ID l = ENUM_MAP::Instance().ToEnum( aChoice ); wxASSERT( IsPcbLayer( l ) ); return m_frame->GetColorSettings()->GetColor( l ).ToColour(); } ); ret->SetLabel( wxGetTranslation( aProperty->Name() ) ); ret->SetName( aProperty->Name() ); ret->SetHelpString( wxGetTranslation( aProperty->Name() ) ); ret->SetClientData( const_cast( aProperty ) ); return ret; } return PGPropertyFactory( aProperty ); } void PCB_PROPERTIES_PANEL::valueChanged( wxPropertyGridEvent& aEvent ) { PCB_SELECTION_TOOL* selectionTool = m_frame->GetToolManager()->GetTool(); const SELECTION& selection = selectionTool->GetSelection(); BOARD_ITEM* firstItem = static_cast( selection.Front() ); wxCHECK( firstItem, /* void */ ); PROPERTY_BASE* property = m_propMgr.GetProperty( TYPE_HASH( *firstItem ), aEvent.GetPropertyName() ); wxVariant newValue = aEvent.GetPropertyValue(); BOARD_COMMIT changes( m_frame ); for( EDA_ITEM* edaItem : selection ) { BOARD_ITEM* item = static_cast( edaItem ); changes.Modify( item ); item->Set( property, newValue ); } // Pushing the commit will result in a SelectedItemsModified event, which we want to skip m_skipNextUpdate = true; changes.Push( _( "Change property" ) ); m_frame->Refresh(); // Perform grid updates as necessary based on value change AfterCommit(); } void PCB_PROPERTIES_PANEL::updateLists( const BOARD* aBoard ) { wxPGChoices layersAll, layersCu, nets; // Regenerate all layers for( LSEQ seq = aBoard->GetEnabledLayers().UIOrder(); seq; ++seq ) layersAll.Add( LSET::Name( *seq ), *seq ); for( LSEQ seq = LSET( aBoard->GetEnabledLayers() & LSET::AllCuMask() ).UIOrder(); seq; ++seq ) layersCu.Add( LSET::Name( *seq ), *seq ); m_propMgr.GetProperty( TYPE_HASH( BOARD_ITEM ), _HKI( "Layer" ) )->SetChoices( layersAll ); m_propMgr.GetProperty( TYPE_HASH( PCB_SHAPE ), _HKI( "Layer" ) )->SetChoices( layersAll ); // Copper only properties m_propMgr.GetProperty( TYPE_HASH( BOARD_CONNECTED_ITEM ), _HKI( "Layer" ) )->SetChoices( layersCu ); m_propMgr.GetProperty( TYPE_HASH( PCB_VIA ), _HKI( "Layer Top" ) )->SetChoices( layersCu ); m_propMgr.GetProperty( TYPE_HASH( PCB_VIA ), _HKI( "Layer Bottom" ) )->SetChoices( layersCu ); // Regenerate nets for( const auto& [ netCode, netInfo ] : aBoard->GetNetInfo().NetsByNetcode() ) nets.Add( UnescapeString( netInfo->GetNetname() ), netCode ); auto netProperty = m_propMgr.GetProperty( TYPE_HASH( BOARD_CONNECTED_ITEM ), _HKI( "Net" ) ); netProperty->SetChoices( nets ); }