X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fbuilder%2Fbuilder-impl.cpp;h=ca264ab7e988b7e25b79e1477e67ebaa1f96825d;hp=d16c64ffb895f3d351f271c19212a05ba3e2f070;hb=36a298758d1b6244b7846a0102b528d76002dbda;hpb=3f11de583ac51192f62df16e5125b28519ab3242 diff --git a/dali-toolkit/internal/builder/builder-impl.cpp b/dali-toolkit/internal/builder/builder-impl.cpp index d16c64f..ca264ab 100644 --- a/dali-toolkit/internal/builder/builder-impl.cpp +++ b/dali-toolkit/internal/builder/builder-impl.cpp @@ -1,31 +1,40 @@ -// -// Copyright (c) 2014 Samsung Electronics Co., Ltd. -// -// Licensed under the Flora License, Version 1.0 (the License); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://floralicense.org/license/ -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an AS IS BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ // CLASS HEADER #include // EXTERNAL INCLUDES #include - -// INTERNAL INCLUDES -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +// INTERNAL INCLUDES #include -#include +#include #include #include @@ -42,15 +51,14 @@ namespace Internal { class Replacement; -extern Animation CreateAnimation(const TreeNode& child, const Replacement& replacements, const Dali::Actor searchRoot ); +extern Animation CreateAnimation(const TreeNode& child, const Replacement& replacements, const Dali::Actor searchRoot, Builder* const builder ); extern bool SetPropertyFromNode( const TreeNode& node, Property::Value& value ); extern bool SetPropertyFromNode( const TreeNode& node, Property::Value& value, const Replacement& replacements ); extern bool SetPropertyFromNode( const TreeNode& node, Property::Type type, Property::Value& value ); extern bool SetPropertyFromNode( const TreeNode& node, Property::Type type, Property::Value& value, const Replacement& replacements ); -extern Actor SetupSignalAction(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor); -extern Actor SetupPropertyNotification(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor); -extern Actor SetupActor( const TreeNode& node, Actor& actor ); -extern Control SetupControl( const TreeNode& node, Control& actor ); +extern Actor SetupSignalAction(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, Dali::Toolkit::Internal::Builder* const builder); +extern Actor SetupPropertyNotification(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, Dali::Toolkit::Internal::Builder* const builder); +extern Actor SetupActor( const TreeNode& node, Actor& actor, const Replacement& constant ); #if defined(DEBUG_ENABLED) Integration::Log::Filter* gFilterScript = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_SCRIPT"); @@ -85,6 +93,7 @@ std::string ToString(const Rect& value) return ss.str(); } +#if defined(DEBUG_ENABLED) std::string PropertyValueToString( const Property::Value& value ) { @@ -159,12 +168,12 @@ std::string PropertyValueToString( const Property::Value& value ) } case Property::ARRAY: { - ret = std::string("Array Size=") + ToString( value.Get().size() ); + ret = std::string("Array Size=") + ToString( value.Get().Size() ); break; } case Property::MAP: { - ret = std::string("Map Size=") + ToString( value.Get().size() ); + ret = std::string("Map Size=") + ToString( value.Get().Count() ); break; } case Property::TYPE_COUNT: @@ -176,6 +185,7 @@ std::string PropertyValueToString( const Property::Value& value ) return ret; } +#endif // DEBUG_ENABLED /* * Recursively collects all stylesin a node (An array of style names). @@ -207,6 +217,7 @@ void CollectAllStyles( const TreeNode& stylesCollection, const TreeNode& style, } } + } // namespace anon /* @@ -222,7 +233,7 @@ void Builder::SetProperties( const TreeNode& node, Handle& handle, const Replace std::string key( keyChild.first ); - // ignore special fields; type,actors,signals + // ignore special fields; type,actors,signals,styles if(key == KEYNAME_TYPE || key == KEYNAME_ACTORS || key == KEYNAME_SIGNALS || key == KEYNAME_STYLES) { continue; @@ -252,12 +263,15 @@ void Builder::SetProperties( const TreeNode& node, Handle& handle, const Replace // special field 'effect' references the shader effect instances if(key == "effect") { - Actor actor = Actor::DownCast(handle); - OptionalString s = constant.IsString( keyChild.second ); - if(actor && s) + RenderableActor actor = RenderableActor::DownCast(handle); + if( actor ) { - ShaderEffect e = GetShaderEffect(*s, constant); - actor.SetShaderEffect(e); + OptionalString str = constant.IsString( keyChild.second ); + if( str ) + { + ShaderEffect effect = GetShaderEffect( *str, constant ); + actor.SetShaderEffect(effect); + } } else { @@ -269,11 +283,11 @@ void Builder::SetProperties( const TreeNode& node, Handle& handle, const Replace Handle propertyObject( handle ); - Property::Index index = propertyObject.GetPropertyIndex( key ); + Dali::Property::Index index = propertyObject.GetPropertyIndex( key ); if( Property::INVALID_INDEX == index ) { - Actor actor = Actor::DownCast(propertyObject); + RenderableActor actor = RenderableActor::DownCast(handle); if( actor ) { if( ShaderEffect effect = actor.GetShaderEffect() ) @@ -328,19 +342,11 @@ void Builder::ApplyProperties( const TreeNode& root, const TreeNode& node, if( actor ) { - SetupActor( node, actor ); - - Control control = Control::DownCast(actor); - - if( control ) - { - SetupControl( node, control ); - } + SetupActor( node, actor, constant ); // add signals - SetupSignalAction( mSlotDelegate.GetConnectionTracker(), root, node, actor ); - - SetupPropertyNotification( mSlotDelegate.GetConnectionTracker(), root, node, actor ); + SetupSignalAction( mSlotDelegate.GetConnectionTracker(), root, node, actor, this ); + SetupPropertyNotification( mSlotDelegate.GetConnectionTracker(), root, node, actor, this ); } } else @@ -472,7 +478,6 @@ BaseHandle Builder::DoCreate( const TreeNode& root, const TreeNode& node, baseHandle = typeInfo.CreateInstance(); Handle handle = Handle::DownCast(baseHandle); Actor actor = Actor::DownCast(handle); - Control control = Control::DownCast(handle); if(handle) { @@ -491,6 +496,7 @@ BaseHandle Builder::DoCreate( const TreeNode& root, const TreeNode& node, DALI_SCRIPT_VERBOSE(" Is Actor id=%d\n", actor.GetId()); } + Toolkit::Control control = Toolkit::Control::DownCast(handle); if(control) { DALI_SCRIPT_VERBOSE(" Is Control id=%d\n", actor.GetId()); @@ -510,9 +516,7 @@ BaseHandle Builder::DoCreate( const TreeNode& root, const TreeNode& node, } } - ApplyProperties( root, node, handle, replacements ); - - if( actor) + if( actor ) { // add children of all the styles if( OptionalChild actors = IsChild( node, KEYNAME_ACTORS ) ) @@ -532,7 +536,10 @@ BaseHandle Builder::DoCreate( const TreeNode& root, const TreeNode& node, parent.Add( actor ); } } - + else + { + ApplyProperties( root, node, handle, replacements ); + } } else { @@ -543,19 +550,6 @@ BaseHandle Builder::DoCreate( const TreeNode& root, const TreeNode& node, return baseHandle; } - -ActorContainer Builder::GetTopLevelActors() const -{ - // deprecated function. - return ActorContainer(); -} - -Animation Builder::GetAnimation( const std::string &name ) const -{ - // deprecated - return Animation(); -} - void Builder::SetupTask( RenderTask& task, const TreeNode& node, const Replacement& constant ) { const Stage& stage = Stage::GetCurrent(); @@ -727,11 +721,12 @@ FrameBufferImage Builder::GetFrameBufferImage( const std::string &name, const Re { if( OptionalChild image = IsChild( *images, name ) ) { - Dali::Property::Value propertyMap(Property::MAP); - if( SetPropertyFromNode( *image, Property::MAP, propertyMap, constant ) ) + Dali::Property::Value property(Property::MAP); + if( SetPropertyFromNode( *image, Property::MAP, property, constant ) ) { - propertyMap.SetValue(KEYNAME_TYPE, Property::Value(std::string("FrameBufferImage"))); - ret = Dali::Scripting::NewImage( propertyMap ); + Property::Map* map = property.GetMap(); + (*map)[ KEYNAME_TYPE ] = Property::Value(std::string("FrameBufferImage") ); + ret = FrameBufferImage::DownCast( Dali::Scripting::NewImage( property ) ); mFrameBufferImageLut[ name ] = ret; } } @@ -741,29 +736,283 @@ FrameBufferImage Builder::GetFrameBufferImage( const std::string &name, const Re return ret; } -Font Builder::GetFont( const std::string& name ) const +Path Builder::GetPath( const std::string& name ) { - // deprecated function. - Font font; - return font; + DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded"); + + Path ret; + + PathLut::const_iterator iter( mPathLut.find( name ) ); + if( iter != mPathLut.end() ) + { + ret = iter->second; + } + else + { + if( OptionalChild paths = IsChild( *mParser.GetRoot(), "paths") ) + { + if( OptionalChild path = IsChild( *paths, name ) ) + { + //points property + if( OptionalChild pointsProperty = IsChild( *path, "points") ) + { + Dali::Property::Value points(Property::ARRAY); + if( SetPropertyFromNode( *pointsProperty, Property::ARRAY, points ) ) + { + ret = Path::New(); + ret.SetProperty( Path::Property::POINTS, points); + + //control-points property + if( OptionalChild pointsProperty = IsChild( *path, "control-points") ) + { + Dali::Property::Value points(Property::ARRAY); + if( SetPropertyFromNode( *pointsProperty, Property::ARRAY, points ) ) + { + ret.SetProperty( Path::Property::CONTROL_POINTS, points); + } + } + else + { + //Curvature + float curvature(0.25f); + if( OptionalFloat pointsProperty = IsFloat( *path, "curvature") ) + { + curvature = *pointsProperty; + } + ret.GenerateControlPoints(curvature); + } + + //Add the new path to the hash table for paths + mPathLut[ name ] = ret; + } + } + else + { + //Interpolation points not specified + DALI_SCRIPT_WARNING("Interpolation points not specified for path '%s'\n", name.c_str() ); + } + } + + } + } + + return ret; } -TextStyle Builder::GetTextStyle( const std::string& name ) const +PathConstrainer Builder::GetPathConstrainer( const std::string& name ) { - // deprecated - return TextStyle(); + DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded"); + + //Search the pathConstrainer in the LUT + size_t count( mPathConstrainerLut.size() ); + for( size_t i(0); i!=count; ++i ) + { + if( mPathConstrainerLut[i].name == name ) + { + //PathConstrainer has already been created + return mPathConstrainerLut[i].pathConstrainer; + } + } + + //Create a new PathConstrainer + PathConstrainer ret; + if( OptionalChild constrainers = IsChild( *mParser.GetRoot(), "constrainers") ) + { + if( OptionalChild pathConstrainer = IsChild( *constrainers, name ) ) + { + OptionalString constrainerType(IsString(IsChild(*pathConstrainer, "type"))); + if(!constrainerType) + { + DALI_SCRIPT_WARNING("Constrainer type not specified for constrainer '%s'\n", name.c_str() ); + } + else if( *constrainerType == "PathConstrainer") + { + //points property + if( OptionalChild pointsProperty = IsChild( *pathConstrainer, "points") ) + { + Dali::Property::Value points(Property::ARRAY); + if( SetPropertyFromNode( *pointsProperty, Property::ARRAY, points ) ) + { + ret = PathConstrainer::New(); + ret.SetProperty( PathConstrainer::Property::POINTS, points); + + //control-points property + if( OptionalChild pointsProperty = IsChild( *pathConstrainer, "control-points") ) + { + Dali::Property::Value points(Property::ARRAY); + if( SetPropertyFromNode( *pointsProperty, Property::ARRAY, points ) ) + { + ret.SetProperty( PathConstrainer::Property::CONTROL_POINTS, points); + } + + //Forward vector + OptionalVector3 forward( IsVector3( IsChild(*pathConstrainer, "forward" ) ) ); + if( forward ) + { + ret.SetProperty( PathConstrainer::Property::FORWARD, *forward); + } + + //Add the new constrainer to the vector of PathConstrainer + PathConstrainerEntry entry = {name,ret}; + mPathConstrainerLut.push_back( entry ); + } + else + { + //Control points not specified + DALI_SCRIPT_WARNING("Control points not specified for pathConstrainer '%s'\n", name.c_str() ); + } + } + } + else + { + //Interpolation points not specified + DALI_SCRIPT_WARNING("Interpolation points not specified for pathConstrainer '%s'\n", name.c_str() ); + } + } + else + { + DALI_SCRIPT_WARNING("Constrainer '%s' is not a PathConstrainer\n", name.c_str() ); + } + } + } + + return ret; } -Image Builder::GetImage( const std::string& name) const +bool Builder::IsPathConstrainer( const std::string& name ) { - // deprecated function. - return Image(); + size_t count( mPathConstrainerLut.size() ); + for( size_t i(0); i!=count; ++i ) + { + if( mPathConstrainerLut[i].name == name ) + { + return true; + } + } + + if( OptionalChild constrainers = IsChild( *mParser.GetRoot(), "constrainers") ) + { + if( OptionalChild constrainer = IsChild( *constrainers, name ) ) + { + OptionalString constrainerType(IsString(IsChild(*constrainer, "type"))); + if(!constrainerType) + { + return false; + } + else + { + return *constrainerType == "PathConstrainer"; + } + } + } + return false; } -Actor Builder::GetActor( const std::string &name ) const +Dali::LinearConstrainer Builder::GetLinearConstrainer( const std::string& name ) { - // deprecated function. - return Actor(); + DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded"); + + //Search the LinearConstrainer in the LUT + size_t count( mLinearConstrainerLut.size() ); + for( size_t i(0); i!=count; ++i ) + { + if( mLinearConstrainerLut[i].name == name ) + { + //LinearConstrainer has already been created + return mLinearConstrainerLut[i].linearConstrainer; + } + } + + //Create a new LinearConstrainer + LinearConstrainer ret; + if( OptionalChild constrainers = IsChild( *mParser.GetRoot(), "constrainers") ) + { + if( OptionalChild linearConstrainer = IsChild( *constrainers, name ) ) + { + OptionalString constrainerType(IsString(IsChild(*linearConstrainer, "type"))); + if(!constrainerType) + { + DALI_SCRIPT_WARNING("Constrainer type not specified for constrainer '%s'\n", name.c_str() ); + } + else if( *constrainerType == "LinearConstrainer") + { + //points property + if( OptionalChild pointsProperty = IsChild( *linearConstrainer, "value") ) + { + Dali::Property::Value points(Property::ARRAY); + if( SetPropertyFromNode( *pointsProperty, Property::ARRAY, points ) ) + { + ret = Dali::LinearConstrainer::New(); + ret.SetProperty( LinearConstrainer::Property::VALUE, points); + + //control-points property + if( OptionalChild pointsProperty = IsChild( *linearConstrainer, "progress") ) + { + Dali::Property::Value points(Property::ARRAY); + if( SetPropertyFromNode( *pointsProperty, Property::ARRAY, points ) ) + { + ret.SetProperty( LinearConstrainer::Property::PROGRESS, points); + } + } + //Add the new constrainer to vector of LinearConstrainer + LinearConstrainerEntry entry = {name,ret}; + mLinearConstrainerLut.push_back( entry ); + } + } + else + { + //Interpolation points not specified + DALI_SCRIPT_WARNING("Values not specified for LinearConstrainer '%s'\n", name.c_str() ); + } + } + else + { + DALI_SCRIPT_WARNING("Constrainer '%s' is not a LinearConstrainer\n", name.c_str() ); + } + } + } + + return ret; +} + +bool Builder::IsLinearConstrainer( const std::string& name ) +{ + //Search the LinearConstrainer in the LUT + size_t count( mLinearConstrainerLut.size() ); + for( size_t i(0); i!=count; ++i ) + { + if( mLinearConstrainerLut[i].name == name ) + { + return true; + } + } + + if( OptionalChild constrainers = IsChild( *mParser.GetRoot(), "constrainers") ) + { + if( OptionalChild constrainer = IsChild( *constrainers, name ) ) + { + OptionalString constrainerType(IsString(IsChild(*constrainer, "type"))); + if(!constrainerType) + { + return false; + } + else + { + return *constrainerType == "LinearConstrainer"; + } + } + } + return false; +} + +Toolkit::Builder::BuilderSignalType& Builder::QuitSignal() +{ + return mQuitSignal; +} + +void Builder::EmitQuitSignal() +{ + mQuitSignal.Emit(); } void Builder::AddActors( Actor toActor ) @@ -776,7 +1025,7 @@ void Builder::AddActors( const std::string §ionName, Actor toActor ) { DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded"); - PropertyValueMap overrideMap; + Property::Map overrideMap; Replacement replacements(overrideMap, mReplacementMap); OptionalChild add = IsChild(*mParser.GetRoot(), sectionName); @@ -819,7 +1068,7 @@ Animation Builder::CreateAnimation( const std::string& animationName, const Repl { if( OptionalChild animation = IsChild(*animations, animationName) ) { - anim = Dali::Toolkit::Internal::CreateAnimation( *animation, replacement, sourceActor ); + anim = Dali::Toolkit::Internal::CreateAnimation( *animation, replacement, sourceActor, this ); } else { @@ -834,13 +1083,13 @@ Animation Builder::CreateAnimation( const std::string& animationName, const Repl return anim; } -Animation Builder::CreateAnimation( const std::string& animationName, const PropertyValueMap& map, Dali::Actor sourceActor ) +Animation Builder::CreateAnimation( const std::string& animationName, const Property::Map& map, Dali::Actor sourceActor ) { Replacement replacement(map, mReplacementMap); return CreateAnimation( animationName, replacement, sourceActor); } -Animation Builder::CreateAnimation( const std::string& animationName, const PropertyValueMap& map ) +Animation Builder::CreateAnimation( const std::string& animationName, const Property::Map& map ) { Replacement replacement(map, mReplacementMap); return CreateAnimation( animationName, replacement, Stage::GetCurrent().GetRootLayer() ); @@ -862,8 +1111,6 @@ Animation Builder::CreateAnimation( const std::string& animationName ) void Builder::LoadFromString( std::string const& data, Dali::Toolkit::Builder::UIFormat format ) { - DALI_ASSERT_ALWAYS( format == Dali::Toolkit::Builder::JSON && "Currently only JSON is supported" ); - // parser to get constants and includes only Dali::Toolkit::JsonParser parser = Dali::Toolkit::JsonParser::New(); @@ -916,12 +1163,9 @@ void Builder::LoadFromString( std::string const& data, Dali::Toolkit::Builder::U } -void Builder::AddConstants( const PropertyValueMap& map ) +void Builder::AddConstants( const Property::Map& map ) { - for(PropertyValueMap::const_iterator iter = map.begin(); iter != map.end(); ++iter) - { - mReplacementMap[ (*iter).first ] = (*iter).second; - } + mReplacementMap.Merge( map ); } void Builder::AddConstant( const std::string& key, const Property::Value& value ) @@ -929,17 +1173,17 @@ void Builder::AddConstant( const std::string& key, const Property::Value& value mReplacementMap[key] = value; } -const PropertyValueMap& Builder::GetConstants() const +const Property::Map& Builder::GetConstants() const { return mReplacementMap; } const Property::Value& Builder::GetConstant( const std::string& key ) const { - PropertyValueMap::const_iterator iter = mReplacementMap.find( key ); - if( iter != mReplacementMap.end() ) + Property::Value* match = mReplacementMap.Find( key ); + if( match ) { - return (*iter).second; + return (*match); } else { @@ -948,7 +1192,7 @@ const Property::Value& Builder::GetConstant( const std::string& key ) const } } -void Builder::LoadConstants( const TreeNode& root, PropertyValueMap& intoMap ) +void Builder::LoadConstants( const TreeNode& root, Property::Map& intoMap ) { Replacement replacer(intoMap); @@ -977,10 +1221,10 @@ void Builder::LoadConstants( const TreeNode& root, PropertyValueMap& intoMap ) } #if defined(DEBUG_ENABLED) - PropertyValueMap::const_iterator iter = intoMap.find( "CONFIG_SCRIPT_LOG_LEVEL" ); - if( iter != intoMap.end() && (*iter).second.GetType() == Property::STRING ) + Property::Value* iter = intoMap.Find( "CONFIG_SCRIPT_LOG_LEVEL" ); + if( iter && iter->GetType() == Property::STRING ) { - std::string logLevel( (*iter).second.Get< std::string >() ); + std::string logLevel( iter->Get< std::string >() ); if( logLevel == "NoLogging" ) { gFilterScript->SetLogLevel( Integration::Log::NoLogging ); @@ -1002,13 +1246,13 @@ void Builder::LoadConstants( const TreeNode& root, PropertyValueMap& intoMap ) } -void Builder::ApplyStyle( const std::string& styleName, Handle& handle ) +bool Builder::ApplyStyle( const std::string& styleName, Handle& handle ) { Replacement replacer( mReplacementMap ); - ApplyStyle( styleName, handle, replacer ); + return ApplyStyle( styleName, handle, replacer ); } -void Builder::ApplyStyle( const std::string& styleName, Handle& handle, const Replacement& replacement ) +bool Builder::ApplyStyle( const std::string& styleName, Handle& handle, const Replacement& replacement ) { DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded"); @@ -1018,15 +1262,15 @@ void Builder::ApplyStyle( const std::string& styleName, Handle& handle, const Re if( styles && style ) { ApplyAllStyleProperties( *mParser.GetRoot(), *style, handle, replacement ); + return true; } else { - DALI_SCRIPT_WARNING("No styles section to create style '%s'\n", styleName.c_str()); + return false; } - } -BaseHandle Builder::Create( const std::string& templateName, const PropertyValueMap& map ) +BaseHandle Builder::Create( const std::string& templateName, const Property::Map& map ) { Replacement replacement( map, mReplacementMap ); return Create( templateName, replacement ); @@ -1069,6 +1313,44 @@ BaseHandle Builder::Create( const std::string& templateName, const Replacement& return baseHandle; } +BaseHandle Builder::CreateFromJson( const std::string& json ) +{ + BaseHandle ret; + + // merge in new template, hoping no one else has one named '@temp@' + std::string newTemplate = + std::string("{\"templates\":{\"@temp@\":") + \ + json + \ + std::string("}}"); + + if( mParser.Parse(newTemplate) ) + { + Replacement replacement( mReplacementMap ); + ret = Create( "@temp@", replacement ); + } + + return ret; +} + +bool Builder::ApplyFromJson( Handle& handle, const std::string& json ) +{ + bool ret = false; + + // merge new style, hoping no one else has one named '@temp@' + std::string newStyle = + std::string("{\"styles\":{\"@temp@\":") + \ + json + \ + std::string("}}"); + + if( mParser.Parse(newStyle) ) + { + Replacement replacement( mReplacementMap ); + ret = ApplyStyle( "@temp@", handle, replacement ); + } + + return ret; +} + BaseHandle Builder::Create( const std::string& templateName ) {