The InteractiveWindowGroup will have handlers for all the input event that come from Java.
Lets make the simplifying assumption that there can only be one interactor running at a time. This means that when an Interactor is already running, the InteractiveWindowGroup can check each event to see if it is the stop event for that running interactor, and if so, call stop on the interactor, and otherwise call running on the interactor. If it calls stop, then it should check using getState after stop returns to see if the interactor is no longer running (if state == IDLE).
When no interactor is running, InteractiveWindowGroup will need to go through all the interactors for each input event to see if any interactor wants to start. The InteractiveWindowGroup should do the checking for the input event for each interactor (using the getStartEvent method of the interactor and comparing to the event from Java). If the event matches, the InteractiveWindowGroup should let the interactor itself do the hit testing, since, for example, ChoiceInteractors only should start if the start-event happens over a graphical object that implements the Selectable interface. Therefore, the start() method of the interactor should be called if the event matches, and the start method should first check the position to see if the interactor should actually start. Therefore, InteractiveWindowGroup will need to check after calling start() whether the interactor started or not, using getState() on the interactor.
When testing for starting, interactors should check to see if the event is inside any of the children of their attached group (note: not the group itself). Thus, all interactors operate over the immediate children of the group. If you need an interactor to operate on a single object, you would have to add it to an extra level of group.
Note also that you have to hit-test the children returned by getChildren() in reverse order (front most to back most). Fortunately that's easy to do with List.listIterator().
All Events include mouse pointer information, even keystrokes. That's a difference from Java -- KeyEvents in Java don't include the current mouse position. So InteractiveWindowGroup has to store the mouse position in order to add it to keystroke events.
> I've written up part of the code for MoveInteractor and it works but
> i'm facing the following problem when using InteractiveWindowGroup. I
> have the following test code
>
> InteractiveWindowGroup w = new
> InteractiveWindowGroup("Test",400,400);
> Interactor inter = new MoveInteractor();
> SimpleGroup simple = new SimpleGroup(0, 0, 200, 200);
> simple.addChild(new Rect(0,0,40,40,Color.red,1));
> simple.addChild(new FilledRect(50,10,40,40,Color.blue));
> simple.addChild(new Rect(10,90,60,40,Color.magenta,1));
>
> inter.setGroup(simple);
> inter.setStartAnywhere(false);
> inter.setStartEvent(new Event(Event.MOUSE_DOWN,
> InputEvent.BUTTON1_MASK, 0, 0, 0));
> inter.setStopEvent(new Event(Event.MOUSE_UP, InputEvent.BUTTON1_MASK,
> 0, 0, 0));
> w.addInteractor(inter);
> w.addChild(simple);
>
> First of all, is this the right approach? Should I be setting the start
> and stop events here or should MoveInteractor set its own start and
> stop events automatically in the constructor?
This seems fine to me. Yes, the user of an Interactor should set its events, just as your code does. You should have your interactors set reasonable default events in its constructor, but our tests won't count on it. We'll use setStartEvent and setStopEvent to configure it, just like you do.
> Secondly, in WindowGroup, simple gets drawn on "private JComponent
> canvas" . Now in InteractiveWindowGroup, when I do register for the
> events, I get the x, y location wrt the entire frame, and not the
> canvas. There doesn't seem anyway for me to translate those coordinates
> to coordinates wrt the canvas. Am I missing something?
This shouldn't be a problem, because the canvas is always at 0,0 relative to the frame.