/* * Geotoolkit.org - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2009-2012, Open Source Geospatial Foundation (OSGeo) * (C) 2009-2012, Geomatys * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotoolkit.gui.swing.image; import java.awt.Component; import javax.swing.ListSelectionModel; import javax.swing.table.TableColumnModel; import javax.swing.table.TableCellRenderer; import org.jdesktop.swingx.JXTreeTable; import org.jdesktop.swingx.table.TableColumnExt; import org.jdesktop.swingx.renderer.StringValue; import org.jdesktop.swingx.renderer.DefaultTableRenderer; import org.apache.sis.util.ArraysExt; import org.geotoolkit.resources.Vocabulary; import org.geotoolkit.gui.swing.tree.TreeTableNode; import org.geotoolkit.image.io.metadata.MetadataTreeNode; import org.geotoolkit.image.io.metadata.MetadataTreeTable; import org.geotoolkit.internal.swing.table.BooleanRenderer; import org.geotoolkit.internal.swing.table.IdentifiedObjectRenderer; import org.geotoolkit.internal.swing.table.JTables; import org.opengis.referencing.IdentifiedObject; import static org.geotoolkit.image.io.metadata.MetadataTreeTable.COLUMN_COUNT; import static org.geotoolkit.image.io.metadata.MetadataTreeTable.VALUE_COLUMN; /** * The {@code TreeTable} implementation for {@link IIOMetadataPanel}. * * @author Martin Desruisseaux (Geomatys) * @version 3.09 * * @see MetadataTreeTable * * @since 3.05 * @module */ @SuppressWarnings("serial") final class IIOMetadataTreeTable extends JXTreeTable implements StringValue { /** * The currently selected tree node. This is read and set by {@link IIMetadataPanel} in * order to remember the selected item of that particular view when we switch between * different metadata views. */ MetadataTreeNode selectedNode; /** * Renderers for special kind of values. */ private final TableCellRenderer booleanRenderer, identifiedObjectRenderer; /** * Creates a new table for the given table. The given root <strong>must</strong> be * the value returned by {@link MetadataTreeTable#getRootNode()}, or something having * the same structure. * * @param root The output of {@link MetadataTreeTable#getRootNode()}. * @param visibleTable The table which was show prior the invocation of this constructor, or * {@code null} if none. This is used for copying some properties like the columns * positions. */ IIOMetadataTreeTable(final TreeTableNode root, final IIOMetadataTreeTable visibleTable) { super(new Model(root)); ((Model) getTreeTableModel()).owner = this; setRootVisible(false); setColumnControlVisible(true); setDefaultRenderer(Class.class, new DefaultTableRenderer(this)); setSelectionMode(ListSelectionModel.SINGLE_SELECTION); booleanRenderer = new BooleanRenderer(); identifiedObjectRenderer = new IdentifiedObjectRenderer(); /* * Assign programmatic identifiers to the columns, for handling by JTables static * methods. We need to remove the "value" column if there is no such column. */ final TableColumnModel columns = getColumnModel(); int c = columns.getColumnCount(); String[] identifiers = Model.IDENTIFIERS; if (c != COLUMN_COUNT) { identifiers = ArraysExt.remove(identifiers, VALUE_COLUMN, 1); } JTables.setIdentifiers(columns, (Object[]) identifiers); /* * Hide every columns except the one for the names and only one additional column: * * - For IIOMetadataFormat, the type * - For IIOMetadata, the value. * * Note that the "default value" column is empty most of the time anyway. The only * non-null values are usually "false" for the boolean type. The user can select * columns to be made visible with the icon in the upper-right corner. */ if (visibleTable == null) { final int keep = (c == COLUMN_COUNT) ? VALUE_COLUMN : 2; while (--c >= 1) { if (c != keep) { ((TableColumnExt) columns.getColumn(c)).setVisible(false); } } /* * --- MAINTENANCE NOTE: -------------------------------------- * * If the preferred colum width below is modified, consider * updating the preferred panel width in IIOMetadataPanel. */ columns.getColumn(0).setPreferredWidth(240); } else { /* * Just replicate the settings of the previous table. */ JTables.copyConfiguration(visibleTable.getColumnModel(), columns); } } /** * The table model for the {@link javax.imageio.metadata.IIOMetadata} * or {@link javax.imageio.metadata.IIOMetadataFormat}. The columns * are documented in the {@link MetadataTreeTable} javadoc. * * @author Martin Desruisseaux (Geomatys) * @version 3.05 * * @since 3.05 * @module */ private static final class Model extends org.geotoolkit.gui.swing.TreeTableModelAdapter { /** * Columns identifiers for programmatic purpose. * Shall be consistent with {@link #getColumnName}. */ static final String[] IDENTIFIERS = { "name", "description", "type", "occurrence", "value", "default", "validValues" }; /** * The component which own this model. * This is used only for fetching the locale. */ Component owner; /** * Creates a model for the given root. The given root <strong>must</strong> be * the value returned by {@link MetadataTreeTable#getRootNode()}, or something * having the same structure. */ Model(final TreeTableNode root) { super(root); } /** * Returns the name of the given column. The columns shall * matches the ones documented in {@link MetadataTreeTable}. */ @Override public String getColumnName(int column) { final short key; if (column >= VALUE_COLUMN) { column += COLUMN_COUNT - getColumnCount(); // Skip the "values" column if it doesn't exist. } switch (column) { case 0: key = Vocabulary.Keys.Name; break; case 1: key = Vocabulary.Keys.Description; break; case 2: key = Vocabulary.Keys.Type; break; case 3: key = Vocabulary.Keys.Occurrence; break; case VALUE_COLUMN: key = Vocabulary.Keys.Value; break; case 5: key = Vocabulary.Keys.Default; break; case 6: key = Vocabulary.Keys.ValidValues; break; case COLUMN_COUNT: // The later is added only for making sure at compile-time that // we are not declaring more columns than the expected number. default: return super.getColumnName(column); } final Component owner = this.owner; return Vocabulary.getResources(owner != null ? owner.getLocale() : null).getString(key); } } /** * Returns the string representation of a few types to be handled especially. This * is used only when the whole column has the same type, otherwise we need to use * {@link #getCellRenderer(int, int)}. */ @Override public String getString(final Object value) { if (value == null) { return null; } if (value instanceof Class<?>) { return ((Class<?>) value).getSimpleName(); } return value.toString(); } /** * Returns the renderer for the given cell. This method returns a special * renderer for the {@link Boolean} type. */ @Override public TableCellRenderer getCellRenderer(final int row, final int column) { final Object value = getValueAt(row, column); if (value instanceof Boolean) { return booleanRenderer; } if (value instanceof IdentifiedObject) { return identifiedObjectRenderer; } return super.getCellRenderer(row, column); } }