1 Properties

1.5 Composite Properties

A property’s value may itself be an object which exports properties; such an object is known as a composite property, and its properties are called subproperties.

Property handles for subproperties may be obtained from the top-level exporting class using getProperty(), with successive sub-property names delimited by a ’.’ character. For example, if a class exports a property textureProps, whose value is a composite property exporting a sub-property called mode, then a handle to the mode property can be obtained from the top-level class using

   Property mode = getProperty ("textureProps.mode");

which has the same effect as

   Property texture = getProperty ("textureProps");
   Property mode =
       ((HasProperties)texture).getProperty ("mode");

Composite properties should adhere to a couple of rules. First, they should be returned by reference; i.e., the hosting class should return a pointer to the original property, rather than a copy. Secondly, they should implement the CompositeProperty interface. This is an extension of HasProperties with the following methods:

interface CompositeProperty extends HasProperties
{
   // returns the host class exporting this property
   HasProperties getPropertyHost();
   // returns information about this property
   PropertyInfo getPropertyInfo();
   // sets the host class exporting this property
   void setPropertyHost (HasProperties host);
   // sets information for this property
   void setPropertyInfo (PropertyInfo info);
}

These methods can be easily implemented using local variables to store the relevant information, as in

   HasProperties myHost;
   HasProperties getPropertyHost() {
      return myHost;
   }
   void setPropertyHost (HasProperties host) {
      myHost = host;
   }

and similarly for the property information.

The purpose of the CompositeProperty interface is to allow traversal of the composite property tree by the property support code.

The accessor method that sets a composite property within a host should set it’s host and property information. This can be done using using the setPropertyHost and setPropertyInfo methods, as in the following example for a compound property of type TextureProps:

   setRenderProps (RenderProps props) {
      if (props != myProps) {
         if (props != null) {
            props.setPropertyInfo(myProps.get("renderProps"));
            props.setPropertyHost(this);
         }
         if (myProps != null) {
            props.setPropertyHost (null);
         }
         myProps = props;
      }
   }

Alternatively, the same thing can be done using the static convenience method PropertyUtils.updateCompositeProperty:

   setRenderProps (RenderProps props) {
      if (props != myProps) {
         PropertyUtils.updateCompositeProperty (
            this, "textureProps", myProps, props);
         myProps = props;
      }
   }

If a composite property has a number of subclasses, it may optionally implement the static method

   public static Class<?>[] getSubClasses();

which returns an array of the class types of these subclasses. This can then be used by the system to automatically create GUI widgets that allow different instances of these subclasses to be selected.