/* * * * 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.io.FileOutputStream; import java.io.FileNotFoundException; 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 uk.ac.sanger.artemis.j2ssh.FileTransferProgressMonitor; import uk.ac.sanger.artemis.j2ssh.FTProgress; 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.util.FileDocument; 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 JTreeTable 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 JTreeTable 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); /** file separator */ private String fs = new String(System.getProperty("file.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; public JTreeTable(TreeModel treeTableModel) { super(); setName("File Tree"); 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)); //Listen for when a file is selected MouseListener mouseListener = new MouseAdapter() { public void mouseClicked(MouseEvent me) { if(me.getClickCount() == 2 && isFileSelection() && !me.isPopupTrigger()) { setCursor(cbusy); FileNode node = getSelectedNode(); String selected = node.getFile().getAbsolutePath(); showFilePane(selected); setCursor(cdone); } } }; this.addMouseListener(mouseListener); // Popup menu addMouseListener(new PopupListener()); popup = new JPopupMenu(); JMenuItem menuItem = new JMenuItem("Refresh"); menuItem.addActionListener(this); popup.add(menuItem); JMenuItem gotoItem = new JMenuItem("GoTo Directory..."); gotoItem.addActionListener(this); popup.add(gotoItem); popup.add(new JSeparator()); //open menu JMenu openMenu = new JMenu("Open With"); popup.add(openMenu); menuItem = new JMenuItem("Jemboss Alignment 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); // Set the first visible column to 10 pixels wide TableColumn col = getColumnModel().getColumn(1); col.setPreferredWidth(10); } public TreeTableCellRenderer getTree() { return tree; } /** * * Get FileNode of selected node * @return node that is currently selected * */ public FileNode getSelectedNode() { TreePath path = tree.getLeadSelectionPath(); if(path == null) return null; FileNode node = (FileNode)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; } private void refresh(FileNode node) { node.removeAllChildren(); node.reset(); node.getChildren( ((FileSystemModel)tree.getModel()).getFilter() ); ((DefaultTreeModel)tree.getModel()).nodeStructureChanged(node); tree.revalidate(); tree.repaint(); revalidate(); } protected void refreshAll() { FileSystemModel model = (FileSystemModel)tree.getModel(); Object root = model.getRoot(); Vector vnodes = new Vector(); addChildren(vnodes, (FileNode)root, model); for(int i = 0; i 1) { TransferableFileNodeList list = new TransferableFileNodeList(nlist); FileNode 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; } }