WxSmith tutorial: Adding advanced properties into items

From Code::Blocks
Revision as of 20:35, 19 April 2007 by Byo (talk | contribs)

WARNING: NOT YET FINISHED

Preface

In previous tutorial we learned how to add some basic properties into our custom item. In this tutorial we will learn how to create fully customizable properties by operating directly on wxProperytGrid and xml structures. Let's take a look how wxSmith deal with them:

Fully customizable properties

To create fully costomizable property we hve to handle few operations done on it:

  • Adding property to property grid
  • Reacting to change of this property
  • Reading data from XML (XRC) structures
  • Writing data to XML (XRC) structures

Each of these operations is done inside one virtual function of class which adds item into wxSmith (like wxsChart in our chart example). Overriding it and giving custom implementation allows to freely operate on properties.

Adding custom property to property grid

To include our own properties in list of properties, we have to add following function into our class:

void OnAddExtraProperties(wxsPropertyGridManager* Grid);

Inside this class we can freely operate on given wxsPropertyGridManager (see wxPropertyGrid site to learn more on how to operate on this class), but the operations should be limited to ading properties (it may be risky to delete or change existing ones).

At the end of custom implementation of this function, we should also call the original function declared inside wxsWidget class:

void CustomClass::OnAddExtraProperties(wxsPropertyGridManager* Grid)
{
    // Add custom properties here

    wxsWidget::OnAddExtraProperties(Grid);
}

If it won't be called, item wont allow to edit any events because they are added inside wxsWidget::OnAddExtraProperties(Grid); call.


Reacting to change of custom properties

Processing changes of custom properties is simillar to creating them. We just have to override following function:

void OnExtraPropertyChanged(wxsPropertyGridManager* Grid,wxPGId Id);

It has extra parameter comparing to previous function - Id. It's id of property which was changed. It's advised that you compare value of Id with identifiers generated inside OnAddExtraProperties to avoid unnecessary reads from property grid. At the end of this function you should also call original one but only if you're sure that your properties have not changed:

void CustomClass::OnExtraPropertyChanged(wxsPropertyGridManager* Grid,wxPGId Id)
{
    if ( Id == Property_Id )
    {
        // Read value of property here

        NotifyPropertyChange(true);
        return;
    }

    wxsWidget::OnExtraPropertyChanged(Grid,Id);
}

Note that there's also call to NorifyPropertyChange(true); at the end of value reading. This call updates all things related to current resource: regenerates source code and XRC files if necessary, updates the content of editor and does few more things to keep wxSmith's state up to date.

Reading data from XML (XRC) structures

Reading of our custom properties is done inside following function:

bool OnXmlRead(TiXmlElement* Element,bool IsXRC,bool IsExtra);

The Element argument is object represending xml node of current widget. To load custom properties we must locate child nodes and read data from them. Code::Blocks and wxSmith are using TinyXml to operate on xml structures so to get more informations on how to read and manipulate xml data, read TinyXml's documentation.

The IsXRC and IsExtra arguments require some better description. From the very beginning wxSmith tends to be compatible with XRC files which allow storing structure of window inside xml file. Usually XRC files are limited to widgets which are provided with wxWidgets library. And they don't provide some extra data used by wxSmith like enteries for event handlers and variable name. wxSmith does split data of widgets into two parts - the firs one is strict XRC data and the second one is extra data provided by wxSmith. If IsXRC parameter is true, this mean that function should read XRC data part, if IsExtra is true, this mean that it should read extra data (both arguments may be true in one call). Most of contrib items would have XRC support disabled so we should read data only when IsExtra is true:

bool CustomClass::OnXmlRead(TiXmlElement* Element,bool IsXRC,bool IsExtra)
{
    if ( IsExtra )
    {
        // Process xml structures here
    }

    return wxsTool::OnXmlRead(Element,IsXRC,IsExtra);
}

At the end of this implementation we must call original function as usual ;)


Writing data to XML (XRC) structures

Writing data into xml structures is simillar to reading them. We have to implement following function:

bool CustomClass::OnXmlWrite(TiXmlElement* Element,bool IsXRC,bool IsExtra)
{
    if ( IsExtra )
    {
        // Store data into xml structure
    }

    return wxsTool::OnXmlRead(Element,IsXRC,IsExtra);
}

The meaning of arguments is same as in case of reading data. The only difference is that we write data here instead of reading it.


Adding custom property into wxChart

Now it's time to do some really complex task. We will add property which adds some data into chart widget so it would be possible to show some content in editor, preview and of course in target application. But before we do this, we need some knowledge about wxChart's data managment.

Each wxChartCtrl widget can show few sets of data which create one chart shape (one pie, one line etc). Each of these sets is stored inside class derived from wxChartPoints and the class type depends on type of chart we want to show. This structure keep data of points, percentages or any other data required to build chart. Following chart types are available in wxChart:

  • Bar
  • Bar3D
  • Pie
  • Pie3D
  • Points
  • Points3D
  • Line
  • Line3D
  • Area
  • Area3D

Different data types may be stored inside one chart which will result in many charts shown inside one control.

Now let's add some property.

First thing we need here is to provide dynamically changing list of data sets (wxChartPoints structures). Because it's not as easy as in case of base properties, we have to handle our properties manually. So first we add new functions which will manage our custom properties.

We add this code into wxsChart's declaration:

        void OnAddExtraProperties(wxsPropertyGridManager* Grid);
        void OnExtraPropertyChanged(wxsPropertyGridManager* Grid,wxPGId Id);
        bool OnXmlRead(TiXmlElement* Element,bool IsXRC,bool IsExtra);
        bool OnXmlWrite(TiXmlElement* Element,bool IsXRC,bool IsExtra);

and the following initial implementations:

void wxsChart::OnAddExtraProperties(wxsPropertyGridManager* Grid)
{
    wxsWidget::OnAddExtraProperties(Grid);
} 

void wxsChart::OnExtraPropertyChanged(wxsPropertyGridManager* Grid,wxPGId Id)
{
    wxsWidget::OnExtraPropertyChanged(Grid,Id);
}

bool wxsChart::OnXmlRead(TiXmlElement* Element,bool IsXRC,bool IsExtra)
{
    return wxsWidget::OnXmlRead(Element,IsXRC,IsExtra);
}

bool wxsChart::OnXmlWrite(TiXmlElement* Element,bool IsXRC,bool IsExtra)
{
    return wxsWidget::OnXmlWrite(Element,IsXRC,IsExtra);
}

These implementations are just calling original functions to let wxSmith do it's work inside of them.