Package org.freeplane.features.clipboard.mindmapmode

Source Code of org.freeplane.features.clipboard.mindmapmode.MClipboardController$ImageFlavorHandler

/*
*  Freeplane - mind map editor
*  Copyright (C) 2008 Joerg Mueller, Daniel Polansky, Christian Foltin, Dimitry Polivaev
*
*  This file is created by Dimitry Polivaev in 2008.
*
*  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, see <http://www.gnu.org/licenses/>.
*/
package org.freeplane.features.clipboard.mindmapmode;

import java.awt.Graphics2D;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.imageio.ImageIO;
import javax.swing.JFileChooser;
import javax.swing.text.BadLocationException;
import javax.swing.text.Element;
import javax.swing.text.ElementIterator;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;

import org.apache.commons.lang.StringUtils;
import org.freeplane.core.resources.ResourceController;
import org.freeplane.core.ui.ExampleFileFilter;
import org.freeplane.core.ui.components.UITools;
import org.freeplane.core.util.FileUtils;
import org.freeplane.core.util.FixedHTMLWriter;
import org.freeplane.core.util.HtmlUtils;
import org.freeplane.core.util.LogUtils;
import org.freeplane.core.util.TextUtils;
import org.freeplane.features.attribute.AttributeController;
import org.freeplane.features.clipboard.ClipboardController;
import org.freeplane.features.clipboard.MindMapNodesSelection;
import org.freeplane.features.link.LinkController;
import org.freeplane.features.link.NodeLinks;
import org.freeplane.features.link.mindmapmode.MLinkController;
import org.freeplane.features.map.FreeNode;
import org.freeplane.features.map.IMapSelection;
import org.freeplane.features.map.MapModel;
import org.freeplane.features.map.MapReader;
import org.freeplane.features.map.MapReader.NodeTreeCreator;
import org.freeplane.features.map.MapWriter.Hint;
import org.freeplane.features.map.MapWriter.Mode;
import org.freeplane.features.map.NodeModel;
import org.freeplane.features.map.mindmapmode.MMapController;
import org.freeplane.features.mode.Controller;
import org.freeplane.features.mode.ModeController;
import org.freeplane.features.text.TextController;
import org.freeplane.features.text.mindmapmode.MTextController;
import org.freeplane.features.url.UrlManager;
import org.freeplane.n3.nanoxml.XMLException;
import org.freeplane.view.swing.features.filepreview.ExternalResource;
import org.freeplane.view.swing.features.filepreview.ViewerController;
import org.freeplane.view.swing.features.filepreview.ViewerController.PasteMode;

/**
* @author Dimitry Polivaev
*/
public class MClipboardController extends ClipboardController {
  public static final String RESOURCES_REMIND_USE_RICH_TEXT_IN_NEW_NODES = "remind_use_rich_text_in_new_nodes";
  private class DirectHtmlFlavorHandler implements IDataFlavorHandler {
    private String textFromClipboard;

    public DirectHtmlFlavorHandler(final String textFromClipboard) {
      this.textFromClipboard = textFromClipboard;
    }

    void paste(final NodeModel target) {
      textFromClipboard = cleanHtml(textFromClipboard);
      final NodeModel node = Controller.getCurrentModeController().getMapController().newNode(textFromClipboard,
          Controller.getCurrentController().getMap());
      final String text = textFromClipboard;
      final Matcher m = HREF_PATTERN.matcher(text);
      if (m.matches()) {
        final String body = m.group(2);
        if (!body.matches(".*<\\s*a.*")) {
          final String href = m.group(1);
          ((MLinkController) LinkController.getController()).setLinkTypeDependantLink(node, href);
        }
      }
      ((MMapController) Controller.getCurrentModeController().getMapController()).insertNode(node, target);
    }

    public void paste(Transferable t, final NodeModel target, final boolean asSibling, final boolean isLeft, int dropAction) {
      paste(target);
    }
  }

  private class FileListFlavorHandler implements IDataFlavorHandler {
    final List<File> fileList;

    public FileListFlavorHandler(final List<File> fileList) {
      super();
      this.fileList = fileList;
    }

    public void paste(Transferable t, final NodeModel target, final boolean asSibling, final boolean isLeft, int dropAction) {
      boolean pasteImages = dropAction == DnDConstants.ACTION_COPY;
      ViewerController viewerController = ((ViewerController)Controller.getCurrentModeController().getExtension(ViewerController.class));
      for (final File file : fileList) {
        if(pasteImages  && viewerController.paste(file, target, PasteMode.valueOf(asSibling), isLeft)){
          continue;
        }
        final MMapController mapController = (MMapController) Controller.getCurrentModeController().getMapController();
        final NodeModel node = mapController.newNode(file.getName(), target.getMap());
        ((MLinkController) LinkController.getController()).setLinkTypeDependantLink(node, file);
        mapController.insertNode(node, target, asSibling, isLeft, isLeft);
      }
    }
  }

  interface IDataFlavorHandler {
    void paste(Transferable t, NodeModel target, boolean asSibling, boolean isLeft, int dropAction);
  }

  private class MindMapNodesFlavorHandler implements IDataFlavorHandler {
    private final String textFromClipboard;

    public MindMapNodesFlavorHandler(final String textFromClipboard) {
      this.textFromClipboard = textFromClipboard;
    }

    public void paste(Transferable t, final NodeModel target, final boolean asSibling, final boolean isLeft, int dropAction) {
      if (textFromClipboard != null) {
        paste(textFromClipboard, target, asSibling, isLeft);
      }
    }

    private void paste(final String text, final NodeModel target, final boolean asSibling, final boolean isLeft) {
      final String[] textLines = text.split(ClipboardController.NODESEPARATOR);
      final MMapController mapController = (MMapController) Controller.getCurrentModeController().getMapController();
      final MapReader mapReader = mapController.getMapReader();
      final NodeTreeCreator nodeTreeCreator = mapReader.nodeTreeCreator(target.getMap());
      nodeTreeCreator.setHint(Hint.MODE, Mode.CLIPBOARD);
      for (int i = 0; i < textLines.length; ++i) {
        try {
          final NodeModel newModel = nodeTreeCreator.create(new StringReader(textLines[i]));
          newModel.removeExtension(FreeNode.class);
          final boolean wasLeft = newModel.isLeft();
          mapController.insertNode(newModel, target, asSibling, isLeft, wasLeft != isLeft);
        }
        catch (final XMLException e) {
          LogUtils.severe("error on paste", e);
        }
      }
      nodeTreeCreator.finish(target);
    }
  }

  private static class PasteHtmlWriter extends FixedHTMLWriter {
    private final Element element;

    public PasteHtmlWriter(final Writer writer, final Element element, final HTMLDocument doc, final int pos,
                           final int len) {
      super(writer, doc, pos, len);
      this.element = getStandAloneElement(element);
    }

    @Override
    protected ElementIterator getElementIterator() {
      return new ElementIterator(element);
    }

    private Element getStandAloneElement(final Element element) {
      final String name = element.getName();
      if (name.equals("ul") || name.equals("ol") || name.equals("table") || name.equals("html")) {
        return element;
      }
      return getStandAloneElement(element.getParentElement());
    }

    @Override
    public void write() throws IOException, BadLocationException {
      if (element.getName().equals("html")) {
        super.write();
        return;
      }
      write("<html>");
      super.write();
      write("</html>");
    }
  }

  private class StringFlavorHandler implements IDataFlavorHandler {
    private final String textFromClipboard;

    public StringFlavorHandler(final String textFromClipboard) {
      this.textFromClipboard = textFromClipboard;
    }

    public void paste(Transferable t, final NodeModel target, final boolean asSibling, final boolean isLeft, int dropAction) {
      final TextFragment[] textFragments = split(textFromClipboard);
      pasteStringWithoutRedisplay(textFragments, target, asSibling, isLeft);
    }

    private TextFragment[] split(final String textFromClipboard) {
      final LinkedList<TextFragment> textFragments = new LinkedList<TextFragment>();
      final String[] textLines = textFromClipboard.split("\n");
      for (int i = 0; i < textLines.length; ++i) {
        String text = textLines[i];
        text = text.replaceAll("\t", "        ");
        if (text.matches(" *")) {
          continue;
        }
        int depth = 0;
        while (depth < text.length() && text.charAt(depth) == ' ') {
          ++depth;
        }
        final String visibleText = text.trim();
        final String link = LinkController.findLink(text);
        if (!visibleText.equals("")) {
          textFragments.add(new TextFragment(visibleText, link, depth));
        }
      }
      return textFragments.toArray(new TextFragment[textFragments.size()]);
    }
  }

  private class StructuredHtmlFlavorHandler implements IDataFlavorHandler {
    private final String textFromClipboard;

    public StructuredHtmlFlavorHandler(final String textFromClipboard) {
      this.textFromClipboard = textFromClipboard;
    }

    private String addFragment(final HTMLDocument doc, final Element element, final int depth, final int start,
                               final int end, final LinkedList<TextFragment> htmlFragments)
            throws BadLocationException, IOException {
      final String paragraphText = doc.getText(start, end - start).trim();
      if (paragraphText.length() > 0) {
        final StringWriter out = new StringWriter();
        new PasteHtmlWriter(out, element, doc, start, end - start).write();
        final String string = out.toString();
        if (!string.equals("")) {
          final String link = LinkController.findLink(string);
          final TextFragment htmlFragment = new TextFragment(string, link, depth);
          htmlFragments.add(htmlFragment);
        }
      }
      return paragraphText;
    }

    private Element getParentElement(final HTMLDocument doc) {
      final Element htmlRoot = doc.getDefaultRootElement();
      final Element bodyElement = htmlRoot.getElement(htmlRoot.getElementCount() - 1);
      Element parentCandidate = bodyElement;
      do {
        if (parentCandidate.getElementCount() > 1) {
          return parentCandidate;
        }
        parentCandidate = parentCandidate.getElement(0);
      } while (!(parentCandidate.isLeaf() || parentCandidate.getName().equalsIgnoreCase("p-implied")));
      return bodyElement;
    }

    private boolean isSeparateElement(final Element current) {
      return !current.isLeaf();
    }

    public void paste(Transferable t, final NodeModel target, final boolean asSibling, final boolean isLeft, int dropAction) {
      pasteHtmlWithoutRedisplay(textFromClipboard, target, asSibling, isLeft);
    }

    private void pasteHtmlWithoutRedisplay(final Object t, final NodeModel parent, final boolean asSibling,
                                           final boolean isLeft) {
      String textFromClipboard = (String) t;
      textFromClipboard = cleanHtml(textFromClipboard);
      final TextFragment[] htmlFragments = split(textFromClipboard);
      pasteStringWithoutRedisplay(htmlFragments, parent, asSibling, isLeft);
    }

    private void split(final HTMLDocument doc, final Element parent, final LinkedList<TextFragment> htmlFragments,
                       int depth) throws BadLocationException, IOException {
      final int elementCount = parent.getElementCount();
      int headerDepth = 0;
      boolean headerFound = false;
      int start = -1;
      int end = -1;
      Element last = null;
      for (int i = 0; i < elementCount; i++) {
        final Element current = parent.getElement(i);
        final String name = current.getName();
        final Matcher matcher = HEADER_REGEX.matcher(name);
        if (matcher.matches()) {
          try {
            if (!headerFound) {
              depth--;
            }
            final int newHeaderDepth = Integer.parseInt(matcher.group(1));
            depth += newHeaderDepth - headerDepth;
            headerDepth = newHeaderDepth;
            headerFound = true;
          }
          catch (final NumberFormatException e) {
            LogUtils.severe(e);
          }
        }
        else {
          if (headerFound) {
            headerFound = false;
            depth++;
          }
        }
        final boolean separateElement = isSeparateElement(current);
        if (separateElement && current.getElementCount() != 0) {
          start = -1;
          last = null;
          split(doc, current, htmlFragments, depth + 1);
          continue;
        }
        if (separateElement && start != -1) {
          addFragment(doc, last, depth, start, end, htmlFragments);
        }
        if (start == -1 || separateElement) {
          start = current.getStartOffset();
          last = current;
        }
        end = current.getEndOffset();
        if (separateElement) {
          addFragment(doc, current, depth, start, end, htmlFragments);
        }
      }
      if (start != -1) {
        addFragment(doc, last, depth, start, end, htmlFragments);
      }
    }

    private TextFragment[] split(final String text) {
      final LinkedList<TextFragment> htmlFragments = new LinkedList<TextFragment>();
      final HTMLEditorKit kit = new HTMLEditorKit();
      final HTMLDocument doc = new HTMLDocument();
      final StringReader buf = new StringReader(text);
      try {
        kit.read(buf, doc, 0);
        final Element parent = getParentElement(doc);
        split(doc, parent, htmlFragments, 0);
      }
      catch (final IOException e) {
        LogUtils.severe(e);
      }
      catch (final BadLocationException e) {
        LogUtils.severe(e);
      }
      return htmlFragments.toArray(new TextFragment[htmlFragments.size()]);
    }
  }

  private static class TextFragment {
    int depth;
    String link;
    String text;

    public TextFragment(final String text, final String link, final int depth) {
      super();
      this.text = text;
      this.depth = depth;
      this.link = link;
    }
  }

    private class ImageFlavorHandler implements IDataFlavorHandler {
      private static final String IMAGE_FORMAT = "png";
    final private BufferedImage image;

    public ImageFlavorHandler(BufferedImage img) {
      super();
      BufferedImage fixedImg = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB);
      Graphics2D fig = fixedImg.createGraphics();
      fig.drawImage(img, 0, 0, null);
      fig.dispose();
      fixedImg.flush();
      this.image = fixedImg;
    }

        public void paste(Transferable t, NodeModel target, boolean asSibling, boolean isLeft, int dropAction) {
      final ModeController modeController = Controller.getCurrentModeController();
      final MMapController mapController = (MMapController) modeController.getMapController();
            File mindmapFile = target.getMap().getFile();
            if(mindmapFile == null) {
                UITools.errorMessage(TextUtils.getRawText("map_not_saved"));
                return;
            }
      final String mmFileName = mindmapFile.getName();
      String fileNameTemplate = mmFileName.substring(0, mmFileName.lastIndexOf('.')) + "_";
      while (fileNameTemplate.length() < 3)
        fileNameTemplate = fileNameTemplate + '_';
      //file that we'll save to disk.
            File file;
            try {
              final File dir = mindmapFile.getParentFile();
        file = File.createTempFile(fileNameTemplate, "."+IMAGE_FORMAT, dir);
              String imgfilepath=file.getAbsolutePath();
              File tempFile = file = new File(imgfilepath);
              final JFileChooser fileChooser = new JFileChooser(file);   
              final ExampleFileFilter filter = new ExampleFileFilter();
          filter.addExtension(IMAGE_FORMAT);
          fileChooser.setAcceptAllFileFilterUsed(false);
          fileChooser.setFileFilter(filter);
          fileChooser.setSelectedFile(file);
          int returnVal = fileChooser.showSaveDialog(UITools.getFrame());
          if (returnVal != JFileChooser.APPROVE_OPTION) {
            tempFile.delete();
            return;
          }
          file = fileChooser.getSelectedFile();
          if(tempFile.exists() && ! file.getAbsoluteFile().equals(tempFile)){
            tempFile.delete();
          }
          if(file.isDirectory())
            return;
          if(! FileUtils.getExtension(file.getName()).equals(IMAGE_FORMAT))
            file = new File(file.getPath() + '.' + IMAGE_FORMAT);
          final URI uri = LinkController.toLinkTypeDependantURI(mindmapFile, file);
              ImageIO.write(image, IMAGE_FORMAT, file);
        final NodeModel node = mapController.newNode(file.getName(), target.getMap());
        final ExternalResource extension = new ExternalResource(uri);
        node.addExtension(extension);
        mapController.insertNode(node, target, asSibling, isLeft, isLeft);
            }
            catch (IOException e) {
              e.printStackTrace();
            }
        }
    }
  private static final Pattern HEADER_REGEX = Pattern.compile("h(\\d)", Pattern.CASE_INSENSITIVE);
  private static final Pattern HREF_PATTERN = Pattern
      .compile("<html>\\s*<body>\\s*<a\\s+href=\"([^>]+)\">(.*)</a>\\s*</body>\\s*</html>");
  private static final String RESOURCE_UNFOLD_ON_PASTE = "unfold_on_paste";
  public static final String RESOURCES_CUT_NODES_WITHOUT_QUESTION = "cut_nodes_without_question";

  public static String firstLetterCapitalized(final String text) {
    if (text == null || text.length() == 0) {
      return text;
    }
    return text.substring(0, 1).toUpperCase() + text.substring(1, text.length());
  }

  private List<NodeModel> newNodes;

  /**
   * @param modeController
   */
  public MClipboardController() {
    super();
    createActions();
  }

  private String cleanHtml(String in) {
    in = in.replaceFirst("(?i)(?s)<head>.*</head>", "").replaceFirst("(?i)(?s)^.*<html[^>]*>", "<html>")
        .replaceFirst("(?i)(?s)<body [^>]*>", "<body>").replaceAll("(?i)(?s)<script.*?>.*?</script>", "")
        .replaceAll("(?i)(?s)</?tbody.*?>", "").replaceAll("(?i)(?s)<!--.*?-->", "").replaceAll(
            "(?i)(?s)</?o[^>]*>", "");
    if (StringUtils.equals(ResourceController.getResourceController().getProperty(
        "cut_out_pictures_when_pasting_html"), "true")) {
      in = in.replaceAll("(?i)(?s)<img[^>]*>", "");
    }
    in = HtmlUtils.unescapeHTMLUnicodeEntity(in);
    return in;
  }

  /**
   * @param modeController
   */
  private void createActions() {
    final ModeController modeController = Controller.getCurrentModeController();
    modeController.addAction(new CutAction());
    modeController.addAction(new PasteAction());
    modeController.addAction(new SelectedPasteAction());
    modeController.addAction(new CloneAction());
    modeController.addAction(new MoveAction());
  }
 
 

  @Override
    public Transferable copy(IMapSelection selection) {
      final List<NodeModel> collection = selection.getSortedSelection(true);
    final MindMapNodesSelection transferable = copy(collection, false);
    transferable.setNodeObjects(collection);
    return transferable;
    }

  Transferable cut(final List<NodeModel> collection) {
    Controller.getCurrentModeController().getMapController().sortNodesByDepth(collection);
    final MindMapNodesSelection transferable = copy(collection, true);
    for (final NodeModel node : collection) {
      if (node.getParentNode() != null) {
        ((MMapController) Controller.getCurrentModeController().getMapController()).deleteNode(node);
      }
    }
    setClipboardContents(transferable);
    return transferable;
  }

  private IDataFlavorHandler getFlavorHandler(final Transferable t) {
    if (t.isDataFlavorSupported(MindMapNodesSelection.mindMapNodesFlavor)) {
      try {
        final String textFromClipboard = t.getTransferData(MindMapNodesSelection.mindMapNodesFlavor).toString();
        return new MindMapNodesFlavorHandler(textFromClipboard);
      }
      catch (final UnsupportedFlavorException e) {
      }
      catch (final IOException e) {
      }
    }
    if (t.isDataFlavorSupported(MindMapNodesSelection.fileListFlavor)) {
      try {
        final List<File> fileList = castToFileList(t.getTransferData(MindMapNodesSelection.fileListFlavor));
        if (!shouldIgnoreFileListFlavor(fileList))
          return new FileListFlavorHandler(fileList);
      }
      catch (final UnsupportedFlavorException e) {
      }
      catch (final IOException e) {
      }
    }
    final ResourceController resourceController = ResourceController.getResourceController();
    if (t.isDataFlavorSupported(MindMapNodesSelection.htmlFlavor)) {
      try {
        final String textFromClipboard = t.getTransferData(MindMapNodesSelection.htmlFlavor).toString();
        if (textFromClipboard.charAt(0) != 65533) {
          if (t.isDataFlavorSupported(DataFlavor.stringFlavor)) {
            final MTextController textController = (MTextController) TextController
                .getController();
            final boolean richText = textController.useRichTextInEditor(RESOURCES_REMIND_USE_RICH_TEXT_IN_NEW_NODES);
            if (richText) {
              final boolean structuredHtmlImport = resourceController
                  .getBooleanProperty("structured_html_import");
              final IDataFlavorHandler htmlFlavorHandler;
              if (structuredHtmlImport) {
                htmlFlavorHandler = new StructuredHtmlFlavorHandler(textFromClipboard);
              }
              else {
                htmlFlavorHandler = new DirectHtmlFlavorHandler(textFromClipboard);
              }
              return htmlFlavorHandler;
            }
          }
        }
      }
      catch (final UnsupportedFlavorException e) {
      }
      catch (final IOException e) {
      }
    }
    if (t.isDataFlavorSupported(DataFlavor.stringFlavor)) {
      try {
        final String plainTextFromClipboard = t.getTransferData(DataFlavor.stringFlavor).toString();
        return new StringFlavorHandler(plainTextFromClipboard);
      }
      catch (final UnsupportedFlavorException e) {
      }
      catch (final IOException e) {
      }
    }
    if (t.isDataFlavorSupported(DataFlavor.imageFlavor)) {
      try {
        BufferedImage image = (BufferedImage) t.getTransferData(DataFlavor.imageFlavor);
        return new ImageFlavorHandler(image);
      }
      catch (final UnsupportedFlavorException e) {
      }
      catch (final IOException e) {
      }
    }
    return null;
  }

  private boolean shouldIgnoreFileListFlavor(final List<File> fileList) {
    if(fileList.isEmpty())
      return true;
    final File file = fileList.get(0);
    if(file.isDirectory())
      return false;
      final String name = file.getName();
    return name.endsWith(".URL") || name.endsWith(".url");
    }

  @SuppressWarnings("unchecked")
    private List<File> castToFileList(Object transferData) {
      return (List<File>) transferData;
    }

  Collection<IDataFlavorHandler> getFlavorHandlers() {
    final Transferable t = getClipboardContents();   
    final Collection<IDataFlavorHandler> handlerList = new LinkedList<IDataFlavorHandler>();
    if (t == null) {
      return handlerList;
    }
    if (t.isDataFlavorSupported(MindMapNodesSelection.mindMapNodesFlavor)) {
      try {
        final String textFromClipboard = t.getTransferData(MindMapNodesSelection.mindMapNodesFlavor).toString();
        handlerList.add(new MindMapNodesFlavorHandler(textFromClipboard));
      }
      catch (final UnsupportedFlavorException e) {
      }
      catch (final IOException e) {
      }
    }
    if (t.isDataFlavorSupported(MindMapNodesSelection.htmlFlavor)) {
      try {
        final String textFromClipboard = t.getTransferData(MindMapNodesSelection.htmlFlavor).toString();
        if (textFromClipboard.charAt(0) != 65533) {
          if (t.isDataFlavorSupported(DataFlavor.stringFlavor)) {
            handlerList.add(new StructuredHtmlFlavorHandler(textFromClipboard));
            handlerList.add(new DirectHtmlFlavorHandler(textFromClipboard));
          }
        }
      }
      catch (final UnsupportedFlavorException e) {
      }
      catch (final IOException e) {
      }
    }
    if (t.isDataFlavorSupported(DataFlavor.stringFlavor)) {
      try {
        final String plainTextFromClipboard = t.getTransferData(DataFlavor.stringFlavor).toString();
        handlerList.add(new StringFlavorHandler(plainTextFromClipboard));
      }
      catch (final UnsupportedFlavorException e) {
      }
      catch (final IOException e) {
      }
    }
    if (t.isDataFlavorSupported(MindMapNodesSelection.fileListFlavor)) {
      try {
        final List<File> fileList = castToFileList(t.getTransferData(MindMapNodesSelection.fileListFlavor));
        handlerList.add(new FileListFlavorHandler(fileList));
      }
      catch (final UnsupportedFlavorException e) {
      }
      catch (final IOException e) {
      }
    }
    if (t.isDataFlavorSupported(DataFlavor.imageFlavor)) {
      try {
        BufferedImage image = (BufferedImage) t.getTransferData(DataFlavor.imageFlavor);
        handlerList.add(new ImageFlavorHandler(image));
      }
      catch (final UnsupportedFlavorException e) {
      }
      catch (final IOException e) {
      }
    }
    return handlerList;
  }
  public void paste(final Transferable t, final NodeModel target, final boolean asSibling, final boolean isLeft) {
    paste(t, target, asSibling, isLeft, DnDConstants.ACTION_NONE);
  }
 
  public void paste(final Transferable t, final NodeModel target, final boolean asSibling, final boolean isLeft, int dropAction) {
    if (t == null) {
      return;
    }
    /*
     * DataFlavor[] fl = t.getTransferDataFlavors(); for (int i = 0; i <
     * fl.length; i++) { System.out.println(fl[i]); }
     */
    final IDataFlavorHandler handler = getFlavorHandler(t);
    paste(t, handler, target, asSibling, isLeft, dropAction);
  }

  void paste(final Transferable t, final IDataFlavorHandler handler, final NodeModel target, final boolean asSibling, final boolean isLeft) {
    paste(t, handler, target, asSibling, isLeft, DnDConstants.ACTION_NONE);
    }
 
  void paste(final Transferable t, final IDataFlavorHandler handler, final NodeModel target, final boolean asSibling, final boolean isLeft, int dropAction) {
    if (handler == null) {
      return;
    }
    final MMapController mapController = (MMapController) Controller.getCurrentModeController().getMapController();
    if (asSibling && !mapController.isWriteable(target.getParentNode()) || !asSibling
            && !mapController.isWriteable(target)) {
      final String message = TextUtils.getText("node_is_write_protected");
      UITools.errorMessage(message);
      return;
    }
    try {
      Controller.getCurrentController().getViewController().setWaitingCursor(true);
      if (newNodes == null) {
        newNodes = new LinkedList<NodeModel>();
      }
      newNodes.clear();
      handler.paste(t, target, asSibling, isLeft, dropAction);
      final ModeController modeController = Controller.getCurrentModeController();
      if (!asSibling && modeController.getMapController().isFolded(target)
              && ResourceController.getResourceController().getBooleanProperty(RESOURCE_UNFOLD_ON_PASTE)) {
        modeController.getMapController().setFolded(target, false);
      }
      for (final NodeModel child : newNodes) {
        AttributeController.getController().performRegistrySubtreeAttributes(child);
      }
    }
    finally {
      Controller.getCurrentController().getViewController().setWaitingCursor(false);
    }
  }

  private void pasteStringWithoutRedisplay(final TextFragment[] textFragments, NodeModel parent,
                                                final boolean asSibling, final boolean isLeft) {
    final MapModel map = parent.getMap();
    int insertionIndex;
    if (asSibling) {
      NodeModel target = parent;
      parent = parent.getParentNode();
      insertionIndex = parent.getChildPosition(target);
    }
    else{
      insertionIndex = parent.getChildCount();
    }
    final ArrayList<NodeModel> parentNodes = new ArrayList<NodeModel>();
    final ArrayList<Integer> parentNodesDepths = new ArrayList<Integer>();
    parentNodes.add(parent);
    parentNodesDepths.add(new Integer(-1));
    final MMapController mapController = (MMapController) Controller.getCurrentModeController().getMapController();
    for (int i = 0; i < textFragments.length; ++i) {
      final TextFragment textFragment = textFragments[i];
      String text = textFragment.text;
      final String link = textFragment.link;
      URI uri = null;
      if (link != null) {
        try {
          URI linkUri = new URI(link);
          uri = linkUri;
         
          File absoluteFile = UrlManager.getController().getAbsoluteFile(map, uri);
          if(absoluteFile != null) {
          //if ("file".equals(linkUri.getScheme())) {
            final File mapFile = map.getFile();
            uri  = LinkController.toLinkTypeDependantURI(mapFile, absoluteFile);
            if(link.equals(text)){
              text =  uri.toString();
            }
          }
         
        }
        catch (Exception e) {
        }
      }
      final NodeModel node = mapController.newNode(text, map);
      if(uri != null){
        NodeLinks.createLinkExtension(node).setHyperLink(uri);
      }
      for (int j = parentNodes.size() - 1; j >= 0; --j) {
        if (textFragment.depth > ((Integer) parentNodesDepths.get(j)).intValue()) {
          for (int k = j + 1; k < parentNodes.size(); ++k) {
            final NodeModel n = (NodeModel) parentNodes.get(k);
            if (n.getParentNode() == null) {
              mapController.insertNode(n, parent, insertionIndex++);
            }
            parentNodes.remove(k);
            parentNodesDepths.remove(k);
          }
          final NodeModel target = (NodeModel) parentNodes.get(j);
          node.setLeft(isLeft);
          if (target != parent) {
            target.setFolded(true);
            target.insert(node, target.getChildCount());
          }
          parentNodes.add(node);
          parentNodesDepths.add(new Integer(textFragment.depth));
          break;
        }
      }
    }
    {
      for (int k = 0; k < parentNodes.size(); ++k) {
        final NodeModel n = (NodeModel) parentNodes.get(k);
        if (map.getRootNode() != n && n.getParentNode() == null) {
          mapController.insertNode(n, parent, insertionIndex++);
        }
      }
    }
  }
 
  private enum Operation{CLONE, MOVE};
 
  public void addClone(final Transferable transferable, final NodeModel target) {
    processTransferable(transferable, target, Operation.CLONE);
    }

  public void move(final Transferable transferable, final NodeModel target) {
    processTransferable(transferable, target, Operation.MOVE);
    }
 
  private void processTransferable(final Transferable transferable, final NodeModel target, Operation operation) {
      if(!transferable.isDataFlavorSupported(MindMapNodesSelection.mindMapNodeObjectsFlavor))
      return;
    try {
          @SuppressWarnings("unchecked")
          final List<NodeModel> clonedNodes = (List<NodeModel>) transferable.getTransferData(MindMapNodesSelection.mindMapNodeObjectsFlavor);
          for(NodeModel clonedNode:clonedNodes){
            if(clonedNode.getParentNode() == null || ! clonedNode.getMap().equals(target.getMap()))
              return;
            final MMapController mapController = (MMapController) Controller.getCurrentModeController().getMapController();
            if (!clonedNode.isRoot() && ! clonedNode.subtreeContainsCloneOf(target)) {
              switch(operation){
                case CLONE:
                  final NodeModel clone = clonedNode.cloneTree();
                  mapController.addNewNode(clone, target, target.getChildCount(), target.isNewChildLeft());
                  break;
                case MOVE:
                  mapController.moveNodeAsChild(clonedNode, target, target.isNewChildLeft(), target.isNewChildLeft()!=clonedNode.isLeft());
                  break;
              }
            }
          }
        }
        catch (Exception e) {
          LogUtils.severe(e);
        }
    }
}
TOP

Related Classes of org.freeplane.features.clipboard.mindmapmode.MClipboardController$ImageFlavorHandler

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.