home *** CD-ROM | disk | FTP | other *** search
/ Hackers Magazine 57 / CdHackersMagazineNr57.iso / Software / Multimedia / k3d-setup-0.7.11.0.exe / include / k3d / k3dsdk / data.h < prev    next >
Encoding:
C/C++ Source or Header  |  2009-02-16  |  63.4 KB  |  2,751 lines

  1. #ifndef K3DSDK_DATA_H
  2. #define K3DSDK_DATA_H
  3.  
  4. // K-3D
  5. // Copyright (c) 1995-2008, Timothy M. Shead
  6. //
  7. // Contact: tshead@k-3d.com
  8. //
  9. // This program is free software; you can redistribute it and/or
  10. // modify it under the terms of the GNU General Public
  11. // License as published by the Free Software Foundation; either
  12. // version 2 of the License, or (at your option) any later version.
  13. //
  14. // This program is distributed in the hope that it will be useful,
  15. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17. // General Public License for more details.
  18. //
  19. // You should have received a copy of the GNU General Public
  20. // License along with this program; if not, write to the Free Software
  21. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  22.  
  23. #include "idocument.h"
  24. #include "ienumeration_property.h"
  25. #include "ihint.h"
  26. #include "ilist_property.h"
  27. #include "imeasurement_property.h"
  28. #include "inode.h"
  29. #include "inode_change_signal.h"
  30. #include "inode_collection.h"
  31. #include "inode_collection_property.h"
  32. #include "inode_property.h"
  33. #include "ipath_property.h"
  34. #include "ipersistent.h"
  35. #include "ipersistent_collection.h"
  36. #include "ipersistent_lookup.h"
  37. #include "iplugin_factory.h"
  38. #include "iproperty.h"
  39. #include "iproperty_collection.h"
  40. #include "iscript_property.h"
  41. #include "istate_container.h"
  42. #include "istate_recorder.h"
  43. #include "iwritable_property.h"
  44. #include "nodes.h"
  45. #include "result.h"
  46. #include "state_change_set.h"
  47. #include "xml.h"
  48.  
  49. #include <boost/lexical_cast.hpp>
  50. #include <boost/static_assert.hpp>
  51. #include <boost/type_traits.hpp>
  52. #include <boost/version.hpp>
  53.  
  54. #include <cassert>
  55. #include <string>
  56. #include <typeinfo>
  57.  
  58. namespace k3d
  59. {
  60.  
  61. namespace data
  62. {
  63.  
  64. /////////////////////////////////////////////////////////////////////////////
  65. // container
  66.  
  67. /// Host class for storing data using serialization, property, name, constraint, undo, storage, and signal policies
  68. template<typename value_t, class serialization_policy_t>
  69. class container :
  70.     public serialization_policy_t
  71. {
  72. public:
  73.     template<typename init_t>
  74.     container(const init_t& Init) :
  75.         serialization_policy_t(Init)
  76.     {
  77.     }
  78. };
  79.  
  80. /////////////////////////////////////////////////////////////////////////////
  81. // no_serialization
  82.  
  83. /// Serialization policy for data containers that do not need to be serialized
  84. template<typename value_t, class property_policy_t>
  85. class no_serialization :
  86.     public property_policy_t
  87. {
  88. protected:
  89.     template<typename init_t>
  90.     no_serialization(const init_t& Init) :
  91.         property_policy_t(Init)
  92.     {
  93.     }
  94. };
  95.  
  96. /////////////////////////////////////////////////////////////////////////////
  97. // with_serialization
  98.  
  99. /// Serialization policy for data containers that can be serialized as XML
  100. template<typename value_t, class property_policy_t>
  101. class with_serialization :
  102.     public property_policy_t,
  103.     public ipersistent
  104. {
  105.     // This policy only works for data stored by-value
  106.     BOOST_STATIC_ASSERT((!boost::is_pointer<value_t>::value));
  107.  
  108. public:
  109.     void save(xml::element& Element, const ipersistent::save_context& Context)
  110.     {
  111.         Element.append(xml::element("property", string_cast(property_policy_t::internal_value()), xml::attribute("name", property_policy_t::name())));
  112.     }
  113.  
  114.     void load(xml::element& Element, const ipersistent::load_context& Context)
  115.     {
  116.         std::string value = Element.text;
  117.         property_policy_t::set_value(from_string(value, property_policy_t::internal_value()));
  118.     }
  119.  
  120. protected:
  121.     template<typename init_t>
  122.     with_serialization(const init_t& Init) :
  123.         property_policy_t(Init)
  124.     {
  125.         Init.persistent_collection().enable_serialization(Init.name(), *this);
  126.     }
  127. };
  128.  
  129. /////////////////////////////////////////////////////////////////////////////
  130. // path_serialization
  131.  
  132. xml::element& save_external_resource(xml::element& Element, const ipersistent::save_context& Context, const std::string& Name, const ipath_property::reference_t Reference, const filesystem::path& Value);
  133. void load_external_resource(xml::element& Element, const ipersistent::load_context& Context, ipath_property::reference_t& Reference, filesystem::path& Value);
  134.  
  135. /// Serialization policy for filesystem path data that handles external filesystem resources
  136. template<typename value_t, class property_policy_t>
  137. class path_serialization :
  138.     public property_policy_t,
  139.     public ipersistent
  140. {
  141.     // This policy only works for data stored by-value
  142.     BOOST_STATIC_ASSERT((!boost::is_pointer<value_t>::value));
  143.  
  144. public:
  145.     void save(xml::element& Element, const ipersistent::save_context& Context)
  146.     {
  147.         save_external_resource(Element, Context, property_policy_t::name(), property_policy_t::property_path_reference(), property_policy_t::internal_value());
  148.     }
  149.  
  150.     void load(xml::element& Element, const ipersistent::load_context& Context)
  151.     {
  152.         ipath_property::reference_t reference;
  153.         filesystem::path value;
  154.  
  155.         load_external_resource(Element, Context, reference, value);
  156.  
  157.         property_policy_t::set_property_path_reference(reference);
  158.         property_policy_t::set_value(value);
  159.     }
  160.  
  161. protected:
  162.     template<typename init_t>
  163.     path_serialization(const init_t& Init) :
  164.         property_policy_t(Init)
  165.     {
  166.         Init.persistent_collection().enable_serialization(Init.name(), *this);
  167.     }
  168. };
  169.  
  170. /////////////////////////////////////////////////////////////////////////////
  171. // node_serialization
  172.  
  173. /// Serialization policy for data containers that store a document node and can be serialized as XML
  174. template<typename value_t, class property_policy_t>
  175. class node_serialization :
  176.     public property_policy_t,
  177.     public ipersistent
  178. {
  179.     // If this assertion fires, it means that you're trying to use node_serialization with a non-node data type
  180.     BOOST_STATIC_ASSERT((boost::is_base_and_derived<iunknown, typename boost::remove_pointer<value_t>::type>::value));
  181.  
  182. public:
  183.     void save(xml::element& Element, const ipersistent::save_context& Context)
  184.     {
  185.         if(property_policy_t::internal_node())
  186.             Element.append(xml::element("property", string_cast(Context.lookup.lookup_id(property_policy_t::internal_node())), xml::attribute("name", property_policy_t::name())));
  187.         else
  188.             Element.append(xml::element("property", "0", xml::attribute("name", property_policy_t::name())));
  189.     }
  190.  
  191.     void load(xml::element& Element, const ipersistent::load_context& Context)
  192.     {
  193.         std::string value = Element.text;
  194.         property_policy_t::set_value(dynamic_cast<value_t>(Context.lookup.lookup_object(from_string(value, static_cast<ipersistent_lookup::id_type>(0)))));
  195.     }
  196.  
  197. protected:
  198.     template<typename init_t>
  199.     node_serialization(const init_t& Init) :
  200.         property_policy_t(Init)
  201.     {
  202.         Init.persistent_collection().enable_serialization(Init.name(), *this);
  203.     }
  204.  
  205. private:
  206.     ipersistent_lookup::id_type m_node_id;
  207. };
  208.  
  209. /////////////////////////////////////////////////////////////////////////////
  210. // node_collection_serialization
  211.  
  212. /// Serialization policy for data containers that can be serialized as XML
  213. template<typename value_t, class property_policy_t>
  214. class node_collection_serialization :
  215.     public property_policy_t,
  216.     public ipersistent
  217. {
  218. public:
  219.     void save(xml::element& Element, const ipersistent::save_context& Context)
  220.     {
  221.         std::stringstream buffer;
  222.  
  223.         const inode_collection_property::nodes_t& nodes = property_policy_t::internal_value();
  224.         for(inode_collection_property::nodes_t::const_iterator node = nodes.begin(); node != nodes.end(); ++node)
  225.         {
  226.             if(*node)
  227.                 buffer << " " << string_cast(Context.lookup.lookup_id(*node));
  228.             else
  229.                 buffer << " 0";
  230.         }
  231.  
  232.         Element.append(xml::element("property", buffer.str(), xml::attribute("name", property_policy_t::name())));
  233.     }
  234.  
  235.     void load(xml::element& Element, const ipersistent::load_context& Context)
  236.     {
  237.         inode_collection_property::nodes_t nodes;
  238.  
  239.         std::stringstream buffer(Element.text);
  240.         std::string node;
  241.         while(buffer >> node)
  242.             nodes.push_back(dynamic_cast<inode*>(Context.lookup.lookup_object(from_string(node, static_cast<ipersistent_lookup::id_type>(0)))));
  243.         nodes.erase(std::remove(nodes.begin(), nodes.end(), static_cast<inode*>(0)), nodes.end());
  244.  
  245.         property_policy_t::set_value(nodes);
  246.     }
  247.  
  248. protected:
  249.     template<typename init_t>
  250.     node_collection_serialization(const init_t& Init) :
  251.         property_policy_t(Init)
  252.     {
  253.         Init.persistent_collection().enable_serialization(Init.name(), *this);
  254.     }
  255. };
  256.  
  257. /////////////////////////////////////////////////////////////////////////////
  258. // property_lookup
  259.  
  260. /** \brief Encapsulates the lookup process for connected properties
  261.     \note In the case of circular dependencies, returns the same value as the input property
  262. */
  263. iproperty* property_lookup(iproperty* const Source);
  264.  
  265. /////////////////////////////////////////////////////////////////////////////
  266. // no_property
  267.  
  268. /// Property policy for data containers that do not expose their values using the K-3D property mechanism
  269. template<typename value_t, class name_policy_t>
  270. class no_property :
  271.     public name_policy_t
  272. {
  273. public:
  274.  
  275. protected:
  276.     template<typename init_t>
  277.     no_property(const init_t& Init) :
  278.         name_policy_t(Init)
  279.     {
  280.     }
  281. };
  282.  
  283. /////////////////////////////////////////////////////////////////////////////
  284. // read_only_property
  285.  
  286. /// Property policy that exposes a data container as a read-only K-3D property
  287. template<typename value_t, class name_policy_t>
  288. class read_only_property :
  289.     public name_policy_t,
  290.     public iproperty
  291. {
  292. public:
  293.     const value_t pipeline_value()
  294.     {
  295.         iproperty* const source = property_lookup(this);
  296.         if(source != this)
  297.             return name_policy_t::constrain_value(boost::any_cast<value_t>(source->property_internal_value()));
  298.  
  299.         return name_policy_t::internal_value();
  300.     }
  301.  
  302.     const std::string property_name()
  303.     {
  304.         return name_policy_t::name();
  305.     }
  306.  
  307.     const std::string property_label()
  308.     {
  309.         return m_label;
  310.     }
  311.  
  312.     const std::string property_description()
  313.     {
  314.         return m_description;
  315.     }
  316.  
  317.     const std::type_info& property_type()
  318.     {
  319.         return typeid(value_t);
  320.     }
  321.  
  322.     const boost::any property_internal_value()
  323.     {
  324.         return name_policy_t::internal_value();
  325.     }
  326.  
  327.     const boost::any property_pipeline_value()
  328.     {
  329.         return pipeline_value();
  330.     }
  331.  
  332.     inode* property_node()
  333.     {
  334.         return m_node;
  335.     }
  336.  
  337.     typename name_policy_t::changed_signal_t& property_changed_signal()
  338.     {
  339.         return name_policy_t::changed_signal();
  340.     }
  341.  
  342.     deleted_signal_t& property_deleted_signal()
  343.     {
  344.         return m_deleted_signal;
  345.     }
  346.  
  347.     iproperty* property_dependency()
  348.     {
  349.         return m_dependency;
  350.     }
  351.  
  352.     void property_set_dependency(iproperty* Dependency)
  353.     {
  354.         m_dependency = Dependency;
  355.     }
  356.  
  357. protected:
  358.     template<typename init_t>
  359.     read_only_property(const init_t& Init) :
  360.         name_policy_t(Init),
  361.         m_node(Init.node()),
  362.         m_label(Init.label()),
  363.         m_description(Init.description()),
  364.         m_dependency(0)
  365.     {
  366.         Init.property_collection().register_property(*this);
  367.     }
  368.  
  369.     ~read_only_property()
  370.     {
  371.         m_deleted_signal.emit();
  372.     }
  373.  
  374. private:
  375.     inode* const m_node;
  376.     const char* const m_label;
  377.     const char* const m_description;
  378.     deleted_signal_t m_deleted_signal;
  379.     iproperty* m_dependency;
  380. };
  381.  
  382. /////////////////////////////////////////////////////////////////////////////
  383. // writable_property
  384.  
  385. /// Property policy that exposes a data container as a writable K-3D property
  386. template<typename value_t, class name_policy_t>
  387. class writable_property :
  388.     public name_policy_t,
  389.     public iproperty,
  390.     public iwritable_property
  391. {
  392. public:
  393.     const value_t pipeline_value()
  394.     {
  395.         iproperty* const source = property_lookup(this);
  396.         if(source != this)
  397.             return name_policy_t::constrain_value(boost::any_cast<value_t>(source->property_internal_value()));
  398.  
  399.         return name_policy_t::internal_value();
  400.     }
  401.  
  402.     const std::string property_name()
  403.     {
  404.         return name_policy_t::name();
  405.     }
  406.  
  407.     const std::string property_label()
  408.     {
  409.         return m_label;
  410.     }
  411.  
  412.     const std::string property_description()
  413.     {
  414.         return m_description;
  415.     }
  416.  
  417.     const std::type_info& property_type()
  418.     {
  419.         return typeid(value_t);
  420.     }
  421.  
  422.     const boost::any property_internal_value()
  423.     {
  424.         return name_policy_t::internal_value();
  425.     }
  426.     
  427.     const boost::any property_pipeline_value()
  428.     {
  429.         return pipeline_value();
  430.     }
  431.  
  432.     inode* property_node()
  433.     {
  434.         return m_node;
  435.     }
  436.  
  437.     typename name_policy_t::changed_signal_t& property_changed_signal()
  438.     {
  439.         return name_policy_t::changed_signal();
  440.     }
  441.  
  442.     deleted_signal_t& property_deleted_signal()
  443.     {
  444.         return m_deleted_signal;
  445.     }
  446.  
  447.     bool property_set_value(const boost::any Value, ihint* const Hint)
  448.     {
  449.         const value_t* const new_value = boost::any_cast<value_t>(&Value);
  450.         if(!new_value)
  451.             return false;
  452.  
  453.         name_policy_t::set_value(*new_value, Hint);
  454.         return true;
  455.     }
  456.  
  457.     iproperty* property_dependency()
  458.     {
  459.         return m_dependency;
  460.     }
  461.  
  462.     void property_set_dependency(iproperty* Dependency)
  463.     {
  464.         m_dependency = Dependency;
  465.     }
  466.  
  467. protected:
  468.     template<typename init_t>
  469.     writable_property(const init_t& Init) :
  470.         name_policy_t(Init),
  471.         m_node(Init.node()),
  472.         m_label(Init.label()),
  473.         m_description(Init.description()),
  474.         m_dependency(0)
  475.     {
  476.         Init.property_collection().register_property(*this);
  477.     }
  478.  
  479.     ~writable_property()
  480.     {
  481.         m_deleted_signal.emit();
  482.     }
  483.  
  484. private:
  485.     inode* const m_node;
  486.     const char* const m_label;
  487.     const char* const m_description;
  488.     deleted_signal_t m_deleted_signal;
  489.     iproperty* m_dependency;
  490. };
  491.  
  492. /////////////////////////////////////////////////////////////////////////////
  493. // string_property
  494.  
  495. /// Property policy that exposes a data container as a writable string property
  496. template<typename value_t, class name_policy_t>
  497. class string_property :
  498.     public name_policy_t,
  499.     public iproperty,
  500.     public iwritable_property
  501. {
  502. public:
  503.     const value_t pipeline_value()
  504.     {
  505.         iproperty* const source = property_lookup(this);
  506.         if(source != this)
  507.             return name_policy_t::constrain_value(boost::any_cast<value_t>(source->property_internal_value()));
  508.  
  509.         return name_policy_t::internal_value();
  510.     }
  511.  
  512.     const std::string property_name()
  513.     {
  514.         return name_policy_t::name();
  515.     }
  516.  
  517.     const std::string property_label()
  518.     {
  519.         return m_label;
  520.     }
  521.  
  522.     const std::string property_description()
  523.     {
  524.         return m_description;
  525.     }
  526.  
  527.     const std::type_info& property_type()
  528.     {
  529.         return typeid(std::string);
  530.     }
  531.  
  532.     const boost::any property_internal_value()
  533.     {
  534.         try
  535.         {
  536.             return boost::any(boost::lexical_cast<std::string>(name_policy_t::internal_value()));
  537.         }
  538.         catch(...)
  539.         {
  540.         }
  541.  
  542.         return boost::any();
  543.     }
  544.  
  545.     const boost::any property_pipeline_value()
  546.     {
  547.         return pipeline_value();
  548.     }
  549.  
  550.     inode* property_node()
  551.     {
  552.         return m_node;
  553.     }
  554.  
  555.     typename name_policy_t::changed_signal_t& property_changed_signal()
  556.     {
  557.         return name_policy_t::changed_signal();
  558.     }
  559.  
  560.     deleted_signal_t& property_deleted_signal()
  561.     {
  562.         return m_deleted_signal;
  563.     }
  564.  
  565.     iproperty* property_dependency()
  566.     {
  567.         return m_dependency;
  568.     }
  569.  
  570.     void property_set_dependency(iproperty* Dependency)
  571.     {
  572.         m_dependency = Dependency;
  573.     }
  574.  
  575.     bool property_set_value(const boost::any Value, ihint* const Hint)
  576.     {
  577.         const std::string* const new_value = boost::any_cast<std::string>(&Value);
  578.         if(!new_value)
  579.             return false;
  580.  
  581.         try
  582.         {
  583.             set_value(boost::lexical_cast<value_t>(*new_value), Hint);
  584.             return true;
  585.         }
  586.         catch(...)
  587.         {
  588.         }
  589.  
  590.         return false;
  591.     }
  592.  
  593. protected:
  594.     template<typename init_t>
  595.     string_property(const init_t& Init) :
  596.         name_policy_t(Init),
  597.         m_node(Init.node()),
  598.         m_label(Init.label()),
  599.         m_description(Init.description()),
  600.         m_dependency(0)
  601.     {
  602.         Init.property_collection().register_property(*this);
  603.     }
  604.  
  605.     ~string_property()
  606.     {
  607.         m_deleted_signal.emit();
  608.     }
  609.  
  610. private:
  611.     inode* const m_node;
  612.     const char* const m_label;
  613.     const char* const m_description;
  614.     deleted_signal_t m_deleted_signal;
  615.     iproperty* m_dependency;
  616. };
  617.  
  618. /////////////////////////////////////////////////////////////////////////////
  619. // path_property
  620.  
  621. /// Property policy that exposes a data container as a writable K-3D path property
  622. template<typename value_t, class name_policy_t>
  623. class path_property :
  624.     public name_policy_t,
  625.     public iproperty,
  626.     public iwritable_property,
  627.     public ipath_property
  628. {
  629. public:
  630.     const value_t pipeline_value()
  631.     {
  632.         iproperty* const source = property_lookup(this);
  633.         if(source != this)
  634.             return name_policy_t::constrain_value(boost::any_cast<value_t>(source->property_internal_value()));
  635.  
  636.         return name_policy_t::internal_value();
  637.     }
  638.  
  639.     const std::string property_name()
  640.     {
  641.         return name_policy_t::name();
  642.     }
  643.  
  644.     const std::string property_label()
  645.     {
  646.         return m_label;
  647.     }
  648.  
  649.     const std::string property_description()
  650.     {
  651.         return m_description;
  652.     }
  653.  
  654.     const std::type_info& property_type()
  655.     {
  656.         return typeid(value_t);
  657.     }
  658.  
  659.     const boost::any property_internal_value()
  660.     {
  661.         return name_policy_t::internal_value();
  662.     }
  663.  
  664.     const boost::any property_pipeline_value()
  665.     {
  666.         return pipeline_value();
  667.     }
  668.  
  669.     inode* property_node()
  670.     {
  671.         return m_node;
  672.     }
  673.  
  674.     typename name_policy_t::changed_signal_t& property_changed_signal()
  675.     {
  676.         return name_policy_t::changed_signal();
  677.     }
  678.  
  679.     deleted_signal_t& property_deleted_signal()
  680.     {
  681.         return m_deleted_signal;
  682.     }
  683.  
  684.     iproperty* property_dependency()
  685.     {
  686.         return m_dependency;
  687.     }
  688.  
  689.     void property_set_dependency(iproperty* Dependency)
  690.     {
  691.         m_dependency = Dependency;
  692.     }
  693.  
  694.     bool property_set_value(const boost::any Value, ihint* const Hint)
  695.     {
  696.         const value_t* const new_value = boost::any_cast<value_t>(&Value);
  697.         if(!new_value)
  698.             return false;
  699.         name_policy_t::set_value(*new_value, Hint);
  700.         return true;
  701.     }
  702.  
  703.     const ipath_property::mode_t property_path_mode()
  704.     {
  705.         return m_mode;
  706.     }
  707.  
  708.     const std::string property_path_type()
  709.     {
  710.         return m_type;
  711.     }
  712.  
  713.     const ipath_property::reference_t property_path_reference()
  714.     {
  715.         return m_reference;
  716.     }
  717.  
  718.     void set_property_path_reference(const ipath_property::reference_t Reference)
  719.     {
  720.         if(Reference != m_reference)
  721.         {
  722.             m_reference = Reference;
  723.             m_reference_changed_signal.emit();
  724.         }
  725.     }
  726.  
  727.     ipath_property::path_reference_changed_signal_t& property_path_reference_changed_signal()
  728.  
  729.     {
  730.         return m_reference_changed_signal;
  731.     }
  732.  
  733.     const ipath_property::pattern_filters_t pattern_filters()
  734.     {
  735.         return m_pattern_filters;
  736.     }
  737.  
  738.     void add_pattern_filter(const ipath_property::pattern_filter& PatternFilter)
  739.     {
  740.         m_pattern_filters.push_back(PatternFilter);
  741.     }
  742.  
  743. protected:
  744.     template<typename init_t>
  745.     path_property(const init_t& Init) :
  746.         name_policy_t(Init),
  747.         m_node(Init.node()),
  748.         m_label(Init.label()),
  749.         m_description(Init.description()),
  750.         m_mode(Init.path_mode()),
  751.         m_type(Init.path_type()),
  752.         m_reference(RELATIVE_REFERENCE),
  753.         m_dependency(0)
  754.     {
  755.         Init.property_collection().register_property(*this);
  756.     }
  757.  
  758.     ~path_property()
  759.     {
  760.         m_deleted_signal.emit();
  761.     }
  762.  
  763. private:
  764.     inode* const m_node;
  765.     const char* const m_label;
  766.     const char* const m_description;
  767.     deleted_signal_t m_deleted_signal;
  768.     const ipath_property::mode_t m_mode;
  769.     const std::string m_type;
  770.     ipath_property::reference_t m_reference;
  771.     ipath_property::path_reference_changed_signal_t m_reference_changed_signal;
  772.     ipath_property::pattern_filters_t m_pattern_filters;
  773.     iproperty* m_dependency;
  774. };
  775.  
  776. /////////////////////////////////////////////////////////////////////////////
  777. // script_property
  778.  
  779. /// Property policy that exposes a data container as a writable K-3D script property
  780. template<typename value_t, class name_policy_t>
  781. class script_property :
  782.     public name_policy_t,
  783.     public iproperty,
  784.     public iwritable_property,
  785.     public iscript_property
  786. {
  787. public:
  788.     const value_t pipeline_value()
  789.     {
  790.         iproperty* const source = property_lookup(this);
  791.         if(source != this)
  792.             return name_policy_t::constrain_value(boost::any_cast<value_t>(source->property_internal_value()));
  793.  
  794.         return name_policy_t::internal_value();
  795.     }
  796.  
  797.     const std::string property_name()
  798.     {
  799.         return name_policy_t::name();
  800.     }
  801.  
  802.     const std::string property_label()
  803.     {
  804.         return m_label;
  805.     }
  806.  
  807.     const std::string property_description()
  808.     {
  809.         return m_description;
  810.     }
  811.  
  812.     const std::type_info& property_type()
  813.     {
  814.         return typeid(std::string);
  815.     }
  816.  
  817.     const boost::any property_internal_value()
  818.     {
  819.         try
  820.         {
  821.             return boost::any(boost::lexical_cast<std::string>(name_policy_t::internal_value()));
  822.         }
  823.         catch(...)
  824.         {
  825.         }
  826.  
  827.         return boost::any();
  828.     }
  829.  
  830.     const boost::any property_pipeline_value()
  831.     {
  832.         return pipeline_value();
  833.     }
  834.  
  835.     inode* property_node()
  836.     {
  837.         return m_node;
  838.     }
  839.  
  840.     typename name_policy_t::changed_signal_t& property_changed_signal()
  841.     {
  842.         return name_policy_t::changed_signal();
  843.     }
  844.  
  845.     deleted_signal_t& property_deleted_signal()
  846.     {
  847.         return m_deleted_signal;
  848.     }
  849.  
  850.     iproperty* property_dependency()
  851.     {
  852.         return m_dependency;
  853.     }
  854.  
  855.     void property_set_dependency(iproperty* Dependency)
  856.     {
  857.         m_dependency = Dependency;
  858.     }
  859.  
  860.     bool property_set_value(const boost::any Value, ihint* const Hint)
  861.     {
  862.         const std::string* const new_value = boost::any_cast<std::string>(&Value);
  863.         if(!new_value)
  864.             return false;
  865.  
  866.         try
  867.         {
  868.             set_value(boost::lexical_cast<value_t>(*new_value), Hint);
  869.             return true;
  870.         }
  871.         catch(...)
  872.         {
  873.         }
  874.  
  875.         return false;
  876.     }
  877.  
  878. protected:
  879.     template<typename init_t>
  880.     script_property(const init_t& Init) :
  881.         name_policy_t(Init),
  882.         m_node(Init.node()),
  883.         m_label(Init.label()),
  884.         m_description(Init.description()),
  885.         m_dependency(0)
  886.     {
  887.         Init.property_collection().register_property(*this);
  888.     }
  889.  
  890.     ~script_property()
  891.     {
  892.         m_deleted_signal.emit();
  893.     }
  894.  
  895. private:
  896.     inode* const m_node;
  897.     const char* const m_label;
  898.     const char* const m_description;
  899.     deleted_signal_t m_deleted_signal;
  900.     iproperty* m_dependency;
  901. };
  902.  
  903. /////////////////////////////////////////////////////////////////////////////
  904. // enumeration_property
  905.  
  906. /// Property policy that exposes a data container as a K-3D enumeration property
  907. template<typename value_t, class name_policy_t>
  908. class enumeration_property :
  909.     public name_policy_t,
  910.     public iproperty,
  911.     public iwritable_property,
  912.     public ienumeration_property
  913. {
  914. public:
  915.     const value_t pipeline_value()
  916.     {
  917.         iproperty* const source = property_lookup(this);
  918.         if(source != this)
  919.         {
  920.             try
  921.             {
  922.                 // Because enumeration properties all have type "string", we have to convert the source property into our internal type (which
  923.                 // could fail) before applying any constraints.
  924.                 return name_policy_t::constrain_value(boost::lexical_cast<value_t>(boost::any_cast<string_t>(source->property_internal_value())));
  925.             }
  926.             catch(...)
  927.             {
  928.                 return name_policy_t::internal_value();
  929.             }
  930.         }
  931.  
  932.         return name_policy_t::internal_value();
  933.     }
  934.  
  935.     const string_t property_name()
  936.     {
  937.         return name_policy_t::name();
  938.     }
  939.  
  940.     const string_t property_label()
  941.     {
  942.         return m_label;
  943.     }
  944.  
  945.     const string_t property_description()
  946.     {
  947.         return m_description;
  948.     }
  949.  
  950.     const std::type_info& property_type()
  951.     {
  952.         return typeid(string_t);
  953.     }
  954.  
  955.     const boost::any property_internal_value()
  956.     {
  957.         try
  958.         {
  959.             return boost::any(boost::lexical_cast<string_t>(name_policy_t::internal_value()));
  960.         }
  961.         catch(...)
  962.         {
  963.         }
  964.  
  965.         return boost::any();
  966.     }
  967.  
  968.     const boost::any property_pipeline_value()
  969.     {
  970.         try
  971.         {
  972.             return boost::any(boost::lexical_cast<string_t>(pipeline_value()));
  973.         }
  974.         catch(...)
  975.         {
  976.         }
  977.  
  978.         return boost::any();
  979.     }
  980.  
  981.     inode* property_node()
  982.     {
  983.         return m_node;
  984.     }
  985.  
  986.     typename name_policy_t::changed_signal_t& property_changed_signal()
  987.     {
  988.         return name_policy_t::changed_signal();
  989.     }
  990.  
  991.     deleted_signal_t& property_deleted_signal()
  992.     {
  993.         return m_deleted_signal;
  994.     }
  995.  
  996.     iproperty* property_dependency()
  997.     {
  998.         return m_dependency;
  999.     }
  1000.  
  1001.     void property_set_dependency(iproperty* Dependency)
  1002.     {
  1003.         m_dependency = Dependency;
  1004.     }
  1005.  
  1006.     bool property_set_value(const boost::any Value, ihint* const Hint)
  1007.     {
  1008.         const string_t* const new_value = boost::any_cast<string_t>(&Value);
  1009.         if(!new_value)
  1010.             return false;
  1011.  
  1012.         try
  1013.         {
  1014.             set_value(boost::lexical_cast<value_t>(*new_value), Hint);
  1015.             return true;
  1016.         }
  1017.         catch(...)
  1018.         {
  1019.         }
  1020.  
  1021.         return false;
  1022.     }
  1023.  
  1024.     enumeration_values_t enumeration_values()
  1025.     {
  1026.         return m_values;
  1027.     }
  1028.  
  1029.     sigc::connection connect_enumeration_values_changed(const sigc::slot<void>& Slot)
  1030.     {
  1031.         return m_values_changed_signal.connect(Slot);
  1032.     }
  1033.  
  1034.     void notify_enumeration_values_changed()
  1035.     {
  1036.         m_values_changed_signal.emit();
  1037.     }
  1038.  
  1039. protected:
  1040.     template<typename init_t>
  1041.     enumeration_property(const init_t& Init) :
  1042.         name_policy_t(Init),
  1043.         m_node(Init.node()),
  1044.         m_label(Init.label()),
  1045.         m_description(Init.description()),
  1046.         m_values(Init.values()),
  1047.         m_dependency(0)
  1048.     {
  1049.         Init.property_collection().register_property(*this);
  1050.     }
  1051.  
  1052.     ~enumeration_property()
  1053.     {
  1054.         m_deleted_signal.emit();
  1055.     }
  1056.  
  1057. private:
  1058.     inode* const m_node;
  1059.     const char* const m_label;
  1060.     const char* const m_description;
  1061.     const ienumeration_property::enumeration_values_t& m_values;
  1062.     sigc::signal<void> m_values_changed_signal;
  1063.     deleted_signal_t m_deleted_signal;
  1064.     iproperty* m_dependency;
  1065. };
  1066.  
  1067. /////////////////////////////////////////////////////////////////////////////
  1068. // list_property
  1069.  
  1070. /// Property policy that exposes a data container as a K-3D list property
  1071. template<typename value_t, class name_policy_t>
  1072. class list_property :
  1073.     public name_policy_t,
  1074.     public iproperty,
  1075.     public iwritable_property,
  1076.     public ilist_property<value_t>
  1077. {
  1078. public:
  1079.     const value_t pipeline_value()
  1080.     {
  1081.         iproperty* const source = property_lookup(this);
  1082.         if(source != this)
  1083.             return name_policy_t::constrain_value(boost::any_cast<value_t>(source->property_internal_value()));
  1084.  
  1085.         return name_policy_t::internal_value();
  1086.     }
  1087.  
  1088.     const std::string property_name()
  1089.     {
  1090.         return name_policy_t::name();
  1091.     }
  1092.  
  1093.     const std::string property_label()
  1094.     {
  1095.         return m_label;
  1096.     }
  1097.  
  1098.     const std::string property_description()
  1099.     {
  1100.         return m_description;
  1101.     }
  1102.  
  1103.     const std::type_info& property_type()
  1104.     {
  1105.         return typeid(value_t);
  1106.     }
  1107.  
  1108.     const boost::any property_internal_value()
  1109.     {
  1110.         return boost::any(name_policy_t::internal_value());
  1111.     }
  1112.  
  1113.     const boost::any property_pipeline_value()
  1114.     {
  1115.         return pipeline_value();
  1116.     }
  1117.  
  1118.     inode* property_node()
  1119.     {
  1120.         return m_node;
  1121.     }
  1122.  
  1123.     typename name_policy_t::changed_signal_t& property_changed_signal()
  1124.     {
  1125.         return name_policy_t::changed_signal();
  1126.     }
  1127.  
  1128.     deleted_signal_t& property_deleted_signal()
  1129.     {
  1130.         return m_deleted_signal;
  1131.     }
  1132.  
  1133.     iproperty* property_dependency()
  1134.     {
  1135.         return m_dependency;
  1136.     }
  1137.  
  1138.     void property_set_dependency(iproperty* Dependency)
  1139.     {
  1140.         m_dependency = Dependency;
  1141.     }
  1142.  
  1143.     bool property_set_value(const boost::any Value, ihint* const Hint)
  1144.     {
  1145.         const value_t* const new_value = boost::any_cast<value_t>(&Value);
  1146.         if(!new_value)
  1147.             return false;
  1148.  
  1149.         set_value(*new_value, Hint);
  1150.         return true;
  1151.     }
  1152.  
  1153.     typename ilist_property<value_t>::values_t property_values()
  1154.     {
  1155.         return m_values;
  1156.     }
  1157.  
  1158. protected:
  1159.     template<typename init_t>
  1160.     list_property(const init_t& Init) :
  1161.         name_policy_t(Init),
  1162.         m_node(Init.node()),
  1163.         m_label(Init.label()),
  1164.         m_description(Init.description()),
  1165.         m_values(Init.values()),
  1166.         m_dependency(0)
  1167.     {
  1168.         Init.property_collection().register_property(*this);
  1169.     }
  1170.  
  1171.     ~list_property()
  1172.     {
  1173.         m_deleted_signal.emit();
  1174.     }
  1175.  
  1176. private:
  1177.     inode* const m_node;
  1178.     const char* const m_label;
  1179.     const char* const m_description;
  1180.     const typename ilist_property<value_t>::values_t& m_values;
  1181.     deleted_signal_t m_deleted_signal;
  1182.     iproperty* m_dependency;
  1183. };
  1184.  
  1185. /////////////////////////////////////////////////////////////////////////////
  1186. // node_property
  1187.  
  1188. /// Property policy that exposes a data container as a K-3D node property
  1189. template<typename value_t, class name_policy_t>
  1190. class node_property :
  1191.     public name_policy_t,
  1192.     public iproperty,
  1193.     public iwritable_property,
  1194.     public inode_property
  1195. {
  1196. public:
  1197.     const value_t pipeline_value()
  1198.     {
  1199.         iproperty* const source = property_lookup(this);
  1200.         if(source != this)
  1201.             return name_policy_t::constrain_value(dynamic_cast<value_t>(boost::any_cast<inode*>(source->property_internal_value())));
  1202.  
  1203.         return name_policy_t::internal_value();
  1204.     }
  1205.  
  1206.     const std::string property_name()
  1207.     {
  1208.         return name_policy_t::name();
  1209.     }
  1210.  
  1211.     const std::string property_label()
  1212.     {
  1213.         return m_label;
  1214.     }
  1215.  
  1216.     const std::string property_description()
  1217.     {
  1218.         return m_description;
  1219.     }
  1220.  
  1221.     const std::type_info& property_type()
  1222.     {
  1223.         return typeid(inode*);
  1224.     }
  1225.  
  1226.     const boost::any property_internal_value()
  1227.     {
  1228.         return boost::any(name_policy_t::internal_node());
  1229.     }
  1230.  
  1231.     const boost::any property_pipeline_value()
  1232.     {
  1233.         return dynamic_cast<inode*>(pipeline_value());
  1234.     }
  1235.  
  1236.     inode* property_node()
  1237.     {
  1238.         return m_node;
  1239.     }
  1240.  
  1241.     typename name_policy_t::changed_signal_t& property_changed_signal()
  1242.     {
  1243.         return name_policy_t::changed_signal();
  1244.     }
  1245.  
  1246.     deleted_signal_t& property_deleted_signal()
  1247.     {
  1248.         return m_deleted_signal;
  1249.     }
  1250.  
  1251.     iproperty* property_dependency()
  1252.     {
  1253.         return m_dependency;
  1254.     }
  1255.  
  1256.     void property_set_dependency(iproperty* Dependency)
  1257.     {
  1258.         m_dependency = Dependency;
  1259.     }
  1260.  
  1261.     bool property_set_value(const boost::any Value, ihint* const Hint)
  1262.     {
  1263.         inode* const * new_value = boost::any_cast<inode*>(&Value);
  1264.         if(!new_value)
  1265.             return false;
  1266.  
  1267.         name_policy_t::set_value(dynamic_cast<value_t>(*new_value), Hint);
  1268.         return true;
  1269.     }
  1270.  
  1271.     bool property_allow_none()
  1272.     {
  1273.         return name_policy_t::allow_none();
  1274.     }
  1275.  
  1276.     bool property_allow(iplugin_factory& Factory)
  1277.     {
  1278.         return name_policy_t::allow(Factory);
  1279.     }
  1280.  
  1281.     bool property_allow(inode& Object)
  1282.     {
  1283.         return name_policy_t::allow(Object);
  1284.     }
  1285.  
  1286. protected:
  1287.     template<typename init_t>
  1288.     node_property(const init_t& Init) :
  1289.         name_policy_t(Init),
  1290.         m_node(Init.node()),
  1291.         m_label(Init.label()),
  1292.         m_description(Init.description()),
  1293.         m_dependency(0)
  1294.     {
  1295.         Init.property_collection().register_property(*this);
  1296.     }
  1297.  
  1298.     ~node_property()
  1299.     {
  1300.         m_deleted_signal.emit();
  1301.     }
  1302.  
  1303. private:
  1304.     inode* const m_node;
  1305.     const char* const m_label;
  1306.     const char* const m_description;
  1307.     deleted_signal_t m_deleted_signal;
  1308.     iproperty* m_dependency;
  1309. };
  1310.  
  1311. /////////////////////////////////////////////////////////////////////////////
  1312. // measurement_property
  1313.  
  1314. /// Property policy that exposes a data container as a K-3D measurement property
  1315. template<typename value_t, class name_policy_t>
  1316. class measurement_property :
  1317.     public name_policy_t,
  1318.     public iproperty,
  1319.     public iwritable_property,
  1320.     public imeasurement_property
  1321. {
  1322. public:
  1323.     const value_t pipeline_value()
  1324.     {
  1325.         iproperty* const source = property_lookup(this);
  1326.         if(source != this)
  1327.             return name_policy_t::constrain_value(boost::any_cast<value_t>(source->property_internal_value()));
  1328.  
  1329.         return name_policy_t::internal_value();
  1330.     }
  1331.  
  1332.     const std::string property_name()
  1333.     {
  1334.         return name_policy_t::name();
  1335.     }
  1336.  
  1337.     const std::string property_label()
  1338.     {
  1339.         return m_label;
  1340.     }
  1341.  
  1342.     const std::string property_description()
  1343.     {
  1344.         return m_description;
  1345.     }
  1346.  
  1347.     const std::type_info& property_type()
  1348.     {
  1349.         return typeid(value_t);
  1350.     }
  1351.  
  1352.     const boost::any property_internal_value()
  1353.     {
  1354.         return boost::any(name_policy_t::internal_value());
  1355.     }
  1356.  
  1357.     const boost::any property_pipeline_value()
  1358.     {
  1359.         return pipeline_value();
  1360.     }
  1361.  
  1362.     inode* property_node()
  1363.     {
  1364.         return m_node;
  1365.     }
  1366.  
  1367.     typename name_policy_t::changed_signal_t& property_changed_signal()
  1368.     {
  1369.         return name_policy_t::changed_signal();
  1370.     }
  1371.  
  1372.     deleted_signal_t& property_deleted_signal()
  1373.     {
  1374.         return m_deleted_signal;
  1375.     }
  1376.  
  1377.     iproperty* property_dependency()
  1378.     {
  1379.         return m_dependency;
  1380.     }
  1381.  
  1382.     void property_set_dependency(iproperty* Dependency)
  1383.     {
  1384.         m_dependency = Dependency;
  1385.     }
  1386.  
  1387.     bool property_set_value(const boost::any Value, ihint* const Hint)
  1388.     {
  1389.         const value_t* const new_value = boost::any_cast<value_t>(&Value);
  1390.         if(!new_value)
  1391.             return false;
  1392.  
  1393.         name_policy_t::set_value(*new_value, Hint);
  1394.         return true;
  1395.     }
  1396.  
  1397.     const double property_step_increment()
  1398.     {
  1399.         return m_step_increment;
  1400.     }
  1401.  
  1402.     const std::type_info& property_units()
  1403.     {
  1404.         return m_units;
  1405.     }
  1406.  
  1407. protected:
  1408.     template<typename init_t>
  1409.     measurement_property(const init_t& Init) :
  1410.         name_policy_t(Init),
  1411.         m_node(Init.node()),
  1412.         m_label(Init.label()),
  1413.         m_description(Init.description()),
  1414.         m_step_increment(Init.step_increment()),
  1415.         m_units(Init.units()),
  1416.         m_dependency(0)
  1417.     {
  1418.         Init.property_collection().register_property(*this);
  1419.     }
  1420.  
  1421.     ~measurement_property()
  1422.     {
  1423.         m_deleted_signal.emit();
  1424.     }
  1425.  
  1426. private:
  1427.     inode* const m_node;
  1428.     const char* const m_label;
  1429.     const char* const m_description;
  1430.     const double m_step_increment;
  1431.     const std::type_info& m_units;
  1432.     deleted_signal_t m_deleted_signal;
  1433.     iproperty* m_dependency;
  1434. };
  1435.  
  1436. /////////////////////////////////////////////////////////////////////////////
  1437. // no_name
  1438.  
  1439. /// Name policy for unnamed data containers
  1440. template<class constraint_policy_t>
  1441. class no_name :
  1442.     public constraint_policy_t
  1443. {
  1444. protected:
  1445.     template<typename init_t>
  1446.     no_name(const init_t& Init) :
  1447.         constraint_policy_t(Init)
  1448.     {
  1449.     }
  1450. };
  1451.  
  1452. /////////////////////////////////////////////////////////////////////////////
  1453. // immutable_name
  1454.  
  1455. /// Name policy for data containers whose name cannot be changed
  1456. template<class constraint_policy_t>
  1457. class immutable_name :
  1458.     public constraint_policy_t
  1459. {
  1460. public:
  1461.     /// Returns the container name
  1462.     const std::string name() const
  1463.     {
  1464.         return m_name;
  1465.     }
  1466.  
  1467. protected:
  1468.     template<typename init_t>
  1469.     immutable_name(const init_t& Init) :
  1470.         constraint_policy_t(Init),
  1471.         m_name(Init.name())
  1472.     {
  1473.     }
  1474.  
  1475. private:
  1476.     /// Storage for the container name
  1477.     const char* const m_name;
  1478. };
  1479.  
  1480. /////////////////////////////////////////////////////////////////////////////
  1481. // no_constraint
  1482.  
  1483. /// Constraint policy for data containers whose values are unconstrained
  1484. template<typename value_t, class undo_policy_t>
  1485. class no_constraint :
  1486.     public undo_policy_t
  1487. {
  1488. public:
  1489.     void set_value(const value_t& Value, ihint* const Hint = 0)
  1490.     {
  1491.         if(Value != undo_policy_t::internal_value())
  1492.             undo_policy_t::set_value(Value, Hint);
  1493.     }
  1494.  
  1495.     const value_t constrain_value(const value_t Value)
  1496.     {
  1497.         return Value;
  1498.     }
  1499.  
  1500. protected:
  1501.     template<typename init_t>
  1502.     no_constraint(const init_t& Init) :
  1503.         undo_policy_t(Init)
  1504.     {
  1505.     }
  1506. };
  1507.  
  1508. /////////////////////////////////////////////////////////////////////////////
  1509. // iconstraint
  1510.  
  1511. /// Abstract interface for a chain-of-responsibility constraint node
  1512. template<typename value_t>
  1513. class iconstraint
  1514. {
  1515. public:
  1516.     virtual ~iconstraint() {}
  1517.  
  1518.     void constrain(value_t& Value)
  1519.     {
  1520.         on_constrain(Value);
  1521.  
  1522.         if(m_next_constraint.get())
  1523.             m_next_constraint->constrain(Value);
  1524.     }
  1525.  
  1526. protected:
  1527.     explicit iconstraint(iconstraint<value_t>* NextConstraint) :
  1528.         m_next_constraint(NextConstraint)
  1529.     {
  1530.     }
  1531.  
  1532. private:
  1533.     /// Implement this method in a derived class to modify / constrain the input Value
  1534.     virtual void on_constrain(value_t& Value) = 0;
  1535.  
  1536.     /// Storage for the (optional) next constraint to apply in the chain
  1537.     const std::auto_ptr<iconstraint<value_t> > m_next_constraint;
  1538. };
  1539.  
  1540. namespace constraint
  1541. {
  1542.  
  1543. /////////////////////////////////////////////////////////////////////////////
  1544. // minimum_t
  1545.  
  1546. /// Constraint node that enforces a minimum value (using the std::max concept)
  1547. template<typename value_t>
  1548. class minimum_t :
  1549.     public iconstraint<value_t>
  1550. {
  1551.     // We require that the minimum constraint be applied only to signed types, to prevent
  1552.     // overflow problems associated with unsigned types (for example, if you had a minimum
  1553.     // constraint of 0 applied to an unsigned long with current value 0, and subtract 1, the
  1554.     // result will 0xffffffff, which compares as larger than 0)
  1555.     BOOST_STATIC_ASSERT((std::numeric_limits<value_t>::is_signed));
  1556.  
  1557. public:
  1558.     minimum_t(const value_t MinimumValue, iconstraint<value_t>* NextConstraint = 0) :
  1559.         iconstraint<value_t>(NextConstraint),
  1560.         m_minimum_value(MinimumValue)
  1561.     {
  1562.     }
  1563.  
  1564. private:
  1565.     void on_constrain(value_t& Value)
  1566.     {
  1567.         Value = std::max(Value, m_minimum_value);
  1568.     }
  1569.  
  1570.     const value_t m_minimum_value;
  1571. };
  1572.  
  1573. /////////////////////////////////////////////////////////////////////////////
  1574. // minimum
  1575.  
  1576. /// Convenience factory function for creating minimum_t constraint nodes
  1577. template<typename value_t>
  1578. iconstraint<value_t>* minimum(const value_t MinimumValue, iconstraint<value_t>* NextConstraint = 0)
  1579. {
  1580.     return new minimum_t<value_t>(MinimumValue, NextConstraint);
  1581. }
  1582.  
  1583. /////////////////////////////////////////////////////////////////////////////
  1584. // maximum_t
  1585.  
  1586. /// Constraint node that enforces a maximum value (using the std::min concept)
  1587. template<typename value_t>
  1588. class maximum_t :
  1589.     public iconstraint<value_t>
  1590. {
  1591. public:
  1592.     maximum_t(const value_t MaximumValue, iconstraint<value_t>* NextConstraint = 0) :
  1593.         iconstraint<value_t>(NextConstraint),
  1594.         m_maximum_value(MaximumValue)
  1595.     {
  1596.     }
  1597.  
  1598. private:
  1599.     void on_constrain(value_t& Value)
  1600.     {
  1601.         Value = std::min(Value, m_maximum_value);
  1602.     }
  1603.  
  1604.     const value_t m_maximum_value;
  1605. };
  1606.  
  1607. /////////////////////////////////////////////////////////////////////////////
  1608. // maximum
  1609.  
  1610. /// Convenience factory function for creating maximum_t constraint nodes
  1611. template<typename value_t>
  1612. iconstraint<value_t>* maximum(const value_t MaximumValue, iconstraint<value_t>* NextConstraint = 0)
  1613. {
  1614.     return new maximum_t<value_t>(MaximumValue, NextConstraint);
  1615. }
  1616.  
  1617. } // namespace constraint
  1618.  
  1619. /////////////////////////////////////////////////////////////////////////////
  1620. // with_constraint
  1621.  
  1622. /// Policy for data nodes whose values are constrained by a chain of one-to-many iconstraint nodes
  1623. template<typename value_t, class undo_policy_t>
  1624. class with_constraint :
  1625.     public undo_policy_t
  1626. {
  1627. public:
  1628.     void set_value(value_t Value, ihint* const Hint = 0)
  1629.     {
  1630.         m_constraint->constrain(Value);
  1631.  
  1632.         if(Value != undo_policy_t::internal_value())
  1633.             undo_policy_t::set_value(Value, Hint);
  1634.     }
  1635.  
  1636.     const value_t constrain_value(value_t Value)
  1637.     {
  1638.         m_constraint->constrain(Value);
  1639.         return Value;
  1640.     }
  1641.  
  1642. protected:
  1643.     template<typename init_t>
  1644.     with_constraint(const init_t& Init) :
  1645.         undo_policy_t(Init),
  1646.         m_constraint(Init.constraint())
  1647.     {
  1648.         assert(m_constraint.get());
  1649.     }
  1650.  
  1651. private:
  1652.     /// Stores the (mandatory) chain of constraint nodes to apply to incoming values
  1653.     const std::auto_ptr<iconstraint<value_t> > m_constraint;
  1654. };
  1655.  
  1656. /////////////////////////////////////////////////////////////////////////////
  1657. // no_undo
  1658.  
  1659. /// Undo policy for data containers that do not store state changes for undo/redo
  1660. template<typename value_t, class storage_policy_t>
  1661. class no_undo :
  1662.     public storage_policy_t
  1663. {
  1664. protected:
  1665.     template<typename init_t>
  1666.     no_undo(const init_t& Init) :
  1667.         storage_policy_t(Init)
  1668.     {
  1669.     }
  1670.  
  1671.     /// This little bit of magic makes it possible for base classes (such as node_storage) to update their own values while observing the correct undo policy
  1672.     void internal_set_value(const value_t& Value, ihint* const Hint)
  1673.     {
  1674.         set_value(Value, Hint);
  1675.     }
  1676. };
  1677.  
  1678. /////////////////////////////////////////////////////////////////////////////
  1679. // with_undo
  1680.  
  1681. /// Undo policy for data containers that stores state changes for undo/redo
  1682. template <typename value_t, class storage_policy_t>
  1683. class with_undo :
  1684.     public storage_policy_t,
  1685.     public virtual sigc::trackable
  1686. {
  1687. public:
  1688.     /// Returns true iff the next write to the underlying storage will generate undo/redo data (useful if you need to perform additional undo/redo related operations, such as creating a signal connection)
  1689.     bool ready_to_record()
  1690.     {
  1691.         return !m_changes && m_state_recorder.current_change_set();
  1692.     }
  1693.  
  1694.     /// Returns the state recorder for storing undo/redo data
  1695.     istate_recorder& state_recorder()
  1696.     {
  1697.         return m_state_recorder;
  1698.     }
  1699.  
  1700. protected:
  1701.     template<typename init_t>
  1702.     with_undo(const init_t& Init) :
  1703.         storage_policy_t(Init),
  1704.         m_state_recorder(Init.document().state_recorder()),
  1705.         m_changes(false)
  1706.     {
  1707.     }
  1708.  
  1709.     typedef with_undo<value_t, storage_policy_t> this_t;
  1710.  
  1711.     /// This little bit of magic makes it possible for base classes (such as node_storage) to update their own values while observing the correct undo policy
  1712.     void internal_set_value(const value_t& Value, ihint* const Hint)
  1713.     {
  1714.         set_value(Value, Hint);
  1715.     }
  1716.  
  1717.     void set_value(const value_t& Value, ihint* const Hint = 0)
  1718.     {
  1719.         if(ready_to_record())
  1720.         {
  1721.             m_changes = true;
  1722.             /// Note ... we don't save the connection here because connections are automatically disconnected when the signal is emitted
  1723.             m_state_recorder.connect_recording_done_signal(sigc::mem_fun(*this, &this_t::on_recording_done));
  1724.             storage_policy_t::start_recording(m_state_recorder);
  1725.         }
  1726.  
  1727.         storage_policy_t::set_value(Value, Hint);
  1728.     }
  1729.  
  1730. private:
  1731.     /// Called by the signal system once undo/redo recording is complete, so we can record our final value for redo purposes
  1732.     void on_recording_done()
  1733.     {
  1734.         // Sanity check ...
  1735.         assert(m_changes);
  1736.         assert(m_state_recorder.current_change_set());
  1737.  
  1738.         m_changes = false;
  1739.         storage_policy_t::finish_recording(m_state_recorder);
  1740.     }
  1741.  
  1742.     /// Central location where undo/redo data is stored
  1743.     istate_recorder& m_state_recorder;
  1744.     /// Set to true iff the underlying data has changed during undo/redo recording
  1745.     bool m_changes;
  1746. };
  1747.  
  1748. /////////////////////////////////////////////////////////////////////////////
  1749. // local_storage
  1750.  
  1751. /// Storage policy for data containers that store their state by value
  1752. template<typename value_t, class signal_policy_t>
  1753. class local_storage :
  1754.     public signal_policy_t
  1755. {
  1756. public:
  1757.     /// Writable access to the underlying data - this is handy for working with STL containers, but be careful - writing data in this way will bypass signal and undo policies
  1758.     value_t& internal_value()
  1759.     {
  1760.         return m_value;
  1761.     }
  1762.  
  1763.     /// Read-only access to the underlying data
  1764.     const value_t& internal_value() const
  1765.     {
  1766.         return m_value;
  1767.     }
  1768.  
  1769. protected:
  1770.     template<typename init_t>
  1771.     local_storage(const init_t& Init) :
  1772.         signal_policy_t(Init),
  1773.         m_value(Init.value())
  1774.     {
  1775.     }
  1776.  
  1777.     /// Optionally called to store the original state of the data prior to modification
  1778.     void start_recording(istate_recorder& StateRecorder)
  1779.     {
  1780.         signal_policy_t::start_recording(StateRecorder);
  1781.         StateRecorder.current_change_set()->record_old_state(new value_container(m_value));
  1782.     }
  1783.  
  1784.     /// Sets a new value for the data
  1785.     void set_value(const value_t& Value, ihint* const Hint = 0)
  1786.     {
  1787.         m_value = Value;
  1788.         signal_policy_t::set_value(Hint);
  1789.     }
  1790.  
  1791.     /// Optionally called to store the new state of the data after one-or-more modifications
  1792.     void finish_recording(istate_recorder& StateRecorder)
  1793.     {
  1794.         StateRecorder.current_change_set()->record_new_state(new value_container(m_value));
  1795.         signal_policy_t::finish_recording(StateRecorder);
  1796.     }
  1797.  
  1798. private:
  1799.     /// Local storage for the data stored by this policy
  1800.     value_t m_value;
  1801.  
  1802.     /// Provides an implementation of istate_container for storing nodes by value (ValueType must have a copy constructor and assignment operator)
  1803.     class value_container :
  1804.         public istate_container
  1805.     {
  1806.     public:
  1807.         value_container(value_t& Instance) :
  1808.             m_instance(Instance),
  1809.             m_value(Instance)
  1810.         {
  1811.         }
  1812.  
  1813.         void restore_state()
  1814.         {
  1815.             m_instance = m_value;
  1816.         }
  1817.  
  1818.     private:
  1819.         value_t& m_instance;
  1820.         const value_t m_value;
  1821.     };
  1822. };
  1823.  
  1824. /////////////////////////////////////////////////////////////////////////////
  1825. // node_storage
  1826.  
  1827. /// Storage policy for data containers that store a pointer to a document node that could be deleted by the user at any time - note that value_t should be the interface type used to access the node
  1828. template<typename value_t, class signal_policy_t>
  1829. class node_storage :
  1830.     public signal_policy_t,
  1831.     public virtual sigc::trackable
  1832. {
  1833. public:
  1834.     /// Returns an interface pointer to the node (could be NULL)
  1835.     value_t internal_value()
  1836.     {
  1837.         return dynamic_cast<value_t>(m_node);
  1838.     }
  1839.  
  1840.     /// Returns the underlying node (could be NULL)
  1841.     inode* internal_node()
  1842.     {
  1843.         return m_node;
  1844.     }
  1845.  
  1846.     /// Returns true iff the value is allowed to be NULL
  1847.     bool allow_none()
  1848.     {
  1849.         return true;
  1850.     }
  1851.  
  1852.     /// Returns true iff the given factory creates an node that could be stored by this container
  1853.     bool allow(iplugin_factory& Factory)
  1854.     {
  1855.         return Factory.implements(typeid(typename boost::remove_pointer<value_t>::type));
  1856.     }
  1857.  
  1858.     /// Returns true iff the given node coult be stored by this container
  1859.     bool allow(inode& Object)
  1860.     {
  1861.         return dynamic_cast<value_t>(&Object) ? true : false;
  1862.     }
  1863.  
  1864. protected:
  1865.     template<typename init_t>
  1866.     node_storage(const init_t& Init) :
  1867.         signal_policy_t(Init),
  1868.         m_node(dynamic_cast<inode*>(Init.value()))
  1869.     {
  1870.         if(m_node)
  1871.         {
  1872.             m_node_deleted_connection = m_node->deleted_signal().connect(sigc::mem_fun(*this, &node_storage::on_node_deleted));
  1873.             if(inode_change_signal* const node_change_signal = dynamic_cast<inode_change_signal*>(m_node))
  1874.                 m_node_changed_connection = node_change_signal->connect_node_changed_signal(signal_policy_t::changed_signal().make_slot());
  1875.         }
  1876.     }
  1877.  
  1878.     virtual ~node_storage()
  1879.     {
  1880.     }
  1881.  
  1882.     void on_node_deleted()
  1883.     {
  1884.         internal_set_value(0, 0);
  1885.     }
  1886.  
  1887.     /// Optionally called to store the original state of the data prior to modification
  1888.     void start_recording(istate_recorder& StateRecorder)
  1889.     {
  1890.         signal_policy_t::start_recording(StateRecorder);
  1891.         StateRecorder.current_change_set()->record_old_state(new value_container(m_node));
  1892.     }
  1893.  
  1894.     /// Sets a new value for the data
  1895.     void set_value(value_t Value, ihint* const Hint)
  1896.     {
  1897.         if(m_node)
  1898.         {
  1899.             m_node_deleted_connection.disconnect();
  1900.             m_node_changed_connection.disconnect();
  1901.         }
  1902.  
  1903.         m_node = dynamic_cast<inode*>(Value);
  1904.  
  1905.         if(m_node)
  1906.         {
  1907.             m_node_deleted_connection = m_node->deleted_signal().connect(sigc::mem_fun(*this, &node_storage::on_node_deleted));
  1908.             if(inode_change_signal* const node_change_signal = dynamic_cast<inode_change_signal*>(m_node))
  1909.                 m_node_changed_connection = node_change_signal->connect_node_changed_signal(signal_policy_t::changed_signal().make_slot());
  1910.         }
  1911.  
  1912.         signal_policy_t::set_value(Hint);
  1913.     }
  1914.  
  1915.     /// Optionally called to store the new state of the data after one-or-more modifications
  1916.     void finish_recording(istate_recorder& StateRecorder)
  1917.     {
  1918.         StateRecorder.current_change_set()->record_new_state(new value_container(m_node));
  1919.         signal_policy_t::finish_recording(StateRecorder);
  1920.     }
  1921.  
  1922. private:
  1923.     /// This little bit of magic allows us to "call" the derived undo policy when our state is modified internally, e.g. if the node is deleted
  1924.     virtual void internal_set_value(const value_t& Value, ihint* const Hint)
  1925.     {
  1926.     }
  1927.  
  1928.     /// Local storage for the node stored by this policy
  1929.     inode* m_node;
  1930.     sigc::connection m_node_deleted_connection;
  1931.     sigc::connection m_node_changed_connection;
  1932.  
  1933.     /// Provides an implementation of istate_container for storing nodes by value (ValueType must have a copy constructor and assignment operator)
  1934.     class value_container :
  1935.         public istate_container
  1936.     {
  1937.     public:
  1938.         value_container(inode*& Instance) :
  1939.             m_instance(Instance),
  1940.             m_value(Instance)
  1941.         {
  1942.         }
  1943.  
  1944.         void restore_state()
  1945.         {
  1946.             m_instance = m_value;
  1947.         }
  1948.  
  1949.     private:
  1950.         inode*& m_instance;
  1951.         inode* m_value;
  1952.     };
  1953. };
  1954.  
  1955. /////////////////////////////////////////////////////////////////////////////
  1956. // pointer_storage
  1957.  
  1958. /// Read-only storage policy that stores a value by pointer, created on-demand
  1959. /** \deprecated Use pointer_demand_storage instead */
  1960. template<typename pointer_t, typename signal_policy_t>
  1961. class pointer_storage :
  1962.     public signal_policy_t
  1963. {
  1964.     // This policy only works for data stored by-pointer
  1965.     BOOST_STATIC_ASSERT((boost::is_pointer<pointer_t>::value));
  1966.  
  1967. public:
  1968.     typedef typename boost::remove_pointer<pointer_t>::type non_pointer_t;
  1969.     typedef pointer_storage<pointer_t, signal_policy_t> this_t;
  1970.  
  1971.     /// Set a slot that will be called to initialize the value when first created
  1972.     void set_initialize_slot(const sigc::slot<void, non_pointer_t&>& Slot)
  1973.     {
  1974.         m_initialize_slot = Slot;
  1975.         reset();
  1976.     }
  1977.  
  1978.     /// Set the slot that will be called to update the value whenever it changes
  1979.     void set_update_slot(const sigc::slot<void, non_pointer_t&>& Slot)
  1980.     {
  1981.         m_update_slot = Slot;
  1982.         update();
  1983.     }
  1984.  
  1985.     /// Returns a slot that will invoke the reset() method
  1986.     sigc::slot<void, ihint*> make_reset_slot()
  1987.     {
  1988.         return sigc::bind<0>(sigc::mem_fun(*this, &this_t::reset), static_cast<pointer_t>(0));
  1989.     }
  1990.  
  1991.     /// Returns a slot that will invoke the update() method
  1992.     sigc::slot<void, ihint*> make_update_slot()
  1993.     {
  1994.         return sigc::mem_fun(*this, &this_t::update);
  1995.     }
  1996.  
  1997.     /// Store an object as the new value, taking control of its lifetime
  1998.     void reset(pointer_t NewValue = 0, ihint* const Hint = 0)
  1999.     {
  2000.         // Ensure that our value doesn't go out-of-scope while it's being modified
  2001.         if(m_executing)
  2002.             return;
  2003.  
  2004.         m_value.reset(NewValue);
  2005.         signal_policy_t::set_value(Hint);
  2006.     }
  2007.  
  2008.     /// Schedule an update for the value the next time it's read
  2009.     void update(ihint* const Hint = 0)
  2010.     {
  2011.         // Ensure that our value doesn't go out-of-scope while it's being modified
  2012.         if(m_executing)
  2013.             return;
  2014.  
  2015.         m_update = true;
  2016.         signal_policy_t::set_value(Hint);
  2017.     }
  2018.  
  2019.     /// Accesses the underlying value, creating it if it doesn't already exist
  2020.     pointer_t internal_value()
  2021.     {
  2022.         if(!m_value.get())
  2023.         {
  2024.             m_executing = true;
  2025.  
  2026.             // We can cancel pending updates since we're creating the value from scratch
  2027.             m_update = false;
  2028.  
  2029.             // Note: we create the value and update its state in two steps
  2030.             // because m_data_slot() may cause this method to be executed in a loop
  2031.             m_value.reset(new non_pointer_t());
  2032.             m_initialize_slot(*m_value);
  2033.  
  2034.             m_executing = false;
  2035.         }
  2036.         
  2037.         if(m_update)
  2038.         {
  2039.             m_executing = true;
  2040.  
  2041.             m_update = false;
  2042.             m_update_slot(*m_value);
  2043.  
  2044.             m_executing = false;
  2045.         }
  2046.  
  2047.         return m_value.get();
  2048.     }
  2049.  
  2050. protected:
  2051.     template<typename init_t>
  2052.     pointer_storage(const init_t& Init) :
  2053.         signal_policy_t(Init),
  2054.         m_update(false),
  2055.         m_executing(false)
  2056.     {
  2057.     }
  2058.  
  2059. private:
  2060.     /// Storage for this policy's value
  2061.     std::auto_ptr<non_pointer_t> m_value;
  2062.     /// Set to true if this policy's value is stale and needs to be updated
  2063.     bool m_update;
  2064.     /// Stores a slot that will be executed to initialize this policy's value
  2065.     sigc::slot<void, non_pointer_t&> m_initialize_slot;
  2066.     /// Stores a slot that will be executed to update this policy's value
  2067.     sigc::slot<void, non_pointer_t&> m_update_slot;
  2068.     /// Set to true during initialization / update of the policy value, to prevent problems with recursion
  2069.     bool m_executing;
  2070. };
  2071.  
  2072. /////////////////////////////////////////////////////////////////////////////
  2073. // computed_storage
  2074.  
  2075. /// Read-only storage policy that returns a computed value, storing nothing
  2076. template<typename value_t, typename signal_policy_t>
  2077. class computed_storage :
  2078.     public signal_policy_t
  2079. {
  2080. public:
  2081.     // This policy only works for data stored by-value
  2082.     BOOST_STATIC_ASSERT((!boost::is_pointer<value_t>::value));
  2083.  
  2084.     /// Returns a slot that will invoke the reset() method
  2085.     sigc::slot<void, ihint*> make_reset_slot()
  2086.     {
  2087.         return sigc::mem_fun(*this, &computed_storage<value_t, signal_policy_t>::reset);
  2088.     }
  2089.  
  2090.     /// Resets the underlying data so it will be recalculated the next time it's read
  2091.     void reset(ihint* const Hint = 0)
  2092.     {
  2093.         if(m_executing)
  2094.             return;
  2095.  
  2096.         m_cache.reset();
  2097.         signal_policy_t::set_value(0);
  2098.     }
  2099.  
  2100.     /// Accesses the underlying data, creating it if it doesn't already exist
  2101.     value_t internal_value()
  2102.     {
  2103.         if(!m_cache.get())
  2104.         {
  2105.             m_executing = true;
  2106.  
  2107.             // Note: we create the cache and set its value in two steps
  2108.             // because m_data_slot() may cause this method to be executed in a loop
  2109.             m_cache.reset(new value_t());
  2110.             *m_cache = m_data_slot();
  2111.  
  2112.             m_executing = false;
  2113.         }
  2114.  
  2115.         return *m_cache;
  2116.     }
  2117.  
  2118. protected:
  2119.     template<typename init_t>
  2120.     computed_storage(const init_t& Init) :
  2121.         signal_policy_t(Init),
  2122.         m_data_slot(Init.slot()),
  2123.         m_executing(false)
  2124.     {
  2125.     }
  2126.  
  2127. private:
  2128.     /// Storage for this policy's value
  2129.     std::auto_ptr<value_t> m_cache;
  2130.     /// Stores a slot that will be executed to initialize this policy's value
  2131.     sigc::slot<value_t> m_data_slot;
  2132.     /// Set to true during initialization of the policy value, to prevent problems with recursion
  2133.     bool m_executing;
  2134. };
  2135.  
  2136. /////////////////////////////////////////////////////////////////////////////
  2137. // no_signal
  2138.  
  2139. /// Signal policy for data containers that do not notify observers when their value changes
  2140. template<typename value_t>
  2141. class no_signal
  2142. {
  2143. protected:
  2144.     template<typename init_t>
  2145.     no_signal(const init_t& Init)
  2146.     {
  2147.     }
  2148.  
  2149.     void start_recording(istate_recorder& StateRecorder)
  2150.     {
  2151.     }
  2152.  
  2153.     void set_value(ihint* const Hint)
  2154.     {
  2155.     }
  2156.  
  2157.     void finish_recording(istate_recorder& StateRecorder)
  2158.     {
  2159.     }
  2160. };
  2161.  
  2162. /////////////////////////////////////////////////////////////////////////////
  2163. // change_signal
  2164.  
  2165. /// Signal policy for data containers that notify observers when their value changes, including through undo/redo.
  2166. template<typename value_t>
  2167. class change_signal
  2168. {
  2169. public:
  2170.     /// Defines a signal emitted when the underlying data changes.  The signal includes an optional "hint" that describes the nature of the change.
  2171.     typedef sigc::signal<void, ihint*> changed_signal_t;
  2172.  
  2173.     /// Returns a reference to the signal that is emitted whenever the underlying data changes
  2174.     changed_signal_t& changed_signal()
  2175.     {
  2176.         return m_changed_signal;
  2177.     }
  2178.  
  2179. protected:
  2180.     template<typename init_t>
  2181.     change_signal(const init_t& Init)
  2182.     {
  2183.     }
  2184.  
  2185.     void start_recording(istate_recorder& StateRecorder)
  2186.     {
  2187.     }
  2188.  
  2189.     void set_value(ihint* const Hint)
  2190.     {
  2191.         m_changed_signal.emit(Hint);
  2192.     }
  2193.  
  2194.     void finish_recording(istate_recorder& StateRecorder)
  2195.     {
  2196.         StateRecorder.current_change_set()->connect_undo_signal(sigc::bind(m_changed_signal.make_slot(), static_cast<ihint*>(0)));
  2197.         StateRecorder.current_change_set()->connect_redo_signal(sigc::bind(m_changed_signal.make_slot(), static_cast<ihint*>(0)));
  2198.     }
  2199.  
  2200. private:
  2201.     changed_signal_t m_changed_signal;
  2202. };
  2203.  
  2204. /// Signal policy for data containers that notify observers when their value changes.  Observers can choose whether to be notified every time the value changes (including undo/redo), or only when the value is changed explicitly by a caller.
  2205. template<typename value_t>
  2206. class explicit_change_signal
  2207. {
  2208. public:
  2209.     /// Defines a signal emitted when the underlying data changes.  The signal includes an optional "hint" that describes the nature of the change.
  2210.     typedef sigc::signal<void, k3d::ihint*> changed_signal_t;
  2211.  
  2212.     /// Returns a reference to the signal that is emitted whenever the underlying data changes.
  2213.     changed_signal_t& changed_signal()
  2214.     {
  2215.         return m_changed_signal;
  2216.     }
  2217.  
  2218.     /// Connects a slot to a signal that is emitted whenever the underlying data is modified explicitly through set_value, never by undo/redo
  2219.     const sigc::connection connect_explicit_change_signal(const sigc::slot<void, k3d::ihint*>& Slot)
  2220.     {
  2221.         return m_explicit_change_signal.connect(Slot);
  2222.     }
  2223.  
  2224. protected:
  2225.     template<typename init_t>
  2226.     explicit_change_signal(const init_t& Init)
  2227.     {
  2228.     }
  2229.  
  2230.     void start_recording(k3d::istate_recorder& StateRecorder)
  2231.     {
  2232.     }
  2233.  
  2234.     void set_value(k3d::ihint* const Hint)
  2235.     {
  2236.         m_changed_signal.emit(Hint);
  2237.         m_explicit_change_signal.emit(Hint);
  2238.     }
  2239.  
  2240.     void finish_recording(k3d::istate_recorder& StateRecorder)
  2241.     {
  2242.         StateRecorder.current_change_set()->connect_undo_signal(sigc::bind(m_changed_signal.make_slot(), static_cast<k3d::ihint*>(0)));
  2243.         StateRecorder.current_change_set()->connect_redo_signal(sigc::bind(m_changed_signal.make_slot(), static_cast<k3d::ihint*>(0)));
  2244.     }
  2245.  
  2246. private:
  2247.     changed_signal_t m_changed_signal;
  2248.     changed_signal_t m_explicit_change_signal;
  2249. };
  2250.  
  2251. /// Convenience macro for declaring k3d::data::container nodes
  2252. #define k3d_data(value_type, name_policy, signal_policy, undo_policy, storage_policy, constraint_policy, property_policy, serialization_policy) \
  2253.     k3d::data::container<value_type, serialization_policy<value_type, property_policy<value_type, name_policy<constraint_policy<value_type, undo_policy<value_type, storage_policy<value_type, signal_policy<value_type> > > > > > > >
  2254.  
  2255. /// Allows an arbitrary set of initializers to be consolidated into a single node
  2256. template<class init_t>
  2257. class initializer_t :
  2258.     public init_t
  2259. {
  2260. public:
  2261.     explicit initializer_t(const init_t& Init) :
  2262.         init_t(Init)
  2263.     {
  2264.     };
  2265. };
  2266.  
  2267. /// Helper class used to consolidate two initializers into a single node
  2268. template<typename lhs_t, typename rhs_t>
  2269. class composition_t :
  2270.     public lhs_t,
  2271.     public rhs_t
  2272. {
  2273. public:
  2274.     explicit composition_t(const lhs_t& LHS, const rhs_t& RHS) :
  2275.         lhs_t(LHS),
  2276.         rhs_t(RHS)
  2277.     {
  2278.     }
  2279. };
  2280.  
  2281. /// Consolidates two initializers into a single node, which can be consolidated in-turn
  2282. template<typename lhs_t, typename rhs_t>
  2283. inline const initializer_t<composition_t<lhs_t, rhs_t> > operator+(const initializer_t<lhs_t>& LHS, const initializer_t<rhs_t>& RHS)
  2284. {
  2285.     return initializer_t<composition_t<lhs_t, rhs_t> >(composition_t<lhs_t, rhs_t>(LHS, RHS));
  2286. }
  2287.  
  2288. /// Helper class used to set a data container's initial value
  2289. template<typename value_t>
  2290. class value_initializer_t
  2291. {
  2292. public:
  2293.     explicit value_initializer_t(const value_t& Value) :
  2294.         m_value(Value)
  2295.     {
  2296.     }
  2297.  
  2298.     const value_t& value() const
  2299.     {
  2300.         return m_value;
  2301.     }
  2302.  
  2303. private:
  2304.     const value_t m_value;
  2305. };
  2306.  
  2307. template<typename value_t>
  2308. inline const initializer_t<value_initializer_t<value_t> > init_value(const value_t& Value)
  2309. {
  2310.     return initializer_t<value_initializer_t<value_t> >(value_initializer_t<value_t>(Value));
  2311. }
  2312.  
  2313. /// Helper class used to set a data container's name
  2314. class name_t
  2315. {
  2316. public:
  2317.     explicit name_t(const char* const Name) :
  2318.         m_name(Name)
  2319.     {
  2320.     }
  2321.  
  2322.     const char* const name() const
  2323.     {
  2324.         return m_name;
  2325.     }
  2326.  
  2327. private:
  2328.     const char* const m_name;
  2329. };
  2330.  
  2331. inline const initializer_t<name_t> init_name(const char* const Name)
  2332. {
  2333.     return initializer_t<name_t>(name_t(Name));
  2334. }
  2335.  
  2336. /// Helper class used to initialize a data container's label
  2337. class label_t
  2338. {
  2339. public:
  2340.     explicit label_t(const char* const Label) :
  2341.         m_label(Label)
  2342.     {
  2343.     }
  2344.  
  2345.     const char* const label() const
  2346.     {
  2347.         return m_label;
  2348.     }
  2349.  
  2350. private:
  2351.     const char* const m_label;
  2352. };
  2353.  
  2354. inline const initializer_t<label_t> init_label(const char* const Label)
  2355. {
  2356.     return initializer_t<label_t>(label_t(Label));
  2357. }
  2358.  
  2359. /// Helper class used to initialize a data container's description
  2360. class description_t
  2361. {
  2362. public:
  2363.     explicit description_t(const char* const Description) :
  2364.         m_description(Description)
  2365.     {
  2366.     }
  2367.  
  2368.     const char* const description() const
  2369.     {
  2370.         return m_description;
  2371.     }
  2372.  
  2373. private:
  2374.     const char* const m_description;
  2375. };
  2376.  
  2377. inline const initializer_t<description_t> init_description(const char* const Description)
  2378. {
  2379.     return initializer_t<description_t>(description_t(Description));
  2380. }
  2381.  
  2382. /// Helper class used to initialize a data container's constraints
  2383. template<typename data_t>
  2384. class constraint_t
  2385. {
  2386. public:
  2387.     explicit constraint_t(iconstraint<data_t>* Constraint) :
  2388.         m_constraint(Constraint)
  2389.     {
  2390.     }
  2391.  
  2392.     iconstraint<data_t>* constraint() const
  2393.     {
  2394.         return m_constraint;
  2395.     }
  2396.  
  2397. private:
  2398.     iconstraint<data_t>* const m_constraint;
  2399. };
  2400.  
  2401. template<typename data_t>
  2402. inline const initializer_t<constraint_t<data_t> > init_constraint(iconstraint<data_t>* Constraint)
  2403. {
  2404.     return initializer_t<constraint_t<data_t> >(constraint_t<data_t>(Constraint));
  2405. }
  2406.  
  2407. /// Helper class used to initialize the mode for path property nodes
  2408. class path_mode_t
  2409. {
  2410. public:
  2411.     explicit path_mode_t(const ipath_property::mode_t Mode) :
  2412.         m_mode(Mode)
  2413.     {
  2414.     }
  2415.  
  2416.     const ipath_property::mode_t path_mode() const
  2417.     {
  2418.         return m_mode;
  2419.     }
  2420.  
  2421. private:
  2422.     ipath_property::mode_t m_mode;
  2423. };
  2424.  
  2425. inline const initializer_t<path_mode_t> init_path_mode(const ipath_property::mode_t Mode)
  2426. {
  2427.     return initializer_t<path_mode_t>(path_mode_t(Mode));
  2428. }
  2429.  
  2430. /// Helper class used to initialize the type for path property nodes
  2431. class path_type_t
  2432. {
  2433. public:
  2434.     explicit path_type_t(const std::string& Type) :
  2435.         m_type(Type)
  2436.     {
  2437.     }
  2438.  
  2439.     const std::string& path_type() const
  2440.     {
  2441.         return m_type;
  2442.     }
  2443.  
  2444. private:
  2445.     const std::string m_type;
  2446. };
  2447.  
  2448. inline const initializer_t<path_type_t> init_path_type(const std::string& Type)
  2449. {
  2450.     return initializer_t<path_type_t>(path_type_t(Type));
  2451. }
  2452.  
  2453. /// Helper class used to initialize enumeration property types
  2454. class enumeration_t
  2455. {
  2456. public:
  2457.     explicit enumeration_t(const ienumeration_property::enumeration_values_t& Values) :
  2458.         m_values(Values)
  2459.     {
  2460.     }
  2461.  
  2462.     const ienumeration_property::enumeration_values_t& values() const
  2463.     {
  2464.         return m_values;
  2465.     }
  2466.  
  2467. private:
  2468.     const ienumeration_property::enumeration_values_t& m_values;
  2469. };
  2470.  
  2471. inline const initializer_t<enumeration_t> init_enumeration(const ienumeration_property::enumeration_values_t& Values)
  2472. {
  2473.     return initializer_t<enumeration_t>(enumeration_t(Values));
  2474. }
  2475.  
  2476. /// Helper class used to initialize list properties
  2477. template<typename data_t>
  2478. class values_t
  2479. {
  2480. public:
  2481.     explicit values_t(const data_t& Values) :
  2482.         m_values(Values)
  2483.     {
  2484.     }
  2485.  
  2486.     const data_t& values() const
  2487.     {
  2488.         return m_values;
  2489.     }
  2490.  
  2491. private:
  2492.     const data_t& m_values;
  2493. };
  2494.  
  2495. template<typename data_t>
  2496. inline const initializer_t<values_t<data_t> > init_values(const data_t& Values)
  2497. {
  2498.     return initializer_t<values_t<data_t> >(values_t<data_t>(Values));
  2499. }
  2500.  
  2501. /// Helper class used to initialize measurement properties
  2502. class step_increment_t
  2503. {
  2504. public:
  2505.     explicit step_increment_t(const double StepIncrement) :
  2506.         m_step_increment(StepIncrement)
  2507.     {
  2508.     }
  2509.  
  2510.     const double step_increment() const
  2511.     {
  2512.         return m_step_increment;
  2513.     }
  2514.  
  2515. private:
  2516.     const double m_step_increment;
  2517. };
  2518.  
  2519. inline const initializer_t<step_increment_t> init_step_increment(const double StepIncrement)
  2520. {
  2521.     return initializer_t<step_increment_t>(step_increment_t(StepIncrement));
  2522. }
  2523.  
  2524. /// Helper class used to initialize measurement properties
  2525. class units_t
  2526. {
  2527. public:
  2528.     explicit units_t(const std::type_info& Units) :
  2529.         m_units(Units)
  2530.     {
  2531.     }
  2532.  
  2533.     const std::type_info& units() const
  2534.     {
  2535.         return m_units;
  2536.     }
  2537.  
  2538. private:
  2539.     const std::type_info& m_units;
  2540. };
  2541.  
  2542. inline const initializer_t<units_t> init_units(const std::type_info& Units)
  2543. {
  2544.     return initializer_t<units_t>(units_t(Units));
  2545. }
  2546.  
  2547. /// Helper class used to initialize data containers
  2548. template<typename owner_t>
  2549. class owner_initializer_t
  2550. {
  2551. public:
  2552.     explicit owner_initializer_t(owner_t& Owner) :
  2553.         m_owner(Owner)
  2554.     {
  2555.     }
  2556.  
  2557.     owner_t& owner() const
  2558.     {
  2559.         return m_owner;
  2560.     }
  2561.  
  2562.     idocument& document() const
  2563.     {
  2564.         return m_owner.document();
  2565.     }
  2566.  
  2567.     iproperty_collection& property_collection() const
  2568.     {
  2569.         return m_owner;
  2570.     }
  2571.  
  2572.     ipersistent_collection& persistent_collection() const
  2573.     {
  2574.         return m_owner;
  2575.     }
  2576.  
  2577.     inode* node() const
  2578.     {
  2579.         return dynamic_cast<inode*>(&m_owner);
  2580.     }
  2581.  
  2582. private:
  2583.     owner_t& m_owner;
  2584. };
  2585.  
  2586. template<typename owner_t>
  2587. inline const initializer_t<owner_initializer_t<owner_t> > init_owner(owner_t& Owner)
  2588. {
  2589.     return initializer_t<owner_initializer_t<owner_t> >(owner_initializer_t<owner_t>(Owner));
  2590. }
  2591.  
  2592. /// Helper class used to initialize data containers
  2593. class external_owner_initializer_t
  2594. {
  2595. public:
  2596.     explicit external_owner_initializer_t(idocument& Document, iproperty_collection& PropertyCollection, ipersistent_collection& PersistentCollection, inode* const Node) :
  2597.         m_document(Document),
  2598.         m_property_collection(PropertyCollection),
  2599.         m_persistent_collection(PersistentCollection),
  2600.         m_node(Node)
  2601.     {
  2602.     }
  2603.  
  2604.     idocument& document() const
  2605.     {
  2606.         return m_document;
  2607.     }
  2608.  
  2609.     iproperty_collection& property_collection() const
  2610.     {
  2611.         return m_property_collection;
  2612.     }
  2613.  
  2614.     ipersistent_collection& persistent_collection() const
  2615.     {
  2616.         return m_persistent_collection;
  2617.     }
  2618.  
  2619.     inode* node() const
  2620.     {
  2621.         return m_node;
  2622.     }
  2623.  
  2624. private:
  2625.     idocument& m_document;
  2626.     iproperty_collection& m_property_collection;
  2627.     ipersistent_collection& m_persistent_collection;
  2628.     inode* const m_node;
  2629. };
  2630.  
  2631. inline const initializer_t<external_owner_initializer_t> init_owner(idocument& Document, iproperty_collection& PropertyCollection, ipersistent_collection& PersistentCollection, inode* const Object)
  2632. {
  2633.     return initializer_t<external_owner_initializer_t>(external_owner_initializer_t(Document, PropertyCollection, PersistentCollection, Object));
  2634. }
  2635.  
  2636. /// Helper class used to initialize slots
  2637. template<typename slot_t>
  2638. class slot_initializer_t
  2639. {
  2640. public:
  2641.     explicit slot_initializer_t(const slot_t& Slot) :
  2642.         m_slot(Slot)
  2643.     {
  2644.     }
  2645.  
  2646.     const slot_t& slot() const
  2647.     {
  2648.         return m_slot;
  2649.     }
  2650.  
  2651. private:
  2652.     const slot_t& m_slot;
  2653. };
  2654.  
  2655. template<typename slot_t>
  2656. inline const initializer_t<slot_initializer_t<slot_t> > init_slot(const slot_t& Slot)
  2657. {
  2658.     return initializer_t<slot_initializer_t<slot_t> >(slot_initializer_t<slot_t>(Slot));
  2659. }
  2660.  
  2661. } // namespace data
  2662.  
  2663. namespace detail
  2664. {
  2665.  
  2666. template<typename instance_t>
  2667. class instance_container :
  2668.     public istate_container,
  2669.     public sigc::trackable
  2670. {
  2671. public:
  2672.     instance_container(instance_t* const Instance, const bool Owned) :
  2673.         m_instance(Instance),
  2674.         m_owned(Owned)
  2675.     {
  2676.     }
  2677.  
  2678.     virtual ~instance_container()
  2679.     {
  2680.         if(m_owned)
  2681.             delete m_instance;
  2682.     }
  2683.  
  2684.     void restore_state()
  2685.     {
  2686.     }
  2687.  
  2688.     void on_owned(bool Owned)
  2689.     {
  2690.         m_owned = Owned;
  2691.     }
  2692.  
  2693. private:
  2694.     instance_t* const m_instance;
  2695.     bool m_owned;
  2696. };
  2697.  
  2698. } // namespace detail
  2699.  
  2700. /////////////////////////////////////////////////////////////////////////////
  2701. // undoable_new
  2702.  
  2703. /// To make creation of an object undoable / redoable, pass it to this function after calling operator new
  2704. template<typename object_t>
  2705. void undoable_new(object_t* const Object, idocument& Document)
  2706. {
  2707.     // If we aren't recording undos, we're done...
  2708.     state_change_set* const changeset = Document.state_recorder().current_change_set();
  2709.     if(!changeset)
  2710.         return;
  2711.  
  2712.     // Create an instance container that only deletes the object if it has been undone
  2713.     typedef detail::instance_container<object_t> container_t;
  2714.     container_t* const container = new container_t(Object, false);
  2715.     changeset->connect_undo_signal(sigc::bind(sigc::mem_fun(*container, &container_t::on_owned), true));
  2716.     changeset->connect_redo_signal(sigc::bind(sigc::mem_fun(*container, &container_t::on_owned), false));
  2717.  
  2718.     changeset->record_old_state(container);
  2719. }
  2720.  
  2721. /////////////////////////////////////////////////////////////////////////////
  2722. // undoable_delete
  2723.  
  2724. /// To make deletion of an object undoable / redoable, pass it to this function instead of calling operator delete
  2725. template<typename object_t>
  2726. void undoable_delete(object_t* const Object, idocument& Document)
  2727. {
  2728.     // If we aren't recording undos, delete it the old-fashioned way ...
  2729.     state_change_set* const changeset = Document.state_recorder().current_change_set();
  2730.     if(!changeset)
  2731.     {
  2732.         delete Object;
  2733.         return;
  2734.     }
  2735.  
  2736.     // Create an instance container that only deletes the object if it hasn't been undone
  2737.     typedef detail::instance_container<object_t> container_t;
  2738.     container_t* const container = new container_t(Object, true);
  2739.     changeset->connect_undo_signal(sigc::bind(sigc::mem_fun(*container, &container_t::on_owned), false));
  2740.     changeset->connect_redo_signal(sigc::bind(sigc::mem_fun(*container, &container_t::on_owned), true));
  2741.  
  2742.     changeset->record_old_state(container);
  2743. }
  2744.  
  2745. } // namespace k3d
  2746.  
  2747. using namespace k3d::data;
  2748.  
  2749. #endif // !K3DSDK_DATA_H
  2750.  
  2751.