// -*- mode:java; encoding:utf-8 -*-
// vim:set fileencoding=utf-8:
// @homepage@

package example;

import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.Objects;
import javax.swing.*;

public final class MainPanel extends JPanel {
  private final JLabel label = new JLabel();
  private final ImageIcon i1 = new ImageIcon(Objects.requireNonNull(getClass().getResource("i03-04.gif")));
  private final ImageIcon i2 = new ImageIcon(Objects.requireNonNull(getClass().getResource("i03-10.gif")));
  private File file;

  private MainPanel() {
    super(new BorderLayout());
    label.setVerticalTextPosition(SwingConstants.BOTTOM);
    label.setVerticalAlignment(SwingConstants.CENTER);
    label.setHorizontalTextPosition(SwingConstants.CENTER);
    label.setHorizontalAlignment(SwingConstants.CENTER);
    label.setBorder(BorderFactory.createTitledBorder("Drag Source JLabel"));
    clearFile();

    // // JDK 1.5.0
    // DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(
    //       label, DnDConstants.ACTION_MOVE, new DragGestureListener() {
    //   @Override public void dragGestureRecognized(DragGestureEvent e) {
    //     File tmpFile = getFile();
    //     if (Objects.isNull(tmpFile)) {
    //       return;
    //     }
    //     DragSourceAdapter dsa = new DragSourceAdapter() {
    //       @Override public void dragDropEnd(DragSourceDropEvent ev) {
    //         if (ev.getDropSuccess()) {
    //           clearFile();
    //         }
    //       }
    //     };
    //     e.startDrag(DragSource.DefaultMoveDrop, new TempFileTransferable(tmpFile), dsa);
    //   }
    // });

    label.setTransferHandler(new TransferHandler() {
      @Override public int getSourceActions(JComponent c) {
        return TransferHandler.COPY_OR_MOVE;
      }

      @Override protected Transferable createTransferable(JComponent c) {
        File tmpFile = getFile();
        if (Objects.nonNull(tmpFile)) {
          return new TempFileTransferable(tmpFile);
        } else {
          return null;
        }
      }

      @Override protected void exportDone(JComponent c, Transferable data, int action) {
        cleanup(c, action == TransferHandler.MOVE);
      }

      private void cleanup(JComponent c, boolean isMoved) {
        if (isMoved) {
          clearFile();
          c.repaint();
        }
      }
    });
    label.addMouseListener(new MouseAdapter() {
      @Override public void mousePressed(MouseEvent e) {
        System.out.println(e);
        JComponent c = (JComponent) e.getComponent();
        c.getTransferHandler().exportAsDrag(c, e, TransferHandler.COPY);
      }
    });

    JButton button = new JButton("Create Temp File");
    button.addActionListener(e -> {
      File outfile;
      try {
        outfile = File.createTempFile("test", ".tmp");
        outfile.deleteOnExit();
      } catch (IOException ex) {
        JComponent c = (JComponent) e.getSource();
        UIManager.getLookAndFeel().provideErrorFeedback(c);
        String msg = "Could not create file.";
        JOptionPane.showMessageDialog(c.getRootPane(), msg, "Error", JOptionPane.ERROR_MESSAGE);
        return;
      }
      setFile(outfile);
    });

    JButton clearButton = new JButton("Clear");
    clearButton.addActionListener(e -> {
      clearFile();
      label.repaint();
    });

    Box box = Box.createHorizontalBox();
    box.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
    box.add(Box.createHorizontalGlue());
    box.add(button);
    box.add(Box.createHorizontalStrut(2));
    box.add(clearButton);
    add(label);
    add(box, BorderLayout.SOUTH);
    setPreferredSize(new Dimension(320, 240));
  }

  public File getFile() {
    return file;
  }

  public void setFile(File file) {
    this.file = file;
    label.setIcon(i2);
    label.setText("tmpFile#exists(): true(draggable)");
  }

  public void clearFile() {
    file = null;
    label.setIcon(i1);
    label.setText("tmpFile#exists(): false");
  }

  public static void main(String[] args) {
    EventQueue.invokeLater(MainPanel::createAndShowGui);
  }

  private static void createAndShowGui() {
    try {
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
      ex.printStackTrace();
      Toolkit.getDefaultToolkit().beep();
    }
    JFrame frame = new JFrame("@title@");
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    frame.getContentPane().add(new MainPanel());
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}

class TempFileTransferable implements Transferable {
  private final File file;

  protected TempFileTransferable(File file) {
    this.file = file;
  }

  @Override public Object getTransferData(DataFlavor flavor) {
    return Collections.singletonList(file);
  }

  @Override public DataFlavor[] getTransferDataFlavors() {
    return new DataFlavor[] {DataFlavor.javaFileListFlavor};
  }

  @Override public boolean isDataFlavorSupported(DataFlavor flavor) {
    return flavor.equals(DataFlavor.javaFileListFlavor);
  }
}

@@ -316,16 +316,44 @@
 eption;%0A
+import java.io.InputStream;%0A
 import j
@@ -400,16 +400,73 @@
 bjects;%0A
+import java.util.Optional;%0Aimport javax.imageio.ImageIO;%0A
 import j
@@ -583,29 +583,34 @@
 ivate final 
-Image
+transient 
 Icon i1 = ne
@@ -611,69 +611,26 @@
 1 = 
-new I
 ma
-g
+k
 eIcon(
-Objects.requireNonNull(getClass().getResource(%22
+%22example/
 i03-
@@ -633,26 +633,24 @@
 i03-04.gif%22)
-))
 ;%0A  private 
@@ -655,21 +655,26 @@
 e final 
-Image
+transient 
 Icon i2 
@@ -679,69 +679,26 @@
 2 = 
-new I
 ma
-g
+k
 eIcon(
-Objects.requireNonNull(getClass().getResource(%22
+%22example/
 i03-
@@ -705,18 +705,16 @@
 10.gif%22)
-))
 ;%0A  priv
@@ -4178,32 +4178,534 @@
 : false%22);%0A  %7D%0A%0A
+  private static Icon makeIcon(String path) %7B%0A    ClassLoader cl = Thread.currentThread().getContextClassLoader();%0A    return Optional.ofNullable(cl.getResource(path)).map(url -%3E %7B%0A      try (InputStream s = url.openStream()) %7B%0A        return new ImageIcon(ImageIO.read(s));%0A      %7D catch (IOException ex) %7B%0A        return makeMissingIcon();%0A      %7D%0A    %7D).orElseGet(MainPanel::makeMissingIcon);%0A  %7D%0A%0A  private static Icon makeMissingIcon() %7B%0A    return UIManager.getIcon(%22OptionPane.errorIcon%22);%0A  %7D%0A%0A
   public static 

argument 'javaClass#getResource(...)' might be null