Tuesday, November 13, 2012

Creating EasyTooltip class: Part 12

In this tutorial we will improve our positioning and sizing algorithm.

Before we start, I'd like to give the code in the main.as class, which is being used to test out examples:

var myStyle:TooltipStyle = new TooltipStyle();
myStyle.minWidth = 240;
myStyle.maxWidth = 300;
myStyle.offsetX = -10;
myStyle.offsetY = -10;

tooltip = new EasyTooltip(stage, stage.stageWidth, stage.stageHeight);
tooltip.setStyle(myStyle);
tooltip.addListener(object1, "This is a piece of a longer text. It should fit in the visible area.");

Go to the TooltipCursor class and find the updateSize() function.

The first change we'll make is related to direction calculation. In the part where we choose whether to go bottom or top, change parentH to h-style.offsetY. This will make sure that the tooltip is displayed below the cursor only when absolutely necessary.

// calculate best direction
if (this.y <= h-style.offsetY) { 
direction = "bottom"; 
actual_y = -style.offsetY;
} else
if (this.y > h-style.offsetY) { 
direction = "top";
actual_y = -h + style.offsetY;
}

Now in the if...statement that has "topright" and "bottomright" in the conditional, add "+ style.offsetX" in the line that calculates this.x if width is less than style's minWidth. Then, in the conditional of the while loop, also check if width is less than style.maxWidth and is greater than or equals minWidth. Check the same inside the if...statement in that while loop.

// If sticks out on the right:
if(direction == "topright" || direction == "bottomright"){
// if tooltip sticks out of border - calculate shortened width to fit the content
if (this.x + actual_x + w > parentW) {
txt.wordWrap = true;
w = parentW - this.x - actual_x;
h = txt.textHeight + 4 + style.textPadding.top + style.textPadding.bottom;
if (w > style.maxWidth) w = style.maxWidth;
if (h > style.maxHeight) h = style.maxHeight;
if (w < style.minWidth) {
w = style.minWidth;
this.x = parentW - w + style.offsetX;
}
if (h < style.minHeight) h = style.minHeight;
} else {
// if doesn't stick out, keep adding 1 pixel to the width until as much text is seen as possible
while (this.x + actual_x + w < parentW && w < style.maxWidth && w >= style.minWidth) {
w += 1;
// try turning off wordwrap and see if it still fits (as one line)
txt.wordWrap = false;
if (w > txt.textWidth + 4 + style.textPadding.left + style.textPadding.right && w > style.minWidth && w < style.maxWidth) {
w = txt.textWidth + 4 + style.textPadding.left + style.textPadding.right;
break;
}
txt.wordWrap = true;
}
}
}

In the "topleft" and "bottomleft" part, add the same conditions in the while loop and in the if..statement which is inside the while loop:

// If sticks out on the left:
if(direction == "topleft" || direction == "bottomleft"){
if (this.x + actual_x <= 0) {
txt.wordWrap = true;
actual_x = -this.x;
w = this.x + style.offsetX;
h = txt.textHeight + 4 + style.textPadding.top + style.textPadding.bottom;
if (w > style.maxWidth) w = style.maxWidth;
if (h > style.maxHeight) h = style.maxHeight;
if (w < style.minWidth) w = style.minWidth;
if (h < style.minHeight) h = style.minHeight;
} else {
// if doesn't stick out, keep adding 1 pixel to the width (and substracting it from actual_x) until as much text is seen as possible
while (this.x + actual_x > 0 && w < style.maxWidth && w >= style.minWidth) {
actual_x -= 1;
w += 1;
// try turning off wordwrap and see if it still fits (as one line)
txt.wordWrap = false;
if (w > txt.textWidth + 4 + style.textPadding.left + style.textPadding.right && w > style.minWidth && w <= style.maxWidth) {
w = txt.textWidth + 4 + style.textPadding.left + style.textPadding.right;
break;
}
txt.wordWrap = true; 
}
}
}

Full class code so far:

package com.kircode.EasyTooltip 
{
import flash.display.MovieClip;
import flash.display.Shape;
import flash.text.TextField;
import flash.text.TextFormat;
/**
 * The cursor that follows the mouse (if not set otherwise) and displays each tooltip.
 * @author Kirill Poletaev
 */
public class TooltipCursor extends MovieClip
{

public var txt:TextField;
private var style:TooltipStyle;
private var background:Shape;
private var w:int;
private var h:int;
private var actual_x:int;
private var actual_y:int;
private var parentW:int;
private var parentH:int;
private var direction:String = "";

public function TooltipCursor(pW:int, pH:int) 
{
parentW = pW;
parentH = pH;
txt = new TextField();
txt.multiline = true;
background = new Shape();
addChild(background);
addChild(txt);
}

/**
 * Set style of the tooltips.
 * @paramst TooltipStyle object to apply.
 */

public function setStyle(st:TooltipStyle):void {
style = st;
}

/**
 * Change the text value of the tooltip.
 * @parammessage The new text value.
 */

public function setText(message:String):void {
txt.text = message;
txt.setTextFormat(style.textFormat);
updateSize();
updateDisplay();
}

private function updateDisplay():void {
background.graphics.clear();
background.graphics.beginFill(style.backgroundColor, style.backgroundAlpha);
background.graphics.drawRect(actual_x, actual_y, w, h);
background.graphics.endFill();

txt.width = w - style.textPadding.left - style.textPadding.right;
txt.height = h - style.textPadding.top - style.textPadding.bottom;
txt.x = actual_x + style.textPadding.left;
txt.y = actual_y + style.textPadding.top;
}

private function updateSize():void {
if (style.maxWidth == 0) style.maxWidth = parentW;
if (style.maxHeight == 0) style.maxHeight = parentH;
txt.wordWrap = true;
w = txt.textWidth + 4 + style.textPadding.left + style.textPadding.right;
h = txt.textHeight + 4 + style.textPadding.top + style.textPadding.bottom;
if (w > style.maxWidth) w = style.maxWidth;
if (h > style.maxHeight) h = style.maxHeight;
if (w < style.minWidth) w = style.minWidth;
if (h < style.minHeight) h = style.minHeight;

// calculate best direction
if (this.y <= h-style.offsetY) { 
direction = "bottom"; 
actual_y = -style.offsetY;
} else
if (this.y > h-style.offsetY) { 
direction = "top";
actual_y = -h + style.offsetY;
}

if (this.x <= parentW * 0.5) { 
direction += "right"; 
actual_x = - style.offsetX;
} else
if (this.x > parentW * 0.5) { 
direction += "left";
actual_x = -w + style.offsetX;
}

// If sticks out on the right:
if(direction == "topright" || direction == "bottomright"){
// if tooltip sticks out of border - calculate shortened width to fit the content
if (this.x + actual_x + w > parentW) {
txt.wordWrap = true;
w = parentW - this.x - actual_x;
h = txt.textHeight + 4 + style.textPadding.top + style.textPadding.bottom;
if (w > style.maxWidth) w = style.maxWidth;
if (h > style.maxHeight) h = style.maxHeight;
if (w < style.minWidth) {
w = style.minWidth;
this.x = parentW - w + style.offsetX;
}
if (h < style.minHeight) h = style.minHeight;
} else {
// if doesn't stick out, keep adding 1 pixel to the width until as much text is seen as possible
while (this.x + actual_x + w < parentW && w < style.maxWidth && w >= style.minWidth) {
w += 1;
// try turning off wordwrap and see if it still fits (as one line)
txt.wordWrap = false;
if (w > txt.textWidth + 4 + style.textPadding.left + style.textPadding.right && w > style.minWidth && w < style.maxWidth) {
w = txt.textWidth + 4 + style.textPadding.left + style.textPadding.right;
break;
}
txt.wordWrap = true;
}
}
}

// If sticks out on the left:
if(direction == "topleft" || direction == "bottomleft"){
if (this.x + actual_x <= 0) {
txt.wordWrap = true;
actual_x = -this.x;
w = this.x + style.offsetX;
h = txt.textHeight + 4 + style.textPadding.top + style.textPadding.bottom;
if (w > style.maxWidth) w = style.maxWidth;
if (h > style.maxHeight) h = style.maxHeight;
if (w < style.minWidth) w = style.minWidth;
if (h < style.minHeight) h = style.minHeight;
} else {
// if doesn't stick out, keep adding 1 pixel to the width (and substracting it from actual_x) until as much text is seen as possible
while (this.x + actual_x > 0 && w < style.maxWidth && w >= style.minWidth) {
actual_x -= 1;
w += 1;
// try turning off wordwrap and see if it still fits (as one line)
txt.wordWrap = false;
if (w > txt.textWidth + 4 + style.textPadding.left + style.textPadding.right && w > style.minWidth && w <= style.maxWidth) {
w = txt.textWidth + 4 + style.textPadding.left + style.textPadding.right;
break;
}
txt.wordWrap = true; 
}
}
}

}

}

}

Thanks for reading!

Here are the results:


No comments:

Post a Comment