1

I have next problem. In my project I need to delegate message to the third-party library when nodes are added or removed from layer. In order to achieve this I have extended PLayer in next way:

public class DelegateLayer extends PLayer {
    private Delegate delegate = null;
    private boolean delegationNeeded = false;
    public DelegateLayer() {
        super();
    }
    @Override
    public void removeChildren(final Collection children) {
        for (Object child : children) {
            removeChild((PNode)child);
        }
    }
    @Override
    public void addChildren(final Collection children) {
        for (Object child : children) {
            addChild((PNode) child);
        }
    }

    @Override
    public void addChild(final PNode child) {
        if (delegationNeeded) {
            Preconditions.checkNotNull(delegate, "DelegateLayer: Delegate is not initialized");
            delegate.delegateNodeAdded((CloudNode)child);
        }
        super.addChild(child);
    }

    @Override
    public PNode removeChild(final PNode child) {
        if (delegationNeeded) {
            Preconditions.checkNotNull(delegate, "DelegateLayer: Delegate is not initialized");
            delegate.delegateNodeRemoved((CloudNode)child);
        }
        return super.removeChild(child);
    }

    public void setDelegationNeeded(boolean needed) {
        this.delegationNeeded = needed;
    }

    public void setDelegate(ClusterUpdateDelegate delegate) {
        this.delegate = delegate;
    }
}


I have also added this node layer to the canvas's camera:

DelegateLayer nodeLayer = new DelegateLayer();
camera.addLayer(0, nodeLayer);

However, after I place nodes to the layer and apply transformation (centering nodes on point) nothing happens. But as soon as I swith to PLayer that I get using camera.getLayer(0) everything works fine.

So, could anyone, please, explain what is wrong?

Anjenson
  • 117
  • 1
  • 11

1 Answers1

1

You may be missing a call to add a newly created layer to a PRoot. Here is a snapshot of the runtime structure that is described in in Piccolo2D Patterns:

enter image description here

In this brief demo, when you comment out canvas.getCamera().getRoot().addChild(layer); the animation stops working:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.geom.Point2D;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

import edu.umd.cs.piccolo.PCanvas;
import edu.umd.cs.piccolo.PLayer;
import edu.umd.cs.piccolo.PNode;
import edu.umd.cs.piccolo.event.PBasicInputEventHandler;
import edu.umd.cs.piccolo.event.PInputEvent;
import edu.umd.cs.piccolo.nodes.PPath;
import edu.umd.cs.piccolo.util.PBounds;

public class Test {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {   
            public void run() {   
                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLocationByPlatform(true);

                final PCanvas canvas = new PCanvas() {
                    @Override
                    public Dimension getPreferredSize() {
                        return new Dimension(600, 400);
                    }
                };

                PLayer layer = new PLayer() {
                    @Override
                    public void addChild(final PNode child) {
                        System.out.println("notify: addChild");
                        super.addChild(child);
                    }
                };

                canvas.getCamera().addLayer(0, layer);
                canvas.getCamera().getRoot().addChild(layer);

                final PPath node = PPath.createRectangle(0, 0, 100, 100);
                node.setPaint(Color.RED);
                canvas.getLayer().addChild(node);

                canvas.addInputEventListener(new PBasicInputEventHandler() {
                    @Override
                    public void mouseClicked(PInputEvent event) {
                        Point2D p = event.getCamera().localToView(
                                event.getCanvasPosition());
                        PBounds bounds = node.getBounds();
                        final double dx = p.getX() - bounds.getCenterX();
                        final double dy = p.getY() - bounds.getCenterY();
                        node.animateToBounds(node.getBounds().x + dx, bounds.y
                                + dy, bounds.width, bounds.height, 300);
                    }
                });

                frame.add(canvas);            
                frame.pack();
                frame.setVisible(true);
            }
        });
    }    
}

Also, as an alternative, you can listener to PNode.PROPERTY_CHILDREN property without adding a custom layer:

canvas.getLayer().addPropertyChangeListener(PNode.PROPERTY_CHILDREN, new PropertyChangeListener() {
    @Override
    public void propertyChange(PropertyChangeEvent e) {
        System.out.println("notify");
    }
});

Although, in this approach you have no information which child was added/removed.

tenorsax
  • 21,123
  • 9
  • 60
  • 107
  • Also, in this [answer](http://stackoverflow.com/a/20793211/1048330) there is a source code of `PUtil.createBasicScenegraph()` that illustrates how a link between a root and a layer is created. – tenorsax Jul 21 '14 at 23:12