/* * * * This file is part of Artemis * * Copyright(C) 2006 Genome Research Limited * * 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 2 * 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ package uk.ac.sanger.artemis.components.filetree; import javax.swing.*; import javax.swing.tree.*; import javax.swing.table.*; import javax.swing.filechooser.FileSystemView; import java.io.File; import java.io.IOException; import java.awt.*; import java.awt.event.*; import java.awt.datatransfer.*; import java.awt.dnd.*; import java.awt.image.BufferedImage; import java.util.Vector; import java.util.Enumeration; import uk.ac.sanger.artemis.j2ssh.FileTransferProgressMonitor; import uk.ac.sanger.artemis.j2ssh.FTProgress; import uk.ac.sanger.artemis.util.RemoteFileDocument; import uk.ac.sanger.artemis.Options; import uk.ac.sanger.artemis.Entry; import uk.ac.sanger.artemis.EntryGroup; import uk.ac.sanger.artemis.SimpleEntryGroup; import uk.ac.sanger.artemis.util.OutOfRangeException; import uk.ac.sanger.artemis.io.EntryInformation; import uk.ac.sanger.artemis.io.SimpleEntryInformation; import uk.ac.sanger.artemis.components.EntryEdit; import uk.ac.sanger.artemis.components.EntryFileDialog; import uk.ac.sanger.artemis.components.SwingWorker; import uk.ac.sanger.artemis.components.MessageDialog; import uk.ac.sanger.artemis.sequence.NoSequenceException; /** * * This example shows how to create a simple SshJTreeTable component, * by using a JTree as a renderer (and editor) for the cells in a * particular column in the JTable. * * modified from the example at: * http://java.sun.com/products/jfc/tsc/articles/treetable1/ * */ public class SshJTreeTable extends JTable implements DragGestureListener, DragSourceListener, DropTargetListener, ActionListener, Autoscroll { /** */ private static final long serialVersionUID = 1L; /** popup menu */ private JPopupMenu popup; /** busy cursor */ private Cursor cbusy = new Cursor(Cursor.WAIT_CURSOR); /** done cursor */ private Cursor cdone = new Cursor(Cursor.DEFAULT_CURSOR); /** line separator */ private String ls = new String(System.getProperty("line.separator")); /** AutoScroll margin */ private static final int AUTOSCROLL_MARGIN = 45; /** used by AutoScroll method */ private Insets autoscrollInsets = new Insets( 0, 0, 0, 0 ); protected TreeTableCellRenderer tree; private JFrame frame; public SshJTreeTable(TreeModel treeTableModel, final JFrame frame) { super(); this.frame = frame; DragSource dragSource = DragSource.getDefaultDragSource(); dragSource.createDefaultDragGestureRecognizer( this, // component where drag originates DnDConstants.ACTION_COPY_OR_MOVE, // actions this); // drag gesture recognizer setDropTarget(new DropTarget(this,this)); // Create the tree. It will be used as a renderer and editor. tree = new TreeTableCellRenderer(treeTableModel); // Install a tableModel representing the visible rows in the tree. super.setModel(new TreeTableModelAdapter(treeTableModel, tree)); // Force the JTable and JTree to share their row selection models. tree.setSelectionModel(new DefaultTreeSelectionModel() { /** */ private static final long serialVersionUID = 1L; // Extend the implementation of the constructor, as if: /* public this() */ { setSelectionModel(listSelectionModel); } }); // Make the tree and table row heights the same. tree.setRowHeight(getRowHeight()); // Install the tree editor renderer and editor. setDefaultRenderer(TreeTableModel.class, tree); setDefaultEditor(TreeTableModel.class, new TreeTableCellEditor()); setShowGrid(false); setIntercellSpacing(new Dimension(3, 0)); // popup menu addMouseListener(new PopupListener()); popup = new JPopupMenu(); JMenuItem menuItem = new JMenuItem("Refresh"); menuItem.addActionListener(this); popup.add(menuItem); popup.add(new JSeparator()); //open menu JMenu openMenu = new JMenu("Open With"); popup.add(openMenu); menuItem = new JMenuItem("Jemboss Aligmnment Editor"); menuItem.addActionListener(this); openMenu.add(menuItem); menuItem = new JMenuItem("Artemis"); menuItem.addActionListener(this); openMenu.add(menuItem); menuItem = new JMenuItem("Rename..."); menuItem.addActionListener(this); popup.add(menuItem); menuItem = new JMenuItem("New Folder..."); menuItem.addActionListener(this); popup.add(menuItem); menuItem = new JMenuItem("Delete..."); menuItem.addActionListener(this); popup.add(menuItem); popup.add(new JSeparator()); menuItem = new JMenuItem("De-select All"); menuItem.addActionListener(this); popup.add(menuItem); //Listen for when a file is selected addMouseListener(new MouseListener() { public void mouseClicked(MouseEvent me) { if(me.getClickCount() == 2 && isFileSelection() && !me.isPopupTrigger()) { RemoteFileNode node = (RemoteFileNode)tree.getLastSelectedPathComponent(); if(node==null) return; frame.setCursor(cbusy); if(node.isLeaf()) showFilePane(node); frame.setCursor(cdone); } } public void mousePressed(MouseEvent me){} public void mouseEntered(MouseEvent me){} public void mouseExited(MouseEvent me){} public void mouseReleased(MouseEvent me){} }); } /** * * Determine if selected node is a file * @return true if the selected node is a file * */ public boolean isFileSelection() { TreePath path = tree.getLeadSelectionPath(); if(path == null) return false; RemoteFileNode node = (RemoteFileNode)path.getLastPathComponent(); return !node.isDirectory(); } /** * * Get FileNode of selected node * @return node that is currently selected * */ public RemoteFileNode getSelectedNode() { TreePath path = tree.getLeadSelectionPath(); if(path == null) return null; RemoteFileNode node = (RemoteFileNode)path.getLastPathComponent(); return node; } /* Workaround for BasicTableUI anomaly. Make sure the UI never tries to * paint the editor. The UI currently uses different techniques to * paint the renderers and editors and overriding setBounds() below * is not the right thing to do for an editor. Returning -1 for the * editing row in this case, ensures the editor is never painted. */ public int getEditingRow() { return (getColumnClass(editingColumn) == TreeTableModel.class) ? -1 : editingRow; } protected void refresh(RemoteFileNode node) { node.reset(); node.removeAllChildren(); node.getChildren(); ((DefaultTreeModel)tree.getModel()).nodeStructureChanged(node); } /** * * Get FileNodes of selected nodes * @return node that is currently selected * */ private RemoteFileNode[] getSelectedNodes() { TreePath path[] = tree.getSelectionPaths(); if(path == null) return null; int numberSelected = path.length; RemoteFileNode nodes[] = new RemoteFileNode[numberSelected]; for(int i=0;i 1) { TransferableFileNodeList list = new TransferableFileNodeList(nlist); RemoteFileNode nodes[] = getSelectedNodes(); for(int i=0; i 0 ) top = AUTOSCROLL_MARGIN; if( location.x - rect.x < AUTOSCROLL_MARGIN && rect.x > 0 ) left = AUTOSCROLL_MARGIN; if( bottomEdge - location.y < AUTOSCROLL_MARGIN && bottomEdge < size.height ) bottom = AUTOSCROLL_MARGIN; if( rightEdge - location.x < AUTOSCROLL_MARGIN && rightEdge < size.width ) right = AUTOSCROLL_MARGIN; rect.x += right - left; rect.y += bottom - top; scrollRectToVisible( rect ); } /** * * Gets the insets used for the autoscroll. * @return The insets. * */ public Insets getAutoscrollInsets() { Dimension size = getSize(); Rectangle rect = getVisibleRect(); autoscrollInsets.top = rect.y + AUTOSCROLL_MARGIN; autoscrollInsets.left = rect.x + AUTOSCROLL_MARGIN; autoscrollInsets.bottom = size.height - (rect.y+rect.height) + AUTOSCROLL_MARGIN; autoscrollInsets.right = size.width - (rect.x+rect.width) + AUTOSCROLL_MARGIN; return autoscrollInsets; } }