/* * This file is part of muCommander, http://www.mucommander.com * Copyright (C) 2002-2016 Maxence Bernard * * muCommander 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 3 of the License, or * (at your option) any later version. * * muCommander 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, see <http://www.gnu.org/licenses/>. */ package com.mucommander.ui.dnd; import com.mucommander.commons.file.AbstractFile; import com.mucommander.commons.file.util.FileSet; import com.mucommander.ui.main.FolderPanel; import com.mucommander.ui.main.table.FileTable; import com.mucommander.ui.main.table.FileTableModel; import java.awt.*; import java.awt.dnd.*; import java.awt.event.InputEvent; /** * This class adds 'drag' support to components that are registered using the {@link #enableDrag(java.awt.Component)} * method. * * <p>A {@link com.mucommander.ui.main.FolderPanel} instance has to be specified at creation time, this instance will be * used to retrieve the list of selected/marked file(s) that are dragged, whenever a drag operation is initiated on * of the registered components. * * @author Maxence Bernard */ public class FileDragSourceListener implements DragGestureListener, DragSourceListener { /** the FolderPanel instance used to retrieve dragged files */ private FolderPanel folderPanel; /** * Creates a new FileDragSourceListener using the specified FolderPanel that will be used to retreive the dragged files * based on the current file selection. * * @param folderPanel the FolderPanel used to retrieve the list of selected/marked file(s) that are dragged */ public FileDragSourceListener(FolderPanel folderPanel) { this.folderPanel = folderPanel; } /** * Enables drag operations on the specified component. This class will be notified wheneven drag operations * are performed on the component. * * @param c the component for which to add 'drag' support */ public void enableDrag(Component c) { DragSource dragSource = DragSource.getDefaultDragSource(); dragSource.createDefaultDragGestureRecognizer(c, DnDConstants.ACTION_COPY|DnDConstants.ACTION_MOVE|DnDConstants.ACTION_LINK, this); } // /** // * Creates a custom DragGestureEvent instance re-using the information contained in the given DragGestureEvent, but // * overridding the actions with the specified actions bitwise mask. // * When used with <code>DragSource.startDrag</code>, this allows to start a drag operation with a different source // * action set from the one specified in the <code>DragGestureRecognizer</code>, based on the current state and // * contents of the FolderPanel. // */ // private DragGestureEvent createCustomDragGestureEvent(DragGestureEvent originalDGE, int actions) { // Vector eventList = new Vector(); // Iterator eventIterator = originalDGE.iterator(); // // while(eventIterator.hasNext()) // eventList.add(eventIterator.next()); // // DragGestureRecognizer dragGestureRecognizer = originalDGE.getSourceAsDragGestureRecognizer(); // dragGestureRecognizer.setSourceActions(actions); // // return new DragGestureEvent(dragGestureRecognizer, // actions, // originalDGE.getDragOrigin(), // eventList); // } ///////////////////////////////// // DragGestureListener methods // ///////////////////////////////// public void dragGestureRecognized(DragGestureEvent event) { if(folderPanel.getMainFrame().getNoEventsMode()) return; FileTable fileTable = folderPanel.getFileTable(); FileTableModel tableModel = fileTable.getFileTableModel(); // Return (do not initiate drag) if mouse button2 or button3 was used if((event.getTriggerEvent().getModifiers() & (InputEvent.BUTTON2_MASK|InputEvent.BUTTON3_MASK))!=0) return; // Do not use that to retrieve the current selected file as it is inaccurate: the selection could have changed since the // the mouse was clicked. // AbstractFile selectedFile = fileTable.getSelectedFile(false); // // Return if selected file is null (could happen if '..' is selected) // if(selectedFile==null) // return; // Find out which row was clicked int clickedRow = fileTable.rowAtPoint(event.getDragOrigin()); // Return (do not initiate drag) if the selected file is the parent folder '..' if (clickedRow==-1 || fileTable.isParentFolder(clickedRow)) return; // Retrieve the file corresponding to the clicked row AbstractFile selectedFile = tableModel.getFileAtRow(clickedRow); // Find out which files are to be dragged, based on the selected file and currenlty marked files. // If there are some files marked, drag marked files only if the selected file is one of the marked files. // In any other case, only drag the selected file. FileSet markedFiles; FileSet draggedFiles; if(tableModel.getNbMarkedFiles()>0 && (markedFiles=fileTable.getSelectedFiles()).contains(selectedFile)) { draggedFiles = markedFiles; } else { draggedFiles = new FileSet(folderPanel.getCurrentFolder(), selectedFile); } // Set initial DnDContext information DnDContext.setDragInitiatedByMucommander(true); DnDContext.setDragInitiator(folderPanel); DnDContext.setDragGestureModifiersEx(event.getTriggerEvent().getModifiersEx()); // Start dragging DragSource.getDefaultDragSource().startDrag(event, null, new TransferableFileSet(draggedFiles), this); // DragSource.getDefaultDragSource().startDrag(createCustomDragGestureEvent(event, DnDConstants.ACTION_MOVE), null, new TransferableFileSet(draggedFiles), this); } /////////////////////////////////////// // DragSourceListener implementation // /////////////////////////////////////// public void dragEnter(DragSourceDragEvent event) { // Update drag gesture modifiers DnDContext.setDragGestureModifiersEx(event.getGestureModifiersEx()); } public void dragOver(DragSourceDragEvent event) { } public void dropActionChanged(DragSourceDragEvent event) { // Update drag gesture modifiers DnDContext.setDragGestureModifiersEx(event.getGestureModifiersEx()); } public void dragExit(DragSourceEvent event) { } public void dragDropEnd(DragSourceDropEvent event) { // Reset DnDContext information DnDContext.setDragInitiatedByMucommander(false); DnDContext.setDragInitiator(null); DnDContext.setDragGestureModifiersEx(0); } }