 		}
 		override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
 		{
-			super.updateDisplayList.apply(this,arguments);
-			
+			super.updateDisplayList(unscaledWidth, unscaledHeight);
+			
+			var keysChanged:Boolean = detectLinkableObjectChange(updateDisplayList, filteredKeySet);
 			var varsChanged:Boolean = detectLinkableObjectChange(updateDisplayList, vars);
 			var scriptChanged:Boolean = detectLinkableObjectChange(updateDisplayList, drawScript)
 				
-			// do nothing if nothing changed (script, vars, size)
-			if (!scriptChanged && !varsChanged && _prevSize.x == unscaledWidth && _prevSize.y == unscaledHeight)
+			// do nothing if nothing changed (keys, script, vars, size)
+			if (!keysChanged && !scriptChanged && !varsChanged && _prevSize.x == unscaledWidth && _prevSize.y == unscaledHeight)
 				return;
 			
 			// wait until vars are not busy
-			if (linkableObjectIsBusy(vars))
+			if (linkableObjectIsBusy(vars) || linkableObjectIsBusy(filteredKeySet))
 				return;
 			
 			// remember current size for next time

	
	import mx.containers.Canvas;
	
	import weave.api.WeaveAPI;
	import weave.api.core.ILinkableHashMap;
	import weave.api.data.IAttributeColumn;
	import weave.api.data.IKeySet;
	import weave.api.detectLinkableObjectChange;
	import weave.api.getCallbackCollection;
	import weave.api.linkableObjectIsBusy;

		public function get bitmapData():BitmapData { return bitmap.bitmapData; }
		public const textGraphics:TextGraphics = new TextGraphics();
		public const canvas:Canvas = new Canvas();
		public var locals:Object; // for use inside scripts
		private const filteredKeySet:FilteredKeySet = newLinkableChild(this, FilteredKeySet);
		
		public function get keys():Array
		{
			return filteredKeySet.keys;
		}
		
		public function getSelectableAttributes():Array
		{
