| /** |
| * |
| * Copyright (c) 2011, 2016 - Loetz GmbH&Co.KG (69115 Heidelberg, Germany) |
| * |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Christophe Loetz (Loetz GmbH&Co.KG) - initial implementation |
| */ |
| package org.eclipse.osbp.osgi.hybrid.api; |
| |
| import java.lang.reflect.InvocationTargetException; |
| import java.lang.reflect.Method; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import com.vaadin.event.FieldEvents.BlurEvent; |
| import com.vaadin.event.FieldEvents.BlurListener; |
| import com.vaadin.event.FieldEvents.BlurNotifier; |
| import com.vaadin.event.FieldEvents.FocusEvent; |
| import com.vaadin.event.FieldEvents.FocusListener; |
| import com.vaadin.event.FieldEvents.FocusNotifier; |
| import com.vaadin.server.AbstractClientConnector; |
| import com.vaadin.ui.AbstractComponent; |
| import com.vaadin.ui.AbstractComponentContainer; |
| import com.vaadin.ui.AbstractLayout; |
| import com.vaadin.ui.Component; |
| import com.vaadin.ui.HasComponents; |
| import com.vaadin.ui.HasComponents.ComponentAttachDetachNotifier; |
| import com.vaadin.ui.HasComponents.ComponentAttachEvent; |
| import com.vaadin.ui.HasComponents.ComponentAttachListener; |
| import com.vaadin.ui.HasComponents.ComponentDetachEvent; |
| import com.vaadin.ui.HasComponents.ComponentDetachListener; |
| |
| import org.eclipse.osbp.utils.theme.EnumCssClass; |
| |
| |
| public class RecursiveFocusBlurListener implements ComponentAttachListener, ComponentDetachListener { |
| |
| private static final Logger LOGGER = LoggerFactory.getLogger(RecursiveFocusBlurListener.class); |
| private AbstractComponentContainer fParent; |
| |
| protected RecursiveFocusBlurListener(AbstractComponentContainer container) { |
| fParent = container; |
| } |
| |
| public static RecursiveFocusBlurListener attachFor(AbstractComponentContainer container) { |
| RecursiveFocusBlurListener listener = new RecursiveFocusBlurListener(container); |
| listener.recursiveAddComponentAttachDetachListener(container); |
| listener.recursiveAddFocusBlurListener(container); |
| return listener; |
| } |
| |
| public void detach() { |
| recursiveRemoveComponentAttachDetachListener(fParent); |
| recursiveRemoveFocusBlurListener(fParent); |
| } |
| |
| private FocusListener fFocusListener = new FocusListener() { |
| @Override |
| public void focus(FocusEvent event) { |
| if (event.getComponent() instanceof AbstractComponent) { |
| AbstractComponent component = (AbstractComponent) event.getComponent(); |
| recursiveFocus((AbstractComponent)event.getComponent()); |
| } |
| } |
| }; |
| |
| private void recursiveFocus(AbstractComponent component) { |
| if (component != null) { |
| component.addStyleName(EnumCssClass.HAS_FOCUS.styleName()); |
| if (!component.equals(fParent) && (component.getParent() instanceof AbstractComponent)) { |
| recursiveFocus((AbstractComponent)component.getParent()); |
| } |
| } |
| } |
| |
| private BlurListener fBlurListener = new BlurListener() { |
| @Override |
| public void blur(BlurEvent event) { |
| if (event.getComponent() instanceof AbstractComponent) { |
| AbstractComponent component = (AbstractComponent) event.getComponent(); |
| recursiveBlur((AbstractComponent)event.getComponent()); |
| } |
| } |
| }; |
| |
| private void recursiveBlur(AbstractComponent component) { |
| if (component != null) { |
| component.removeStyleName(EnumCssClass.HAS_FOCUS.styleName()); |
| if (!component.equals(fParent) && (component.getParent() instanceof AbstractComponent)) { |
| recursiveBlur((AbstractComponent)component.getParent()); |
| } |
| } |
| } |
| |
| private static final long serialVersionUID = 3497317619845108761L; |
| |
| @Override |
| public void componentAttachedToContainer(ComponentAttachEvent event) { |
| if (event.getAttachedComponent() instanceof ComponentAttachDetachNotifier) { |
| recursiveAddComponentAttachDetachListener((ComponentAttachDetachNotifier)event.getAttachedComponent()); |
| } |
| if (event.getAttachedComponent() instanceof AbstractClientConnector) { |
| recursiveAddFocusBlurListener((AbstractClientConnector)event.getAttachedComponent()); |
| } |
| } |
| |
| @Override |
| public void componentDetachedFromContainer(ComponentDetachEvent event) { |
| if (event.getDetachedComponent() instanceof ComponentAttachDetachNotifier) { |
| recursiveRemoveComponentAttachDetachListener((ComponentAttachDetachNotifier)event.getDetachedComponent()); |
| } |
| if (event.getDetachedComponent() instanceof AbstractComponent) { |
| recursiveRemoveFocusBlurListener((AbstractComponent)event.getDetachedComponent()); |
| } |
| } |
| |
| private void recursiveAddComponentAttachDetachListener(ComponentAttachDetachNotifier container) { |
| AbstractComponent ccontainer = (AbstractComponent) container; |
| //ccontainer.setImmediate(true); |
| Collection<?> attachListeners = ccontainer.getListeners(ComponentAttachEvent.class); |
| if (!attachListeners.contains(this)) { |
| container.addComponentAttachListener(this); |
| } |
| Collection<?> detachListeners = ccontainer.getListeners(ComponentDetachEvent.class); |
| if (!detachListeners.contains(this)) { |
| container.addComponentAttachListener(this); |
| } |
| if (container instanceof HasComponents) { |
| Iterator<Component> iterator = ((HasComponents)container).iterator(); |
| while (iterator.hasNext()) { |
| Component component = iterator.next(); |
| if (component instanceof ComponentAttachDetachNotifier) { |
| recursiveAddComponentAttachDetachListener((ComponentAttachDetachNotifier)component); |
| } |
| } |
| } |
| } |
| |
| private void recursiveRemoveComponentAttachDetachListener(ComponentAttachDetachNotifier container) { |
| container.removeComponentAttachListener(this); |
| container.removeComponentAttachListener(this); |
| if (container instanceof HasComponents) { |
| Iterator<Component> iterator = ((HasComponents)container).iterator(); |
| while (iterator.hasNext()) { |
| Component component = iterator.next(); |
| if (component instanceof AbstractComponentContainer) { |
| recursiveRemoveComponentAttachDetachListener((AbstractComponentContainer)component); |
| } |
| } |
| } |
| } |
| |
| private Map<Class<?>,Method> fAddFocusListenerMethods = new HashMap<>(); |
| private Map<Class<?>,Method> fRemoveFocusListenerMethods = new HashMap<>(); |
| private Map<Class<?>,Method> fAddBlurListenerMethods = new HashMap<>(); |
| private Map<Class<?>,Method> fRemoveBlurListenerMethods = new HashMap<>(); |
| |
| private static Set<String> fFocusListenerLogList = new HashSet<>(); |
| private static Set<String> fBlurListenerLogList = new HashSet<>(); |
| |
| private void addFocusListener(AbstractClientConnector component) { |
| Method addFocusListenerMethod = fAddFocusListenerMethods.get(component.getClass()); |
| if (addFocusListenerMethod == null) { |
| try { |
| addFocusListenerMethod = component.getClass().getDeclaredMethod("addFocusListener", FocusListener.class); |
| if (addFocusListenerMethod != null) { |
| fAddFocusListenerMethods.put(component.getClass(), addFocusListenerMethod); |
| Method removeFocusListenerMethod = component.getClass().getDeclaredMethod("removeFocusListener", FocusListener.class); |
| if (removeFocusListenerMethod != null) { |
| fRemoveFocusListenerMethods.put(component.getClass(), removeFocusListenerMethod); |
| } |
| } |
| } |
| catch (NoSuchMethodException | SecurityException e) { |
| } |
| } |
| String className = component.getClass().getCanonicalName(); |
| if (fFocusListenerLogList.contains(className)) { |
| className = null; |
| } |
| else { |
| fFocusListenerLogList.add(className); |
| } |
| if (addFocusListenerMethod != null) { |
| try { |
| addFocusListenerMethod.invoke(component, new Object[] {fFocusListener}); |
| } |
| catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { |
| if ((className != null) && LOGGER.isWarnEnabled()) { LOGGER.warn("focuL: "+className+" could not invoke "+e.getLocalizedMessage()); } |
| } |
| } |
| else { |
| if (!(component instanceof AbstractLayout)) { |
| if ((className != null) && LOGGER.isWarnEnabled()) { LOGGER.warn("focuL: "+className+" DOESN'T IMPLEMENT FocusNotifier"); } |
| } |
| } |
| } |
| |
| private void addBlurListener(AbstractClientConnector component) { |
| Method addBlurListenerMethod = fAddBlurListenerMethods.get(component.getClass()); |
| if (addBlurListenerMethod == null) { |
| try { |
| addBlurListenerMethod = component.getClass().getDeclaredMethod("addBlurListener", BlurListener.class); |
| if (addBlurListenerMethod != null) { |
| fAddBlurListenerMethods.put(component.getClass(), addBlurListenerMethod); |
| Method removeBlurListenerMethod = component.getClass().getDeclaredMethod("removeBlurListener", BlurListener.class); |
| if (removeBlurListenerMethod != null) { |
| fRemoveBlurListenerMethods.put(component.getClass(), removeBlurListenerMethod); |
| } |
| } |
| } |
| catch (NoSuchMethodException | SecurityException e) { |
| } |
| } |
| String className = component.getClass().getCanonicalName(); |
| if (fBlurListenerLogList.contains(className)) { |
| className = null; |
| } |
| else { |
| fBlurListenerLogList.add(className); |
| } |
| if (addBlurListenerMethod != null) { |
| try { |
| addBlurListenerMethod.invoke(component, new Object[] {fBlurListener}); |
| } |
| catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { |
| if ((className != null) && LOGGER.isWarnEnabled()) { LOGGER.warn("blurL: "+className+" could not invoke "+e.getLocalizedMessage()); } |
| } |
| } |
| else { |
| if (!(component instanceof AbstractLayout)) { |
| if ((className != null) && LOGGER.isWarnEnabled()) { LOGGER.warn("blurL: "+className+" DOESN'T IMPLEMENT BlurNotifier"); } |
| } |
| } |
| } |
| |
| private void recursiveAddFocusBlurListener(AbstractClientConnector component) { |
| Collection<?> focusListeners = ((AbstractClientConnector)component).getListeners(FocusEvent.class); |
| if (!focusListeners.contains(fFocusListener)) { |
| if (component instanceof FocusNotifier) { |
| ((FocusNotifier) component).addFocusListener(fFocusListener); |
| } |
| else { |
| addFocusListener(component); |
| } |
| if (component instanceof BlurNotifier) { |
| ((BlurNotifier) component).addBlurListener(fBlurListener); |
| } |
| else { |
| addBlurListener(component); |
| } |
| } |
| if (component instanceof AbstractComponentContainer) { |
| Iterator<Component> iterator = ((AbstractComponentContainer)component).iterator(); |
| while (iterator.hasNext()) { |
| Component child = iterator.next(); |
| if (component instanceof AbstractClientConnector) { |
| recursiveAddFocusBlurListener((AbstractClientConnector)child); |
| } |
| } |
| } |
| } |
| |
| private void recursiveRemoveFocusBlurListener(AbstractClientConnector component) { |
| if (component instanceof FocusNotifier) { |
| ((FocusNotifier) component).removeFocusListener(fFocusListener); |
| } |
| else { |
| Method removeFocusListenerMethod = fRemoveFocusListenerMethods.get(component.getClass()); |
| if (removeFocusListenerMethod != null) { |
| try { |
| removeFocusListenerMethod.invoke(component, new Object[] {fFocusListener}); |
| } |
| catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { |
| } |
| } |
| } |
| if (component instanceof BlurNotifier) { |
| ((BlurNotifier) component).removeBlurListener(fBlurListener); |
| } |
| else { |
| Method removeBlurListenerMethod = fRemoveBlurListenerMethods.get(component.getClass()); |
| if (removeBlurListenerMethod != null) { |
| try { |
| removeBlurListenerMethod.invoke(component, new Object[] {fBlurListener}); |
| } |
| catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { |
| } |
| } |
| } |
| if (component instanceof HasComponents) { |
| Iterator<Component> iterator = ((HasComponents)component).iterator(); |
| while (iterator.hasNext()) { |
| Component child = iterator.next(); |
| if (component instanceof AbstractComponent) { |
| recursiveRemoveFocusBlurListener((AbstractComponent)child); |
| } |
| } |
| } |
| } |
| } |