package de.duehl.swing.ui.dragndrop;

/*
 * Copyright 2021 Christian Dühl. All rights reserved.
 *
 * This program is free software. You can redistribute it and/or
 * modify it under the same terms as perl:
 *
 * general:  http://dev.perl.org/licenses/
 * GPL:      http://dev.perl.org/licenses/gpl1.html
 * artistic: http://dev.perl.org/licenses/artistic.html
 */

import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.io.IOException;

import javax.swing.text.JTextComponent;

/**
 * Dieses Klasse stellt eine Basis für einen DropTargetListener für normale JTextFields dar, bei
 * dem der eingefügte Text vor dem Einfügen behandelt wird.
 *
 * @version 1.01     2021-07-27
 * @author Christian Dühl
 */

public abstract class TextEditingDropTargetListener implements DropTargetListener {

    /** Das JTextField, auf dem der Listener installiert wird. */
    protected final JTextComponent textComponent;

    /** Der vom Benutzer gezogene Text. */
    private String draggedText;

    /**
     * Konstruktor.
     *
     * @param listeningTextComponent
     *            Das JTextField oder die JTextArea, auf dem der Listener installiert wird.
     */
    public TextEditingDropTargetListener(JTextComponent listeningTextComponent) {
        this.textComponent = listeningTextComponent;
    }

    /**
     * Called while a drag operation is ongoing, when the mouse pointer enters the operable part of
     * the drop site for the <code>DropTarget</code> registered with this listener.
     *
     * @param dtde
     *            the <code>DropTargetDragEvent</code>
     */
    @Override
    public void dragEnter(DropTargetDragEvent dtde) {
        try {
            DataFlavor flavor = DataFlavor.stringFlavor;
            draggedText = dtde.getTransferable().getTransferData(flavor).toString();
        }
        catch (UnsupportedFlavorException e) {
            e.printStackTrace();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Called when a drag operation is ongoing, while the mouse pointer is still over the operable
     * part of the drop site for the <code>DropTarget</code> registered with this listener.
     *
     * @param dtde
     *            the <code>DropTargetDragEvent</code>
     */
    @Override
    public void dragOver(DropTargetDragEvent dtde) {
    }

    /**
     * Called if the user has modified the current drop gesture.
     * <P>
     *
     * @param dtde
     *            the <code>DropTargetDragEvent</code>
     */
    @Override
    public void dropActionChanged(DropTargetDragEvent dtde) {
    }

    /**
     * Called while a drag operation is ongoing, when the mouse pointer has exited the operable
     * part of the drop site for the <code>DropTarget</code> registered with this listener.
     *
     * @param dte
     *            the <code>DropTargetEvent</code>
     */
    @Override
    public void dragExit(DropTargetEvent dte) {
    }

    /**
     * Called when the drag operation has terminated with a drop on the operable part of the drop
     * site for the <code>DropTarget</code> registered with this listener. <p>
     *
     * This method is responsible for undertaking the transfer of the data associated with the
     * gesture. The <code>DropTargetDropEvent</code> provides a means to obtain a
     * <code>Transferable</code> object that represents the data object(s) to be transfered. <P>
     *
     * From this method, the <code>DropTargetListener</code> shall accept or reject the drop via
     * the acceptDrop(int dropAction) or rejectDrop() methods of the
     * <code>DropTargetDropEvent</code> parameter. <P>
     *
     * Subsequent to acceptDrop(), but not before, <code>DropTargetDropEvent</code>'s
     * getTransferable() method may be invoked, and data transfer may be performed via the returned
     * <code>Transferable</code>'s getTransferData() method. <P>
     *
     * At the completion of a drop, an implementation of this method is required to signal the
     * success/failure of the drop by passing an appropriate <code>boolean</code> to the
     * <code>DropTargetDropEvent</code>'s dropComplete(boolean success) method. <P>
     *
     * Note: The data transfer should be completed before the call to the
     * <code>DropTargetDropEvent</code>'s dropComplete(boolean success) method. After that, a call
     * to the getTransferData() method of the <code>Transferable</code> returned by
     * <code>DropTargetDropEvent.getTransferable()</code> is guaranteed to succeed only if the data
     * transfer is local; that is, only if <code>DropTargetDropEvent.isLocalTransfer()</code>
     * returns <code>true</code>. Otherwise, the behavior of the call is implementation-dependent.
     *
     * @param dtde
     *            the <code>DropTargetDropEvent</code>
     */
    @Override
    public void drop(DropTargetDropEvent dtde) {
        int dropAction = dtde.getDropAction();
        dtde.acceptDrop(dropAction);
        editContent(draggedText);
        dtde.dropComplete(true);
    }

    /**
     * In dieser Methode wird der eingefügte Text bearbeitet.
     *
     * @param draggedText
     *            Der gezogene Text.
     */
    abstract protected void editContent(String draggedText);

}
