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
|
|
|
|
* @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 "properties_panel.h"
|
|
|
|
#include <tool/selection.h>
|
|
|
|
#include <eda_base_frame.h>
|
|
|
|
#include <eda_item.h>
|
2020-10-19 01:57:18 +00:00
|
|
|
#include <import_export.h>
|
2020-02-04 08:40:25 +00:00
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
#include <set>
|
|
|
|
|
2021-08-22 14:15:49 +00:00
|
|
|
#include <wx/settings.h>
|
|
|
|
#include <wx/stattext.h>
|
|
|
|
|
2020-02-04 08:40:25 +00:00
|
|
|
|
2020-10-19 01:57:18 +00:00
|
|
|
extern APIIMPORT wxPGGlobalVarsClass* wxPGGlobalVars;
|
2020-04-07 18:13:19 +00:00
|
|
|
|
2020-02-04 08:40:25 +00:00
|
|
|
PROPERTIES_PANEL::PROPERTIES_PANEL( wxWindow* aParent, EDA_BASE_FRAME* aFrame )
|
|
|
|
: wxPanel( aParent ), m_frame( aFrame )
|
|
|
|
{
|
|
|
|
wxBoxSizer* mainSizer = new wxBoxSizer( wxVERTICAL );
|
|
|
|
|
2020-04-07 18:13:19 +00:00
|
|
|
// on some platforms wxPGGlobalVars is initialized automatically,
|
|
|
|
// but others need an explicit init
|
|
|
|
if( !wxPGGlobalVars )
|
|
|
|
wxPGInitResourceModule();
|
|
|
|
|
2021-08-22 14:15:49 +00:00
|
|
|
m_caption = new wxStaticText( this, wxID_ANY, _( "No objects selected" ), wxDefaultPosition,
|
|
|
|
wxDefaultSize, 0 );
|
|
|
|
mainSizer->Add( m_caption, 0, wxALL | wxEXPAND, 5 );
|
|
|
|
|
2020-02-04 08:40:25 +00:00
|
|
|
m_grid = new wxPropertyGrid( this, wxID_ANY, wxDefaultPosition, wxSize( 300, 400 ),
|
2021-08-22 14:15:49 +00:00
|
|
|
wxPG_AUTO_SORT | wxPG_DEFAULT_STYLE );
|
2020-10-19 01:57:18 +00:00
|
|
|
m_grid->SetUnspecifiedValueAppearance( wxPGCell( wxT( "<...>" ) ) );
|
2020-02-04 08:40:25 +00:00
|
|
|
mainSizer->Add( m_grid, 1, wxALL | wxEXPAND, 5 );
|
|
|
|
|
2021-08-22 14:15:49 +00:00
|
|
|
m_grid->SetCellDisabledTextColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) );
|
|
|
|
|
2020-02-04 08:40:25 +00:00
|
|
|
SetSizer( mainSizer );
|
|
|
|
Layout();
|
|
|
|
|
2021-08-22 14:15:49 +00:00
|
|
|
m_grid->CenterSplitter();
|
|
|
|
|
2020-02-04 08:40:25 +00:00
|
|
|
Connect( wxEVT_PG_CHANGED, wxPropertyGridEventHandler( PROPERTIES_PANEL::valueChanged ), NULL, this );
|
|
|
|
Connect( wxEVT_PG_CHANGING, wxPropertyGridEventHandler( PROPERTIES_PANEL::valueChanging ), NULL, this );
|
2020-02-06 11:43:32 +00:00
|
|
|
Connect( wxEVT_SHOW, wxShowEventHandler( PROPERTIES_PANEL::onShow ), NULL, this );
|
2020-02-04 08:40:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PROPERTIES_PANEL::update( const SELECTION& aSelection )
|
|
|
|
{
|
|
|
|
m_grid->Clear();
|
|
|
|
m_displayed.clear();
|
|
|
|
|
|
|
|
if( aSelection.Empty() )
|
2021-08-22 14:15:49 +00:00
|
|
|
{
|
|
|
|
m_caption->SetLabel( _( "No objects selected" ) );
|
2020-02-04 08:40:25 +00:00
|
|
|
return;
|
2021-08-22 14:15:49 +00:00
|
|
|
}
|
2020-02-04 08:40:25 +00:00
|
|
|
|
|
|
|
// Get all the selected types
|
2021-08-22 14:15:49 +00:00
|
|
|
std::set<TYPE_ID> types;
|
2020-02-04 08:40:25 +00:00
|
|
|
|
|
|
|
for( EDA_ITEM* item : aSelection )
|
|
|
|
types.insert( TYPE_HASH( *item ) );
|
|
|
|
|
|
|
|
wxCHECK( !types.empty(), /* void */ );
|
2021-08-22 14:15:49 +00:00
|
|
|
|
|
|
|
if( aSelection.Size() > 1 )
|
|
|
|
{
|
|
|
|
m_caption->SetLabel( _( "Multiple objects selected" ) );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-05-08 22:54:24 +00:00
|
|
|
m_caption->SetLabel( aSelection.Front()->GetTypeDesc() );
|
2021-08-22 14:15:49 +00:00
|
|
|
}
|
|
|
|
|
2020-02-04 08:40:25 +00:00
|
|
|
PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
|
|
|
|
propMgr.SetUnits( m_frame->GetUserUnits() );
|
|
|
|
|
2021-08-22 14:15:49 +00:00
|
|
|
std::set<PROPERTY_BASE*> commonProps;
|
2020-02-04 08:40:25 +00:00
|
|
|
const PROPERTY_LIST& allProperties = propMgr.GetProperties( *types.begin() );
|
|
|
|
copy( allProperties.begin(), allProperties.end(), inserter( commonProps, commonProps.begin() ) );
|
|
|
|
|
|
|
|
// Get all possible properties
|
|
|
|
for( const auto& type : types )
|
|
|
|
{
|
|
|
|
const PROPERTY_LIST& itemProps = propMgr.GetProperties( type );
|
|
|
|
|
|
|
|
for( auto it = commonProps.begin(); it != commonProps.end(); /* ++it in the loop */ )
|
|
|
|
{
|
|
|
|
if( !binary_search( itemProps.begin(), itemProps.end(), *it ) )
|
|
|
|
it = commonProps.erase( it );
|
|
|
|
else
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find a set of properties that is common to all selected items
|
|
|
|
for( const auto& property : commonProps )
|
|
|
|
{
|
|
|
|
if( !property->Available( aSelection.Front() ) )
|
|
|
|
continue;
|
|
|
|
|
2020-03-29 19:14:10 +00:00
|
|
|
// Either determine the common value for a property or "<...>" to indicate multiple values
|
2020-02-04 08:40:25 +00:00
|
|
|
bool available = true;
|
|
|
|
wxVariant commonVal, itemVal;
|
|
|
|
|
|
|
|
for( EDA_ITEM* item : aSelection )
|
|
|
|
{
|
2020-03-29 19:14:10 +00:00
|
|
|
if( !property->Available( item ) )
|
|
|
|
break; // there is an item that does not have this property, so do not display it
|
2020-02-04 08:40:25 +00:00
|
|
|
|
2020-03-29 19:14:10 +00:00
|
|
|
wxVariant& value = commonVal.IsNull() ? commonVal : itemVal;
|
|
|
|
const wxAny& any = item->Get( property );
|
|
|
|
bool converted = false;
|
2020-02-04 08:40:25 +00:00
|
|
|
|
2020-03-29 19:14:10 +00:00
|
|
|
if( property->HasChoices() )
|
2020-02-04 08:40:25 +00:00
|
|
|
{
|
2020-03-29 19:14:10 +00:00
|
|
|
// handle enums as ints, since there are no default conversion functions for wxAny
|
2020-02-04 08:40:25 +00:00
|
|
|
int tmp;
|
2020-03-29 19:14:10 +00:00
|
|
|
converted = any.GetAs<int>( &tmp );
|
2020-02-04 08:40:25 +00:00
|
|
|
|
2020-03-29 19:14:10 +00:00
|
|
|
if( converted )
|
2020-02-04 08:40:25 +00:00
|
|
|
value = wxVariant( tmp );
|
|
|
|
}
|
|
|
|
|
2020-03-29 19:14:10 +00:00
|
|
|
if( !converted ) // all other types
|
|
|
|
converted = any.GetAs( &value );
|
|
|
|
|
|
|
|
if( !converted )
|
|
|
|
{
|
|
|
|
wxFAIL_MSG( "Could not convert wxAny to wxVariant" );
|
|
|
|
available = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( !commonVal.IsNull() && value != commonVal )
|
2020-02-04 08:40:25 +00:00
|
|
|
{
|
|
|
|
commonVal.MakeNull(); // items have different values for this property
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( available )
|
|
|
|
{
|
|
|
|
wxPGProperty* pgProp = createPGProperty( property );
|
|
|
|
|
|
|
|
if( pgProp )
|
|
|
|
{
|
|
|
|
pgProp->SetValue( commonVal );
|
|
|
|
m_grid->Append( pgProp );
|
|
|
|
m_displayed.push_back( property );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m_grid->FitColumns();
|
|
|
|
}
|
2020-02-06 11:43:32 +00:00
|
|
|
|
|
|
|
|
|
|
|
void PROPERTIES_PANEL::onShow( wxShowEvent& aEvent )
|
|
|
|
{
|
|
|
|
if( aEvent.IsShown() )
|
2020-03-30 15:27:17 +00:00
|
|
|
UpdateData();
|
2020-02-06 11:43:32 +00:00
|
|
|
}
|