KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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_draw_frame.h>
28#include <eda_units.h>
33#include <properties/property.h>
34#include <string_utils.h>
36
37// reg-ex describing a signed valid value with a unit
38static const wxChar REGEX_SIGNED_DISTANCE[] = wxT( "([-+]?[0-9]+[\\.?[0-9]*) *(mm|in|mils)*" );
39static const wxChar REGEX_UNSIGNED_DISTANCE[] = wxT( "([0-9]+[\\.?[0-9]*) *(mm|in|mils)*" );
40
41
42class wxAnyToEDA_ANGLE_VARIANTRegistrationImpl : public wxAnyToVariantRegistration
43{
44public:
45 wxAnyToEDA_ANGLE_VARIANTRegistrationImpl( wxVariantDataFactory factory )
46 : wxAnyToVariantRegistration( factory )
47 {
48 }
49
50public:
51 static bool IsSameClass(const wxAnyValueType* otherType)
52 {
53 return AreSameClasses( *s_instance.get(), *otherType );
54 }
55
56 static wxAnyValueType* GetInstance()
57 {
58 return s_instance.get();
59 }
60
61 virtual wxAnyValueType* GetAssociatedType() override
62 {
64 }
65private:
66 static bool AreSameClasses(const wxAnyValueType& a, const wxAnyValueType& b)
67 {
68 return wxTypeId(a) == wxTypeId(b);
69 }
70
71 static wxAnyValueTypeScopedPtr s_instance;
72};
73
74
75wxAnyValueTypeScopedPtr wxAnyToEDA_ANGLE_VARIANTRegistrationImpl::s_instance( new wxAnyValueTypeImpl<EDA_ANGLE>() );
76
77static wxAnyToEDA_ANGLE_VARIANTRegistrationImpl s_wxAnyToEDA_ANGLE_VARIANTRegistration( &EDA_ANGLE_VARIANT_DATA::VariantDataFactory );
78
79
80wxPGProperty* PGPropertyFactory( const PROPERTY_BASE* aProperty, EDA_DRAW_FRAME* aFrame )
81{
82 wxPGProperty* ret = nullptr;
83 PROPERTY_DISPLAY display = aProperty->Display();
84
85 switch( display )
86 {
88 ret = new PGPROPERTY_SIZE();
89 ret->SetEditor( PG_UNIT_EDITOR::BuildEditorName( aFrame ) );
90 break;
91
93 ret = new PGPROPERTY_COORD();
94 static_cast<PGPROPERTY_COORD*>( ret )->SetCoordType( aProperty->CoordType() );
95 ret->SetEditor( PG_UNIT_EDITOR::BuildEditorName( aFrame ) );
96 break;
97
100 {
102
103 if( display == PROPERTY_DISPLAY::PT_DECIDEGREE )
104 prop->SetScale( 10.0 );
105
106 ret = prop;
107 ret->SetEditor( PG_UNIT_EDITOR::BuildEditorName( aFrame ) );
108 break;
109 }
110
111 default:
112 wxFAIL;
114 /* fall through */
116 {
117 // Create a corresponding wxPGProperty
118 size_t typeId = aProperty->TypeHash();
119
120 // Enum property
121 if( aProperty->HasChoices() )
122 {
123 // I do not know why enum property takes a non-const reference to wxPGChoices..
124 ret = new wxEnumProperty( wxPG_LABEL, wxPG_LABEL,
125 const_cast<wxPGChoices&>( aProperty->Choices() ) );
126 }
127 else if( typeId == TYPE_HASH( int ) || typeId == TYPE_HASH( long ) )
128 {
129 ret = new wxIntProperty();
130 }
131 else if( typeId == TYPE_HASH( unsigned int ) || typeId == TYPE_HASH( unsigned long ) )
132 {
133 ret = new wxUIntProperty();
134 }
135 else if( typeId == TYPE_HASH( float ) || typeId == TYPE_HASH( double ) )
136 {
137 ret = new wxFloatProperty();
138 }
139 else if( typeId == TYPE_HASH( bool ) )
140 {
141 ret = new PGPROPERTY_BOOL();
142 }
143 else if( typeId == TYPE_HASH( wxString ) )
144 {
145 ret = new PGPROPERTY_STRING();
146 }
147 else
148 {
149 wxFAIL_MSG( wxString::Format( wxS( "Property %s not supported by PGPropertyFactory" ),
150 aProperty->Name() ) );
151 ret = new wxPropertyCategory();
152 ret->Enable( false );
153 }
154 break;
155 }
156 }
157
158 if( ret )
159 {
160 ret->SetLabel( wxGetTranslation( aProperty->Name() ) );
161 ret->SetName( aProperty->Name() );
162 ret->SetHelpString( wxGetTranslation( aProperty->Name() ) );
163 ret->SetClientData( const_cast<PROPERTY_BASE*>( aProperty ) );
164 }
165
166 return ret;
167}
168
169
172 m_coordType( aCoordType )
173{
174 m_regExValidator.reset( new REGEX_VALIDATOR( aRegEx ) );
175}
176
177
179{
180}
181
182
183bool PGPROPERTY_DISTANCE::StringToDistance( wxVariant& aVariant, const wxString& aText,
184 int aArgFlags ) const
185{
186 // TODO(JE): Are there actual use cases for this?
187 wxCHECK_MSG( false, false, wxS( "PGPROPERTY_DISTANCE::StringToDistance should not be used." ) );
188}
189
190
191wxString PGPROPERTY_DISTANCE::DistanceToString( wxVariant& aVariant, int aArgFlags ) const
192{
193 wxCHECK( aVariant.GetType() == wxPG_VARIANT_TYPE_LONG, wxEmptyString );
194
195 long distanceIU = aVariant.GetLong();
196
198
199 if( transforms )
200 distanceIU = transforms->ToDisplay( static_cast<long long int>( distanceIU ), m_coordType );
201
202 switch( PROPERTY_MANAGER::Instance().GetUnits() )
203 {
204 case EDA_UNITS::INCHES:
205 return wxString::Format( wxS( "%g in" ), pcbIUScale.IUToMils( distanceIU ) / 1000.0 );
206
207 case EDA_UNITS::MILS:
208 return wxString::Format( wxS( "%d mils" ), pcbIUScale.IUToMils( distanceIU ) );
209
210 case EDA_UNITS::MILLIMETRES:
211 return wxString::Format( wxS( "%g mm" ), pcbIUScale.IUTomm( distanceIU ) );
212
213 case EDA_UNITS::UNSCALED:
214 return wxString::Format( wxS( "%li" ), distanceIU );
215
216 default:
217 // DEGREEs are handled by PGPROPERTY_ANGLE
218 break;
219 }
220
221 wxFAIL;
222 return wxEmptyString;
223}
224
225
226PGPROPERTY_SIZE::PGPROPERTY_SIZE( const wxString& aLabel, const wxString& aName,
227 long aValue )
228 : wxUIntProperty( aLabel, aName, aValue ), PGPROPERTY_DISTANCE( REGEX_UNSIGNED_DISTANCE )
229{
230}
231
232
234{
235 return nullptr;
236}
237
238
239PGPROPERTY_COORD::PGPROPERTY_COORD( const wxString& aLabel, const wxString& aName,
240 long aValue, ORIGIN_TRANSFORMS::COORD_TYPES_T aCoordType ) :
241 wxIntProperty( aLabel, aName, aValue ),
243{
244}
245
246
248{
249 return nullptr;
250}
251
252
253bool PGPROPERTY_ANGLE::StringToValue( wxVariant& aVariant, const wxString& aText, int aArgFlags ) const
254{
255 double value = 0.0;
256
257 if( !aText.ToDouble( &value ) )
258 {
259 aVariant.MakeNull();
260 return true;
261 }
262
263 value *= m_scale;
264
265 if( aVariant.IsNull() || aVariant.GetDouble() != value )
266 {
267 aVariant = value;
268 return true;
269 }
270
271 return false;
272}
273
274
275wxString PGPROPERTY_ANGLE::ValueToString( wxVariant& aVariant, int aArgFlags ) const
276{
277 if( aVariant.GetType() == wxPG_VARIANT_TYPE_DOUBLE )
278 {
279 // TODO(JE) Is this still needed?
280 return wxString::Format( wxS( "%g\u00B0" ), aVariant.GetDouble() / m_scale );
281 }
282 else if( aVariant.GetType() == wxS( "EDA_ANGLE" ) )
283 {
284 wxString ret;
285 static_cast<EDA_ANGLE_VARIANT_DATA*>( aVariant.GetData() )->Write( ret );
286 return ret;
287 }
288 else
289 {
290 wxCHECK_MSG( false, wxEmptyString, wxS( "Unexpected variant type in PGPROPERTY_ANGLE" ) );
291 }
292}
293
294
296{
297 return nullptr;
298}
299
300
302{
303 // TODO(JE) calculate size from window metrics?
304 return wxSize( 16, 12 );
305}
306
307
308void PGPROPERTY_COLORENUM::OnCustomPaint( wxDC& aDC, const wxRect& aRect,
309 wxPGPaintData& aPaintData )
310{
311 int index = aPaintData.m_choiceItem;
312
313 if( index < 0 )
314 index = GetIndex();
315
316 // GetIndex can return -1 when the control hasn't been set up yet
317 if( index < 0 || index >= static_cast<int>( GetChoices().GetCount() ) )
318 return;
319
320 wxColour color = GetColor( GetChoices().GetValue( index ) );
321
322 if( color == wxNullColour )
323 return;
324
325 aDC.SetPen( *wxTRANSPARENT_PEN );
326 aDC.SetBrush( wxBrush( color ) );
327 aDC.DrawRectangle( aRect );
328
329 aPaintData.m_drawnWidth = aRect.width;
330}
331
332
333wxString PGPROPERTY_STRING::ValueToString( wxVariant& aValue, int aFlags ) const
334{
335 if( aValue.GetType() != wxPG_VARIANT_TYPE_STRING )
336 return wxEmptyString;
337
338 return UnescapeString( aValue.GetString() );
339}
340
341
342bool PGPROPERTY_STRING::StringToValue( wxVariant& aVariant, const wxString& aString,
343 int aFlags ) const
344{
345 aVariant = EscapeString( aString, CTX_QUOTED_STR );
346 return true;
347}
348
349
350PGPROPERTY_BOOL::PGPROPERTY_BOOL( const wxString& aLabel, const wxString& aName, bool aValue ) :
351 wxBoolProperty( aLabel, aName, aValue )
352{
354}
355
356
357const wxPGEditor* PGPROPERTY_BOOL::DoGetEditorClass() const
358{
359 wxCHECK_MSG( m_customEditor, wxPGEditor_CheckBox,
360 wxT( "Make sure to set custom editor for PGPROPERTY_BOOL!" ) );
361 return m_customEditor;
362}
int color
Definition: DXF_plotter.cpp:57
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:109
static wxVariantData * VariantDataFactory(const wxAny &aAny)
The base class for create windows for drawing purpose.
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.
A wxEnumProperty that displays a color next to the enum value.
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
Do not perform PG validation; the UX is not what we want.
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
Customized wxPGProperty class to handle angles.
Definition: pg_properties.h:80
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
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:54
std::unique_ptr< REGEX_VALIDATOR > m_regExValidator
Definition: pg_properties.h:53
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:75
static wxString BuildEditorName(EDA_DRAW_FRAME *aFrame)
Definition: pg_editors.cpp:48
virtual size_t TypeHash() const =0
Return type-id of the property type.
PROPERTY_DISPLAY Display() const
Definition: property.h:273
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:201
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:119
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, EDA_DRAW_FRAME *aFrame)
Customized abstract wxPGProperty class to handle coordinate/size units.
static const wxChar REGEX_UNSIGNED_DISTANCE[]
#define TYPE_HASH(x)
Definition: property.h:63
PROPERTY_DISPLAY
Common property types.
Definition: property.h:54
@ PT_DEGREE
Angle expressed in degrees.
Definition: property.h:58
@ PT_COORD
Coordinate expressed in distance units (mm/inch)
Definition: property.h:57
@ PT_DECIDEGREE
Angle expressed in decidegrees.
Definition: property.h:59
@ PT_DEFAULT
Default property for a given type.
Definition: property.h:55
@ PT_SIZE
Size expressed in distance units (mm/inch)
Definition: property.h:56
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:58
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.