org.xmind.ui.internal.dnd.FileDndClient.java Source code

Java tutorial

Introduction

Here is the source code for org.xmind.ui.internal.dnd.FileDndClient.java

Source

/* ******************************************************************************
 * Copyright (c) 2006-2012 XMind Ltd. and others.
 * 
 * This file is a part of XMind 3. XMind releases 3 and
 * above are dual-licensed under the Eclipse Public License (EPL),
 * which is available at http://www.eclipse.org/legal/epl-v10.html
 * and the GNU Lesser General Public License (LGPL), 
 * which is available at http://www.gnu.org/licenses/lgpl.html
 * See http://www.xmind.net/license.html for details.
 * 
 * Contributors:
 *     XMind Ltd. - initial API and implementation
 *******************************************************************************/
package org.xmind.ui.internal.dnd;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialogWithToggle;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.FileTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.dnd.TransferData;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.internal.DPIUtil;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.xmind.core.IFileEntry;
import org.xmind.core.ITopic;
import org.xmind.core.IWorkbook;
import org.xmind.core.util.FileUtils;
import org.xmind.core.util.HyperlinkUtils;
import org.xmind.gef.GEF;
import org.xmind.gef.IViewer;
import org.xmind.gef.Request;
import org.xmind.gef.draw2d.geometry.Geometry;
import org.xmind.gef.part.IPart;
import org.xmind.ui.internal.MindMapUIPlugin;
import org.xmind.ui.internal.dialogs.DialogMessages;
import org.xmind.ui.internal.protocols.FilePathParser;
import org.xmind.ui.mindmap.MindMapUI;
import org.xmind.ui.prefs.PrefConstants;
import org.xmind.ui.util.ImageFormat;
import org.xmind.ui.util.Logger;

@SuppressWarnings("restriction")
public class FileDndClient extends MindMapDNDClientBase {

    private static final String CREATE_IMAGE = "CREATE_IMAGE"; //$NON-NLS-1$

    private static final String ADD_EXTERNAL_FILE = "dndConfirm.ExternalFile"; //$NON-NLS-1$

    private class FileDropHandler {

        private String path;
        private String active;

        public FileDropHandler(String path, String action) {
            this.path = path;
            this.active = action;
        }

        public void createViewerElements(IWorkbook workbook, ITopic targetParent, List<Object> elements) {
            File file = new File(path);
            if (PrefConstants.CREATE_HYPERLINK.equals(active)) {
                elements.add(createFileHyperlinkTopic(workbook, file));
            } else if (PrefConstants.CREATE_ATTACHMENT.equals(active)) {
                elements.add(createAttachmentTopic(workbook, file, null));
            } else if (CREATE_IMAGE.equals(active)) {
                if (targetParent != null) {
                    elements.add(createImageOnTopic(workbook, targetParent, file));
                }
            }
        }

        private ITopic createFileHyperlinkTopic(IWorkbook workbook, File file) {
            ITopic topic = workbook.createTopic();
            topic.setTitleText(file.getName());
            topic.setHyperlink(FilePathParser.toURI(file.getAbsolutePath(), false));
            return topic;
        }

        private ITopic createAttachmentTopic(IWorkbook workbook, File file, ITopic parent) {
            ITopic topic = workbook.createTopic();
            topic.setTitleText(file.getName());
            if (file.isDirectory()) {
                String[] subfiles = file.list();
                for (int i = 0; i < subfiles.length; i++) {
                    File subfile = new File(file, subfiles[i]);
                    ITopic subtopic = createAttachmentTopic(workbook, subfile, topic);
                    topic.add(subtopic, ITopic.ATTACHED);
                }
            } else {
                try {
                    IFileEntry entry = workbook.getManifest().createAttachmentFromFilePath(file.getAbsolutePath());
                    entry.decreaseReference();
                    entry.increaseReference();
                    if (isImagePath(file.getAbsolutePath())) {
                        Dimension size = getImageSize(file.getAbsolutePath());
                        if (size != null) {
                            topic.getImage().setSource(HyperlinkUtils.toAttachmentURL(entry.getPath()));
                            topic.getImage().setSize(size.width, size.height);
                            topic.setTitleText(""); //$NON-NLS-1$
                        } else {
                            topic.setHyperlink(HyperlinkUtils.toAttachmentURL(entry.getPath()));
                        }
                    } else {
                        topic.setHyperlink(HyperlinkUtils.toAttachmentURL(entry.getPath()));
                    }
                } catch (IOException e) {
                    Logger.log(e, "Error occurred when transfering file: " //$NON-NLS-1$
                            + file.getAbsolutePath());
                }
            }
            return topic;
        }

        private Object createImageOnTopic(IWorkbook workbook, ITopic topic, File file) {
            try {
                IFileEntry entry = workbook.getManifest().createAttachmentFromFilePath(file.getAbsolutePath());
                entry.decreaseReference();
                entry.increaseReference();

                Dimension size = getImageSize(file.getAbsolutePath());
                if (size != null) {
                    return createModifyImageCommand(topic, HyperlinkUtils.toAttachmentURL(entry.getPath()),
                            size.width, size.height, null);
                } else {
                    Logger.log("[FileDndClient] Failed to open invalid image file: " //$NON-NLS-1$
                            + file.getAbsolutePath());
                }
            } catch (IOException e) {
                Logger.log(e, "Error occurred when transfering file: " //$NON-NLS-1$
                        + file.getAbsolutePath());
            }
            return null;
        }
    }

    private FileTransfer transfer = FileTransfer.getInstance();

    private IPreferenceStore pref = null;

    public Object getData(Transfer transfer, TransferData data) {
        if (transfer == this.transfer) {
            return this.transfer.nativeToJava(data);
        }
        return null;
    }

    public Transfer getTransfer() {
        return transfer;
    }

    public Object toTransferData(Object[] viewerElements, IViewer viewer) {
        return null;
    }

    @Override
    protected Object[] toViewerElements(Object transferData, Request request, IWorkbook workbook,
            ITopic targetParent, boolean dropInParent) {
        if (transferData instanceof String[]) {
            String[] paths = (String[]) transferData;
            if (workbook != null) {
                List<FileDropHandler> handlers = createFileDropHandlers(paths,
                        request.getIntParameter(GEF.PARAM_DROP_OPERATION, DND.DROP_DEFAULT), dropInParent,
                        request.getTargetViewer().getControl().getShell());
                if (handlers != null) {
                    List<Object> elements = new ArrayList<Object>(handlers.size());
                    for (FileDropHandler handler : handlers) {
                        handler.createViewerElements(workbook, targetParent, elements);
                    }
                    return elements.toArray();
                }
            }
        }
        return null;
    }

    private List<FileDropHandler> createFileDropHandlers(String[] paths, int operation, boolean dropInParent,
            Shell shell) {
        List<FileDropHandler> handlers = new ArrayList<FileDropHandler>(paths.length);
        if (isSingleImage(paths) && dropInParent) {
            createImageFileDropHandler(paths[0], operation, handlers);
        } else if (isSingleFolder(paths)) {
            createSingleFolderDropHandler(paths[0], operation, handlers, shell);
        } else if (isSingleFile(paths)) {
            createSingleFileDropHandler(paths[0], operation, handlers, shell);
        } else {
            createMultipleFilesDropHandler(paths, operation, handlers, shell);
        }
        return handlers;
    }

    private void createImageFileDropHandler(String imagePath, int operation, List<FileDropHandler> handlers) {
        if (operation == DND.DROP_LINK) {
            createFileDropHandlers(handlers, PrefConstants.CREATE_HYPERLINK, imagePath);
        } else {
            createFileDropHandlers(handlers, CREATE_IMAGE, imagePath);
        }
    }

    private void createSingleFolderDropHandler(String path, int operation, List<FileDropHandler> handlers,
            Shell shell) {
        if (operation == DND.DROP_LINK) {
            createFileDropHandlers(handlers, PrefConstants.CREATE_HYPERLINK, path);
        } else if (operation == DND.DROP_COPY) {
            createFileDropHandlers(handlers, PrefConstants.CREATE_ATTACHMENT, path);
        } else {
            askForConfirmation(shell, DialogMessages.DND_ExternalFolder, ADD_EXTERNAL_FILE,
                    NLS.bind(DialogMessages.DND_ExternalFolder_confirmation_with_path, path), handlers, path);
        }
    }

    private void createSingleFileDropHandler(String path, int operation, List<FileDropHandler> handlers,
            Shell shell) {
        if (operation == DND.DROP_LINK) {
            createFileDropHandlers(handlers, PrefConstants.CREATE_HYPERLINK, path);
        } else if (operation == DND.DROP_COPY) {
            createFileDropHandlers(handlers, PrefConstants.CREATE_ATTACHMENT, path);
        } else {
            askForConfirmation(shell, DialogMessages.DND_ExternalFile, ADD_EXTERNAL_FILE,
                    NLS.bind(DialogMessages.DND_ExternalFile_confirmation_with_path_size, path,
                            org.xmind.ui.viewers.FileUtils.fileLengthToString(new File(path).length())),
                    handlers, path);
        }
    }

    private void createMultipleFilesDropHandler(String[] paths, int operation, List<FileDropHandler> handlers,
            Shell shell) {
        if (operation == DND.DROP_LINK) {
            createFileDropHandlers(handlers, PrefConstants.CREATE_HYPERLINK, paths);
        } else if (operation == DND.DROP_COPY) {
            createFileDropHandlers(handlers, PrefConstants.CREATE_ATTACHMENT, paths);
        } else {
            StringBuffer sb = new StringBuffer(paths.length * 30);
            for (int i = 0; i < paths.length; i++) {
                File file = new File(paths[i]);
                if (i < 3) {
                    if (i > 0) {
                        sb.append('\r');
                        sb.append('\n');
                    }
                    sb.append(paths[i]);
                    if (!file.isDirectory()) {
                        sb.append(' ');
                        sb.append('(');
                        long size = file.length();
                        sb.append(org.xmind.ui.viewers.FileUtils.fileLengthToString(size));
                        sb.append(')');
                    }
                } else {
                    sb.append('\r');
                    sb.append('\n');
                    sb.append(NLS.bind(DialogMessages.DND_MultipleExternalFiles_moreFiles_with_number,
                            paths.length - 3));
                    break;
                }
            }
            askForConfirmation(shell, DialogMessages.DND_MultipleExternalFiles, ADD_EXTERNAL_FILE,
                    NLS.bind(DialogMessages.DND_MultipleExternalFiles_confirmation_with_fileList, sb.toString()),
                    handlers, paths);
        }
    }

    private void askForConfirmation(Shell shell, String itemName, String prefKey, String dialogMessage,
            List<FileDropHandler> handlers, String... paths) {
        String active = getPref().getString(prefKey);
        if ("".equals(active) || PrefConstants.ASK_USER.equals(active)) { //$NON-NLS-1$
            active = null;
        }
        if (active == null) {
            shell.forceActive();
            MessageDialogWithToggle dialog = new MessageDialogWithToggle(shell,
                    NLS.bind(DialogMessages.DND_ConfirmDroppingFileDialog_title_with_type, itemName), null, //
                    dialogMessage, //
                    SWT.ICON_QUESTION, //
                    new String[] { //
                            DialogMessages.DND_ConfirmDroppingFileDialog_LinkButton_text, //
                            DialogMessages.DND_ConfirmDroppingFileDialog_CopyButton_text, //
                            IDialogConstants.CANCEL_LABEL //
                    }, 0, //
                    NLS.bind(DialogMessages.DND_ConfirmDroppingFileDialog_RememberCheck_text_with_type, itemName),
                    false);
            int ret = dialog.open();
            if (ret == IDialogConstants.INTERNAL_ID) {
                active = PrefConstants.CREATE_HYPERLINK;
            } else if (ret == IDialogConstants.INTERNAL_ID + 1) {
                active = PrefConstants.CREATE_ATTACHMENT;
            }
            if (dialog.getToggleState() && active != null) {
                getPref().setValue(prefKey, active);
            }
        }
        if (active != null) {
            createFileDropHandlers(handlers, active, paths);
        }
    }

    private void createFileDropHandlers(List<FileDropHandler> handlers, String action, String... paths) {
        for (int i = 0; i < paths.length; i++) {
            handlers.add(new FileDropHandler(paths[i], action));
        }
    }

    private IPreferenceStore getPref() {
        if (pref == null) {
            pref = MindMapUIPlugin.getDefault().getPreferenceStore();
        }
        return pref;
    }

    private static boolean isSingleImage(String[] paths) {
        return paths.length == 1 && isImagePath(paths[0]);
    }

    private static boolean isImagePath(String path) {
        String ext = FileUtils.getExtension(path);
        return ImageFormat.findByExtension(ext, null) != null;
    }

    private static boolean isSingleFolder(String[] paths) {
        return paths.length == 1 && new File(paths[0]).isDirectory();
    }

    private static boolean isSingleFile(String[] paths) {
        return paths.length == 1;
    }

    private static Dimension getImageSize(String path) {
        try {
            Image tempImage = new Image(Display.getCurrent(), path);
            Rectangle imageBounds = tempImage.getBounds();
            tempImage.dispose();
            boolean needZoom = DPIUtil.getDeviceZoom() > 100;
            int width = needZoom ? imageBounds.width / 2 : imageBounds.width;
            int height = needZoom ? imageBounds.height / 2 : imageBounds.height;
            return Geometry.getScaledConstrainedSize(width, height, MindMapUI.IMAGE_INIT_WIDTH,
                    MindMapUI.IMAGE_INIT_HEIGHT);
        } catch (Throwable e) {
        }
        return null;
    }

    public boolean canLink(TransferData data, IViewer viewer, Point location, IPart target) {
        return true;
    }

}