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-----
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-----