1

I'm trying to create a connection between two ellipses on a canvas, AFTER having created the ellipses and storing their positions on the canvas. These stored positions need to be used to create the connection. The code I've written works for RectangleFigures but does not for Ellipses. I can't seem to see the difference between the two cases. Could someone please help? Thanks.*I've added short testable code to illustrate my problem. To see it working with Rectangles, please uncomment the line saying UNCOMMENT THIS

    import java.util.ArrayList;
    import org.eclipse.draw2d.ColorConstants;
    import org.eclipse.draw2d.ChopboxAnchor;
    import org.eclipse.draw2d.Ellipse;
    import org.eclipse.draw2d.Figure;
    import org.eclipse.draw2d.IFigure;
    import org.eclipse.draw2d.LightweightSystem;
    import org.eclipse.draw2d.PolygonDecoration;
    import org.eclipse.draw2d.PolylineConnection;
    import org.eclipse.draw2d.RectangleFigure;
    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.SelectionAdapter;
    import org.eclipse.swt.events.SelectionEvent;
    import org.eclipse.swt.layout.GridData;
    import org.eclipse.swt.layout.GridLayout;
    import org.eclipse.swt.widgets.Button;
    import org.eclipse.swt.widgets.Display;
    import org.eclipse.swt.widgets.Layout;
    import org.eclipse.swt.widgets.Shell;
    import org.eclipse.swt.widgets.Group;
    import org.eclipse.swt.widgets.Canvas;
    import org.eclipse.swt.widgets.Label;



    public class EllipseProblem
   { 
    private Shell        shell;
    private Display      display;
    private final Label  lblUnicorn;
    private final Canvas canvas;
    final IFigure panel;
    public static ArrayList canvasElements= new ArrayList(); 

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

    public EllipseProblem()
    {
        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");
        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));

        Button btnCreate = new Button(grpPalette, SWT.CENTER);
        GridData gd_btnCreate = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
        gd_btnCreate.widthHint = 87;
        gd_btnCreate.heightHint = 33;
        btnCreate.setLayoutData(gd_btnCreate);
        btnCreate.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                drawConnection(); 
            }
        });
        btnCreate.setText("Make Connection");

        LightweightSystem lws = new LightweightSystem(canvas); 
        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; 
                    org.eclipse.swt.graphics.Point droppoint = canvas.toControl(event.x, event.y);
                    canvasElements.add(droppoint);
                    Rectangle rect=new Rectangle(droppoint.x, droppoint.y, 40, 20);
                    Rectangle rect2=new Rectangle(droppoint.x+20, droppoint.y, 100, 25);

                    Ellipse node= new Ellipse();
                    //RectangleFigure node= new RectangleFigure(); UNCOMMENT THIS

                    node.setBounds(rect); 
                    System.out.println(node.getBounds());
                    node.setLocation(new Point(droppoint.x, droppoint.y));

                    node.setBackgroundColor(ColorConstants.red);
                    panel.add(node);
                    org.eclipse.draw2d.Label droppedName= 
                            new org.eclipse.draw2d.Label(finald);
                    droppedName.setLocation(new Point(droppoint.x, droppoint.y)); //draw2d. point
                    droppedName.setBounds(rect2);

                    panel.add(node);
                    panel.add(droppedName);

                    canvas.redraw();
                }
            }
        });

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

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

    protected void drawConnection()
    {

        org.eclipse.swt.graphics.Point swt_origin= (org.eclipse.swt.graphics.Point) canvasElements.get(0);
        org.eclipse.draw2d.geometry.Point origin_point= new org.eclipse.draw2d.geometry.Point(swt_origin.x, swt_origin.y); 
        org.eclipse.swt.graphics.Point swt_destination= (org.eclipse.swt.graphics.Point) canvasElements.get(1);
        org.eclipse.draw2d.geometry.Point destination_point= new org.eclipse.draw2d.geometry.Point(swt_destination.x, swt_destination.y); 

        IFigure origin = panel.findFigureAt(origin_point);
        IFigure destination = panel.findFigureAt(destination_point);

        PolylineConnection conn = new PolylineConnection();

        conn.setSourceAnchor(new ChopboxAnchor(origin));
        conn.setTargetAnchor(new ChopboxAnchor(destination));
        conn.setTargetDecoration(new PolygonDecoration());
        panel.add(conn);


    }

}
Asher
  • 811
  • 3
  • 10
  • 19
  • What do you get and what do you expect? – Mirco Jul 22 '14 at 09:08
  • @verbose-mode With ellipses, the arrow-head just situated itself on the side of the screen. With RectangleFigures and what I expect, is the complete arrow from one figure to another. – Asher Jul 22 '14 at 09:11

1 Answers1

2

Your problem is caused by the fact, that your method to determine the source and target IFigures is flawed.

You store the top left corner for the lookup. That works just fine for the RectangleFigure, since that rectangle actually contains the top left corner. The Ellipse, however, doesn't (which is why the source and target of the PolylineConnection is their parent).

Best illustrated with an image:

enter image description here

If you instead store the center of the figure you'll end up with this:

enter image description here

Baz
  • 36,440
  • 11
  • 68
  • 94
  • Thank you for your answer! I can't think of any other way so I'm just using the point of drop plus half of the width/height as a general ballpark figure and storing that. Do you know of a better way than that though? Couldn't find anything relevant in the API. – Asher Jul 22 '14 at 09:54
  • @Asher If you can be certain that all your figures actually contain the center point, then using it should be fine. – Baz Jul 22 '14 at 10:05