org.apache.wicket.ComponentEventSender Maven / Gradle / Ivy
/*
* 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 java.util.List;
import org.apache.wicket.behavior.Behavior;
import org.apache.wicket.event.Broadcast;
import org.apache.wicket.event.IEventSink;
import org.apache.wicket.event.IEventSource;
import org.apache.wicket.request.cycle.RequestCycle;
import org.apache.wicket.util.lang.Args;
import org.apache.wicket.util.visit.IVisit;
import org.apache.wicket.util.visit.IVisitor;
import org.apache.wicket.util.visit.Visits;
/**
* Implements event {@link Broadcast}ing
*
* @author Igor Vaynberg (ivaynberg)
*/
final class ComponentEventSender implements IEventSource
{
private final Component source;
private final IEventDispatcher dispatcher;
/**
* Constructor
*
* @param source
* component that originated the event
* @param dispatcher
*/
public ComponentEventSender(Component source, IEventDispatcher dispatcher)
{
Args.notNull(source, "source");
Args.notNull(dispatcher, "dispatcher");
this.source = source;
this.dispatcher = dispatcher;
}
/** {@inheritDoc} */
@Override
public void send(IEventSink sink, Broadcast type, T payload)
{
ComponentEvent> event = new ComponentEvent(sink, source, type, payload);
Args.notNull(type, "type");
switch (type)
{
case BUBBLE :
bubble(event);
break;
case BREADTH :
breadth(event);
break;
case DEPTH :
depth(event);
break;
case EXACT :
exact(event);
break;
}
}
/**
* Exact broadcast
*
* Broadcasts the event only to the sink. In case the sink is a Component
* then all its behaviors are notified as well.
*
* @param event
* The event with the payload
*/
private void exact(ComponentEvent> event)
{
IEventSink sink = event.getSink();
if (sink instanceof Component)
{
dispatchToComponent(dispatcher, (Component) sink, event);
}
else
{
dispatcher.dispatchEvent(sink, event, null);
}
}
/**
* Breadth broadcast
*
* @param event
*/
private void breadth(final ComponentEvent> event)
{
IEventSink sink = event.getSink();
boolean targetsApplication = sink instanceof Application;
boolean targetsSession = targetsApplication || sink instanceof Session;
boolean targetsCycle = targetsSession || sink instanceof RequestCycle;
boolean targetsComponent = sink instanceof Component;
if (!targetsComponent && !targetsCycle)
{
dispatcher.dispatchEvent(sink, event, null);
return;
}
if (targetsApplication)
{
dispatcher.dispatchEvent(source.getApplication(), event, null);
}
if (event.isStop())
{
return;
}
if (targetsSession)
{
dispatcher.dispatchEvent(source.getSession(), event, null);
}
if (event.isStop())
{
return;
}
if (targetsCycle)
{
dispatcher.dispatchEvent(source.getRequestCycle(), event, null);
}
if (event.isStop())
{
return;
}
Component cursor = targetsCycle ? source.getPage() : (Component)sink;
dispatchToComponent(dispatcher, cursor, event);
if (event.isStop())
{
return;
}
event.resetShallow(); // reset shallow flag
if (cursor instanceof MarkupContainer)
{
((MarkupContainer)cursor).visitChildren(new ComponentEventVisitor(event, dispatcher));
}
}
/**
* Depth broadcast
*
* @param event
* event
*/
private void depth(final ComponentEvent> event)
{
IEventSink sink = event.getSink();
boolean targetsApplication = sink instanceof Application;
boolean targetsSession = targetsApplication || sink instanceof Session;
boolean targetsCycle = targetsSession || sink instanceof RequestCycle;
boolean targetsComponent = sink instanceof Component;
if (!targetsComponent && !targetsCycle)
{
dispatcher.dispatchEvent(sink, event, null);
return;
}
Component cursor = (targetsCycle) ? source.getPage() : (Component)sink;
if (cursor instanceof MarkupContainer)
{
Visits.visitPostOrder(cursor, new ComponentEventVisitor(event, dispatcher));
}
else
{
dispatchToComponent(dispatcher, cursor, event);
}
if (event.isStop())
{
return;
}
if (targetsCycle)
{
dispatcher.dispatchEvent(source.getRequestCycle(), event, null);
}
if (event.isStop())
{
return;
}
if (targetsSession)
{
dispatcher.dispatchEvent(source.getSession(), event, null);
}
if (event.isStop())
{
return;
}
if (targetsApplication)
{
dispatcher.dispatchEvent(source.getApplication(), event, null);
}
}
/**
* Bubbles the event
*
* @param event
* event
*/
private void bubble(ComponentEvent> event)
{
IEventSink sink = event.getSink();
boolean targetsComponent = sink instanceof Component;
boolean targetsCycle = targetsComponent || sink instanceof RequestCycle;
boolean targetsSession = targetsCycle || sink instanceof Session;
boolean targetsApplication = targetsSession || sink instanceof Application;
if (!targetsApplication && !targetsComponent)
{
dispatcher.dispatchEvent(sink, event, null);
return;
}
if (targetsComponent)
{
Component cursor = (Component)sink;
dispatchToComponent(dispatcher, cursor, event);
if (event.isStop())
{
return;
}
cursor.visitParents(MarkupContainer.class, new ComponentEventVisitor(event, dispatcher));
}
if (event.isStop())
{
return;
}
if (targetsCycle)
{
dispatcher.dispatchEvent(source.getRequestCycle(), event, null);
}
if (event.isStop())
{
return;
}
if (targetsSession)
{
dispatcher.dispatchEvent(source.getSession(), event, null);
}
if (event.isStop())
{
return;
}
if (targetsApplication)
{
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
*
* @author igor
*/
private static class ComponentEventVisitor implements IVisitor
{
private final ComponentEvent> e;
private final IEventDispatcher dispatcher;
/**
* Constructor
*
* @param event
* event to send
* @param dispatcher
* event dispatcher
*/
private ComponentEventVisitor(ComponentEvent> event, IEventDispatcher dispatcher)
{
e = event;
this.dispatcher = dispatcher;
}
/** {@inheritDoc} */
@Override
public void component(T object, IVisit visit)
{
dispatchToComponent(dispatcher, object, e);
if (e.isStop())
{
visit.stop();
}
if (e.isShallow())
{
visit.dontGoDeeper();
}
e.resetShallow(); // reset shallow bit
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy