So what now, Stig?

Reading about the BBC’s failed attempts in the High Court to stop publisher HarperCollins outing Top Gear’s Stig as ex-racing driver Ben Collins in his new autobiography, there has been lots of talk of the BBC’s anger at the publisher, but I’ve not read anything about their relationship with Ben Collins himself.

It’s been mentioned that there were obvious confidentiality agreements in place which have now been breached, but I don’t quite understand why the focus of the anger seems to have been towards HarperCollins and not Ben Collins – it’s him that has broken the agreement, not the publisher. Or am I missing something? Maybe it’s just the way it has been reported, or the way I’ve interpreted it.

So where does that leave The Stig? I’m assuming Collins will lose the gig (man, what a job!). Will The Stig be killed off again as happened with the original driver in the role, Perry McCarthy?

Maybe I should get myself a firesuit and Simpson helmet with black visor and send my CV in… 😉

Substance custom table cell renderers

I use the Substance Look & Feel in most of my Java Swing GUIs these days. It’s a very well engineered, mature, configurable implementation of a Swing look & feel which can transform the appearance of any Swing GUI. The author Kirill Grouchnikov has done a great job with it over the years and I’d like to thank him for his work on this project (and his other projects such as the Trident animation library and Flamingo component suite).

Although Substance is extremely configurable, one area that I’ve had problems with in the past is that of custom table cell renderers. Substance provides default renderers for common cell value classes such as strings, numbers, booleans etc. which covers most use cases. However, if you want to customise the cell renderer behaviour and still benefit from all of the Substance effects such as row striping, selection highlighting animation etc. you’re quite limited because Substance enforces that your custom renderer is sub-classed from the SubstanceDefaultTableCellRenderer, which itself sub-classes DefaultTableCellRenderer. This is fine as long as your custom renderer is happy to be, effectively, a sub-class of JLabel, but for anything involving custom painting it’s no good.

This is one area that I think Substance could possibly be improved to make it a bit more extensible and flexible.

One specific situation I encountered this problem with recently was where I wanted to display a mini bar-chart in a table cell. The actual custom bar component was a trivial amount of custom painting but I couldn’t see an easy way of getting this into a Substance table cell renderer. I tried creating a simple cell renderer which extended the bar component and implemented the obligatory TableCellRenderer interface, and although this worked to a degree, I lost all of the nice Substance effects mentioned above by virtue of the fact that the renderer wasn’t derived from SubstanceDefaultTableCellRenderer. I managed to get row background striping back quite easily by calling the SubstanceStripingUtils.applyStripedBackground() method but that wasn’t good enough.

Then I had a mini flash of inspiration triggered when I noticed that Substance provided a default renderer for icons…

Because the Substance default renderer is based on a label, I could set the icon property to an implementation of the javax.swing.Icon interface to get my custom painting “injected” into the renderer. The steps involved were:

  1. Make my custom bar component implement the Icon interface. This was simply a case of moving my custom painting code from the paintComponent method to paintIcon and also providing implementations of the getIconWidth and getIconHeight methods.
  2. Create a simple SubstanceDefaultTableCellRenderer sub-class which wraps an instance of my bar component. In the renderer constuctor I call setIcon to attach the bar component to the renderer. The renderer also needs to override the two setBounds methods so that it can set the size of the wrapped bar component, otherwise it wouldn’t resize with the table cell! Oh, and of course an overridden setValue method needs to update the wrapped bar component value as appropriate.

As a result, my two classes looked something like this:

BarIconComponent

package com.purplegem.substanceplay;

import javax.swing.*;
import java.awt.*;

/**
 * Simple custom component which renders a mini bar chart.
 * Implements the Icon interface so it can be used where an Icon can.
 */
public class BarIconComponent extends JComponent implements Icon {

  private double value = 0.5d;

  public BarIconComponent() {
    setSize(40, 20);
  }

  public double getValue() {
    return value;
  }

  public void setValue(double value) {
    this.value = value;
  }

  @Override
  public void paintIcon(Component c, Graphics g, int x, int y) {
    Graphics2D g2 = (Graphics2D) g;
    g2.setColor(Color.GREEN);
    g2.fillRect(0, 0, (int) (getIconWidth() * value), getIconHeight());
  }

  @Override
  public int getIconWidth() {
    return getWidth();
  }

  @Override
  public int getIconHeight() {
    return getHeight();
  }

  @Override
  protected void paintComponent(Graphics g) {
    paintIcon(this, g, 0, 0);
  }

}

BarCellRenderer

package com.purplegem.substanceplay;

import org.pushingpixels.substance.api.renderers.SubstanceDefaultTableCellRenderer;

import java.awt.*;

/**
 * Custom Substance table cell renderer which renders a mini bar
 * chart using the wrapped BarIconComponent instance
 */
public class BarCellRenderer extends SubstanceDefaultTableCellRenderer {

  private BarIconComponent barComponent = new BarIconComponent();

  public BarCellRenderer() {
    // attach our bar component as an icon
    setIcon(barComponent);
  }

  @Override
  public void setBounds(int x, int y, int width, int height) {
    super.setBounds(x, y, width, height);
    // ensure we update the size of the wrapped bar component
    barComponent.setSize(width, height);
  }

  @Override
  public void setBounds(Rectangle r) {
    super.setBounds(r);
    // ensure we update the size of the wrapped bar component
    barComponent.setSize((int) r.getWidth(), (int) r.getHeight());
  }

  @Override
  protected void setValue(Object value) {
    if (value != null) {
      // update the value of the bar component for this particular table cell
      barComponent.setValue((Double) value);
    }
  }

}

Once I’d implemented all of this I then had exactly the result I was expecting – a mini bar chart in a table cell with all the expected Substance table cell effects 🙂

Uploading files using scp and the Maven Wagon plugin

I’ve been struggling with a little Maven problem for a while but only just managed to find time to look into it in any detail. What I’ve been trying to do is copy an artifact to a remote server using scp. The artifact in question is a WAR which I want to copy to a server hosting Tomcat, so this is not a typical deploy-artifact-to-repository type of requirement.

(As an aside, I know all about the Cargo plugin for deploying web apps to servlet containers but in this instance I’m more interested in the more general issue of copying any artifact, be it a WAR or a JAR or something else, using scp)

In principle this sounds like a very simple thing to do. The Maven Wagon plugin is the tool for the job but the documentation is woefully inadequate and I just could not get it to do what I wanted.

Anyway, after a lot of Googling and, crucially, inspecting Maven debug output from failed attempts at using the plugin I’ve finally cracked it.

Everything I’d seen written about this involved the following aspects…

Configuring details about the server to be copied to (typically in your main Maven settings.xml configuration):

<server>
  <serverId>my-server-id</serverId>
  <user>my-user-name</user>
  <password>my-password</password>
</server>

Using the Wagon plugin to perform the actual copy:

<build>
  <extensions>
    <extension>
       <groupId>org.apache.maven.wagon</groupId>
       <artifactId>wagon-ssh</artifactId>
       <version>1.0-beta-6</version>
     </extension>
   </extensions>

   <plugins>
     <plugin>
       <groupId>org.codehaus.mojo</groupId>
       <artifactId>wagon-maven-plugin</artifactId>
       <version>1.0-beta-3</version>
       <configuration>
         <fromFile>${project.build.directory}/${project.build.finalName}.war</fromFile>
         <url>scp://my-server-id.fully.qualified.domain/path/to/destination</url>
       </configuration>
       <executions>
         <execution>
           <id>upload-war-to-server</id>
           <phase>deploy</phase>
           <goals>
             <goal>upload-single</goal>
           </goals>
         </execution>
       </executions>
     </plugin>
   </plugins>

 </build>

All looks logical… but it simply refused to work, complaining about authentication failures. I knew the corresponding <server> configuration block was using the correct username and password, so the symptoms suggested that it wasn’t finding the <server> configuration. I’d made sure the host part of the server domain in the scp:// URL matched the server id element but it just wouldn’t match them up.

And then I noticed something in the Wagon plugin’s debug output – mention of a serverId property in the configuration. I’d not seen this documented anywhere before, but I thought I’d try adding it to my Wagon plugin configuration all the same…

      <configuration>
        <serverId>my-server-id</serverId></pre>
        <fromFile>${project.build.directory}/${project.build.finalName}.war</fromFile>
        <url>scp://my-server-id.fully.qualified.domain/path/to/destination</url>
      </configuration>

…and all of a sudden it started working! So, in my situation that appears to have been the missing link between my Wagon plugin and the server configuration details.