RvSnoop: April 2006 Archives

Dynamic Date Formatting

|

I’ve noticed a neat feature in Path Finder where it changes the date format used to display time stamps in the main table based on the width of the column. In rvSnoop I was allowing the user to set a preferred format as a configuration option, but this seems much better.

It turns out that this is pretty easy to achieve in Java, just use the following class:

private static class DateCellRenderer extends DefaultTableCellRenderer {
    // Or load these from a user preference...
    private static final DateFormat[] FORMATS = {
        new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"),
        new SimpleDateFormat("yy-MM-dd HH:mm:ss.SSS"),
        new SimpleDateFormat("MM/dd HH:mm:ss.SSS"),
        new SimpleDateFormat("HH:mm:ss.SSS"),
        new SimpleDateFormat("HH:mm:ss.SS"),
        new SimpleDateFormat("HH:mm:ss.S"),
        new SimpleDateFormat("HH:mm:ss"),
        new SimpleDateFormat("HH:mm") };
    private int currentWidth;
    private Font currentFont;
    private DateFormat currentFormat;
    public Component getTableCellRendererComponent(JTable table, Object value,
            boolean isSelected, boolean hasFocus, int row, int col) {
        final DateFormat format = getFormat(table.getColumnModel().getColumn(col).getWidth(), table);
        final String displayed = value != null ? format.format((Date) value) : "";
        return super.getTableCellRendererComponent(table, displayed, isSelected, hasFocus, row, col);
    }
    private DateFormat getFormat(int width, JTable table) {
        final Font font = table.getFont();
        if (currentWidth != width) currentFormat = null;
        if (currentFont == null || !currentFont.equals(font)) currentFormat = null;
        if (currentFormat == null) {
            currentWidth = width;
            currentFont = font;
            final Date date = new Date();
            final FontMetrics metrics = table.getFontMetrics(font);
            for (int i = 0, imax = FORMATS.length; i < imax; ++i) {
                final int dateWidth = metrics.stringWidth(FORMATS[i].format(date));
                if (dateWidth < width) {
                    currentFormat = FORMATS[i];
                    break;
                }
            }
            if (currentFormat == null) {
                currentFormat = FORMATS[FORMATS.length - 1];
            }
        }
        return currentFormat;
    }
}

rvSnoop

| | Comments (0)

I’ve taken over pretty much all of the development of the rvSnoop utility now, the first major new release has been put out today with a number of changes in it. Here, briefly, are the plans for the next few versions:

  • A graphical widget to display messages instead of the text field.

  • More import/export formats for messages.

  • General user interface clean-up.

  • Better documentation.

I’ll have more plans once I get to know the code a little better.