1//////////////////////////////////////////////////////////////////////////////// 2// 3// ADOBE SYSTEMS INCORPORATED 4// Copyright 2009 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 12package spark.effects 13{ 14import flash.utils.Dictionary; 15 16/** 17 * This internal class is a utility used by AnimateTransform to 18 * store, retrieve, and remove shared objects. The class uses a 19 * Dictionary of Dictionaries internally to store the shared 20 * objects and keeps a reference count for the entries to know 21 * when it is okay to remove the top level dictionary entry. 22 * 23 * The reason this is needed by AnimateTransform is that we want 24 * to share transform instances per top-level Parallel effect. 25 * But rather than keep the Dictionary-of-Dictionaries at that level, 26 * we keep it in this utility class. We add the reference count 27 * to the upper-level dictionary to know when we can delete it 28 * (Dictionary lacks any useful isEmpty() capability). 29 * 30 * The top level Dictionary elements are stored in sharedObjectMaps 31 * by the mapKey passed into storeSharedObject(). The items in 32 * sharedObjectMaps are Dictionaries using the target argument passed 33 * into storeSharedObject() to store their entries. 34 */ 35internal class SharedObjectDepot 36{ 37 /** 38 * The upper level Dictionary object. This will store our 39 * lower level Dictionaries that we create on the fly 40 */ 41 private var sharedObjectMaps:Dictionary = new Dictionary(true); 42 43 /** 44 * The refcount per key in sharedObjectMaps. When the refcount 45 * for any map dips to zero, we delete it from sharedObjectMaps. 46 */ 47 private var sharedObjectRefcounts:Dictionary = new Dictionary(true); 48 49 public function SharedObjectDepot() 50 { 51 } 52 53 /** 54 * Returns a shared object if it exists. The top level map is 55 * searched to see if there is an entry (another map) for the key 56 * 'mapKey'. If that exists, that map is searched to see if there 57 * is an entry with the key 'target'. mapKey must be non-null. 58 * 59 * @return Object the shared object, if it exists, or null otherwise. 60 */ 61 public function getSharedObject(mapKey:Object, target:Object):Object 62 { 63 if (mapKey != null) 64 { 65 var sharedObjectMap:Dictionary = 66 Dictionary(sharedObjectMaps[mapKey]); 67 if (sharedObjectMap != null) 68 return sharedObjectMap[target]; 69 } 70 return null; 71 } 72 73 /** 74 * Stores a new entry in the shared object map. First, the 75 * top level map is searched to see if there is an existing 76 * map entry (also a map) with the key 'mapKey'. If not, a 77 * new map is created and stored with this key in the top level 78 * map. Then the lower level map is queried to see if there 79 * is an entry with the key 'target'. If not, the refcount for 80 * mapKey is incremented. Finally, an entry is stored in the lower 81 * level map with the key 'target'. mapKey must be non-null. 82 * 83 */ 84 public function storeSharedObject(mapKey:Object, target:Object, 85 instance:Object):void 86 { 87 if (mapKey != null) 88 { 89 var sharedObjectMap:Dictionary = sharedObjectMaps[mapKey]; 90 if (!sharedObjectMap) 91 { 92 sharedObjectMap = new Dictionary(); 93 sharedObjectMaps[mapKey] = sharedObjectMap; 94 } 95 if (!sharedObjectMap[target]) 96 { 97 if (!sharedObjectRefcounts[mapKey]) 98 sharedObjectRefcounts[mapKey] = 1; 99 else 100 sharedObjectRefcounts[mapKey] += 1; 101 } 102 sharedObjectMap[target] = instance; 103 } 104 } 105 106 /** 107 * Removes the entry accessed with the upper level key of mapKey and 108 * lower level key of target. If the refcount for mapKey reaches zero, 109 * that entry is deleted from the upper level map. mapKey must be 110 * non-null 111 */ 112 public function removeSharedObject(mapKey:Object, target:Object):void 113 { 114 if (mapKey != null) 115 { 116 var sharedObjectMap:Dictionary = sharedObjectMaps[mapKey]; 117 if (!sharedObjectMap) 118 return; 119 if (sharedObjectMap[target]) 120 { 121 delete sharedObjectMap[target]; 122 sharedObjectRefcounts[mapKey] -= 1; 123 if (sharedObjectRefcounts[mapKey] <= 0) 124 { 125 delete sharedObjectMaps[mapKey]; 126 delete sharedObjectRefcounts[mapKey]; 127 } 128 } 129 } 130 } 131} 132}