Alignment Property Example

This section provides a complete example of an alignment property for a SuperLabel class, which allows users to specify how they want the text aligned inside a label: left, right, and center. The example shows how to:

For the sample code, see A Complete Example.

Basic alignment Property

The basic code for creating the alignment property is as follows. In the setAlignment method, the invalidate function is called, which indirectly forces the control to repaint so that it will reflect the new property value:

private int align = AlignStyle.LEFT;

public int getAlignment() {
   return align;
}

public void setAlignment(int value) {
   align = value;
   invalidate();   // Repaint control when property changes
}

Creating An Enumerated Property Value

Because there are only three possible values for the property, you can use an enumerator (enum) to define them. Although Java does not have native support for enumeration types, WFC provides a com.ms.wfc.core.Enum class. Any class that derives from com.ms.wfc.core.Enum will be treated as an Enum object. All Enum objects conform to the standard that they contain only public static final integers that represent the valid selections. They may optionally contain a valid method that returns true if a passed value is legal in that Enum object.

Enumerator objects are recognized in the Properties window. Therefore, when you subclass the Enum class, you automatically get a drop-down list of valid items in the Properties window at design time.

The following example shows a class that defines an AlignStyle enumerator:

// AlignStyle.java
import com.ms.wfc.core.*;

public class AlignStyle extends Enum
{
   public static final int LEFT = 1;
   public static final int RIGHT = 2;
   public static final int CENTER = 3;
   
   // Optional valid method to test passed value
   public static boolean valid(int value) {
      return (LEFT <= value && value <= CENTER);
   }
}

Note   Creating the valid method as a static member allows users to call it without having to create an instance of the class first.

Providing Property Validation

In order to test that the user has specified a legal alignment value when setting the property, you can add validation to the setAlignment method. To test the value, you can call the valid method of the AlignStyle enumerator. If there is an error, you can throw the WFCInvalidEnumException exception.

The example below shows a modified setAlignment method with validation added:

public void setAlignment(int value) {
   if (!AlignStyle.valid(value))
      throw new WFCInvalidEnumException("value", value, AlignStyle.class);
   align = value;
   invalidate();   // Repaint control when property changes
}

Note   For information about using invalidate to repaint a control, see Updating Visual Display.

By throwing a WFCInvalidEnumException, you get the benefit that it is a non-checked exception, and there is a predefined message associated with it. This message has been translated to multiple languages so that when you run this control in various locales, you automatically get a meaningful error message.

Using the Property Value when Painting

The alignment property affects the appearance of text in the control. Therefore, whenever the control is painted, the paint code must check the property's value and use it accordingly.

You specify paint behavior by overriding the onPaint method. The example below shows you would read the alignment property value and then use the value in the drawString method to set the alignment. The constants LEFT, RIGHT, and so on are defined in the TextFormat class in com.ms.wfc.ui:

protected void onPaint(PaintEvent p) {
   Graphics g = p.graphics;
   int style = 0;
   switch (align) {
      case AlignStyle.LEFT:
         style = TextFormat.LEFT;
         break;
      case AlignStyle.RIGHT:
         style = TextFormat.RIGHT;
         break;
      case AlignStyle.CENTER:
         style = TextFormat.HORIZONTALCENTER;
         break;
   }
   g.drawString(getText(), getClientRect(), style);
}

Exposing the Property at Design Time

To make the alignment property available at design time, you subclass ClassInfo to first define the property (by creating an instance of PropertyInfo). You then expose the property by calling the getProperties method:

public static class ClassInfo extends Control.ClassInfo {
   public static final PropertyInfo alignment = new PropertyInfo(
      MyControl.class, "alignment", AlignStyle.class);

   public void getProperties(IProperties props) {
      super.getProperties(props);
      props.add(alignment);
   }
}

Note   The third parameter passed to the PropertyInfo constructor (in this case, AlignStyle.class) is normally the data type of the property. However, because this property is an enumerated value, you pass the class you created that extends Enum.

Because AlignStyle derives from the Enum class, the Properties window uses the editor associated with the Enum class. The result is a drop-down list that allows you to set the value of the property.

Note   To create a property that is not exposed at design time (for example, a run time-only property), use the PropertyInfo object to set the BrowsableAttribute attribute to NO. For details, see Specifying Custom Property Attributes.

A Complete Example

The following example shows a complete label control with an alignment property including all the features discussed previously:

// SuperLabel.java
import com.ms.wfc.ui.*;
import com.ms.wfc.core.*;

public class SuperLabel extends Control {
   private int align = AlignStyle.LEFT;

   public int getAlignment() {
      return align;
   }

   public void setAlignment(int value) {
      if (!AlignStyle.valid(value))
         throw new WFCInvalidEnumException("value", value, AlignStyle.class);
      align = value;
      invalidate();   // Repaint control when property changes
   }
   
   protected void onPaint(PaintEvent p) {
      Graphics g = p.graphics;
      int style = 0;
      switch (align) {
         case AlignStyle.LEFT:
            style = TextFormat.LEFT;
            break;
         case AlignStyle.RIGHT:
            style = TextFormat.RIGHT;
            break;
         case AlignStyle.CENTER:
            style = TextFormat.HORIZONTALCENTER;
            break;
      }
      g.drawString(getText(), getClientRect(), style);
   }

   public static class ClassInfo extends Control.ClassInfo {
      public static final PropertyInfo alignment = new PropertyInfo(
         SuperLabel.class, "alignment", AlignStyle.class);
         
      public void getProperties(IProperties props) {
         super.getProperties(props);
         props.add(alignment);
      }
   }
}