Guest User

Untitled

a guest
Jul 12th, 2018
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.21 KB | None | 0 0
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // ADOBE SYSTEMS INCORPORATED
  4. // Copyright 2005-2007 Adobe Systems Incorporated
  5. // All Rights Reserved.
  6. //
  7. // NOTICE: Adobe permits you to use, modify, and distribute this file
  8. // in accordance with the terms of the license agreement accompanying it.
  9. //
  10. ////////////////////////////////////////////////////////////////////////////////
  11.  
  12. package mx.collections
  13. {
  14.  
  15. import flash.events.EventDispatcher;
  16. import flash.events.IEventDispatcher;
  17. import flash.utils.IDataInput;
  18. import flash.utils.IDataOutput;
  19. import flash.utils.IExternalizable;
  20. import flash.utils.getQualifiedClassName;
  21. import mx.core.IPropertyChangeNotifier;
  22. import mx.core.mx_internal;
  23. import mx.events.CollectionEvent;
  24. import mx.events.CollectionEventKind;
  25. import mx.events.PropertyChangeEvent;
  26. import mx.events.PropertyChangeEventKind;
  27. import mx.managers.ISystemManager;
  28. import mx.managers.SystemManager;
  29. import mx.resources.IResourceManager;
  30. import mx.resources.ResourceManager;
  31. import mx.utils.ArrayUtil;
  32. import mx.utils.UIDUtil;
  33.  
  34. //--------------------------------------
  35. // Events
  36. //--------------------------------------
  37.  
  38. /**
  39. * Dispatched when the IList has been updated in some way.
  40. *
  41. * @eventType mx.events.CollectionEvent.COLLECTION_CHANGE
  42. */
  43. [Event(name="collectionChange", type="mx.events.CollectionEvent")]
  44.  
  45. //--------------------------------------
  46. // Other metadata
  47. //--------------------------------------
  48.  
  49. [ExcludeClass]
  50.  
  51. [RemoteClass(alias="flex.messaging.io.ArrayList")]
  52.  
  53. [ResourceBundle("collections")]
  54.  
  55. /**
  56. * @private
  57. * A simple implementation of IList that uses a backing Array.
  58. * This base class will not throw ItemPendingErrors but it
  59. * is possible that a subclass might.
  60. */
  61. public class ArrayList extends EventDispatcher
  62. implements IList, IExternalizable, IPropertyChangeNotifier
  63. {
  64. include "../core/Version.as";
  65.  
  66. //--------------------------------------------------------------------------
  67. //
  68. // Constructor
  69. //
  70. //--------------------------------------------------------------------------
  71.  
  72. /**
  73. * Construct a new ArrayList using the specified array as its source.
  74. * If no source is specified an empty array will be used.
  75. */
  76. public function ArrayList(source:Array = null)
  77. {
  78. super();
  79.  
  80. disableEvents();
  81. this.source = source;
  82. enableEvents();
  83. _uid = UIDUtil.createUID();
  84. }
  85.  
  86. //--------------------------------------------------------------------------
  87. //
  88. // Variables
  89. //
  90. //--------------------------------------------------------------------------
  91.  
  92. /**
  93. * @private
  94. * Used for accessing localized Error messages.
  95. */
  96. private var resourceManager:IResourceManager =
  97. ResourceManager.getInstance();
  98.  
  99. //--------------------------------------------------------------------------
  100. //
  101. // Properties
  102. //
  103. //--------------------------------------------------------------------------
  104.  
  105. //----------------------------------
  106. // length
  107. //----------------------------------
  108.  
  109. /**
  110. * Get the number of items in the list. An ArrayList should always
  111. * know its length so it shouldn't return -1, though a subclass may
  112. * override that behavior.
  113. *
  114. * @return int representing the length of the source.
  115. */
  116. public function get length():int
  117. {
  118. if (source)
  119. return source.length;
  120. else
  121. return 0;
  122. }
  123.  
  124. //----------------------------------
  125. // source
  126. //----------------------------------
  127.  
  128. /**
  129. * The source array for this ArrayList.
  130. * Any changes done through the IList interface will be reflected in the
  131. * source array.
  132. * If no source array was supplied the ArrayList will create one internally.
  133. * Changes made directly to the underlying Array (e.g., calling
  134. * <code>theList.source.pop()</code> will not cause <code>CollectionEvents</code>
  135. * to be dispatched.
  136. *
  137. * @return An Array that represents the underlying source.
  138. */
  139. public function get source():Array
  140. {
  141. return _source;
  142. }
  143.  
  144. public function set source(s:Array):void
  145. {
  146. var i:int;
  147. var len:int;
  148. if (_source && _source.length)
  149. {
  150. len = _source.length;
  151. for (i = 0; i < len; i++)
  152. {
  153. stopTrackUpdates(_source[i]);
  154. }
  155. }
  156. _source = s ? s : [];
  157. len = _source.length;
  158. for (i = 0; i < len; i++)
  159. {
  160. startTrackUpdates(_source[i]);
  161. }
  162.  
  163. if (_dispatchEvents == 0)
  164. {
  165. var event:CollectionEvent =
  166. new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
  167. event.kind = CollectionEventKind.RESET;
  168. dispatchEvent(event);
  169. }
  170. }
  171.  
  172. //----------------------------------
  173. // uid -- mx.core.IPropertyChangeNotifier
  174. //----------------------------------
  175.  
  176. /**
  177. * Provides access to the unique id for this list.
  178. *
  179. * @return String representing the internal uid.
  180. */
  181. public function get uid():String
  182. {
  183. return _uid;
  184. }
  185.  
  186. public function set uid(value:String):void
  187. {
  188. _uid = value;
  189. }
  190.  
  191. //--------------------------------------------------------------------------
  192. //
  193. // Methods
  194. //
  195. //--------------------------------------------------------------------------
  196.  
  197. /**
  198. * Get the item at the specified index.
  199. *
  200. * @param index the index in the list from which to retrieve the item
  201. * @param prefetch int indicating both the direction and amount of items
  202. * to fetch during the request should the item not be local.
  203. * @return the item at that index, null if there is none
  204. * @throws ItemPendingError if the data for that index needs to be
  205. * loaded from a remote location
  206. * @throws RangeError if the index < 0 or index >= length
  207. */
  208. public function getItemAt(index:int, prefetch:int = 0):Object
  209. {
  210. if (index < 0 || index >= length)
  211. {
  212. var message:String = resourceManager.getString(
  213. "collections", "outOfBounds", [ index ]);
  214. throw new RangeError(message);
  215. }
  216.  
  217. return source[index];
  218. }
  219.  
  220. /**
  221. * Place the item at the specified index.
  222. * If an item was already at that index the new item will replace it and it
  223. * will be returned.
  224. *
  225. * @param item the new value for the index
  226. * @param index the index at which to place the item
  227. * @return the item that was replaced, null if none
  228. * @throws RangeError if index is less than 0 or greater than or equal to length
  229. */
  230. public function setItemAt(item:Object, index:int):Object
  231. {
  232. if (index < 0 || index >= length)
  233. {
  234. var message:String = resourceManager.getString(
  235. "collections", "outOfBounds", [ index ]);
  236. throw new RangeError(message);
  237. }
  238.  
  239. var oldItem:Object = source[index];
  240. source[index] = item;
  241. stopTrackUpdates(oldItem);
  242. startTrackUpdates(item);
  243.  
  244. //dispatch the appropriate events
  245. if (_dispatchEvents == 0)
  246. {
  247. var hasCollectionListener:Boolean =
  248. hasEventListener(CollectionEvent.COLLECTION_CHANGE);
  249. var hasPropertyListener:Boolean =
  250. hasEventListener(PropertyChangeEvent.PROPERTY_CHANGE);
  251. var updateInfo:PropertyChangeEvent;
  252.  
  253. if (hasCollectionListener || hasPropertyListener)
  254. {
  255. updateInfo = new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGE);
  256. updateInfo.kind = PropertyChangeEventKind.UPDATE;
  257. updateInfo.oldValue = oldItem;
  258. updateInfo.newValue = item;
  259. updateInfo.property = index;
  260. }
  261.  
  262. if (hasCollectionListener)
  263. {
  264. var event:CollectionEvent =
  265. new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
  266. event.kind = CollectionEventKind.REPLACE;
  267. event.location = index;
  268. event.items.push(updateInfo);
  269. dispatchEvent(event);
  270. }
  271.  
  272. if (hasPropertyListener)
  273. {
  274. dispatchEvent(updateInfo);
  275. }
  276. }
  277. return oldItem;
  278. }
  279.  
  280. /**
  281. * Add the specified item to the end of the list.
  282. * Equivalent to addItemAt(item, length);
  283. *
  284. * @param item the item to add
  285. */
  286. public function addItem(item:Object):void
  287. {
  288. addItemAt(item, length);
  289. }
  290.  
  291. /**
  292. * Add the item at the specified index.
  293. * Any item that was after this index is moved out by one.
  294. *
  295. * @param item the item to place at the index
  296. * @param index the index at which to place the item
  297. * @throws RangeError if index is less than 0 or greater than the length
  298. */
  299. public function addItemAt(item:Object, index:int):void
  300. {
  301. if (index < 0 || index > length)
  302. {
  303. var message:String = resourceManager.getString(
  304. "collections", "outOfBounds", [ index ]);
  305. throw new RangeError(message);
  306. }
  307.  
  308. source.splice(index, 0, item);
  309.  
  310. startTrackUpdates(item);
  311. internalDispatchEvent(CollectionEventKind.ADD, item, index);
  312. }
  313.  
  314. /**
  315. * Return the index of the item if it is in the list such that
  316. * getItemAt(index) == item.
  317. * Note that in this implementation the search is linear and is therefore
  318. * O(n).
  319. *
  320. * @param item the item to find
  321. * @return the index of the item, -1 if the item is not in the list.
  322. */
  323. public function getItemIndex(item:Object):int
  324. {
  325. return ArrayUtil.getItemIndex(item, source);
  326. }
  327.  
  328. /**
  329. * Removes the specified item from this list, should it exist.
  330. *
  331. * @param item Object reference to the item that should be removed.
  332. * @return Boolean indicating if the item was removed.
  333. */
  334. public function removeItem(item:Object):Boolean
  335. {
  336. var index:int = getItemIndex(item);
  337. var result:Boolean = index >= 0;
  338. if (result)
  339. removeItemAt(index);
  340.  
  341. return result;
  342. }
  343.  
  344. /**
  345. * Remove the item at the specified index and return it.
  346. * Any items that were after this index are now one index earlier.
  347. *
  348. * @param index the index from which to remove the item
  349. * @return the item that was removed
  350. * @throws RangeError is index < 0 or index >= length
  351. */
  352. public function removeItemAt(index:int):Object
  353. {
  354. if (index < 0 || index >= length)
  355. {
  356. var message:String = resourceManager.getString(
  357. "collections", "outOfBounds", [ index ]);
  358. throw new RangeError(message);
  359. }
  360.  
  361. var removed:Object = source.splice(index, 1)[0];
  362. stopTrackUpdates(removed);
  363. internalDispatchEvent(CollectionEventKind.REMOVE, removed, index);
  364. return removed;
  365. }
  366.  
  367. /**
  368. * Remove all items from the list.
  369. */
  370. public function removeAll():void
  371. {
  372. if (length > 0)
  373. {
  374. var len:int = length;
  375. for (var i:int = 0; i < len; i++)
  376. {
  377. stopTrackUpdates(source[i]);
  378. }
  379.  
  380. source.splice(0, length);
  381. internalDispatchEvent(CollectionEventKind.RESET);
  382. }
  383. }
  384.  
  385. /**
  386. * Notify the view that an item has been updated.
  387. * This is useful if the contents of the view do not implement
  388. * <code>IEventDispatcher</code>.
  389. * If a property is specified the view may be able to optimize its
  390. * notification mechanism.
  391. * Otherwise it may choose to simply refresh the whole view.
  392. *
  393. * @param item The item within the view that was updated.
  394. *
  395. * @param property A String, QName, or int
  396. * specifying the property that was updated.
  397. *
  398. * @param oldValue The old value of that property.
  399. * (If property was null, this can be the old value of the item.)
  400. *
  401. * @param newValue The new value of that property.
  402. * (If property was null, there's no need to specify this
  403. * as the item is assumed to be the new value.)
  404. *
  405. * @see mx.events.CollectionEvent
  406. * @see mx.core.IPropertyChangeNotifier
  407. * @see mx.events.PropertyChangeEvent
  408. */
  409. public function itemUpdated(item:Object, property:Object = null,
  410. oldValue:Object = null,
  411. newValue:Object = null):void
  412. {
  413. var event:PropertyChangeEvent =
  414. new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGE);
  415.  
  416. event.kind = PropertyChangeEventKind.UPDATE;
  417. event.source = item;
  418. event.property = property;
  419. event.oldValue = oldValue;
  420. event.newValue = newValue;
  421.  
  422. itemUpdateHandler(event);
  423. }
  424.  
  425. /**
  426. * Return an Array that is populated in the same order as the IList
  427. * implementation.
  428. *
  429. * @throws ItemPendingError if the data is not yet completely loaded
  430. * from a remote location
  431. */
  432. public function toArray():Array
  433. {
  434. return source.concat();
  435. }
  436.  
  437. /**
  438. * Ensures that only the source property is seralized.
  439. * @private
  440. */
  441. public function readExternal(input:IDataInput):void
  442. {
  443. source = input.readObject();
  444. }
  445.  
  446. /**
  447. * Ensures that only the source property is serialized.
  448. * @private
  449. */
  450. public function writeExternal(output:IDataOutput):void
  451. {
  452. output.writeObject(_source);
  453. }
  454.  
  455. /**
  456. * Pretty prints the contents of this ArrayList to a string and returns it.
  457. */
  458. override public function toString():String
  459. {
  460. if (source)
  461. return source.toString();
  462. else
  463. return getQualifiedClassName(this);
  464. }
  465.  
  466. //--------------------------------------------------------------------------
  467. //
  468. // Internal Methods
  469. //
  470. //--------------------------------------------------------------------------
  471.  
  472. /**
  473. * Enables event dispatch for this list.
  474. */
  475. private function enableEvents():void
  476. {
  477. _dispatchEvents++;
  478. if (_dispatchEvents > 0)
  479. _dispatchEvents = 0;
  480. }
  481.  
  482. /**
  483. * Disables event dispatch for this list.
  484. * To re-enable events call enableEvents(), enableEvents() must be called
  485. * a matching number of times as disableEvents().
  486. */
  487. private function disableEvents():void
  488. {
  489. _dispatchEvents--;
  490. }
  491.  
  492. /**
  493. * Dispatches a collection event with the specified information.
  494. *
  495. * @param kind String indicates what the kind property of the event should be
  496. * @param item Object reference to the item that was added or removed
  497. * @param location int indicating where in the source the item was added.
  498. */
  499. private function internalDispatchEvent(kind:String, item:Object = null, location:int = -1):void
  500. {
  501. if (_dispatchEvents == 0)
  502. {
  503. if (hasEventListener(CollectionEvent.COLLECTION_CHANGE))
  504. {
  505. var event:CollectionEvent =
  506. new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
  507. event.kind = kind;
  508. event.items.push(item);
  509. event.location = location;
  510. dispatchEvent(event);
  511. }
  512.  
  513. // now dispatch a complementary PropertyChangeEvent
  514. if (hasEventListener(PropertyChangeEvent.PROPERTY_CHANGE) &&
  515. (kind == CollectionEventKind.ADD || kind == CollectionEventKind.REMOVE))
  516. {
  517. var objEvent:PropertyChangeEvent =
  518. new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGE);
  519. objEvent.property = location;
  520. if (kind == CollectionEventKind.ADD)
  521. objEvent.newValue = item;
  522. else
  523. objEvent.oldValue = item;
  524. dispatchEvent(objEvent);
  525. }
  526. }
  527. }
  528.  
  529. /**
  530. * Called whenever any of the contained items in the list fire an
  531. * ObjectChange event.
  532. * Wraps it in a CollectionEventKind.UPDATE.
  533. */
  534. protected function itemUpdateHandler(event:PropertyChangeEvent):void
  535. {
  536. internalDispatchEvent(CollectionEventKind.UPDATE, event);
  537. // need to dispatch object event now
  538. if (_dispatchEvents == 0 && hasEventListener(PropertyChangeEvent.PROPERTY_CHANGE))
  539. {
  540. var objEvent:PropertyChangeEvent = PropertyChangeEvent(event.clone());
  541. var index:uint = getItemIndex(event.target);
  542. objEvent.property = index.toString() + "." + event.property;
  543. dispatchEvent(objEvent);
  544. }
  545. }
  546.  
  547. /**
  548. * If the item is an IEventDispatcher watch it for updates.
  549. * This is called by addItemAt and when the source is initially
  550. * assigned.
  551. */
  552. protected function startTrackUpdates(item:Object):void
  553. {
  554. if (item && (item is IEventDispatcher))
  555. {
  556. IEventDispatcher(item).addEventListener(
  557. PropertyChangeEvent.PROPERTY_CHANGE,
  558. itemUpdateHandler, false, 0, true);
  559. }
  560. }
  561.  
  562. /**
  563. * If the item is an IEventDispatcher stop watching it for updates.
  564. * This is called by removeItemAt, removeAll, and before a new
  565. * source is assigned.
  566. */
  567. protected function stopTrackUpdates(item:Object):void
  568. {
  569. if (item && item is IEventDispatcher)
  570. {
  571. IEventDispatcher(item).removeEventListener(
  572. PropertyChangeEvent.PROPERTY_CHANGE,
  573. itemUpdateHandler);
  574. }
  575. }
  576.  
  577. //--------------------------------------------------------------------------
  578. //
  579. // Variables
  580. //
  581. //--------------------------------------------------------------------------
  582.  
  583. /**
  584. * indicates if events should be dispatched.
  585. * calls to enableEvents() and disableEvents() effect the value when == 0
  586. * events should be dispatched.
  587. */
  588. private var _dispatchEvents:int = 0;
  589. private var _source:Array;
  590. private var _uid:String;
  591. }
  592.  
  593. }
Add Comment
Please, Sign In to add comment