Legal Terms and Copyright Notice
/* 
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
 * 
 * Copyright © 2010, Oracle and/or its affiliates. All rights reserved.
 * Oracle is a registered trademark of Oracle Corporation and/or its affiliates. 
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates. 
 * Other names may be trademarks of their respective owners.
 * 
 * This file is available and licensed under the following license:
 * 
 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met:

 *   *  Redistributions of source code must retain the above copyright notice, 
        trademark notice, this list of conditions, and the following disclaimer.

 *   *  Redistributions in binary form must reproduce the above copyright notice, 
        trademark notice, this list of conditions, and the following disclaimer in 
        the documentation and/or other materials provided with the distribution.

 *   *  Neither the name of Oracle nor the names of its contributors may be used 
        to endorse or promote products derived from this software without specific 
        prior written permission.
 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
 * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES LOSS OF USE, 
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package transformer;

import javafx.animation.Timeline;
import javafx.scene.CustomNode;
import javafx.scene.Group;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.scene.transform.Transform;


var codeLine: String;
var objective: String;
var description: String;
var transformations: Group;

def color = Color.rgb(51, 51, 51, 1.0);
def textColor = Color.rgb(153, 153, 153, 1.0);

def toggleGroup = ToggleGroup {
}

class MyRadioButton extends CustomNode {
  var text: String;
  var code: String;
  var comment: String;
  var example: Group;

  def button = RadioButton {
    toggleGroup: toggleGroup
    selected: true
  }

  def selected = bind button.selected on replace {
    if (selected) {
      transformations = example;
      codeLine = code;
      description = comment;
      def index = text.indexOf("\n");
      objective = if (index < 0) text else text.substring(0, index)
    }
  }

  override function create() {
    Group {
      content: [
        button,
        Label {
          translateX: button.width + 5
          height: button.height
          textFill: textColor
          text: text
          font: Font {
            name: "Arial Bold"
            size: 12
          }
        }
      ]
    }
  }
}

class MyText extends CustomNode {
  var title: String;
  var text: String;

  override function create() {
    VBox {
      spacing: 3
      content: [
        Text {
          content: bind title
          fill: Color.WHITE
          font: Font {
            name: "Arial Bold"
          }
        }
        Text {
          content: bind text
          fill: textColor
          font: Font {
            name: "Arial"
            size : 11
          }
        }
      ]
    }
  }
}

Application {
  title: "JavaFX Controls"
  header: Group {
    content: [
      ImageView {
        image: Image {
          url: "{__DIR__}logo.png"
        }
      }
      Line {
        startX: 10
        startY: 35
        endX: 540
        endY:  35
        stroke: color
      }
    ]
  }
  background: Color.rgb(29, 29, 29, 1)

  content: [
    Group {
      content: for(x in [0..30]) [
        Line {
          startX: 0
          startY: 10 * x
          endX: 300
          endY: 10 * x
          stroke: color
        }
        Line {
          startX: 10 * x
          startY: 0
          endX: 10 * x
          endY: 300
          stroke: color
        }
      ]
    }
    ImageView {
      x: 100
      y: 100
      image: Image {
        url: "{__DIR__}letter.png"
      }
      rotate: bind transformations.rotate;
      translateX: bind transformations.translateX;
      translateY: bind transformations.translateY;
      scaleX: bind transformations.scaleX;
      scaleY: bind transformations.scaleY;
      transforms: bind transformations.transforms;
    }
    Line {
      startX: 320
      startY: 0
      endX: 320
      endY: 300
      stroke: color
    }
    VBox {
      translateX: 340
      spacing: 10
      content: [
        Label {
          textFill: textColor
          text: "Select a Transformation to Apply"
          font: Font {
            name: "Arial Bold"
            size: 14
          }
        }
        MyRadioButton {
          text: "Rotate Around the Center"
          code: "rotate: 45"
          comment: "Rotates the object 45 degrees around its center, a point with coordinates x=140, y=135.\n"
                   "Rotation occurs clockwise"
          example: Group {
            rotate: 45
          }
        }
        MyRadioButton {
          text: "Rotate Around the Pivot Point"
          code: "transforms: Transform.rotate(45, 180, 180)"
          comment: "Rotates the object 45 degrees clockwise around the specified pivot point with coordinates x=180, y=180.\n"
                   "To enable rotating around the center of the object, you should define the pivot point as x=140, y=135"
          example: Group {
            transforms: Transform.rotate(45, 180, 180)
          }
        }
        MyRadioButton {
          text: "Translate"
          code: "translateX: 30, translateY: 30"
          comment: "Moves the object along the x and y axis relative to the object's initial position.\n"
                   "The coordinates of the object after the transformation are x=130, y=130"
          example: Group {
            translateX: 30
            translateY: 30
          }
        }
        MyRadioButton {
          text: "Scale Relative to the Center"
          code: "scaleX: 1.5, scaleY: 1.5"
          comment: "Scales the image relative to its center. The scaling factor for both dimensions is 1.5\n"
                   "The image increases so that its center remains in the same position: x=140, y=135"
          example: Group {
            scaleX: 1.5
            scaleY: 1.5
          }
        }
        MyRadioButton {
          text: "Scale Relative to the Pivot Point"
          code: "transforms: Transform.scale(0.5, 0.5, 180, 180)"
          comment: "Scales the image relative to the specified pivot point with coordinates x=180, y=180.\n"
                   "The scaling factor for both dimensions is 0.5."
          example: Group {
            transforms: Transform.scale(0.5, 0.5, 180, 180)
          }
        }
        MyRadioButton {
          text: "Shear"
          code: "transforms: Transform.shear(0.5, 0)"
          comment: "Transforms the image so its coordinates are shifted by the specified multipliers. While the y coordinate\n"
                   "remains the same (the corresponding multiplier is 0), the new x coordinate is x=100+100*0.5=150"
          example: Group {
            transforms: Transform.shear(0.5, 0)
          }
        }
        MyRadioButton {
          text: "Multiple Transformations"
          code: "transforms: [Transform.rotate(190, 180, 180), Transform.scale(0.5, 0.5, 100, 100), Transform.shear(0.5, 0)]"
          comment: "Consequently applies rotation around the point (180, 180), then reduces the image twice, and then\n"
                   "applies shearing transformation with the 0.5 multiplier for the x axis"
          example: Group {
            transforms: [
              Transform.rotate(190, 180, 180),
              Transform.scale(0.5, 0.5, 100, 100),
              Transform.shear(0.5, 0)
            ]
          }
        }
        Line {
          startX: 320
          startY: 250
          endX: 515
          endY: 250
          stroke: color
        }
        MyRadioButton {
          text: "Remove Transformations \n(return to the initial state)"
          code: "No transformations are applied"
          comment: "The initial state of the experiment. The coordinates of the image are x=100, y =100"
          example: Group {
          }
        }
      ]
    }
    Line {
      startX: 5
      startY: 315
      endX: 535
      endY: 315
      stroke: color
    }
    MyText {
      translateX: 5
      translateY: 325
      title: bind objective
      text: bind description
    }
    MyText {
      translateX: 5
      translateY: 375
      title: "Code"
      text: bind codeLine
    }
  ]
}