package fliptransition;

import javafx.animation.*;
import javafx.ext.swing.*;
import javafx.scene.input.*;
import javafx.scene.*;
import javafx.scene.effect.*;
import javafx.scene.shape.*;
import javafx.scene.paint.*;
import javafx.scene.transform.*;
import javafx.scene.image.*;
import javafx.stage.*;
import javafx.scene.text.*;
import java.lang.Math;

/*
 * FlipView is a custom node which alternately displays two
 * child nodes, the front and the back, by flipping between
 * them with a 3-D transition.
 */

class FlipView extends CustomNode {
    // public variables for users of this class to set the front and back
    public var frontNode:Node;
    public var backNode:Node;

    var flipped = false;

    // the animation to flip between front and back
    var time = Math.PI/2;
    public var anim = Timeline {
        keyFrames: [
            at(0s) { time=> Math.PI/2 tween Interpolator.LINEAR},
            at(1s) { time=> -Math.PI/2 tween Interpolator.LINEAR},
            KeyFrame {
                time: 1.0s
                action: function() { flipped = not flipped; }
            }
        ]
    }
    
    override public function create():Node {
        return Group {
            content: [ 
                Group { content: backNode visible: bind (time<0) effect: bind getPT(time) },
                Group { content: frontNode  visible: bind (time>0) effect: bind getPT(time) },
            ]
        }
    }

    // Returns the actual perspective transform.
    // Calcualtes the transform by stretching the front and back
    // edges according to a sine and cosine curve multiplied by
    // the constants: radius and back
    function getPT(t:Number):PerspectiveTransform {
        var width = 200;
        var height = 200;
        var radius = width/2;
        var back = height/10;
        return PerspectiveTransform {
            ulx: radius - Math.sin(t)*radius     uly: 0 - Math.cos(t)*back
            urx: radius + Math.sin(t)*radius     ury: 0 + Math.cos(t)*back
            lrx: radius + Math.sin(t)*radius     lry: height - Math.cos(t)*back
            llx: radius - Math.sin(t)*radius     lly: height + Math.cos(t)*back
        }
    }

}

// create an instance of FlipView  using two pictures of the lion
var flip = FlipView {
    translateX: 50
    translateY: 40+50
    backNode: ImageView { image: Image { url: "{__DIR__}lion1.png"  }  }
    frontNode: ImageView { image: Image { url: "{__DIR__}lion2.png"  }  }
};

// create a stage containing the transform and a control button
Stage {
    title: "Flip Transition"
    scene: Scene {
        fill: Color.BLACK
        width: 300
        height: 340
        content: [

            // the flip transition
            flip,

            // click button
            Group {
                translateX: 50
                translateY: 5
                content:[
                    Rectangle { width: 200 height: 35 fill: Color.rgb(100,100,100) stroke: Color.DARKGRAY }
                    Text { fill: Color.WHITE content: "Click Here to Flip" y: 25 x: 27 font: Font { size: 18 }},
                    Rectangle { width: 200 height: 35 fill: Color.rgb(200,0,0,0.0)
                        onMousePressed: function(e:MouseEvent) {
                            if(flip.flipped) {
                                flip.anim.rate = -1.0;
                                flip.anim.time = 1s;
                            } else {
                                flip.anim.rate = 1.0;
                                flip.anim.time = 0s;
                            }
                            flip.anim.play();
                        }
                    }
                ]
            }
        ]
    }
}