blob: 9dd2914bb54b721e638cdf091ab4b695e5d0a5ba [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.apache.chemistry.opencmis.workbench;
import java.awt.Cursor;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.EnumMap;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Map;
import javax.swing.DropMode;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.TransferHandler;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import org.apache.chemistry.opencmis.client.api.CmisObject;
import org.apache.chemistry.opencmis.client.api.Document;
import org.apache.chemistry.opencmis.client.api.Folder;
import org.apache.chemistry.opencmis.commons.enums.Action;
import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
import org.apache.chemistry.opencmis.commons.enums.UnfileObject;
import org.apache.chemistry.opencmis.workbench.icons.CheckedOutIcon;
import org.apache.chemistry.opencmis.workbench.icons.DocumentIcon;
import org.apache.chemistry.opencmis.workbench.icons.FolderIcon;
import org.apache.chemistry.opencmis.workbench.icons.ItemIcon;
import org.apache.chemistry.opencmis.workbench.icons.PolicyIcon;
import org.apache.chemistry.opencmis.workbench.icons.PwcIcon;
import org.apache.chemistry.opencmis.workbench.icons.RelationshipIcon;
import org.apache.chemistry.opencmis.workbench.model.ClientModel;
import org.apache.chemistry.opencmis.workbench.model.ClientModelEvent;
import org.apache.chemistry.opencmis.workbench.model.FolderListener;
import org.apache.chemistry.opencmis.workbench.swing.GregorianCalendarRenderer;
public class FolderTable extends JTable implements FolderListener {
private static final long serialVersionUID = 1L;
private static final String[] COLUMN_NAMES = { "", "Name", "Type", "Content Type", "Size", "Creation Date",
"Created by", "Modification Date", "Modified by", "Id" };
private static final int[] COLUMN_WIDTHS = { ClientHelper.OBJECT_ICON_SIZE + 4, 200, 150, 150, 80, 180, 100, 180,
100, 300 };
public static final int ID_COLUMN = 9;
private final ClientModel model;
private Map<BaseTypeId, Icon> icons;
private Icon checkedOutIcon;
private Icon pwcIcon;
public FolderTable(final ClientModel model) {
super();
this.model = model;
setModel(new FolderTableModel());
setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
setAutoResizeMode(AUTO_RESIZE_OFF);
setAutoCreateRowSorter(true);
setDefaultRenderer(GregorianCalendar.class, new GregorianCalendarRenderer());
setTransferHandler(new FolderTransferHandler());
setDragEnabled(true);
setDropMode(DropMode.INSERT);
for (int i = 0; i < COLUMN_WIDTHS.length; i++) {
TableColumn column = getColumnModel().getColumn(i);
column.setPreferredWidth(WorkbenchScale.scaleInt(COLUMN_WIDTHS[i]));
}
setRowHeight((int) (getFontMetrics(getFont()).getHeight() * 1.1));
final JPopupMenu popup = new JPopupMenu();
// popup menu: clipboard
final JMenuItem clipboardAllItem = new JMenuItem("Copy all rows to clipboard");
popup.add(clipboardAllItem);
clipboardAllItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ClientHelper.copyTableToClipboard(FolderTable.this, false);
}
});
final JMenuItem clipboardSelectedItem = new JMenuItem("Copy selected rows to clipboard");
popup.add(clipboardSelectedItem);
clipboardSelectedItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ClientHelper.copyTableToClipboard(FolderTable.this, true);
}
});
popup.addSeparator();
// popup menu: delete
final JMenuItem deleteItem = new JMenuItem("Delete");
deleteItem.setEnabled(false);
popup.add(deleteItem);
deleteItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (model.getCurrentObject() != null) {
int answer = JOptionPane.showConfirmDialog(FolderTable.this, "Do you really want to delete '"
+ model.getCurrentObject().getName() + "'?", "Delete", JOptionPane.YES_NO_OPTION,
JOptionPane.WARNING_MESSAGE);
if (answer == JOptionPane.YES_OPTION) {
try {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
if (model.getCurrentObject() instanceof Folder) {
List<String> ids = ((Folder) model.getCurrentObject()).deleteTree(true,
UnfileObject.DELETE, true);
if (ids != null && !ids.isEmpty()) {
StringBuilder sb = new StringBuilder(128);
sb.append("Delete tree failed! At least the following objects could not be deleted:\n");
for (String id : ids) {
sb.append('\n');
sb.append(id);
}
JOptionPane.showMessageDialog(FolderTable.this, sb.toString(), "Delete Tree",
JOptionPane.ERROR_MESSAGE);
}
} else {
model.getCurrentObject().delete();
}
model.reloadFolder();
} catch (Exception ex) {
ClientHelper.showError(FolderTable.this, ex);
return;
} finally {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}
}
}
});
// popup menu: download
final JMenuItem downloadItem = new JMenuItem("Download");
downloadItem.setEnabled(false);
popup.add(downloadItem);
downloadItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (model.getCurrentObject() != null) {
ClientHelper.download(FolderTable.this, model.getCurrentObject(), null);
}
}
});
getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
if (e.getValueIsAdjusting()) {
return;
}
int row = getSelectedRow();
if (row > -1) {
String id = getModel().getValueAt(getRowSorter().convertRowIndexToModel(row), ID_COLUMN).toString();
try {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
model.loadObject(id);
// enable or disable popup menu items
if (model.getCurrentObject() != null && model.getCurrentObject().getAllowableActions() != null) {
CmisObject object = model.getCurrentObject();
deleteItem.setEnabled(object.hasAllowableAction(Action.CAN_DELETE_OBJECT)
|| object.hasAllowableAction(Action.CAN_DELETE_TREE));
downloadItem.setEnabled(object.hasAllowableAction(Action.CAN_GET_CONTENT_STREAM));
} else {
deleteItem.setEnabled(false);
downloadItem.setEnabled(false);
}
} catch (Exception ex) {
ClientHelper.showError(null, ex);
return;
} finally {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}
}
});
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
doAction(e.isShiftDown());
}
}
@Override
public void mousePressed(MouseEvent e) {
maybeShowPopup(e);
}
@Override
public void mouseReleased(MouseEvent e) {
maybeShowPopup(e);
}
private void maybeShowPopup(MouseEvent e) {
if (e.isPopupTrigger()) {
popup.show(e.getComponent(), e.getX(), e.getY());
}
}
});
addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
doAction(e.isShiftDown());
}
}
@Override
public void keyPressed(KeyEvent e) {
}
});
// load icon and set icon column size
loadIcons();
getColumnModel().getColumn(0).setPreferredWidth(
(int) (icons.get(BaseTypeId.CMIS_DOCUMENT).getIconWidth() * 1.1));
}
private void loadIcons() {
icons = new EnumMap<BaseTypeId, Icon>(BaseTypeId.class);
icons.put(BaseTypeId.CMIS_DOCUMENT, new DocumentIcon(ClientHelper.OBJECT_ICON_SIZE,
ClientHelper.OBJECT_ICON_SIZE));
icons.put(BaseTypeId.CMIS_FOLDER, new FolderIcon(ClientHelper.OBJECT_ICON_SIZE, ClientHelper.OBJECT_ICON_SIZE));
icons.put(BaseTypeId.CMIS_RELATIONSHIP, new RelationshipIcon(ClientHelper.OBJECT_ICON_SIZE,
ClientHelper.OBJECT_ICON_SIZE));
icons.put(BaseTypeId.CMIS_POLICY, new PolicyIcon(ClientHelper.OBJECT_ICON_SIZE, ClientHelper.OBJECT_ICON_SIZE));
icons.put(BaseTypeId.CMIS_ITEM, new ItemIcon(ClientHelper.OBJECT_ICON_SIZE, ClientHelper.OBJECT_ICON_SIZE));
checkedOutIcon = new CheckedOutIcon(ClientHelper.OBJECT_ICON_SIZE, ClientHelper.OBJECT_ICON_SIZE);
pwcIcon = new PwcIcon(ClientHelper.OBJECT_ICON_SIZE, ClientHelper.OBJECT_ICON_SIZE);
}
@Override
public void folderLoaded(final ClientModelEvent event) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
event.getClientModel().getCurrentChildren();
((FolderTableModel) getModel()).fireTableDataChanged();
}
});
}
private void doAction(boolean alternate) {
int row = getSelectedRow();
if ((row > -1) && (row < model.getCurrentChildren().size())) {
String id = getModel().getValueAt(getRowSorter().convertRowIndexToModel(row), ID_COLUMN).toString();
CmisObject object = model.getFromCurrentChildren(id);
if (object instanceof Document) {
if (alternate) {
ClientHelper.download(this.getParent(), object, null);
} else {
ClientHelper.open(this.getParent(), object, null);
}
} else if (object instanceof Folder) {
try {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
model.loadFolder(object.getId(), false);
} catch (Exception ex) {
ClientHelper.showError(null, ex);
return;
} finally {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}
}
}
class FolderTableModel extends AbstractTableModel {
private static final long serialVersionUID = 1L;
@Override
public String getColumnName(int columnIndex) {
return COLUMN_NAMES[columnIndex];
}
@Override
public int getColumnCount() {
return COLUMN_NAMES.length;
}
@Override
public int getRowCount() {
return model.getCurrentChildren().size();
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
CmisObject obj = model.getCurrentChildren().get(rowIndex);
switch (columnIndex) {
case 0:
if (obj instanceof Document) {
Document doc = (Document) obj;
if (Boolean.TRUE.equals(doc.isVersionSeriesCheckedOut())) {
if (doc.getId().equals(doc.getVersionSeriesCheckedOutId())) {
return pwcIcon;
} else {
return checkedOutIcon;
}
} else {
return icons.get(BaseTypeId.CMIS_DOCUMENT);
}
}
return icons.get(obj.getBaseTypeId());
case 1:
return obj.getName();
case 2:
return obj.getType().getId();
case 3:
if (obj instanceof Document) {
return ((Document) obj).getContentStreamMimeType();
} else {
return null;
}
case 4:
if (obj instanceof Document) {
return ((Document) obj).getContentStreamLength();
} else {
return null;
}
case 5:
return obj.getCreationDate();
case 6:
return obj.getCreatedBy();
case 7:
return obj.getLastModificationDate();
case 8:
return obj.getLastModifiedBy();
case ID_COLUMN:
return obj.getId();
default:
}
return "";
}
@Override
public Class<?> getColumnClass(int columnIndex) {
switch (columnIndex) {
case 0:
return ImageIcon.class;
case 4:
return Long.class;
case 5:
case 7:
return GregorianCalendar.class;
default:
}
return String.class;
}
}
class FolderTransferHandler extends TransferHandler {
private static final long serialVersionUID = 1L;
public FolderTransferHandler() {
super();
}
@Override
public boolean canImport(TransferSupport support) {
if (!support.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
return false;
}
if (!support.isDrop()) {
return false;
}
return true;
}
@SuppressWarnings("unchecked")
@Override
public boolean importData(TransferSupport support) {
if (!canImport(support)) {
return false;
}
File file = null;
try {
List<File> fileList = (List<File>) support.getTransferable().getTransferData(
DataFlavor.javaFileListFlavor);
if ((fileList == null) || (fileList.size() != 1) || (fileList.get(0) == null)
|| !fileList.get(0).isFile()) {
return false;
}
file = fileList.get(0);
} catch (Exception ex) {
ClientHelper.showError(null, ex);
return false;
}
new CreateDocumentDialog(null, model, file);
return true;
}
@Override
public int getSourceActions(JComponent c) {
return COPY;
}
@Override
protected Transferable createTransferable(JComponent c) {
int row = getSelectedRow();
if ((row > -1) && (row < model.getCurrentChildren().size())) {
String id = getValueAt(row, ID_COLUMN).toString();
CmisObject object = model.getFromCurrentChildren(id);
if (object instanceof Document) {
Document doc = (Document) object;
File tempFile = null;
try {
tempFile = ClientHelper.createTempFileFromDocument(doc, null);
} catch (Exception e) {
ClientHelper.showError(null, e);
}
final File tempTransFile = tempFile;
return new Transferable() {
@Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
return flavor == DataFlavor.javaFileListFlavor;
}
@Override
public DataFlavor[] getTransferDataFlavors() {
return new DataFlavor[] { DataFlavor.javaFileListFlavor };
}
@Override
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
return Collections.singletonList(tempTransFile);
}
};
}
}
return null;
}
}
}