Skip to content

Instantly share code, notes, and snippets.

@msamujlo
Created October 18, 2010 12:43
Show Gist options
  • Save msamujlo/632144 to your computer and use it in GitHub Desktop.
Save msamujlo/632144 to your computer and use it in GitHub Desktop.
/**
* ...
* @author Michal Samujlo
* @version 0.1
*/
package com.ydp.view {
import flash.display.DisplayObjectContainer;
import flash.display.MovieClip;
import flash.events.EventDispatcher;
import flash.events.MouseEvent;
import flash.events.Event;
/**
* Adds button behavior to movie clip
* Movie clip should have 3 frames - normal,over,down
*/
public class ButtonDecorator extends EventDispatcher
{
public static const CLICK:String = "click";
public static const DOWN:String = "down";
public static const OUT:String = "out";
public static const OVER:String = "over";
public var clip:MovieClip;
private var _wasDown:Boolean;
private var _wasUp:Boolean = false;
private var _enabled:Boolean = true;
// TODO Decorator powinien dodać skinMc do swojej display listy i dodawać się do parenta skinMc
public function ButtonDecorator( skinMc:MovieClip )
{
super();
if (!(skinMc is MovieClip)) {
throw new ArgumentError("parameter is not a MovieClip")
}
clip = skinMc;
clip.gotoAndStop(1);
clip.buttonMode = true;
clip.useHandCursor = true;
clip.mouseChildren = false;
clip.addEventListener(MouseEvent.ROLL_OVER,mOver);
clip.addEventListener(MouseEvent.ROLL_OUT,mOut);
clip.addEventListener(MouseEvent.MOUSE_DOWN,mDown);
clip.addEventListener(MouseEvent.MOUSE_UP, mUp);
clip.addEventListener(MouseEvent.CLICK, mClick);
}
public function mOver(event:MouseEvent):void
{
if (!_enabled) return;
clip.gotoAndStop(2);
dispatchEvent( new Event(OVER) );
}
public function mOut(event:MouseEvent):void
{
if (!_enabled) return;
clip.gotoAndStop(1)
dispatchEvent( new Event(OUT) );
}
public function mDown(event:MouseEvent):void
{
if (!_enabled) return;
_wasDown = true;
_wasUp = false;
clip.gotoAndStop(3);
dispatchEvent( new Event(DOWN) );
}
public function mUp(event:MouseEvent):void
{
if (!_wasDown || !_enabled) return;
_wasDown = false;
_wasUp = true;
clip.gotoAndStop(2);
dispatchEvent( new Event(CLICK) );
}
public function mClick(event:MouseEvent):void {
if (!_enabled) return;
if (!_wasUp) {
_wasDown = false;
clip.gotoAndStop(2);
dispatchEvent( new Event(CLICK) );
}
_wasUp = false;
}
public function set enabled(st:Boolean):void
{
var fr:int = st? 1 : 4;
if (fr > clip.totalFrames) {
fr = 1;
}
clip.gotoAndStop( fr );
_enabled = st;
clip.useHandCursor = st;
}
public function cleanUp():void {
clip.removeEventListener(MouseEvent.ROLL_OVER,mOver);
clip.removeEventListener(MouseEvent.ROLL_OUT,mOut);
clip.removeEventListener(MouseEvent.MOUSE_DOWN,mDown);
clip.removeEventListener(MouseEvent.MOUSE_UP, mUp);
}
}
}
var btn:MovieClip = new MyOwnMovieClipClass();
var bDecorator = new ButtonDecorator(btn);
var bDecorator.addEventListener(ButtonDecorator.CLICK, onButtonClicked);
var styleDecorator = new ThemeStyleDecorator(btn);
var new TooltipDecorator(btn, getTooltipForButton(btnName));
package com.ydp.view
{
import com.ydp.style.IStyleServer;
import com.ydp.style.StyleSelectorInfo;
import com.ydp.utils.ColorUtil;
import flash.display.DisplayObject;
import flash.display.MovieClip;
import flash.events.Event;
import flash.geom.ColorTransform;
import flash.text.TextField;
import pl.ydp.nexl.INexlExtensionDescription;
import pl.ydp.nexl.Nexl;
/**
* ThemeStyleDecorator searches decorated movie clip for instances named
* PrimaryTheme, SecondaryTheme or ContractTheme and applies to them color
* transformations based on colors defined in global styles: primaryThemeColor,
* primaryThemeAlpha, secondaryThemeColor, secondaryThemeAlpha, contrastThemeColor,
* contrastThemeAlpha, textThemeColor.
*
* To avoid querying IStyleServer for each decorated movie clip, styles are initialized only once
* and stored in static vars. This means IStyleServer instance must be ready when TSD is created!
*
* @throws Error "IStyleServer not found" is thrown if IStyleServer implementation wasn't found
* @author loleszczak
*/
public class ThemeStyleDecorator {
private static var _stylesInitialized:Boolean = false;
private static var _styleServer:IStyleServer
private static var _primaryThemeColor:int = -1;
private static var _primaryThemeAlpha:Number = 1;
private static var _secondaryThemeColor:int = -1;
private static var _secondaryThemeAlpha:Number = 1;
private static var _contrastThemeColor:int = -1;
private static var _contrastThemeAlpha:Number = 1;
private static var _textThemeColor:int = -1;
private static var _textThemeAlpha:Number = 1;
private var _maxThemeObjects:uint = 5;
private var _target:DisplayObject;
private var _originalColorInited:Boolean = false;
private var _originalTextColor:uint = 0;
public function ThemeStyleDecorator(target:DisplayObject) {
_target = target;
if(!_target){
return;
}
initializeStyles();
if (_target is MovieClip) {
for (var i:int = 0; i < MovieClip(_target).totalFrames; i++){
MovieClip(_target).addFrameScript(i, updateStyles );
}
} else if (_target is TextField) {
if (ThemeStyleDecorator._textThemeColor>0) {
TextField(_target).textColor = ThemeStyleDecorator._textThemeColor;
} else {
TextField(_target).textColor = _originalTextColor;
}
} else {
applyTint( _target, ThemeStyleDecorator._primaryThemeColor, ThemeStyleDecorator._primaryThemeAlpha);
}
}
private function initializeStyles():void
{
if (!ThemeStyleDecorator._stylesInitialized) {
var exts:Array = Nexl.library.list( { type: "com.ydp.style.IStyleServer" } );
if (exts.length == 0) {
throw new Error("ThemeStyleDecorator::initializeStyles IStyleServer not found");
}
var ext:INexlExtensionDescription = exts[0];
_styleServer = ext.create() as IStyleServer;
if (!_styleServer) {
throw new Error("ThemeStyleDecorator::initializeStyles IStyleServer not found");
}
stylesChanged();
_stylesInitialized = true;
}
if (_styleServer) {
_styleServer.addEventListener( Event.CHANGE, stylesChanged );
}
applyStyles();
}
protected function stylesChanged(event:Event=null):void {
var styleSelector:StyleSelectorInfo = new StyleSelectorInfo("presenterskin");
var styles:Object = _styleServer.getStyleDescriptionForSelector( styleSelector );
resetStyles();
if (styles.hasOwnProperty("primaryThemeColor"))
ThemeStyleDecorator._primaryThemeColor = styles.primaryThemeColor;
if (styles.hasOwnProperty("primaryThemeAlpha"))
ThemeStyleDecorator._primaryThemeAlpha = styles.primaryThemeAlpha;
if (styles.hasOwnProperty("secondaryThemeColor"))
ThemeStyleDecorator._secondaryThemeColor = styles.secondaryThemeColor;
if (styles.hasOwnProperty("secondaryThemeAlpha"))
ThemeStyleDecorator._secondaryThemeAlpha = styles.secondaryThemeAlpha;
if (styles.hasOwnProperty("contrastThemeColor"))
ThemeStyleDecorator._contrastThemeColor = styles.contrastThemeColor;
if (styles.hasOwnProperty("contrastThemeAlpha"))
ThemeStyleDecorator._contrastThemeAlpha = styles.contrastThemeAlpha;
if (styles.hasOwnProperty("textThemeColor"))
ThemeStyleDecorator._textThemeColor = styles.textThemeColor;
if (event) {
applyStyles();
}
}
protected function applyStyles():void {
if (_target is MovieClip) {
updateStyles();
} else if (_target is TextField) {
if (!_originalColorInited) {
_originalColorInited = true;
_originalTextColor = TextField(_target).textColor;
}
if (ThemeStyleDecorator._textThemeColor!=-1) {
TextField(_target).textColor = ThemeStyleDecorator._textThemeColor;
} else {
TextField(_target).textColor = _originalTextColor;
}
} else {
applyTint( _target, ThemeStyleDecorator._primaryThemeColor, ThemeStyleDecorator._primaryThemeAlpha);
}
}
protected function updateStyles():void {
updateTheme("PrimaryTheme", _primaryThemeColor, _primaryThemeAlpha);
updateTheme("SecondaryTheme", _secondaryThemeColor, _secondaryThemeAlpha);
updateTheme("ContrastTheme", _contrastThemeColor, _contrastThemeAlpha);
}
protected function resetStyles():void {
ThemeStyleDecorator._primaryThemeColor = -1;
ThemeStyleDecorator._primaryThemeAlpha = 1;
ThemeStyleDecorator._secondaryThemeColor = -1;
ThemeStyleDecorator._secondaryThemeAlpha = 1;
ThemeStyleDecorator._contrastThemeColor = -1;
ThemeStyleDecorator._contrastThemeAlpha = 1;
ThemeStyleDecorator._textThemeColor = -1;
}
protected function updateTheme(themeName:String, tintColor:Number, tintAlpha:Number):void {
var mc:MovieClip = _target[themeName];
if (mc) {
applyTint(mc, tintColor, tintAlpha);
}
for (var i:int = 0; i < _maxThemeObjects; i++){
mc = _target[themeName+String(i)];
if (mc) {
applyTint(mc, tintColor, tintAlpha);
}else {
break;
}
}
}
protected function applyTint(target:DisplayObject, color:int, alpha:Number):void {
var tint:ColorTransform = ColorUtil.setTint(color,alpha);
target.transform.colorTransform = tint;
}
}
}
package com.ydp.view
{
import flash.display.Sprite;
import com.ydp.view.TooltipDecorator;
import flash.display.Sprite;
import com.ydp.style.IStyleServer;
import com.ydp.style.IStyleClient;
import com.ydp.style.StyleSelectorInfo;
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.InteractiveObject;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import pl.ydp.nexl.Nexl;
import pl.ydp.nexl.INexlExtensionDescription;
/**
* ...
* @author loleszczak
*/
public class Tooltip extends Sprite
{
private var tf:TextField;
private var _mc:InteractiveObject;
public function Tooltip(mc:InteractiveObject, tooltip:String, autoSize:String = "") {
_mc = mc;
var exts:Array = Nexl.library.list( { type: "com.ydp.style.IStyleServer" } );
var ext:INexlExtensionDescription = exts[0];
var impl:IStyleServer = ext.create() as IStyleServer;
var styleSelector:StyleSelectorInfo = new StyleSelectorInfo();
var client:IStyleClient = impl.findNearestStyleClient( _mc );
if (client) {
styleSelector.styleType = client.styleType;
styleSelector.styleClass = client.styleClasses.concat();
styleSelector.styleIds = client.styleIds.concat();
styleSelector.stylePseudoClass = client.stylePseudoClasses.concat();
}
styleSelector.stylePseudoClass.push( "tooltip" )
var styles:Object = impl.getStyleDescriptionForSelector( styleSelector );
var embedFont:Boolean = String(styles.embedFont) == "true";
tf = new TextField();
tf.mouseEnabled = false;
tf.autoSize = autoSize ? autoSize : TextFieldAutoSize.CENTER;
tf.border = true;
tf.embedFonts = embedFont;
tf.borderColor = (styles.borderColor)? styles.borderColor : 0;
tf.background = true;
tf.backgroundColor = (styles.backgroundColor)? styles.backgroundColor : 0xFFFFFF;
var tfm:TextFormat = new TextFormat();
tfm.font = (styles.fontFamily)? styles.fontFamily : "Arial";
tfm.size = (styles.fontSize)? styles.fontSize : 10;
tfm.color = (styles.color)? styles.color : 0;
tfm.leftMargin = 2;
tfm.rightMargin = 2;
tf.defaultTextFormat = tfm;
tf.htmlText = tooltip;
tf.height = tf.textHeight + 4;
tf.mouseEnabled = false;
tf.x = 0;
tf.y = 0;
mouseEnabled = false;
addChild(tf);
}
}
}
package com.ydp.view
{
import com.ydp.view.TooltipDecorator;
import flash.display.Sprite;
import com.ydp.style.IStyleServer;
import com.ydp.style.IStyleClient;
import com.ydp.style.StyleSelectorInfo;
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.InteractiveObject;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.utils.setTimeout;
import pl.ydp.nexl.Nexl;
import pl.ydp.nexl.INexlExtensionDescription;
/**
* Adds tooltip behavior to MovieClip
* @author Łukasz Oleszczak
* @author Michał Samujło
*/
public class TooltipDecorator
{
public static var displayTime:uint = 0; //ms
public static var tooltipClass:Class = Tooltip;
private var _mc:InteractiveObject;
private var _text:Array;
private var _tooltip:Object;
private var _displayTime:Number = NaN;
private var _styleClass:String;
public function TooltipDecorator(mc:InteractiveObject, ... tooltips ):void {
if (!mc) {
return;
}
mc.addEventListener( MouseEvent.MOUSE_OVER, showTooltip, false, 0, false );
mc.addEventListener( MouseEvent.MOUSE_OUT, hideTooltip, false, 0, false );
mc.addEventListener( MouseEvent.CLICK, changeTooltip, false, 0, false );
this._mc = mc;
this._text = tooltips;
if (_text[0] == null) {
throw new Error("...no tooltips defined");
}
}
public function set styleClass(value:String):void {
_styleClass = value;
}
private function changeTooltip(e:MouseEvent):void {
hideTooltip();
showTooltip();
}
private function showTooltip(e:MouseEvent = null):void {
hideTooltip();
if (_mc.stage) {
_tooltip = new tooltipClass(_mc, tooltip);
var styleClass:String;
var xOffset:Number = 0;
var yOffset:Number = 0;
var xOffsetPoint:String = "center";
var yOffsetPoint:String = "bottom";
if (_styleClass) {
var exts:Array = Nexl.library.list( { type: "com.ydp.style.IStyleServer" } );
var ext:INexlExtensionDescription = exts[0];
var impl:IStyleServer = ext.create() as IStyleServer;
var styleSelector:StyleSelectorInfo = new StyleSelectorInfo(_styleClass);
var styles:Object = impl.getStyleDescriptionForSelector(styleSelector);
if (styles.hasOwnProperty("xoffset")) {
xOffset = Number(styles["xoffset"]);
}
if (styles.hasOwnProperty("yoffset")) {
yOffset = Number(styles["yoffset"]);
}
if (styles.hasOwnProperty("horizontaltooltipalign")) {
xOffsetPoint = String(styles["horizontaltooltipalign"]);
}
if (styles.hasOwnProperty("verticaltooltipalign")) {
yOffsetPoint = String(styles["verticaltooltipalign"]);
}
}
var p:Point = new Point(_mc.width/2,0);
p = _mc.localToGlobal(p);
var px:Number = 0;
var py:Number = 0;
switch(xOffsetPoint) {
case "right":
px = _tooltip.width;
break;
case "left":
px = 0;
break;
case "center":
default:
px = _tooltip.width/2;
break;
}
switch(yOffsetPoint) {
case "bottom":
py =_tooltip.height;
break;
case "top":
py = 0;
break;
case "center":
default :
py = _tooltip.height/2;
break;
}
_tooltip.x = Math.max( (p.x +xOffset) - px, 2) ;
_tooltip.x = Math.min( (_tooltip.x ), _mc.stage.stageWidth - _tooltip.width - 2);
_tooltip.y = Math.max( (p.y +yOffset) - py, 2);
_tooltip.y = Math.min( (_tooltip.y), _mc.stage.stageHeight -_tooltip.height - 2);
_mc.stage.addChild( _tooltip as DisplayObject);
if (tooltipDisplayTime > 0) {
setTimeout(hideTooltip, tooltipDisplayTime);
}
}
}
private function get tooltip():String {
var mc:MovieClip = _mc as MovieClip;
return (mc && (_text[1] is String) && (mc.currentFrame>=4))? _text[1] : _text[0];
}
private function hideTooltip(e:MouseEvent = null):void {
if (_tooltip && _tooltip.parent) {
_tooltip.parent.removeChild( _tooltip as DisplayObject);
}
_tooltip = null;
}
public function unload():void {
if(_mc){
_mc.removeEventListener( MouseEvent.MOUSE_OVER, showTooltip, false );
_mc.removeEventListener( MouseEvent.MOUSE_OUT, hideTooltip, false );
_mc.removeEventListener( MouseEvent.CLICK, changeTooltip, false);
hideTooltip();
}
_mc = null;
}
public function set tooltipDisplayTime(value:Number):void {
_displayTime = value;
}
public function get tooltipDisplayTime():Number{
if (isNaN(_displayTime)) {
return TooltipDecorator.displayTime;
}else {
return _displayTime;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment