00001 #ifndef K3DSDK_DATA_H
00002 #define K3DSDK_DATA_H
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <k3dsdk/idocument.h>
00024 #include <k3dsdk/ienumeration_property.h>
00025 #include <k3dsdk/ihint.h>
00026 #include <k3dsdk/ilist_property.h>
00027 #include <k3dsdk/imeasurement_property.h>
00028 #include <k3dsdk/inode.h>
00029 #include <k3dsdk/inode_change_signal.h>
00030 #include <k3dsdk/inode_collection.h>
00031 #include <k3dsdk/inode_collection_property.h>
00032 #include <k3dsdk/inode_property.h>
00033 #include <k3dsdk/ipath_property.h>
00034 #include <k3dsdk/ipersistent.h>
00035 #include <k3dsdk/ipersistent_collection.h>
00036 #include <k3dsdk/ipersistent_lookup.h>
00037 #include <k3dsdk/iplugin_factory.h>
00038 #include <k3dsdk/iproperty.h>
00039 #include <k3dsdk/iproperty_collection.h>
00040 #include <k3dsdk/iscript_property.h>
00041 #include <k3dsdk/istate_container.h>
00042 #include <k3dsdk/istate_recorder.h>
00043 #include <k3dsdk/iwritable_property.h>
00044 #include <k3dsdk/nodes.h>
00045 #include <k3dsdk/result.h>
00046 #include <k3dsdk/state_change_set.h>
00047 #include <k3dsdk/xml.h>
00048
00049 #include <boost/lexical_cast.hpp>
00050 #include <boost/static_assert.hpp>
00051 #include <boost/type_traits.hpp>
00052 #include <boost/version.hpp>
00053
00054 #include <cassert>
00055 #include <string>
00056 #include <typeinfo>
00057
00058 namespace k3d
00059 {
00060
00061 namespace data
00062 {
00063
00065
00066
00068 template<typename value_t, class serialization_policy_t>
00069 class container :
00070 public serialization_policy_t
00071 {
00072 public:
00073 template<typename init_t>
00074 container(const init_t& Init) :
00075 serialization_policy_t(Init)
00076 {
00077 }
00078 };
00079
00081
00082
00084 template<typename value_t, class property_policy_t>
00085 class no_serialization :
00086 public property_policy_t
00087 {
00088 protected:
00089 template<typename init_t>
00090 no_serialization(const init_t& Init) :
00091 property_policy_t(Init)
00092 {
00093 }
00094 };
00095
00097
00098
00100 template<typename value_t, class property_policy_t>
00101 class with_serialization :
00102 public property_policy_t,
00103 public ipersistent
00104 {
00105
00106 BOOST_STATIC_ASSERT((!boost::is_pointer<value_t>::value));
00107
00108 public:
00109 void save(xml::element& Element, const ipersistent::save_context&)
00110 {
00111 Element.append(xml::element("property", string_cast(property_policy_t::internal_value()), xml::attribute("name", property_policy_t::name())));
00112 }
00113
00114 void load(xml::element& Element, const ipersistent::load_context&)
00115 {
00116 std::string value = Element.text;
00117 property_policy_t::set_value(from_string(value, property_policy_t::internal_value()));
00118 }
00119
00120 protected:
00121 template<typename init_t>
00122 with_serialization(const init_t& Init) :
00123 property_policy_t(Init)
00124 {
00125 Init.persistent_collection().enable_serialization(Init.name(), *this);
00126 }
00127 };
00128
00130
00131
00132 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);
00133 void load_external_resource(xml::element& Element, const ipersistent::load_context& Context, ipath_property::reference_t& Reference, filesystem::path& Value);
00134
00136 template<typename value_t, class property_policy_t>
00137 class path_serialization :
00138 public property_policy_t,
00139 public ipersistent
00140 {
00141
00142 BOOST_STATIC_ASSERT((!boost::is_pointer<value_t>::value));
00143
00144 public:
00145 void save(xml::element& Element, const ipersistent::save_context& Context)
00146 {
00147 save_external_resource(Element, Context, property_policy_t::name(), property_policy_t::property_path_reference(), property_policy_t::internal_value());
00148 }
00149
00150 void load(xml::element& Element, const ipersistent::load_context& Context)
00151 {
00152 ipath_property::reference_t reference;
00153 filesystem::path value;
00154
00155 load_external_resource(Element, Context, reference, value);
00156
00157 property_policy_t::set_property_path_reference(reference);
00158 property_policy_t::set_value(value);
00159 }
00160
00161 protected:
00162 template<typename init_t>
00163 path_serialization(const init_t& Init) :
00164 property_policy_t(Init)
00165 {
00166 Init.persistent_collection().enable_serialization(Init.name(), *this);
00167 }
00168 };
00169
00171
00172
00174 template<typename value_t, class property_policy_t>
00175 class node_serialization :
00176 public property_policy_t,
00177 public ipersistent
00178 {
00179
00180 BOOST_STATIC_ASSERT((boost::is_base_and_derived<iunknown, typename boost::remove_pointer<value_t>::type>::value));
00181
00182 public:
00183 void save(xml::element& Element, const ipersistent::save_context& Context)
00184 {
00185 if(property_policy_t::internal_node())
00186 Element.append(xml::element("property", string_cast(Context.lookup.lookup_id(property_policy_t::internal_node())), xml::attribute("name", property_policy_t::name())));
00187 else
00188 Element.append(xml::element("property", "0", xml::attribute("name", property_policy_t::name())));
00189 }
00190
00191 void load(xml::element& Element, const ipersistent::load_context& Context)
00192 {
00193 std::string value = Element.text;
00194 property_policy_t::set_value(dynamic_cast<value_t>(Context.lookup.lookup_object(from_string(value, static_cast<ipersistent_lookup::id_type>(0)))));
00195 }
00196
00197 protected:
00198 template<typename init_t>
00199 node_serialization(const init_t& Init) :
00200 property_policy_t(Init)
00201 {
00202 Init.persistent_collection().enable_serialization(Init.name(), *this);
00203 }
00204
00205 private:
00206 ipersistent_lookup::id_type m_node_id;
00207 };
00208
00210
00211
00213 template<typename value_t, class property_policy_t>
00214 class node_collection_serialization :
00215 public property_policy_t,
00216 public ipersistent
00217 {
00218 public:
00219 void save(xml::element& Element, const ipersistent::save_context& Context)
00220 {
00221 std::stringstream buffer;
00222
00223 const inode_collection_property::nodes_t& nodes = property_policy_t::internal_value();
00224 for(inode_collection_property::nodes_t::const_iterator node = nodes.begin(); node != nodes.end(); ++node)
00225 {
00226 if(*node)
00227 buffer << " " << string_cast(Context.lookup.lookup_id(*node));
00228 else
00229 buffer << " 0";
00230 }
00231
00232 Element.append(xml::element("property", buffer.str(), xml::attribute("name", property_policy_t::name())));
00233 }
00234
00235 void load(xml::element& Element, const ipersistent::load_context& Context)
00236 {
00237 inode_collection_property::nodes_t nodes;
00238
00239 std::stringstream buffer(Element.text);
00240 std::string node;
00241 while(buffer >> node)
00242 nodes.push_back(dynamic_cast<inode*>(Context.lookup.lookup_object(from_string(node, static_cast<ipersistent_lookup::id_type>(0)))));
00243 nodes.erase(std::remove(nodes.begin(), nodes.end(), static_cast<inode*>(0)), nodes.end());
00244
00245 property_policy_t::set_value(nodes);
00246 }
00247
00248 protected:
00249 template<typename init_t>
00250 node_collection_serialization(const init_t& Init) :
00251 property_policy_t(Init)
00252 {
00253 Init.persistent_collection().enable_serialization(Init.name(), *this);
00254 }
00255 };
00256
00258
00259
00263 iproperty* property_lookup(iproperty* const Source);
00264
00266
00267
00269 template<typename value_t, class name_policy_t>
00270 class no_property :
00271 public name_policy_t
00272 {
00273 public:
00274
00275 protected:
00276 template<typename init_t>
00277 no_property(const init_t& Init) :
00278 name_policy_t(Init)
00279 {
00280 }
00281 };
00282
00284
00285
00287 template<typename value_t, class name_policy_t>
00288 class read_only_property :
00289 public name_policy_t,
00290 public iproperty
00291 {
00292 public:
00293 const value_t pipeline_value()
00294 {
00295 iproperty* const source = property_lookup(this);
00296 if(source != this)
00297 return name_policy_t::constrain_value(boost::any_cast<value_t>(source->property_internal_value()));
00298
00299 return name_policy_t::internal_value();
00300 }
00301
00302 const std::string property_name()
00303 {
00304 return name_policy_t::name();
00305 }
00306
00307 const std::string property_label()
00308 {
00309 return m_label;
00310 }
00311
00312 const std::string property_description()
00313 {
00314 return m_description;
00315 }
00316
00317 const std::type_info& property_type()
00318 {
00319 return typeid(value_t);
00320 }
00321
00322 const boost::any property_internal_value()
00323 {
00324 return name_policy_t::internal_value();
00325 }
00326
00327 const boost::any property_pipeline_value()
00328 {
00329 return pipeline_value();
00330 }
00331
00332 inode* property_node()
00333 {
00334 return m_node;
00335 }
00336
00337 typename name_policy_t::changed_signal_t& property_changed_signal()
00338 {
00339 return name_policy_t::changed_signal();
00340 }
00341
00342 deleted_signal_t& property_deleted_signal()
00343 {
00344 return m_deleted_signal;
00345 }
00346
00347 iproperty* property_dependency()
00348 {
00349 return m_dependency;
00350 }
00351
00352 void property_set_dependency(iproperty* Dependency)
00353 {
00354 m_dependency = Dependency;
00355 }
00356
00357 protected:
00358 template<typename init_t>
00359 read_only_property(const init_t& Init) :
00360 name_policy_t(Init),
00361 m_node(Init.node()),
00362 m_label(Init.label()),
00363 m_description(Init.description()),
00364 m_dependency(0)
00365 {
00366 Init.property_collection().register_property(*this);
00367 }
00368
00369 ~read_only_property()
00370 {
00371 m_deleted_signal.emit();
00372 }
00373
00374 private:
00375 inode* const m_node;
00376 const char* const m_label;
00377 const char* const m_description;
00378 deleted_signal_t m_deleted_signal;
00379 iproperty* m_dependency;
00380 };
00381
00383
00384
00386 template<typename value_t, class name_policy_t>
00387 class writable_property :
00388 public name_policy_t,
00389 public iproperty,
00390 public iwritable_property
00391 {
00392 public:
00393 const value_t pipeline_value()
00394 {
00395 iproperty* const source = property_lookup(this);
00396 if(source != this)
00397 return name_policy_t::constrain_value(boost::any_cast<value_t>(source->property_internal_value()));
00398
00399 return name_policy_t::internal_value();
00400 }
00401
00402 const std::string property_name()
00403 {
00404 return name_policy_t::name();
00405 }
00406
00407 const std::string property_label()
00408 {
00409 return m_label;
00410 }
00411
00412 const std::string property_description()
00413 {
00414 return m_description;
00415 }
00416
00417 const std::type_info& property_type()
00418 {
00419 return typeid(value_t);
00420 }
00421
00422 const boost::any property_internal_value()
00423 {
00424 return name_policy_t::internal_value();
00425 }
00426
00427 const boost::any property_pipeline_value()
00428 {
00429 return pipeline_value();
00430 }
00431
00432 inode* property_node()
00433 {
00434 return m_node;
00435 }
00436
00437 typename name_policy_t::changed_signal_t& property_changed_signal()
00438 {
00439 return name_policy_t::changed_signal();
00440 }
00441
00442 deleted_signal_t& property_deleted_signal()
00443 {
00444 return m_deleted_signal;
00445 }
00446
00447 bool property_set_value(const boost::any Value, ihint* const Hint)
00448 {
00449 const value_t* const new_value = boost::any_cast<value_t>(&Value);
00450 if(!new_value)
00451 return false;
00452
00453 name_policy_t::set_value(*new_value, Hint);
00454 return true;
00455 }
00456
00457 iproperty* property_dependency()
00458 {
00459 return m_dependency;
00460 }
00461
00462 void property_set_dependency(iproperty* Dependency)
00463 {
00464 m_dependency = Dependency;
00465 }
00466
00467 protected:
00468 template<typename init_t>
00469 writable_property(const init_t& Init) :
00470 name_policy_t(Init),
00471 m_node(Init.node()),
00472 m_label(Init.label()),
00473 m_description(Init.description()),
00474 m_dependency(0)
00475 {
00476 Init.property_collection().register_property(*this);
00477 }
00478
00479 ~writable_property()
00480 {
00481 m_deleted_signal.emit();
00482 }
00483
00484 private:
00485 inode* const m_node;
00486 const char* const m_label;
00487 const char* const m_description;
00488 deleted_signal_t m_deleted_signal;
00489 iproperty* m_dependency;
00490 };
00491
00493
00494
00496 template<typename value_t, class name_policy_t>
00497 class string_property :
00498 public name_policy_t,
00499 public iproperty,
00500 public iwritable_property
00501 {
00502 public:
00503 const value_t pipeline_value()
00504 {
00505 iproperty* const source = property_lookup(this);
00506 if(source != this)
00507 return name_policy_t::constrain_value(boost::any_cast<value_t>(source->property_internal_value()));
00508
00509 return name_policy_t::internal_value();
00510 }
00511
00512 const std::string property_name()
00513 {
00514 return name_policy_t::name();
00515 }
00516
00517 const std::string property_label()
00518 {
00519 return m_label;
00520 }
00521
00522 const std::string property_description()
00523 {
00524 return m_description;
00525 }
00526
00527 const std::type_info& property_type()
00528 {
00529 return typeid(std::string);
00530 }
00531
00532 const boost::any property_internal_value()
00533 {
00534 try
00535 {
00536 return boost::any(boost::lexical_cast<std::string>(name_policy_t::internal_value()));
00537 }
00538 catch(...)
00539 {
00540 }
00541
00542 return boost::any();
00543 }
00544
00545 const boost::any property_pipeline_value()
00546 {
00547 return pipeline_value();
00548 }
00549
00550 inode* property_node()
00551 {
00552 return m_node;
00553 }
00554
00555 typename name_policy_t::changed_signal_t& property_changed_signal()
00556 {
00557 return name_policy_t::changed_signal();
00558 }
00559
00560 deleted_signal_t& property_deleted_signal()
00561 {
00562 return m_deleted_signal;
00563 }
00564
00565 iproperty* property_dependency()
00566 {
00567 return m_dependency;
00568 }
00569
00570 void property_set_dependency(iproperty* Dependency)
00571 {
00572 m_dependency = Dependency;
00573 }
00574
00575 bool property_set_value(const boost::any Value, ihint* const Hint)
00576 {
00577 const std::string* const new_value = boost::any_cast<std::string>(&Value);
00578 if(!new_value)
00579 return false;
00580
00581 try
00582 {
00583 set_value(boost::lexical_cast<value_t>(*new_value), Hint);
00584 return true;
00585 }
00586 catch(...)
00587 {
00588 }
00589
00590 return false;
00591 }
00592
00593 protected:
00594 template<typename init_t>
00595 string_property(const init_t& Init) :
00596 name_policy_t(Init),
00597 m_node(Init.node()),
00598 m_label(Init.label()),
00599 m_description(Init.description()),
00600 m_dependency(0)
00601 {
00602 Init.property_collection().register_property(*this);
00603 }
00604
00605 ~string_property()
00606 {
00607 m_deleted_signal.emit();
00608 }
00609
00610 private:
00611 inode* const m_node;
00612 const char* const m_label;
00613 const char* const m_description;
00614 deleted_signal_t m_deleted_signal;
00615 iproperty* m_dependency;
00616 };
00617
00619
00620
00622 template<typename value_t, class name_policy_t>
00623 class path_property :
00624 public name_policy_t,
00625 public iproperty,
00626 public iwritable_property,
00627 public ipath_property
00628 {
00629 public:
00630 const value_t pipeline_value()
00631 {
00632 iproperty* const source = property_lookup(this);
00633 if(source != this)
00634 return name_policy_t::constrain_value(boost::any_cast<value_t>(source->property_internal_value()));
00635
00636 return name_policy_t::internal_value();
00637 }
00638
00639 const std::string property_name()
00640 {
00641 return name_policy_t::name();
00642 }
00643
00644 const std::string property_label()
00645 {
00646 return m_label;
00647 }
00648
00649 const std::string property_description()
00650 {
00651 return m_description;
00652 }
00653
00654 const std::type_info& property_type()
00655 {
00656 return typeid(value_t);
00657 }
00658
00659 const boost::any property_internal_value()
00660 {
00661 return name_policy_t::internal_value();
00662 }
00663
00664 const boost::any property_pipeline_value()
00665 {
00666 return pipeline_value();
00667 }
00668
00669 inode* property_node()
00670 {
00671 return m_node;
00672 }
00673
00674 typename name_policy_t::changed_signal_t& property_changed_signal()
00675 {
00676 return name_policy_t::changed_signal();
00677 }
00678
00679 deleted_signal_t& property_deleted_signal()
00680 {
00681 return m_deleted_signal;
00682 }
00683
00684 iproperty* property_dependency()
00685 {
00686 return m_dependency;
00687 }
00688
00689 void property_set_dependency(iproperty* Dependency)
00690 {
00691 m_dependency = Dependency;
00692 }
00693
00694 bool property_set_value(const boost::any Value, ihint* const Hint)
00695 {
00696 const value_t* const new_value = boost::any_cast<value_t>(&Value);
00697 if(!new_value)
00698 return false;
00699 name_policy_t::set_value(*new_value, Hint);
00700 return true;
00701 }
00702
00703 ipath_property::mode_t property_path_mode()
00704 {
00705 return m_mode;
00706 }
00707
00708 const std::string property_path_type()
00709 {
00710 return m_type;
00711 }
00712
00713 ipath_property::reference_t property_path_reference()
00714 {
00715 return m_reference;
00716 }
00717
00718 void set_property_path_reference(const ipath_property::reference_t Reference)
00719 {
00720 if(Reference != m_reference)
00721 {
00722 m_reference = Reference;
00723 m_reference_changed_signal.emit();
00724 }
00725 }
00726
00727 ipath_property::path_reference_changed_signal_t& property_path_reference_changed_signal()
00728
00729 {
00730 return m_reference_changed_signal;
00731 }
00732
00733 const ipath_property::pattern_filters_t pattern_filters()
00734 {
00735 return m_pattern_filters;
00736 }
00737
00738 void add_pattern_filter(const ipath_property::pattern_filter& PatternFilter)
00739 {
00740 m_pattern_filters.push_back(PatternFilter);
00741 }
00742
00743 protected:
00744 template<typename init_t>
00745 path_property(const init_t& Init) :
00746 name_policy_t(Init),
00747 m_node(Init.node()),
00748 m_label(Init.label()),
00749 m_description(Init.description()),
00750 m_mode(Init.path_mode()),
00751 m_type(Init.path_type()),
00752 m_reference(RELATIVE_REFERENCE),
00753 m_dependency(0)
00754 {
00755 Init.property_collection().register_property(*this);
00756 }
00757
00758 ~path_property()
00759 {
00760 m_deleted_signal.emit();
00761 }
00762
00763 private:
00764 inode* const m_node;
00765 const char* const m_label;
00766 const char* const m_description;
00767 deleted_signal_t m_deleted_signal;
00768 const ipath_property::mode_t m_mode;
00769 const std::string m_type;
00770 ipath_property::reference_t m_reference;
00771 ipath_property::path_reference_changed_signal_t m_reference_changed_signal;
00772 ipath_property::pattern_filters_t m_pattern_filters;
00773 iproperty* m_dependency;
00774 };
00775
00777
00778
00780 template<typename value_t, class name_policy_t>
00781 class script_property :
00782 public name_policy_t,
00783 public iproperty,
00784 public iwritable_property,
00785 public iscript_property
00786 {
00787 public:
00788 const value_t pipeline_value()
00789 {
00790 iproperty* const source = property_lookup(this);
00791 if(source != this)
00792 return name_policy_t::constrain_value(boost::any_cast<value_t>(source->property_internal_value()));
00793
00794 return name_policy_t::internal_value();
00795 }
00796
00797 const std::string property_name()
00798 {
00799 return name_policy_t::name();
00800 }
00801
00802 const std::string property_label()
00803 {
00804 return m_label;
00805 }
00806
00807 const std::string property_description()
00808 {
00809 return m_description;
00810 }
00811
00812 const std::type_info& property_type()
00813 {
00814 return typeid(std::string);
00815 }
00816
00817 const boost::any property_internal_value()
00818 {
00819 try
00820 {
00821 return boost::any(boost::lexical_cast<std::string>(name_policy_t::internal_value()));
00822 }
00823 catch(...)
00824 {
00825 }
00826
00827 return boost::any();
00828 }
00829
00830 const boost::any property_pipeline_value()
00831 {
00832 return pipeline_value();
00833 }
00834
00835 inode* property_node()
00836 {
00837 return m_node;
00838 }
00839
00840 typename name_policy_t::changed_signal_t& property_changed_signal()
00841 {
00842 return name_policy_t::changed_signal();
00843 }
00844
00845 deleted_signal_t& property_deleted_signal()
00846 {
00847 return m_deleted_signal;
00848 }
00849
00850 iproperty* property_dependency()
00851 {
00852 return m_dependency;
00853 }
00854
00855 void property_set_dependency(iproperty* Dependency)
00856 {
00857 m_dependency = Dependency;
00858 }
00859
00860 bool property_set_value(const boost::any Value, ihint* const Hint)
00861 {
00862 const std::string* const new_value = boost::any_cast<std::string>(&Value);
00863 if(!new_value)
00864 return false;
00865
00866 try
00867 {
00868 set_value(boost::lexical_cast<value_t>(*new_value), Hint);
00869 return true;
00870 }
00871 catch(...)
00872 {
00873 }
00874
00875 return false;
00876 }
00877
00878 protected:
00879 template<typename init_t>
00880 script_property(const init_t& Init) :
00881 name_policy_t(Init),
00882 m_node(Init.node()),
00883 m_label(Init.label()),
00884 m_description(Init.description()),
00885 m_dependency(0)
00886 {
00887 Init.property_collection().register_property(*this);
00888 }
00889
00890 ~script_property()
00891 {
00892 m_deleted_signal.emit();
00893 }
00894
00895 private:
00896 inode* const m_node;
00897 const char* const m_label;
00898 const char* const m_description;
00899 deleted_signal_t m_deleted_signal;
00900 iproperty* m_dependency;
00901 };
00902
00904
00905
00907 template<typename value_t, class name_policy_t>
00908 class enumeration_property :
00909 public name_policy_t,
00910 public iproperty,
00911 public iwritable_property,
00912 public ienumeration_property
00913 {
00914 public:
00915 const value_t pipeline_value()
00916 {
00917 iproperty* const source = property_lookup(this);
00918 if(source != this)
00919 {
00920 try
00921 {
00922
00923
00924 return name_policy_t::constrain_value(boost::lexical_cast<value_t>(boost::any_cast<string_t>(source->property_internal_value())));
00925 }
00926 catch(...)
00927 {
00928 return name_policy_t::internal_value();
00929 }
00930 }
00931
00932 return name_policy_t::internal_value();
00933 }
00934
00935 const string_t property_name()
00936 {
00937 return name_policy_t::name();
00938 }
00939
00940 const string_t property_label()
00941 {
00942 return m_label;
00943 }
00944
00945 const string_t property_description()
00946 {
00947 return m_description;
00948 }
00949
00950 const std::type_info& property_type()
00951 {
00952 return typeid(string_t);
00953 }
00954
00955 const boost::any property_internal_value()
00956 {
00957 try
00958 {
00959 return boost::any(boost::lexical_cast<string_t>(name_policy_t::internal_value()));
00960 }
00961 catch(...)
00962 {
00963 }
00964
00965 return boost::any();
00966 }
00967
00968 const boost::any property_pipeline_value()
00969 {
00970 try
00971 {
00972 return boost::any(boost::lexical_cast<string_t>(pipeline_value()));
00973 }
00974 catch(...)
00975 {
00976 }
00977
00978 return boost::any();
00979 }
00980
00981 inode* property_node()
00982 {
00983 return m_node;
00984 }
00985
00986 typename name_policy_t::changed_signal_t& property_changed_signal()
00987 {
00988 return name_policy_t::changed_signal();
00989 }
00990
00991 deleted_signal_t& property_deleted_signal()
00992 {
00993 return m_deleted_signal;
00994 }
00995
00996 iproperty* property_dependency()
00997 {
00998 return m_dependency;
00999 }
01000
01001 void property_set_dependency(iproperty* Dependency)
01002 {
01003 m_dependency = Dependency;
01004 }
01005
01006 bool property_set_value(const boost::any Value, ihint* const Hint)
01007 {
01008 const string_t* const new_value = boost::any_cast<string_t>(&Value);
01009 if(!new_value)
01010 return false;
01011
01012 try
01013 {
01014 set_value(boost::lexical_cast<value_t>(*new_value), Hint);
01015 return true;
01016 }
01017 catch(...)
01018 {
01019 }
01020
01021 return false;
01022 }
01023
01024 enumeration_values_t enumeration_values()
01025 {
01026 return m_values;
01027 }
01028
01029 sigc::connection connect_enumeration_values_changed(const sigc::slot<void>& Slot)
01030 {
01031 return m_values_changed_signal.connect(Slot);
01032 }
01033
01034 void notify_enumeration_values_changed()
01035 {
01036 m_values_changed_signal.emit();
01037 }
01038
01039 protected:
01040 template<typename init_t>
01041 enumeration_property(const init_t& Init) :
01042 name_policy_t(Init),
01043 m_node(Init.node()),
01044 m_label(Init.label()),
01045 m_description(Init.description()),
01046 m_values(Init.values()),
01047 m_dependency(0)
01048 {
01049 Init.property_collection().register_property(*this);
01050 }
01051
01052 ~enumeration_property()
01053 {
01054 m_deleted_signal.emit();
01055 }
01056
01057 private:
01058 inode* const m_node;
01059 const char* const m_label;
01060 const char* const m_description;
01061 const ienumeration_property::enumeration_values_t& m_values;
01062 sigc::signal<void> m_values_changed_signal;
01063 deleted_signal_t m_deleted_signal;
01064 iproperty* m_dependency;
01065 };
01066
01068
01069
01071 template<typename value_t, class name_policy_t>
01072 class list_property :
01073 public name_policy_t,
01074 public iproperty,
01075 public iwritable_property,
01076 public ilist_property<value_t>
01077 {
01078 public:
01079 const value_t pipeline_value()
01080 {
01081 iproperty* const source = property_lookup(this);
01082 if(source != this)
01083 return name_policy_t::constrain_value(boost::any_cast<value_t>(source->property_internal_value()));
01084
01085 return name_policy_t::internal_value();
01086 }
01087
01088 const std::string property_name()
01089 {
01090 return name_policy_t::name();
01091 }
01092
01093 const std::string property_label()
01094 {
01095 return m_label;
01096 }
01097
01098 const std::string property_description()
01099 {
01100 return m_description;
01101 }
01102
01103 const std::type_info& property_type()
01104 {
01105 return typeid(value_t);
01106 }
01107
01108 const boost::any property_internal_value()
01109 {
01110 return boost::any(name_policy_t::internal_value());
01111 }
01112
01113 const boost::any property_pipeline_value()
01114 {
01115 return pipeline_value();
01116 }
01117
01118 inode* property_node()
01119 {
01120 return m_node;
01121 }
01122
01123 typename name_policy_t::changed_signal_t& property_changed_signal()
01124 {
01125 return name_policy_t::changed_signal();
01126 }
01127
01128 deleted_signal_t& property_deleted_signal()
01129 {
01130 return m_deleted_signal;
01131 }
01132
01133 iproperty* property_dependency()
01134 {
01135 return m_dependency;
01136 }
01137
01138 void property_set_dependency(iproperty* Dependency)
01139 {
01140 m_dependency = Dependency;
01141 }
01142
01143 bool property_set_value(const boost::any Value, ihint* const Hint)
01144 {
01145 const value_t* const new_value = boost::any_cast<value_t>(&Value);
01146 if(!new_value)
01147 return false;
01148
01149 set_value(*new_value, Hint);
01150 return true;
01151 }
01152
01153 typename ilist_property<value_t>::values_t property_values()
01154 {
01155 return m_values;
01156 }
01157
01158 protected:
01159 template<typename init_t>
01160 list_property(const init_t& Init) :
01161 name_policy_t(Init),
01162 m_node(Init.node()),
01163 m_label(Init.label()),
01164 m_description(Init.description()),
01165 m_values(Init.values()),
01166 m_dependency(0)
01167 {
01168 Init.property_collection().register_property(*this);
01169 }
01170
01171 ~list_property()
01172 {
01173 m_deleted_signal.emit();
01174 }
01175
01176 private:
01177 inode* const m_node;
01178 const char* const m_label;
01179 const char* const m_description;
01180 const typename ilist_property<value_t>::values_t& m_values;
01181 deleted_signal_t m_deleted_signal;
01182 iproperty* m_dependency;
01183 };
01184
01186
01187
01189 template<typename value_t, class name_policy_t>
01190 class node_property :
01191 public name_policy_t,
01192 public iproperty,
01193 public iwritable_property,
01194 public inode_property
01195 {
01196 public:
01197 const value_t pipeline_value()
01198 {
01199 iproperty* const source = property_lookup(this);
01200 if(source != this)
01201 return name_policy_t::constrain_value(dynamic_cast<value_t>(boost::any_cast<inode*>(source->property_internal_value())));
01202
01203 return name_policy_t::internal_value();
01204 }
01205
01206 const std::string property_name()
01207 {
01208 return name_policy_t::name();
01209 }
01210
01211 const std::string property_label()
01212 {
01213 return m_label;
01214 }
01215
01216 const std::string property_description()
01217 {
01218 return m_description;
01219 }
01220
01221 const std::type_info& property_type()
01222 {
01223 return typeid(inode*);
01224 }
01225
01226 const boost::any property_internal_value()
01227 {
01228 return boost::any(name_policy_t::internal_node());
01229 }
01230
01231 const boost::any property_pipeline_value()
01232 {
01233 return dynamic_cast<inode*>(pipeline_value());
01234 }
01235
01236 inode* property_node()
01237 {
01238 return m_node;
01239 }
01240
01241 typename name_policy_t::changed_signal_t& property_changed_signal()
01242 {
01243 return name_policy_t::changed_signal();
01244 }
01245
01246 deleted_signal_t& property_deleted_signal()
01247 {
01248 return m_deleted_signal;
01249 }
01250
01251 iproperty* property_dependency()
01252 {
01253 return m_dependency;
01254 }
01255
01256 void property_set_dependency(iproperty* Dependency)
01257 {
01258 m_dependency = Dependency;
01259 }
01260
01261 bool property_set_value(const boost::any Value, ihint* const Hint)
01262 {
01263 inode* const * new_value = boost::any_cast<inode*>(&Value);
01264 if(!new_value)
01265 return false;
01266
01267 name_policy_t::set_value(dynamic_cast<value_t>(*new_value), Hint);
01268 return true;
01269 }
01270
01271 bool property_allow_none()
01272 {
01273 return name_policy_t::allow_none();
01274 }
01275
01276 bool property_allow(iplugin_factory& Factory)
01277 {
01278 return name_policy_t::allow(Factory);
01279 }
01280
01281 bool property_allow(inode& Object)
01282 {
01283 return name_policy_t::allow(Object);
01284 }
01285
01286 protected:
01287 template<typename init_t>
01288 node_property(const init_t& Init) :
01289 name_policy_t(Init),
01290 m_node(Init.node()),
01291 m_label(Init.label()),
01292 m_description(Init.description()),
01293 m_dependency(0)
01294 {
01295 Init.property_collection().register_property(*this);
01296 }
01297
01298 ~node_property()
01299 {
01300 m_deleted_signal.emit();
01301 }
01302
01303 private:
01304 inode* const m_node;
01305 const char* const m_label;
01306 const char* const m_description;
01307 deleted_signal_t m_deleted_signal;
01308 iproperty* m_dependency;
01309 };
01310
01312
01313
01315 template<typename value_t, class name_policy_t>
01316 class measurement_property :
01317 public name_policy_t,
01318 public iproperty,
01319 public iwritable_property,
01320 public imeasurement_property
01321 {
01322 public:
01323 const value_t pipeline_value()
01324 {
01325 iproperty* const source = property_lookup(this);
01326 if(source != this)
01327 return name_policy_t::constrain_value(boost::any_cast<value_t>(source->property_internal_value()));
01328
01329 return name_policy_t::internal_value();
01330 }
01331
01332 const std::string property_name()
01333 {
01334 return name_policy_t::name();
01335 }
01336
01337 const std::string property_label()
01338 {
01339 return m_label;
01340 }
01341
01342 const std::string property_description()
01343 {
01344 return m_description;
01345 }
01346
01347 const std::type_info& property_type()
01348 {
01349 return typeid(value_t);
01350 }
01351
01352 const boost::any property_internal_value()
01353 {
01354 return boost::any(name_policy_t::internal_value());
01355 }
01356
01357 const boost::any property_pipeline_value()
01358 {
01359 return pipeline_value();
01360 }
01361
01362 inode* property_node()
01363 {
01364 return m_node;
01365 }
01366
01367 typename name_policy_t::changed_signal_t& property_changed_signal()
01368 {
01369 return name_policy_t::changed_signal();
01370 }
01371
01372 deleted_signal_t& property_deleted_signal()
01373 {
01374 return m_deleted_signal;
01375 }
01376
01377 iproperty* property_dependency()
01378 {
01379 return m_dependency;
01380 }
01381
01382 void property_set_dependency(iproperty* Dependency)
01383 {
01384 m_dependency = Dependency;
01385 }
01386
01387 bool property_set_value(const boost::any Value, ihint* const Hint)
01388 {
01389 const value_t* const new_value = boost::any_cast<value_t>(&Value);
01390 if(!new_value)
01391 return false;
01392
01393 name_policy_t::set_value(*new_value, Hint);
01394 return true;
01395 }
01396
01397 double property_step_increment()
01398 {
01399 return m_step_increment;
01400 }
01401
01402 const std::type_info& property_units()
01403 {
01404 return m_units;
01405 }
01406
01407 protected:
01408 template<typename init_t>
01409 measurement_property(const init_t& Init) :
01410 name_policy_t(Init),
01411 m_node(Init.node()),
01412 m_label(Init.label()),
01413 m_description(Init.description()),
01414 m_step_increment(Init.step_increment()),
01415 m_units(Init.units()),
01416 m_dependency(0)
01417 {
01418 Init.property_collection().register_property(*this);
01419 }
01420
01421 ~measurement_property()
01422 {
01423 m_deleted_signal.emit();
01424 }
01425
01426 private:
01427 inode* const m_node;
01428 const char* const m_label;
01429 const char* const m_description;
01430 const double m_step_increment;
01431 const std::type_info& m_units;
01432 deleted_signal_t m_deleted_signal;
01433 iproperty* m_dependency;
01434 };
01435
01437
01438
01440 template<class constraint_policy_t>
01441 class no_name :
01442 public constraint_policy_t
01443 {
01444 protected:
01445 template<typename init_t>
01446 no_name(const init_t& Init) :
01447 constraint_policy_t(Init)
01448 {
01449 }
01450 };
01451
01453
01454
01456 template<class constraint_policy_t>
01457 class immutable_name :
01458 public constraint_policy_t
01459 {
01460 public:
01462 const std::string name() const
01463 {
01464 return m_name;
01465 }
01466
01467 protected:
01468 template<typename init_t>
01469 immutable_name(const init_t& Init) :
01470 constraint_policy_t(Init),
01471 m_name(Init.name())
01472 {
01473 }
01474
01475 private:
01477 const char* const m_name;
01478 };
01479
01481
01482
01484 template<typename value_t, class undo_policy_t>
01485 class no_constraint :
01486 public undo_policy_t
01487 {
01488 public:
01489 void set_value(const value_t& Value, ihint* const Hint = 0)
01490 {
01491 if(Value != undo_policy_t::internal_value())
01492 undo_policy_t::set_value(Value, Hint);
01493 }
01494
01495 const value_t constrain_value(const value_t Value)
01496 {
01497 return Value;
01498 }
01499
01500 protected:
01501 template<typename init_t>
01502 no_constraint(const init_t& Init) :
01503 undo_policy_t(Init)
01504 {
01505 }
01506 };
01507
01509
01510
01512 template<typename value_t>
01513 class iconstraint
01514 {
01515 public:
01516 virtual ~iconstraint() {}
01517
01518 void constrain(value_t& Value)
01519 {
01520 on_constrain(Value);
01521
01522 if(m_next_constraint.get())
01523 m_next_constraint->constrain(Value);
01524 }
01525
01526 protected:
01527 explicit iconstraint(iconstraint<value_t>* NextConstraint) :
01528 m_next_constraint(NextConstraint)
01529 {
01530 }
01531
01532 private:
01534 virtual void on_constrain(value_t& Value) = 0;
01535
01537 const std::auto_ptr<iconstraint<value_t> > m_next_constraint;
01538 };
01539
01540 namespace constraint
01541 {
01542
01544
01545
01547 template<typename value_t>
01548 class minimum_t :
01549 public iconstraint<value_t>
01550 {
01551
01552
01553
01554
01555 BOOST_STATIC_ASSERT((std::numeric_limits<value_t>::is_signed));
01556
01557 public:
01558 minimum_t(const value_t MinimumValue, iconstraint<value_t>* NextConstraint = 0) :
01559 iconstraint<value_t>(NextConstraint),
01560 m_minimum_value(MinimumValue)
01561 {
01562 }
01563
01564 private:
01565 void on_constrain(value_t& Value)
01566 {
01567 Value = std::max(Value, m_minimum_value);
01568 }
01569
01570 const value_t m_minimum_value;
01571 };
01572
01574
01575
01577 template<typename value_t>
01578 iconstraint<value_t>* minimum(const value_t MinimumValue, iconstraint<value_t>* NextConstraint = 0)
01579 {
01580 return new minimum_t<value_t>(MinimumValue, NextConstraint);
01581 }
01582
01584
01585
01587 template<typename value_t>
01588 class maximum_t :
01589 public iconstraint<value_t>
01590 {
01591 public:
01592 maximum_t(const value_t MaximumValue, iconstraint<value_t>* NextConstraint = 0) :
01593 iconstraint<value_t>(NextConstraint),
01594 m_maximum_value(MaximumValue)
01595 {
01596 }
01597
01598 private:
01599 void on_constrain(value_t& Value)
01600 {
01601 Value = std::min(Value, m_maximum_value);
01602 }
01603
01604 const value_t m_maximum_value;
01605 };
01606
01608
01609
01611 template<typename value_t>
01612 iconstraint<value_t>* maximum(const value_t MaximumValue, iconstraint<value_t>* NextConstraint = 0)
01613 {
01614 return new maximum_t<value_t>(MaximumValue, NextConstraint);
01615 }
01616
01617 }
01618
01620
01621
01623 template<typename value_t, class undo_policy_t>
01624 class with_constraint :
01625 public undo_policy_t
01626 {
01627 public:
01628 void set_value(value_t Value, ihint* const Hint = 0)
01629 {
01630 m_constraint->constrain(Value);
01631
01632 if(Value != undo_policy_t::internal_value())
01633 undo_policy_t::set_value(Value, Hint);
01634 }
01635
01636 const value_t constrain_value(value_t Value)
01637 {
01638 m_constraint->constrain(Value);
01639 return Value;
01640 }
01641
01642 protected:
01643 template<typename init_t>
01644 with_constraint(const init_t& Init) :
01645 undo_policy_t(Init),
01646 m_constraint(Init.constraint())
01647 {
01648 assert(m_constraint.get());
01649 }
01650
01651 private:
01653 const std::auto_ptr<iconstraint<value_t> > m_constraint;
01654 };
01655
01657
01658
01660 template<typename value_t, class storage_policy_t>
01661 class no_undo :
01662 public storage_policy_t
01663 {
01664 protected:
01665 template<typename init_t>
01666 no_undo(const init_t& Init) :
01667 storage_policy_t(Init)
01668 {
01669 }
01670
01672 void internal_set_value(const value_t& Value, ihint* const Hint)
01673 {
01674 set_value(Value, Hint);
01675 }
01676 };
01677
01679
01680
01682 template <typename value_t, class storage_policy_t>
01683 class with_undo :
01684 public storage_policy_t,
01685 public virtual sigc::trackable
01686 {
01687 public:
01689 bool ready_to_record()
01690 {
01691 return !m_changes && m_state_recorder.current_change_set();
01692 }
01693
01695 istate_recorder& state_recorder()
01696 {
01697 return m_state_recorder;
01698 }
01699
01700 protected:
01701 template<typename init_t>
01702 with_undo(const init_t& Init) :
01703 storage_policy_t(Init),
01704 m_state_recorder(Init.document().state_recorder()),
01705 m_changes(false)
01706 {
01707 }
01708
01709 typedef with_undo<value_t, storage_policy_t> this_t;
01710
01712 void internal_set_value(const value_t& Value, ihint* const Hint)
01713 {
01714 set_value(Value, Hint);
01715 }
01716
01717 void set_value(const value_t& Value, ihint* const Hint = 0)
01718 {
01719 if(ready_to_record())
01720 {
01721 m_changes = true;
01723 m_state_recorder.connect_recording_done_signal(sigc::mem_fun(*this, &this_t::on_recording_done));
01724 storage_policy_t::start_recording(m_state_recorder);
01725 }
01726
01727 storage_policy_t::set_value(Value, Hint);
01728 }
01729
01730 private:
01732 void on_recording_done()
01733 {
01734
01735 assert(m_changes);
01736 assert(m_state_recorder.current_change_set());
01737
01738 m_changes = false;
01739 storage_policy_t::finish_recording(m_state_recorder);
01740 }
01741
01743 istate_recorder& m_state_recorder;
01745 bool m_changes;
01746 };
01747
01749
01750
01752 template<typename value_t, class signal_policy_t>
01753 class local_storage :
01754 public signal_policy_t
01755 {
01756 public:
01758 value_t& internal_value()
01759 {
01760 return m_value;
01761 }
01762
01764 const value_t& internal_value() const
01765 {
01766 return m_value;
01767 }
01768
01769 protected:
01770 template<typename init_t>
01771 local_storage(const init_t& Init) :
01772 signal_policy_t(Init),
01773 m_value(Init.value())
01774 {
01775 }
01776
01778 void start_recording(istate_recorder& StateRecorder)
01779 {
01780 signal_policy_t::start_recording(StateRecorder);
01781 StateRecorder.current_change_set()->record_old_state(new value_container(m_value));
01782 }
01783
01785 void set_value(const value_t& Value, ihint* const Hint = 0)
01786 {
01787 m_value = Value;
01788 signal_policy_t::set_value(Hint);
01789 }
01790
01792 void finish_recording(istate_recorder& StateRecorder)
01793 {
01794 StateRecorder.current_change_set()->record_new_state(new value_container(m_value));
01795 signal_policy_t::finish_recording(StateRecorder);
01796 }
01797
01798 private:
01800 value_t m_value;
01801
01803 class value_container :
01804 public istate_container
01805 {
01806 public:
01807 value_container(value_t& Instance) :
01808 m_instance(Instance),
01809 m_value(Instance)
01810 {
01811 }
01812
01813 void restore_state()
01814 {
01815 m_instance = m_value;
01816 }
01817
01818 private:
01819 value_t& m_instance;
01820 const value_t m_value;
01821 };
01822 };
01823
01825
01826
01828 template<typename value_t, class signal_policy_t>
01829 class node_storage :
01830 public signal_policy_t,
01831 public virtual sigc::trackable
01832 {
01833 public:
01835 value_t internal_value()
01836 {
01837 return dynamic_cast<value_t>(m_node);
01838 }
01839
01841 inode* internal_node()
01842 {
01843 return m_node;
01844 }
01845
01847 bool allow_none()
01848 {
01849 return true;
01850 }
01851
01853 bool allow(iplugin_factory& Factory)
01854 {
01855 return Factory.implements(typeid(typename boost::remove_pointer<value_t>::type));
01856 }
01857
01859 bool allow(inode& Object)
01860 {
01861 return dynamic_cast<value_t>(&Object) ? true : false;
01862 }
01863
01864 protected:
01865 template<typename init_t>
01866 node_storage(const init_t& Init) :
01867 signal_policy_t(Init),
01868 m_node(dynamic_cast<inode*>(Init.value()))
01869 {
01870 if(m_node)
01871 {
01872 m_node_deleted_connection = m_node->deleted_signal().connect(sigc::mem_fun(*this, &node_storage::on_node_deleted));
01873 if(inode_change_signal* const node_change_signal = dynamic_cast<inode_change_signal*>(m_node))
01874 m_node_changed_connection = node_change_signal->connect_node_changed_signal(signal_policy_t::changed_signal().make_slot());
01875 }
01876 }
01877
01878 virtual ~node_storage()
01879 {
01880 }
01881
01882 void on_node_deleted()
01883 {
01884 internal_set_value(0, 0);
01885 }
01886
01888 void start_recording(istate_recorder& StateRecorder)
01889 {
01890 signal_policy_t::start_recording(StateRecorder);
01891 StateRecorder.current_change_set()->record_old_state(new value_container(m_node));
01892 }
01893
01895 void set_value(value_t Value, ihint* const Hint)
01896 {
01897 if(m_node)
01898 {
01899 m_node_deleted_connection.disconnect();
01900 m_node_changed_connection.disconnect();
01901 }
01902
01903 m_node = dynamic_cast<inode*>(Value);
01904
01905 if(m_node)
01906 {
01907 m_node_deleted_connection = m_node->deleted_signal().connect(sigc::mem_fun(*this, &node_storage::on_node_deleted));
01908 if(inode_change_signal* const node_change_signal = dynamic_cast<inode_change_signal*>(m_node))
01909 m_node_changed_connection = node_change_signal->connect_node_changed_signal(signal_policy_t::changed_signal().make_slot());
01910 }
01911
01912 signal_policy_t::set_value(Hint);
01913 }
01914
01916 void finish_recording(istate_recorder& StateRecorder)
01917 {
01918 StateRecorder.current_change_set()->record_new_state(new value_container(m_node));
01919 signal_policy_t::finish_recording(StateRecorder);
01920 }
01921
01922 private:
01924 virtual void internal_set_value(const value_t&, ihint* const)
01925 {
01926 }
01927
01929 inode* m_node;
01930 sigc::connection m_node_deleted_connection;
01931 sigc::connection m_node_changed_connection;
01932
01934 class value_container :
01935 public istate_container
01936 {
01937 public:
01938 value_container(inode*& Instance) :
01939 m_instance(Instance),
01940 m_value(Instance)
01941 {
01942 }
01943
01944 void restore_state()
01945 {
01946 m_instance = m_value;
01947 }
01948
01949 private:
01950 inode*& m_instance;
01951 inode* m_value;
01952 };
01953 };
01954
01956
01957
01959
01960 template<typename pointer_t, typename signal_policy_t>
01961 class pointer_storage :
01962 public signal_policy_t
01963 {
01964
01965 BOOST_STATIC_ASSERT((boost::is_pointer<pointer_t>::value));
01966
01967 public:
01968 typedef typename boost::remove_pointer<pointer_t>::type non_pointer_t;
01969 typedef pointer_storage<pointer_t, signal_policy_t> this_t;
01970
01972 void set_initialize_slot(const sigc::slot<void, non_pointer_t&>& Slot)
01973 {
01974 m_initialize_slot = Slot;
01975 reset();
01976 }
01977
01979 void set_update_slot(const sigc::slot<void, non_pointer_t&>& Slot)
01980 {
01981 m_update_slot = Slot;
01982 update();
01983 }
01984
01986 sigc::slot<void, ihint*> make_reset_slot()
01987 {
01988 return sigc::bind<0>(sigc::mem_fun(*this, &this_t::reset), static_cast<pointer_t>(0));
01989 }
01990
01992 sigc::slot<void, ihint*> make_update_slot()
01993 {
01994 return sigc::mem_fun(*this, &this_t::update);
01995 }
01996
01998 void reset(pointer_t NewValue = 0, ihint* const Hint = 0)
01999 {
02000
02001 if(m_executing)
02002 return;
02003
02004 m_value.reset(NewValue);
02005 signal_policy_t::set_value(Hint);
02006 }
02007
02009 void update(ihint* const Hint = 0)
02010 {
02011
02012 if(m_executing)
02013 return;
02014
02015 m_update = true;
02016 signal_policy_t::set_value(Hint);
02017 }
02018
02020 pointer_t internal_value()
02021 {
02022 if(!m_value.get())
02023 {
02024 m_executing = true;
02025
02026
02027 m_update = false;
02028
02029
02030
02031 m_value.reset(new non_pointer_t());
02032 m_initialize_slot(*m_value);
02033
02034 m_executing = false;
02035 }
02036
02037 if(m_update)
02038 {
02039 m_executing = true;
02040
02041 m_update = false;
02042 m_update_slot(*m_value);
02043
02044 m_executing = false;
02045 }
02046
02047 return m_value.get();
02048 }
02049
02050 protected:
02051 template<typename init_t>
02052 pointer_storage(const init_t& Init) :
02053 signal_policy_t(Init),
02054 m_update(false),
02055 m_executing(false)
02056 {
02057 }
02058
02059 private:
02061 std::auto_ptr<non_pointer_t> m_value;
02063 bool m_update;
02065 sigc::slot<void, non_pointer_t&> m_initialize_slot;
02067 sigc::slot<void, non_pointer_t&> m_update_slot;
02069 bool m_executing;
02070 };
02071
02073
02074
02076 template<typename value_t>
02077 class no_signal
02078 {
02079 protected:
02080 template<typename init_t>
02081 no_signal(const init_t&)
02082 {
02083 }
02084
02085 void start_recording(istate_recorder&)
02086 {
02087 }
02088
02089 void set_value(ihint* const)
02090 {
02091 }
02092
02093 void finish_recording(istate_recorder&)
02094 {
02095 }
02096 };
02097
02099
02100
02102 template<typename value_t>
02103 class change_signal
02104 {
02105 public:
02107 typedef sigc::signal<void, ihint*> changed_signal_t;
02108
02110 changed_signal_t& changed_signal()
02111 {
02112 return m_changed_signal;
02113 }
02114
02115 protected:
02116 template<typename init_t>
02117 change_signal(const init_t&)
02118 {
02119 }
02120
02121 void start_recording(istate_recorder&)
02122 {
02123 }
02124
02125 void set_value(ihint* const Hint)
02126 {
02127 m_changed_signal.emit(Hint);
02128 }
02129
02130 void finish_recording(istate_recorder& StateRecorder)
02131 {
02132 StateRecorder.current_change_set()->connect_undo_signal(sigc::bind(m_changed_signal.make_slot(), static_cast<ihint*>(0)));
02133 StateRecorder.current_change_set()->connect_redo_signal(sigc::bind(m_changed_signal.make_slot(), static_cast<ihint*>(0)));
02134 }
02135
02136 private:
02137 changed_signal_t m_changed_signal;
02138 };
02139
02141 template<typename value_t>
02142 class explicit_change_signal
02143 {
02144 public:
02146 typedef sigc::signal<void, k3d::ihint*> changed_signal_t;
02147
02149 changed_signal_t& changed_signal()
02150 {
02151 return m_changed_signal;
02152 }
02153
02155 const sigc::connection connect_explicit_change_signal(const sigc::slot<void, k3d::ihint*>& Slot)
02156 {
02157 return m_explicit_change_signal.connect(Slot);
02158 }
02159
02160 protected:
02161 template<typename init_t>
02162 explicit_change_signal(const init_t&)
02163 {
02164 }
02165
02166 void start_recording(k3d::istate_recorder&)
02167 {
02168 }
02169
02170 void set_value(k3d::ihint* const Hint)
02171 {
02172 m_changed_signal.emit(Hint);
02173 m_explicit_change_signal.emit(Hint);
02174 }
02175
02176 void finish_recording(k3d::istate_recorder& StateRecorder)
02177 {
02178 StateRecorder.current_change_set()->connect_undo_signal(sigc::bind(m_changed_signal.make_slot(), static_cast<k3d::ihint*>(0)));
02179 StateRecorder.current_change_set()->connect_redo_signal(sigc::bind(m_changed_signal.make_slot(), static_cast<k3d::ihint*>(0)));
02180 }
02181
02182 private:
02183 changed_signal_t m_changed_signal;
02184 changed_signal_t m_explicit_change_signal;
02185 };
02186
02188 #define k3d_data(value_type, name_policy, signal_policy, undo_policy, storage_policy, constraint_policy, property_policy, serialization_policy) \
02189 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> > > > > > > >
02190
02192 template<class init_t>
02193 class initializer_t :
02194 public init_t
02195 {
02196 public:
02197 explicit initializer_t(const init_t& Init) :
02198 init_t(Init)
02199 {
02200 };
02201 };
02202
02204 template<typename lhs_t, typename rhs_t>
02205 class composition_t :
02206 public lhs_t,
02207 public rhs_t
02208 {
02209 public:
02210 explicit composition_t(const lhs_t& LHS, const rhs_t& RHS) :
02211 lhs_t(LHS),
02212 rhs_t(RHS)
02213 {
02214 }
02215 };
02216
02218 template<typename lhs_t, typename rhs_t>
02219 inline const initializer_t<composition_t<lhs_t, rhs_t> > operator+(const initializer_t<lhs_t>& LHS, const initializer_t<rhs_t>& RHS)
02220 {
02221 return initializer_t<composition_t<lhs_t, rhs_t> >(composition_t<lhs_t, rhs_t>(LHS, RHS));
02222 }
02223
02225 template<typename value_t>
02226 class value_initializer_t
02227 {
02228 public:
02229 explicit value_initializer_t(const value_t& Value) :
02230 m_value(Value)
02231 {
02232 }
02233
02234 const value_t& value() const
02235 {
02236 return m_value;
02237 }
02238
02239 private:
02240 const value_t m_value;
02241 };
02242
02243 template<typename value_t>
02244 inline const initializer_t<value_initializer_t<value_t> > init_value(const value_t& Value)
02245 {
02246 return initializer_t<value_initializer_t<value_t> >(value_initializer_t<value_t>(Value));
02247 }
02248
02250 class name_t
02251 {
02252 public:
02253 explicit name_t(const char* const Name) :
02254 m_name(Name)
02255 {
02256 }
02257
02258 const char* name() const
02259 {
02260 return m_name;
02261 }
02262
02263 private:
02264 const char* const m_name;
02265 };
02266
02267 inline const initializer_t<name_t> init_name(const char* const Name)
02268 {
02269 return initializer_t<name_t>(name_t(Name));
02270 }
02271
02273 class label_t
02274 {
02275 public:
02276 explicit label_t(const char* const Label) :
02277 m_label(Label)
02278 {
02279 }
02280
02281 const char* label() const
02282 {
02283 return m_label;
02284 }
02285
02286 private:
02287 const char* const m_label;
02288 };
02289
02290 inline const initializer_t<label_t> init_label(const char* const Label)
02291 {
02292 return initializer_t<label_t>(label_t(Label));
02293 }
02294
02296 class description_t
02297 {
02298 public:
02299 explicit description_t(const char* const Description) :
02300 m_description(Description)
02301 {
02302 }
02303
02304 const char* description() const
02305 {
02306 return m_description;
02307 }
02308
02309 private:
02310 const char* const m_description;
02311 };
02312
02313 inline const initializer_t<description_t> init_description(const char* const Description)
02314 {
02315 return initializer_t<description_t>(description_t(Description));
02316 }
02317
02319 template<typename data_t>
02320 class constraint_t
02321 {
02322 public:
02323 explicit constraint_t(iconstraint<data_t>* Constraint) :
02324 m_constraint(Constraint)
02325 {
02326 }
02327
02328 iconstraint<data_t>* constraint() const
02329 {
02330 return m_constraint;
02331 }
02332
02333 private:
02334 iconstraint<data_t>* const m_constraint;
02335 };
02336
02337 template<typename data_t>
02338 inline const initializer_t<constraint_t<data_t> > init_constraint(iconstraint<data_t>* Constraint)
02339 {
02340 return initializer_t<constraint_t<data_t> >(constraint_t<data_t>(Constraint));
02341 }
02342
02344 class path_mode_t
02345 {
02346 public:
02347 explicit path_mode_t(const ipath_property::mode_t Mode) :
02348 m_mode(Mode)
02349 {
02350 }
02351
02352 ipath_property::mode_t path_mode() const
02353 {
02354 return m_mode;
02355 }
02356
02357 private:
02358 ipath_property::mode_t m_mode;
02359 };
02360
02361 inline const initializer_t<path_mode_t> init_path_mode(const ipath_property::mode_t Mode)
02362 {
02363 return initializer_t<path_mode_t>(path_mode_t(Mode));
02364 }
02365
02367 class path_type_t
02368 {
02369 public:
02370 explicit path_type_t(const std::string& Type) :
02371 m_type(Type)
02372 {
02373 }
02374
02375 const std::string& path_type() const
02376 {
02377 return m_type;
02378 }
02379
02380 private:
02381 const std::string m_type;
02382 };
02383
02384 inline const initializer_t<path_type_t> init_path_type(const std::string& Type)
02385 {
02386 return initializer_t<path_type_t>(path_type_t(Type));
02387 }
02388
02390 class enumeration_t
02391 {
02392 public:
02393 explicit enumeration_t(const ienumeration_property::enumeration_values_t& Values) :
02394 m_values(Values)
02395 {
02396 }
02397
02398 const ienumeration_property::enumeration_values_t& values() const
02399 {
02400 return m_values;
02401 }
02402
02403 private:
02404 const ienumeration_property::enumeration_values_t& m_values;
02405 };
02406
02407 inline const initializer_t<enumeration_t> init_enumeration(const ienumeration_property::enumeration_values_t& Values)
02408 {
02409 return initializer_t<enumeration_t>(enumeration_t(Values));
02410 }
02411
02413 template<typename data_t>
02414 class values_t
02415 {
02416 public:
02417 explicit values_t(const data_t& Values) :
02418 m_values(Values)
02419 {
02420 }
02421
02422 const data_t& values() const
02423 {
02424 return m_values;
02425 }
02426
02427 private:
02428 const data_t& m_values;
02429 };
02430
02431 template<typename data_t>
02432 inline const initializer_t<values_t<data_t> > init_values(const data_t& Values)
02433 {
02434 return initializer_t<values_t<data_t> >(values_t<data_t>(Values));
02435 }
02436
02438 class step_increment_t
02439 {
02440 public:
02441 explicit step_increment_t(const double StepIncrement) :
02442 m_step_increment(StepIncrement)
02443 {
02444 }
02445
02446 double step_increment() const
02447 {
02448 return m_step_increment;
02449 }
02450
02451 private:
02452 const double m_step_increment;
02453 };
02454
02455 inline const initializer_t<step_increment_t> init_step_increment(const double StepIncrement)
02456 {
02457 return initializer_t<step_increment_t>(step_increment_t(StepIncrement));
02458 }
02459
02461 class units_t
02462 {
02463 public:
02464 explicit units_t(const std::type_info& Units) :
02465 m_units(Units)
02466 {
02467 }
02468
02469 const std::type_info& units() const
02470 {
02471 return m_units;
02472 }
02473
02474 private:
02475 const std::type_info& m_units;
02476 };
02477
02478 inline const initializer_t<units_t> init_units(const std::type_info& Units)
02479 {
02480 return initializer_t<units_t>(units_t(Units));
02481 }
02482
02484 template<typename owner_t>
02485 class owner_initializer_t
02486 {
02487 public:
02488 explicit owner_initializer_t(owner_t& Owner) :
02489 m_owner(Owner)
02490 {
02491 }
02492
02493 owner_t& owner() const
02494 {
02495 return m_owner;
02496 }
02497
02498 idocument& document() const
02499 {
02500 return m_owner.document();
02501 }
02502
02503 iproperty_collection& property_collection() const
02504 {
02505 return m_owner;
02506 }
02507
02508 ipersistent_collection& persistent_collection() const
02509 {
02510 return m_owner;
02511 }
02512
02513 inode* node() const
02514 {
02515 return dynamic_cast<inode*>(&m_owner);
02516 }
02517
02518 private:
02519 owner_t& m_owner;
02520 };
02521
02522 template<typename owner_t>
02523 inline const initializer_t<owner_initializer_t<owner_t> > init_owner(owner_t& Owner)
02524 {
02525 return initializer_t<owner_initializer_t<owner_t> >(owner_initializer_t<owner_t>(Owner));
02526 }
02527
02529 class external_owner_initializer_t
02530 {
02531 public:
02532 explicit external_owner_initializer_t(idocument& Document, iproperty_collection& PropertyCollection, ipersistent_collection& PersistentCollection, inode* const Node) :
02533 m_document(Document),
02534 m_property_collection(PropertyCollection),
02535 m_persistent_collection(PersistentCollection),
02536 m_node(Node)
02537 {
02538 }
02539
02540 idocument& document() const
02541 {
02542 return m_document;
02543 }
02544
02545 iproperty_collection& property_collection() const
02546 {
02547 return m_property_collection;
02548 }
02549
02550 ipersistent_collection& persistent_collection() const
02551 {
02552 return m_persistent_collection;
02553 }
02554
02555 inode* node() const
02556 {
02557 return m_node;
02558 }
02559
02560 private:
02561 idocument& m_document;
02562 iproperty_collection& m_property_collection;
02563 ipersistent_collection& m_persistent_collection;
02564 inode* const m_node;
02565 };
02566
02567 inline const initializer_t<external_owner_initializer_t> init_owner(idocument& Document, iproperty_collection& PropertyCollection, ipersistent_collection& PersistentCollection, inode* const Object)
02568 {
02569 return initializer_t<external_owner_initializer_t>(external_owner_initializer_t(Document, PropertyCollection, PersistentCollection, Object));
02570 }
02571
02573 template<typename slot_t>
02574 class slot_initializer_t
02575 {
02576 public:
02577 explicit slot_initializer_t(const slot_t& Slot) :
02578 m_slot(Slot)
02579 {
02580 }
02581
02582 const slot_t& slot() const
02583 {
02584 return m_slot;
02585 }
02586
02587 private:
02588 const slot_t& m_slot;
02589 };
02590
02591 template<typename slot_t>
02592 inline const initializer_t<slot_initializer_t<slot_t> > init_slot(const slot_t& Slot)
02593 {
02594 return initializer_t<slot_initializer_t<slot_t> >(slot_initializer_t<slot_t>(Slot));
02595 }
02596
02597 }
02598
02599 namespace detail
02600 {
02601
02602 template<typename instance_t>
02603 class instance_container :
02604 public istate_container,
02605 public sigc::trackable
02606 {
02607 public:
02608 instance_container(instance_t* const Instance, const bool Owned) :
02609 m_instance(Instance),
02610 m_owned(Owned)
02611 {
02612 }
02613
02614 virtual ~instance_container()
02615 {
02616 if(m_owned)
02617 delete m_instance;
02618 }
02619
02620 void restore_state()
02621 {
02622 }
02623
02624 void on_owned(bool Owned)
02625 {
02626 m_owned = Owned;
02627 }
02628
02629 private:
02630 instance_t* const m_instance;
02631 bool m_owned;
02632 };
02633
02634 }
02635
02637
02638
02640 template<typename object_t>
02641 void undoable_new(object_t* const Object, idocument& Document)
02642 {
02643
02644 state_change_set* const changeset = Document.state_recorder().current_change_set();
02645 if(!changeset)
02646 return;
02647
02648
02649 typedef detail::instance_container<object_t> container_t;
02650 container_t* const container = new container_t(Object, false);
02651 changeset->connect_undo_signal(sigc::bind(sigc::mem_fun(*container, &container_t::on_owned), true));
02652 changeset->connect_redo_signal(sigc::bind(sigc::mem_fun(*container, &container_t::on_owned), false));
02653
02654 changeset->record_old_state(container);
02655 }
02656
02658
02659
02661 template<typename object_t>
02662 void undoable_delete(object_t* const Object, idocument& Document)
02663 {
02664
02665 state_change_set* const changeset = Document.state_recorder().current_change_set();
02666 if(!changeset)
02667 {
02668 delete Object;
02669 return;
02670 }
02671
02672
02673 typedef detail::instance_container<object_t> container_t;
02674 container_t* const container = new container_t(Object, true);
02675 changeset->connect_undo_signal(sigc::bind(sigc::mem_fun(*container, &container_t::on_owned), false));
02676 changeset->connect_redo_signal(sigc::bind(sigc::mem_fun(*container, &container_t::on_owned), true));
02677
02678 changeset->record_old_state(container);
02679 }
02680
02681 }
02682
02683 using namespace k3d::data;
02684
02685 #endif // !K3DSDK_DATA_H
02686