All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scaffold.libs_as.org.osflash.signals.natives.NativeRelaySignal.as Maven / Gradle / Ivy

package org.osflash.signals.natives
{
	import org.osflash.signals.ISlot;
	import org.osflash.signals.Signal;
	import org.osflash.signals.Slot;
	import org.osflash.signals.SlotList;

	import flash.events.Event;
	import flash.events.IEventDispatcher;

	/**
	 * The NativeRelaySignal class is used to relay events from an IEventDispatcher
	 * to listeners.
	 * The difference as compared to NativeSignal is that
	 * NativeRelaySignal has its own dispatching code,
	 * whereas NativeSignal uses the IEventDispatcher to dispatch.
	 */
	public class NativeRelaySignal extends Signal implements INativeDispatcher
	{
		protected var _target : IEventDispatcher;

		/** @inheritDoc */
		public function get target() : IEventDispatcher
		{
			return _target;
		}

		public function set target( value : IEventDispatcher ) : void
		{
			if( value == _target ) return;
			if( _target ) removeAll();
			_target = value;
		}

		protected var _eventType : String;

		/** @inheritDoc */
		public function get eventType() : String
		{
			return _eventType;
		}

		public function set eventType( value : String ) : void
		{
			_eventType = value;
		}

		protected var _eventClass : Class;

		/** @inheritDoc */
		public function get eventClass() : Class
		{
			return _eventClass;
		}

		public function set eventClass( value : Class ) : void
		{
			_eventClass = value || Event;
			_valueClasses = [ _eventClass ];
		}

		override public function set valueClasses( value : Array ) : void
		{
			eventClass = (value && value.length > 0) ? value[ 0 ] : null;
		}

		/**
		 * Creates a new NativeRelaySignal instance to relay events from an IEventDispatcher.
		 * @param    target    An object that implements the flash.events.IEventDispatcher interface.
		 * @param    eventType    The event string name that would normally be passed to IEventDispatcher.addEventListener().
		 * @param    eventClass An optional class reference that enables an event type check in dispatch().
		 * Because the target is an IEventDispatcher,
		 * eventClass needs to be flash.events.Event or a subclass of it.
		 */
		public function NativeRelaySignal( target : IEventDispatcher, eventType : String, eventClass : Class = null )
		{
			super( eventClass || Event );

			this.eventType = eventType;
			this.eventClass = eventClass;
			this.target = target;
		}

		/**
		 * @inheritDoc
		 * @throws flash.errors.IllegalOperationError IllegalOperationError: You cannot addOnce() then add() the same listener without removing the relationship first.
		 * @throws ArgumentError ArgumentError: Given listener is null.
		 * @throws ArgumentError ArgumentError: Target object cannot be null.
		 */
		override public function add( listener : Function ) : ISlot
		{
			return addWithPriority( listener );
		}

		/**
		 * @inheritDoc
		 * @throws flash.errors.IllegalOperationError IllegalOperationError: You cannot addOnce() then add() the same listener without removing the relationship first.
		 * @throws ArgumentError ArgumentError: Given listener is null.
		 * @throws ArgumentError ArgumentError: Target object cannot be null.
		 */
		override public function addOnce( listener : Function ) : ISlot
		{
			return addOnceWithPriority( listener );
		}

		/** @inheritDoc */
		override public function remove( listener : Function ) : ISlot
		{
			const nonEmptyBefore : Boolean = slots.nonEmpty;
			const slot : ISlot = super.remove( listener );
			if( nonEmptyBefore != slots.nonEmpty )
				target.removeEventListener( eventType, onNativeEvent );
			return slot;
		}

		/**
		 * @inheritDoc
		 */
		override public function removeAll() : void
		{
			if( target ) target.removeEventListener( eventType, onNativeEvent );
			super.removeAll();
		}

		/**
		 * @inheritDoc
		 * @throws ArgumentError ArgumentError: Event object expected.
		 * @throws ArgumentError ArgumentError: No more than one Event object expected.
		 * @throws ArgumentError ArgumentError: Target object cannot be null.
		 * @throws ArgumentError ArgumentError: Event object cannot be null.
		 * @throws ArgumentError ArgumentError: Event object [event] is not an instance of [eventClass].
		 * @throws ArgumentError ArgumentError: Event object has incorrect type. Expected [eventType] but was [event.type].
		 */
		override public function dispatch( ...valueObjects ) : void
		{
			if( null == valueObjects ) throw new ArgumentError( 'Event object expected.' );

			if( valueObjects.length != 1 ) throw new ArgumentError( 'No more than one Event object expected.' );

			dispatchEvent( valueObjects[ 0 ] as Event );
		}

		/**
		 * @inheritDoc
		 * @throws flash.errors.IllegalOperationError IllegalOperationError: You cannot addOnce() then add() the same listener without removing the relationship first.
		 * @throws ArgumentError ArgumentError: Given listener is null.
		 * @throws ArgumentError ArgumentError: Target object cannot be null.
		 */
		public function addWithPriority( listener : Function, priority : int = 0 ) : ISlot
		{
			return registerListenerWithPriority( listener, false, priority );
		}

		/**
		 * @inheritDoc
		 * @throws flash.errors.IllegalOperationError IllegalOperationError: You cannot addOnce() then add() the same listener without removing the relationship first.
		 * @throws ArgumentError ArgumentError: Given listener is null.
		 * @throws ArgumentError ArgumentError: Target object cannot be null.
		 */
		public function addOnceWithPriority( listener : Function, priority : int = 0 ) : ISlot
		{
			return registerListenerWithPriority( listener, true, priority );
		}

		protected function registerListenerWithPriority( listener : Function, once : Boolean = false, priority : int = 0 ) : ISlot
		{
			if( !target ) throw new ArgumentError( 'Target object cannot be null.' );
			const nonEmptyBefore : Boolean = slots.nonEmpty;

			var slot : ISlot = null;
			if( registrationPossible( listener, once ) )
			{
				slot = new Slot( listener, this, once, priority );
				slots = slots.insertWithPriority( slot );
			}
			else
				slot = slots.find( listener );

			// Account for cases where the same listener is added twice.
			if( nonEmptyBefore != slots.nonEmpty )
				target.addEventListener( eventType, onNativeEvent, false, priority );

			return slot;
		}

		/**
		 * Unlike other signals, NativeRelaySignal does not dispatch null
		 * because it causes an exception in EventDispatcher.
		 * @inheritDoc
		 * @throws ArgumentError ArgumentError: Target object cannot be null.
		 * @throws ArgumentError ArgumentError: Event object cannot be null.
		 * @throws ArgumentError ArgumentError: Event object [event] is not an instance of [eventClass].
		 * @throws ArgumentError ArgumentError: Event object has incorrect type. Expected [eventType] but was [event.type].
		 */
		public function dispatchEvent( event : Event ) : Boolean
		{
			if( !target ) throw new ArgumentError( 'Target object cannot be null.' );
			if( !event ) throw new ArgumentError( 'Event object cannot be null.' );

			if( !(event is eventClass) )
				throw new ArgumentError( 'Event object ' + event + ' is not an instance of ' + eventClass + '.' );

			if( event.type != eventType )
				throw new ArgumentError( 'Event object has incorrect type. Expected <' + eventType + '> but was <' + event.type + '>.' );

			return target.dispatchEvent( event );
		}

		protected function onNativeEvent( event : Event ) : void
		{
			var slotsToProcess : SlotList = slots;

			while( slotsToProcess.nonEmpty )
			{
				slotsToProcess.head.execute1( event );
				slotsToProcess = slotsToProcess.tail;
			}
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy