From “Engineer Thinking” by Matt Legend Gemmell:

If you’ve exposed underling complexity or unnecessary choice in your software because you see those things as inevitable, it’s because your job isn’t finished. If you’re going to write GUI software for other people to use, do it properly, and treat those people like human beings instead of software engineers. If you want to expose complexity to the user and wash your hands of it, write command-line tools – or utilities that are used exclusively by other machine processes.

You can’t have it both ways. Writing GUI software is for people who strive for excellence not only in the “software” part but in the “GUI” part too.

New in Trident 1.2

March 8th, 2010

The Trident animation library was born in February 2009 out of the internal animation layer used in Substance look-and-feel over the last three years. A year after, it is nearing its third official release which focuses mainly on stabilizing the API and ironing out the existing bugs.

The major milestone for this release is moving Substance 6.0 to use Trident – along with validating the library performance and flexibility to support a wide variety of UI animations. Trident 1.2 has also added a few new APIs to address a few common application requirements.

Custom property accessors

The default mechanism to retrieve and update the interpolated field is to use reflection to look up and call the matching published getter and setter. Application code that does not wish to expose these methods should use the following APIs:

  • TimelinePropertyBuilder.getWith(PropertyGetter)new in 1.2
  • TimelinePropertyBuilder.setWith(PropertySetter)
  • TimelinePropertyBuilder.accessWith(PropertyAccessor)new in 1.2

Where the relevant interfaces are defined in the TimelinePropertyBuilder class as follows:

If the timeline property builder is configured with a custom property setter / accessor, the set() will be called at every timeline pulse passing the object, the name of the field and the new value to set on the field. If the timeline property builder is configured with a custom property getter / accessor, the get() will be called when the current value of the field is needed. For example, when the builder is configured with fromCurrent(), the get() will be called to get the current field value when the timeline starts playing.

The following sample shows usage of a custom property setter:

public class CustomSetter {
   private float value;

   public static void main(String[] args) {
      final CustomSetter helloWorld = new CustomSetter();
      Timeline timeline = new Timeline(helloWorld);
      PropertySetter propertySetter = new PropertySetter() {
         @Override
         public void set(Object obj, String fieldName, Float value) {
            SimpleDateFormat sdf = new SimpleDateFormat("ss.SSS");
            float oldValue = helloWorld.value;
            System.out.println(sdf.format(new Date()) + " : " + oldValue
                  + " -> " + value);
            helloWorld.value = value;
         }
      };
      timeline.addPropertyToInterpolate(Timeline. property("value")
            .from(0.0f).to(1.0f).setWith(propertySetter));
      timeline.play();

      try {
         Thread.sleep(3000);
      } catch (Exception exc) {
      }
   }
}

Here, the CustomSetter class does not wish to expose the value field via a public setter. Instead, a custom property setter is provided to be called on every timeline pulse. Note that while this sample code does update the matching object field, it is not a strict requirement. Your custom property setter can do anything it wants in the set implementation – update a key-value map, update multiple fields or even ignore some of the values altogether.

The following sample shows usage of a custom property accessor backed up by a key-value map:

public class CustomAccessor {
   private Map values = new HashMap();

   public static void main(String[] args) {
      final CustomAccessor helloWorld = new CustomAccessor();
      Timeline timeline = new Timeline(helloWorld);

      PropertyAccessor propertyAccessor = new PropertyAccessor() {
         @Override
         public Float get(Object obj, String fieldName) {
            return helloWorld.values.get("value");
         }

         @Override
         public void set(Object obj, String fieldName, Float value) {
            SimpleDateFormat sdf = new SimpleDateFormat("ss.SSS");
            float oldValue = helloWorld.values.get("value");
            System.out.println(sdf.format(new Date()) + " : " + oldValue
                  + " -> " + value);
            helloWorld.values.put("value", value);
         }
      };
      helloWorld.values.put("value", 50f);

      timeline.addPropertyToInterpolate(Timeline. property("value")
            .fromCurrent().to(100.0f).accessWith(propertyAccessor));
      timeline.setDuration(300);
      timeline.play();

      try {
         Thread.sleep(1000);
      } catch (Exception exc) {
      }
   }
}

Note that both examples assume that the setter / accessor is used only for one specific field (“value”). You can use the same getter / setter / accessor implementation to access multiple fields – using the fieldName parameter passed to the get() and set() methods.

Stopping a timeline

In some cases you will want to stop a running timeline. There are three different APIs that you can use, each with its own semantics:

  • Timeline.abort(). The timeline transitions to the idle state. No application callbacks or field interpolations are done.
  • Timeline.end()new in 1.2. The timeline transitions to the done state, with the timeline position set to 0.0 or 1.0 – based on the direction of the timeline. After application callbacks and field interpolations are done on the done state, the timeline transitions to the idle state. Application callbacks and field interpolations are done on this state as well.
  • Timeline.cancel(). The timeline transitions to the cancelled state, preserving its current timeline position. After application callbacks and field interpolations are done on the cancelled state, the timeline transitions to the idle state. Application callbacks and field interpolations are done on this state as well.

In addition, there is a method to indicate that a looping timeline should stop once it reaches the end of the loop. For example, suppose that you have a pulsating animation of system tray icon to indicate unread messages. Once the message is read, this animation is canceled in the application code. However, immediate cancellation of the pulsating animation may result in jarring visuals, especially if it is done at the “peak” of the pulsation cycle. Calling Timeline.cancelAtCycleBreak() method will indicate that the looping animation should stop once it reaches the end of the loop.

http://farm1.static.flickr.com/187/479222383_bd71636018.jpg

Image by maistora

Every month this series is tracking the latest design trends and collecting the best examples of modern web designs. Here is the list for February 2010 with almost 1400 links from 44 aggregator posts:

The art of writing documentation

February 20th, 2010

From the excellent “Coders at Work” by @peterseibelKen Thompson answers a question on documentation:

Documenting is an art as fine as programming. It’s rare I find documentation at the level I like. Usually it’s much, much finer-grained than need be. It contains a bunch of irrelevancies and dangling references that assume knowledge not there. Documenting is very, very hard; it’s time consuming. To do it right, you’ve got to do it like programming. You’ve got to deconstruct it, put it together in nice ways, rewrite it when it’s wrong. People don’t do that.