Drag and drop for non-String objects

H

Hendrik Maryns

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi all,

I’d like to revive a thread I started a while ago but which got no
satisfying answers.

I want to implement drag and drop for non-String objects.

Setting: a JList with a DefaultListModel. It contains Formula’s (a
class of my own making, with a whole hierarchy underneath it:
Conjunction, Negation etc.). I then do

result.setDragEnabled(true);
result.setTransferHandler(new FormulaTransferHandler());
result.setDropMode(DropMode.INSERT);

on the JList. Here follows an almost minimal SSCCE, note that it needs
Java 6:

import java.io.Serializable;

/**
~ * A class for specifying a formula in monadic second order logic.
~ */
public class Formula implements Serializable {
}

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class UIBuilder {
~ public UIBuilder() {
~ super();
~ this.frame = new JFrame();
~ this.frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
~ this.queryField = this.createQueryField();
~ this.initMenu();
~ }
~ private final JFrame frame;
~ final private JList queryField;
~ /**
~ * Initialize the edit area. Make a JList, enable dragging with a custom
~ * TransferHandler class
~ *
~ * @return The list which contains the formulas being edited.
~ */
~ private JList createQueryField() {
~ final JList result = new JList(new DefaultListModel());
~ result.setDragEnabled(true);
~ result.setTransferHandler(new FormulaTransferHandler());
~ result.setDropMode(DropMode.INSERT);
~ this.frame.getContentPane().add(result, BorderLayout.CENTER);
~ return result;
~ }
~ private void initMenu() {
~ final JMenuBar mb = new JMenuBar();
~ this.frame.setJMenuBar(mb);
~ final JMenu atomicMenu = new JMenu("Formula");
~ mb.add(atomicMenu);
~ final JMenuItem addItem = new JMenuItem("Add");
~ atomicMenu.add(addItem);
~ addItem.addActionListener(new ActionListener() {
~ public void actionPerformed(final ActionEvent evt) {
~ ((DefaultListModel) UIBuilder.this.queryField.getModel()).add(0,
~ new Formula());
~ }
~ });
~ }
~ public static void main(final String[] args) {
~ SwingUtilities.invokeLater(new Runnable() {
~ public void run() {
~ final UIBuilder MonaSearch = new UIBuilder();
~ MonaSearch.frame.setSize(400, 400);
~ MonaSearch.frame.setVisible(true);
~ }
~ });
~ }
}

import java.awt.datatransfer.*;
import java.io.IOException;

import javax.activation.ActivationDataFlavor;
import javax.activation.DataHandler;
import javax.swing.*;

/**
~ * A transfer handler for formulas. Based on Sun’s Swing DnD tutorial.
~ */
public class FormulaTransferHandler extends TransferHandler {

~ /**
~ * Initialize the formula transfer handler. Sets the supported
flavors. For
~ * now these are:
~ * <ul>
~ * <li>new ActivationDataFlavor(Formula.class,
~ * DataFlavor.javaJVMLocalObjectMimeType, "Arrays of formulas");</li>
~ * </ul>
~ */
~ public FormulaTransferHandler() {
~ this.localFormulaFlavor = new ActivationDataFlavor(Formula.class,
~ DataFlavor.javaJVMLocalObjectMimeType, "Arrays of formulas");
~ }

~ /**
~ * The data flavor for formulas local to the JVM.
~ */
~ private final DataFlavor localFormulaFlavor;

~ /**
~ * The formulas being transfered.
~ */
~ private Object[] transferedFormulas = null;

~ @Override
~ protected Transferable createTransferable(final JComponent c) {
~ final JList formulaList = (JList) c;
~ this.transferedFormulas = formulaList.getSelectedValues();
~ return new DataHandler(this.transferedFormulas, this.localFormulaFlavor
~ .getMimeType());
~ // TODO: add support via serialization?
~ }

~ @Override
~ public boolean canImport(final TransferHandler.TransferSupport info) {
~ // only support drop, I don’t see a use for paste here
~ if (!info.isDrop()) {
~ return false;
~ }
~ if (!info.isDataFlavorSupported(this.localFormulaFlavor)) {
~ // TODO: allow serialization?
~ return false;
~ }
~ return true;
~ }

~ @Override
~ public int getSourceActions(final JComponent c) {
~ return TransferHandler.COPY_OR_MOVE;
~ }

~ @Override
~ public boolean importData(final TransferHandler.TransferSupport info) {
~ if (this.canImport(info)) {
~ try {
~ final Formula[] formulas = (Formula[]) info.getTransferable()
~ .getTransferData(this.localFormulaFlavor);
~ int index = ((JList.DropLocation)
info.getDropLocation()).getIndex();
~ // put at the beginning if invalid drop
~ if (index == -1) {
~ index = 0;
~ }
~ final DefaultListModel listModel = (DefaultListModel) ((JList) info
~ .getComponent()).getModel();
~ for (final Formula element : formulas) {
~ listModel.add(index++, element);
~ }
~ return true;
~ } catch (final UnsupportedFlavorException ufe) {
~ ufe.printStackTrace();
~ } catch (final IOException ioe) {
~ ioe.printStackTrace();
~ }
~ }
~ return false;
~ }

~ @Override
~ protected void exportDone(final JComponent c, final Transferable data,
~ final int action) {
~ if (action == TransferHandler.MOVE && this.transferedFormulas !=
null) {
~ final JList list = (JList) c;
~ final int[] indices = list.getSelectedIndices();
~ final DefaultListModel model = (DefaultListModel) list.getModel();
~ for (int i = 0; i < indices.length - 1; i++) {
~ model.remove(indices);
~ }
~ }
~ }
}

If you add some formulas with the menu and try to drag one somewhere, it
shows the ‘forbidden’ sign all the time. It seems the canImport method
returns false at all times, but I do not understand why.

H.
- --
Hendrik Maryns
http://tcl.sfs.uni-tuebingen.de/~hendrik/
==================
http://aouw.org
Ask smart questions, get good answers:
http://www.catb.org/~esr/faqs/smart-questions.html

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.9 (GNU/Linux)
Comment: Using GnuPG with SUSE - http://enigmail.mozdev.org

iEYEARECAAYFAkiEdEgACgkQBGFP0CTku6MwsQCg1MJuQA/Ecyj4YjSAI3rLOueS
gakAoJtt2laq0lWRLHR3ErP47/S6UwHn
=EkgU
-----END PGP SIGNATURE-----
 
N

Nigel Wade

Hendrik said:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi all,

I’d like to revive a thread I started a while ago but which got no
satisfying answers.

I want to implement drag and drop for non-String objects.

Setting: a JList with a DefaultListModel. It contains Formula’s (a
class of my own making, with a whole hierarchy underneath it:
Conjunction, Negation etc.). I then do

result.setDragEnabled(true);
result.setTransferHandler(new FormulaTransferHandler());
result.setDropMode(DropMode.INSERT);

on the JList. Here follows an almost minimal SSCCE, note that it needs
Java 6:

Here you specify that the DataFlavor which drop will accept is of class
Formula...

~ this.localFormulaFlavor = new ActivationDataFlavor(Formula.class,
~ DataFlavor.javaJVMLocalObjectMimeType, "Arrays of formulas");
~ }
~ /**
~ * The data flavor for formulas local to the JVM.
~ */
~ private final DataFlavor localFormulaFlavor;

~ /**
~ * The formulas being transfered.
~ */
~ private Object[] transferedFormulas = null;

~ @Override
~ protected Transferable createTransferable(final JComponent c) {
~ final JList formulaList = (JList) c;
~ this.transferedFormulas = formulaList.getSelectedValues();
~ return new DataHandler(this.transferedFormulas, this.localFormulaFlavor
~ .getMimeType());
~ // TODO: add support via serialization?
~ }

...but what you actually transfer is an Object[]
 
H

Hendrik Maryns

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Nigel Wade schreef:
| Hendrik Maryns wrote:
|
|> -----BEGIN PGP SIGNED MESSAGE-----
|> Hash: SHA1
|>
|> Hi all,
|>
|> I’d like to revive a thread I started a while ago but which got no
|> satisfying answers.
|>
|> I want to implement drag and drop for non-String objects.
|>
|> Setting: a JList with a DefaultListModel. It contains Formula’s (a
|> class of my own making, with a whole hierarchy underneath it:
|> Conjunction, Negation etc.). I then do
|>
|> result.setDragEnabled(true);
|> result.setTransferHandler(new FormulaTransferHandler());
|> result.setDropMode(DropMode.INSERT);
|>
|> on the JList. Here follows an almost minimal SSCCE, note that it needs
|> Java 6:
|>
|
| Here you specify that the DataFlavor which drop will accept is of class
| Formula...
|
|
|> ~ this.localFormulaFlavor = new ActivationDataFlavor(Formula.class,
|> ~ DataFlavor.javaJVMLocalObjectMimeType, "Arrays of formulas");
|> ~ }
|
|> ~ /**
|> ~ * The data flavor for formulas local to the JVM.
|> ~ */
|> ~ private final DataFlavor localFormulaFlavor;
|>
|> ~ /**
|> ~ * The formulas being transfered.
|> ~ */
|> ~ private Object[] transferedFormulas = null;
|>
|> ~ @Override
|> ~ protected Transferable createTransferable(final JComponent c) {
|> ~ final JList formulaList = (JList) c;
|> ~ this.transferedFormulas = formulaList.getSelectedValues();
|> ~ return new DataHandler(this.transferedFormulas,
this.localFormulaFlavor
|> ~ .getMimeType());
|> ~ // TODO: add support via serialization?
|> ~ }
|
| ..but what you actually transfer is an Object[]

I see. What solution would you suggest: convert the Object[] to
Formula[] and update above also, or simply use Object as the local
flavor above and let the JList find out? I guess there is no need for
Formula indeed, since I do not invoke any methods on it, so I could as
well use Object[].

I wonder whether some day the Swing classes will start using generics as
well. It would make things much easier.

Thanks, H.
- --
Hendrik Maryns
http://tcl.sfs.uni-tuebingen.de/~hendrik/
==================
http://aouw.org
Ask smart questions, get good answers:
http://www.catb.org/~esr/faqs/smart-questions.html
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.9 (GNU/Linux)
Comment: Using GnuPG with SUSE - http://enigmail.mozdev.org

iEYEARECAAYFAkiEnosACgkQBGFP0CTku6PzwACbBB7CVsQTcYqdEsE0I1uVt3a4
bXUAoJOqz17RFCgl7tDDBUjRkkDUklpu
=4d4M
-----END PGP SIGNATURE-----
 
H

Hendrik Maryns

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hendrik Maryns schreef:
| Nigel Wade schreef:
| | Hendrik Maryns wrote:
| |
| |> -----BEGIN PGP SIGNED MESSAGE-----
| |> Hash: SHA1
| |>
| |> Hi all,
| |>
| |> I’d like to revive a thread I started a while ago but which got no
| |> satisfying answers.
| |>
| |> I want to implement drag and drop for non-String objects.
| |>
| |> Setting: a JList with a DefaultListModel. It contains Formula’s (a
| |> class of my own making, with a whole hierarchy underneath it:
| |> Conjunction, Negation etc.). I then do
| |>
| |> result.setDragEnabled(true);
| |> result.setTransferHandler(new FormulaTransferHandler());
| |> result.setDropMode(DropMode.INSERT);
| |>
| |> on the JList. Here follows an almost minimal SSCCE, note that it needs
| |> Java 6:
| |>
| |
| | Here you specify that the DataFlavor which drop will accept is of class
| | Formula...
| |
| |
| |> ~ this.localFormulaFlavor = new ActivationDataFlavor(Formula.class,
| |> ~ DataFlavor.javaJVMLocalObjectMimeType, "Arrays of formulas");
| |> ~ }
| |
| |> ~ /**
| |> ~ * The data flavor for formulas local to the JVM.
| |> ~ */
| |> ~ private final DataFlavor localFormulaFlavor;
| |>
| |> ~ /**
| |> ~ * The formulas being transfered.
| |> ~ */
| |> ~ private Object[] transferedFormulas = null;
| |>
| |> ~ @Override
| |> ~ protected Transferable createTransferable(final JComponent c) {
| |> ~ final JList formulaList = (JList) c;
| |> ~ this.transferedFormulas = formulaList.getSelectedValues();
| |> ~ return new DataHandler(this.transferedFormulas,
| this.localFormulaFlavor
| |> ~ .getMimeType());
| |> ~ // TODO: add support via serialization?
| |> ~ }
| |
| | ..but what you actually transfer is an Object[]
|
| I see. What solution would you suggest: convert the Object[] to
| Formula[] and update above also, or simply use Object as the local
| flavor above and let the JList find out? I guess there is no need for
| Formula indeed, since I do not invoke any methods on it, so I could as
| well use Object[].

Ok, the latter option now makes the drop being accepted, but nothing
changes, i.e.: everything in the list remains at its place.

The only change with the above is:

~ public FormulaTransferHandler() {
~ this.localFormulaFlavor = new ActivationDataFlavor(Object[].class,
~ DataFlavor.javaJVMLocalObjectMimeType, "Arrays of objects");
~ }

Also, I note that this should actually belong on c.l.j.gui, so f-up to
there.

Thanks already, though!
H.
- --
Hendrik Maryns
http://tcl.sfs.uni-tuebingen.de/~hendrik/
==================
http://aouw.org
Ask smart questions, get good answers:
http://www.catb.org/~esr/faqs/smart-questions.html
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.9 (GNU/Linux)
Comment: Using GnuPG with SUSE - http://enigmail.mozdev.org

iEYEARECAAYFAkiErq8ACgkQBGFP0CTku6NvkQCeLxauaEPalb2tjpwCqMewPHsw
0xEAoMXrJPy98GjUZwq5bNufuUBlb3/u
=yXs+
-----END PGP SIGNATURE-----
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,534
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top