0

I see no getSource() method in PInputEvent class.

I want to get reference to an object, which handler was added to.

UPDATE

In the following example, three concentric circles created. Each bigger circle owns smaller one. Mouse click handler is attached to circle2. Since this circle owns circle3, handler triggers when clicked both circle2 and circle3, but not circle1.

How to obtain reference to circle2 from within handler if click was made to circle3?

Neither of tested methods help.

package test.piccolo;

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.piccolox.PFrame;

public class App {

    @SuppressWarnings("serial")
    public static void main(String[] args) {

        new PFrame() {

            public void initialize() {

                PPath circle1 = PPath.createEllipse(-50, -50, 100, 100);
                circle1.setPaint(null);
                System.out.println("circle1 = " + circle1.toString());

                getCanvas().getLayer().addChild(circle1);

                PPath circle2 = PPath.createEllipse(-40, -40, 80, 80);
                circle2.setPaint(null);
                System.out.println("circle2 = " + circle2.toString());

                circle1.addChild(circle2);

                PPath circle3 = PPath.createEllipse(-30, -30, 60, 60);
                circle3.setPaint(null);
                System.out.println("circle3 = " + circle3.toString());

                circle2.addChild(circle3);

                circle2.addInputEventListener(new PBasicInputEventHandler() {
                    @Override
                    public void mouseClicked(PInputEvent event) {

                        Object o;

                        o = event.getSourceSwingEvent().getSource().toString();
                        System.out.println("event.getSourceSwingEvent().getSource() = " + o);

                        o = event.getComponent().toString();
                        System.out.println("event.getComponent() = " + o);

                        o = event.getPickedNode().toString();
                        System.out.println("event.getPickedNode() = " + o);

                    }
                });
            };





        };
    }
}

UPDATE 2

My requirement is to treat some topmost dummy node as wrapper for it's children. I want to attach handler to a parent and track all events underneath. At the same moment, parent can be a child of some more complex scene as a whole. So, I need to catch event at some intermediate level.

Suzan Cioc
  • 29,281
  • 63
  • 213
  • 385

1 Answers1

1

PInputEvent.getSourceSwingEvent() returns the underlying swing event - InputEvent, from that getSource() should give you the source, ie:

event.getSourceSwingEvent().getSource()

EDIT:

It appears that event.getSourceSwingEvent().getSource() is always a canvas. It makes sense as the event actually originated on canvas.

event.getPickedNode() is the actual picked node. It may be a child of a node that have a registered listener, such as circle3 in the posted sample code.

I am not sure what is the scenario and the reason for finding a node that registered a listener. In most cases, the desired output is the picked node. To find what you're looking for you may have a custom designated extension of PInputEventListener that can hold a reference to a node that registers it. It may be an overkill, depending on a situation. For example:

public static class MyEventHandler extends PBasicInputEventHandler {
    private PNode node;
    public MyEventHandler(PNode node) {
        this.node = node;
    }

    public PNode getNode() {
        return this.node;
    }
}

Another hacky way that comes to mind is to traverse either a stack of objects in a pick path or an hierarchy of nodes to find a node that has this listener. For example to traverse the hierarchy of nodes (similarly it is also possible to enumerate nodes in event.getPath().getNodeStackReference()) :

public static PNode getRealEventSource(PInputEvent event, PInputEventListener listener) {
    PNode node = event.getPickedNode();
    while(node != null){
        EventListenerList listeners = node.getListenerList();
        if (listeners != null) {
            if (Arrays.asList(listeners.getListenerList()).contains(listener)) {
                return node;
            }
        }
        node = node.getParent();
    }

    return null;
}

And then, invoke it like this from within the mouseClicked() method:

System.out.println("The real source:" + getRealEventSource(event, this));
tenorsax
  • 21,123
  • 9
  • 60
  • 107
  • This also gives not the same object, handler was attached to – Suzan Cioc Nov 06 '13 at 08:24
  • First method you propose requires one instance of handler per each attached node. This makes hard to detach when required. So I already used this sort of solution with the addition that handler attaches and detaches itself. Second method will not work if the same handler attached twice in the hierarchy. – Suzan Cioc Nov 06 '13 at 23:23
  • @SuzanCioc in the above sample if you attach the handler to all the circles, the second method works ok. Although, the event probably needs to be marked as handled. All in all, the method is missing, but it is probably intentional according to design of piccolo's graph scene. – tenorsax Nov 07 '13 at 00:23