001package jmri.jmrit.display.palette;
002
003import java.awt.Color;
004import java.awt.Dimension;
005import java.awt.datatransfer.DataFlavor;
006import java.awt.datatransfer.Transferable;
007import java.awt.dnd.DnDConstants;
008import java.awt.dnd.DragGestureEvent;
009import java.awt.dnd.DragGestureListener;
010import java.awt.dnd.DragSource;
011import java.awt.dnd.DragSourceDragEvent;
012import java.awt.dnd.DragSourceDropEvent;
013import java.awt.dnd.DragSourceEvent;
014import java.awt.dnd.DragSourceListener;
015
016import javax.swing.BorderFactory;
017import javax.swing.JComponent;
018import javax.swing.JPanel;
019
020import jmri.util.ThreadingUtil;
021
022/**
023 * Gives a JComponent the capability to Drag and Drop
024 * <hr>
025 * This file is part of JMRI.
026 * <p>
027 * JMRI is free software; you can redistribute it and/or modify it under the
028 * terms of version 2 of the GNU General Public License as published by the Free
029 * Software Foundation. See the "COPYING" file for a copy of this license.
030 * <p>
031 * JMRI is distributed in the hope that it will be useful, but WITHOUT ANY
032 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
033 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
034 *
035 * @author Pete Cressman Copyright 2011
036 *
037 */
038public abstract class DragJComponent extends JPanel implements DragGestureListener, DragSourceListener, Transferable {
039
040    DataFlavor _dataFlavor;
041    JComponent _component;
042
043    protected DragJComponent(DataFlavor flavor,  JComponent comp) {
044        super();
045        _component = comp;
046        _dataFlavor = flavor;
047        ThreadingUtil.runOnGUI( () -> init(comp));
048    }
049
050    private void init( JComponent comp) {
051        setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.black),
052                Bundle.getMessage("dragToPanel")));
053        // guestimate border is about 5 pixels thick. plus some margin
054        add(comp);
055        setPreferredSize();
056        setToolTipText(Bundle.getMessage("ToolTipDragIcon"));
057        DragSource dragSource = DragSource.getDefaultDragSource();
058        dragSource.createDefaultDragGestureRecognizer(this,
059                DnDConstants.ACTION_COPY, this);
060    }
061
062    @Override
063    public void invalidate() {
064        setPreferredSize();
065        super.invalidate();
066    }
067
068    protected void setPreferredSize() {
069        Dimension dim = _component.getSize();
070        int width = Math.max(100, dim.width + 30);
071        int height = Math.max(65, dim.height + 35);
072        setPreferredSize(new java.awt.Dimension(width, height));
073    }
074
075    protected JComponent getThing() {
076        return _component;
077    }
078        
079    protected boolean okToDrag() {
080        return true;
081    }
082    
083    /**
084     * ************** DragGestureListener **************
085     * {@inheritDoc }
086     */
087    @Override
088    public void dragGestureRecognized(DragGestureEvent e) {
089        log.debug("DragJLabel.dragGestureRecognized ");
090        if (okToDrag()) {
091            e.startDrag(DragSource.DefaultCopyDrop, this, this);            
092        }
093    }
094
095    /**
096     * ************** DragSourceListener ***********
097     * {@inheritDoc }
098     */
099    @Override
100    public void dragDropEnd(DragSourceDropEvent e) {
101        log.debug("DragJLabel.dragDropEnd ");
102    }
103
104    @Override
105    public void dragEnter(DragSourceDragEvent e) {
106    }
107
108    @Override
109    public void dragExit(DragSourceEvent e) {
110    }
111
112    @Override
113    public void dragOver(DragSourceDragEvent e) {
114    }
115
116    @Override
117    public void dropActionChanged(DragSourceDragEvent e) {
118    }
119
120    /**
121     * ************* Transferable ********************
122     */
123    @Override
124    public DataFlavor[] getTransferDataFlavors() {
125        return new DataFlavor[]{_dataFlavor, DataFlavor.stringFlavor};
126    }
127
128    @Override
129    public boolean isDataFlavorSupported(DataFlavor flavor) {
130        return _dataFlavor.equals(flavor);
131    }
132
133    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(DragJComponent.class);
134}