There are many built-in data types supported directly by the wxXS but aside of them, also custom data types can be processed by the library. For this case, the wxXS provides set of code macros and classes suitable for a creation and registration of user-defined I/O handlers.
In the following example a new I/O handler suitable for serialization/deserialization of wxColourData class is created and used. Note, that the example application is one of sample projects distributed together with the library source code. It is highly recommended to study reference documentation as well as the supplied sample projects for full understanding of discussed topics.
So, first of all, the programmer must declare new I/O handler class and define code macros used for marking of a serialized data members. This should be done in appropriate header file. The declaration code can be as follows:
////////////////////////////////////////////
// Declaration of new I/O handler
////////////////////////////////////////////
// Declaration of a class 'xsColourDataPropIO' encapsulating
// the custom property I/O handler for 'wxColouData' data type.
XS_DECLARE_IO_HANDLER(wxColourData, xsColourDataPropIO);
// Code macros which create new serialized wxColourData property
#define XS_SERIALIZE_COLOURDATA(x, name)
XS_SERIALIZE_PROPERTY(x, wxT("colourdata"), name);
#define XS_SERIALIZE_COLOURDATA_EX(x, name, def)
XS_SERIALIZE_PROPERTY_EX(x,wxT("colourdata"), name, xsColourDataPropIO::ToString(def));
Let us discuss the code listed above in more details. The macro XS_DECLARE_IO_HANDLERS
declares a new class called xsColourDataPropIO
suitable for processing
of data members with data type wxColourData
which is a class provided
by the wxWidgets used for data transfer between an application and the color picker
dialog. User-defined macros XS_SERIALIZE_COLOURDATA
and
XS_SERIALIZE_COLOURDATA_EX
can be later used in the implementation
code to mark wxColourData
class members in the similar way as the
standard XS_SERIALIZE
macro. Note that the text string “colourdata”
must be a unique identifier used for identification of this data type in
serialized XMLstructure.
Now see the implementation code:
// Define custom data I/O handler
XS_DEFINE_IO_HANDLER(wxColourData, xsColourDataPropIO);
// Two following static member functions of the data handler class MUST
// be defined manualy:
// wxString xsPropIO::ToString(T value) -> creates a string representation of the given value:
wxString xsColourDataPropIO::ToString(wxColourData value)
{
wxString out;
out << xsColourPropIO::ToString(value.GetColour());
for(int i = 0; i < 16; i++)
{
out << wxT("|") << xsColourPropIO::ToString(value.GetCustomColour(i));
}
return out;
}
// T xsPropIO::FromString(const wxString& value) -> converts data from
// given string representation to its relevant value:
wxColourData xsColourDataPropIO::FromString(const wxString& value)
{
wxColourData data;
if(!value.IsEmpty())
{
int i = 0;
wxStringTokenizer tokens(value, wxT("|"), wxTOKEN_STRTOK);
data.SetColour(xsColourPropIO::FromString(tokens.GetNextToken()));
while(tokens.HasMoreTokens())
{
data.SetCustomColour(i, xsColourPropIO::FromString(tokens.GetNextToken()));
i++;
}
}
return data;
}
The most of the implementation effort is hidden in the
XS_DEFINE_IO_HANDLER
macro. Here, the programmer must manually create
only two static functions responsible for conversion of processed data value to its
string representation and vice versa. These static functions are then internally
used be core library classes for serialization and deserialization but they can
be used also for any other purposes. For example, in the code above you can see
similar static functions called xsColourPropIO::FromString()
and
xsColourPropIO::ToString()
defined by built-in I/O handler designed
for processing of wxColour
data members.
Now, let's declare and define a class containing member data of type
wxColourData
and mark it for serialization via previously
user-defined I/O handler:
////////////////////////////////////////////
// CustomDataSampleApp class
////////////////////////////////////////////
bool CustomDataSampleApp::OnInit()
{
// load application settings if the configuration file exists, otherwise
// create new settings class object with default values
// initialize serializer (m_XmlIO class member)
m_XmlIO.SetSerializerOwner(wxT("CustomDataSampleApp"));
m_XmlIO.SetSerializerRootName(wxT("settings"));
m_XmlIO.SetSerializerVersion(wxT("1.0.0"));
// register new property I/O handler 'xsColourDataPropIO' for data type with name 'colourdata'
XS_REGISTER_IO_HANDLER(wxT("colourdata"), xsColourDataPropIO);
// create serialized settings class object manualy with default values
m_pSettings = new Settings();
// insert settings class object into serializer as its root node
m_XmlIO.SetRootItem(m_pSettings);
if( wxFileExists(wxT("settings.xml")) )
{
// load settings from configuration file
m_XmlIO.DeserializeFromXml(wxT("settings.xml"));
}
// do some other initialization step ...
return true;
}
Note that new macros XS_DECLARE_CLONABLE_CLASS
and
XS_DECLARE_CLONABLE_CLASS
were used in the code. These macros differ
from DECLARE_DYNAMIC_CLASS
and IMPLEMENT_DYNAMIC_CLASS
macros in such way that they implement also Clone()
function for the class,
which can be used for retrieving the exact copy of the class instance.
This function is further used by wxXmlSerializer::CopyItems()
member
function and its copy constructor so a whole serializer's content can be copied
in a single program line.
The last step needed for proper initialization of the new I/O handler class is
its registration. It should be done as soon as possible, typically in the application
initialization code. For registration of the I/O handler, the
XS_REGISTER_IO_HANDLER
macro can be used as shown in the following
code:
////////////////////////////////////////////
// CustomDataSampleApp class
////////////////////////////////////////////
bool CustomDataSampleApp::OnInit()
{
// load application settings if the configuration file exists, otherwise
// create new settings class object with default values
// initialize serializer (m_XmlIO class member)
m_XmlIO.SetSerializerOwner(wxT("CustomDataSampleApp"));
m_XmlIO.SetSerializerRootName(wxT("settings"));
m_XmlIO.SetSerializerVersion(wxT("1.0.0"));
// register new property I/O handler 'xsColourDataPropIO' for data type with name 'colourdata'
XS_REGISTER_IO_HANDLER(wxT("colourdata"), xsColourDataPropIO);
// create serialized settings class object
// manualy with default values
m_pSettings = new Settings();
// insert settings class object into serializer as its root node
m_XmlIO.SetRootItem(m_pSettings);
if( wxFileExists(wxT("settings.xml")) )
{
// load settings from configuration file
m_XmlIO.DeserializeFromXml(wxT("settings.xml"));
}
// do some other initialization step ...
return true;
}