/*********************************************************************** * mt4j Copyright (c) 2008 - 2009 Christopher Ruff, Fraunhofer-Gesellschaft All rights reserved. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * ***********************************************************************/ package org.mt4j.input; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.mt4j.input.inputProcessors.IGestureEventListener; import org.mt4j.input.inputProcessors.IInputProcessor; import org.mt4j.input.inputProcessors.MTGestureEvent; public class GestureEventSupport { // private List<IGestureEventListener> gestureListeners; /** The gestureEvtSenders to listener. */ private Map<Class<? extends IInputProcessor>, IGestureEventListener[]> gestureSenderToGestureListener; /** The Constant EMPTY. */ private static final IGestureEventListener[] EMPTY = {}; public GestureEventSupport() { super(); // this.gestureListeners = new ArrayList<IGestureEventListener>(); } // /** // * Constructs a <code>PropertyChangeSupport</code> object. // * // * @param sourceBean The bean to be given as the source for any events. // */ // public GestureEventSupport(Object sourceBean) { // if (sourceBean == null) { // throw new NullPointerException(); // } // source = sourceBean; // } /** * Add a gestureEvtSenderChangeListener to the listener map. * If <code>listener</code> is null, no exception is thrown and no action * is taken. * * @param gestureEvtSender the gestureEvtSender * @param listener The gestureEvtSenderChangeListener to be added */ public synchronized void addGestureEvtListener(Class<? extends IInputProcessor> gestureEvtSender, IGestureEventListener listener) { if (listener == null) { return; } this.lazyInitializeMap(); IGestureEventListener[] array = this.gestureSenderToGestureListener.get(gestureEvtSender); //Add listener to array int size = (array != null) ? array.length : 0; IGestureEventListener[] clone = newArray(size + 1); clone[size] = listener; if (array != null) { System.arraycopy(array, 0, clone, 0, size); } //Put new listener array into map this.gestureSenderToGestureListener.put(gestureEvtSender, clone); } /** * Creates a new array of listeners of the specified size. * * @param length the length * * @return the gestureEvtSender change listener[] */ protected IGestureEventListener[] newArray(int length) { return (0 < length) ? new IGestureEventListener[length] : EMPTY; } /** * Removes a IGestureEventListener to the listener map. * Throws no error if the listener isnt found. * * @param gestureEvtSender the gestureEvtSender * @param listener the listener */ public synchronized void removeGestureEventListener(Class<? extends IInputProcessor> gestureEvtSender, IGestureEventListener listener) { if (listener == null || gestureEvtSender == null) { return; } this.lazyInitializeMap(); if (this.gestureSenderToGestureListener != null) { IGestureEventListener[] array = this.gestureSenderToGestureListener.get(gestureEvtSender); if (array != null) { for (int i = 0; i < array.length; i++) { if (listener.equals(array[i])) { int size = array.length - 1; if (size > 0) { IGestureEventListener[] clone = newArray(size); System.arraycopy(array, 0, clone, 0, i); System.arraycopy(array, i + 1, clone, i, size - i); this.gestureSenderToGestureListener.put(gestureEvtSender, clone); } else { this.gestureSenderToGestureListener.remove(gestureEvtSender); if (this.gestureSenderToGestureListener.isEmpty()) { this.gestureSenderToGestureListener = null; } } break; } } } } } /** * Clear listeners. */ public synchronized void clearListeners(){ if (this.gestureSenderToGestureListener == null){ return; } this.lazyInitializeMap(); this.gestureSenderToGestureListener.clear(); } /** * Fire an existing GestureEvent to any registered listeners. * * @param evt The GestureEvent object. */ public void fireGestureEvt(MTGestureEvent evt) { if (this.gestureSenderToGestureListener != null && !this.gestureSenderToGestureListener.isEmpty() ){ // Class<? extends GestureEventFireMarker> gestureEvtSenderName = evt.getgestureEvtSender(); Class<? extends IInputProcessor> marker = evt.getSource().getClass(); IGestureEventListener[] common = this.gestureSenderToGestureListener.get(null); IGestureEventListener[] named = (marker != null) ? this.gestureSenderToGestureListener.get(marker) : null; this.fire(common, evt); this.fire(named, evt); } } /** * Fires the events to the listeners. * * @param listeners the listeners * @param event the event */ private void fire(IGestureEventListener[] listeners, MTGestureEvent event) { if (listeners != null) { for (IGestureEventListener listener : listeners) { listener.processGestureEvent(event); } } } /** * Returns all listeners in the map. * * @return an array of all listeners */ public final synchronized IGestureEventListener[] getListeners() { if (this.gestureSenderToGestureListener == null) { return newArray(0); } List<IGestureEventListener> list = new ArrayList<IGestureEventListener>(); IGestureEventListener[] listeners = this.gestureSenderToGestureListener.get(null); if (listeners != null) { for (IGestureEventListener listener : listeners) { list.add(listener); } } for (Entry<Class<? extends IInputProcessor>, IGestureEventListener[]> entry : this.gestureSenderToGestureListener.entrySet()) { Class<? extends IInputProcessor> gestureEvtSender = entry.getKey(); if (gestureEvtSender != null) { for (IGestureEventListener listener : entry.getValue()) { list.add(listener); } } } return list.toArray(newArray(list.size())); } /** * Returns listeners that have been associated with the named gestureEvtSender. * * @param gestureEvtSender the name of the property * * @return an array of listeners for the named property */ public final IGestureEventListener[] getListeners(Class<? extends IInputProcessor> gestureEvtSender) { if (gestureEvtSender != null) { IGestureEventListener[] listeners = this.gestureSenderToGestureListener.get(gestureEvtSender); if (listeners != null) { return listeners.clone(); } } return newArray(0); } /** * Indicates whether the map contains * at least one listener to be notified. * * @param gestureEvtSender the gestureEvtSender * * @return {@code true} if at least one listener exists or * {@code false} otherwise */ public final synchronized boolean hasListeners(Class<? extends IInputProcessor> gestureEvtSender) { if (this.gestureSenderToGestureListener == null) { return false; } IGestureEventListener[] array = this.gestureSenderToGestureListener.get(null); return (array != null) || ((gestureEvtSender != null) && (null != this.gestureSenderToGestureListener.get(gestureEvtSender))); } /** * Checks if the map is null and then lazily initializes it. */ private void lazyInitializeMap(){ if (gestureSenderToGestureListener == null){ gestureSenderToGestureListener = new HashMap<Class<? extends IInputProcessor>, IGestureEventListener[]>(); } } }