001 
002 /*
003  *  JScripter Standard 1.0 - To Script In Java
004  *  Copyright (C) 2008-2011  J.J.Liu<jianjunliu@126.com> <http://www.jscripter.org>
005  *  
006  *  This program is free software: you can redistribute it and/or modify
007  *  it under the terms of the GNU Affero General Public License as published by
008  *  the Free Software Foundation, either version 3 of the License, or
009  *  (at your option) any later version.
010  *  
011  *  This program is distributed in the hope that it will be useful,
012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014  *  GNU Affero General Public License for more details.
015  *  
016  *  You should have received a copy of the GNU Affero General Public License
017  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
018  */
019 
020 package jsx.ui.fx;
021 
022 import js.Initializer;
023 import js.Js;
024 import js.JsApplet;
025 import js.ObjectLike;
026 import jsx.client.Browser;
027 import jsx.dom.Styles;
028 import jsx.ui.Component;
029 import jsx.ui.event.Style;
030 import jsx.ui.fx.event.Animation;
031 
032 /**
033  * <p>A base class for widgets providing transformation effects to their components.</p>
034  * 
035  * @author <a href="mailto:jianjunliu@126.com">J.J.Liu (Jianjun Liu)</a> at <a href="http://www.jscripter.org" target="_blank">http://www.jscripter.org</a>
036  */
037 public class Transform extends Effects
038 {
039     private double x, y, w, h, dx, dy, dw, dh;
040 
041     /**
042      * <p>Constructs a transformation effects over a component.</p>
043      * <p>This constructor simply invokes its super constructor with the component
044      * as argument.</p>
045      * @param e A component to have the visual effects.
046      * @since 1.0
047      */
048     public Transform(Component e) {
049         super(e);
050     }
051 
052     /**
053      * <p>Defines an action for the given frame.</p>
054      * <p>This method changes the position and size of the widget in accordance with 
055      * the {@link jsx.motion.Motion} definition of the {@link Effects#MOTION} property.</p>
056      * @param i An index of the current frame ranging from 0 and the total number 
057      * of frames obtained by {@link #getFrames(Effects)}.
058      * @since 1.0
059      */
060     @Override
061     protected void frame(int i) {
062         double s = getMotion(this).get(i);
063         ObjectLike p = new Initializer().var();
064         Styles.left  (p, Styles.px(x + s * dx));
065         Styles.top   (p, Styles.px(y + s * dy));
066         Styles.width (p, Styles.px(w + s * dw));
067         Styles.height(p, Styles.px(h + s * dh));
068         Component.applyStyle(unwrap(), p);
069     }
070 
071     /**
072      * <p>Performs an action on the dispatched event.</p>
073      * <p>This method animates the widget with transformation effects.</p>
074      * @param evt The event dispatched to this listener.
075      * @since 1.0
076      */
077     public void onEvent(Animation evt) {
078         Class<? extends Effects> fx = ini(evt).var(Animation.FX);
079         if (Js.not(fx) || fx == Transform.class) {
080             ObjectLike style = ini(evt).var(Style.STYLE);
081             ini(this).var(Style.STYLE, style);
082             Component e = unwrap();
083             x = Component.left(e);
084             y = Component.top (e);
085             if (Browser.isIE) {
086                 w = (double)Component.offsetWidth (e);
087                 h = (double)Component.offsetHeight(e);
088             } else {
089                 w = Component.contentWidth (e);
090                 h = Component.contentHeight(e);
091             }
092             if (Js.be(style)) {
093                 dx = dx(Styles.left  (style), x);
094                 dy = dx(Styles.top   (style), y);
095                 dw = dx(Styles.width (style), w);
096                 dh = dx(Styles.height(style), h);
097             }
098             animate(style);
099         }
100     }
101 
102     private static final double dx(String s, double x) {
103         return Js.be(s) ? Styles.px(s) - x : 0;
104     }
105 
106     /**
107      * <p>Animates a component with transformation effects.</p>
108      * @param e A component to fade out.
109      * @param p A final style to the component.
110      * @since 1.0
111      */
112     public static final void animate(Component e, ObjectLike p) {
113         synchronized(JsApplet.class) {
114             Transform tf = new Transform(e);
115             tf.exec(new Animation(Transform.class, p));
116             e.removeListener(Animation.class, tf);
117         }
118     }
119 }