wxFontProperty and wxMultiChoiceProperty use TextCtrlAndButton editor so they can be implemented as parents of wxEditorDialogProperty to share common functions and data.
Properties using TextCtrlAndButton editor (like wxLongStringProperty, wxDirProperty, wxFileProperty) share some features, like button triggering the editor dialog, and share a data, like dialog window attributes, so for the sake of the clear design it would be good to derive them from the common base class in which all shared functions/data are implemented. This class is not intended to be instantiated so it's an abstract class.
Move template function NumericValidation() to wxNumericProperty because all data necessary to validate the value are available here: acceptable value range, SpinCtrl editor value wrapping mode, etc.
All numeric properties (wxIntProperty, wxUIntProperty, wxFloatProperty) share some features (like specific attributes, numeric validation, SpinCtrl editor support) so for the sake of clear design it would be good to derive them from the common base class (wxNumericProperty) in which all shared functions are implemented. This class is not intended to be instantiated so it's an abstract class.
Instantiate NumericValidation() template directly for required data type in DoValidation() and avoid this way intermediate conversions to another data types.
Duplicating the code of the entire NumericValidation() template function just for one specialization (for double value type) seems to be an overkill. Only small fraction of the code (to round the validated value) is really dependent on the value type and this part can be moved to the template function GetRoundedValue() which in turn can be specialized as required.
Having definitions of several wxPGProperty and wxPropertyGridPageState functions in wxPropertyGrid header is misleading so they should be moved to the files with their own classes definitions for the sake of clarity.
Editor used by wxLongStringProperty is wxTextCtrl-based and it should be possible to set the limit of the length of the entered text just like it's done for such editors in another properties like wxStringProperty.
Setting the limit for the length of the text the user can enter in the text editor makes sense only for properties having text editors so in wxPGProperty::SetMaxLength() should be done a check whether to actually set a limit or not depending on the kind of editor used.
wxPropertyGridInterface::SetPropertyMaxLength() should be implemented on top of wxPGProperty::SetMaxLength() to proceed only if maximum length was actually set.
The code to handle events split into separate functions dedicated to handle the events of specific type is more readable than the code concentrated in one function handling all kinds of events.
Because changing the number of columns may change their total width from value greater than current client size to the value less than this size or vice versa we need to know this total width prior to determining wxProperyGrid scrolled view in order to account this actual width in the calculations.
So far it was implemented as property which could take int values 0/1 so it was acting essentially as a Boolean property. Implementing it explicitly as a Boolean one will make it more intuitive. Legacy code setting 0/1 int values shouldn't be affected because conversion from int to bool is implicit.
All wxPG_FILE_xxx attributes are used only in wxFileProperty to set respective internal data members and don't have to be stored in the property's attribute store.
By moving the code to display file selector dialog from wxPGFileDialogAdapter to wxFileProperty we can encapsulate the operation of showing the dialog because all required parameters are stored in the corresponding data members and there is no need to use call generic GetAttribute() function to retrieve them. This also helps in making wxFileProperty attributes built-ones in the future.
This attribute is used only internally in wxFileProperty so it can be considered as a built-in attribute which value can be stored in the local data member and not in the property's attribute store.
We need implement copy ctor and assignment operator because we are going to do a shallow copy of wxPGHashMapS2P data member and therefore we have to manually update reference counters of the objects being referenced in this map.
Notification about changes of column widths needs to be sent locally from wxPropertyGrid to wxPropertyGridManager (to update the header) so it would be good to use a dedicated non-public event type for these purposes.
If given attribute is not a built-in attribute handled by the current property it should be passed to the parent property because it may be handled there.