/*
* Copyright (C) 2011 Rhegium Team
*
* Licensed 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.rhegium.vaadin.internal.mvc;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import org.rhegium.api.mvc.View;
import org.rhegium.api.uibinder.TargetHandler;
import org.rhegium.api.uibinder.UiBinderEventService;
import org.rhegium.api.uibinder.UiBinderException;
import org.rhegium.internal.utils.StringUtils;
import com.vaadin.data.Container;
import com.vaadin.data.Container.ItemSetChangeEvent;
import com.vaadin.data.Item;
import com.vaadin.data.Item.PropertySetChangeEvent;
import com.vaadin.data.Property;
import com.vaadin.data.Property.ReadOnlyStatusChangeEvent;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.event.FieldEvents;
import com.vaadin.event.FieldEvents.BlurEvent;
import com.vaadin.event.FieldEvents.FocusEvent;
import com.vaadin.event.ItemClickEvent;
import com.vaadin.event.LayoutEvents;
import com.vaadin.event.LayoutEvents.LayoutClickEvent;
import com.vaadin.event.MouseEvents;
import com.vaadin.event.MouseEvents.ClickEvent;
import com.vaadin.event.MouseEvents.DoubleClickEvent;
import com.vaadin.ui.Button;
import com.vaadin.ui.Component;
import com.vaadin.ui.Component.ErrorEvent;
import com.vaadin.ui.ComponentContainer;
import com.vaadin.ui.ComponentContainer.ComponentAttachEvent;
import com.vaadin.ui.ComponentContainer.ComponentDetachEvent;
import com.vaadin.ui.TabSheet;
import com.vaadin.ui.TabSheet.SelectedTabChangeEvent;
import com.vaadin.ui.Table;
import com.vaadin.ui.Table.ColumnResizeEvent;
import com.vaadin.ui.Table.FooterClickEvent;
import com.vaadin.ui.Table.HeaderClickEvent;
import com.vaadin.ui.Tree;
import com.vaadin.ui.Tree.CollapseEvent;
import com.vaadin.ui.Tree.ExpandEvent;
import com.vaadin.ui.Upload;
import com.vaadin.ui.Upload.FailedEvent;
import com.vaadin.ui.Upload.FinishedEvent;
import com.vaadin.ui.Upload.StartedEvent;
import com.vaadin.ui.Upload.SucceededEvent;
import com.vaadin.ui.Window;
import com.vaadin.ui.Window.CloseEvent;
import com.vaadin.ui.Window.ResizeEvent;
class EventBusHandler implements TargetHandler {
private static final Map<String, Class<?>> eventMap = new HashMap<String, Class<?>>();
static {
eventMap.put("error", Component.ErrorListener.class);
eventMap.put("componentAttach", ComponentContainer.ComponentAttachListener.class);
eventMap.put("componentDetach", ComponentContainer.ComponentDetachListener.class);
eventMap.put("valueChange", Property.ValueChangeListener.class);
eventMap.put("readOnlyStatusChange", Property.ReadOnlyStatusChangeListener.class);
eventMap.put("propertySetChange", Container.PropertySetChangeListener.class);
eventMap.put("itemSetChange", Container.ItemSetChangeListener.class);
eventMap.put("blur", FieldEvents.BlurListener.class);
eventMap.put("focus", FieldEvents.FocusListener.class);
eventMap.put("layoutClick", LayoutEvents.LayoutClickListener.class);
eventMap.put("click", Button.ClickListener.class);
eventMap.put("mouseClick", MouseEvents.ClickListener.class);
eventMap.put("mouseDoubleClick", MouseEvents.DoubleClickListener.class);
eventMap.put("itemPropertySetChange", Item.PropertySetChangeListener.class);
eventMap.put("itemClick", ItemClickEvent.ItemClickListener.class);
eventMap.put("columnResize", Table.ColumnResizeListener.class);
eventMap.put("headerClick", Table.HeaderClickListener.class);
eventMap.put("footerClick", Table.FooterClickListener.class);
eventMap.put("collapse", Tree.CollapseListener.class);
eventMap.put("expand", Tree.ExpandListener.class);
eventMap.put("failed", Upload.FailedListener.class);
eventMap.put("finished", Upload.FinishedListener.class);
eventMap.put("progress", Upload.ProgressListener.class);
eventMap.put("started", Upload.StartedListener.class);
eventMap.put("succeeded", Upload.SucceededListener.class);
eventMap.put("close", Window.CloseListener.class);
eventMap.put("resize", Window.ResizeListener.class);
eventMap.put("selectedTabChange", TabSheet.SelectedTabChangeListener.class);
}
private final ComponentHandler componentHandler;
private final UiBinderEventService uiBinderEventService;
private final View<?, ?, ?> view;
EventBusHandler(View<?, ?, ?> view, ComponentHandler componentHandler, UiBinderEventService uiBinderEventService) {
this.view = view;
this.componentHandler = componentHandler;
this.uiBinderEventService = uiBinderEventService;
}
@Override
public String getTargetNamespace() {
return "urn:de.heldenreich.wcc.framework.mvc.uibinder.event";
}
@Override
public void handleStartElement(String uri, String name) {
}
@Override
public void handleEndElement(String uri, String name) {
}
@Override
public void handleAttribute(String name, Object value) {
if (value == null || !(value instanceof String) || StringUtils.isEmpty(value.toString())) {
throw new UiBinderException("Illegal attribute value found");
}
String eventName = value.toString();
bindListener(componentHandler.getCurrentComponent(), name, eventName);
}
private void bindListener(Component component, String eventType, String eventName) {
Class<?> eventTypeClass = eventMap.get(eventType);
try {
Method addListener = component.getClass().getMethod("addListener", new Class[] { eventTypeClass });
addListener.invoke(component, new DispatchingListenerImpl(uiBinderEventService, eventName));
}
catch (Exception e) {
throw new UiBinderException(String.format("The component %s does not support listeners of type '%s'", component
.getClass().getName(), eventType.getClass().getName()));
}
}
private String buildEventHandlerName(String prefix, String eventName) {
return prefix + Character.toUpperCase(eventName.charAt(0)) + eventName.substring(1);
}
@SuppressWarnings("serial")
private class DispatchingListenerImpl implements Component.ErrorListener, ComponentContainer.ComponentAttachListener,
ComponentContainer.ComponentDetachListener, Property.ValueChangeListener, Property.ReadOnlyStatusChangeListener,
Container.PropertySetChangeListener, Container.ItemSetChangeListener, FieldEvents.BlurListener,
FieldEvents.FocusListener, LayoutEvents.LayoutClickListener, Button.ClickListener, MouseEvents.ClickListener,
MouseEvents.DoubleClickListener, Item.PropertySetChangeListener, ItemClickEvent.ItemClickListener,
Table.ColumnResizeListener, Table.FooterClickListener, Table.HeaderClickListener, Tree.CollapseListener,
Tree.ExpandListener, TabSheet.SelectedTabChangeListener, Upload.FailedListener, Upload.FinishedListener,
Upload.ProgressListener, Upload.StartedListener, Upload.SucceededListener, Window.CloseListener,
Window.ResizeListener {
private final UiBinderEventService uiBinderEventService;
private final String eventName;
DispatchingListenerImpl(UiBinderEventService uiBinderEventService, String eventName) {
this.uiBinderEventService = uiBinderEventService;
this.eventName = buildEventHandlerName("on", eventName);
}
@Override
public void windowResized(ResizeEvent event) {
uiBinderEventService.dispatchEvent(view, eventName, event);
}
@Override
public void windowClose(CloseEvent event) {
uiBinderEventService.dispatchEvent(view, eventName, event);
}
@Override
public void uploadSucceeded(SucceededEvent event) {
uiBinderEventService.dispatchEvent(view, eventName, event);
}
@Override
public void uploadStarted(StartedEvent event) {
uiBinderEventService.dispatchEvent(view, eventName, event);
}
@Override
public void updateProgress(long readBytes, long contentLength) {
uiBinderEventService.dispatchEvent(view, eventName, readBytes, contentLength);
}
@Override
public void uploadFinished(FinishedEvent event) {
uiBinderEventService.dispatchEvent(view, eventName, event);
}
@Override
public void uploadFailed(FailedEvent event) {
uiBinderEventService.dispatchEvent(view, eventName, event);
}
@Override
public void selectedTabChange(SelectedTabChangeEvent event) {
uiBinderEventService.dispatchEvent(view, eventName, event);
}
@Override
public void nodeExpand(ExpandEvent event) {
uiBinderEventService.dispatchEvent(view, eventName, event);
}
@Override
public void nodeCollapse(CollapseEvent event) {
uiBinderEventService.dispatchEvent(view, eventName, event);
}
@Override
public void headerClick(HeaderClickEvent event) {
uiBinderEventService.dispatchEvent(view, eventName, event);
}
@Override
public void footerClick(FooterClickEvent event) {
uiBinderEventService.dispatchEvent(view, eventName, event);
}
@Override
public void columnResize(ColumnResizeEvent event) {
uiBinderEventService.dispatchEvent(view, eventName, event);
}
@Override
public void itemClick(ItemClickEvent event) {
uiBinderEventService.dispatchEvent(view, eventName, event);
}
@Override
public void itemPropertySetChange(PropertySetChangeEvent event) {
uiBinderEventService.dispatchEvent(view, eventName, event);
}
@Override
public void doubleClick(DoubleClickEvent event) {
uiBinderEventService.dispatchEvent(view, eventName, event);
}
@Override
public void click(ClickEvent event) {
uiBinderEventService.dispatchEvent(view, eventName, event);
}
@Override
public void buttonClick(com.vaadin.ui.Button.ClickEvent event) {
uiBinderEventService.dispatchEvent(view, eventName, event);
}
@Override
public void layoutClick(LayoutClickEvent event) {
uiBinderEventService.dispatchEvent(view, eventName, event);
}
@Override
public void focus(FocusEvent event) {
uiBinderEventService.dispatchEvent(view, eventName, event);
}
@Override
public void blur(BlurEvent event) {
uiBinderEventService.dispatchEvent(view, eventName, event);
}
@Override
public void containerItemSetChange(ItemSetChangeEvent event) {
uiBinderEventService.dispatchEvent(view, eventName, event);
}
@Override
public void containerPropertySetChange(com.vaadin.data.Container.PropertySetChangeEvent event) {
// TODO Auto-generated method stub
uiBinderEventService.dispatchEvent(view, eventName, event);
}
@Override
public void readOnlyStatusChange(ReadOnlyStatusChangeEvent event) {
uiBinderEventService.dispatchEvent(view, eventName, event);
}
@Override
public void valueChange(ValueChangeEvent event) {
uiBinderEventService.dispatchEvent(view, eventName, event);
}
@Override
public void componentDetachedFromContainer(ComponentDetachEvent event) {
uiBinderEventService.dispatchEvent(view, eventName, event);
}
@Override
public void componentAttachedToContainer(ComponentAttachEvent event) {
uiBinderEventService.dispatchEvent(view, eventName, event);
}
@Override
public void componentError(ErrorEvent event) {
uiBinderEventService.dispatchEvent(view, eventName, event);
}
}
}