//////////////////////////////////////////////////////////////////////////////// // // 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.managers { import flash.display.DisplayObject; import flash.events.Event; import flash.events.EventDispatcher; import flash.events.IEventDispatcher; import flash.events.MouseEvent; import flash.events.TimerEvent; import flash.geom.Point; import flash.geom.Rectangle; import flash.utils.Timer; import mx.controls.ToolTip; import mx.core.FlexGlobals; import mx.core.FlexVersion; import mx.core.IFlexModule; import mx.core.IInvalidating; import mx.core.ILayoutDirectionElement; import mx.core.IToolTip; import mx.core.IUIComponent; import mx.core.LayoutDirection; import mx.core.mx_internal; import mx.effects.EffectManager; import mx.effects.IAbstractEffect; import mx.events.DynamicEvent; import mx.events.EffectEvent; import mx.events.ToolTipEvent; import mx.managers.IToolTipManagerClient; import mx.styles.IStyleClient; import mx.validators.IValidatorListener; use namespace mx_internal; [ExcludeClass] /** * @private * The ToolTipManager lets you set basic ToolTip and error tip functionality, * such as display delay and the disabling of ToolTips. * * @see mx.controls.ToolTip * @see mx.validators.Validator */ public class ToolTipManagerImpl extends EventDispatcher implements IToolTipManager2 { include "../core/Version.as"; //-------------------------------------------------------------------------- // // Class variables // //-------------------------------------------------------------------------- /** * @private */ private static var instance:IToolTipManager2; /** * @private * * Place to hook in additional classes */ public static var mixins:Array; //-------------------------------------------------------------------------- // // Class methods // //-------------------------------------------------------------------------- /** * @private */ public static function getInstance():IToolTipManager2 { if (!instance) instance = new ToolTipManagerImpl(); return instance; } //-------------------------------------------------------------------------- // // Constructor // //-------------------------------------------------------------------------- /** * @private */ public function ToolTipManagerImpl() { super(); if (instance) throw new Error("Instance already exists."); if (mixins) { var n:int = mixins.length; for (var i:int = 0; i < n; i++) { new mixins[i](this); } } if (hasEventListener("initialize")) dispatchEvent(new Event("initialize")); } //-------------------------------------------------------------------------- // // Variables // //-------------------------------------------------------------------------- /** * @private * A flag that keeps track of whether this class's initialize() * method has been executed. */ mx_internal var initialized:Boolean = false; /** * @private * This timer is used to delay the appearance of a normal ToolTip * after the mouse moves over a target; an error tip has no such delay. * *
This timer, which is lazily created, is started when the mouse * moves over an object with a ToolTip, with a duration specified * by showDelay. * If the mouse moves out of this object before the timer fires, * the ToolTip is never created. * If the mouse stays over the object until the timer fires, * the ToolTip is created and its showEffect is started. */ mx_internal var showTimer:Timer; /** * @private * This timer is used to make the tooltip "time out" and hide itself * if the mouse stays over a target. * *
This timer, which is lazily created, is started * when the showEffect ends. * When it fires, the hideEffect is started.
*/ mx_internal var hideTimer:Timer; /** * @private * This timer is used to implement mousing quickly over multiple targets * with ToolTip... * *This timer, which is lazily created, is started * when ...
*/ mx_internal var scrubTimer:Timer; /** * @private */ mx_internal var currentText:String; /** * @private */ mx_internal var isError:Boolean; /** * The UIComponent with the ToolTip assigned to it * that was most recently under the mouse. * During much of the tool tip life cycle this property * has the same value as thecurrentTarget
property.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
mx_internal var previousTarget:DisplayObject;
//--------------------------------------------------------------------------
//
// Properties
//
//--------------------------------------------------------------------------
//----------------------------------
// currentTarget
//----------------------------------
/**
* @private
*/
private var _currentTarget:DisplayObject;
/**
* The UIComponent that is currently displaying a ToolTip,
* or null
if none is.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get currentTarget():DisplayObject
{
return _currentTarget;
}
/**
* @private
*/
public function set currentTarget(value:DisplayObject):void
{
_currentTarget = value;
}
//----------------------------------
// currentToolTip
//----------------------------------
/**
* @private
*/
mx_internal var _currentToolTip:DisplayObject;
/**
* The ToolTip object that is currently visible,
* or null
if none is shown.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get currentToolTip():IToolTip
{
return _currentToolTip as IToolTip;
}
/**
* @private
*/
public function set currentToolTip(value:IToolTip):void
{
_currentToolTip = value as DisplayObject;
if (hasEventListener("currentToolTip"))
dispatchEvent(new Event("currentToolTip"));
}
//----------------------------------
// enabled
//----------------------------------
/**
* @private
*/
private var _enabled:Boolean = true;
/**
* If true
, the ToolTipManager will automatically show
* ToolTips when the user moves the mouse pointer over components.
* If false
, no ToolTips will be shown.
*
* @default true
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get enabled():Boolean
{
return _enabled;
}
/**
* @private
*/
public function set enabled(value:Boolean):void
{
_enabled = value;
}
//----------------------------------
// hideDelay
//----------------------------------
/**
* @private
*/
private var _hideDelay:Number = 10000; // milliseconds
/**
* The amount of time, in milliseconds, that Flex waits
* to hide the ToolTip after it appears.
* Once Flex hides a ToolTip, the user must move the mouse
* off the component and then back onto it to see the ToolTip again.
* If you set hideDelay
to Infinity
,
* Flex does not hide the ToolTip until the user triggers an event,
* such as moving the mouse off of the component.
*
* @default 10000
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get hideDelay():Number
{
return _hideDelay;
}
/**
* @private
*/
public function set hideDelay(value:Number):void
{
_hideDelay = value;
}
//----------------------------------
// hideEffect
//----------------------------------
/**
* @private
*/
private var _hideEffect:IAbstractEffect;
/**
* The effect that plays when a ToolTip is hidden,
* or null
if the ToolTip should disappear with no effect.
*
* Effects are not marshaled across applicationDomains in a sandbox * as they may not be supportable in different versions
* * @default null * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get hideEffect():IAbstractEffect { return _hideEffect; } /** * @private */ public function set hideEffect(value:IAbstractEffect):void { _hideEffect = value as IAbstractEffect; } //---------------------------------- // scrubDelay //---------------------------------- /** * @private */ private var _scrubDelay:Number = 100; // milliseconds /** * The amount of time, in milliseconds, that a user can take * when moving the mouse between controls before Flex again waits * for the duration ofshowDelay
to display a ToolTip.
*
* This setting is useful if the user moves quickly from one control
* to another; after displaying the first ToolTip, Flex will display
* the others immediately rather than waiting.
* The shorter the setting for scrubDelay
, the more
* likely that the user must wait for an amount of time specified
* by showDelay
in order to see the next ToolTip.
* A good use of this property is if you have several buttons on a
* toolbar, and the user will quickly scan across them to see brief
* descriptions of their functionality.
showDelay
to 0.
*
* @default 500
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get showDelay():Number
{
return _showDelay;
}
/**
* @private
*/
public function set showDelay(value:Number):void
{
_showDelay = value;
}
//----------------------------------
// showEffect
//----------------------------------
/**
* @private
*/
private var _showEffect:IAbstractEffect;
/**
* The effect that plays when a ToolTip is shown,
* or null
if the ToolTip should appear with no effect.
*
* Effects are not marshaled across applicationDomains in a sandbox * as they may not be supportable in different versions
* * @default null * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get showEffect():IAbstractEffect { return _showEffect; } /** * @private */ public function set showEffect(value:IAbstractEffect):void { _showEffect = value as IAbstractEffect; } //---------------------------------- // toolTipClass //---------------------------------- /** * @private */ private var _toolTipClass:Class = ToolTip; /** * The class to use for creating ToolTips. * *The ToolTipClass is not marshaled across applicationDomains in a sandbox * as they may not be supportable in different versions. Child * applications should only be interested in setting the tooltip * for objects within themselves
* * @default mx.controls.ToolTip * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get toolTipClass():Class { return _toolTipClass; } /** * @private */ public function set toolTipClass(value:Class):void { _toolTipClass = value; } //-------------------------------------------------------------------------- // // Methods // //-------------------------------------------------------------------------- /** * @private * Initializes the class. * *This method sets up three Timer objects that ToolTipManager * starts and stops while tracking the mouse. * The repeatCount is set to 1 so that they fire only once. * Their duration is set later, just before they are started. * The timers are never destroyed once they are created here.
* *This method is called by targetChanged(); Flex waits to initialize * the class until mouse-tracking happens in order to optimize * startup time.
*/ mx_internal function initialize():void { if (!showTimer) { showTimer = new Timer(0, 1); showTimer.addEventListener(TimerEvent.TIMER, showTimer_timerHandler); } if (!hideTimer) { hideTimer = new Timer(0, 1); hideTimer.addEventListener(TimerEvent.TIMER, hideTimer_timerHandler); } if (!scrubTimer) scrubTimer = new Timer(0, 1); initialized = true; } /** * Registers a target UIComponent or UITextField, and the text * for its ToolTip, with the ToolTipManager. * This causes the ToolTipManager to display a ToolTip * when the mouse hovers over the target. * *This method is called by the setter * for the toolTip property in UIComponent and UITextField.
* * @param target The UIComponent or UITextField that owns the ToolTip. * * @param oldToolTip The old text that was displayed * in the ToolTip. * * @param newToolTip The new text to display in the ToolTip. * If null, no ToolTip will be displayed when the mouse hovers * over the target. * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function registerToolTip(target:DisplayObject, oldToolTip:String, newToolTip:String):void { if (!oldToolTip && newToolTip) { target.addEventListener(MouseEvent.MOUSE_OVER, toolTipMouseOverHandler); target.addEventListener(MouseEvent.MOUSE_OUT, toolTipMouseOutHandler); // If the mouse is already over the object // that's getting a toolTip, show the tip. if (mouseIsOver(target)) showImmediately(target); } else if (oldToolTip && !newToolTip) { target.removeEventListener(MouseEvent.MOUSE_OVER, toolTipMouseOverHandler); target.removeEventListener(MouseEvent.MOUSE_OUT, toolTipMouseOutHandler); // If the mouse is over the object whose toolTip // is being removed, hide the tip. if (mouseIsOver(target)) hideImmediately(target); } } /** * Registers a target UIComponent, and the text * for its error tip, with the ToolTipManager. * This causes the ToolTipManager to display an error tip * when the mouse hovers over the target. * *This method is called by the setter * for the errorString property in UIComponent.
* * @param target The UIComponent or UITextField that owns the ToolTip. * * @param oldErrorString The old text that was displayed * in the error tip. * * @param newErrorString The new text to display in the error tip. * If null, no error tip will be displayed when the mouse hovers * over the target. * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function registerErrorString(target:DisplayObject, oldErrorString:String, newErrorString:String):void { if (!oldErrorString && newErrorString) { target.addEventListener(MouseEvent.MOUSE_OVER, errorTipMouseOverHandler); target.addEventListener(MouseEvent.MOUSE_OUT, errorTipMouseOutHandler); // If the mouse is already over the object // that's getting an errorTip, show the tip. if (mouseIsOver(target)) showImmediately(target); } else if (oldErrorString && !newErrorString) { target.removeEventListener(MouseEvent.MOUSE_OVER, errorTipMouseOverHandler); target.removeEventListener(MouseEvent.MOUSE_OUT, errorTipMouseOutHandler); // If the mouse is over the object whose toolTip // is being removed, hide the tip. if (mouseIsOver(target)) hideImmediately(target); } } /** * @private * Returns true if the mouse is over the specified target. */ private function mouseIsOver(target:DisplayObject):Boolean { if (!target || !target.stage) return false; //SDK:13465 - If we pass through the above if block, then //we have a target component and its been added to the //display list. If the mouse coordinates are (0,0), there //is a chance the component has not been positioned yet //and we'll end up mistakenly showing tooltips since the //target hitTest will return true. if ((target.stage.mouseX == 0) && (target.stage.mouseY == 0)) return false; if (target is ILayoutManagerClient && !ILayoutManagerClient(target).initialized) return false; return target.hitTestPoint(target.stage.mouseX, target.stage.mouseY, true); } /** * @private * Shows the tip immediately when the toolTip or errorTip property * becomes non-null and the mouse is over the target. */ private function showImmediately(target:DisplayObject):void { var oldShowDelay:Number = ToolTipManager.showDelay; ToolTipManager.showDelay = 0; checkIfTargetChanged(target); ToolTipManager.showDelay = oldShowDelay; } /** * @private * Hides the tip immediately when the toolTip or errorTip property * becomes null and the mouse is over the target. */ private function hideImmediately(target:DisplayObject):void { checkIfTargetChanged(null); } /** * Replaces the ToolTip, if necessary. * *Determines whether the UIComponent or UITextField object * with the ToolTip assigned to it that is currently under the mouse * pointer is the most recent such object. * If not, it removes the old ToolTip and displays the new one.
* * @param displayObject The UIComponent or UITextField that is currently under the mouse. * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ mx_internal function checkIfTargetChanged(displayObject:DisplayObject):void { if (!enabled) return; findTarget(displayObject); if (currentTarget != previousTarget) { targetChanged(); previousTarget = currentTarget; } } /** * Searches from thedisplayObject
object up the chain
* of parent objects until it finds a UIComponent or UITextField object
* with a toolTip
or errorString
property.
* Treats an empty string as a valid toolTip
property.
* Sets the currentTarget
property.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
mx_internal function findTarget(displayObject:DisplayObject):void
{
// Walk up the DisplayObject parent chain looking for a UIComponent
// with a toolTip or errorString property. Note that we stop
// even if we find a tooltip which is an empty string. Although
// we don't display empty tooltips, we have to track when we
// are over a movieclip with an empty tooltip so that we can
// hide any previous tooltip. This allows a child to set
// toolTip="" to "cancel" its parent's toolTip.
while (displayObject)
{
if (displayObject is IValidatorListener)
{
currentText = IValidatorListener(displayObject).errorString;
var showErrorTip:Boolean;
if (displayObject is IStyleClient)
showErrorTip = FlexVersion.compatibilityVersion < FlexVersion.VERSION_4_0 ||
IStyleClient(displayObject).getStyle("showErrorTip");
;
if (currentText != null && currentText != "" && showErrorTip)
{
currentTarget = displayObject;
isError = true;
return;
}
}
if (displayObject is IToolTipManagerClient)
{
currentText = IToolTipManagerClient(displayObject).toolTip;
if (currentText != null)
{
currentTarget = displayObject;
isError = false;
return;
}
}
displayObject = displayObject.parent;
}
currentText = null;
currentTarget = null;
}
/**
* Removes any ToolTip that is currently displayed and displays
* the ToolTip for the UIComponent that is currently under the mouse
* pointer, as determined by the currentTarget
property.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
mx_internal function targetChanged():void
{
// Do lazy creation of the Timer objects this class uses.
if (!initialized)
initialize()
var event:ToolTipEvent;
if (previousTarget && currentToolTip)
{
if (currentToolTip is IToolTip)
{
event = new ToolTipEvent(ToolTipEvent.TOOL_TIP_HIDE);
event.toolTip = currentToolTip;
previousTarget.dispatchEvent(event);
}
else
{
if (hasEventListener(ToolTipEvent.TOOL_TIP_HIDE))
dispatchEvent(new Event(ToolTipEvent.TOOL_TIP_HIDE));
}
}
reset();
if (currentTarget)
{
// Don't display empty tooltips.
if (currentText == "")
return;
// Dispatch a "startToolTip" event
// from the object displaying the tooltip.
event = new ToolTipEvent(ToolTipEvent.TOOL_TIP_START);
currentTarget.dispatchEvent(event);
if (showDelay == 0 || scrubTimer.running)
{
// Create the tooltip and start its showEffect.
createTip();
initializeTip();
positionTip();
showTip();
}
else
{
showTimer.delay = showDelay;
showTimer.start();
// After the delay, showTimer_timerHandler()
// will create the tooltip and start its showEffect.
}
}
}
/**
* Creates an invisible new ToolTip.
*
* If the ToolTipManager's enabled
property is
* true
this method is automatically called
* when the user moves the mouse over an object that has
* the toolTip
property set,
* The ToolTipManager makes subsequent calls to
* initializeTip()
, positionTip()
,
* and showTip()
to complete the display
* of the ToolTip.
The type of ToolTip that is created is determined by the
* toolTipClass
property.
* By default, this is the ToolTip class.
* This class can be styled to appear as either a normal ToolTip
* (which has a yellow background by default) or as an error tip
* for validation errors (which is red by default).
After creating the ToolTip with the new
* operator, this method stores a reference to it in the
* currentToolTip
property.
* It then uses addChild() to add this ToolTip to the
* SystemManager's toolTips layer.
If the ToolTipManager's enabled
property is
* true
this method is automatically called
* when the user moves the mouse over an object that has
* the toolTip
property set.
* The ToolTipManager calls createTip()
before
* this method, and positionTip()
and
* showTip()
after.
If a normal ToolTip is being displayed, this method
* sets its text as specified by the toolTip
* property of the object under the mouse.
* If an error tip is being displayed, the text is as
* specified by the errorString
property
* of the object under the mouse.
This method also makes the ToolTip the appropriate * size for the text that it needs to display.
* * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ mx_internal function initializeTip():void { // Set the text of the tooltip. if (currentToolTip is IToolTip) IToolTip(currentToolTip).text = currentText; if (isError && currentToolTip is IStyleClient) IStyleClient(currentToolTip).setStyle("styleName", "errorTip"); sizeTip(currentToolTip); if (currentToolTip is IStyleClient) { // Set up its "show" and "hide" effects. if (showEffect) IStyleClient(currentToolTip).setStyle("showEffect", showEffect); if (hideEffect) IStyleClient(currentToolTip).setStyle("hideEffect", hideEffect); } if (showEffect || hideEffect) { currentToolTip.addEventListener(EffectEvent.EFFECT_END, effectEndHandler); } } /** * @private * Objects added to the SystemManager's ToolTip layer don't get * automatically measured or sized, so ToolTipManager has to * measure it and set its size. */ public function sizeTip(toolTip:IToolTip):void { // Force measure() to be called on the tooltip. // Otherwise, its measured size will be 0. if (toolTip is IInvalidating) IInvalidating(toolTip).validateNow(); toolTip.setActualSize( toolTip.getExplicitOrMeasuredWidth(), toolTip.getExplicitOrMeasuredHeight()); } /** * Positions a newly created and initialized ToolTip on the stage. * *If the ToolTipManager's enabled
property is
* true
this method is automatically called
* when the user moves the mouse over an object that has
* the toolTip
property set.
* The ToolTipManager calls createTip()
and
* initializeTip()
before this method,
* and showTip()
after.
If a normal ToolTip is being displayed, this method positions * its upper-left (upper-right) corner near the lower-right (lower-left) * of the arrow cursor. This method ensures that the ToolTip is * completely in view. * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ mx_internal function positionTip():void { // Determine layoutDirection of the target component. var layoutDirection:String; if (currentTarget is ILayoutDirectionElement) layoutDirection = ILayoutDirectionElement(currentTarget).layoutDirection; else layoutDirection = LayoutDirection.LTR; const mirror:Boolean = (layoutDirection == LayoutDirection.RTL); var x:Number; var y:Number; var screenWidth:Number = currentToolTip.screen.width; var screenHeight:Number = currentToolTip.screen.height; if (isError) { // Tooltips are laid out in the same direction as the target // component. var tipElt:ILayoutDirectionElement = currentToolTip as ILayoutDirectionElement; if (tipElt && tipElt.layoutDirection != layoutDirection) { tipElt.layoutDirection = layoutDirection; // sizeTip below will call validateNow() tipElt.invalidateLayoutDirection(); } var targetGlobalBounds:Rectangle = getGlobalBounds(currentTarget, currentToolTip.root, mirror); x = mirror ? targetGlobalBounds.left - 4 : targetGlobalBounds.right + 4; y = targetGlobalBounds.top - 1; // If there's no room to the right (left) of the control, put it // above or below, with the left (right) edge of the error tip // aligned with the left (right) edge of the target. var noRoom:Boolean = mirror ? x < currentToolTip.width : x + currentToolTip.width > screenWidth; if (noRoom) { var newWidth:Number = NaN; var oldWidth:Number = NaN; x = mirror ? targetGlobalBounds.right + 2 - currentToolTip.width : targetGlobalBounds.left - 2; // If the error tip would be too wide for the stage, // reduce the maximum width to fit onstage. Note that // we have to reassign the text in order to get the tip // to relayout after changing the border style and maxWidth. if (mirror) { if (x < currentToolTip.width + 4) { // -4 on the left, +2 on the right = -2 x = 4; newWidth = targetGlobalBounds.right - 2; } } else { if (x + currentToolTip.width + 4 > screenWidth) newWidth = screenWidth - x - 4; } if (!isNaN(newWidth)) { oldWidth = Object(toolTipClass).maxWidth; Object(toolTipClass).maxWidth = newWidth; if (currentToolTip is IStyleClient) IStyleClient(currentToolTip).setStyle("borderStyle", "errorTipAbove"); currentToolTip["text"] = currentToolTip["text"]; } // Even if the error tip will fit onstage, we still need to // change the border style and get the error tip to relayout. else { if (currentToolTip is IStyleClient) IStyleClient(currentToolTip).setStyle("borderStyle", "errorTipAbove"); currentToolTip["text"] = currentToolTip["text"]; } if (currentToolTip.height + 2 < targetGlobalBounds.top) { // There's room to put it above the control. y = targetGlobalBounds.top - (currentToolTip.height + 2); } else { // No room above, put it below the control. y = targetGlobalBounds.bottom + 2; if (!isNaN(newWidth)) Object(toolTipClass).maxWidth = newWidth; if (currentToolTip is IStyleClient) IStyleClient(currentToolTip).setStyle("borderStyle", "errorTipBelow"); currentToolTip["text"] = currentToolTip["text"]; } } // Since the border style of the error tip may have changed, // we have to force a remeasurement and change its size. // This is because objects in the toolTips layer // don't undergo normal measurement and layout. sizeTip(currentToolTip) // If we changed the tooltip max size, we change it back. // Otherwise, if RTL, and x wasn't set for maxWidth, reposition // because the width may have changed during the remeasure. if (!isNaN(oldWidth)) Object(toolTipClass).maxWidth = oldWidth; else if (mirror) x = targetGlobalBounds.right + 2 - currentToolTip.width; } else { var sm:ISystemManager = getSystemManager(currentTarget); // Position the upper-left (upper-right) of the tooltip // at the lower-right (lower-left) of the arrow cursor. x = DisplayObject(sm).mouseX + 11; if (mirror) x -= currentToolTip.width; y = DisplayObject(sm).mouseY + 22; // If the tooltip is too wide to fit onstage, move it left (right). var toolTipWidth:Number = currentToolTip.width; if (mirror) { if (x < 2) x = 2; } else if (x + toolTipWidth > screenWidth) { x = screenWidth - toolTipWidth; } // If the tooltip is too tall to fit onstage, move it up. var toolTipHeight:Number = currentToolTip.height; if (y + toolTipHeight > screenHeight) y = screenHeight - toolTipHeight; var pos:Point = new Point(x, y); pos = DisplayObject(sm).localToGlobal(pos); pos = DisplayObject(sm.getSandboxRoot()).globalToLocal(pos); x = pos.x; y = pos.y; } currentToolTip.move(x, y); } /** * Shows a newly created, initialized, and positioned ToolTip. * *
If the ToolTipManager's enabled
property is
* true
this method is automatically called
* when the user moves the mouse over an object that has
* the toolTip
property set.
* The ToolTipManager calls createTip()
,
* initializeTip()
, and positionTip()
* before this method.
This method first dispatches a "showToolTip"
* event from the object under the mouse.
* This gives you a chance to do special processing on a
* particular object's ToolTip just before it becomes visible.
* It then makes the ToolTip visible, which triggers
* the ToolTipManager's showEffect
if one is specified.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
mx_internal function showTip():void
{
// Dispatch a "showToolTip" event
// from the object displaying the tooltip.
var event:ToolTipEvent =
new ToolTipEvent(ToolTipEvent.TOOL_TIP_SHOW);
event.toolTip = currentToolTip;
currentTarget.dispatchEvent(event);
if (isError)
{
// Listen for a change event so we know when to hide the tip
currentTarget.addEventListener(Event.CHANGE, changeHandler);
}
else
{
var sm:ISystemManager = getSystemManager(currentTarget);
sm.addEventListener(MouseEvent.MOUSE_DOWN,
systemManager_mouseDownHandler);
}
// Make the tooltip visible.
// If showEffect exists, this effect will play.
// When the effect ends, effectEndHandler()
// will start the hideTimer.
currentToolTip.visible = true;
if (!showEffect)
showEffectEnded();
}
/**
* Hides the current ToolTip.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
mx_internal function hideTip():void
{
// Dispatch a "hideToolTip" event
// from the object that was displaying the tooltip.
if (previousTarget)
{
var event:ToolTipEvent =
new ToolTipEvent(ToolTipEvent.TOOL_TIP_HIDE);
event.toolTip = currentToolTip;
previousTarget.dispatchEvent(event);
}
// Make the tooltip invisible.
// If hideEffect exists, this effect will play.
// When the effect ends, effectEndHandler()
// will reset the ToolTipManager to a no-tip state.
if (currentToolTip)
currentToolTip.visible = false;
// When to do this?
if (isError)
{
if (currentTarget)
currentTarget.removeEventListener(Event.CHANGE, changeHandler);
}
else
{
if (previousTarget)
{
var sm:ISystemManager = getSystemManager(previousTarget);
sm.removeEventListener(MouseEvent.MOUSE_DOWN,
systemManager_mouseDownHandler);
}
}
if (!hideEffect)
hideEffectEnded();
}
/**
* Removes any currently visible ToolTip.
* If the ToolTip is starting to show or hide, this method
* removes the ToolTip immediately without completing the effect.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
mx_internal function reset():void
{
// Reset the three timers, in case any are running.
showTimer.reset();
hideTimer.reset();
// If there is a current tooltip...
if (currentToolTip)
{
// Remove the event handlers for the effectEnd of the showEffect
// and hideEffect, so that calling endEffectsForTarget() doesn't
// trigger effectEndHandler().
if (showEffect || hideEffect)
{
currentToolTip.removeEventListener(EffectEvent.EFFECT_END,
effectEndHandler);
}
// End any show or hide effects that might be playing on it.
EffectManager.endEffectsForTarget(currentToolTip);
var e:DynamicEvent;
if (hasEventListener("removeChild"))
{
e = new DynamicEvent("removeChild", false, true);
e.sm = currentToolTip.systemManager;
e.toolTip = currentToolTip;
}
if (!e || dispatchEvent(e))
{
// Remove it.
var sm:ISystemManager = currentToolTip.systemManager as ISystemManager;
sm.topLevelSystemManager.toolTipChildren.removeChild(currentToolTip as DisplayObject);
}
currentToolTip = null;
scrubTimer.delay = scrubDelay;
scrubTimer.reset();
if (scrubDelay > 0)
{
scrubTimer.delay = scrubDelay;
scrubTimer.start();
}
}
}
/**
* Creates an instance of the ToolTip class with the specified text
* and displays it at the specified location in stage coordinates.
*
*
ToolTips appear in their own layer, on top of everything * except cursors.
* *The standard way of using ToolTips is to let the ToolTipManager
* automatically show and hide them as the user moves the mouse over
* the objects that have the toolTip
property set.
* You can turn off this automatic ToolTip management by setting
* the ToolTipManager's enabled
property to
* false
.
By contrast, this method—along with hideToolTip()
—gives
* you programmatic control over ToolTips.
* You can show them when and where you choose,
* and you can even show more than one at once if you need to.
* (The ToolTipManager never does this, because it is generally
* confusing to the user).
This method first creates a new instance of ToolTip and calls the
* addChild()
method to put it into the SystemManager's
* toolTips layer.
* If you are showing an error tip, it sets the appropriate styles.
* Then it sets the text for the ToolTip, sizes the ToolTip based on
* its text, and positions it where you specified.
You must save the reference to the ToolTip that this method
* returns so that you can pass it to the hideToolTip()
method.
context
argument.
*
* @param y The vertical coordinate of the ToolTip in stage coordinates.
* In case of multiple stages, the relevant stage is determined
* from the context
argument.
*
* @param errorTipBorderStyle The border style of an error tip. This method
* argument can be null, "errorTipRight", "errorTipAbove", or "errorTipBelow".
* If it is null, then the createToolTip()
method creates a normal ToolTip. If it is
* "errorTipRight", "errorTipAbove", or "errorTipBelow", then the createToolTip()
* method creates an error tip, and this parameter determines where the arrow
* of the error tip points to (the error's target). For example, if you pass "errorTipRight", Flex
* positions the error tip (via the x and y arguments) to the
* right of the error target; the arrow is on the left edge of the error tip.
*
* @param context This property is not currently used.
*
* @return The newly created ToolTip.
*
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function createToolTip(text:String, x:Number, y:Number,
errorTipBorderStyle:String = null,
context:IUIComponent = null):IToolTip
{
var toolTip:ToolTip = new ToolTip();
var sm:ISystemManager = context ?
context.systemManager as ISystemManager:
FlexGlobals.topLevelApplication.systemManager as ISystemManager;
if (context is IFlexModule)
toolTip.moduleFactory = IFlexModule(context).moduleFactory;
else
toolTip.moduleFactory = sm;
var e:DynamicEvent;
if (hasEventListener("addChild"))
{
e = new DynamicEvent("addChild", false, true);
e.sm = sm;
e.toolTip = toolTip;
}
if (!e || dispatchEvent(e))
{
sm.topLevelSystemManager.toolTipChildren.addChild(toolTip as DisplayObject);
}
if (errorTipBorderStyle)
{
toolTip.setStyle("styleName", "errorTip");
toolTip.setStyle("borderStyle", errorTipBorderStyle);
}
toolTip.text = text;
sizeTip(toolTip);
toolTip.move(x, y);
// Ensure that tip is on screen?
// Should x and y for error tip be tip of pointy border?
// show effect?
return toolTip as IToolTip;
}
/**
* Destroys a specified ToolTip that was created by the createToolTip()
method.
*
* This method calls the removeChild()
method to remove the specified
* ToolTip from the SystemManager's ToolTips layer.
* It will then be garbage-collected unless you keep a
* reference to it.
You should not call this method on the ToolTipManager's
* currentToolTip
.