Exemplo n.º 1
0
	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();
	}
Exemplo n.º 2
0
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);
	}
}
//==============================================================================
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;
}
Exemplo n.º 4
0
//------------------------------------------------------------------------------
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;
		}
	}