Over the course of the next few days i’m going to talk about different concepts in the Trident animation library for Java applications. Part two talks about APIs to interpolate primitive and non-primitive fields of Java objects.
Interpolation of primitive fields
A timeline allows changing field values of the associated object. For example, in a fade-in animation the timeline will interpolate the value of alpha
field from 0.0
to 1.0
. There are two steps involved in setting up such timeline.
The first step is to create a Timeline
instance passing the main object. The timeline is then configured to interpolate one or more fields of this main object. Let’s see a simple example:
import org.pushingpixels.trident.Timeline;
public class HelloWorld {
private float value;
public void setValue(float newValue) {
System.out.println(this.value + " -- " + newValue);
this.value = newValue;
}
public static void main(String[] args) {
HelloWorld hello = new HelloWorld();
Timeline timeline = new Timeline(hello);
timeline.addPropertyToInterpolate("value", 0.0f, 1.0f);
timeline.play();
try {
Thread.sleep(3000);
} catch (Exception exc) {
}
}
}
Here, the timeline has the associated HelloWorld
instance; this timeline is instructed to interpolate the value
field of that instance from 0.0
to 1.0
over the duration of the timeline.
There is an important assumption that the application code must honor. Each field added with the addPropertyToInterpolate
must have the matching public setter.
A timeline can interpolate multiple fields. In the following example the timeline will change values of three fields at each timeline pulse:
Timeline timeline = new Timeline(circle);
timeline.addPropertyToInterpolate("x", initX, finalX);
timeline.addPropertyToInterpolate("y", initY, finalY);
timeline.addPropertyToInterpolate("opacity", 1.0f, 0.0f);
Interpolating non-primitive fields
In addition to interpolating primitive fields, the Timeline.addPropertyToInterpolate
APIs allow the application code to interpolate fields of other types. Each interpolation is using the matching property interpolator that implements the org.pushingpixels.trident.interpolator.PropertyInterpolator
interface:
public interface PropertyInterpolator {
public Class getBasePropertyClass();
public T interpolate(T from, T to, float timelinePosition);
}
The interpolate
method is used at each timeline pulse to compute the interpolated value. To interpolate a field using the specific property interpolator call the following Timeline
API:
addPropertyToInterpolate(String, Object, Object, PropertyInterpolator)
The parameters are:
- The field name.
- The start value.
- The end value.
- The property interpolator.
Note that the application is responsible to make sure that the object passed to the timeline constructor has a public setter accepting the interpolated value returned by the interpolate
implementation of this property interpolator.
The PropertyInterpolator.getBasePropertyClass
is not used when the application code explicitly passes the property interpolator – and it is safe to return any value (including null
) from it. This method is used only during dynamic lookup of custom property interpolators.
Additional interpolation capabilities
The addPropertyToInterpolate
API above is used to interpolate a specific field from the given start value to the given end value. Application code can also use the following variations of this API:
-
addPropertyToInterpolate(Object, String, Object, Object)
– to interpolate the specified field of an object different from the main timeline object. This object is passed as the first parameter to this method
-
addPropertyToInterpolate(Object, String, Object, Object, PropertyInterpolator)
– to interpolate the specified field of an object different from the main timeline object using the specified property interpolator
When the start value is not known at timeline initialization time, the following APIs can be used to interpolate the field from its current value (as known at runtime) to the specified end value:
-
addPropertyToInterpolateTo(String, Object)
– to interpolate the specified field of the main timeline object
-
addPropertyToInterpolateTo(Object, String, Object)
– to interpolate the specified field of an object different from the main timeline object. This object is passed as the first parameter to this method
-
addPropertyToInterpolateTo(Object, String, Object, PropertyInterpolator)
– to interpolate the specified field of an object different from the main timeline object using the specified property interpolator
Over the course of the next few days i’m going to talk about different concepts in the Trident animation library for Java applications. Part one introduces the “Hello world” example.
Timeline is the most important concept in Trident. Here is a simple example that illustrates the basic timeline terms:
import org.pushingpixels.trident.Timeline;
public class HelloWorld {
private float value;
public void setValue(float newValue) {
System.out.println(this.value + " -- " + newValue);
this.value = newValue;
}
public static void main(String[] args) {
HelloWorld hello = new HelloWorld();
Timeline timeline = new Timeline(hello);
timeline.addPropertyToInterpolate("value", 0.0f, 1.0f);
timeline.play();
try {
Thread.sleep(3000);
} catch (Exception exc) {
}
}
}
- We import the
org.pushingpixels.trident.Timeline
class.
- We define a private float attribute of this class, and provide a public setter for this attribute.
- We create a new instance of our test class and a timeline associated with that instance.
- We specify that the
value
attribute of that instance should be interpolated from 0.of
to 1.0f
when the timeline is played.
- Finally, we play the timeline.
- The
Thread.sleep(3000)
makes sure that the application waits long enough for the timeline to finish playing
Here is the output of this application:
0.0 -- 0.0
0.0 -- 0.436
0.436 -- 0.514
0.514 -- 0.594
0.594 -- 0.672
0.672 -- 0.75
0.75 -- 0.828
0.828 -- 0.906
0.906 -- 0.984
0.984 -- 1.0
1.0 -- 1.0
Note that the actual numbers depend on the current system load. The setter is called by the timeline at timeline pulses. A timeline pulse is the point where the timeline “wakes up” and changes the values of all registered fields. The values are changed based on how much time has passed since the timeline has started playing.
The three basic timeline concepts illustrated in this sample are:
- A timeline is associated with an object.
- A timeline interpolates values of object fields using the public setters of the relevant class.
- The field values are changed at timeline pulses.
One of the best presentations I’ve heard at this year’s EclipseCon was given by Alexandra Imrie on the topic of usability. Usability is sometimes abandoned altogether due to budget constraints, often addressed as a hasty afterthought, and almost never viewed by developers as a necessity. In this interview Alex looks at the usability angle from the end user perspective, highlighting its importance to us, the developers.
Tell us a little bit about yourself
I’m Alex Imrie, and I work at BREDEX GmbH in Braunschweig, Germany. I have various roles at the company including Marketing, customer demonstrations, training and support as well as documentation and conceptual design for some of our software. I also do some testing. The unifying part of all these roles is that I represent the user and customer side – I have a non-technical background in linguistics, but a good knowledge of how to work with our software from the user’s perspective, so that makes me a good advocate for our users and customers!
What does usability mean to you?
The main aspect of usability for me is that software should help the user to do his job, not make the job harder! The application as a whole should be consistent in its work-flows and allow the user to work in different ways (and each way should be as simple as possible). The software should adapt to the user, not vice-versa. I also believe that most applications shouldn’t involve the user in internal technical aspects. The user should be able to work with the software without knowing how it ticks in the background.
Even if a piece of software is well written in these terms, we need ways of helping new users with the software. From context-sensitive help to tutorials and examples, it should be easy to find out more about the application without having to read the whole manual or attend weeks of training. Obviously, training may be necessary for some applications, or to learn how to work best with an application, but it shouldn’t be necessary from the very outset.
Why should developers be aware of usability aspects of the products they’re creating?
I think the very simple answer is because the products are meant to be used by the users! Whether the users themselves are developers or not, we always need to bear the target group in mind when an application is being designed, or when new areas are being added. Features are all very well and good, but if the application is hard to understand or hard to use, then users will be alienated and annoyed. In terms of commercial software, this can lead to dissatisfied users – and word of mouth about bad software can spread quickly.
Can usability be sacrificed for internal products that people will have to use in any case?
On the contrary, I think that internal products can be a good way to practice making software more usable. After all, internal feedback can be quickly incorporated into the product and developers can really get the chance to see how users think. Internal users are still users at the end of the day, and deserve to have an application that will make their life easier, not more frustrating! Another way to think of this is in terms of the support costs your team will save by not having to answer “basic” questions about how to use the software. In smaller companies especially, making usable software can be conducive to good relations between developers and users. Making usability a priority internally brings value for external products. The design process will no longer separate functionality from usability – all functions will be designed to be usable right from the start. The benefits are endless, really.
Why is usability at best an afterthought, and in most cases non-existent in business applications?
On the one hand, it’s often very difficult to see things from the user’s perspective. Developers think like developers, and rightly so. It’s just very difficult to put yourself into someone else’s shoes and forget all you know about the internal workings of something. (This is the same reason that developers aren’t necessarily good as functional testers!).
The other issue is time and costs. If usability isn’t explicitly considered at the beginning, it can be harder to add later when the need arises. With deadlines for features and releases, it can be hard to make the decision to lose a feature to gain usability. I think that too much time is often spent working out how a feature should work technically, and not how the user should be able to access it, even though the two aspects actually belong together.
What are the most common usability errors that you see in popular applications?
One thing I notice quite frequently is inconsistent behaviour. Like some delete actions requiring confirmation and others not. Or options being available in a context menu in one area, but not in another. This also affects menus where certain entries are completely missing instead of just disabled when they are not available. That can be confusing!
These are also quite minimal things that can easily be changed. I like knowing where I am in a workflow – what are the prerequisites, and what must I do next. I appreciate progress dialogs for so I can see how much longer I need to wait, and which reassure me that the application hasn’t crashed. I also find it difficult to work with applications that only offer one way of doing things. I’m a fan of using keyboard shortcuts, so a mouse-only application can be frustrating.
Do we need to facilitate an emotional connection between the users and the ap-plications?
I think so. I think that a user should feel “led” by an application, and should feel safe in the knowledge that the application will not let him or her do anything horribly wrong. One concept we use quite extensively at Bredex is the idea of the “first 15 minutes”. I think this can be where a large part of the emotional connection comes from. At the very least, these first fifteen minutes should be the easiest, and there should be no way at all of running into trouble. Layout and graphics can play a large part in making an application simply look more friendly, and I’m particularly fond of welcome screens, like those in the Eclipse framework, to present important information in an accessible way at the start up of an application.
Do we still need manuals and organized help in the age of wikis, blogs, forums and mailing lists?
Yes, I believe we do. The idea of the documentation as a wiki is certainly appealing, but I think there is still a place for manuals. Wikis are certainly more dynamic, but this can be a problem – with manuals, you can always tell which version of a software the manual is for. For me, the appeal of a manual is having one single source of reference for all of the possibilities of a piece of software. As well as describing tasks, a manual can also introduce best practices and can be directly integrated into the software as context sensitive help to save trawling through a forum or waiting for an answer in a mailing list. Media like mailing lists and forums certainly have their place, but I see them more as a place to ask very specific questions, whereas the manual should deal with the various tasks you can do with the program and the concepts of the software.
No documentation, and the users will be upset. A lot of documentation and nobody will read it. How to find the “sweet spot”?
If I knew the answer to this question I’d be rich! Seriously, I think that a task-oriented approach to the documentation is the best way to go. For each task, pre- and post-requisites as well as related tasks should be linked. This makes searching for the piece of the documentation considerably easier. I also think it’s important to reduce the amount of explaining the documentation has to do. If the technical writer is spending days trying to get a section right, it’s a sure sign that the application itself is too compli-cated. If each and every text field has to be explained, that’s a hint that the labels for the text fields aren’t very good. Documentation is necessary, but it shouldn’t become an issue of “XYZ doesn’t work like ABC, so we’ll document it instead of fixing it”.
Is there anything else you’d like to add?
One thing we have found works well for us in making sure that usability is considered from the outset is to have the technical writer(s) (and also the testers) present at the design and concept meetings. These are usually the people who can tell you “that’s not how it works in other areas” or “that’s not clear enough” or even “why not do it another way”. By not having the same background and perspective as the developers, they can offer valuable advice for the usability of an application.
Release 5.2 of Substance look-and-feel made a few visual changes to the Raven Graphite skins, but these did not address the overall usability of these skins – especially the contrast between the background and the controls, and the background / foreground contrast of text components.
The latest drop of version 5.3dev (code named Reykjavik) features significant overhaul of both Raven Graphite skins, aiming to address the contrast usability issues raised by the users.
Here is a screenshot of a sample application under the Raven Graphite skin in the latest stable 5.2 release:

And here is the same application under the 5.3dev drop:

Here is another screenshot of the same application under the old Raven Graphite visuals:

and the new visuals under the latest 5.3dev drop:

The main changes are:
- Removing the watermark that contributed significant visual noise
- Darker border color for controls, bringing more delineation to check boxes and radio buttons
- Darker background color for text components, resulting in better readability
The same changes were made for the Raven Graphite Glass skin. Here is the sample application under the stable 5.2 release:

and here is the same application under the latest 5.3dev drop:

In addition to the visual changes above, the Raven Graphite Glass skin has removed the glass arc gradient from the toolbars and added a two-tone separator to delineate the title bar / menu bar from the rest of the application content.
To illustrate the visual difference in a larger content, here is a screenshot of a big UI under the stable 5.2 release (click to see the full-size view):

and the same application under the 5.3dev branch:

If you want to take the new visuals for a spin, click on the WebStart button below and change the skin to Raven Graphite and Raven Graphite Glass from the “Skins” menu:

You’re more than welcome to take the latest 5.3dev drop for a spin and leave your comments.