KiCad PCB EDA Suite
pg_properties.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KICAD, a free EDA CAD application.
3 *
4 * Copyright (C) 2020 CERN
5 * Copyright (C) 2021-2023 KiCad Developers, see AUTHORS.TXT for contributors.
6 * @author Maciej Suminski <[email protected]>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 3
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include <wx/dc.h>
23#include <wx/propgrid/propgrid.h>
24
25#include <macros.h>
26#include <validators.h>
27#include <eda_units.h>
32#include <properties/property.h>
33#include <string_utils.h>
35
36// reg-ex describing a signed valid value with a unit
37static const wxChar REGEX_SIGNED_DISTANCE[] = wxT( "([-+]?[0-9]+[\\.?[0-9]*) *(mm|in|mils)*" );
38static const wxChar REGEX_UNSIGNED_DISTANCE[] = wxT( "([0-9]+[\\.?[0-9]*) *(mm|in|mils)*" );
39
40
41class wxAnyToEDA_ANGLE_VARIANTRegistrationImpl : public wxAnyToVariantRegistration
42{
43public:
44 wxAnyToEDA_ANGLE_VARIANTRegistrationImpl( wxVariantDataFactory factory )
45 : wxAnyToVariantRegistration( factory )
46 {
47 }
48
49public:
50 static bool IsSameClass(const wxAnyValueType* otherType)
51 {
52 return AreSameClasses( *s_instance.get(), *otherType );
53 }
54
55 static wxAnyValueType* GetInstance()
56 {
57 return s_instance.get();
58 }
59
60 virtual wxAnyValueType* GetAssociatedType() override
61 {
63 }
64private:
65 static bool AreSameClasses(const wxAnyValueType& a, const wxAnyValueType& b)
66 {
67 return wxTypeId(a) == wxTypeId(b);
68 }
69
70 static wxAnyValueTypeScopedPtr s_instance;
71};
72
73
74wxAnyValueTypeScopedPtr wxAnyToEDA_ANGLE_VARIANTRegistrationImpl::s_instance( new wxAnyValueTypeImpl<EDA_ANGLE>() );
75
76static wxAnyToEDA_ANGLE_VARIANTRegistrationImpl s_wxAnyToEDA_ANGLE_VARIANTRegistration( &EDA_ANGLE_VARIANT_DATA::VariantDataFactory );
77
78
79wxPGProperty* PGPropertyFactory( const PROPERTY_BASE* aProperty )
80{
81 wxPGProperty* ret = nullptr;
82 PROPERTY_DISPLAY display = aProperty->Display();
83
84 switch( display )
85 {
87 ret = new PGPROPERTY_SIZE();
88 ret->SetEditor( PG_UNIT_EDITOR::EDITOR_NAME );
89 break;
90
92 ret = new PGPROPERTY_COORD();
93 static_cast<PGPROPERTY_COORD*>( ret )->SetCoordType( aProperty->CoordType() );
94 ret->SetEditor( PG_UNIT_EDITOR::EDITOR_NAME );
95 break;
96
99 {
101
102 if( display == PROPERTY_DISPLAY::PT_DECIDEGREE )
103 prop->SetScale( 10.0 );
104
105 ret = prop;
106 ret->SetEditor( PG_UNIT_EDITOR::EDITOR_NAME );
107 break;
108 }
109
110 default:
111 wxFAIL;
113 /* fall through */
115 {
116 // Create a corresponding wxPGProperty
117 size_t typeId = aProperty->TypeHash();
118
119 // Enum property
120 if( aProperty->HasChoices() )
121 {
122 // I do not know why enum property takes a non-const reference to wxPGChoices..
123 ret = new wxEnumProperty( wxPG_LABEL, wxPG_LABEL,
124 const_cast<wxPGChoices&>( aProperty->Choices() ) );
125 }
126 else if( typeId == TYPE_HASH( int ) || typeId == TYPE_HASH( long ) )
127 {
128 ret = new wxIntProperty();
129 }
130 else if( typeId == TYPE_HASH( unsigned int ) || typeId == TYPE_HASH( unsigned long ) )
131 {
132 ret = new wxUIntProperty();
133 }
134 else if( typeId == TYPE_HASH( float ) || typeId == TYPE_HASH( double ) )
135 {
136 ret = new wxFloatProperty();
137 }
138 else if( typeId == TYPE_HASH( bool ) )
139 {
140 ret = new PGPROPERTY_BOOL();
141 }
142 else if( typeId == TYPE_HASH( wxString ) )
143 {
144 ret = new PGPROPERTY_STRING();
145 }
146 else
147 {
148 wxFAIL_MSG( wxString::Format( wxS( "Property %s not supported by PGPropertyFactory" ),
149 aProperty->Name() ) );
150 ret = new wxPropertyCategory();
151 ret->Enable( false );
152 }
153 break;
154 }
155 }
156
157 if( ret )
158 {
159 ret->SetLabel( wxGetTranslation( aProperty->Name() ) );
160 ret->SetName( aProperty->Name() );
161 ret->SetHelpString( wxGetTranslation( aProperty->Name() ) );
162 ret->SetClientData( const_cast<PROPERTY_BASE*>( aProperty ) );
163 }
164
165 return ret;
166}
167
168
171 m_coordType( aCoordType )
172{
173 m_regExValidator.reset( new REGEX_VALIDATOR( aRegEx ) );
174}
175
176
178{
179}
180
181
182bool PGPROPERTY_DISTANCE::StringToDistance( wxVariant& aVariant, const wxString& aText,
183 int aArgFlags ) const
184{
185 // TODO(JE): Are there actual use cases for this?
186 wxCHECK_MSG( false, false, wxS( "PGPROPERTY_DISTANCE::StringToDistance should not be used." ) );
187}
188
189
190wxString PGPROPERTY_DISTANCE::DistanceToString( wxVariant& aVariant, int aArgFlags ) const
191{
192 wxCHECK( aVariant.GetType() == wxPG_VARIANT_TYPE_LONG, wxEmptyString );
193
194 long distanceIU = aVariant.GetLong();
195
197
198 if( transforms )
199 distanceIU = transforms->ToDisplay( static_cast<long long int>( distanceIU ), m_coordType );
200
201 switch( PROPERTY_MANAGER::Instance().GetUnits() )
202 {
204 return wxString::Format( wxS( "%g in" ), pcbIUScale.IUToMils( distanceIU ) / 1000.0 );
205
206 case EDA_UNITS::MILS:
207 return wxString::Format( wxS( "%d mils" ), pcbIUScale.IUToMils( distanceIU ) );
208
210 return wxString::Format( wxS( "%g mm" ), pcbIUScale.IUTomm( distanceIU ) );
211
213 return wxString::Format( wxS( "%li" ), distanceIU );
214
215 default:
216 // DEGREEs are handled by PGPROPERTY_ANGLE
217 break;
218 }
219
220 wxFAIL;
221 return wxEmptyString;
222}
223
224
225PGPROPERTY_SIZE::PGPROPERTY_SIZE( const wxString& aLabel, const wxString& aName,
226 long aValue )
227 : wxUIntProperty( aLabel, aName, aValue ), PGPROPERTY_DISTANCE( REGEX_UNSIGNED_DISTANCE )
228{
229}
230
231
233{
234 return nullptr;
235}
236
237
238PGPROPERTY_COORD::PGPROPERTY_COORD( const wxString& aLabel, const wxString& aName,
239 long aValue, ORIGIN_TRANSFORMS::COORD_TYPES_T aCoordType ) :
240 wxIntProperty( aLabel, aName, aValue ),
242{
243}
244
245
247{
248 return nullptr;
249}
250
251
252bool PGPROPERTY_ANGLE::StringToValue( wxVariant& aVariant, const wxString& aText, int aArgFlags ) const
253{
254 double value = 0.0;
255
256 if( !aText.ToDouble( &value ) )
257 {
258 aVariant.MakeNull();
259 return true;
260 }
261
262 value *= m_scale;
263
264 if( aVariant.IsNull() || aVariant.GetDouble() != value )
265 {
266 aVariant = value;
267 return true;
268 }
269
270 return false;
271}
272
273
274wxString PGPROPERTY_ANGLE::ValueToString( wxVariant& aVariant, int aArgFlags ) const
275{
276 if( aVariant.GetType() == wxPG_VARIANT_TYPE_DOUBLE )
277 {
278 // TODO(JE) Is this still needed?
279 return wxString::Format( wxS( "%g\u00B0" ), aVariant.GetDouble() / m_scale );
280 }
281 else if( aVariant.GetType() == wxS( "EDA_ANGLE" ) )
282 {
283 wxString ret;
284 static_cast<EDA_ANGLE_VARIANT_DATA*>( aVariant.GetData() )->Write( ret );
285 return ret;
286 }
287 else
288 {
289 wxCHECK_MSG( false, wxEmptyString, wxS( "Unexpected variant type in PGPROPERTY_ANGLE" ) );
290 }
291}
292
293
295{
296 return nullptr;
297}
298
299
301{
302 // TODO(JE) calculate size from window metrics?
303 return wxSize( 16, 12 );
304}
305
306
307void PGPROPERTY_COLORENUM::OnCustomPaint( wxDC& aDC, const wxRect& aRect,
308 wxPGPaintData& aPaintData )
309{
310 int index = aPaintData.m_choiceItem;
311
312 if( index < 0 )
313 index = GetIndex();
314
315 // GetIndex can return -1 when the control hasn't been set up yet
316 if( index < 0 || index >= static_cast<int>( GetChoices().GetCount() ) )
317 return;
318
319 wxColour color = GetColor( GetChoices().GetValue( index ) );
320
321 if( color == wxNullColour )
322 return;
323
324 aDC.SetPen( *wxTRANSPARENT_PEN );
325 aDC.SetBrush( wxBrush( color ) );
326 aDC.DrawRectangle( aRect );
327
328 aPaintData.m_drawnWidth = aRect.width;
329}
330
331
332wxString PGPROPERTY_STRING::ValueToString( wxVariant& aValue, int aFlags ) const
333{
334 if( aValue.GetType() != wxPG_VARIANT_TYPE_STRING )
335 return wxEmptyString;
336
337 return UnescapeString( aValue.GetString() );
338}
339
340
341bool PGPROPERTY_STRING::StringToValue( wxVariant& aVariant, const wxString& aString,
342 int aFlags ) const
343{
344 aVariant = EscapeString( aString, CTX_QUOTED_STR );
345 return true;
346}
347
348
349PGPROPERTY_BOOL::PGPROPERTY_BOOL( const wxString& aLabel, const wxString& aName, bool aValue ) :
350 wxBoolProperty( aLabel, aName, aValue )
351{
353}
354
355
356const wxPGEditor* PGPROPERTY_BOOL::DoGetEditorClass() const
357{
358 wxCHECK_MSG( m_customEditor, wxPGEditor_CheckBox,
359 wxT( "Make sure to set custom editor for PGPROPERTY_BOOL!" ) );
360 return m_customEditor;
361}
int color
Definition: DXF_plotter.cpp:57
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:109
static wxVariantData * VariantDataFactory(const wxAny &aAny)
A class to perform either relative or absolute display origin transforms for a single axis of a point...
virtual int ToDisplay(int aValue, COORD_TYPES_T aCoordType) const
COORD_TYPES_T
The supported Display Origin Transform types.
‍Customized wxPGProperty class to handle angles
Definition: pg_properties.h:98
void SetScale(double aScale)
wxString ValueToString(wxVariant &aVariant, int aArgFlags=0) const override
double m_scale
‍Scale factor to convert between raw and displayed value
wxValidator * DoGetValidator() const override
bool StringToValue(wxVariant &aVariant, const wxString &aText, int aArgFlags=0) const override
const wxPGEditor * DoGetEditorClass() const override
PGPROPERTY_BOOL(const wxString &aLabel=wxPG_LABEL, const wxString &aName=wxPG_LABEL, bool aValue=false)
wxColour GetColor(int aValue)
wxSize OnMeasureImage(int aItem=-1) const override
void OnCustomPaint(wxDC &aDC, const wxRect &aRect, wxPGPaintData &aPaintData) override
PGPROPERTY_COORD(const wxString &aLabel=wxPG_LABEL, const wxString &aName=wxPG_LABEL, long aValue=0, ORIGIN_TRANSFORMS::COORD_TYPES_T aCoordType=ORIGIN_TRANSFORMS::NOT_A_COORD)
wxValidator * DoGetValidator() const override
‍Customized abstract wxPGProperty class to handle coordinate/size units
Definition: pg_properties.h:37
PGPROPERTY_DISTANCE(const wxString &aRegEx, ORIGIN_TRANSFORMS::COORD_TYPES_T aCoordType=ORIGIN_TRANSFORMS::NOT_A_COORD)
wxString DistanceToString(wxVariant &aVariant, int aArgFlags=0) const
bool StringToDistance(wxVariant &aVariant, const wxString &aText, int aArgFlags=0) const
virtual ~PGPROPERTY_DISTANCE()=0
ORIGIN_TRANSFORMS::COORD_TYPES_T m_coordType
Definition: pg_properties.h:51
std::unique_ptr< REGEX_VALIDATOR > m_regExValidator
Definition: pg_properties.h:50
PGPROPERTY_SIZE(const wxString &aLabel=wxPG_LABEL, const wxString &aName=wxPG_LABEL, long aValue=0)
wxValidator * DoGetValidator() const override
wxString ValueToString(wxVariant &aValue, int aFlags=0) const override
bool StringToValue(wxVariant &aVariant, const wxString &aString, int aFlags=0) const override
static const wxString EDITOR_NAME
Definition: pg_editors.h:71
static const wxString EDITOR_NAME
Definition: pg_editors.h:34
virtual size_t TypeHash() const =0
Return type-id of the property type.
PROPERTY_DISPLAY Display() const
Definition: property.h:271
ORIGIN_TRANSFORMS::COORD_TYPES_T CoordType() const
Definition: property.h:276
virtual bool HasChoices() const
Return true if this PROPERTY has a limited set of possible values.
Definition: property.h:225
const wxString & Name() const
Definition: property.h:198
virtual const wxPGChoices & Choices() const
Return a limited set of possible values (e.g.
Definition: property.h:207
static PROPERTY_MANAGER & Instance()
Definition: property_mgr.h:76
ORIGIN_TRANSFORMS * GetTransforms() const
Definition: property_mgr.h:224
Custom validator that checks verifies that a string exactly matches a regular expression.
Definition: validators.h:117
static wxAnyValueTypeScopedPtr s_instance
static bool IsSameClass(const wxAnyValueType *otherType)
virtual wxAnyValueType * GetAssociatedType() override
static wxAnyValueType * GetInstance()
wxAnyToEDA_ANGLE_VARIANTRegistrationImpl(wxVariantDataFactory factory)
static bool AreSameClasses(const wxAnyValueType &a, const wxAnyValueType &b)
This file contains miscellaneous commonly used macros and functions.
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition: macros.h:83
static const wxChar REGEX_SIGNED_DISTANCE[]
wxPGProperty * PGPropertyFactory(const PROPERTY_BASE *aProperty)
static const wxChar REGEX_UNSIGNED_DISTANCE[]
#define TYPE_HASH(x)
Definition: property.h:62
PROPERTY_DISPLAY
Common property types.
Definition: property.h:53
@ PT_DEGREE
Angle expressed in degrees.
Definition: property.h:57
@ PT_COORD
Coordinate expressed in distance units (mm/inch)
Definition: property.h:56
@ PT_DECIDEGREE
Angle expressed in decidegrees.
Definition: property.h:58
@ PT_DEFAULT
Default property for a given type.
Definition: property.h:54
@ PT_SIZE
Size expressed in distance units (mm/inch)
Definition: property.h:55
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
wxString UnescapeString(const wxString &aSource)
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
@ CTX_QUOTED_STR
Definition: string_utils.h:57
constexpr double IUTomm(int iu) const
Definition: base_units.h:87
constexpr int IUToMils(int iu) const
Definition: base_units.h:100
Custom text control validator definitions.