/* * Copyright (C) 2010 Brockmann Consult GmbH (info@brockmann-consult.de) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 3 of the License, or (at your option) * any later version. * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see http://www.gnu.org/licenses/ */ package org.esa.snap.ui.product; import org.esa.snap.core.datamodel.ProductNode; import org.esa.snap.core.datamodel.ProductNodeEvent; import org.esa.snap.core.datamodel.ProductNodeListener; import org.esa.snap.core.datamodel.VectorDataNode; import org.esa.snap.core.util.SystemUtils; import org.esa.snap.ui.BasicView; import org.esa.snap.ui.PopupMenuHandler; import org.esa.snap.ui.io.TableModelCsvEncoder; import org.openide.util.Utilities; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.JLabel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; import javax.swing.table.TableRowSorter; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Cursor; import java.awt.event.ActionEvent; import java.awt.event.MouseEvent; import java.io.IOException; import java.io.StringWriter; import java.util.Enumeration; import java.util.List; /** * A view component used to display a product's metadata in tabular form. */ public class ProductPlacemarkView extends BasicView implements ProductNodeView { private VectorDataNode vectorDataNode; private final PlacemarkTableModel tableModel; public ProductPlacemarkView(VectorDataNode vectorDataNode) { this.vectorDataNode = vectorDataNode; this.vectorDataNode.getProduct().addProductNodeListener(new PNL()); tableModel = new PlacemarkTableModel(); JTable placemarkTable = new JTable(); placemarkTable.setRowSorter(new TableRowSorter<>(tableModel)); placemarkTable.addMouseListener(new PopupMenuHandler(this)); placemarkTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); placemarkTable.setModel(tableModel); final TableCellRenderer renderer = placemarkTable.getTableHeader().getDefaultRenderer(); final int margin = placemarkTable.getTableHeader().getColumnModel().getColumnMargin(); Enumeration<TableColumn> columns = placemarkTable.getColumnModel().getColumns(); while (columns.hasMoreElements()) { TableColumn tableColumn = columns.nextElement(); final int width = getColumnMinWith(tableColumn, renderer, margin); tableColumn.setMinWidth(width); } final JScrollPane scrollPane = new JScrollPane(placemarkTable); setLayout(new BorderLayout()); add(scrollPane, BorderLayout.CENTER); } public VectorDataNode getVectorDataNode() { return vectorDataNode; } /** * Returns the currently visible product node. */ @Override public ProductNode getVisibleProductNode() { return vectorDataNode; } @Override public JPopupMenu createPopupMenu(Component component) { JPopupMenu popupMenu = new JPopupMenu(); List<? extends Action> viewActions = Utilities.actionsForPath("Context/ProductPlacemarkView"); for (Action action : viewActions) { popupMenu.add(action); } popupMenu.add(new CopyToClipboardAction()); return popupMenu; } @Override public JPopupMenu createPopupMenu(MouseEvent event) { return null; } private int getColumnMinWith(TableColumn column, TableCellRenderer renderer, int margin) { final Object headerValue = column.getHeaderValue(); final JLabel label = (JLabel) renderer.getTableCellRendererComponent(null, headerValue, false, false, 0, 0); return label.getPreferredSize().width + margin; } private void onNodeChange(ProductNodeEvent event) { ProductNode sourceNode = event.getSourceNode(); if (sourceNode == vectorDataNode) { updateTable(); } else if (sourceNode.getOwner() == vectorDataNode.getPlacemarkGroup()) { updateTable(); } } private class PlacemarkTableModel extends AbstractTableModel { @Override public int getRowCount() { return vectorDataNode.getPlacemarkGroup().getNodeCount(); } @Override public int getColumnCount() { return vectorDataNode.getFeatureType().getAttributeCount(); } @Override public String getColumnName(int columnIndex) { return vectorDataNode.getFeatureType().getDescriptor(columnIndex).getLocalName(); } @Override public Class<?> getColumnClass(int columnIndex) { return vectorDataNode.getFeatureType().getDescriptor(columnIndex).getType().getBinding(); } @Override public Object getValueAt(int rowIndex, int columnIndex) { return vectorDataNode.getPlacemarkGroup().get(rowIndex).getFeature().getAttribute(columnIndex); } } private class PNL implements ProductNodeListener { @Override public void nodeChanged(ProductNodeEvent event) { onNodeChange(event); } @Override public void nodeDataChanged(ProductNodeEvent event) { onNodeChange(event); } @Override public void nodeAdded(ProductNodeEvent event) { onNodeChange(event); } @Override public void nodeRemoved(ProductNodeEvent event) { onNodeChange(event); } } private void updateTable() { tableModel.fireTableDataChanged(); } private void copyTextDataToClipboard() { final Cursor oldCursor = getCursor(); try { setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); final String dataAsText = getDataAsText(); if (dataAsText != null) { SystemUtils.copyToClipboard(dataAsText); } } finally { setCursor(oldCursor); } } private String getDataAsText() { final StringWriter writer = new StringWriter(); try { new TableModelCsvEncoder(tableModel).encodeCsv(writer); writer.close(); } catch (IOException ignore) { } return writer.toString(); } private class CopyToClipboardAction extends AbstractAction { public CopyToClipboardAction() { super("Copy to clipboard"); putValue(SHORT_DESCRIPTION, "The entire table content will be copied to the clipboard."); } @Override public void actionPerformed(ActionEvent e) { copyTextDataToClipboard(); } } }