I look everywhre on internet to have a wiki about "how to create custom variant" ?
I would like to create my own variant 'using wxVariantData' to store couple of value (key / value) into a wxHashMap that takes 2 variants : a variant as key, another as value.
Why ? To make generic way to pop table from lua script returns parameters. An lua table is always a couple of key/value like dictionnaries, with key that could be 1,2,3... when no key is defined.
Some peaple has alredy done this kind of features ?
Thanks.
Create own wxVariant
Re: Create own wxVariant
Which version of wx are you using? In wx 2.9 you can store really anything in the new wxAny : http://docs.wxwidgets.org/2.9.2/classwx_any.html
"Keyboard not detected. Press F1 to continue"
-- Windows
-- Windows
Re: Create own wxVariant
wxWidgets 2.8.12, not have wxAny.
wxWidgets 3.0 should released one year ago, for the moment nothing is released....
wxWidgets 3.0 should released one year ago, for the moment nothing is released....
Re: Create own wxVariant
You need to derive your custom wxVariant from the wxVariantData class, then override the pure virtual functions.
http://docs.wxwidgets.org/2.9.2/classwx ... _data.html
You will need to add whatever functions (comparisons, assignment operator, etc.) that wxHashMap needs to manipulate its elements.
http://docs.wxwidgets.org/2.9.2/classwx ... _data.html
Code: Select all
class MyVariant : public wxVariantData {
double m_double;
public:
MyVariant(double d) : wxVariantData(), m_double(d) { }
bool Eq(wxVariantData &data) const {
MyVariant *value_ptr = dynamic_cast<MyVariant*>(&data);
return (value_ptr != 0) && ((*value_ptr).m_double == m_double);
}
wxString GetType() const { return wxString("MyVariant"); }
double GetDouble() const { return m_double; }
};
I was using wxVariant with wxDataViewListCtrl using custom renderers for some columns, but I couldn't seem to convert to using wxAny on the attempt I made a few months ago, so I'm not sure how backward compatible it is with some classes. It could have been my lack of understanding/experience.Auria wrote:Which version of wx are you using? In wx 2.9 you can store really anything in the new wxAny : http://docs.wxwidgets.org/2.9.2/classwx_any.html
Re: Create own wxVariant
I have wrote this code (see below) but it is not really easy to use because I need to cast all time I need to use it to the correct variant type.
Else it's seem to work fine.
Header
Else it's seem to work fine.
Header
Code: Select all
/////////////////////////////////////////////////////////////////////////////
// Name: wxETKVariant.cpp
// Library: wxETK
// Purpose: Header of wxVariant extension classes.
// Author: Stéphane Château
// Modified by:
// Created: 12/07/2011
// Licence: LGPL
/////////////////////////////////////////////////////////////////////////////
#ifndef WX_ETK_VARIANT_H
#define WX_ETK_VARIANT_H
#include "wxETKTypes.h"
#include <wx/variant.h>
/**
* Class used to record hash map into variant.
*
* To be used with wxVariant class. To use this class, call:
*<pre>
* wxVariant varMap(new wxETKVariantDataMap())
*</pre>
*
* To convert a variant into the map, call:
*<pre>
* if (varValues.GetType() == wxETKVariantDataMap::STR_VARIANT_MAP_TYPE)
* { // To be sure it is the correct variant type, else cast throw exception
* wxETKVariantDataMap &rMap = (dynamic_cast<wxETKVariantDataMap>(*varValues.GetData());
* }
*</pre>
*
* @author Stéphane Château
* @version Name : wxETK<br>
* Revision : <b>1.0</b>
*/
class EXPORT_IMPORT wxETKVariantDataMap : public wxVariantData
{
private:
// To declare a hashmap<wxVariant, wxVariant>
WX_DECLARE_HASH_MAP( wxVariant, // type of the keys
wxVariant, // type of the values
wxStringHash, // hasher
wxStringEqual, // key equality predicate
wxHashMapVariant); // name of the class
public:
static const wxString STR_VARIANT_MAP_TYPE;
/// @name typedef. Same as wxHashMap class, see wxWidgets documentation.
//@{
typedef wxHashMapVariant::size_type size_type;
typedef wxHashMapVariant::iterator iterator;
typedef wxHashMapVariant::const_iterator const_iterator;
typedef wxHashMapVariant::key_type key_type;
typedef wxHashMapVariant::const_key_type const_key_type;
typedef wxHashMapVariant::value_type value_type;
typedef wxHashMapVariant::Insert_Result Insert_Result;
//@}
private:
/**
* Map that record the values of this variant.
*/
wxHashMapVariant m_mapValue;
public:
/// @name Constructor / Destructor.
//@{
/**
* Default constructor.
*/
wxETKVariantDataMap();
/**
* Copy constructor.
*
* \param _rOther Object to copy from.
*/
wxETKVariantDataMap(const wxETKVariantDataMap& _rOther);
protected:
/**
* Default destructor.
*
* Is protected, must be allocated on the heap.
*/
virtual ~wxETKVariantDataMap();
//@}
public:
/**
* What type is it?
*
* @return a string name.
*/
virtual wxString GetType() const;
/// @name Operators.
//@{
/** Assignment operator.
*
* @param _rOther Object to assign from.
* @return A reference to this.
*/
wxETKVariantDataMap & operator=(const wxETKVariantDataMap& _rOther);
/** Element accessor.
*
* Use the key as an array subscript.
* The only difference is that if the given key is not present in the hash map,
* an element with the default value_type() is inserted in the table.
*
* @param _rKey Key to find.
* @return A reference to the value found or added.
*/
wxVariant & operator[](const wxVariant &_rKey);
//@}
/**
* Override these to provide common functionality.
*
* @param _rvariantData Variant to test if is equal to this.
* @return true if is same.
*/
virtual bool Eq(wxVariantData& _rvariantData) const;
/**
*
* Verify if key exists.
*
* @param _rKey Key to find.
* @return true if the key exist, false else.
*/
bool IsExist(const wxVariant &_rKey) const;
/// @name Map operators. Same as wxHashMap class, see wxWidgets documentation.
//@{
void clear() { return m_mapValue.clear(); }
size_type size() const { return m_mapValue.size(); }
size_type max_size() const { return m_mapValue.max_size(); }
bool empty() const { return m_mapValue.empty(); }
const_iterator end() const { return m_mapValue.end(); }
iterator end() { return m_mapValue.end(); }
const_iterator begin() const { return m_mapValue.begin(); }
iterator begin() { return m_mapValue.begin(); }
size_type erase(const key_type& _rKey) { return m_mapValue.erase(_rKey); }
void erase(const iterator& _rIt) { return m_mapValue.erase(_rIt); }
const_iterator find(const const_key_type& _rKey) const { return m_mapValue.find(_rKey); }
iterator find( const const_key_type& _rKey) { return m_mapValue.find(_rKey); }
Insert_Result insert(const value_type& _rValue) { return m_mapValue.insert(_rValue); }
size_type count(const const_key_type& _rKey) { return m_mapValue.count(_rKey); }
//@}
};
#endif // WX_ETK_VARIANT_H
[b]Implementation[/b]
Code: Select all
/////////////////////////////////////////////////////////////////////////////
// Name: wxETKVariant.cpp
// Library: wxETK
// Purpose: Implementation of wxVariant extension classes.
// Author: Stéphane Château
// Modified by:
// Created: 12/07/2011
// Licence: LGPL
/////////////////////////////////////////////////////////////////////////////
#include "wxETKVariant.h"
const wxString wxETKVariantDataMap::STR_VARIANT_MAP_TYPE = wxT("map");
wxETKVariantDataMap::wxETKVariantDataMap()
{
}
wxETKVariantDataMap::wxETKVariantDataMap(const wxETKVariantDataMap& _rOther)
{
operator=(_rOther);
}
wxETKVariantDataMap::~wxETKVariantDataMap()
{
}
wxString wxETKVariantDataMap::GetType() const
{
return STR_VARIANT_MAP_TYPE;
}
wxETKVariantDataMap& wxETKVariantDataMap::operator=(const wxETKVariantDataMap& _rOther)
{
if (this == &_rOther)
{
return *this; // handle self assignment
}
m_mapValue = _rOther.m_mapValue;
// assignment operator
return *this;
}
bool wxETKVariantDataMap::Eq(wxVariantData& _rvariantData) const
{
bool bRet = false;
if (_rvariantData.GetType() == STR_VARIANT_MAP_TYPE)
{
wxETKVariantDataMap &rvariantData = dynamic_cast<wxETKVariantDataMap &>(_rvariantData);
if (m_mapValue.size() == rvariantData.m_mapValue.size())
{ // Verify if all keys/datas are present and same into the 2 maps
for (wxHashMapVariant::const_iterator it = m_mapValue.begin();it!=m_mapValue.end();++it)
{
wxHashMapVariant::const_iterator itToFind = rvariantData.m_mapValue.find(it->first);
if ( itToFind == rvariantData.m_mapValue.end() // This key doesn't exists
|| it->first != itToFind->first // This key is different (strange)
|| it->second != itToFind->second // This value is different
)
{
break;
}
}
// All is same
bRet = true;
}
}
return bRet;
}
wxVariant & wxETKVariantDataMap::operator[](const wxVariant &_rKey)
{
return m_mapValue[_rKey];
}
bool wxETKVariantDataMap::IsExist(const wxVariant &_rKey) const
{
return m_mapValue.find(_rKey) != m_mapValue.end();
}
Re: Create own wxVariant
Do you mean you have to cast in code outside of this class?
I needed to use dynamic_cast in my wxDataViewCustomRenderer in SetValue so that I could make the assignment of my custom variant to the local copy that Render() uses. There doesn't seem to be any way to avoid something like this. dynamic_cast is part of the language, so I've come to accept it, at least in this situation of interfacing with another library.
Also, I put a comment in this part of your code. I believe the break statement will only break you out of the for-loop, so you will always return "true." Instead of break, maybe just return false inside this inner if statement.
I needed to use dynamic_cast in my wxDataViewCustomRenderer in SetValue so that I could make the assignment of my custom variant to the local copy that Render() uses. There doesn't seem to be any way to avoid something like this. dynamic_cast is part of the language, so I've come to accept it, at least in this situation of interfacing with another library.
Also, I put a comment in this part of your code. I believe the break statement will only break you out of the for-loop, so you will always return "true." Instead of break, maybe just return false inside this inner if statement.
Feneck91 wrote:Code: Select all
bool wxETKVariantDataMap::Eq(wxVariantData& _rvariantData) const { bool bRet = false; if (_rvariantData.GetType() == STR_VARIANT_MAP_TYPE) { wxETKVariantDataMap &rvariantData = dynamic_cast<wxETKVariantDataMap &>(_rvariantData); if (m_mapValue.size() == rvariantData.m_mapValue.size()) { // Verify if all keys/datas are present and same into the 2 maps for (wxHashMapVariant::const_iterator it = m_mapValue.begin();it!=m_mapValue.end();++it) { wxHashMapVariant::const_iterator itToFind = rvariantData.m_mapValue.find(it->first); if ( itToFind == rvariantData.m_mapValue.end() // This key doesn't exists || it->first != itToFind->first // This key is different (strange) || it->second != itToFind->second // This value is different ) { break; // just return false; instead of break } } // All is same bRet = true; // <--- Always gets hit } } return bRet; }