Wednesday, April 22, 2009

AS3 ToolTip





I've been busy living my other life as a programmer and haven't done too much drawing... I'm busy at work on a project that allows you to do lots of drawing over the Internet but I can't tell you anymore than that. But I want to share something with everyone. Here's a super lightweight AS3 ToolTip class that's easy to use and easy to customize. It uses some neat tricks too so if you want to learn some AS3 black magic take a close look.

Tooltip.as

package {

import flash.display.Sprite;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.text.TextFieldAutoSize;
import flash.text.TextLineMetrics;
import flash.display.BlendMode;
import flash.utils.Timer;
import flash.events.MouseEvent;

public class ToolTip extends Sprite {

private var _tip:String;

// You'll need this for proper text formatting
private var _tf:TextField = new TextField();
private var _format:TextFormat = new TextFormat();

private static const ROUND:Number = 2;
private static const HEIGHT:Number = 25;
private static const FONT_SIZE:uint = 14;
private static const FONT:String = 'Arial';
private static const PADDING:Number = 5;
private static const MIN_ALPHA:Number = .00;
private static const ALPHA_INC:Number = .05;
private static const MAX_ALPHA:Number = .75;
private static const REFRESH:Number = MAX_ALPHA / ALPHA_INC;

// For fading in and out
private var _timer:Timer;

public function ToolTip( tip:String ) {

// Hold onto the tip for posterity
_tip = tip;

// This ensures the textfield inherits this class's
// alpha property. Very important because otherwise tf
// would always have an alpha of 1 meaning it will always be visible
this.blendMode = BlendMode.LAYER;

_format.size = FONT_SIZE;
_format.font = FONT;

// Make sure the text behaves and looks
// the way text on a button should
_tf.defaultTextFormat = _format; // Always call defaultTextFormat before setting text otherwise
// the text doesn't use the formatting defined in tf

_tf.autoSize = TextFieldAutoSize.LEFT; // You have to set autoSize to TextFieldAutoSize.LEFT
// for box.textWidth to be accurate
_tf.multiline = false;
_tf.text = tip;
_tf.selectable = false;
_tf.x += PADDING;
_tf.y += PADDING;
addChild( _tf );

// Draw the background
graphics.beginFill( 0xFFFFFF, 1 );
graphics.drawRoundRect( 0, 0, _tf.textWidth+PADDING*4, HEIGHT, ROUND );
graphics.endFill();
this.alpha = MIN_ALPHA;
}

// You have to call this after
// the tooltip has been added to the
// display list
public function start():void {
this.parent.addEventListener( MouseEvent.MOUSE_OVER, mouse_over );
}

public function mouse_over( e:MouseEvent ):void {
this.parent.setChildIndex( this, this.parent.numChildren-1 ) // Move the tool tip to the top!
var fadeSpeed:Number = 500 / REFRESH;
_timer = new Timer( fadeSpeed, REFRESH );
_timer.addEventListener( "timer", fadeIn )
_timer.start();
this.parent.addEventListener( MouseEvent.MOUSE_OUT, mouse_out );
}

public function mouse_out( e:MouseEvent ):void {
var fadeSpeed:Number = 500 / REFRESH;
_timer = new Timer( fadeSpeed, REFRESH );
_timer.addEventListener( "timer", fadeOut )
_timer.start();
}

private function fadeIn( i:uint ):void {
this.alpha += ALPHA_INC;
}

private function fadeOut( i:uint ):void {
this.alpha -= ALPHA_INC;
}
}
}


Using it in your code is this easy.

// Construct a tooltip
var toolTip:ToolTip = new ToolTip( 'This thingy does remarkable things when pressed' );

// Add the tooltip to the display object you want to give a tip about
thingy.addChild( toolTip );

// Start the tooltip
toolTip.start();

8 comments:

Luana Moura said...

Hi!! thanks for this tutorial! But i had a problem,

I received this message: "1137: Incorrect number of arguments. Expected no more than 0."

on this line:
var toolTip:ToolTip = new ToolTip( 'test' );

Adam Tavares said...

I don't know why you would get that error. The ToolTip constructor you're calling needs exactly one argument.

public function ToolTip( tip:String ) {

I'd double check the syntax of the rest of your code.

Good luck!

Unknown said...

Hello, thanks for sharing that. It seems very nice but it is not working.
I put the as file in the same folder of the .fla file.
I get the following errors:

1046: Type was not found or was not a compile-time constant:
1180: Call to a possibly undefined method ToolTip.ToolTip.
1061: Call to a possibly undefined method addChild through a reference with static type flash.display:SimpleButton.

Is it a referencing error ?
Thanks!
Zac

Adam Tavares said...

zac.

I use the Flex command line compiler on my projects. You're using the Flash authoring environment. Importing classes are a little different between the two so what you need to do is remove the lines 'package {' and the closing brace on the final line '}'.

Then you'll need to add this line to your actions 'import ToolTip.as'.

You can read more about this here.

http://livedocs.adobe.com/flash/8/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00001310.html

beBopper said...

This doesn't work in Flash CS3 AS3.

If you "import tooltip.as" it says: 1084: Syntax error: expecting identifier before as.

If you "import tooltip" you don't get an error, but then when you try to use it, you get the error: 1180: Call to a possibly undefined method ToolTip.

beBopper said...

removing package { and the last } had no effect.

1046: Type was not found or was not a compile-time constant: ToolTip.
1180: Call to a possibly undefined method ToolTip.
1061: Call to a possibly undefined method addChild through a reference with static type flash.text:TextField.

Anonymous said...

Excuse my english.... i had problems with this code. "Type was not found or was not a compile-time constant: ToolTip" It's because the class name ToolTip have a capital letter in the middle. I change the name of the class for Tooltip and it's works very well. Thank you!!

William said...

How do i stop the transparent problem with tool tip?