| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // Licensed to the Apache Software Foundation (ASF) under one or more |
| // contributor license agreements. See the NOTICE file distributed with |
| // this work for additional information regarding copyright ownership. |
| // The ASF licenses this file to You under the Apache License, Version 2.0 |
| // (the "License"); you may not use this file except in compliance with |
| // the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| package mx.controls.dataGridClasses |
| { |
| |
| import flash.display.DisplayObject; |
| import flash.geom.Point; |
| import flash.geom.Rectangle; |
| import flash.utils.getDefinitionByName; |
| import flash.utils.getQualifiedClassName; |
| import flash.utils.getQualifiedSuperclassName; |
| |
| import mx.controls.DataGrid; |
| import mx.controls.listClasses.BaseListData; |
| import mx.controls.listClasses.IDropInListItemRenderer; |
| import mx.controls.listClasses.IListItemRenderer; |
| import mx.core.IDataRenderer; |
| import mx.core.IFlexDisplayObject; |
| import mx.core.IToolTip; |
| import mx.core.UIComponent; |
| import mx.core.UIComponentGlobals; |
| import mx.core.UITextField; |
| import mx.core.mx_internal; |
| import mx.events.FlexEvent; |
| import mx.events.InterManagerRequest; |
| import mx.events.ToolTipEvent; |
| import mx.managers.ILayoutManagerClient; |
| import mx.managers.ISystemManager; |
| import mx.styles.CSSStyleDeclaration; |
| import mx.styles.IStyleClient; |
| import mx.styles.StyleProtoChain; |
| import mx.utils.PopUpUtil; |
| |
| use namespace mx_internal; |
| |
| /** |
| * Dispatched when the <code>data</code> property changes. |
| * |
| * <p>When you use a component as an item renderer, |
| * the <code>data</code> property contains the data to display. |
| * You can listen for this event and update the component |
| * when the <code>data</code> property changes.</p> |
| * |
| * @eventType mx.events.FlexEvent.DATA_CHANGE |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Event(name="dataChange", type="mx.events.FlexEvent")] |
| |
| /** |
| * The DataGridItemRenderer class defines the default item renderer for a DataGrid control. |
| * By default, the item renderer |
| * draws the text associated with each item in the grid. |
| * |
| * <p>You can override the default item renderer by creating a custom item renderer.</p> |
| * |
| * @see mx.controls.DataGrid |
| * @see mx.core.IDataRenderer |
| * @see mx.controls.listClasses.IDropInListItemRenderer |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public class DataGridItemRenderer extends UITextField |
| implements IDataRenderer, |
| IDropInListItemRenderer, ILayoutManagerClient, |
| IListItemRenderer, IStyleClient |
| { |
| include "../../core/Version.as"; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Constructor |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * Constructor. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function DataGridItemRenderer() |
| { |
| super(); |
| |
| tabEnabled = false; |
| mouseWheelEnabled = false; |
| |
| ignorePadding = false; |
| |
| addEventListener(ToolTipEvent.TOOL_TIP_SHOW, toolTipShowHandler); |
| |
| inheritingStyles = nonInheritingStyles = |
| StyleProtoChain.STYLE_UNINITIALIZED; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Variables |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| private var invalidatePropertiesFlag:Boolean = false; |
| |
| /** |
| * @private |
| */ |
| private var invalidateSizeFlag:Boolean = false; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Overridden properties: UIComponent |
| // |
| //-------------------------------------------------------------------------- |
| |
| //---------------------------------- |
| // nestLevel |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| override public function set nestLevel(value:int):void |
| { |
| super.nestLevel = value; |
| |
| UIComponentGlobals.layoutManager.invalidateProperties(this); |
| invalidatePropertiesFlag = true; |
| |
| UIComponentGlobals.layoutManager.invalidateSize(this); |
| invalidateSizeFlag = true; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Properties |
| // |
| //-------------------------------------------------------------------------- |
| |
| //---------------------------------- |
| // data |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| private var _data:Object; |
| |
| [Bindable("dataChange")] |
| |
| /** |
| * The implementation of the <code>data</code> property as |
| * defined by the IDataRenderer interface. |
| * |
| * The value is ignored. Only the listData property is used. |
| * @see mx.core.IDataRenderer |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get data():Object |
| { |
| return _data; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set data(value:Object):void |
| { |
| _data = value; |
| |
| dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE)); |
| } |
| |
| //---------------------------------- |
| // listData |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| private var _listData:DataGridListData; |
| |
| [Bindable("dataChange")] |
| |
| /** |
| * The implementation of the <code>listData</code> property as |
| * defined by the IDropInListItemRenderer interface. |
| * The text of the renderer is set to the <code>label</code> |
| * property of the listData. |
| * |
| * @see mx.controls.listClasses.IDropInListItemRenderer |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get listData():BaseListData |
| { |
| return _listData; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set listData(value:BaseListData):void |
| { |
| _listData = DataGridListData(value); |
| if (nestLevel && !invalidatePropertiesFlag) |
| { |
| UIComponentGlobals.layoutManager.invalidateProperties(this); |
| invalidatePropertiesFlag = true; |
| UIComponentGlobals.layoutManager.invalidateSize(this); |
| invalidateSizeFlag = true; |
| } |
| } |
| |
| //---------------------------------- |
| // styleDeclaration |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the styleDeclaration property. |
| */ |
| private var _styleDeclaration:CSSStyleDeclaration; |
| |
| /** |
| * Storage for the inline inheriting styles on this object. |
| * This CSSStyleDeclaration is created the first time that setStyle() |
| * is called on this component to set an inheriting style. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get styleDeclaration():CSSStyleDeclaration |
| { |
| return _styleDeclaration; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set styleDeclaration(value:CSSStyleDeclaration):void |
| { |
| _styleDeclaration = value; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Overridden methods: UITextField |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| override public function initialize():void |
| { |
| regenerateStyleCache(false) |
| } |
| |
| /** |
| * @private |
| */ |
| override public function validateNow():void |
| { |
| if (data && parent) |
| { |
| var newColor:Number; |
| |
| if (DataGridBase(_listData.owner).isItemHighlighted(_listData.uid)) |
| { |
| newColor = getStyle("textRollOverColor"); |
| } |
| else if (DataGridBase(_listData.owner).isItemSelected(_listData.uid)) |
| { |
| newColor = getStyle("textSelectedColor"); |
| } |
| else |
| { |
| newColor = getStyle("color"); |
| } |
| |
| if (newColor != explicitColor) |
| { |
| styleChangedFlag = true; |
| explicitColor = newColor; |
| invalidateDisplayList(); |
| } |
| } |
| |
| super.validateNow(); |
| } |
| |
| /** |
| * @copy mx.core.UIComponent#getStyle() |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| override public function getStyle(styleProp:String):* |
| { |
| return (styleManager.inheritingStyles[styleProp]) ? |
| inheritingStyles[styleProp] : nonInheritingStyles[styleProp]; |
| } |
| |
| /** |
| * @copy mx.core.UIComponent#setStyle() |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| override public function setStyle(styleProp:String, newValue:*):void |
| { |
| if (styleProp == "styleName") |
| { |
| // Let the setter handle this one, see UIComponent. |
| styleName = newValue; |
| |
| // Short circuit, because styleName isn't really a style. |
| return; |
| } |
| |
| /* |
| if (styleProp == "themeColor") |
| { |
| // setThemeColor handles the side effects. |
| setThemeColor(newValue); |
| |
| // Do not short circuit, because themeColor is a style. |
| // It just has side effects, too. |
| } |
| */ |
| |
| // If this UIComponent didn't previously have any inline styles, |
| // then regenerate the UIComponent's proto chain (and the proto chains |
| // of this UIComponent's descendants). |
| var isInheritingStyle:Boolean = |
| styleManager.isInheritingStyle(styleProp); |
| var isProtoChainInitialized:Boolean = |
| inheritingStyles != StyleProtoChain.STYLE_UNINITIALIZED; |
| if (isInheritingStyle) |
| { |
| if (getStyle(styleProp) == newValue && isProtoChainInitialized) |
| return; |
| |
| if (!styleDeclaration) |
| { |
| styleDeclaration = new CSSStyleDeclaration(null, styleManager); |
| styleDeclaration.setLocalStyle(styleProp, newValue); |
| |
| // If inheritingStyles is undefined, then this object is being |
| // initialized and we haven't yet generated the proto chain. To |
| // avoid redundant work, don't bother to create the proto chain here. |
| if (isProtoChainInitialized) |
| regenerateStyleCache(true); |
| } |
| else |
| { |
| styleDeclaration.setLocalStyle(styleProp, newValue); |
| } |
| } |
| else |
| { |
| if (getStyle(styleProp) == newValue && isProtoChainInitialized) |
| return; |
| |
| if (!styleDeclaration) |
| { |
| styleDeclaration = new CSSStyleDeclaration(null, styleManager); |
| styleDeclaration.setLocalStyle(styleProp, newValue); |
| |
| // If nonInheritingStyles is undefined, then this object is being |
| // initialized and we haven't yet generated the proto chain. To |
| // avoid redundant work, don't bother to create the proto chain here. |
| if (isProtoChainInitialized) |
| regenerateStyleCache(false); |
| } |
| else |
| { |
| styleDeclaration.setLocalStyle(styleProp, newValue); |
| } |
| } |
| |
| if (isProtoChainInitialized) |
| { |
| styleChanged(styleProp); |
| notifyStyleChangeInChildren(styleProp, isInheritingStyle); |
| } |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Methods |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * If Flex calls the <code>LayoutManager.invalidateProperties()</code> |
| * method on this ILayoutManagerClient, then |
| * this function is called when it's time to commit property values. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function validateProperties():void |
| { |
| invalidatePropertiesFlag = false; |
| if (_listData) |
| { |
| var dg:DataGrid = DataGrid(_listData.owner); |
| |
| var column:DataGridColumn = |
| dg.mx_internal::rawColumns[_listData.columnIndex]; |
| |
| text = _listData.label; |
| |
| if (_data is DataGridColumn) |
| wordWrap = dg.columnHeaderWordWrap(column); |
| else |
| wordWrap = dg.columnWordWrap(column); |
| |
| if (dg.variableRowHeight) |
| multiline = true; |
| |
| var dataTips:Boolean = dg.showDataTips; |
| if (column.showDataTips == true) |
| dataTips = true; |
| if (column.showDataTips == false) |
| dataTips = false; |
| if (dataTips) |
| { |
| if (!(_data is DataGridColumn) && (textWidth > width |
| || column.dataTipFunction || column.dataTipField |
| || dg.dataTipFunction || dg.dataTipField)) |
| { |
| toolTip = column.itemToDataTip(_data); |
| } |
| else |
| { |
| toolTip = null; |
| } |
| } |
| else |
| { |
| toolTip = null; |
| } |
| } |
| else |
| { |
| text = " "; |
| toolTip = null; |
| } |
| } |
| |
| /** |
| * If Flex calls the <code>LayoutManager.invalidateSize()</code> |
| * method on this ILayoutManagerClient, then |
| * this function is called when it's time to do measurements. |
| * |
| * @param recursive If <code>true</code>, call this method |
| * on the object's children. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function validateSize(recursive:Boolean = false):void |
| { |
| invalidateSizeFlag = false; |
| validateNow(); |
| } |
| |
| /** |
| * If Flex calls <code>LayoutManager.invalidateDisplayList()</code> |
| * method on this ILayoutManagerClient, then |
| * this function is called when it's time to update the display list. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function validateDisplayList():void |
| { |
| validateNow(); |
| } |
| |
| /** |
| * @copy mx.core.UIComponent#clearStyle() |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function clearStyle(styleProp:String):void |
| { |
| setStyle(styleProp, undefined); |
| } |
| |
| /** |
| * @inheritDoc |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function notifyStyleChangeInChildren( |
| styleProp:String, recursive:Boolean):void |
| { |
| } |
| |
| /** |
| * Sets up the <code>inheritingStyles</code> |
| * and <code>nonInheritingStyles</code> objects |
| * and their proto chains so that the <code>getStyle()</code> method can work. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function initProtoChain():void |
| { |
| styleChangedFlag = true; |
| |
| var classSelectors:Array = []; |
| |
| if (styleName) |
| { |
| if (styleName is CSSStyleDeclaration) |
| { |
| // Get the style sheet referenced by the styleName property |
| classSelectors.push(CSSStyleDeclaration(styleName)); |
| } |
| else if (styleName is IFlexDisplayObject) |
| { |
| // If the styleName property is a UIComponent, then there's a |
| // special search path for that case. |
| StyleProtoChain.initProtoChainForUIComponentStyleName(this); |
| return; |
| } |
| else if (styleName is String) |
| { |
| // Get the style sheet referenced by the styleName property |
| var styleNames:Array = styleName.split(/\s+/); |
| for (var c:int=0; c < styleNames.length; c++) |
| { |
| if (styleNames[c].length) { |
| classSelectors.push(styleManager.getMergedStyleDeclaration("." + |
| styleNames[c])); |
| } |
| } |
| } |
| } |
| |
| // To build the proto chain, we start at the end and work forward. |
| // Referring to the list at the top of this function, we'll start by |
| // getting the tail of the proto chain, which is: |
| // - for non-inheriting styles, the global style sheet |
| // - for inheriting styles, my parent's style object |
| var nonInheritChain:Object = styleManager.stylesRoot; |
| |
| var p:IStyleClient = parent as IStyleClient; |
| if (p) |
| { |
| var inheritChain:Object = p.inheritingStyles; |
| if (inheritChain == StyleProtoChain.STYLE_UNINITIALIZED) |
| inheritChain = nonInheritChain; |
| } |
| else |
| { |
| inheritChain = styleManager.stylesRoot; |
| } |
| |
| // Working backwards up the list, the next element in the |
| // search path is the type selector |
| var typeSelectors:Array = getClassStyleDeclarations(); |
| var n:int = typeSelectors.length; |
| for (var i:int = 0; i < n; i++) |
| { |
| var typeSelector:CSSStyleDeclaration = typeSelectors[i]; |
| inheritChain = typeSelector.addStyleToProtoChain(inheritChain, this); |
| nonInheritChain = typeSelector.addStyleToProtoChain(nonInheritChain, this); |
| } |
| |
| // Next are the class selectors |
| for (i = 0; i < classSelectors.length; i++) |
| { |
| var classSelector:CSSStyleDeclaration = classSelectors[i]; |
| if (classSelector) |
| { |
| inheritChain = classSelector.addStyleToProtoChain(inheritChain, this); |
| nonInheritChain = classSelector.addStyleToProtoChain(nonInheritChain, this); |
| } |
| } |
| |
| |
| // Finally, we'll add the in-line styles |
| // to the head of the proto chain. |
| inheritingStyles = styleDeclaration ? |
| styleDeclaration.addStyleToProtoChain(inheritChain, this) : |
| inheritChain; |
| |
| nonInheritingStyles = styleDeclaration ? |
| styleDeclaration.addStyleToProtoChain(nonInheritChain, this) : |
| nonInheritChain; |
| } |
| |
| /** |
| * @inheritDoc |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function regenerateStyleCache(recursive:Boolean):void |
| { |
| initProtoChain(); |
| } |
| |
| /** |
| * @inheritDoc |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function registerEffects(effects:Array /* of String */):void |
| { |
| } |
| |
| /** |
| * @inheritDoc |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function getClassStyleDeclarations():Array |
| { |
| var className:String = getQualifiedClassName(this) |
| className = className.replace("::", "."); |
| |
| var decls:Array = []; |
| |
| while (className != null && |
| className != "mx.core.UIComponent" && |
| className != "mx.core.UITextField") |
| { |
| var s:CSSStyleDeclaration = |
| styleManager.getMergedStyleDeclaration(className); |
| |
| if (s) |
| { |
| decls.unshift(s); |
| } |
| |
| try |
| { |
| className = getQualifiedSuperclassName(getDefinitionByName(className)); |
| className = className.replace("::", "."); |
| } |
| catch(e:ReferenceError) |
| { |
| className = null; |
| } |
| } |
| |
| return decls; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Event handlers |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * The event handler to position the tooltip. |
| * |
| * @param event The event object. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| protected function toolTipShowHandler(event:ToolTipEvent):void |
| { |
| var toolTip:IToolTip = event.toolTip; |
| |
| // We need to position the tooltip at same x coordinate, |
| // center vertically and make sure it doesn't overlap the screen. |
| // Call the helper function to handle this for us. |
| var pt:Point = PopUpUtil.positionOverComponent(this, |
| systemManager, |
| toolTip.width, |
| toolTip.height, |
| height / 2); |
| toolTip.move(pt.x, pt.y); |
| } |
| } |
| |
| } |