package gui; import java.awt.Color; import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionAdapter; import java.awt.event.MouseMotionListener; import java.util.ArrayList; import java.util.Enumeration; import java.util.ListIterator; import javax.swing.JLabel; import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JTree; import javax.swing.border.EmptyBorder; import javax.swing.plaf.basic.BasicTreeUI; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; import util.GuiOperations; import communication.Download; public class JTreeDownload extends JTree { private static final long serialVersionUID = 6328897696354901796L; private DefaultTreeModel treeModelDL; private JTreeDownload downloadTree; private MainScreen ms; private JPopupMenu downloadMenu; private JMenuItem clearMenuItem; private int[] mousePos = { 0, 0 }; public JTreeDownload( MainScreen _ms ) { super( new DefaultTreeModel( new FolderNode( "Downloads" ) ) ); downloadTree = this; this.ms = _ms; downloadMenu = new JPopupMenu(); clearMenuItem = new JMenuItem( "Clear completed downloads" ); clearMenuItem.addActionListener( new ActionListener() { @Override public void actionPerformed( ActionEvent e ) { cleanDownloads(); } } ); downloadMenu.add( clearMenuItem ); treeModelDL = (DefaultTreeModel) getModel(); setEditable( false ); getSelectionModel().setSelectionMode( TreeSelectionModel.SINGLE_TREE_SELECTION ); setRowHeight( 0 ); setRootVisible( false ); setCellRenderer( new DefaultTreeCellRenderer() { private static final long serialVersionUID = -7105201164017761653L; public Component getTreeCellRendererComponent( JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus ) { if ( value instanceof LeafNode ) { JPanel panel = new JPanel(); String text = ( ( (LeafNode) value ).getDownload() ).getItem().getName(); panel.add( new JLabel( text ) ); panel.setBackground( new Color( 0, 0, 0, 0 ) ); panel.setBorder( new EmptyBorder( 0, 5, 0, 0 ) ); panel.setEnabled( tree.isEnabled() ); return panel; } else { super.getTreeCellRendererComponent( tree, value, sel, expanded, leaf, row, hasFocus ); return this; } } } ); MouseMotionListener mml = new MouseMotionAdapter() { @Override public void mouseMoved( MouseEvent e ) { int selRow = getRowForLocation( 10, e.getY() ); if ( selRow > -1 ) { TreePath selTmp = getPathForRow( selRow ); setSelectionPath( selTmp ); mousePos[ 0 ] = e.getX(); mousePos[ 1 ] = e.getY(); repaint(); } else { setSelectionRow( -1 ); downloadTree.setToolTipText( null ); } super.mouseMoved( e ); } }; addMouseMotionListener( mml ); MouseListener ml = new MouseAdapter() { @Override public void mouseExited( MouseEvent e ) { setSelectionRow( -1 ); super.mouseExited( e ); } @Override public void mouseReleased( MouseEvent e ) { if ( e.getButton() == MouseEvent.BUTTON3 ) downloadMenu.show( e.getComponent(), e.getX(), e.getY() ); else { TreePath path = getSelectionPath(); if ( path != null ) { Object obj = path.getLastPathComponent(); if ( obj instanceof LeafNode ) { LeafNode node = (LeafNode) obj; // Controls int xPos = ( downloadTree.getVisibleRect().width + downloadTree.getVisibleRect().x ) - 43; int selection = 0; // Mouse over control if ( mousePos[ 0 ] >= xPos && mousePos[ 0 ] < ( xPos + 19 ) ) selection = 1; else if ( mousePos[ 0 ] >= ( xPos + 19 ) && mousePos[ 0 ] < ( xPos + 37 ) ) selection = 2; if ( node.getDownload().isCompleted() && !node.getDownload().isFaulty() ) { if ( selection == 1 ) { // Launch GuiOperations.launchItem( ms, node.getItem() ); } if ( selection == 2 ) { // Remove treeModelDL.removeNodeFromParent( node ); } } else { if ( selection == 1 ) { if ( node.getDownload().isCanceled() || node.getDownload().isFaulty() ) { // Retry GuiOperations.retrySelectedItem( ms, node.getItem() ); } else { // Pause/Resume GuiOperations.pauseOrResumeSelectedItem( ms, node.getItem() ); } } if ( selection == 2 ) { if ( node.getDownload().isCanceled() || node.getDownload().isFaulty() ) { // Remove treeModelDL.removeNodeFromParent( node ); } else { // Cancel GuiOperations.cancelSelectedItem( ms, node.getItem() ); } } } if ( selection == 0 ) { DefaultMutableTreeNode leftNode = downloadTree.ms.getItemPanel() .getItemInTree( ( (LeafNode) obj ).getDownload().getItem() ); if ( leftNode != null && leftNode instanceof LeafNode ) downloadTree.ms.getItemPanel().focus( (LeafNode) leftNode ); } } } } super.mouseReleased( e ); } }; addMouseListener( ml ); setUI( new BasicTreeUI() { @Override protected void paintRow( java.awt.Graphics g, java.awt.Rectangle clipBounds, java.awt.Insets insets, java.awt.Rectangle bounds, TreePath path, int row, boolean isExpanded, boolean hasBeenExpanded, boolean isLeaf ) { AnimatedTreeUI.drawCell( g, bounds, downloadTree, path, row ); super.paintRow( g, clipBounds, insets, bounds, path, row, isExpanded, hasBeenExpanded, isLeaf ); AnimatedTreeUI.drawControls( g, bounds, downloadTree, path, row, mousePos ); }; } ); } public synchronized void updateDownload( Download download ) { LeafNode node = getNode( download ); if ( download.isActive() && node == null ) { treeModelDL.insertNodeInto( new LeafNode( download ), ( (DefaultMutableTreeNode) treeModelDL.getRoot() ), ( (DefaultMutableTreeNode) treeModelDL.getRoot() ).getChildCount() ); if ( treeModelDL.getChildCount( ( (DefaultMutableTreeNode) treeModelDL.getRoot() ) ) >= 1 && !isExpanded( 0 ) ) { setRootVisible( true ); expandRow( 0 ); setRootVisible( false ); } } if ( node != null ) { if ( node.getDownload() != download ) node.setDownload( download ); node.setDownPerc( (float) download.getDownloadedAmount() / (float) download.getTotalLength() ); } } public LeafNode getNode( Download download ) { for ( @SuppressWarnings( "rawtypes" ) Enumeration e = ( (DefaultMutableTreeNode) treeModelDL.getRoot() ).children(); e.hasMoreElements(); ) { LeafNode curNode = (LeafNode) e.nextElement(); Object curObj = curNode.getUserObject(); if ( curObj instanceof Download ) { Download dl = (Download) curObj; if ( dl.getItem().getId().equals( download.getItem().getId() ) ) { return curNode; } } } return null; } private void cleanDownloads() { ArrayList<LeafNode> list = new ArrayList<LeafNode>( 1 ); for ( @SuppressWarnings( "rawtypes" ) Enumeration e = ( (DefaultMutableTreeNode) treeModelDL.getRoot() ).children(); e.hasMoreElements(); ) { LeafNode curNode = (LeafNode) e.nextElement(); Object curObj = curNode.getUserObject(); if ( curObj instanceof Download ) { Download dl = (Download) curObj; if ( dl.isCompleted() ) { list.add( curNode ); } } } ListIterator<LeafNode> it = list.listIterator(); while ( it.hasNext() ) { treeModelDL.removeNodeFromParent( it.next() ); } } }