@Override
protected void init()
{
super.init();
final ISapphireUiDef rootdef = this.definition.nearest( ISapphireUiDef.class );
final PropertyEditorDef propertyEditorPartDef = (PropertyEditorDef) this.definition;
final String propertyEditorPath = substituteParams( propertyEditorPartDef.getProperty().text() );
this.property = getModelElement().property( new ModelPath( propertyEditorPath ) );
if( this.property == null )
{
throw new RuntimeException( invalidPath.format( propertyEditorPath ) );
}
// Read the property to ensure that initial events are broadcast and avoid being surprised
// by them later.
this.property.empty();
// Child properties.
final ListFactory<ModelPath> childPropertiesListFactory = ListFactory.start();
final ElementType type = this.property.definition().getType();
if( type != null )
{
if( propertyEditorPartDef.getChildProperties().isEmpty() )
{
for( PropertyDef childProperty : type.properties() )
{
if( childProperty instanceof ValueProperty )
{
childPropertiesListFactory.add( new ModelPath( childProperty.name() ) );
}
}
}
else
{
for( PropertyEditorDef childPropertyEditor : propertyEditorPartDef.getChildProperties() )
{
final ModelPath childPropertyPath = new ModelPath( childPropertyEditor.getProperty().content() );
boolean invalid = false;
if( childPropertyPath.length() == 0 )
{
invalid = true;
}
else
{
ElementType t = type;
for( int i = 0, n = childPropertyPath.length(); i < n && ! invalid; i++ )
{
final ModelPath.Segment segment = childPropertyPath.segment( i );
if( segment instanceof ModelPath.PropertySegment )
{
final PropertyDef p = t.property( ( (ModelPath.PropertySegment) segment ).getPropertyName() );
if( p instanceof ValueProperty )
{
if( i + 1 != n )
{
invalid = true;
}
}
else if( p instanceof ImpliedElementProperty )
{
if( i + 1 == n )
{
invalid = true;
}
else
{
t = p.getType();
}
}
else
{
invalid = true;
}
}
else
{
invalid = true;
}
}
}
if( invalid )
{
final String msg = invalidChildPropertyPath.format( this.property.name(), childPropertyPath.toString() );
Sapphire.service( LoggingService.class ).logError( msg );
}
else
{
childPropertiesListFactory.add( childPropertyPath );
}
}
}
}
this.childPropertyPaths = childPropertiesListFactory.result();
this.childPropertyEditors = new HashMap<Element,Map<ModelPath,PropertyEditorPart>>();
// Listen for PropertyValidationEvent and update property editor's validation.
if( this.property instanceof ElementList || this.property instanceof ElementHandle )
{
this.propertyValidationListener = new FilteredListener<PropertyEvent>()
{
@Override
protected void handleTypedEvent( final PropertyEvent event )
{
if( ! ( event instanceof PropertyContentEvent && event.property() instanceof Value ) )
{
refreshValidation();
}
}
};
this.property.attach( this.propertyValidationListener, "*" );
}
else
{
this.propertyValidationListener = new FilteredListener<PropertyEvent>()
{
@Override
protected void handleTypedEvent( final PropertyEvent event )
{
if( event instanceof PropertyValidationEvent || event instanceof PropertyEnablementEvent )
{
refreshValidation();
}
}
};
this.property.attach( this.propertyValidationListener );
}
// Hints
this.hints = new HashMap<String,Object>();
for( ISapphireHint hint : propertyEditorPartDef.getHints() )
{
final String name = hint.getName().text();
final String valueString = hint.getValue().text();
Object parsedValue = valueString;
if( name.equals( PropertyEditorDef.HINT_SHOW_HEADER ) ||
name.equals( PropertyEditorDef.HINT_BORDER ) ||
name.equals( PropertyEditorDef.HINT_BROWSE_ONLY ) ||
name.equals( PropertyEditorDef.HINT_READ_ONLY ) )
{
parsedValue = Boolean.parseBoolean( valueString );
}
else if( name.startsWith( PropertyEditorDef.HINT_FACTORY ) ||
name.startsWith( PropertyEditorDef.HINT_AUX_TEXT_PROVIDER ) )
{
parsedValue = rootdef.resolveClass( valueString );
}
else if( name.equals( PropertyEditorDef.HINT_LISTENERS ) )
{
final List<Class<?>> contributors = new ArrayList<Class<?>>();
for( String segment : valueString.split( "," ) )
{
final Class<?> cl = rootdef.resolveClass( segment.trim() );
if( cl != null )
{
contributors.add( cl );
}