Minimizing TableModel maintenance (continued)


The idea of using enums as column definitions for Swing table models proved to be very valuable. It simplifies the model maintenance immensely. The support class described in previous post was enhanced and now has many more useful methods which are futher simplifying the work with such table model.

The class has following enhancements:

  • Support for cell selection
  • Support for assigning column renderers and editors
  • Conversion of column definitions to column indexes
  • Support for SwingX JXTable colum identifiers

So without any further due, here the code:


public final class TableEnumColumnSupport {

      public interface ITableColumDefinition {
            String getTitle();
      }

      private TableEnumColumnSupport() {}

      /**
       * Finds column definition by index
       * @param <T>
       * @param cls
       * @param index
       * @return
       */
      public final static > T getDefinition( Class cls, int index ) {
            return cls.getEnumConstants()[index];
      }

      /**
       * Returns titles for all column definitions.
       * If column definition implements ITableColumDefinition interface then it's getTitle method is used,
       * else enum name is converted to be used as a title
       * @param <T>
       * @param cls
       * @return
       */
      public final static > String[] getTitles( Class cls ) {

            T[] defs = cls.getEnumConstants();
            String[] titles = new String[defs.length];

            int i=0;
            for( T c: defs) {
               titles[i++] = getTitle(c);
            }
            return titles;

      }

      /**
       * Returns column title for specified colum definition
       * If column definition implements ITableColumDefinition interface then it's getTitle method is used,
       * else enum name is converted to be used as a title
       * @param <T>
       * @param columnDef
       * @return
       */
      public final static > String getTitle(T columnDef) {
            return columnDef instanceof ITableColumDefinition? ((ITableColumDefinition)columnDef).getTitle(): enumToName(columnDef);
      }

      /**
       * Returns column title for specified column index
       * @param <T>
       * @param cls
       * @param columnIndex
       * @return
       */
      public final static > String getTitle( Class cls, int columnIndex ) {
            return getTitle( getDefinition( cls, columnIndex ));
      }

      /**
       * Converts enum to readable column name
       * @param <T>
       * @param columnDef
       * @return
       */
      public static > String enumToName(T columnDef) {
            return columnDef == null? null:
                   StringUtils.capitalize( columnDef.name().replace('_', ' ').toLowerCase());
      }

      /**
       * Selects cell for specified rowIndex and column definition
       * @param <T>
       * @param table
       * @param rowIndex
       * @param columnDef
       */
      public final static > void setSelectedCell(JTable table, int rowIndex, T columnDef) {
            table.changeSelection(rowIndex, columnDef.ordinal(), false, false);
      }

      /**
       * Sets cell editor for specified column definitions in the table
       * @param <T>
       * @param table
       * @param cellEditor
       * @param columnDefs
       * @return
       */
      public final static > JTable setColumnEditor(JTable table, TableCellEditor cellEditor, T... columnDefs) {
            return TableUtils.setColumnEditor(table, cellEditor, toIndexes(columnDefs));
      }

      /**
       * Sets cell renderer for specified column definitions in the table
       * @param <T>
       * @param table
       * @param cellRenderer
       * @param columnDefs
       * @return
       */
      public final static > JTable setColumnRenderer(JTable table, TableCellRenderer cellRenderer, T... columnDefs) {
            return TableUtils.setColumnRenderer(table, cellRenderer, toIndexes(columnDefs));
      }

      /**
       * Converts column definitions to an array of actual column indexes
       * @param <T>
       * @param columnDefs
       * @return
       */
      public final static > int[] toIndexes(Collection columnDefs) {
            int[] colIndexes = new int[columnDefs.size()];
            int i = 0;
            for( T def: columnDefs ) {
                  colIndexes[i++] = def.ordinal();
            }
            return colIndexes;
      }

      /**
       * Converts column definitions to an array of actual column indexes
       * @param <T>
       * @param columnDefs
       * @return
       */
      public final static > int[] toIndexes(T... columnDefs) {
            return toIndexes( Arrays.asList(columnDefs));
      }

      /**
       * Returns table column for specified colum definition
       * @param <T>
       * @param table
       * @param columnDef
       * @return
       */
      public final static > TableColumn getColumn( JTable table, T columnDef ) {
            return table.getColumnModel().getColumn( columnDef.ordinal());
      }

       /**
     * Sets the identifiers on the table columns to match the specified column definition.
     * This will allow to use getTableColumn(Obj id) to retrieve cols.  This is preferrable to
     * using indexes (not reliable-when hiding/showing cols) or the header string (which is not reliable b/c of renderers).
     */
      public final static > void setColumnIdentifiers( JXTable table, Class cls ) {
          TableColumnModel columnModel = table.getColumnModel();
          Enumeration cols = columnModel.getColumns();
          for (Object c : cls.getEnumConstants())
          {
              cols.nextElement().setIdentifier( c );
          }
      }

}

Advertisements

2 comments

    • @Martin Sorry for references to external classes, but I figured they are obvious simplifications of JTable API. TableUtils.setColumnEditor/TableUtils.setColumnRederer sets editor/renderer for group of columns. Just one line instead of looping through columns. StringUtils.capitalize should be obvious too. The idea is to show how table model maitenance can be greatly simplified with such a utility class.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s