public NodeLinkCanvas(int width, int height) {
        setPreferredSize(new Dimension(width, height));

        // Initialize, and create a layer for the edges (always underneath the nodes)
        nodeLayer = getLayer();
        edgeLayer = new PLayer();
        getRoot().addChild(edgeLayer);
        getCamera().addLayer(0, edgeLayer);
        
        // Create event handler to move nodes and update edges
        nodeLayer.addInputEventListener(new PDragEventHandler() {
            {
                PInputEventFilter filter = new PInputEventFilter();
                filter.setOrMask(InputEvent.BUTTON1_MASK | InputEvent.BUTTON3_MASK);
                setEventFilter(filter);
            }

            public void mouseEntered(PInputEvent e) {
                super.mouseEntered(e);
                if (e.getButton() == MouseEvent.NOBUTTON) {
                    e.getPickedNode().setPaint(Color.RED);
                }
            }
            
            public void mouseExited(PInputEvent e) {
                super.mouseExited(e);
                if (e.getButton() == MouseEvent.NOBUTTON) {
                    e.getPickedNode().setPaint(Color.WHITE);
                }
            }
            
            protected void startDrag(PInputEvent e) {
                super.startDrag(e);
                e.setHandled(true);
                e.getPickedNode().moveToFront();
            }
            
			@SuppressWarnings("unchecked")
			protected void drag(PInputEvent e) {
                super.drag(e);
                
                ArrayList<PPath> edges = (ArrayList<PPath>) e.getPickedNode().getAttribute("edges");
                for (int i = 0; i < edges.size(); i++) {
                    NodeLinkCanvas.this.updateEdge((PPath) edges.get(i));
                }
            }
        });
    }