Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 494223

Summary: When using vertical ToolbarLayout and horizontal ToolbarLayouts only the last element is drawn properly
Product: [Tools] GEF Reporter: Denis Aristov <_den>
Component: GEF-Legacy Draw2dAssignee: gef-inbox <gef-inbox>
Status: RESOLVED INVALID QA Contact:
Severity: normal    
Priority: P3 CC: nyssen
Version: 3.10.1   
Target Milestone: ---   
Hardware: PC   
OS: Linux   
Whiteboard:
Attachments:
Description Flags
Screenshot of the view (missing figures) none

Description Denis Aristov CLA 2016-05-21 05:42:05 EDT
Created attachment 261918 [details]
Screenshot of the view (missing figures)

For example, 1st route consists of 5 nodes and the second one consists of 3 nodes. Then it should look so:

[node10] -> [node11] -> [node12] -> [node13] -> [node14]

[node20] -> [node21] -> [node22]

So I created 3 edit parts.

TopEditPart that uses vertical ToolbarLayout

RouteEditPart that uses horizontal ToolbarLayout

and NodeEditPart

However when I execute the code only the last route is drawn completely. The first route isn't drawn - only the connections between its nodes are drawn.

Below is the source code of the "Route" view. You just need to add the view (RouteView.java) to an existing plugin to reproduce my problem.




import java.beans.PropertyChangeEvent;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.draw2d.ChopboxAnchor;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.FreeformLayer;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.MarginBorder;
import org.eclipse.draw2d.PolygonDecoration;
import org.eclipse.draw2d.PolylineConnection;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.RectangleFigure;
import org.eclipse.draw2d.ToolbarLayout;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.ConnectionEditPart;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartFactory;
import org.eclipse.gef.RootEditPart;
import org.eclipse.gef.editparts.AbstractConnectionEditPart;
import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
import org.eclipse.gef.editparts.FreeformGraphicalRootEditPart;
import org.eclipse.gef.ui.parts.ScrollingGraphicalViewer;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;

public class RouteView extends ViewPart {

    /**
     * The ID of the view as specified by the extension.
     */
    public static final String ID = "RouteView";

    // Use a standard Viewer for the Draw2d canvas
    private ScrollingGraphicalViewer viewer = new ScrollingGraphicalViewer();

    // Use standard RootEditPart as holder for all other edit parts
    private RootEditPart rootEditPart = new FreeformGraphicalRootEditPart();

    // Custom made EditPartFactory, will automatically be called to create edit
    // parts for model elements
    private EditPartFactory editPartFactory = new GraphicalPartFactory();
    // The model
    private Model model;

    /**
     * This is a callback that will allow us to create the viewer and initialize
     * it.
     */
    public void createPartControl(Composite parent) {
        // Create a dummy model
        model = new Model();

        // Initialize the viewer, 'parent' is the enclosing RCP window frame
        viewer.createControl(parent);
        viewer.setRootEditPart(rootEditPart);
        viewer.setEditPartFactory(editPartFactory);

        // Inject the model into the viewer, the viewer will traverse the model automatically
        viewer.setContents(model);

        // Set the view's background to white
        viewer.getControl().setBackground(new Color(null, 255, 255, 255));
    }

    /**
     * Passing the focus request to the viewer's control.
     */
    public void setFocus() {
        viewer.getControl().setFocus();
    }
}

class Model {
    private List<Route> routes;

    public Model() {
        routes = new ArrayList<>();

        Route route1 = new Route();

        for (int i = 0; i < 5; i++) {
            route1.addNode(new Node("Node1" + i));
        }

        routes.add(route1);

        Route route2 = new Route();
        for (int i = 0; i < 3; i++) {
            route2.addNode(new Node("Node2" + i));
        }

        routes.add(route2);

        addConnections();
    }

    private void addConnections() {
        for (int j = 0; j < routes.size(); j++) {
            Route route = routes.get(j);
            for (int i = 0; i < route.getNodes().size() - 1; i++) {
                NodeConnectionModel connection = new NodeConnectionModel();
                Node source = route.getNodes().get(i);
                Node target = route.getNodes().get(i + 1);
                connection.setSource(source);
                connection.setTarget(target);

                source.addSourceConnection(connection);
                target.addTargetConnection(connection);
            }
        }
    }

    public List<Route> getRoutes() {
        return routes;
    }
}

class Route {
    private int times;

    private List<Node> nodes;

    public Route() {
        nodes = new ArrayList<>();
    }

    public List<Node> getNodes() {
        return nodes;
    }

    public void addNode(Node nodeModel) {
        nodes.add(nodeModel);
    }

}

class Node {
    private final String label;

    private List<NodeConnectionModel> sourceConnections = new ArrayList<NodeConnectionModel>();
    private List<NodeConnectionModel> targetConnections = new ArrayList<NodeConnectionModel>();

    public Node(String label) {
        this.label = label;
    }

    public String getLabel() {
        return label;
    }

    public List<NodeConnectionModel> getSourceConnections() {
        return sourceConnections;
    }

    public List<NodeConnectionModel> getTargetConnections() {
        return targetConnections;
    }

    public void addSourceConnection(NodeConnectionModel conn) {
        sourceConnections.add(conn);
    }

    public void addTargetConnection(NodeConnectionModel conn) {
        targetConnections.add(conn);
    }
}

class GraphicalPartFactory implements EditPartFactory {

    public EditPart createEditPart(EditPart iContext, Object model) {

        EditPart editPart = null;
        if (model instanceof Model) {
            editPart = new TopEditPart();
        } else if (model instanceof Route) {
            editPart = new RouteEditPart();
        }

        else if (model instanceof Node) {
            editPart = new NodeEditPart();
        }

        if (editPart != null) {
            editPart.setModel(model);
        }

        return editPart;
    }
}

class NodeEditPart extends AbstractGraphicalEditPart {

    /** The figure's anchor. */
    private ChopboxAnchor anchor;

    protected IFigure createFigure() {
        IFigure rectangle = new RectangleFigure();
        rectangle.setBackgroundColor(new Color(null, 200, 200, 200));
        anchor = new ChopboxAnchor(rectangle);
        return rectangle;
    }

    protected void createEditPolicies() {
    }

    protected void refreshVisuals() {
        Node node = (Node) getModel();
        //This is where the actual drawing is done,
        // Simply a rectangle with text
        Rectangle bounds = new Rectangle(50, 50, 100, 50);
        getFigure().setBounds(bounds);
        Label label = new Label(node.getLabel());
        label.setTextAlignment(PositionConstants.CENTER);
        label.setBounds(bounds.crop(IFigure.NO_INSETS));
        getFigure().add(label);
    }

    public void propertyChange(PropertyChangeEvent evt) {
    }

    protected List getModelSourceConnections() {
        List sourceConnections = ((Node) getModel()).getSourceConnections();
        return sourceConnections;
    }

    protected List getModelTargetConnections() {
        List targetConnection = ((Node) getModel()).getTargetConnections();
        return targetConnection;
    }

    protected ConnectionEditPart createConnection(Object iModel) {
        NodeConnectionEditPart connectPart = (NodeConnectionEditPart) getRoot().getViewer().getEditPartRegistry().get(iModel);
        if (connectPart == null) {
            connectPart = new NodeConnectionEditPart();
            connectPart.setModel(iModel);
        }
        return connectPart;
    }
}

class RouteEditPart extends AbstractGraphicalEditPart {
    protected IFigure createFigure() {
        Figure f = new FreeformLayer();

        f.setBorder(new MarginBorder(1));

        ToolbarLayout layout = new ToolbarLayout();
        layout.setHorizontal(true);
        layout.setSpacing(20);
        f.setLayoutManager(layout);

        f.setOpaque(true);

        return f;
    }

    protected void createEditPolicies() {

    }

    protected List<Node> getModelChildren() {
        List<Node> children = ((Route) getModel()).getNodes();
        return children;
    }
}

class TopEditPart extends AbstractGraphicalEditPart {
    protected IFigure createFigure() {
        Figure f = new FreeformLayer();
        f.setBorder(new MarginBorder(10));

        ToolbarLayout layout = new ToolbarLayout();
        layout.setHorizontal(false);
        layout.setSpacing(10);
        f.setLayoutManager(layout);
        f.setOpaque(true);

        return f;
    }

    protected void createEditPolicies() {

    }

    protected List<Route> getModelChildren() {
        List<Route> children = ((Model) getModel()).getRoutes();
        return children;
    }
}

class NodeConnectionModel {

    private Node source;
    private Node target;

    public void setSource(Node s) {
        source = s;
    }

    public void setTarget(Node t) {
        target = t;
    }
}

class NodeConnectionEditPart extends AbstractConnectionEditPart {
    @Override
    protected IFigure createFigure() {
        PolylineConnection f = new PolylineConnection();
        f.setTargetDecoration(new PolygonDecoration());
        return f;
    }

    protected void createEditPolicies() {
    }
}
Comment 1 Denis Aristov CLA 2016-05-22 09:56:26 EDT
Sorry, if it is not a bug. I'm new to GEF and to Draw2D. I've just noticed that replacing FreeformLayer with Figure in the following code pieces solves the problem.

class RouteEditPart extends AbstractGraphicalEditPart {
     protected IFigure createFigure() {
        Figure f = new FreeformLayer();
        ...


class RouteEditPart extends AbstractGraphicalEditPart {
     protected IFigure createFigure() {
        Figure f = new Figure();
        ...
Comment 2 Alexander Nyßen CLA 2016-05-22 11:01:48 EDT
Resolving als invalid then.