////////////////////////////////////////////////////////////////////////////////
//
// 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.advancedDataGridClasses
{
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.AdvancedDataGrid;
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.UIComponentGlobals;
import mx.core.UIFTETextField;
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;
use namespace mx_internal;
//--------------------------------------
// Events
//--------------------------------------
/**
* Dispatched when the data
property changes.
*
*
When you use a component as an item renderer,
* the data
property contains the data to display.
* You can listen for this event and update the component
* when the data
property changes.
You can override the default item renderer by creating a custom item renderer.
* * @see mx.controls.AdvancedDataGrid * @see mx.core.IDataRenderer * @see mx.controls.listClasses.IDropInListItemRenderer * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public class FTEAdvancedDataGridItemRenderer extends UIFTETextField implements IDataRenderer, IDropInListItemRenderer, ILayoutManagerClient, IListItemRenderer, IStyleClient { include "../../../spark/core/Version.as"; //-------------------------------------------------------------------------- // // Constructor // //-------------------------------------------------------------------------- /** * Constructor. * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public function FTEAdvancedDataGridItemRenderer() { 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 thedata
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 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
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:AdvancedDataGridListData;
[Bindable("dataChange")]
/**
* The implementation of the listData
property as
* defined by the IDropInListItemRenderer interface.
* The text of the renderer is set to the label
* property of this property.
*
* @see mx.controls.listClasses.IDropInListItemRenderer
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function get listData():BaseListData
{
return _listData;
}
/**
* @private
*/
public function set listData(value:BaseListData):void
{
_listData = AdvancedDataGridListData(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
* the setStyle()
method
* is called on this component to set an inheriting style.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
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 adg:AdvancedDataGrid = AdvancedDataGrid(_listData.owner);
var newColor:Number;
if (adg.isItemHighlighted(_listData.uid))
{
newColor = getStyle("textRollOverColor");
}
else if (adg.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 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
override public function getStyle(styleProp:String):*
{
return (styleManager.inheritingStyles[styleProp]) ?
inheritingStyles[styleProp] : nonInheritingStyles[styleProp];
}
/**
* @copy mx.core.UIComponent#setStyle()
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
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 LayoutManager.invalidateProperties()
* method on this ILayoutManagerClient,
* this function is called when it's time to commit property values.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function validateProperties():void
{
invalidatePropertiesFlag = false;
if (_listData)
{
var dg:AdvancedDataGrid = AdvancedDataGrid(_listData.owner);
var column:AdvancedDataGridColumn =
dg.columns[_listData.columnIndex];
text = _listData.label;
if (_data is AdvancedDataGridColumn)
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 AdvancedDataGridColumn) && (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 LayoutManager.invalidateSize()
* method on this ILayoutManagerClient,
* this function is called when it's time to do measurements.
*
* @param recursive If true
, call this method
* on the object's children.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function validateSize(recursive:Boolean = false):void
{
invalidateSizeFlag = false;
validateNow();
}
/**
* If Flex calls LayoutManager.invalidateDisplayList()
* method on this ILayoutManagerClient instance,
* this function is called when it's time to update the display list.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function validateDisplayList():void
{
validateNow();
}
/**
* @copy mx.core.UIComponent#clearStyle()
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function clearStyle(styleProp:String):void
{
setStyle(styleProp, undefined);
}
/**
* @copy mx.core.UIComponent#notifyStyleChangeInChildren()
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function notifyStyleChangeInChildren(
styleProp:String, recursive:Boolean):void
{
}
/**
* Sets up the inheritingStyles
* and nonInheritingStyles
objects
* and their proto chains so that the getStyle()
method can work.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
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;
}
/**
* @copy mx.core.UIComponent#regenerateStyleCache()
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function regenerateStyleCache(recursive:Boolean):void
{
initProtoChain();
}
/**
* @copy mx.core.UIComponent#registerEffects()
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function registerEffects(effects:Array /* of String */):void
{
}
/**
* @copy mx.core.UIComponent#getClassStyleDeclarations()
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
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.UIFTETextField")
{
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 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
protected function toolTipShowHandler(event:ToolTipEvent):void
{
var toolTip:IToolTip = event.toolTip;
// Calculate global position of label.
var sm:ISystemManager = systemManager.topLevelSystemManager;
var sbRoot:DisplayObject = sm.getSandboxRoot();
var screen:Rectangle;
var pt:Point = new Point(0, 0);
pt = localToGlobal(pt);
pt = sbRoot.globalToLocal(pt);
toolTip.move(pt.x, pt.y + (height - toolTip.height) / 2);
screen = sm.getVisibleApplicationRect(null, true);
var screenRight:Number = screen.x + screen.width;
pt.x = toolTip.x;
pt.y = toolTip.y;
pt = sbRoot.localToGlobal(pt);
if (pt.x + toolTip.width > screenRight)
toolTip.move(toolTip.x - (pt.x + toolTip.width - screenRight), toolTip.y);
}
}
}