/flowplayer/branches/3_1_3_dev/src/actionscript/org/flowplayer/model/EventDispatcher.as

http://flowplayer-core.googlecode.com/ · ActionScript · 215 lines · 157 code · 18 blank · 40 comment · 38 complexity · b9cf69bf176f8f0beedc2c9c8e3a4f93 MD5 · raw file

  1. /*
  2. * Copyright 2008 Anssi Piirainen
  3. *
  4. * This file is part of Flowplayer.
  5. *
  6. * Flowplayer is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Flowplayer is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Flowplayer. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. package org.flowplayer.model {
  20. import flash.utils.Dictionary;
  21. import org.flowplayer.flow_internal;
  22. import org.flowplayer.util.Log;
  23. use namespace flow_internal;
  24. /**
  25. * @author api
  26. */
  27. public class EventDispatcher {
  28. protected var log:Log = new Log(this);
  29. private var _beforeListeners:Dictionary = new Dictionary();
  30. private var _listeners:Dictionary = new Dictionary();
  31. protected static var _playerId:String;
  32. /**
  33. * Unbinds the specified listener.
  34. *
  35. * @param listener the listener to unbind
  36. * @param event the type of the event from which the listener is removed, if <code>null</code> it's removed from all event types
  37. * @param beforePhase if <code>true</code> the listener is removed from the before phase, otherwise it's removed from the normal event phase
  38. */
  39. public final function unbind(listener:Function, event:EventType = null, beforePhase:Boolean = false):void {
  40. if (event) {
  41. removeListener(event, listener, beforePhase);
  42. } else {
  43. removeAllEventsListener(listener, beforePhase);
  44. }
  45. }
  46. flow_internal function setListener(event:EventType, listener:Function, clipFilter:Function = null, beforePhase:Boolean = false, addToFront:Boolean = false):void {
  47. if (event) {
  48. addListener(event, new EventListener(listener, clipFilter), beforePhase, addToFront);
  49. } else {
  50. log.debug("adding listeners, beforePhase " + beforePhase);
  51. addAllEventsListener(beforePhase ? cancellableEvents : allEvents, new EventListener(listener, clipFilter), beforePhase, addToFront);
  52. }
  53. }
  54. protected function get cancellableEvents():Dictionary {
  55. throw new Error("cancellableEvents should be overridden the subclass");
  56. return null;
  57. }
  58. protected function get allEvents():Dictionary {
  59. throw new Error("allEvents should be overridden the subclass");
  60. return null;
  61. }
  62. private function removeAllEventsListener(listener:Function, beforePhase:Boolean):void {
  63. for each (var type:Object in (beforePhase ? cancellableEvents : allEvents)) {
  64. removeListener(type as ClipEventType, listener, beforePhase);
  65. }
  66. }
  67. private function addAllEventsListener(events:Dictionary, listener:EventListener, beforePhase:Boolean, addToFront:Boolean = false):void {
  68. log.debug("addAllEventsListener, beforePhase " + beforePhase);
  69. for each (var type:Object in events) {
  70. addListener(type as ClipEventType, listener, beforePhase, addToFront);
  71. }
  72. }
  73. private function dispatchExternalEvent(event:AbstractEvent, beforePhase:Boolean = false):void {
  74. if (! _playerId) return;
  75. var externalReturnVal:Boolean = event.fireExternal(_playerId, beforePhase);
  76. if (! externalReturnVal) {
  77. log.debug("preventing default");
  78. event.preventDefault();
  79. }
  80. }
  81. /**
  82. * Dispatches an event to the before phase listeners.
  83. * @param event the event to dispatch
  84. * @param fireExternal dispatch also to external plugins
  85. * @return false if event propagation was stopped
  86. */
  87. flow_internal final function doDispatchBeforeEvent(event:AbstractEvent, fireExternal:Boolean):Boolean {
  88. log.debug("doDispatchBeforeEvent, fireExternal " + fireExternal);
  89. if (! event.isCancellable()) {
  90. log.debug("event is not cancellable, will not fire event, propagation is allowed");
  91. return true;
  92. }
  93. if (event.target == null) {
  94. event.target = this;
  95. }
  96. if (fireExternal) {
  97. dispatchExternalEvent(event, true);
  98. }
  99. _dispatchEvent(event, _beforeListeners);
  100. return ! event.isDefaultPrevented();
  101. }
  102. /**
  103. * Dispatches the event to the action phase listeners.
  104. */
  105. flow_internal final function doDispatchEvent(event:AbstractEvent, fireExternal:Boolean):void {
  106. if (event.info is ErrorCode) {
  107. doDispatchErrorEvent(event, fireExternal);
  108. return;
  109. }
  110. if (event.target == null) {
  111. event.target = this;
  112. }
  113. if (fireExternal) {
  114. dispatchExternalEvent(event);
  115. }
  116. _dispatchEvent(event, _listeners);
  117. }
  118. /**
  119. * Dispatches an error event to the action phase listeners.
  120. */
  121. flow_internal final function doDispatchErrorEvent(event:AbstractEvent, fireExternal:Boolean):void {
  122. if (event.target == null) {
  123. event.target = this;
  124. }
  125. if (fireExternal) {
  126. event.fireErrorExternal(_playerId);
  127. }
  128. _dispatchEvent(event, _listeners);
  129. }
  130. private function _dispatchEvent(event:AbstractEvent, listenerDict:Dictionary):void {
  131. log.info(this + " dispatchEvent(), event " + event);
  132. var listeners:Array = listenerDict[event.eventType];
  133. var notified:Array = [];
  134. if (! listeners) {
  135. log.debug(this + ": dispatchEvent(): no listeners for event " + event.eventType + (listenerDict == _beforeListeners ? " in before phase" : ""));
  136. return;
  137. }
  138. for (var i : Number = 0; i < listeners.length; i++) {
  139. var listener:EventListener = listeners[i];
  140. if (notified.indexOf(listener) < 0) {
  141. if (listener == null) {
  142. log.error("found null listener");
  143. }
  144. listener.notify(event);
  145. notified.push(listener);
  146. if (event.isPropagationStopped()) {
  147. return;
  148. }
  149. }
  150. }
  151. return;
  152. }
  153. private function addListener(event:EventType, listener:EventListener, beforePhase:Boolean, addToFront:Boolean = false):void {
  154. log.debug(this + ": adding listener for event " + event + (beforePhase ? " to before phase" : ""));
  155. var listenerDict:Dictionary = beforePhase ? _beforeListeners : _listeners;
  156. var listeners:Array = listenerDict[event];
  157. if (! listeners) {
  158. listeners = new Array();
  159. listenerDict[event] = listeners;
  160. }
  161. if (! hasListener(event, listener)) {
  162. if (addToFront) {
  163. listeners.splice(0, 0, listener);
  164. } else {
  165. listeners.push(listener);
  166. }
  167. }
  168. }
  169. internal function removeListener(event:EventType, listener:Function, beforePhase:Boolean = false):void {
  170. doRemoveListener(beforePhase ? _beforeListeners : _listeners, event, listener);
  171. }
  172. private function doRemoveListener(listenerDict:Dictionary, event:EventType, listener:Function):void {
  173. var listeners:Array = listenerDict[event];
  174. if (! listeners) return;
  175. for (var i : Number = 0; i < listeners.length; i++) {
  176. var eventListener:EventListener = listeners[i];
  177. if (eventListener.listener == listener) {
  178. listeners.splice(i, 1);
  179. }
  180. }
  181. }
  182. private function hasListener(event:EventType, listener:EventListener):Boolean {
  183. var listeners:Array = _listeners[event];
  184. if (! listeners) return false;
  185. for (var i : Number = 0; i < listeners.length; i++) {
  186. var eventListener:EventListener = listeners[i];
  187. if (eventListener.listener == listener.listener) {
  188. return true;
  189. }
  190. }
  191. return false;
  192. }
  193. public static function set playerId(playerId:String):void {
  194. _playerId = playerId;
  195. }
  196. }
  197. }