0

I've written code that allows drag and drop onto a canvas. On 'dropping', a RectangleFigure is drawn on the canvas at that point. The problem is that when I drop onto the canvas for the second time, another copy of the first dropped element is made on the screen. Similarly, the third time, the first two elements are recreated.(We know this, to be true because if you drag one of the elements from it's original position, you can see the recreated elements underneath it) Can someone please tell me how to prevent this recreation from taking place? *I have added short testable code illustrating the problem

import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.LightweightSystem;
import org.eclipse.draw2d.MouseEvent;
import org.eclipse.draw2d.MouseListener;
import org.eclipse.draw2d.MouseMotionListener;
import org.eclipse.draw2d.RectangleFigure;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.SWT;


import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSource;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.DragSourceListener;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.DropTargetListener;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.wb.swt.SWTResourceManager;
import org.eclipse.swt.widgets.Label;

/**
* 
*Shortest complete testable code demonstrating the repeated creation problem
*/
public class RepeatDrop
{
/**
 * Launch the application.
 * 
 * @param args
 */

private Shell shell;
private Display display;
private Menu menu;
private Group grpPalette;
private final Label lblUnicorn;
private Group grpCanvas;
private final Canvas canvas;

public static void main(String args[]) {
    new RepeatDrop();
}

/**
 * Create the shell.
 * 
 * @param display
 */
public RepeatDrop() {
    display = new Display();
    shell = new Shell(display);
    shell.setText("SWT Application");
    shell.setSize(450, 393);

    Group grpPalette = new Group(shell, SWT.NONE);
    grpPalette.setText("Palette");
    grpPalette.setBounds(0, 0, 88, 325);

    lblUnicorn = new Label(grpPalette, SWT.BORDER | SWT.HORIZONTAL
            | SWT.CENTER);
    lblUnicorn.setText("UNICORN");
    // ADDED A FINAL HERE!!
    lblUnicorn.setAlignment(SWT.CENTER);
    lblUnicorn.setBounds(10, 24, 68, 53);

    final Group grpCanvas = new Group(shell, SWT.NONE);
    grpCanvas.setText("Canvas");
    grpCanvas.setBounds(94, 0, 330, 325);

    canvas = new Canvas(grpCanvas, SWT.NONE);
    canvas.setBackground(SWTResourceManager.getColor(253, 245, 230));
    canvas.setBounds(10, 20, 320, 295);


    LightweightSystem lws = new LightweightSystem(canvas); //
    final IFigure panel = new Figure(); //
    lws.setContents(panel); //

    DragSource dragSource1 = new DragSource(lblUnicorn, DND.DROP_COPY);
    Transfer[] transfers1 = new Transfer[] { TextTransfer.getInstance() };
    dragSource1.setTransfer(transfers1);
    dragSource1.addDragListener(new DragSourceListener() {
        public void dragStart(DragSourceEvent event) {
            if (lblUnicorn.getText().length() == 0) {
                event.doit = false;
            }
        }

        public void dragSetData(DragSourceEvent event) {
            if (TextTransfer.getInstance().isSupportedType (event.dataType)) {
                event.data = lblUnicorn.getText();
            }
        }

        public void dragFinished(DragSourceEvent event) {
        }
      });

    Transfer[] types = new Transfer[] { TextTransfer.getInstance() };
    DropTarget dropTarget = new DropTarget(canvas, DND.DROP_COPY
            | DND.DROP_DEFAULT);
    dropTarget.setTransfer(types);



    dropTarget.addDropListener(new DropTargetListener() {
        public void dragEnter(DropTargetEvent event) {
            if (event.detail == DND.DROP_DEFAULT) {
                if ((event.operations & DND.DROP_COPY) != 0) {
                    event.detail = DND.DROP_COPY;
                } else {
                    event.detail = DND.DROP_NONE;
                }
            }
        }

        public void dragLeave(DropTargetEvent event) {
        }

        public void dragOperationChanged(DropTargetEvent event) {
        }

        public void dragOver(DropTargetEvent event) {
        }



        public void drop(DropTargetEvent event) {
        }


        public void dropAccept(final DropTargetEvent event) 
        {

            if (TextTransfer.getInstance().isSupportedType(
                    event.currentDataType)) {
                String d = (String) TextTransfer.getInstance()
                        .nativeToJava(event.currentDataType);

                final String finald= d; 

                GC gc = new GC(canvas);
                canvas.redraw();




                canvas.addPaintListener(new PaintListener() {
                    public void paintControl(PaintEvent e) {


org.eclipse.swt.graphics.Point droppoint = canvas.toControl(event.x, event.y);

                        //DRAW 2D SECTION
                        RectangleFigure node1 = new RectangleFigure();
                        Rectangle rect=new Rectangle(droppoint.x, droppoint.y, 20, 20);
                        Rectangle rect2=new Rectangle(droppoint.x, droppoint.y, 100, 25);
                        node1.setBounds(rect);
                        node1.setBackgroundColor(ColorConstants.cyan);


                        org.eclipse.draw2d.Label droppedName= 
                                new org.eclipse.draw2d.Label(finald);
                        droppedName.setLocation(new Point(droppoint.x, droppoint.y)); //draw2d. point
                        droppedName.setBounds(rect2);

                        node1.add(droppedName);
                        panel.add(node1);
                        panel.add(droppedName);

                        Dragger fig = new Dragger(node1);
                        Dragger caption = new Dragger(droppedName);
                        //DRAW 2D SECTION

                    }

                });
            }
        }
    });


    shell.pack();
    shell.open();

    while (!shell.isDisposed()) {
        if (!display.readAndDispatch()) {
            display.sleep();
        }
    }

}

static class Dragger extends MouseMotionListener.Stub implements MouseListener 
{

      public Dragger(IFigure figure){
            figure.addMouseMotionListener(this);
            figure.addMouseListener(this);
      }

      Point last;
      public void mouseReleased(MouseEvent e){
      }
      public void mouseClicked(MouseEvent e){
      }
      public void mouseDoubleClicked(MouseEvent e){
      }
      public void mousePressed(MouseEvent e){
            last = e.getLocation();
      }

      public void mouseDragged(MouseEvent e){
            Point p = e.getLocation();
            Dimension delta = p.getDifference(last);
            {
                last = p;
                Figure f = ((Figure)e.getSource());
                f.setBounds(f.getBounds().getTranslated(delta.width, delta.height));
            }
      }
}


}
Asher
  • 811
  • 3
  • 10
  • 19

1 Answers1

0

Your issue is caused by the fact that you add a new PaintListener each time you add a new figure. That isn't necessary. In fact, you don't need to add any PaintListener at all. The LightweightSystem will take care of that for you.

Here is your code now working fine:

public class RepeatDrop
{
    private Shell        shell;
    private Display      display;
    private final Label  lblUnicorn;
    private final Canvas canvas;

    public static void main(String args[])
    {
        new RepeatDrop();
    }

    public RepeatDrop()
    {
        display = new Display();
        shell = new Shell(display);
        shell.setText("SWT Application");
        shell.setLayout(new GridLayout(2, false));

        Group grpPalette = new Group(shell, SWT.NONE);
        grpPalette.setText("Palette");
        grpPalette.setLayout(new GridLayout());
        grpPalette.setLayoutData(new GridData(SWT.BEGINNING, SWT.FILL, false, true));

        lblUnicorn = new Label(grpPalette, SWT.BORDER | SWT.HORIZONTAL | SWT.CENTER);
        lblUnicorn.setText("UNICORN");
        // ADDED A FINAL HERE!!
        lblUnicorn.setAlignment(SWT.CENTER);

        final Group grpCanvas = new Group(shell, SWT.NONE);
        grpCanvas.setText("Canvas");
        grpCanvas.setLayout(new GridLayout());
        grpCanvas.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

        canvas = new Canvas(grpCanvas, SWT.NONE);
        canvas.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

        LightweightSystem lws = new LightweightSystem(canvas); //
        final IFigure panel = new Figure(); //
        lws.setContents(panel); //

        DragSource dragSource1 = new DragSource(lblUnicorn, DND.DROP_COPY);
        Transfer[] transfers1 = new Transfer[] { TextTransfer.getInstance() };
        dragSource1.setTransfer(transfers1);
        dragSource1.addDragListener(new DragSourceListener()
        {
            public void dragStart(DragSourceEvent event)
            {
                if (lblUnicorn.getText().length() == 0)
                {
                    event.doit = false;
                }
            }

            public void dragSetData(DragSourceEvent event)
            {
                if (TextTransfer.getInstance().isSupportedType(event.dataType))
                {
                    event.data = lblUnicorn.getText();
                }
            }

            public void dragFinished(DragSourceEvent event)
            {
            }
        });

        Transfer[] types = new Transfer[] { TextTransfer.getInstance() };
        DropTarget dropTarget = new DropTarget(canvas, DND.DROP_COPY | DND.DROP_DEFAULT);
        dropTarget.setTransfer(types);

        dropTarget.addDropListener(new DropTargetListener()
        {
            public void dragEnter(DropTargetEvent event)
            {
                if (event.detail == DND.DROP_DEFAULT)
                {
                    if ((event.operations & DND.DROP_COPY) != 0)
                    {
                        event.detail = DND.DROP_COPY;
                    }
                    else
                    {
                        event.detail = DND.DROP_NONE;
                    }
                }
            }

            public void dragLeave(DropTargetEvent event)
            {
            }

            public void dragOperationChanged(DropTargetEvent event)
            {
            }

            public void dragOver(DropTargetEvent event)
            {
            }

            public void drop(DropTargetEvent event)
            {
            }

            public void dropAccept(final DropTargetEvent event)
            {

                if (TextTransfer.getInstance().isSupportedType(event.currentDataType))
                {
                    String d = (String) TextTransfer.getInstance().nativeToJava(event.currentDataType);

                    org.eclipse.swt.graphics.Point droppoint = canvas.toControl(event.x, event.y);

                    // DRAW 2D SECTION
                    RectangleFigure node1 = new RectangleFigure();
                    Rectangle rect = new Rectangle(droppoint.x, droppoint.y, 20, 20);
                    Rectangle rect2 = new Rectangle(droppoint.x, droppoint.y, 100, 25);
                    node1.setBounds(rect);
                    node1.setBackgroundColor(ColorConstants.cyan);

                    org.eclipse.draw2d.Label droppedName = new org.eclipse.draw2d.Label(d);
                    droppedName.setLocation(new Point(droppoint.x, droppoint.y)); // draw2d.
                                                                                  // point
                    droppedName.setBounds(rect2);

                    node1.add(droppedName);
                    panel.add(node1);
                    panel.add(droppedName);

                    new Dragger(node1);
                    new Dragger(droppedName);

                    canvas.redraw();
                }
            }
        });

        shell.pack();
        shell.setSize(400, 300);
        shell.open();

        while (!shell.isDisposed())
        {
            if (!display.readAndDispatch())
            {
                display.sleep();
            }
        }
    }

    static class Dragger extends MouseMotionListener.Stub implements MouseListener
    {
        public Dragger(IFigure figure)
        {
            figure.addMouseMotionListener(this);
            figure.addMouseListener(this);
        }

        Point last;

        public void mouseReleased(MouseEvent e)
        {
        }

        public void mouseClicked(MouseEvent e)
        {
        }

        public void mouseDoubleClicked(MouseEvent e)
        {
        }

        public void mousePressed(MouseEvent e)
        {
            last = e.getLocation();
        }

        public void mouseDragged(MouseEvent e)
        {
            Point p = e.getLocation();
            Dimension delta = p.getDifference(last);
            {
                last = p;
                Figure f = ((Figure) e.getSource());
                f.setBounds(f.getBounds().getTranslated(delta.width, delta.height));
            }
        }
    }
}

Please have a look at the way I used Layouts. It's far more reliable and will work better on different window sizes and screen resolutions.

Please also read this: Understanding Layouts in SWT

Baz
  • 36,440
  • 11
  • 68
  • 94