bool ComponentCollection::ValidateComponent( const ComponentPtr &component, tstring& error ) const
{
    HELIUM_ASSERT( component->GetSlot() != Reflect::ReservedTypes::Invalid );

    // Check for duplicates.
    if ( ContainsComponent( component->GetSlot() ) )
    {
        error = tstring( TXT( "The component '" ) )+ component->GetClass()->m_UIName + TXT( "' is a duplicate (a component already occupies that slot in the collection)." );
        return false;
    }

    // Check to make sure this type of collection accepts this type of component.
    if ( !ValidateCompatible( component, error ) )
    {
        return false;
    }

    // Check to make sure that each component already within the collection is valid with the new one.
    M_Component::const_iterator itr = m_Components.begin();
    M_Component::const_iterator end = m_Components.end();
    for ( ; itr != end; ++itr )
    {
        // Check both directions so that the validation rule only has to be implemented in one place.
        if ( !itr->second->ValidateSibling( component, error ) || !component->ValidateSibling( itr->second.Ptr(), error ) )
        {
            return false;
        }
    }

    return true;
}
bool ComponentCollection::ValidateCompatible( const ComponentPtr& component, tstring& error ) const
{
    HELIUM_ASSERT( component->GetSlot() != Reflect::ReservedTypes::Invalid );

    if ( component->GetComponentBehavior() == ComponentBehaviors::Exclusive )
    {
        error = component->GetClass()->m_UIName + TXT( " cannot be added to a(n) " ) + GetClass()->m_UIName + TXT( " because it is an exclusive component." );
        return false;
    }

    return true;
}
bool ComponentCollection::SetComponent(const ComponentPtr& component, bool validate, tstring* error )
{
    HELIUM_ASSERT( component->GetSlot() != Reflect::ReservedTypes::Invalid );

    M_Component::const_iterator found = m_Components.find( component->GetSlot() );
    if (found != m_Components.end() && found->second == component)
    {
        return true; // nothing to do, this is already in the collection
    }

    tstring errorMessage;
    if ( validate && !ValidateComponent( component, errorMessage ) )
    {
        if ( error )
        {
            *error = tstring( TXT( "Component '" ) ) + component->GetClass()->m_ShortName + TXT( "' is not valid for collection '" ) + GetClass()->m_ShortName + TXT( "': " ) + errorMessage;
        }
        
        return false;
    }

    // Event args
    ComponentCollectionChanged args ( this, component );

    // Set the component and connect the collection
    m_Components[ component->GetSlot() ] = component;
    component->SetCollection( this );

    // Start caring about change to the component
    component->AddChangedListener( ElementChangeSignature::Delegate::Create<ComponentCollection, void (ComponentCollection::*)( const Reflect::ElementChangeArgs& )> ( this, &ComponentCollection::ComponentChanged ) );

    // Raise event
    m_Modified = true;
    m_ComponentAdded.Raise( args );
    return true;
}