Home Contact

[September 12, 2005]

I Gotcha ToolTip Right Heah

Filed under: ActionScript — @ 4:01 pm

I was glad to see the latest in Lee Brimelow’s great series of video Flash tutorials, this one on making tooltips in Flash. I’d been meaning to implement tooltips in my current project for a while, and this got me going. But you know I always prefer to do it in code that I can reuse anywhere, and not depend on library assets if I can help it. And tooltip is a prime candidate for implementation with a Singleton class, so…


import ascb.util.Proxy;

class com.nodename.utils.ToolTip
{
static var version:String = "$Id: ToolTip.as,v 1.9 2006/03/26 18:14:15 ashaw Exp $";

public static function setBoxSize(wd:Number, ht:Number):Void
{
	ToolTip._boxWidth = wd;
	ToolTip._boxHeight = ht;
}

public static function setPointSize(ps:Number):Void
{
	ToolTip._pointSize = ps;
}

/*
 *
 * @function	create
 * @param	tipTarget	the object over which the tooltip is to be shown:
 * 				MovieClip, MCComposite, or Button
 * @param	tip		the text to be displayed in the ToolTip
 *
 */
public static function create(tipTarget, tip:String):Void
{
	tipTarget.onRollOver = Proxy.create(ToolTip, ToolTip.showToolTip, tip);
	tipTarget.onRollOut = tipTarget.onDragOut = ToolTip.hideToolTip;
}

/////////////////////////////////////////
//                                     //
//       End of public interface       //
//                                     //
/////////////////////////////////////////

private static var theOnlyToolTip:ToolTip;

private static function showToolTip(tip:String):Void
{
	if (theOnlyToolTip == undefined)
	{
		theOnlyToolTip = new ToolTip();
	}
	theOnlyToolTip.p_showToolTip(tip);
}

private static function hideToolTip():Void
{
	if (theOnlyToolTip == undefined)
	{
		theOnlyToolTip = new ToolTip();
	}
	theOnlyToolTip.p_hideToolTip();
}

private var _mc:MovieClip;
private var _tf:TextField;
private var _tFormat:TextFormat;

private static var _boxWidth:Number = 150;
private static var _boxHeight:Number = 50;

private static var _pointSize:Number = 10;

private var _tailLeft:Number;		// distance from left edge of box to left edge of tail
private var _tailWidth:Number;
private var _tailHeight:Number;
private var _tailTipOffset:Number;	// tip of tail is this far above registration point
private var _textSideMargin:Number;

private var topY:Number;
private var leftX:Number;

private function ToolTip()
{
	_tailLeft = .40 * ToolTip._boxHeight;
	_tailWidth = .40 * ToolTip._boxHeight;
	_tailHeight = .60 * ToolTip._boxHeight;
	_tailTipOffset = 5;
	_textSideMargin = 5;

	var trueParent:MovieClip = _level0;	// it has to live somewhere...

	this._mc = trueParent.createEmptyMovieClip("nodenameToolTip", trueParent.getNextHighestDepth());

	this._mc._visible = false;

	leftX = -this._tailLeft;
	topY  = -ToolTip._boxHeight - this._tailHeight - this._tailTipOffset;

	this.draw(leftX, topY, ToolTip._boxWidth, ToolTip._boxHeight, this._tailWidth, this._tailTipOffset);

	this.makeTextField(leftX, topY, ToolTip._boxWidth, ToolTip._boxHeight);
}

private function draw(leftX:Number, topY:Number, boxWidth:Number, boxHeight:Number,
			tailWidth:Number, tailTipOffset:Number):Void
{
// TODO:	make rounded corners

	var rightX:Number	= leftX + boxWidth;
	var bottomY:Number	= topY + boxHeight;

	with (this._mc)
	{
		moveTo(leftX, topY);
		lineStyle(1, 0x000000, 100); // black
		beginGradientFill(
				"linear",
				[0xfff3d9, 0xfffbf2],	// colors
				[100, 100],		// alphas
				[0, 255],		// ratios
				{
					matrixType:"box",
					x: leftX, y: topY,
					w: boxWidth, h: boxHeight,
					r: Math.PI/2	// 90 degrees: vertical gradient
				}
				);
		lineTo(rightX, topY);
		lineTo(rightX, bottomY);
		lineTo(tailWidth, bottomY);
		lineTo(0, -tailTipOffset);	// tip of tail
		lineTo(0, bottomY);
		lineTo(leftX, bottomY);
		lineTo(leftX, topY);
		endFill();
	}
}

private function makeTextField(leftX:Number, topY:Number, boxWidth:Number, boxHeight:Number):Void
{
	this._mc.createTextField("_tf", this._mc.getNextHighestDepth(),
				leftX, topY, boxWidth, boxHeight);
	this._tf = this._mc._tf;
	this._tFormat = new TextFormat("_sans", ToolTip._pointSize, 0×000000);
	this._tFormat.align = "center";
	this._tFormat.leftMargin = this._tFormat.rightMargin = this._textSideMargin;
	this._tf.setNewTextFormat(this._tFormat);
	this._tf.wordWrap = true;
	this._tf.autoSize = "none";
}

private var _toolTipIntervalID:Number;
private var _toolTipDelay:Number = 500; // milliseconds

private function p_showToolTip(tip:String):Void
{
	this._toolTipIntervalID = setInterval(this, "reallyShowToolTip", this._toolTipDelay, tip);
}

private function reallyShowToolTip(tip:String):Void
{
	clearInterval(this._toolTipIntervalID);

	this._tf.text = tip;
	updateToolTip();
	this._mc._visible = true;

	this._mc.onMouseMove = Proxy.create(this, updateToolTip);
}

private function updateToolTip():Void
{
	setFlip();

	this._mc._x = this._mc._parent._xmouse;
	this._mc._y = this._mc._parent._ymouse;

	updateAfterEvent();
}

public function setFlip():Void
{
	var loc:Object = {x: this._mc._xmouse, y: this._mc._ymouse};
	this._mc.localToGlobal(loc);
	if (loc.y + topY < 5)
	{
		flipY();
	}
	else
	{
		unflipY();
	}
	if (loc.x + leftX + ToolTip._boxWidth > Stage.width - 5)
	{
		flipX();
	}
	else
	{
		unflipX();
	}
}

private function flipY():Void
{
	this._mc._yscale = -100;
	this._tf._yscale = -100;
	this._tf._y = topY + ToolTip._boxHeight;
}

private function unflipY():Void
{
	this._mc._yscale = 100;
	this._tf._yscale = 100;
	this._tf._y = topY;
}

private function flipX():Void
{
	this._mc._xscale = -100;
	this._tf._xscale = -100;
	this._tf._x = leftX + ToolTip._boxWidth;
}

private function unflipX():Void
{
	this._mc._xscale = 100;
	this._tf._xscale = 100;
	this._tf._x = leftX;
}

private function p_hideToolTip():Void
{
	clearInterval(this._toolTipIntervalID);
	this._mc._visible = false;
	delete this._mc.onMouseMove;
}

}

8 Comments »

  1. …thanks for this great expansion on Lee’s tutorial. This is very useful code to me (and I’m guessing many others).
    Many thanks-
    Mark Holton

    Comment by Mark Holton — September 12, 2005 @ 5:34 pm

  2. Awesome work! I wish there was a way for me to do a tutorial that goes into this much depth, but it would probably be around 2 hours long :-)

    Comment by Lee Brimelow — September 12, 2005 @ 5:35 pm

  3. Hi nodename, nice work. In testing your code, I’m getting one error:

    **Error** src/com/nodename/utils/ToolTip.as: Line 127: The same member name may not be repeated more than once.
    private function showToolTip(tip:String):Void

    **Error** src/com/nodename/utils/ToolTip.as: Line 150: The same member name may not be repeated more than once.
    private function hideToolTip():Void

    Is it a singleton thing perhaps?

    Comment by Shi11 — December 10, 2005 @ 5:07 pm

  4. No, actually at the time I wrote this the mtasc compiler allowed a class to have a static method and an instance method with the same name! That’s been changed, and I think the Flash compiler never allowed it. You’re the first to notice this!

    So I’ve updated the code above. The new version also takes care of flipping the tooltip if it’s too close to the top or right edge of the window.

    Comment by alan — December 10, 2005 @ 8:32 pm

  5. Nice. Can I post another question about this class? In the showToolTip function pasted below, trace “1″ is never triggered. For me, the ToolTip isn’t created until the second time I rollOver a button. Seth

    private static function showToolTip(tip:String):Void
    {
    trace(”0″);
    if (theOnlyToolTip == undefined)
    {
    trace(”1″);
    theOnlyToolTip = new ToolTip();
    }
    trace(”2″);
    theOnlyToolTip.p_showToolTip(tip);
    }

    Comment by Shi11 — December 11, 2005 @ 4:06 am

  6. I’m sorry, Seth, I haven’t seen that behavior here. Trace 1 is _never_ triggered?

    Comment by alan — December 12, 2005 @ 1:15 am

  7. [...] FlashCodersNY recently aquired a copy of Captivate. Now we can create video tutorials with screen capture. Our own Alan Shaw has created the first of many AS2 and AS3 tutorials using Captivate. Special thanks to Alan for his tooltip demo ( stay tuned for part 2 ). [...]

    Pingback by » Blog Archive » Captivate Tutorials. Oh My ! — June 10, 2006 @ 10:49 am

  8. [...] http://nodename.com/blog/2005/09/12/tooltip/  [...]

    Pingback by Actionscript Classes » ToolTip — August 29, 2006 @ 7:40 pm

RSS feed for comments on this post. TrackBack URI

Leave a comment


Contents copyright © Alan Shaw 2005-2008

25 queries. 0.274 seconds. Powered by WordPress version 2.5.1