All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.fife.ui.rtextfilechooser.FileSystemTreeActions Maven / Gradle / Ivy

package org.fife.ui.rtextfilechooser;

import java.awt.Component;
import java.awt.Window;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.EventObject;
import java.util.List;
import java.util.ResourceBundle;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.DefaultCellEditor;
import javax.swing.JOptionPane;
import javax.swing.JTree;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.tree.DefaultTreeCellEditor;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeCellEditor;
import javax.swing.tree.TreePath;

import org.fife.ui.rtextfilechooser.FileSystemTree.FileSystemTreeNode;
import org.fife.ui.rtextfilechooser.extras.FileIOExtras;


/**
 * Actions used by FileSystemTrees.
 *
 * @author Robert Futrell
 * @version 1.0
 */
class FileSystemTreeActions {


	/**
	 * Base class for file system tree-related actions.
	 */
	abstract static class AbstractTreeAction extends AbstractAction {

		protected FileSystemTree tree;
		private static ResourceBundle msg = ResourceBundle.getBundle(
							"org.fife.ui.rtextfilechooser.FileSystemTree");

		public AbstractTreeAction(FileSystemTree tree) {
			this.tree = tree;
		}

		protected String getString(String key) {
			return msg.getString(key);
		}

	}


	/**
	 * Action that handles deleting files.
	 */
	static class DeleteAction extends AbstractTreeAction {

		private Window window;
		private boolean hard;

		public DeleteAction(Window parent, FileSystemTree tree, boolean hard) {
			super(tree);
			putValue(NAME, getString("Delete"));
			this.hard = hard;
			int modifiers = hard ? InputEvent.SHIFT_MASK : 0;
			putValue(Action.ACCELERATOR_KEY,
					KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, modifiers));
			this.window = parent;
		}

		public void actionPerformed(ActionEvent e) {

			if (window==null) { // Often unfortunately null
				window = SwingUtilities.getWindowAncestor(tree);
			}

			// Get the selected files.  If there are no selected files (i.e.,
			// they pressed "delete" when no files were selected), beep.
			File[] files = tree.getSelectedFiles();
			if (files==null || files.length==0) {
				UIManager.getLookAndFeel().provideErrorFeedback(window);
				return;
			}

			FileIOExtras extras = FileIOExtras.getInstance();
			if (!hard && extras!=null) {
				handleDeleteNative(files, extras);
			}
			else {
				handleDeleteViaJava(files);
			}

		}

		private void handleDeleteNative(File[] files, FileIOExtras extras) {
			if (extras.moveToRecycleBin(window, files, true, true)) {
				refresh();
			}
			else {
				UIManager.getLookAndFeel().provideErrorFeedback(window);
			}
		}

		private void handleDeleteViaJava(File[] files) {

			// Prompt to confirm the file deletion.
			int count = files.length;
			int choice;
			if (count==1) {
				String fileName = files[0].getName();
				choice = JOptionPane.showConfirmDialog(window,
					RTextFileChooser.msg.
							getString("DeleteConfirmPrompt") + fileName + "?");
			}
			else { // count>1
				choice = JOptionPane.showConfirmDialog(window,
					RTextFileChooser.msg.
							getString("DeleteMultipleConfirmPrompt"));
			}

			// If they chose "yes," delete the files.
			if (choice==JOptionPane.YES_OPTION) {
				for (int i=0; i

* * At the moment, if the selection is more than one file, or a directory, * or if the destination file already exists, the system beeps and the * copy does not occur. */ static class PasteAction extends AbstractTreeAction { public PasteAction(FileSystemTree tree) { super(tree); putValue(NAME, getString("Paste")); putValue(MNEMONIC_KEY, new Integer(getString("PasteMnemonic").charAt(0))); int mod = tree.getToolkit().getMenuShortcutKeyMask(); putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_V, mod)); } public void actionPerformed(ActionEvent e) { TreePath path = tree.getSelectionPath(); boolean copied = false; if (path!=null) { // Should always be true. FileSystemTreeNode node = (FileSystemTreeNode)path. getLastPathComponent(); File destDir = node.getFile(); if (destDir.isDirectory()) { // Should always be true Clipboard clip = tree.getToolkit().getSystemClipboard(); Transferable contents = clip.getContents(null); DataFlavor accepted = DataFlavor.javaFileListFlavor; if (contents.isDataFlavorSupported(accepted)) { try { List files = (List)contents. getTransferData(accepted); if (files!=null && files.size()==1) { File toCopy = (File)files.get(0); if (toCopy.isFile()) { File dest = new File(destDir, toCopy.getName()); if (!dest.exists()) { Utilities.copyFile(toCopy, dest); tree.refreshChildren(node); ((DefaultTreeModel)tree.getModel()). reload(node); tree.setSelectedFile(dest); copied = true; } } } } catch (UnsupportedFlavorException ufe) { ufe.printStackTrace(); // Never happens } catch (IOException ioe) { ioe.printStackTrace(); } } } } if (!copied) { UIManager.getLookAndFeel().provideErrorFeedback(tree); } } /** * Returns whether the system clipboard contents are "valid" for this * action to be enabled. Currently this verifies that the contents * are just a single file. Applications can enable this action based * on the return value of this method. * * @return Whether the contents of the clipboard are "valid" for this * action to be used. */ public boolean isClipboardContentValid() { Clipboard clip = tree.getToolkit().getSystemClipboard(); Transferable contents = clip.getContents(null); DataFlavor accepted = DataFlavor.javaFileListFlavor; if (contents.isDataFlavorSupported(accepted)) { try { List files = (List)contents.getTransferData(accepted); if (files!=null && files.size()==1) { return ((File)files.get(0)).isFile(); } } catch (UnsupportedFlavorException ufe) { ufe.printStackTrace(); // Never happens } catch (IOException ioe) { ioe.printStackTrace(); } } return false; } } /** * Action that "refreshes" the currently selected directory in the * directory tree. */ static class RefreshAction extends AbstractTreeAction { public RefreshAction(FileSystemTree tree) { super(tree); putValue(NAME, getString("Refresh")); putValue(MNEMONIC_KEY, new Integer(getString("RefreshMnemonic").charAt(0))); putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_F5, 0)); } public void actionPerformed(ActionEvent e) { TreePath path = tree.getSelectionPath(); // If they've selected a tree node (should be a directory to work) if (path!=null) { FileSystemTreeNode node = (FileSystemTreeNode)path. getLastPathComponent(); File file = node.getFile(); DefaultTreeModel model = (DefaultTreeModel)tree.getModel(); // The file should be a directory. The only catch is // that maybe the directory was deleted since the last // time we cached. NOTE: We MUST check whether the file // exists BEFORE we check whether it's a directory because // isDirectory() can return true for a directory that has // been removed after the File object was created, despite // what the Javadoc says. // If the directory no longer exists, refresh the structure // from the parent directory down, in case other stuff has // changed too. if (!file.exists()) { int count = path.getPathCount(); if (count>1) { node = (FileSystemTreeNode)path. getPathComponent(count-2); tree.refreshChildren(node); model.reload(node); } else { // It's the one and only file in the path... tree.removeSelectionPath(path); model.reload(node); } } // If the directory still exists... else if (file.isDirectory()) { tree.refreshChildren(node); model.reload(node); // Causes repaint properly. } // Otherwise, they've removed what was a directory when we // cached data, and created a regular file in its place... // Again, we'll refresh the parent directory's cached data. else { int count = path.getPathCount(); if (count>1) { node = (FileSystemTreeNode)path. getPathComponent(count-2); tree.refreshChildren(node); model.reload(node); } else { // It's the one and only file in the path... tree.removeSelectionPath(path); model.reload(node); } } } // No tree node selected, but we're "in" a directory else if (tree.getRoot()!=null) { tree.refreshChildren(null); } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy