Package xnap.gui

Source Code of xnap.gui.LibraryPanel$DisplayThread

/*
*  XNap
*
*  A pure java file sharing client.
*
*  See AUTHORS for copyright information.
*
*  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 xnap.gui;

import xnap.*;
import xnap.gui.action.CopyFileAction;
import xnap.gui.action.CutFileAction;
import xnap.gui.action.PasteFileAction;
import xnap.gui.action.OpenFileWithMenu;
import xnap.gui.event.*;
import xnap.gui.table.*;
import xnap.gui.tree.*;
import xnap.plugin.*;
import xnap.util.*;
import xnap.util.event.StateEvent;
import xnap.util.event.StateListener;
import xnap.util.audio.*;
import xnap.io.*;

import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import java.util.*;
import java.io.*;
import java.net.*;
import java.text.MessageFormat;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import javax.swing.table.*;
import javax.swing.tree.*;

public class LibraryPanel extends AbstractPanel
    implements PropertyChangeListener, TreeSelectionListener,
         ListSelectionListener, DirectoryCollector, FileCollector {

    //--- Constant(s) ---

    public static final String HISTORY_FILENAME
    = FileHelper.getHomeDir() + "repository_search_history";

    //--- Data field(s) ---

    private AudioPlayer player = null;

    private EditableComboBox jcSearch;

    private JTree jt;
    private JTable jta;
    private JFileChooser jfc = null;
    private LibraryTableModel ltm;
    private DefaultMutableTreeNode root;
    private FileTreeModel ftm;
    private DragFilesSupport dfs;

    private JSplitPane jspH;
    private JSplitPane jspV;

    // preview
    private JPanel jpPreview;
    private JScrollPane jspPreview;
    private JLabel jlStatus;

    private PlayAction playAction = new PlayAction();
    private PlayFileAction playFileAction = new PlayFileAction();
    private RefreshAction refreshAction = new RefreshAction();
    private StopAction stopAction = new StopAction();
    private EnqueueAction enqueueAction = new EnqueueAction();
   
    private PlayFolderAction playFolderAction = new PlayFolderAction();
    private EnqueueFolderAction enqueueFolderAction = new EnqueueFolderAction();
    private OpenFileAction acOpenFile = new OpenFileAction(this);
    private ShareFolderAction shareFolderAction = new ShareFolderAction();
    private UnshareFolderAction unshareFolderAction = new UnshareFolderAction();
    private ReloadTreeAction acReloadTree = new ReloadTreeAction();
    private DeleteAction deleteAction = new DeleteAction();
    private RenameAction renameAction = new RenameAction();

    private CopyFileAction acCopyFile = new CopyFileAction(this);
    private CutFileAction acCutFile = new CutFileAction(this);
    private PasteFileAction acPasteFile = new PasteFileAction(this);
   
    private File currentDir;
    private int currentRow;
    private javax.swing.Timer delayTimer;

    private DisplayThread displayThread = new DisplayThread();

    //--- Constructor(s) ---

    public LibraryPanel()
    {
    initialize();
    }

    //--- Method(s) ---

    private void initialize()
    {
    // search panel
    Box boxOne = new Box(BoxLayout.X_AXIS);
    QueryAction acQuery = new QueryAction();

    EraseAction acErase = new EraseAction();
    JButton jbErase = new JButton(acErase);
    jbErase.setMargin(new Insets(1, 1, 1, 1));
    boxOne.add(jbErase);
 
    jcSearch = new EditableComboBox(acQuery, prefs.getSearchHistorySize());
    jcSearch.readHistoryFile(new File(HISTORY_FILENAME));
    boxOne.add(jcSearch);

    acErase.setJTextField(jcSearch.getJTextField());
       
    JButton jbQuery = new JButton(acQuery);
    boxOne.add(jbQuery);

    JPanel jpTop = new JPanel(new BorderLayout());
    jpTop.setBorder(new TitledBorder(XNap.tr("Library Search", 1)));
    jpTop.add(boxOne, "Center");

    /* tree context menu */
    JPopupMenu treePopup = new JPopupMenu();
    treePopup.add(new JMenuItem(playFolderAction));
    treePopup.add(new JMenuItem(enqueueFolderAction));
    treePopup.addSeparator();
    treePopup.add(new JMenuItem(shareFolderAction));
    treePopup.add(new JMenuItem(unshareFolderAction));
    treePopup.addSeparator();
    treePopup.add(acPasteFile);
    treePopup.addSeparator();
    treePopup.add(new JMenuItem(acReloadTree));
 
    /* tree */
        ftm = new FileTreeModel(XNap.tr("Files"));
 
    //  jt = new JTree(ftm);
    jt = new DroppableJTree(ftm, this);
    jt.addTreeSelectionListener(this);
    jt.setCellRenderer(new FileCellRenderer());
    jt.putClientProperty("JTree.lineStyle", "Angled");
    MouseListener treePopupListener = new PopupListener(treePopup);
    jt.addMouseListener(treePopupListener);
 
    /* allow multiple selections in tree */
    jt.getSelectionModel().setSelectionMode
      (TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);

        JScrollPane jspTree = new JScrollPane();
        jspTree.setViewportView(jt);

    /* table context menu */
    JPopupMenu popup = new JPopupMenu();
    popup.add(new JMenuItem(playAction));
    popup.add(new JMenuItem(enqueueAction));
    popup.addSeparator();
    popup.add(new JMenuItem(acOpenFile));
    popup.add(new OpenFileWithMenu(this));
    popup.addSeparator();
    popup.add(createViewerMenu());
    popup.addSeparator();
    popup.add(acCopyFile);
    popup.add(acCutFile);
    popup.add(acPasteFile);
    popup.addSeparator();
    popup.add(renameAction);
    popup.add(deleteAction);

    /* table */
        ltm = new LibraryTableModel();
    jta = ltm.createJTable();
    dfs = new DragFilesSupport(jta, this);
    jta.getSelectionModel().addListSelectionListener(this);
    jta.setShowGrid(false);

    MouseListener popupListener = new PopupListener(popup);
    jta.addMouseListener(popupListener);
    jta.addMouseListener(new DoubleClickListener(acOpenFile, jta));

    /* set up Emacs keybindings for move actions */
    ActionListener al =
      jta.getActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN,
                               0));
    jta.registerKeyboardAction
      (al,KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_MASK),
       WHEN_FOCUSED);

    al = jta.getActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_UP,
                                0));
    jta.registerKeyboardAction
      (al, KeyStroke.getKeyStroke(KeyEvent.VK_P, InputEvent.CTRL_MASK),
       WHEN_FOCUSED);

    al = jta.getActionForKeyStroke
      (KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, 0));
    jta.registerKeyboardAction
      (al, KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_MASK),
       WHEN_FOCUSED);
 
    al = jta.getActionForKeyStroke
      (KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, 0));
    jta.registerKeyboardAction
      (al, KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.ALT_MASK),
       WHEN_FOCUSED);
 
    al = jta.getActionForKeyStroke
      (KeyStroke.getKeyStroke(KeyEvent.VK_HOME, InputEvent.CTRL_MASK));
    jta.registerKeyboardAction
      (al, KeyStroke.getKeyStroke(KeyEvent.VK_LESS, InputEvent.ALT_MASK),
       WHEN_FOCUSED);

    al = jta.getActionForKeyStroke
      (KeyStroke.getKeyStroke(KeyEvent.VK_END, InputEvent.CTRL_MASK));
    jta.registerKeyboardAction
      (al, KeyStroke.getKeyStroke(KeyEvent.VK_LESS, InputEvent.ALT_MASK
                    + InputEvent.SHIFT_MASK),
       WHEN_FOCUSED);
 

    jta.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0),
                acOpenFile);
    jta.getActionMap().put(acOpenFile, acOpenFile);

    jta.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_F5, 0),
                refreshAction);
    jta.getActionMap().put(refreshAction, refreshAction);

    jta.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0),
                deleteAction);
    jta.getActionMap().put(deleteAction, deleteAction);

    jta.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0),
                renameAction);
    jta.getActionMap().put(renameAction, renameAction);

    jta.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_Q, 0),
                enqueueAction);
    jta.getActionMap().put(enqueueAction, enqueueAction);

    JScrollPane jspTable = new JScrollPane();
    jspTable.setViewportView(jta);

    /* selection delay, which ensures the user really wants the plugin to
           be activated.  */
    delayTimer = new javax.swing.Timer(500, new SelectionListener());
    delayTimer.setRepeats(false);

    /* preview pane */
    jpPreview = new JPanel(new BorderLayout());
    jpPreview.setBackground(Color.gray);

    jspPreview = new JScrollPane(jpPreview);
    al = jspPreview.getActionForKeyStroke
      (KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, 0));
    jspPreview.registerKeyboardAction
      (al, KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, KeyEvent.CTRL_MASK),
       WHEN_IN_FOCUSED_WINDOW);

    al = jspPreview.getActionForKeyStroke
      (KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, 0));
    jspPreview.registerKeyboardAction
      (al, KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, KeyEvent.CTRL_MASK
                    | KeyEvent.SHIFT_MASK),
       WHEN_IN_FOCUSED_WINDOW);
           

    /* split panels */
    jspV = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
        jspV.add(jspTable, JSplitPane.TOP);
        jspV.add(jspPreview, JSplitPane.BOTTOM);
        jspV.setDividerLocation(prefs.getLibraryVerticalDividerLocation());
    jspV.setOneTouchExpandable(true);

    jlStatus = new JLabel(" ");

    JPanel jpV = new JPanel(new BorderLayout());
    jpV.add(jspV, "Center");
    jpV.add(jlStatus, "South");

    jspH = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
        jspH.add(jspTree, JSplitPane.LEFT);
        jspH.add(jpV, JSplitPane.RIGHT);
    jspH.setDividerLocation(prefs.getLibraryHorizontalDividerLocation());
    jspH.setOneTouchExpandable(true);

    /* content */
    setLayout(new BorderLayout());
    add(jpTop, BorderLayout.NORTH);
    add(jspH, BorderLayout.CENTER);

    // make sure we are set
    updateAudioPlayer();

    // show directories
    updateTree();

    // make sure we are notified when the downloadDir changes
    prefs.addPropertyChangeListener(this);
    }
 
    /**
     * Lazy instantiation.
     */
    public JFileChooser getFileChooser()
    {
    if (jfc == null) {
      jfc = new JFileChooser();
      MP3FileFilter filter = new MP3FileFilter();
      jfc.setFileFilter(filter);
    }
    return jfc;
    }

    public JMenu getTableMenu()
    {
    return ltm.createJMenu();
    }
   
    public void hasChanged(File directory)
    {
    if (currentDir != null) {
      showDirectory(currentDir);
    }
    }
   
    /**
     * This hack sets the focus to jcSearch after the searchpanel has been
     * activated. This only works for java 1.3 and the JTabbedPane and not for
     * the IconSplitPane.
     */
    //  public void setVisible(boolean visible)
  //      {
  //    super.setVisible(visible);
  //    if (visible) {
  //        SwingUtilities.invokeLater(new Runnable()
  //      {
  //          public void run()
  //          {
  //        //  System.out.println("swing invoke runnable");
  //        jcSearch.grabFocus();
  //          }
  //      });
  //    }
              
  //      }

    public void purgeHistory()
    {
    jcSearch.removeAllItems();
    }
   
    public void propertyChange(PropertyChangeEvent e)
    {
    String p = e.getPropertyName();
 
    if (e.getSource() == prefs) {
      if (p.equals("incompleteDir")) {
        ftm.removeChildrenOfSubRoot(XNap.tr("Incomplete Files"));
        ftm.addChildOfSubRoot(new File(prefs.getIncompleteDir()),
                    XNap.tr("Incomplete Files"));
      }
     
      else if (p.equals("uploadDirs")) {
        ftm.removeChildrenOfSubRoot(XNap.tr("Shared Files"));
        String[] dirs = prefs.getUploadDirsArray();
        for (int i = 0; i < dirs.length; i++) {
          ftm.addChildOfSubRoot(new File(dirs[i]),
                      XNap.tr("Shared Files"));
        }
      }
      else if (p.equals("mp3PlayerCmd") || p.equals("mp3PlayerType")) {
        updateAudioPlayer();
      }
      else if (p.equals("downloadDir") || p.indexOf("DownloadDir")
           != -1) {
        ftm.removeChildrenOfSubRoot(XNap.tr("Downloaded Files"));
        addDownloadDirs();
      }
    }
    }

    public void savePrefs()
    { 
    prefs.setLibraryHorizontalDividerLocation(jspH.getDividerLocation());
    prefs.setLibraryVerticalDividerLocation(jspV.getDividerLocation());
    jcSearch.setHistorySize(prefs.getSearchHistorySize());
    jcSearch.writeHistoryFile(new File(HISTORY_FILENAME));
    }

    private void updateAudioPlayer()
    {
    player = AudioSupport.getInstance(prefs.getMP3PlayerType(),
                      prefs.getMP3PlayerCmd());
    }

    /**
     * Clears the tree and adds a couple of nodes.
     */
    private void updateTree()
    {
    ftm.removeSubRoots();

    int failed = 0;
    String[] nodes = prefs.getLibraryTreeNodesArray();
    for (int j = 0; j < nodes.length; j++) {
      if (nodes[j].equals("shares")) {
        // add shares
        ftm.addSubRoot(XNap.tr("Shared Files"));
        String[] dirs = prefs.getUploadDirsArray();
        for (int i = 0; i < dirs.length; i++) {
          ftm.addChildOfSubRoot(new File(dirs[i]),
                      XNap.tr("Shared Files"));
        }
        jt.expandRow(jt.getRowCount() - 1);
      }
      else if (nodes[j].equals("incompletes")) {
        // add incomplete dir
        ftm.addChildOfSubRoot(new File(prefs.getIncompleteDir()),
                    XNap.tr("Incomplete Files"));
        // ensure that the actual incomplete directory is viewable
        jt.expandRow(jt.getRowCount() - 1);
      }
      else if (nodes[j].equals("downloads")) {
        addDownloadDirs();
        jt.expandRow(jt.getRowCount() - 1);
      }
      else if (nodes[j].equals("home")) {
        ftm.addChildOfSubRoot(new File
          (System.getProperty("user.home")), XNap.tr("Home Directory"));
        jt.expandRow(jt.getRowCount() - 1);
      }
      else if (nodes[j].equals("root")) {
        // add system roots
        File[] roots = File.listRoots();
        for (int i = 0; i < roots.length; i++) {
          ftm.addChildOfSubRoot(roots[i], XNap.tr("Root Directory"));
        }
        jt.expandRow(jt.getRowCount() - 1);
      }
      else {
        failed++;
      }
    }

    if (failed == nodes.length) {
      // always show at least system roots
      ftm.addSubRoot(XNap.tr("Root Directory"));
      File[] roots = File.listRoots();
      for (int i = 0; i < roots.length; i++) {
        ftm.addChildOfSubRoot(roots[i], XNap.tr("Root Directory"));
      }
      jt.expandRow(jt.getRowCount() - 1);
    }
    }

    /**
     * Adds the main download directory and all media type download
     * directories which are set to the tree.
     */
    private void addDownloadDirs()
    {
    // add download dir
    ftm.addChildOfSubRoot(new File(prefs.getDownloadDir()),
                XNap.tr("Downloaded Files"));

    for (int i = 0; i < SearchFilter.media.length; i++) {
      String type = (String)SearchFilter.media[i];
      String dir = prefs.getMediaTypeDownloadDir(type);
      if (i != SearchFilter.MEDIA_ANYTHING && dir.length() > 0) {
        ftm.addChildOfSubRoot(new File(dir),
                    XNap.tr("Downloaded Files"),
                    " (" + type + ")");
      }
    }
    }
   
    private void showDirectory(File f)
    {
    currentDir = f;
    ltm.clear();
    // check if directory is readable by xnap user
    if (f.canRead()) {
      ltm.add(f);
      ltm.resort();
    }
    resetPanel();
    }

    private void showFiles(File[] files)
    {
    ltm.clear();
    ltm.add(files);
    ltm.resort();
    resetPanel();
    }

    /**
     * Called when a new directory has been selected.
     */
    public void valueChanged(TreeSelectionEvent e)
    {
    Object target = e.getPath().getLastPathComponent();
 
    if (target instanceof File) {
      File f = (File)target;
      showDirectory(f);
    }
    }

 
    /**
     * Called when the table's selection changes, we check what kind of
     * file was selected and call the respective viewer plugin if available.
     */
    public void valueChanged(ListSelectionEvent e)
    {
    /* user is about to select some files, don't show anything */
    if (jta.getSelectedRowCount() > 1) {
      resetPanel();
      return;
    }

    int row = jta.getSelectedRow();
    if (row != -1) {
      currentRow = row;
      delayTimer.restart();
    }
    }

    public AbstractAction[] getActions()
    {
    return (new AbstractAction[]
      {
        playFileAction, enqueueAction, playAction, stopAction, null,
        refreshAction, null, shareFolderAction, unshareFolderAction
      });
    }

 
    private void playFile(final File f)
    {
    if (player != null) {
      (new Thread("PlayFile " + f) {
          public void run()
          {
            boolean success;
            if (f == null)
              success = player.play();
            else
              success = player.play(f);
     
            if (!success) {
              if (f == null)
                setStatus(XNap.tr("Could not start player"));
              else
                setStatus(XNap.tr("Could not play file", 0,
                          1) + f);
            }
            else if (f != null)
              setStatus(XNap.tr("Playing", 0, 1) + f);
            else
              setStatus(XNap.tr("Starting player"));
          }
        }
       ).start();
    }
    else {
      setStatus(XNap.tr("Could not launch player"));
    }
    }
 
    private void enqueueFiles(final LinkedList files)
    {
    if (player != null) {
      (new Thread("EnqueueFiles") {
          public void run()
          {
            int size = files.size();
            while (files.size() > 0) {
              final File f = (File)files.removeFirst();
              if (!player.enqueue(f))
                setStatus(XNap.tr("Could not enqueue file") + f);
            }
            if (size > 0) {
              setStatus(XNap.tr("Enqueued", 0, 1) + size
                    + XNap.tr("file(s)", 1, 0));
            }
          }
        }
       ).start();
    }
    else {
      setStatus(XNap.tr("Could not launch audio player, please check your preferences"));
    }
    }
 
    private void doPlay(int[] rows)
    {
    if (rows.length == 0) {
      playFile(null);
    }
    else if (rows.length > 0 && player.canPlay(ltm.get(rows[0]))) {
      playFile(ltm.get(rows[0]));
    }
 
    if (rows.length > 1) {
      // if more than one file is selected the following files are
      // enqueued to be played later on
      LinkedList filestoEnqueue = new LinkedList();
      for (int i = 1; i < rows.length; i++) {
        if (player.canPlay(ltm.get(rows[i]))) {
          filestoEnqueue.add(ltm.get(rows[i]));
        }
      }
      enqueueFiles(filestoEnqueue);
    }
    }

    public File getDirectory()
    {
    TreePath selected = jt.getSelectionPath();
    if (selected != null) {     
      Object o = selected.getLastPathComponent();
      if (o instanceof File) {
        return (File)o;
      }
    }

    return null;
    }

    public File[] getFiles(boolean showMessage)
    {
    int rowC = jta.getSelectedRowCount();
    int rows[] = jta.getSelectedRows();
 
    if (showMessage && rowC == 0) {
      setStatus(XNap.tr("Please select something first"));
      return null;
    }
 
    File[] files = new File[rowC];
 
    for (int i = 0; i < rowC; i++) {
      files[i] = ltm.get(rows[i]);
    }

    return files;
    }

    public File[] getFiles()
    {
    return getFiles(true);
    }   
 
    /**
     * displays given file if possible in lower preview frame
     */
    private void displayFile(File f)
    {
        if (!f.canRead()) {
      jspPreview.setViewportView(jpPreview);
      jlStatus.setText(XNap.tr("Do not have permission to read file"));
      return;
    }

    ViewerPanel panel
      = GUIPluginManager.getGUIInstance().getViewer(f);

    if (panel != null) {
      jlStatus.setText(panel.getStatus());
      displayThread.setPanel(panel);
    }
    else {
      resetPanel();
    }
    }
   
    public void resetPanel()
    {
    jspPreview.setViewportView(jpPreview);
    updateStatus();
    }

    public int getHorizontalDividerLocation()
    {
    return jspH.getDividerLocation();
    }

    public void setHorizontalDividerLocation(int newValue)
    {
    if (newValue == -1) {
      jspH.setDividerLocation(200);
    }
    else {
      jspH.setDividerLocation(newValue);
    }
    }

    public int getVerticalDividerLocation()
    {
    return jspV.getDividerLocation();
    }

    public void setVerticalDividerLocation(int newValue)
    {
    if (newValue == -1) {
      jspV.setDividerLocation(200);
    }
    else {
      jspV.setDividerLocation(newValue);
    }
    }

    /**
     * Updates the status line below the file table.
     */
    public void updateStatus()
    {
    StringBuffer sb = new StringBuffer();
    File[] files = getFiles(false);
    if (files.length == 0) {
      // nothing is selected
      sb.append(ltm.getRowCount());
      sb.append(" files - ");  
      sb.append(Formatter.formatSize(ltm.getTotalSize()));
    }
    else if (files.length == 1) {
      sb.append("1 file - ");
      sb.append(Formatter.formatNumber(files[0].length()) + " bytes");
    }
    else {
      long totalSize = 0;
      for (int i = 0; i < files.length; i++) {
        totalSize += files[i].length();
      }
      sb.append("selected - ");
      sb.append(files.length);
      sb.append(" files - ");  
      sb.append(Formatter.formatSize(totalSize));
    }

    // FIX: we need some kind of padding
    sb.insert(0, " ");
    jlStatus.setText(sb.toString());
    }


    private JMenu createViewerMenu()
    {
    JMenu jm = new JMenu(XNap.tr("View with Plugin"));
    jm.setIcon(XNapFrame.getEmptyIcon());
    IPlugin[] plugins = PluginManager.getInstance().getPlugins();

    for (int i = 0; i < plugins.length; i++) {
      if (plugins[i] instanceof IViewerPlugin) {
        jm.add(new ViewerAction((IViewerPlugin)plugins[i], this));
      }   
    }
 
    return jm;
    }

    /* inner classes */
 

    private class ViewerAction extends AbstractAction implements StateListener
    {
    private IViewerPlugin plugin;
    private FileCollector fc;
 
    public ViewerAction(IViewerPlugin plugin, FileCollector fc)
    {
      this.plugin = plugin;
      this.fc = fc;
      putValue(Action.NAME, plugin.getName());
      this.setEnabled(plugin.isEnabled());
      GUIPluginManager.getInstance().addStateListener(this);
    }

    public void actionPerformed(ActionEvent event)
    {
      File[] files = fc.getFiles();

      if (files != null && files.length > 0) {
        ViewerPanel vp = plugin.handle(files[0]);
        jlStatus.setText(vp.getStatus());
        displayThread.setPanel(vp);
      }
    }

    public void stateDisabled(StateEvent e)
    {
      if (plugin == e.getSource()) {
        this.setEnabled(false);
      }
    }

    public void stateEnabled(StateEvent e)
    {
      if (plugin == e.getSource()) {
        this.setEnabled(true);
      }
    }
 
    }

    /**
     * Plays a file selected via a FileOpenDialog
     */
    private class PlayFileAction extends AbstractAction {
 
        public PlayFileAction()
    {   
      putValue(Action.NAME, XNap.tr("Play File"));
            putValue(Action.SHORT_DESCRIPTION,
           XNap.tr("Open a file to play"));
      putValue(Action.SMALL_ICON, XNapFrame.getIcon("fileopen.png"));
            putValue(Action.MNEMONIC_KEY, new Integer('O'));
        }

        public void actionPerformed(ActionEvent event)
    {
    
      if (getFileChooser().showOpenDialog(LibraryPanel.this)
        == JFileChooser.APPROVE_OPTION) {
        playFile(jfc.getSelectedFile());
      }
    }
 
    }
   
    /**
     * Plays selected file
     */
    private class PlayAction extends AbstractAction {

        public PlayAction()
    {
            putValue(Action.NAME, XNap.tr("Play"));
            putValue(Action.SHORT_DESCRIPTION,
           XNap.tr("Plays selected file(s)"));
      putValue(Action.SMALL_ICON, XNapFrame.getIcon("1rightarrow.png"));
            putValue(Action.MNEMONIC_KEY, new Integer('P'));
        }

        public void actionPerformed(ActionEvent event)
    {
      doPlay(jta.getSelectedRows());
        }
    }

    /**
     * Stops playing file
     */
    private class StopAction extends AbstractAction {

        public StopAction()
    {
            putValue(Action.NAME, XNap.tr("Stop"));
            putValue(Action.SHORT_DESCRIPTION,
           XNap.tr("Stop player"));
      putValue(Action.SMALL_ICON, XNapFrame.getIcon("player_stop.png"));
            putValue(Action.MNEMONIC_KEY, new Integer('S'));
        }

        public void actionPerformed(ActionEvent event)
    {
      if (player != null)
        player.stop();
    }
    }

    /**
     * Refresh file and directory listings
     */
    private class RefreshAction extends AbstractAction {

        public RefreshAction()
    {
            putValue(Action.NAME, XNap.tr("Refresh"));
            putValue(Action.SHORT_DESCRIPTION,
           XNap.tr("Refresh list of files"));
      putValue(Action.SMALL_ICON, XNapFrame.getIcon("reload.png"));
            putValue(Action.MNEMONIC_KEY, new Integer('R'));
        }

        public void actionPerformed(ActionEvent event)
    {
      if (currentDir != null) {
        showDirectory(currentDir);
      }
    }
    }

    /**
     * Refresh file and directory listings
     */
    private class ReloadTreeAction extends AbstractAction {

        public ReloadTreeAction()
    {
            putValue(Action.NAME, XNap.tr("Reload Tree"));
            putValue(Action.SHORT_DESCRIPTION,
           XNap.tr("Reload Tree"));
      putValue(Action.SMALL_ICON, XNapFrame.getIcon("reload.png"));
        }

        public void actionPerformed(ActionEvent event)
    {
      ftm.reload();
    }

    }

    private class DeleteAction extends AbstractAction
    {
    public DeleteAction()
    {
            putValue(Action.NAME, XNap.tr("Delete"));
            putValue(Action.SHORT_DESCRIPTION,
           XNap.tr("Delete selected file(s)"));
      putValue(Action.SMALL_ICON, XNapFrame.getIcon("editdelete.png"));
            putValue(Action.MNEMONIC_KEY, new Integer('D'));
        }

        public void actionPerformed(ActionEvent event)
    {
      File[] files = getFiles();
      if (files == null)
        return;
     
      files = Dialogs.showDeleteFilesDialog(LibraryPanel.this, files);

      if (files != null) {
        for (int i = 0; i < files.length; i++) {
          if (!ltm.delete(files[i])) {
            setStatus(XNap.tr("Could not delete file", 0, 1)
                  + files[i].getName());
          }
        }
      }
    }
    }

    /**
     * Enqueues a selected file.
     */
    private class EnqueueAction extends AbstractAction {

        public EnqueueAction()
    {
            putValue(Action.NAME, XNap.tr("Enqueue"));
            putValue(Action.SHORT_DESCRIPTION,
           XNap.tr("Enqueue selected file"));
      putValue(Action.SMALL_ICON, XNapFrame.getIcon("queue.png"));
            putValue(Action.MNEMONIC_KEY, new Integer('Q'));
        }

        public void actionPerformed(ActionEvent event)
    {
      { 
        LinkedList filestoEnqueue = new LinkedList();
        int rowC = jta.getSelectedRowCount();
        int[] rows = jta.getSelectedRows();

        // collects selected files
        for (int i = 0; i < rowC; i++) {
          if (player.canPlay(ltm.get(rows[i]))) {
            filestoEnqueue.add(ltm.get(rows[i]));
          }
        }
   
        enqueueFiles(filestoEnqueue);
      }
     
    }
 
    }

    /**
     * Enqueues selected Folder
     */
    private class EnqueueFolderAction extends AbstractAction {

        public EnqueueFolderAction()
    {
            putValue(Action.NAME, XNap.tr("Enqueue Folder"));
            putValue(Action.SHORT_DESCRIPTION,
           XNap.tr("Enqueue selected folder"));
      putValue(Action.SMALL_ICON, XNapFrame.getIcon("queue.png"));
            putValue(Action.MNEMONIC_KEY, new Integer('F'));
        }

        public void actionPerformed(ActionEvent event)
    {
      { 
        /* this is a very simple approach to enqueue the files in the
           specified folder and relies on the shortcomings of our
           current implementation: When you select a folder in the
           tree with the right mousebutton the folder is shown in the
           table, that's why we can just add all files of the table to
           enqueueFiles */
        LinkedList filestoEnqueue = new LinkedList();
        for (int i = 0; i < ltm.getRowCount(); i++) {
          if (player.canPlay(ltm.get(i))) {
            filestoEnqueue.add(ltm.get(i));
          }
        }
        enqueueFiles(filestoEnqueue);
      }
    }
    }

    /**
     * Plays selected Folder
     */
    private class PlayFolderAction extends AbstractAction {

        public PlayFolderAction()
    {
            putValue(Action.NAME, XNap.tr("Play Folder"));
            putValue(Action.SHORT_DESCRIPTION,
           XNap.tr("Plays selected folder"));
      putValue(Action.SMALL_ICON, XNapFrame.getIcon("1rightarrow.png"));
            putValue(Action.MNEMONIC_KEY, new Integer('L'));
        }

        public void actionPerformed(ActionEvent event)
    {
      int[] rows = new int[ltm.getRowCount()];
      for (int i = 1; i < rows.length; i++) {
        rows[i] = i;
      }
      doPlay(rows);
    }
    }

    private class RenameAction extends AbstractAction
    {
    public RenameAction()
    {
            putValue(Action.NAME, XNap.tr("Rename"));
            putValue(Action.SHORT_DESCRIPTION, XNap.tr("Rename selected file"));
            putValue(Action.MNEMONIC_KEY, new Integer('R'));
      putValue(Action.SMALL_ICON, XNapFrame.getEmptyIcon());
        }
       
    public void actionPerformed(ActionEvent event)
    {
      int i = jta.getSelectedRow();
      if (i != -1) {
        ltm.setCellEditable(i, ltm.NAME);
        jta.editCellAt(i, ltm.NAME);
        DefaultCellEditor dce = (DefaultCellEditor)jta.getCellEditor();
        JTextField jtf = (JTextField)dce.getComponent();
        //  jtf.setSelectionStart(0);
        //      jtf.setSelectionEnd(jtf.getText().length());
        jtf.grabFocus();
        jtf.setCaretPosition(0);
        ltm.setCellEditable(-1, -1);
      }
    }
    }

    /**
     *    Share selected Folder
     */
    private class ShareFolderAction extends AbstractAction {

   
        public ShareFolderAction()
    {
            putValue(Action.NAME, XNap.tr("Share Folder"));
            putValue(Action.SHORT_DESCRIPTION, XNap.tr("Share selected folder"));
      putValue(Action.SMALL_ICON,
           XNapFrame.getIcon("connect_established.png"));
            putValue(Action.MNEMONIC_KEY, new Integer('H'));
        }

        public void actionPerformed(ActionEvent event)
    {

      Dialogs.showNotification(LibraryPanel.this, "ShareFolder",
                   XNap.tr("Sharing Folder information"),
                   XNap.tr("Please note: Folders are shared recursively, so all subfolders and their content will be shared on the network too."));

      TreePath[] selected = jt.getSelectionPaths();
   
      for (int i = 0; i < selected.length; i++) {
        final Object o = selected[i].getLastPathComponent();
        if (o instanceof FileNode) {
          prefs.appendToUploadDirs(((FileNode)o).getPath());
          prefs.write();
        }
        else {
          setStatus(XNap.tr("Can not share \"") + o + "\"");
        }
      }
    }
  }

    /**
     * unshare selected Folder
     */
    private class UnshareFolderAction extends AbstractAction {

        public UnshareFolderAction()
    {
            putValue(Action.NAME, XNap.tr("Unshare Folder"));
            putValue(Action.SHORT_DESCRIPTION,
           XNap.tr("Unshare selected folder"));
      putValue(Action.SMALL_ICON, XNapFrame.getIcon("connect_no.png"));
            putValue(Action.MNEMONIC_KEY, new Integer('U'));
        }

        public void actionPerformed(ActionEvent event)
    {
      TreePath[] selected = jt.getSelectionPaths();
   
      for (int i = 0; i < selected.length; i++) {
        Object o = selected[i].getLastPathComponent();
        if (o instanceof FileNode) {
          prefs.removeFromUploadDirs(((FileNode)o).getPath());
          prefs.write();
        }
        else {
          setStatus(XNap.tr("Can not unshare \"") + o + "\"");
        }
      }
    }
    }

    /**
     * Performs a search.
     */
    private class QueryAction extends AbstractAction {

        public QueryAction()
    {
            putValue(Action.NAME, XNap.tr("Query"));
            putValue(Action.SHORT_DESCRIPTION, XNap.tr("Perform search"));
            putValue(Action.MNEMONIC_KEY, new Integer('Q'));
        }

        public void actionPerformed(ActionEvent event)
    {
      String s = jcSearch.getText().trim();
      if (s.length() > 0) {
        File[] files = Repository.getInstance().search(s);
        if (files != null && files.length > 0) {
          jt.clearSelection();
          showFiles(files);
          // having this as well is more consistent and even nicer...
          Object[] arguments = { new Integer(files.length) };
          setStatus(MessageFormat.format
                (XNap.tr("Found {0} files"), arguments));

        }
        else {
          setStatus(s + XNap.tr("not found in library", 1, 0));
        }
        jcSearch.addDistinctItemAtTop(s);
      }
      else {
        setStatus(XNap.tr("What are you trying to search for?"));
      }
        }

    }

    protected class SelectionListener implements ActionListener
    {
    public void actionPerformed(ActionEvent event)
    {
      int row = jta.getSelectedRow();
     
      if (row == -1 || jta.getSelectedRowCount() != 1)
        return;
     
      if (row == currentRow) {
        displayFile(ltm.get(row));
      }
    }
    }

    private class DisplayThread extends Thread
    {
    private ViewerPanel panel;

    public DisplayThread()
    {
      super("LibraryPanelLoader");

      start();
    }

    public void setPanel(ViewerPanel newValue)
    {
      panel = newValue;

      this.interrupt();
      synchronized(this) {
        this.notify();
      }

      // seems to have died, start again
      if (!isAlive()) {
        start();
      }
    }
 
    public void run()
    {
      while (true) {
        while (panel == null) {
          synchronized (this) {
            try {
              this.wait();
            }
            catch (InterruptedException e) {
            }
          }
        }

        panel.display();
        Runnable r = new Runnable()
          {
            private ViewerPanel p = panel;

            public void run()
            {
              jspPreview.getHorizontalScrollBar().setValue(0);
              jspPreview.getVerticalScrollBar().setValue(0);
              jspPreview.setViewportView(p);
              jlStatus.setText(p.getStatus());
            }
          };
        try {
          SwingUtilities.invokeAndWait(r);
        }
        catch (Exception e) {
        }
        panel = null;
      }
    }

    }
}
TOP

Related Classes of xnap.gui.LibraryPanel$DisplayThread

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.