Author: ivaynberg Date: Sat May 7 22:33:15 2011 New Revision: 1100644 URL: http://svn.apache.org/viewvc?rev=1100644&view=rev Log: Introduce IComponentAwareEventSink which will pass the behavior's component as context to onEvent Issue: WICKET-3684
Added: wicket/trunk/wicket-core/src/main/java/org/apache/wicket/IComponentAwareEventSink.java (with props) Modified: wicket/trunk/wicket-core/src/main/java/org/apache/wicket/ComponentEventSender.java wicket/trunk/wicket-core/src/main/java/org/apache/wicket/IEventDispatcher.java wicket/trunk/wicket-core/src/main/java/org/apache/wicket/behavior/Behavior.java wicket/trunk/wicket-core/src/main/java/org/apache/wicket/settings/def/FrameworkSettings.java wicket/trunk/wicket-core/src/test/java/org/apache/wicket/ComponentEventsTest.java wicket/trunk/wicket-core/src/test/java/org/apache/wicket/EventDispatcherTest.java Modified: wicket/trunk/wicket-core/src/main/java/org/apache/wicket/ComponentEventSender.java URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/ComponentEventSender.java?rev=1100644&r1=1100643&r2=1100644&view=diff ============================================================================== --- wicket/trunk/wicket-core/src/main/java/org/apache/wicket/ComponentEventSender.java (original) +++ wicket/trunk/wicket-core/src/main/java/org/apache/wicket/ComponentEventSender.java Sat May 7 22:33:15 2011 @@ -70,7 +70,8 @@ final class ComponentEventSender impleme depth(event); break; case EXACT : - dispatcher.dispatchEvent(event.getSink(), event); + dispatcher.dispatchEvent(event.getSink(), event, ((sink instanceof Component) + ? (Component)sink : null)); break; } } @@ -91,13 +92,13 @@ final class ComponentEventSender impleme if (!targetsComponent && !targetsCycle) { - dispatcher.dispatchEvent(sink, event); + dispatcher.dispatchEvent(sink, event, null); return; } if (targetsApplication) { - dispatcher.dispatchEvent(source.getApplication(), event); + dispatcher.dispatchEvent(source.getApplication(), event, null); } if (event.isStop()) { @@ -105,7 +106,7 @@ final class ComponentEventSender impleme } if (targetsSession) { - dispatcher.dispatchEvent(source.getSession(), event); + dispatcher.dispatchEvent(source.getSession(), event, null); } if (event.isStop()) { @@ -113,7 +114,7 @@ final class ComponentEventSender impleme } if (targetsCycle) { - dispatcher.dispatchEvent(source.getRequestCycle(), event); + dispatcher.dispatchEvent(source.getRequestCycle(), event, null); } if (event.isStop()) { @@ -122,7 +123,7 @@ final class ComponentEventSender impleme Component cursor = targetsCycle ? source.getPage() : (Component)sink; - dispatcher.dispatchEvent(cursor, event); + dispatchToComponent(dispatcher, cursor, event); if (event.isStop()) { @@ -150,11 +151,11 @@ final class ComponentEventSender impleme boolean targetsApplication = sink instanceof Application; boolean targetsSession = targetsApplication || sink instanceof Session; boolean targetsCycle = targetsSession || sink instanceof RequestCycle; - boolean targetsComponnet = sink instanceof Component; + boolean targetsComponent = sink instanceof Component; - if (!targetsComponnet && !targetsCycle) + if (!targetsComponent && !targetsCycle) { - dispatcher.dispatchEvent(sink, event); + dispatcher.dispatchEvent(sink, event, null); return; } @@ -166,7 +167,7 @@ final class ComponentEventSender impleme } else { - dispatcher.dispatchEvent(cursor, event); + dispatchToComponent(dispatcher, cursor, event); } if (event.isStop()) { @@ -174,7 +175,7 @@ final class ComponentEventSender impleme } if (targetsCycle) { - dispatcher.dispatchEvent(source.getRequestCycle(), event); + dispatcher.dispatchEvent(source.getRequestCycle(), event, null); } if (event.isStop()) { @@ -182,7 +183,7 @@ final class ComponentEventSender impleme } if (targetsSession) { - dispatcher.dispatchEvent(source.getSession(), event); + dispatcher.dispatchEvent(source.getSession(), event, null); } if (event.isStop()) { @@ -190,7 +191,7 @@ final class ComponentEventSender impleme } if (targetsApplication) { - dispatcher.dispatchEvent(source.getApplication(), event); + dispatcher.dispatchEvent(source.getApplication(), event, null); } } @@ -211,14 +212,14 @@ final class ComponentEventSender impleme if (!targetsApplication && !targetsComponent) { - dispatcher.dispatchEvent(sink, event); + dispatcher.dispatchEvent(sink, event, null); return; } if (targetsComponent) { Component cursor = (Component)sink; - dispatcher.dispatchEvent(cursor, event); + dispatchToComponent(dispatcher, cursor, event); if (event.isStop()) { return; @@ -232,7 +233,7 @@ final class ComponentEventSender impleme } if (targetsCycle) { - dispatcher.dispatchEvent(source.getRequestCycle(), event); + dispatcher.dispatchEvent(source.getRequestCycle(), event, null); } if (event.isStop()) { @@ -240,7 +241,7 @@ final class ComponentEventSender impleme } if (targetsSession) { - dispatcher.dispatchEvent(source.getSession(), event); + dispatcher.dispatchEvent(source.getSession(), event, null); } if (event.isStop()) { @@ -248,10 +249,32 @@ final class ComponentEventSender impleme } if (targetsApplication) { - dispatcher.dispatchEvent(source.getApplication(), event); + dispatcher.dispatchEvent(source.getApplication(), event, null); } } + private static void dispatchToComponent(IEventDispatcher dispatcher, Component object, + ComponentEvent<?> e) + { + dispatcher.dispatchEvent(object, e, null); + + if (e.isStop()) + { + return; + } + + List<? extends Behavior> behaviors = object.getBehaviors(); + for (Behavior behavior : behaviors) + { + dispatcher.dispatchEvent(behavior, e, object); + if (e.isStop()) + { + break; + } + } + } + + /** * Visitor used to broadcast events to components * @@ -279,26 +302,13 @@ final class ComponentEventSender impleme /** {@inheritDoc} */ public void component(Component object, IVisit<Void> visit) { - dispatcher.dispatchEvent(object, e); + dispatchToComponent(dispatcher, object, e); if (e.isStop()) { visit.stop(); } - List<? extends Behavior> behaviors = object.getBehaviors(); - for (Behavior behavior : behaviors) - { - IEventSink behaviorSink = behavior; - dispatcher.dispatchEvent(behaviorSink, e); - if (e.isStop()) - { - visit.stop(); - break; - } - } - - if (e.isShallow()) { visit.dontGoDeeper(); Added: wicket/trunk/wicket-core/src/main/java/org/apache/wicket/IComponentAwareEventSink.java URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/IComponentAwareEventSink.java?rev=1100644&view=auto ============================================================================== --- wicket/trunk/wicket-core/src/main/java/org/apache/wicket/IComponentAwareEventSink.java (added) +++ wicket/trunk/wicket-core/src/main/java/org/apache/wicket/IComponentAwareEventSink.java Sat May 7 22:33:15 2011 @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.wicket; + +import org.apache.wicket.behavior.Behavior; +import org.apache.wicket.event.IEvent; +import org.apache.wicket.event.IEventSink; + +/** + * A specialization of {@link IEventSink} that adds component as an additional parameter to the + * {@link #onEvent(IEvent, Component)} method. This interface is useful for component plugins which + * wish to participate in event processing, for example {@link Behavior}s + * + * @author igor + */ +public interface IComponentAwareEventSink +{ + /** + * Called when an event is sent to this behavior sink + * + * @param component + * component that owns this sink. For example, if the implementation of this + * interface is a {@link Behavior} then component parameter will contain the + * component to which the behavior is attached. + * @param event + */ + void onEvent(Component component, IEvent<?> event); +} Propchange: wicket/trunk/wicket-core/src/main/java/org/apache/wicket/IComponentAwareEventSink.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: wicket/trunk/wicket-core/src/main/java/org/apache/wicket/IEventDispatcher.java URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/IEventDispatcher.java?rev=1100644&r1=1100643&r2=1100644&view=diff ============================================================================== --- wicket/trunk/wicket-core/src/main/java/org/apache/wicket/IEventDispatcher.java (original) +++ wicket/trunk/wicket-core/src/main/java/org/apache/wicket/IEventDispatcher.java Sat May 7 22:33:15 2011 @@ -16,6 +16,7 @@ */ package org.apache.wicket; +import org.apache.wicket.behavior.Behavior; import org.apache.wicket.event.IEvent; import org.apache.wicket.event.IEventSink; import org.apache.wicket.settings.IFrameworkSettings; @@ -24,6 +25,9 @@ import org.apache.wicket.settings.IFrame * Delivers an event to a component. Developers can implement and register their dispatchers in * {@link IFrameworkSettings} to create custom strategies for how events get delivered to components * + * @see IEventSink + * @see IComponentAwareEventSink + * * @author Igor Vaynberg (ivaynberg) */ public interface IEventDispatcher @@ -32,7 +36,16 @@ public interface IEventDispatcher * Dispatches the even to the target component * * @param sink + * the sink for the event. Sinks usually implement {@link IEventSink} or + * {@link IComponentAwareEventSink}. See the {@code component} parameter described + * below. * @param event + * @param component + * provides context to the sink. Some sinks are owned by the component, eg + * {@link Behavior}s, and thus it is useful for them to have a reference to their + * owning component. If this method is not {@code null} the dispatcher should try to + * look for an alternative sink method which takes a component reference as an + * additional parameter, one such implementation is {@link IComponentAwareEventSink}. */ - void dispatchEvent(IEventSink sink, IEvent<?> event); + void dispatchEvent(Object sink, IEvent<?> event, Component component); } Modified: wicket/trunk/wicket-core/src/main/java/org/apache/wicket/behavior/Behavior.java URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/behavior/Behavior.java?rev=1100644&r1=1100643&r2=1100644&view=diff ============================================================================== --- wicket/trunk/wicket-core/src/main/java/org/apache/wicket/behavior/Behavior.java (original) +++ wicket/trunk/wicket-core/src/main/java/org/apache/wicket/behavior/Behavior.java Sat May 7 22:33:15 2011 @@ -18,8 +18,8 @@ package org.apache.wicket.behavior; import org.apache.wicket.Component; import org.apache.wicket.IClusterable; +import org.apache.wicket.IComponentAwareEventSink; import org.apache.wicket.event.IEvent; -import org.apache.wicket.event.IEventSink; import org.apache.wicket.markup.ComponentTag; import org.apache.wicket.markup.html.IHeaderContributor; import org.apache.wicket.markup.html.IHeaderResponse; @@ -44,7 +44,11 @@ import org.apache.wicket.markup.html.IHe * @author Eelco Hillenius * @author Igor Vaynberg (ivaynberg) */ -public abstract class Behavior implements IClusterable, IEventSink, IHeaderContributor +public abstract class Behavior + implements + IClusterable, + IComponentAwareEventSink, + IHeaderContributor { private static final long serialVersionUID = 1L; @@ -208,7 +212,13 @@ public abstract class Behavior implement { } - public void onEvent(IEvent<?> event) + /** + * Called to notify the behavior about any events sent to the component + * + * @see org.apache.wicket.IComponentAwareEventSink#onEvent(org.apache.wicket.Component, + * org.apache.wicket.event.IEvent) + */ + public void onEvent(Component component, IEvent<?> event) { } Modified: wicket/trunk/wicket-core/src/main/java/org/apache/wicket/settings/def/FrameworkSettings.java URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/settings/def/FrameworkSettings.java?rev=1100644&r1=1100643&r2=1100644&view=diff ============================================================================== --- wicket/trunk/wicket-core/src/main/java/org/apache/wicket/settings/def/FrameworkSettings.java (original) +++ wicket/trunk/wicket-core/src/main/java/org/apache/wicket/settings/def/FrameworkSettings.java Sat May 7 22:33:15 2011 @@ -19,6 +19,8 @@ package org.apache.wicket.settings.def; import java.util.ArrayList; import java.util.List; +import org.apache.wicket.Component; +import org.apache.wicket.IComponentAwareEventSink; import org.apache.wicket.IDetachListener; import org.apache.wicket.IEventDispatcher; import org.apache.wicket.event.IEvent; @@ -87,11 +89,24 @@ public class FrameworkSettings implement /** * Dispatches event to registered dispatchers + * + * @see IEventDispatcher#dispatchEvent(Object, IEvent, Component) + * + * @param sink + * @param event + * @param component */ - public void dispatchEvent(IEventSink sink, IEvent<?> event) + public void dispatchEvent(Object sink, IEvent<?> event, Component component) { // direct delivery - sink.onEvent(event); + if (component != null && sink instanceof IComponentAwareEventSink) + { + ((IComponentAwareEventSink)sink).onEvent(component, event); + } + else if (sink instanceof IEventSink) + { + ((IEventSink)sink).onEvent(event); + } // additional dispatchers delivery if (eventDispatchers == null) @@ -100,7 +115,7 @@ public class FrameworkSettings implement } for (IEventDispatcher dispatcher : eventDispatchers) { - dispatcher.dispatchEvent(sink, event); + dispatcher.dispatchEvent(sink, event, component); } } } Modified: wicket/trunk/wicket-core/src/test/java/org/apache/wicket/ComponentEventsTest.java URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/test/java/org/apache/wicket/ComponentEventsTest.java?rev=1100644&r1=1100643&r2=1100644&view=diff ============================================================================== --- wicket/trunk/wicket-core/src/test/java/org/apache/wicket/ComponentEventsTest.java (original) +++ wicket/trunk/wicket-core/src/test/java/org/apache/wicket/ComponentEventsTest.java Sat May 7 22:33:15 2011 @@ -16,10 +16,13 @@ */ package org.apache.wicket; +import static org.junit.Assert.assertEquals; + import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import org.apache.wicket.behavior.Behavior; import org.apache.wicket.event.Broadcast; import org.apache.wicket.event.IEvent; import org.apache.wicket.markup.html.WebComponent; @@ -359,6 +362,42 @@ public class ComponentEventsTest assertPath(c135, c13, c1, page, cycle, session); } + @Test + public void testBehavior() + { + TestComponent c = new TestComponent("c"); + TestBehavior b1 = new TestBehavior(); + TestBehavior b2 = new TestBehavior(); + c.add(b1, b2); + + c.send(c, Broadcast.BREADTH, new Payload()); + assertEquals(0, c.sequence); + assertEquals(1, b1.sequence); + assertEquals(2, b2.sequence); + } + + @Test + public void testBehavior_stop() + { + TestComponent c = new TestComponent("c"); + TestBehavior b1 = new TestBehavior() + { + @Override + public void onEvent(Component component, IEvent<?> event) + { + super.onEvent(component, event); + event.stop(); + } + }; + TestBehavior b2 = new TestBehavior(); + c.add(b1, b2); + + c.send(c, Broadcast.BREADTH, new Payload()); + assertEquals(0, c.sequence); + assertEquals(1, b1.sequence); + assertEquals(-1, b2.sequence); + } + private void assertPath(Testable... testables) { @@ -582,6 +621,36 @@ public class ComponentEventsTest } } + + private class TestBehavior extends Behavior implements Testable + { + private static final long serialVersionUID = 1L; + + int sequence = -1; + Component component; + + @Override + public void onEvent(Component component, IEvent<?> event) + { + super.onEvent(component, event); + Payload payload = (Payload)event.getPayload(); + sequence = payload.next(); + this.component = component; + // System.out.println(getId()); + if (stop == this) + { + event.stop(); + } + } + + + public int getSequence() + { + return sequence; + } + } + + private static class Payload { private int counter; Modified: wicket/trunk/wicket-core/src/test/java/org/apache/wicket/EventDispatcherTest.java URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/test/java/org/apache/wicket/EventDispatcherTest.java?rev=1100644&r1=1100643&r2=1100644&view=diff ============================================================================== --- wicket/trunk/wicket-core/src/test/java/org/apache/wicket/EventDispatcherTest.java (original) +++ wicket/trunk/wicket-core/src/test/java/org/apache/wicket/EventDispatcherTest.java Sat May 7 22:33:15 2011 @@ -25,7 +25,6 @@ import java.lang.reflect.Method; import org.apache.wicket.behavior.Behavior; import org.apache.wicket.event.Broadcast; import org.apache.wicket.event.IEvent; -import org.apache.wicket.event.IEventSink; import org.apache.wicket.markup.html.WebComponent; /** @@ -46,7 +45,7 @@ public class EventDispatcherTest extends page.add(testComponent); page.send(page, Broadcast.DEPTH, null); assertTrue(testComponent.callbackInvoked); - assertEquals(testComponent.getBehaviors(TestBehavior.class).get(0).invokationTimes, 2); + assertEquals(testComponent.getBehaviors(TestBehavior.class).get(0).invocationTimes, 2); } @Retention(RetentionPolicy.RUNTIME) @@ -58,7 +57,7 @@ public class EventDispatcherTest extends /** */ public static class DispatchToAnnotatedMethod implements IEventDispatcher { - public void dispatchEvent(IEventSink sink, IEvent<?> event) + public void dispatchEvent(Object sink, IEvent<?> event, Component component) { Method[] sinkMethods = sink.getClass().getMethods(); for (Method sinkMethod : sinkMethods) @@ -102,22 +101,23 @@ public class EventDispatcherTest extends } } - private static class TestBehavior extends Behavior implements IEventSink + private static class TestBehavior extends Behavior { private static final long serialVersionUID = 1; - int invokationTimes = 0; + int invocationTimes = 0; - public void onEvent(IEvent<?> event) + @Override + public void onEvent(Component component, IEvent<?> event) { - invokationTimes++; + invocationTimes++; } @EventCallback public void testCallback() { - invokationTimes++; + invocationTimes++; } }