package org.docear.plugin.pdfutilities.listener;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DropTargetDropEvent;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.swing.SwingUtilities;
import org.docear.plugin.core.DocearController;
import org.docear.plugin.core.event.DocearEvent;
import org.docear.plugin.core.event.DocearEventType;
import org.docear.plugin.core.features.DocearMapModelExtension;
import org.docear.plugin.core.features.MapModificationSession;
import org.docear.plugin.core.ui.SwingWorkerDialog;
import org.docear.plugin.core.util.Tools;
import org.docear.plugin.pdfutilities.PdfUtilitiesController;
import org.docear.plugin.pdfutilities.features.AnnotationModel;
import org.docear.plugin.pdfutilities.pdf.PdfAnnotationImporter;
import org.docear.plugin.pdfutilities.pdf.PdfFileFilter;
import org.docear.plugin.pdfutilities.util.MonitoringUtils;
import org.freeplane.core.resources.ResourceController;
import org.freeplane.core.util.LogUtils;
import org.freeplane.core.util.TextUtils;
import org.freeplane.features.clipboard.MindMapNodesSelection;
import org.freeplane.features.map.NodeModel;
import org.freeplane.features.mode.Controller;
import org.freeplane.features.mode.ModeController;
import org.freeplane.view.swing.features.filepreview.ViewerController;
import org.freeplane.view.swing.map.MainView;
import org.freeplane.view.swing.map.NodeView;
import org.freeplane.view.swing.ui.mindmapmode.MNodeDropListener;
import org.jdesktop.swingworker.SwingWorker;
import de.intarsys.pdf.cos.COSRuntimeException;
import de.intarsys.pdf.parser.COSLoadException;
public class DocearNodeDropListener extends MNodeDropListener {
public DocearNodeDropListener(){
super();
}
@SuppressWarnings("unchecked")
public void drop(final DropTargetDropEvent dtde) {
LogUtils.info("DocearNodedroplistener Drop activated...."); //$NON-NLS-1$
final MainView mainView = (MainView) dtde.getDropTargetContext().getComponent();
final NodeView targetNodeView = mainView.getNodeView();
Set<NodeModel> nodes = new HashSet<NodeModel>();
for (NodeModel node : Controller.getCurrentModeController().getMapController().getSelectedNodes()) {
nodes.add(node);
}
NodeModel node = targetNodeView.getModel();
if (!nodes.contains(node)) {
nodes.clear();
nodes.add(node);
}
DocearMapModelExtension modelExtension = node.getMap().getExtension(DocearMapModelExtension.class);
try{
MapModificationSession session = new MapModificationSession();
modelExtension.setMapModificationSession(session);
final DataFlavor fileListFlavor = new DataFlavor("application/x-java-file-list; class=java.util.List"); //$NON-NLS-1$
final DataFlavor uriListFlavor = new DataFlavor("text/uri-list; class=java.lang.String"); //$NON-NLS-1$
//TODO: DOCEAR - why restrict to !dtde.isLocalTransfer only?
if(dtde.isDataFlavorSupported(MindMapNodesSelection.mindMapNodesFlavor) ) {
super.drop(dtde);
return;
}
// do not combine with the previous condition unless you know what you are doing!
if (dtde.isDataFlavorSupported(fileListFlavor) || (dtde.isDataFlavorSupported(uriListFlavor))) {
final Transferable transferable = dtde.getTransferable();
final boolean isLeft = mainView.dropLeft(dtde.getLocation().getX());
mainView.setDraggedOver(NodeView.DRAGGED_OVER_NO);
mainView.repaint();
List<File> fileList = new ArrayList<File>();
if(transferable.isDataFlavorSupported(fileListFlavor)){
dtde.acceptDrop(dtde.getDropAction());
fileList = (List<File>) (transferable.getTransferData(fileListFlavor));
}
else if(transferable.isDataFlavorSupported(uriListFlavor)){
dtde.acceptDrop(dtde.getDropAction());
fileList = Tools.textURIListToFileList((String) transferable.getTransferData(uriListFlavor));
}
Iterator<NodeModel> iter = nodes.iterator();
while (iter.hasNext()) {
pasteFileList(fileList, iter.next(), isLeft);
}
dtde.dropComplete(true);
return;
}
} catch (final Exception e) {
LogUtils.severe("DocearNodeDropListener Drop exception:", e); //$NON-NLS-1$
dtde.dropComplete(false);
return;
}
finally {
modelExtension.resetModificationSession();
}
super.drop(dtde);
}
public static void pasteFileList(final List<File> fileList, final NodeModel targetNode, final boolean isLeft)
throws UnsupportedFlavorException, IOException, ClassNotFoundException, Exception {
SwingWorker<Void, Void> thread = new SwingWorker<Void, Void>(){
@Override
protected Void doInBackground() throws Exception {
int count = 0;
firePropertyChange(SwingWorkerDialog.SET_PROGRESS_BAR_DETERMINATE, null, null);
MapModificationSession session = targetNode.getMap().getExtension(DocearMapModelExtension.class).getMapModificationSession();
if (session == null) {
session = new MapModificationSession();
targetNode.getMap().getExtension(DocearMapModelExtension.class).setMapModificationSession(session);
}
session.putSessionObject(MapModificationSession.FILE_IGNORE_LIST , new HashSet<String>());
for(final File file : fileList){
if(Thread.currentThread().isInterrupted()) return null;
firePropertyChange(SwingWorkerDialog.NEW_FILE, null, file.getName());
boolean importAnnotations = ResourceController.getResourceController().getBooleanProperty(PdfUtilitiesController.AUTO_IMPORT_ANNOTATIONS_KEY);
if(new PdfFileFilter().accept(file) && importAnnotations){
List<AnnotationModel> annotations = new ArrayList<AnnotationModel>();
try{
PdfAnnotationImporter importer = new PdfAnnotationImporter();
annotations = importer.importAnnotations(file.toURI());
//System.gc();
} catch(COSRuntimeException e) {
LogUtils.warn("Exception during import on file: " + file.getName(), e); //$NON-NLS-1$
} catch(IOException e) {
LogUtils.warn("Exception during import on file: " + file.getName(), e); //$NON-NLS-1$
} catch(COSLoadException e) {
LogUtils.warn("Exception during import on file: " + file.getName(), e); //$NON-NLS-1$
}
final List<AnnotationModel> finalAnnotations;
if(annotations != null){
finalAnnotations = annotations;
}
else{
finalAnnotations = new ArrayList<AnnotationModel>();
}
SwingUtilities.invokeAndWait(
new Runnable() {
public void run(){
try {
URI uri = file.toURI();
NodeModel newNode = MonitoringUtils.insertChildNodesFromPdf(uri, finalAnnotations, isLeft, targetNode);
for(AnnotationModel annotation : getInsertedNodes(finalAnnotations)){
firePropertyChange(SwingWorkerDialog.DETAILS_LOG_TEXT, null, TextUtils.getText("DocearNodeDropListener.4") + annotation.getTitle() +TextUtils.getText("DocearNodeDropListener.5")); //$NON-NLS-1$ //$NON-NLS-2$
}
DocearEvent event = new DocearEvent(newNode, DocearEventType.MINDMAP_ADD_PDF_TO_NODE, true);
DocearController.getController().dispatchDocearEvent(event);
}
catch (Exception e) {
LogUtils.severe(e);
}
}
}
);
}
else {
ModeController modeController = Controller.getCurrentController().getModeController();
final ViewerController viewerController = ((ViewerController)modeController.getExtension(ViewerController.class));
SwingUtilities.invokeAndWait(
new Runnable() {
public void run(){
if(!viewerController.paste(file, targetNode, isLeft)){
MonitoringUtils.insertChildNodeFrom(file.toURI(), isLeft, targetNode, null);
}
}
}
);
}
count++;
setProgress(100 * count / fileList.size());
Thread.sleep(1L);
}
return null;
}
@Override
protected void done() {
firePropertyChange(SwingWorkerDialog.IS_DONE, null, null);
}
private Collection<AnnotationModel> getInsertedNodes(Collection<AnnotationModel> annotations){
Collection<AnnotationModel> result = new ArrayList<AnnotationModel>();
for(AnnotationModel annotation : annotations){
result.add(annotation);
result.addAll(this.getInsertedNodes(annotation.getChildren()));
}
return result;
}
};
/*if(fileList.size() > 10){
SwingWorkerDialog monitoringDialog = new SwingWorkerDialog(Controller.getCurrentController().getViewController().getJFrame());
monitoringDialog.showDialog(thread);
}
else{*/
thread.execute();
//}
}
/*public boolean isDragAcceptable(final DropTargetDragEvent ev) {
if(ev.isDataFlavorSupported(TransferableEntrySelection.flavorInternal)){
return true;
}
return super.isDragAcceptable(ev);
}*/
}