/*******************************************************************************
* Mission Control Technologies, Copyright (c) 2009-2012, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* The MCT platform is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
* MCT includes source code licensed under additional open source licenses. See
* the MCT Open Source Licenses file included with this distribution or the About
* MCT Licenses dialog available at runtime from the MCT Help menu for additional
* information.
*******************************************************************************/
package gov.nasa.arc.mct.table.dnd;
import gov.nasa.arc.mct.components.AbstractComponent;
import gov.nasa.arc.mct.gui.View;
import gov.nasa.arc.mct.services.component.ViewType;
import gov.nasa.arc.mct.table.gui.LabeledTable;
import gov.nasa.arc.mct.table.model.ComponentTableModel;
import gov.nasa.arc.mct.table.model.LabeledTableModel;
import gov.nasa.arc.mct.table.view.TableViewManifestation;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JTable;
import javax.swing.TransferHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Implements a drag-and-drop transfer handler for the tabular data views.
* The transfer method is compatible with that of the MCT directory area:
* the data flavor is an array of view roles.
*/
public class TableTransferHandler extends TransferHandler {
private static final long serialVersionUID = 1;
private static final Logger logger = LoggerFactory.getLogger(TableTransferHandler.class);
private TableViewManifestation manifestation;
private LabeledTable table;
/**
* Creates a new transfer handler for a table and a manifestation of that table.
*
* @param manifestation the table view manifestation
* @param table the labeled table being shown in the view manifestation
*/
public TableTransferHandler(TableViewManifestation manifestation, LabeledTable table) {
this.manifestation = manifestation;
this.table = table;
}
@Override
public boolean canImport(TransferSupport support) {
JTable.DropLocation location = (javax.swing.JTable.DropLocation) support.getDropLocation();
boolean result = internalCanImport(support.getDataFlavors(), location.getRow(), location.getColumn(),
location.isInsertRow(), location.isInsertColumn());
support.setShowDropLocation(result);
return result;
}
private boolean internalCanImport(DataFlavor[] flavors, int row, int column, boolean isInsertRow, boolean isInsertColumn) {
// We can only import view roles, usually from the directory tree
// or from a table cell.
if (flavors.length < 1 || flavors[0].getRepresentationClass() != View.class) {
return false;
}
// Ask the model whether a value can be dropped at the location.
LabeledTableModel model = LabeledTableModel.class.cast(table.getTable().getModel());
return model.canSetValueAt(row, column, isInsertRow, isInsertColumn);
}
@Override
protected Transferable createTransferable(JComponent c) {
// We must have at least one selected row.
if (table.getSelectedRows().length==0 || table.getSelectedColumns().length==0) {
return null;
}
// Add a node view role for each selected component.
List<View> views = new ArrayList<View>();
ComponentTableModel model = ComponentTableModel.class.cast(table.getTable().getModel());
for (int rowIndex : table.getSelectedRows()) {
for (int columnIndex : table.getSelectedColumns()) {
AbstractComponent component = (AbstractComponent) model.getStoredValueAt(rowIndex, columnIndex);
if (component != null) {
View view = component.getViewInfos(ViewType.NODE).iterator().next().createView(component);
if (view != null) {
views.add(view);
}
}
}
}
// If we didn't find any applicable roles, just return null so that we
// don't allow the drag.
if (views.isEmpty()) {
return null;
}
return new ViewRoleSelection(views.toArray(new View[views.size()]));
}
@Override
public int getSourceActions(JComponent c) {
return TransferHandler.LINK;
}
@Override
public boolean importData(TransferSupport support) {
JTable.DropLocation location = (JTable.DropLocation) support.getDropLocation();
int row = location.getRow();
int column = location.getColumn();
boolean isInsertRow = location.isInsertRow();
boolean isInsertColumn = location.isInsertColumn();
View[] sourceViewRoles;
try {
sourceViewRoles = (View[]) support.getTransferable().getTransferData(View.DATA_FLAVOR);
} catch (UnsupportedFlavorException e) {
logger.error("Unexpected drop flavor", e);
return false;
} catch (IOException e) {
logger.error("Exception getting dropped data", e);
return false;
}
try {
return manifestation.handleDrop(sourceViewRoles, row, column, isInsertRow, isInsertColumn);
} catch (Exception e) {
logger.error("Unexpected error during drop", e);
return false;
}
}
}