//============================================================================== ObjectHandle SetReflectedPropertyCommand::execute( const ObjectHandle & arguments ) const { ReflectedPropertyCommandArgument * commandArgs = arguments.getBase< ReflectedPropertyCommandArgument >(); auto objManager = definitionManager_.getObjectManager(); assert( objManager != nullptr ); ObjectHandle object = objManager->getObject( commandArgs->getContextId() ); if (!object.isValid()) { return CommandErrorCode::INVALID_ARGUMENTS; } PropertyAccessor property = object.getDefinition( definitionManager_ )->bindProperty( commandArgs->getPropertyPath(), object ); if (property.isValid() == false) { //Can't set return CommandErrorCode::INVALID_ARGUMENTS; } const Variant & data = commandArgs->getPropertyValue(); bool br = property.setValue( data ); if (!br) { return CommandErrorCode::INVALID_VALUE; } // Do not return the object // CommandInstance will hold a reference to the return value // and the CommandInstance is stored in the undo/redo history forever // This is due to a circular reference in CommandManagerImpl::pushFrame return nullptr; }
bool BaseGenericObject::addProperty(const char* name, const Variant& value, MetaData metadata, bool enableNotification) { const IClassDefinition& definition = *this->getDefinition(); ObjectHandle provider = this->getDerivedType(); auto definitionModifier = definition.getDetails().getDefinitionModifier(); if (definitionModifier == nullptr) { return false; } Collection testCollection; bool isCollection = value.tryCast<Collection>(testCollection); if (!definitionModifier->addProperty(name, value.type()->typeId(), std::move(metadata), isCollection)) { return false; } PropertyAccessor accessor = definition.bindProperty(name, provider); if (enableNotification) { return accessor.setValue(value); } else { return accessor.setValueWithoutNotification(value); } }
Variant c_XMLReader::t___get(Variant name) { INSTANCE_METHOD_INJECTION_BUILTIN(XMLReader, XMLReader::__get); const xmlChar *retchar = NULL; int retint = 0; PropertyAccessor *propertyMap = xmlreader_properties_map.get(name); if (m_ptr) { if (propertyMap->getter_char) { retchar = propertyMap->getter_char(m_ptr); } else if (propertyMap->getter_int) { retint = propertyMap->getter_int(m_ptr); } } switch (propertyMap->return_type) { case KindOfString: if (retchar) { return String((char*)retchar, CopyString); } else { return String(""); } case KindOfBoolean: return (retint ? true : false); case KindOfInt64: return retint; default: return null; } return null; }
Variant getValue( const PropertyAccessor & pa ) { // This createKey is added as a work-around for objects that were // not registered with the IObjectManager properly on creation. // // Objects need a key to be shared with other plugins. // E.g. getValue() will be sharing your object with plg_command_manager. // // Better to register your object with IObjectManager::registerObject() // or IObjectManager::registerUnmanagedObject() when you create the // ObjectHandle. // // @see IObjectManager Key key; if (!createKey( pa, key )) { return pa.getValue(); } // TODO: assert access is only on the main thread auto range = commands_.equal_range( key ); for (auto it = range.first; it != range.second; ++it) { auto instance = it->second; commandManager_.waitForInstance(instance); } commands_.erase( range.first, range.second ); return pa.getValue(); }
void setValue( const PropertyAccessor & pa, const Variant & data ) { Key key; if (!createKey( pa, key )) { pa.setValue( data ); return; } std::unique_ptr< ReflectedPropertyCommandArgument > args( new ReflectedPropertyCommandArgument ); args->setContextId( key.first ); args->setPath( key.second.c_str() ); args->setValue( data ); // Access is only on the main thread assert( std::this_thread::get_id() == commandManager_.ownerThreadId() ); const auto commandId = getClassIdentifier< SetReflectedPropertyCommand >(); const auto pArgsDefinition = pa.getDefinitionManager()->getDefinition< ReflectedPropertyCommandArgument >(); ObjectHandle commandArgs( std::move( args ), pArgsDefinition ); auto command = commandManager_.queueCommand( commandId, commandArgs ); // Queuing may cause it to execute straight away // Based on the thread affinity of SetReflectedPropertyCommand if (!command->isComplete()) { commands_.emplace( std::pair< Key, CommandInstancePtr >( key, command ) ); } }
TEST_F( TestCommandFixture, creatMacro ) { auto & controller = getReflectionController(); auto objHandle = klass_->createManagedObject(); PropertyAccessor counter = klass_->bindProperty("counter", objHandle ); CHECK(counter.isValid()); const int TEST_VALUE = 57; { int value = TEST_VALUE; controller.setValue( counter, value ); } { // TODO: wait on controller controller.getValue( counter ); } { auto & commandSystemProvider = getCommandSystemProvider(); auto & history = commandSystemProvider.getHistory(); commandSystemProvider.createMacro( history ); CHECK(commandSystemProvider.getMacros().empty() == false ); } }
//============================================================================== std::string RPURU::resolveContextObjectPropertyPath(const ObjectHandle& contextObject, const char* propertyPath, IDefinitionManager& definitionManager) { assert(contextObject != nullptr); const auto classDef = contextObject.getDefinition(definitionManager); assert(classDef != nullptr); std::string tmp = propertyPath; std::vector<std::string> paths; paths.push_back(tmp); char* pch; pch = strtok(const_cast<char*>(tmp.c_str()), "."); if (pch != NULL) { pch = strtok(NULL, "."); while (pch != NULL) { paths.push_back(pch); pch = strtok(NULL, "."); } } PropertyAccessor pa; for (auto& path : paths) { resolveProperty(contextObject, *classDef, path.c_str(), pa, definitionManager); if (pa.isValid()) { break; } } return pa.getFullPath(); }
Variant BaseGenericObject::invokeProperty(const char* name, const ReflectedMethodParameters& parameters) { const IClassDefinition& definition = *this->getDefinition(); ObjectHandle provider = this->getDerivedType(); PropertyAccessor accessor = definition.bindProperty(name, provider); if (!accessor.isValid()) { TF_ASSERT(false && "Property could not be found"); return Variant(); } return accessor.invoke(parameters); }
TEST_F( TestCommandFixture, undo_redo ) { auto & controller = getReflectionController(); auto objHandle = klass_->createManagedObject(); PropertyAccessor counter = klass_->bindProperty("counter", objHandle ); CHECK(counter.isValid()); int oldValue = -1; { Variant variant = counter.getValue(); CHECK(variant.tryCast( oldValue )); } auto & commandSystemProvider = getCommandSystemProvider(); const int TEST_VALUE = 57; { int value = TEST_VALUE; controller.setValue( counter, value ); } { int value = 0; Variant variant = controller.getValue( counter ); CHECK(variant.tryCast( value )); CHECK_EQUAL(TEST_VALUE, value); } { commandSystemProvider.undo(); CHECK(!commandSystemProvider.canUndo()); CHECK(commandSystemProvider.canRedo()); int value = 0; Variant variant = controller.getValue( counter ); CHECK(variant.tryCast( value )); CHECK_EQUAL(oldValue, value); } { commandSystemProvider.redo(); CHECK(commandSystemProvider.canUndo()); CHECK(!commandSystemProvider.canRedo()); int value = 0; Variant variant = controller.getValue( counter ); CHECK(variant.tryCast( value )); CHECK_EQUAL(TEST_VALUE, value); } }
void DialogTestModel::callBasicDialog(bool modal) { assert(context_ != nullptr); auto uiFramework = context_->queryInterface<IUIFramework>(); assert(uiFramework != nullptr); IDialog::ClosedCallback callback = [this](IDialog& dialog) { assert(definition_ != nullptr); PropertyAccessor accessor = definition_->bindProperty("basicDialogResult", this); accessor.setValue(dialog.result()); }; const IDialog::Mode mode = modal ? IDialog::Mode::MODAL : IDialog::Mode::MODELESS; uiFramework->showDialog("plg_dialog_test/basic_dialog.qml", mode, callback); }
//! @brief read a text Bow file and fills a lexicon //! @param fileIn the file to read //! @param reader the file reader //! @param lex the lexicon to fill //! @param propertyAccessor //! @param referenceProperties void readBowFileText(ifstream& fileIn, BoWBinaryReader& reader, Lexicon& lex, const PropertyAccessor& propertyAccessor, set<LinguisticCode>& referenceProperties ) { BoWText text; reader.readBoWText(fileIn,text); bool filterCategory = false; if ( referenceProperties.size() > 0 ) { filterCategory = true; } BoWTokenIterator it(text); while (! it.isAtEnd()) { const BoWToken& token = *(it.getElement()); if (filterCategory) { set<LinguisticCode>::const_iterator referencePropertyIt = referenceProperties.find(propertyAccessor.readValue(token.getCategory())); if ( referencePropertyIt != referenceProperties.end() ) { lex.add(getStringDecomp(&token),token.getIndexString()); } } else { lex.add(getStringDecomp(&token),token.getIndexString()); } it++; } }
//============================================================================== bool SetReflectedPropertyCommand::validateArguments(const ObjectHandle& arguments) const { if ( !arguments.isValid() ) { return false; } auto commandArgs = arguments.getBase< ReflectedPropertyCommandArgument >(); if ( commandArgs == nullptr ) { return false; } auto objManager = definitionManager_.getObjectManager(); if ( objManager == nullptr ) { return false; } const ObjectHandle & object = objManager->getObject( commandArgs->getContextId() ); if (!object.isValid()) { return false; } const IClassDefinition* defn = object.getDefinition( definitionManager_ ); PropertyAccessor property = defn->bindProperty(commandArgs->getPropertyPath(), object ); if (property.isValid() == false) { return false; } const MetaType * dataType = commandArgs->getPropertyValue().type(); const MetaType * propertyValueType = property.getValue().type(); if ( !dataType->canConvertTo(propertyValueType) ) { return false; } return true; }
bool createKey( const PropertyAccessor & pa, Key & o_Key ) { const auto & obj = pa.getRootObject(); if (obj == nullptr) { return false; } if (!obj.getId( o_Key.first )) { auto om = pa.getDefinitionManager()->getObjectManager(); assert( !om->getObject( obj.data() ).isValid() ); if (!om->getUnmanagedObjectId( obj.data(), o_Key.first )) { o_Key.first = om->registerUnmanagedObject( obj ); } } o_Key.second = pa.getFullPath(); return true; }
//============================================================================== void RPURU::resolveProperty(const ObjectHandle& handle, const IClassDefinition& classDef, const char* propertyPath, PropertyAccessor& o_Pa, IDefinitionManager& definitionManager) { o_Pa = handle.getDefinition(definitionManager)->bindProperty(propertyPath, handle); if (o_Pa.isValid()) { return; } const PropertyIteratorRange& props = classDef.allProperties(); for (PropertyIterator pi = props.begin(); pi != props.end(); ++pi) { std::string parentPath = pi->getName(); const PropertyAccessor& prop = classDef.bindProperty(parentPath.c_str(), handle); assert(prop.isValid()); if (prop.getProperty()->isMethod()) { continue; } const Variant& value = prop.getValue(); if (value.typeIs<ObjectHandle>()) { ObjectHandle subHandle; bool isOk = value.tryCast(subHandle); assert(isOk); if ((subHandle == nullptr) || (subHandle.getDefinition(definitionManager) == nullptr)) { continue; } parentPath = parentPath + "." + propertyPath; resolveProperty(subHandle, *subHandle.getDefinition(definitionManager), parentPath.c_str(), o_Pa, definitionManager); if (o_Pa.isValid()) { return; } } } }
TEST_F( TestCommandFixture, executeMacro ) { auto & controller = getReflectionController(); auto objHandle = klass_->createManagedObject(); PropertyAccessor counter = klass_->bindProperty("counter", objHandle ); CHECK(counter.isValid()); const int TEST_VALUE = 57; { int value = TEST_VALUE; controller.setValue( counter, value ); } { // TODO: wait on controller controller.getValue( counter ); } { auto & commandSystemProvider = getCommandSystemProvider(); commandSystemProvider.undo(); auto & history = commandSystemProvider.getHistory(); commandSystemProvider.createMacro( history, "Macro1" ); CHECK(commandSystemProvider.getMacros().empty() == false ); auto macroObj = static_cast<CompoundCommand*>( commandSystemProvider.findCommand( "Macro1" ) )->getMacroObject(); auto instObj = macroObj.getBase<MacroObject>()->executeMacro(); CommandInstancePtr inst = instObj.getBase<CommandInstance>(); commandSystemProvider.waitForInstance( inst ); { PropertyAccessor counter = klass_->bindProperty("counter", objHandle ); int value = 0; Variant variant = controller.getValue( counter ); CHECK(variant.tryCast( value )); CHECK_EQUAL(TEST_VALUE, value); } } }
//-------------------------------------------------------------------------- ObjectHandle MetaUtilities::findFirstMetaData( const TypeId& typeId, const PropertyAccessor& accessor, const IDefinitionManager & definitionManager) override { auto && metaData = accessor.getMetaData(); auto targetMetaData = findFirstMetaData(typeId, metaData, definitionManager); if (targetMetaData != nullptr) { return targetMetaData; } return nullptr; }
TEST_F( TestCommandFixture, runSingleCommand ) { auto & controller = getReflectionController(); auto objHandle = klass_->createManagedObject(); PropertyAccessor counter = klass_->bindProperty("counter", objHandle ); CHECK(counter.isValid()); const int TEST_VALUE = 57; { int value = TEST_VALUE; controller.setValue( counter, value ); } { int value = 0; Variant variant = controller.getValue( counter ); CHECK(variant.tryCast( value )); CHECK_EQUAL(TEST_VALUE, value); } }
Variant invoke( const PropertyAccessor & pa, const ReflectedMethodParameters & parameters ) { Key key; if (!createKey( pa, key )) { return pa.invoke( parameters ); } std::unique_ptr<ReflectedMethodCommandParameters> commandParameters( new ReflectedMethodCommandParameters() ); commandParameters->setId( key.first ); commandParameters->setPath( key.second.c_str() ); commandParameters->setParameters( parameters ); const auto itr = commands_.emplace( std::pair< Key, CommandInstancePtr >( key, commandManager_.queueCommand( getClassIdentifier<InvokeReflectedMethodCommand>(), ObjectHandle( std::move( commandParameters ), pa.getDefinitionManager()->getDefinition<ReflectedMethodCommandParameters>() ) ) ) ); commandManager_.waitForInstance( itr->second ); ObjectHandle returnValueObject = itr->second.get()->getReturnValue(); commands_.erase( itr ); Variant* returnValuePointer = returnValueObject.getBase<Variant>(); assert( returnValuePointer != nullptr ); return *returnValuePointer; }
Variant c_XMLReader::t___get(Variant name) { const xmlChar *retchar = NULL; int retint = 0; PropertyAccessor *propertyMap = xmlreader_properties_map.get(name); if (!propertyMap) { raiseUndefProp(name.getStringData()); return uninit_null(); } if (m_ptr) { if (propertyMap->getter_char) { retchar = propertyMap->getter_char(m_ptr); } else if (propertyMap->getter_int) { retint = propertyMap->getter_int(m_ptr); } } switch (propertyMap->return_type) { case KindOfString: if (retchar) { return String((char*)retchar, CopyString); } else { return String(""); } case KindOfBoolean: return (retint ? true : false); case KindOfInt64: return retint; default: return uninit_null(); } return uninit_null(); }
void erase( const PropertyAccessor & pa, const Variant & eraseKey ) { Key key; if (!createKey( pa, key )) { pa.erase( eraseKey ); return; } std::unique_ptr<ReflectedCollectionEraseCommandParameters> commandParameters( new ReflectedCollectionEraseCommandParameters() ); commandParameters->id_ = key.first; commandParameters->path_ = key.second; commandParameters->key_ = eraseKey; const auto itr = commands_.emplace( std::pair< Key, CommandInstancePtr >( key, commandManager_.queueCommand( getClassIdentifier<ReflectedCollectionEraseCommand>(), ObjectHandle( std::move( commandParameters ) ) ) ) ); commandManager_.waitForInstance( itr->second ); commands_.erase( itr ); }
ReflectedEnumModel::ReflectedEnumModel(const PropertyAccessor& pA, ObjectHandleT<MetaEnumObj> enumObj) { const wchar_t* enumString = enumObj->getEnumString(); if (enumString != nullptr) { generateFromString(items_, enumString); return; } Collection collection = enumObj->generateEnum(pA.getObject()); auto it = collection.begin(); auto itEnd = collection.end(); for (; it != itEnd; ++it) { int index; it.key().tryCast(index); Variant itValue = it.value(); std::string text; itValue.tryCast(text); items_.push_back(new ReflectedEnumItem(index, text)); } }
bool BaseGenericObject::setProperty(const char* name, const Variant& value, bool enableNotification) { // Get existing property const IClassDefinition& definition = *this->getDefinition(); ObjectHandle provider = this->getDerivedType(); PropertyAccessor accessor = definition.bindProperty(name, provider); // do nothing if property does not exist and the value is void if (!accessor.isValid() && value.isVoid()) { return false; } // set value to the property if property exists and the value is not void if (accessor.isValid() && !value.isVoid()) { if (enableNotification) { return accessor.setValue(value); } else { return accessor.setValueWithoutNotification(value); } } // Property does not exist // Add new property and set it auto definitionModifier = definition.getDetails().getDefinitionModifier(); if (definitionModifier == nullptr) { return false; } if (accessor.isValid() && value.isVoid()) { definitionModifier->removeProperty(name); return false; } return addProperty(name, value, nullptr, enableNotification); }
//------------------------------------------------------------------------------ void ClassDefinition::bindPropertyImpl( const char * name, const ObjectHandle & pBase, PropertyAccessor & o_PropertyAccessor ) const { if (!*name) { // empty name causes noop return; } // find property operator auto propOperator = name; while (true) { if( !*propOperator || *propOperator == INDEX_OPEN || *propOperator == DOT_OPERATOR ) { break; } propOperator += 1; } auto propName = name; auto propLength = propOperator - propName; auto baseProp = findProperty( propName, propLength ); if (baseProp == nullptr) { // error: property `propName` is not found o_PropertyAccessor.setBaseProperty( nullptr ); return; } o_PropertyAccessor.setObject( pBase ); o_PropertyAccessor.setBaseProperty( baseProp ); assert( strncmp( propName, o_PropertyAccessor.getName(), propLength ) == 0 ); if (!*propOperator) { // no operator, so that's it return; } Variant propVal = o_PropertyAccessor.getValue(); if (*propOperator == INDEX_OPEN) { auto wholeIndex = propOperator; // read "multidimensional" indices without recursive bind (optimization) while (true) { Collection collection; if (!propVal.tryCast( collection )) { // error: index operator is applicable to collections only o_PropertyAccessor.setBaseProperty( nullptr ); return; } // determine key type (heterogeneous keys are not supported yet) const auto begin = collection.begin(); const auto end = collection.end(); if (begin == end) { // error: can't index empty collection o_PropertyAccessor.setBaseProperty( nullptr ); return; } // read key Variant key( begin.key().type() ); { propOperator += 1; // skip INDEX_OPEN FixedMemoryStream dataStream( propOperator ); TextStream stream( dataStream ); stream >> key >> match( INDEX_CLOSE ); if (stream.fail()) { // error: either key can't be read, or it isn't followed by INDEX_CLOSE o_PropertyAccessor.setBaseProperty( nullptr ); return; } // skip key and closing bracket propOperator += stream.seek( 0, std::ios_base::cur ); } auto it = collection.find( key ); // If (it == end), still return a valid property accessor to end, // rather than an invalid property accessor. if (!*propOperator || (it == end)) { // name parsing is completed auto baseProp = std::make_shared< CollectionElementHolder >( collection, it, collection.valueType(), wholeIndex ); // o_PropertyAccessor.setObject(); - keep current base o_PropertyAccessor.setBaseProperty( baseProp ); return; } propVal = it.value(); if (*propOperator == INDEX_OPEN) { continue; } // parse next operator break; } }
TEST_F( TestCommandFixture, runBatchCommand ) { auto & controller = getReflectionController(); auto objHandle = klass_->createManagedObject(); const int TEST_VALUE = 57; const char * TEST_TEXT = "HelloCommand"; PropertyAccessor counter = klass_->bindProperty("counter", objHandle ); CHECK(counter.isValid()); PropertyAccessor text = klass_->bindProperty( "text", objHandle ); CHECK(text.isValid()); PropertyAccessor incrementCounter = klass_->bindProperty("incrementCounter", objHandle ); CHECK(incrementCounter.isValid()); { int value = 0; Variant variantValue = controller.getValue( counter ); CHECK( variantValue.tryCast( value ) ); CHECK( TEST_VALUE != value ); std::string text_value; Variant variantText = controller.getValue( text ); CHECK( variantText.tryCast( text_value ) ); CHECK( TEST_TEXT != text_value ); } { int value = TEST_VALUE; auto & commandSystemProvider = getCommandSystemProvider(); commandSystemProvider.beginBatchCommand(); controller.setValue( counter, value ); std::string text_value = TEST_TEXT; controller.setValue( text, text_value ); commandSystemProvider.abortBatchCommand(); } { int value = 0; Variant variantValue = controller.getValue( counter ); CHECK(variantValue.tryCast( value )); CHECK(TEST_VALUE != value); std::string text_value; Variant variantText = controller.getValue( text ); CHECK(variantText.tryCast( text_value )); CHECK(TEST_TEXT != text_value); } { int value = TEST_VALUE; auto & commandSystemProvider = getCommandSystemProvider(); commandSystemProvider.beginBatchCommand(); controller.setValue( counter, value ); std::string text_value = TEST_TEXT; controller.setValue( text, text_value ); commandSystemProvider.endBatchCommand(); } { int value = 0; Variant variantValue = controller.getValue( counter ); CHECK(variantValue.tryCast( value )); CHECK_EQUAL(TEST_VALUE, value); std::string text_value; Variant variantText = controller.getValue( text ); CHECK(variantText.tryCast( text_value )); CHECK_EQUAL(TEST_TEXT, text_value); } { Variant variantValue; int value = 0; auto & commandSystemProvider = getCommandSystemProvider(); commandSystemProvider.beginBatchCommand(); controller.setValue( counter, 0 ); commandSystemProvider.beginBatchCommand(); controller.setValue( counter, 1 ); commandSystemProvider.beginBatchCommand(); controller.setValue( counter, 2 ); commandSystemProvider.beginBatchCommand(); controller.setValue( counter, 3 ); variantValue = controller.getValue( counter ); CHECK( variantValue.tryCast( value ) ); CHECK( value == 3 ); commandSystemProvider.abortBatchCommand(); variantValue = controller.getValue( counter ); CHECK( variantValue.tryCast( value ) ); CHECK( value == 2 ); commandSystemProvider.abortBatchCommand(); variantValue = controller.getValue( counter ); CHECK( variantValue.tryCast( value ) ); CHECK( value == 1); commandSystemProvider.abortBatchCommand(); variantValue = controller.getValue( counter ); CHECK( variantValue.tryCast( value ) ); CHECK( value == 0); commandSystemProvider.endBatchCommand(); variantValue = controller.getValue( counter ); CHECK( variantValue.tryCast( value ) ); CHECK( value == 0); } { int value = 0; controller.setValue( counter, value ); Variant variantValue = controller.getValue( counter ); CHECK(variantValue.tryCast( value )); CHECK_EQUAL(0, value); auto & commandSystemProvider = getCommandSystemProvider(); commandSystemProvider.beginBatchCommand(); controller.invoke( incrementCounter, ReflectedMethodParameters() ); controller.invoke( incrementCounter, ReflectedMethodParameters() ); commandSystemProvider.endBatchCommand(); variantValue = controller.getValue( counter ); CHECK(variantValue.tryCast( value )); CHECK_EQUAL(2, value); commandSystemProvider.beginBatchCommand(); controller.invoke( incrementCounter, ReflectedMethodParameters() ); controller.invoke( incrementCounter, ReflectedMethodParameters() ); commandSystemProvider.abortBatchCommand(); variantValue = controller.getValue( counter ); CHECK(variantValue.tryCast( value )); CHECK_EQUAL(2, value); } }