http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/77148f4a/frameworks/projects/MX/src/main/flex/mx/managers/SystemRawChildrenList.as ---------------------------------------------------------------------- diff --cc frameworks/projects/MX/src/main/flex/mx/managers/SystemRawChildrenList.as index e810815,0000000..5410b35 mode 100644,000000..100644 --- a/frameworks/projects/MX/src/main/flex/mx/managers/SystemRawChildrenList.as +++ b/frameworks/projects/MX/src/main/flex/mx/managers/SystemRawChildrenList.as @@@ -1,240 -1,0 +1,240 @@@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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 +{ + - COMPILE::AS3 ++COMPILE::SWF +{ + import flash.display.DisplayObject; + import flash.geom.Point; +} +COMPILE::JS +{ + import flex.display.DisplayObject; + import org.apache.flex.geom.Point; +} +import mx.core.IChildList; +import mx.core.mx_internal; + +use namespace mx_internal; + +[ExcludeClass] + +/** + * @private + * A SystemManager has various types of children, + * such as the Application, popups, + * tooltips, and custom cursors. + * You can access the just the custom cursors through + * the <code>cursors</code> property, + * the tooltips via <code>toolTips</code>, and + * the popups via <code>popUpChildren</code>. Each one returns + * a SystemChildrenList which implements IChildList. The SystemManager's + * IChildList methods return the set of children that aren't popups, tooltips + * or cursors. To get the list of all children regardless of type, you + * use the rawChildrenList property which returns this SystemRawChildrenList. + */ +public class SystemRawChildrenList implements IChildList +{ + include "../core/Version.as"; + + //-------------------------------------------------------------------------- + // + // Constructor + // + //-------------------------------------------------------------------------- + + /** + * Constructor. + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public function SystemRawChildrenList(owner:SystemManager) + { + super(); + + this.owner = owner; + } + + //-------------------------------------------------------------------------- + // + // Properties + // + //-------------------------------------------------------------------------- + + /** + * @private + */ + private var owner:SystemManager; + + //-------------------------------------------------------------------------- + // + // Methods + // + //-------------------------------------------------------------------------- + + /** + * @copy mx.core.IChildList#numChildren + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public function get numChildren():int + { + return owner.$numChildren; + } + + /** + * @copy mx.core.IChildList#getChildAt + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public function getChildAt(index:int):DisplayObject + { + return owner.rawChildren_getChildAt(index); + } + + /** + * @copy mx.core.IChildList#addChild + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public function addChild(child:DisplayObject):DisplayObject + { + return owner.rawChildren_addChild(child); + } + + /** + * @copy mx.core.IChildList#addChildAt + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public function addChildAt(child:DisplayObject, index:int):DisplayObject + { + return owner.rawChildren_addChildAt(child,index); + } + + /** + * @copy mx.core.IChildList#removeChild + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public function removeChild(child:DisplayObject):DisplayObject + { + return owner.rawChildren_removeChild(child); + } + + /** + * @copy mx.core.IChildList#removeChildAt + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public function removeChildAt(index:int):DisplayObject + { + return owner.rawChildren_removeChildAt(index); + } + + /** + * @copy mx.core.IChildList#getChildByName + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public function getChildByName(name:String):DisplayObject + { + return owner.rawChildren_getChildByName(name); + } + + /** + * @copy mx.core.IChildList#getChildIndex + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public function getChildIndex(child:DisplayObject):int + { + return owner.rawChildren_getChildIndex(child); + } + + /** + * @copy mx.core.IChildList#setChildIndex + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public function setChildIndex(child:DisplayObject, newIndex:int):void + { + owner.rawChildren_setChildIndex(child, newIndex); + } + + /** + * @copy mx.core.IChildList#getObjectsUnderPoint + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public function getObjectsUnderPoint(point:Point):Array + { + return owner.rawChildren_getObjectsUnderPoint(point); + } + + /** + * @copy mx.core.IChildList#contains + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public function contains(child:DisplayObject):Boolean + { + return owner.rawChildren_contains(child); + } +} + +}
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/77148f4a/frameworks/projects/MX/src/main/flex/mx/managers/ToolTipManager.as ---------------------------------------------------------------------- diff --cc frameworks/projects/MX/src/main/flex/mx/managers/ToolTipManager.as index 95a55ff,0000000..c105158 mode 100644,000000..100644 --- a/frameworks/projects/MX/src/main/flex/mx/managers/ToolTipManager.as +++ b/frameworks/projects/MX/src/main/flex/mx/managers/ToolTipManager.as @@@ -1,526 -1,0 +1,526 @@@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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 +{ + - COMPILE::AS3 ++COMPILE::SWF +{ + import flash.display.DisplayObject; +} +COMPILE::JS +{ + import flex.display.DisplayObject; +} +import org.apache.flex.events.EventDispatcher; +import mx.core.IToolTip; +import mx.core.IUIComponent; +import mx.core.Singleton; +import mx.core.mx_internal; +import mx.effects.IAbstractEffect; + +/** + * 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 + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ +public class ToolTipManager extends EventDispatcher +{ + include "../core/Version.as"; + + //-------------------------------------------------------------------------- + // + // Class variables + // + //-------------------------------------------------------------------------- + + /** + * @private + * Linker dependency on implementation class. + */ + private static var implClassDependency:ToolTipManagerImpl; + + /** + * @private + * Storage for the impl getter. + * This gets initialized on first access, + * not at static initialization time, in order to ensure + * that the Singleton registry has already been initialized. + */ + private static var _impl:IToolTipManager2; + + /** + * @private + * The singleton instance of ToolTipManagerImpl which was + * registered as implementing the IToolTipManager2 interface. + */ + private static function get impl():IToolTipManager2 + { + if (!_impl) + { + _impl = IToolTipManager2( + Singleton.getInstance("mx.managers::IToolTipManager2")); + } + + return _impl; + } + + //-------------------------------------------------------------------------- + // + // Class properties + // + //-------------------------------------------------------------------------- + + //---------------------------------- + // currentTarget + //---------------------------------- + + /** + * The UIComponent that is currently displaying a ToolTip, + * or <code>null</code> if none is. + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public static function get currentTarget():DisplayObject + { + return impl.currentTarget; + } + + /** + * @private + */ + public static function set currentTarget(value:DisplayObject):void + { + impl.currentTarget = value; + } + + //---------------------------------- + // currentToolTip + //---------------------------------- + + /** + * The ToolTip object that is currently visible, + * or <code>null</code> if none is shown. + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public static function get currentToolTip():IToolTip + { + return impl.currentToolTip; + } + + /** + * @private + */ + public static function set currentToolTip(value:IToolTip):void + { + impl.currentToolTip = value; + } + + //---------------------------------- + // enabled + //---------------------------------- + + /** + * If <code>true</code>, the ToolTipManager will automatically show + * ToolTips when the user moves the mouse pointer over components. + * If <code>false</code>, no ToolTips will be shown. + * + * @default true + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public static function get enabled():Boolean + { + return impl.enabled; + } + + /** + * @private + */ + public static function set enabled(value:Boolean):void + { + impl.enabled = value; + } + + //---------------------------------- + // hideDelay + //---------------------------------- + + /** + * 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 <code>hideDelay</code> to <code>Infinity</code>, + * 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 static function get hideDelay():Number + { + return impl.hideDelay; + } + + /** + * @private + */ + public static function set hideDelay(value:Number):void + { + impl.hideDelay = value; + } + + //---------------------------------- + // hideEffect + //---------------------------------- + + /** + * The effect that plays when a ToolTip is hidden, + * or <code>null</code> if the ToolTip should disappear with no effect. + * + * @default null + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public static function get hideEffect():IAbstractEffect + { + return impl.hideEffect; + } + + /** + * @private + */ + public static function set hideEffect(value:IAbstractEffect):void + { + impl.hideEffect = value; + } + + //---------------------------------- + // scrubDelay + //---------------------------------- + + /** + * The amount of time, in milliseconds, that a user can take + * when moving the mouse between controls before Flex again waits + * for the duration of <code>showDelay</code> to display a ToolTip. + * + * <p>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 <code>scrubDelay</code>, the more + * likely that the user must wait for an amount of time specified + * by <code>showDelay</code> 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.</p> + * + * @default 100 + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public static function get scrubDelay():Number + { + return impl.scrubDelay; + } + + /** + * @private + */ + public static function set scrubDelay(value:Number):void + { + impl.scrubDelay = value; + } + + //---------------------------------- + // showDelay + //---------------------------------- + + /** + * The amount of time, in milliseconds, that Flex waits + * before displaying the ToolTip box once a user + * moves the mouse over a component that has a ToolTip. + * To make the ToolTip appear instantly, set <code>showDelay</code> to 0. + * + * @default 500 + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public static function get showDelay():Number + { + return impl.showDelay; + } + + /** + * @private + */ + public static function set showDelay(value:Number):void + { + impl.showDelay = value; + } + + //---------------------------------- + // showEffect + //---------------------------------- + + /** + * The effect that plays when a ToolTip is shown, + * or <code>null</code> if the ToolTip should appear with no effect. + * + * @default null + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public static function get showEffect():IAbstractEffect + { + return impl.showEffect; + } + + /** + * @private + */ + public static function set showEffect(value:IAbstractEffect):void + { + impl.showEffect = value; + } + + //---------------------------------- + // toolTipClass + //---------------------------------- + + /** + * The class to use for creating ToolTips. + * + * @default mx.controls.ToolTip + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public static function get toolTipClass():Class + { + return impl.toolTipClass; + } + + /** + * @private + */ + public static function set toolTipClass(value:Class):void + { + impl.toolTipClass = value; + } + + //-------------------------------------------------------------------------- + // + // Methods + // + //-------------------------------------------------------------------------- + + /** + * 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. + * + * <p>This method is called by the setter + * for the toolTip property in UIComponent and UITextField.</p> + * + * @param target The UIComponent or UITextField that owns the ToolTip. + * + * @param toolTip The 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 + */ + mx_internal static function registerToolTip(target:DisplayObject, + oldToolTip:String, + newToolTip:String):void + { + impl.registerToolTip(target, oldToolTip, newToolTip); + } + + /** + * 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. + * + * <p>This method is called by the setter + * for the errorString property in UIComponent.</p> + * + * @param target The UIComponent or UITextField that owns the ToolTip. + * + * @param toolTip The 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 + */ + mx_internal static function registerErrorString(target:DisplayObject, + oldErrorString:String, + newErrorString:String):void + { + impl.registerErrorString(target, oldErrorString, newErrorString); + } + + /** + * @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. + */ + mx_internal static function sizeTip(toolTip:IToolTip):void + { + impl.sizeTip(toolTip); + } + + /** + * Creates an instance of the ToolTip class with the specified text + * and displays it at the specified location in stage coordinates. + * + * <p>ToolTips appear in their own layer, on top of everything + * except cursors.</p> + * + * <p>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 <code>toolTip</code> property set. + * You can turn off this automatic ToolTip management by setting + * the ToolTipManager's <code>enabled</code> property to + * <code>false</code>.</p> + * + * <p>By contrast, this method—along with <code>destroyToolTip()</code>—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).</p> + * + * <p>This method first creates a new instance of ToolTip and calls the + * <code>addChild()</code> 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.</p> + * + * <p>You must save the reference to the ToolTip that this method + * returns so that you can pass it to the <code>destroyToolTip()</code> method.</p> + * + * @param text The text to display in the ToolTip instance. + * + * @param x The horizontal coordinate of the ToolTip in stage coordinates. + * In case of multiple stages, the relevant stage is determined + * from the <code>context</code> argument. + * + * @param y The vertical coordinate of the ToolTip in stage coordinates. + * In case of multiple stages, the relevant stage is determined + * from the <code>context</code> 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 <code>createToolTip()</code> method creates a normal ToolTip. If it is + * "errorTipRight", "errorTipAbove", or "errorTipBelow", then the <code>createToolTip()</code> + * 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 Determines which StyleManager is used. Typically, you pass the object on + * which the ToolTip appears, so that the ToolTip's StyleManager is the same one that is used by that object. + * + * @return The newly created ToolTip. + * + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public static function createToolTip(text:String, x:Number, y:Number, + errorTipBorderStyle:String = null, + context:IUIComponent = null):IToolTip + { + return impl.createToolTip(text, x, y, errorTipBorderStyle, context); + } + + /** + * Destroys a specified ToolTip that was created by the <code>createToolTip()</code> method. + * + * <p>This method calls the <code>removeChild()</code> 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.</p> + * + * <p>You should not call this method on the ToolTipManager's + * <code>currentToolTip</code>.</p> + * + * @param toolTip The ToolTip instance to destroy. + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public static function destroyToolTip(toolTip:IToolTip):void + { + return impl.destroyToolTip(toolTip); + } +} + +} http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/77148f4a/frameworks/projects/MX/src/main/flex/mx/managers/ToolTipManagerImpl.as ---------------------------------------------------------------------- diff --cc frameworks/projects/MX/src/main/flex/mx/managers/ToolTipManagerImpl.as index a1c6f2f,0000000..0cb6c02 mode 100644,000000..100644 --- a/frameworks/projects/MX/src/main/flex/mx/managers/ToolTipManagerImpl.as +++ b/frameworks/projects/MX/src/main/flex/mx/managers/ToolTipManagerImpl.as @@@ -1,1760 -1,0 +1,1760 @@@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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 +{ - COMPILE::AS3 ++COMPILE::SWF +{ + import flash.display.DisplayObject; + import flash.events.TimerEvent; +} +COMPILE::JS +{ + import mx.managers.SystemManagerGlobals; + + import flex.display.DisplayObject; + import flex.events.TimerEvent; +} +import org.apache.flex.events.Event; +import org.apache.flex.events.EventDispatcher; +import org.apache.flex.events.MouseEvent; +import org.apache.flex.geom.Point; +import org.apache.flex.geom.Rectangle; +import org.apache.flex.utils.PointUtils; +import org.apache.flex.utils.Timer; + +import mx.controls.ToolTip; +import mx.core.FlexGlobals; +import mx.core.FlexVersion; +import mx.core.IFlexDisplayObject; +import mx.core.IFlexModule; +import mx.core.IInvalidating; +import mx.core.ILayoutDirectionElement; +import mx.core.IToolTip; +import mx.core.IUIComponent; +import mx.core.IVisualElement; +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.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")); + + COMPILE::JS + { + SystemManagerGlobals.topLevelSystemManagers[0].addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler, true); + } + } + + //-------------------------------------------------------------------------- + // + // 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. + * + * <p>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. + * + * <p>This timer, which is lazily created, is started + * when the showEffect ends. + * When it fires, the hideEffect is started.</p> + */ + mx_internal var hideTimer:Timer; + + /** + * @private + * This timer is used to implement mousing quickly over multiple targets + * with ToolTip... + * + * <p>This timer, which is lazily created, is started + * when ...</p> + */ + 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 the <code>currentTarget</code> 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 <code>null</code> 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 <code>null</code> 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 <code>true</code>, the ToolTipManager will automatically show + * ToolTips when the user moves the mouse pointer over components. + * If <code>false</code>, 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 <code>hideDelay</code> to <code>Infinity</code>, + * 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 <code>null</code> if the ToolTip should disappear with no effect. + * + * <p>Effects are not marshaled across applicationDomains in a sandbox + * as they may not be supportable in different versions</p> + * + * @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 of <code>showDelay</code> to display a ToolTip. + * + * <p>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 <code>scrubDelay</code>, the more + * likely that the user must wait for an amount of time specified + * by <code>showDelay</code> 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.</p> + * + * @default 100 + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public function get scrubDelay():Number + { + return _scrubDelay; + } + + /** + * @private + */ + public function set scrubDelay(value:Number):void + { + _scrubDelay = value; + } + + //---------------------------------- + // showDelay + //---------------------------------- + + /** + * @private + */ + private var _showDelay:Number = 500; // milliseconds + + /** + * The amount of time, in milliseconds, that Flex waits + * before displaying the ToolTip box once a user + * moves the mouse over a component that has a ToolTip. + * To make the ToolTip appear instantly, set <code>showDelay</code> 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 <code>null</code> if the ToolTip should appear with no effect. + * + * <p>Effects are not marshaled across applicationDomains in a sandbox + * as they may not be supportable in different versions</p> + * + * @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. + * + * <p>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</p> + * + * @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. + * + * <p>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.</p> + * + * <p>This method is called by targetChanged(); Flex waits to initialize + * the class until mouse-tracking happens in order to optimize + * startup time.</p> + */ + 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. + * + * <p>This method is called by the setter + * for the toolTip property in UIComponent and UITextField.</p> + * + * @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(); + } + } + + /** + * 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. + * + * <p>This method is called by the setter + * for the errorString property in UIComponent.</p> + * + * @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(); + } + } + + /** + * @private + * Returns true if the mouse is over the specified target. + */ + private function mouseIsOver(target:DisplayObject):Boolean + { - COMPILE::AS3 ++ COMPILE::SWF + { + 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; + + if (target is IVisualElement && !IVisualElement(target).visible) + return false; + + if (target is IFlexDisplayObject && !IFlexDisplayObject(target).visible) + return false; + + if (!isVisibleParentsIncluded(target)) + return false; + + return target.hitTestPoint(target.stage.mouseX, + target.stage.mouseY, true); + } + COMPILE::JS + { + var screenPos:Point = new Point(target.x, target.y); + screenPos = PointUtils.localToGlobal(screenPos, target); + var screenX:Number = lastMouseEvent.screenX; + var screenY:Number = lastMouseEvent.screenY; + return ((screenPos.x <= screenX && screenX <= screenPos.x + target.width) && + (screenPos.y <= screenY && screenY <= screenPos.y + target.height)); + } + } + + /** + * @private + * <p>Determines if the UIComponent and the parents in the hierarchy + * are visible, if yes return true, otherwise returns false.</p> + * + * @param target DisplayObject + * @return Boolean true is all parents are visible, false if one of them is invisible + */ + private static function isVisibleParentsIncluded(target:DisplayObject):Boolean + { + if (target == null) return false; + return isTopLevelApplication(target) ? target.visible : + target.visible && isVisibleParentsIncluded(target.parent); + } + + /** + * @private + * + * <p>Determines if the target is topLevelApplication and + * returns true if yes, otherwise false + * + * @param target UIComponent + * @return Boolean true is is topLevelApplication, otherwise false + */ + private static function isTopLevelApplication(target:DisplayObject):Boolean + { + return target == FlexGlobals.topLevelApplication; + } + + /** + * @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():void + { + checkIfTargetChanged(null); + } + + /** + * Replaces the ToolTip, if necessary. + * + * <p>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.</p> + * + * @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 the <code>displayObject</code> object up the chain + * of parent objects until it finds a UIComponent or UITextField object + * with a <code>toolTip</code> or <code>errorString</code> property. + * Treats an empty string as a valid <code>toolTip</code> property. + * Sets the <code>currentTarget</code> 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 <code>currentTarget</code> 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. + * + * <p>If the ToolTipManager's <code>enabled</code> property is + * <code>true</code> this method is automatically called + * when the user moves the mouse over an object that has + * the <code>toolTip</code> property set, + * The ToolTipManager makes subsequent calls to + * <code>initializeTip()</code>, <code>positionTip()</code>, + * and <code>showTip()</code> to complete the display + * of the ToolTip.</p> + * + * <p>The type of ToolTip that is created is determined by the + * <code>toolTipClass</code> 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).</p> + * + * <p>After creating the ToolTip with the <code>new</code> + * operator, this method stores a reference to it in the + * <code>currentToolTip</code> property. + * It then uses addChild() to add this ToolTip to the + * SystemManager's toolTips layer.</p> + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + mx_internal function createTip():void + { + // Dispatch a "createToolTip" event + // from the object displaying the tooltip. + var event:ToolTipEvent = + new ToolTipEvent(ToolTipEvent.TOOL_TIP_CREATE); + currentTarget.dispatchEvent(event); + + if (event.toolTip) + currentToolTip = event.toolTip; + else + currentToolTip = new toolTipClass(); + + currentToolTip.visible = false; + + // Set the tooltip to be in the same module factory as the target to the + // correct style manager is used. Don't overwrite an existing module factory. + if (currentToolTip is IFlexModule && IFlexModule(currentToolTip).moduleFactory == null && + currentTarget is IFlexModule) + IFlexModule(currentToolTip).moduleFactory = IFlexModule(currentTarget).moduleFactory; + + COMPILE::LATER + { + if (hasEventListener("createTip")) + if (!dispatchEvent(new Event("createTip", false, true))) + return; + } + + var sm:ISystemManager = getSystemManager(currentTarget) as ISystemManager; + sm.topLevelSystemManager.toolTipChildren.addChild(currentToolTip as DisplayObject); + } + + /** + * Initializes a newly created ToolTip with the appropriate text, + * based on the object under the mouse. + * + * <p>If the ToolTipManager's <code>enabled</code> property is + * <code>true</code> this method is automatically called + * when the user moves the mouse over an object that has + * the <code>toolTip</code> property set. + * The ToolTipManager calls <code>createTip()</code> before + * this method, and <code>positionTip()</code> and + * <code>showTip()</code> after.</p> + * + * <p>If a normal ToolTip is being displayed, this method + * sets its text as specified by the <code>toolTip</code> + * property of the object under the mouse. + * If an error tip is being displayed, the text is as + * specified by the <code>errorString</code> property + * of the object under the mouse.</p> + * + * <p>This method also makes the ToolTip the appropriate + * size for the text that it needs to display.</p> + * + * @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. + * + * <p>If the ToolTipManager's <code>enabled</code> property is + * <code>true</code> this method is automatically called + * when the user moves the mouse over an object that has + * the <code>toolTip</code> property set. + * The ToolTipManager calls <code>createTip()</code> and + * <code>initializeTip()</code> before this method, + * and <code>showTip()</code> after.</p> + * + * <p>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 = PointUtils.localToGlobal(pos, sm); + COMPILE::LATER + { + pos = PointUtils.globalToLocal(pos, sm.getSandboxRoot()); + } + x = pos.x; + y = pos.y; + } + + currentToolTip.move(x, y); + } + + /** + * Shows a newly created, initialized, and positioned ToolTip. + * + * <p>If the ToolTipManager's <code>enabled</code> property is + * <code>true</code> this method is automatically called + * when the user moves the mouse over an object that has + * the <code>toolTip</code> property set. + * The ToolTipManager calls <code>createTip()</code>, + * <code>initializeTip()</code>, and <code>positionTip()</code> + * before this method.</p> + * + * <p>This method first dispatches a <code>"showToolTip"</code> + * 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 <code>showEffect</code> 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. + * + * <p>ToolTips appear in their own layer, on top of everything + * except cursors.</p> + * + * <p>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 <code>toolTip</code> property set. + * You can turn off this automatic ToolTip management by setting + * the ToolTipManager's <code>enabled</code> property to + * <code>false</code>.</p> + * + * <p>By contrast, this method—along with <code>hideToolTip()</code>—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).</p> + * + * <p>This method first creates a new instance of ToolTip and calls the + * <code>addChild()</code> 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.</p> + * + * <p>You must save the reference to the ToolTip that this method + * returns so that you can pass it to the <code>hideToolTip()</code> method.</p> + * + * @param text The text to display in the ToolTip instance. + * + * @param x The horizontal coordinate of the ToolTip in stage coordinates. + * In case of multiple stages, the relevant stage is determined + * from the <code>context</code> argument. + * + * @param y The vertical coordinate of the ToolTip in stage coordinates. + * In case of multiple stages, the relevant stage is determined + * from the <code>context</code> 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 <code>createToolTip()</code> method creates a normal ToolTip. If it is + * "errorTipRight", "errorTipAbove", or "errorTipBelow", then the <code>createToolTip()</code> + * 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 <code>createToolTip()</code> method. + * + * <p>This method calls the <code>removeChild()</code> 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.</p> + * + * <p>You should not call this method on the ToolTipManager's + * <code>currentToolTip</code>.</p> + * + * @param toolTip The ToolTip instance to destroy. + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public function destroyToolTip(toolTip:IToolTip):void + { + var e:DynamicEvent; + if (hasEventListener("removeChild")) + { + e = new DynamicEvent("removeChild", false, true); + e.sm = toolTip.systemManager; + e.toolTip = toolTip; + } + if (!e || dispatchEvent(e)) + { + // Remove it. + var sm:ISystemManager = toolTip.systemManager as ISystemManager; + sm.topLevelSystemManager.toolTipChildren.removeChild(toolTip as DisplayObject); + } + + // hide effect? + } + + /** + * @private + */ + mx_internal function showEffectEnded():void + { + if (hideDelay == 0) + { + hideTip(); + } + else if (hideDelay < Infinity) + { + hideTimer.delay = hideDelay; + hideTimer.start(); + } + if (currentTarget) + { + // Dispatch a "toolTipShown" event + // from the object displaying the tooltip. + var event:ToolTipEvent = + new ToolTipEvent(ToolTipEvent.TOOL_TIP_SHOWN); + event.toolTip = currentToolTip; + currentTarget.dispatchEvent(event); + } + } + + /** + * @private + */ + mx_internal function hideEffectEnded():void + { + reset(); + // Dispatch a "toolTipEnd" event + // from the object that was displaying the tooltip. + if (previousTarget) + { + var event:ToolTipEvent = + new ToolTipEvent(ToolTipEvent.TOOL_TIP_END); + event.toolTip = currentToolTip; + previousTarget.dispatchEvent(event); + } + } + + /** + * @private + */ + mx_internal function getSystemManager( + target:DisplayObject):ISystemManager + { + return target is IUIComponent ? + IUIComponent(target).systemManager : + null; + } + + /** + * @private + */ + private static function getGlobalBounds(obj:DisplayObject, + parent:DisplayObject, + mirror:Boolean):Rectangle + { + var upperLeft:Point = new Point(0, 0); + + upperLeft = PointUtils.localToGlobal(upperLeft, obj); + + // If the layout has been mirrored, then the 0,0 is the uppper + // right corner; compensate here. + if (mirror) + upperLeft.x -= obj.width; + + upperLeft = PointUtils.globalToLocal(upperLeft, obj); + + return new Rectangle(upperLeft.x, upperLeft.y, obj.width, obj.height); + } + + //-------------------------------------------------------------------------- + // + // Event handlers + // + //-------------------------------------------------------------------------- + + /** + * @private + * This handler is called when the mouse moves over an object + * with a toolTip. + */ + mx_internal function toolTipMouseOverHandler(event:MouseEvent):void + { + checkIfTargetChanged(DisplayObject(event.target)); + } + + /** + * @private + * This handler is called when the mouse moves out of an object + * with a toolTip. + * @flexjsignorecoercion flex.display.DisplayObject + */ + mx_internal function toolTipMouseOutHandler(event:MouseEvent):void + { + checkIfTargetChanged(event.relatedObject as DisplayObject); + } + + /** + * @private + * This handler is called when the mouse moves over an object + * with an errorString. + */ + mx_internal function errorTipMouseOverHandler(event:MouseEvent):void + { + checkIfTargetChanged(DisplayObject(event.target)); + } + + /** + * @private + * This handler is called when the mouse moves out of an object + * with an errorString. + * @flexjsignorecoercion flex.display.DisplayObject + */ + mx_internal function errorTipMouseOutHandler(event:MouseEvent):void + { + checkIfTargetChanged(event.relatedObject as DisplayObject); + } + + /** + * @private + * This handler is called when the showTimer fires. + * It creates the tooltip and starts its showEffect. + */ + mx_internal function showTimer_timerHandler(event:TimerEvent):void + { + // Make sure we still have a currentTarget when the timer fires. + if (currentTarget) + { + createTip(); + initializeTip(); + positionTip(); + showTip(); + } + } + + /** + * @private + * This handler is called when the hideTimer fires. + * It starts the hideEffect. + */ + mx_internal function hideTimer_timerHandler(event:TimerEvent):void + { + hideTip(); + } + + /** + * @private + * This handler is called when the showEffect or hideEffect ends. + * When the showEffect ends, it starts the hideTimer, + * which will automatically start hiding the tooltip when it fires, + * even if the mouse is still over the target. + * When the hideEffect ends, the tooltip is removed. + */ + mx_internal function effectEndHandler(event:EffectEvent):void + { + if (event.effectInstance.effect == showEffect) + showEffectEnded(); + else if (event.effectInstance.effect == hideEffect) + hideEffectEnded(); + } + + /** + * @private + * This handler is called when the user clicks the mouse + * while a normal tooltip is displayed. + * It immediately hides the tooltip. + */ + mx_internal function systemManager_mouseDownHandler(event:MouseEvent):void + { + reset(); + } + + /** + * @private + */ + mx_internal function changeHandler(event:Event):void + { + reset(); + } + + COMPILE::JS + private var lastMouseEvent:MouseEvent; + + COMPILE::JS + private function mouseMoveHandler(event:MouseEvent):void + { + lastMouseEvent = event; + } + +} + +}
