@@ -754,7 +754,6 @@ namespace ImVue {
754754
755755 if (!success && required) {
756756 IMVUE_EXCEPTION (ElementError, " failed to read required attribute %s" , attribute);
757- return ;
758757 }
759758 }
760759
@@ -768,6 +767,93 @@ namespace ImVue {
768767 D C::* mMemPtr ;
769768 };
770769
770+ /* *
771+ * Setter implementation of attribute reader
772+ */
773+ template <class C , typename Type>
774+ class AttributeSetter : public Attribute {
775+ public:
776+
777+ typedef void (C::*SetterFunc)(Type);
778+
779+ AttributeSetter (SetterFunc func, bool required = false )
780+ : Attribute(required)
781+ , mSetter (func)
782+ {
783+ static_assert (std::is_trivially_constructible<Type>::value, " setter can only be used with trivially constructible types" );
784+ }
785+
786+ void read (const char * attribute, const char * str, Element* element, ScriptState* scriptState, int flags = 0 , ScriptState::Fields* fields = 0 ) const
787+ {
788+ Type value;
789+ bool success = false ;
790+ if (scriptState) {
791+ if (flags & SCRIPT) {
792+ Object object = scriptState->getObject (str, fields, element->getContext ());
793+ if (!object.valid ()) {
794+ IMVUE_EXCEPTION (ScriptError, " failed to evaluate data %s" , str);
795+ return ;
796+ }
797+ success = detail::read (object, &value);
798+ } else if (flags & TEMPLATED_STRING) {
799+ std::string retval;
800+ std::stringstream result;
801+ std::stringstream ss;
802+ bool evaluation = false ;
803+
804+ for (int i = 0 ;;i++) {
805+ if (str[i] == ' \0 ' ) {
806+ break ;
807+ }
808+
809+ if (evaluation && std::strncmp (&str[i], " }}" , 2 ) == 0 ) {
810+ Object object = scriptState->getObject (&ss.str ()[0 ], fields, element->getContext ());
811+ ss = std::stringstream ();
812+ evaluation = false ;
813+ result << object.as <ImString>().c_str ();
814+ i++;
815+ continue ;
816+ }
817+
818+ if (!evaluation && std::strncmp (&str[i], " {{" , 2 ) == 0 ) {
819+ evaluation = true ;
820+ i++;
821+ continue ;
822+ }
823+
824+ if (evaluation) {
825+ ss << str[i];
826+ } else {
827+ result << str[i];
828+ }
829+ }
830+
831+ success = detail::read (&result.str ()[0 ], &value);
832+ }
833+ }
834+
835+ if (!success) {
836+ success = detail::read (str, &value);
837+ }
838+
839+ if (success) {
840+ (static_cast <C*>(element)->*mSetter )(value);
841+ } else if (required) {
842+ IMVUE_EXCEPTION (ElementError, " failed to read required attribute %s" , attribute);
843+ }
844+ }
845+
846+ bool copy (Element* element, Object& dest) const
847+ {
848+ (void )element;
849+ (void )dest;
850+ return false ;
851+ }
852+
853+ private:
854+ SetterFunc mSetter ;
855+ };
856+
771857 /* *
772858 * Handler factory interface
773859 */
@@ -899,23 +985,42 @@ namespace ImVue {
899985 }
900986
901987 /* *
902- * Register attribute reader
988+ * Register attribute
903989 *
904990 * @param name attribute name
905991 * @param memPtr destination to read into (&Element::variable)
906992 * @param required property is required
907993 */
908- template <class D >
909- ElementBuilderImpl<C>& attribute (const char * name, D C::* memPtr, bool required = false )
994+ template <class Type >
995+ ElementBuilderImpl<C>& attribute (const char * name, Type C::* memPtr, bool required = false )
910996 {
911- mAttributes [name] = new AttributeMemPtr<C, D >(memPtr, required);
997+ mAttributes [name] = new AttributeMemPtr<C, Type >(memPtr, required);
912998 mAttributes [name]->owner = this ;
913999 if (required) {
9141000 mRequiredAttrs .push_back (name);
9151001 }
9161002 return *this ;
9171003 }
9181004
1005+ /* *
1006+ * Register attribute setter
1007+ *
1008+ * @param name attribute name
1009+ * @param func setter function to use (&Element::setValue)
1010+ * @param required property is required
1011+ */
1012+ template <class Type >
1013+ ElementBuilderImpl<C>& setter (const char * name, void (C::*func)(Type), bool required = false)
1014+ {
1015+ mAttributes [name] = new AttributeSetter<C, Type>(func, required);
1016+ mAttributes [name]->owner = this ;
1017+ if (required) {
1018+ mRequiredAttrs .push_back (name);
1019+ }
1020+ return *this ;
1021+ }
1022+
1023+
9191024 /* *
9201025 * Register text reader
9211026 *
0 commit comments