/*
 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 */
package tiling;

import javafx.application.Application;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.binding.Bindings;
import javafx.beans.property.Property;
import javafx.beans.value.ObservableDoubleValue;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Slider;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBoxBuilder;
import javafx.scene.paint.ImagePattern;
import javafx.scene.shape.*;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.converter.DoubleStringConverter;

/**
 *
 * @author Aleksandr Sakharuk
 */
public class ImagePatternTilingApp extends Application 
{

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) 
    {
        launch(args);
    }

    protected Scene getScene() 
    {
        shapesCombo.setId(SHAPES_COMBO_ID);
        image = new Image("file:resources/square.gif");
        slider.setId(SLIDER_ID);
        slider.setMin(0);
        slider.setMax(3);
        slider.setValue(0.5);
        sliderValue.setId(SLIDER_VALUE_ID);
        proportionalCheck.setId(PROPORTIONAL_CHECK_ID);
        
        //System.out.println("Image status: " + image.getProgress());
        
        final FlowPane root = new FlowPane(Orientation.VERTICAL);
        
        shapesCombo.setOnAction(new EventHandler<ActionEvent>() {

            public void handle(ActionEvent t) 
            {
                int idx = root.getChildren().indexOf(shape);
                root.getChildren().remove(idx);
                shape = shapesCombo.getValue().getShape();
                shape.setId(SHAPE_ID);
                double q = slider.getValue();
                shape.setFill(new ImagePattern(image, 0, 0, q, q, true));
                root.getChildren().add(idx, shape);
            }
        });
        
        slider.valueProperty().addListener(new InvalidationListener() {
            @Override
            public void invalidated(Observable ov) 
            {
                double q = ((ObservableDoubleValue) ov).get();
                shape.setFill(new ImagePattern(image, 0, 0, q, q, true));
            }
        });
        
        Bindings.bindBidirectional(sliderValue.textProperty(), (Property) slider.valueProperty(), new DoubleStringConverter());
        
        proportionalCheck.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent arg0) {
                if(proportionalCheck.isSelected())
                {
                    slider.setMax(3);
                    slider.valueProperty().addListener(new InvalidationListener() {
                        @Override
                        public void invalidated(Observable ov) 
                        {
                            double q = ((ObservableDoubleValue) ov).get();
                            shape.setFill(new ImagePattern(image, 0, 0, q, q, true));
                        }
                    });
                }
                else
                {
                    slider.setMax(shape.getBoundsInLocal().getWidth() * 3);
                    slider.valueProperty().addListener(new InvalidationListener() {
                        @Override
                        public void invalidated(Observable ov) 
                        {
                            double q = ((ObservableDoubleValue) ov).get();
                            shape.setFill(new ImagePattern(image, 0, 0, q, q, false));
                        }
                    });
                }
            }
        });
        
        root.setVgap(10);
        root.setPadding(new Insets(10));
        shape = ImagePatternTilingApp.Shapes.CIRCLE.getShape();
        proportionalCheck.setSelected(true);
        root.getChildren().addAll(shapesCombo, shape, proportionalCheck, HBoxBuilder.create().children(slider, sliderValue).build());
        shapesCombo.setValue(ImagePatternTilingApp.Shapes.CIRCLE);
        return new Scene(root);
    }
    
    private ComboBox<ImagePatternTilingApp.Shapes> shapesCombo = new ComboBox<ImagePatternTilingApp.Shapes>(FXCollections.observableArrayList(ImagePatternTilingApp.Shapes.values()));
    private Shape shape;
    private Image image;
    private Slider slider = new Slider();
    private TextField sliderValue = new TextField();
    private CheckBox proportionalCheck = new CheckBox("Proportional");
    
    public static final String SHAPES_COMBO_ID = "shapes_combo";
    public static final String SHAPE_ID = "shape";
    public static final String SLIDER_ID = "slider";
    public static final String SLIDER_VALUE_ID = "slider_value";
    public static final String PROPORTIONAL_CHECK_ID = "proportional_check";

    @Override
    public void start(Stage stage) throws Exception 
    {
        stage.setScene(getScene());
        stage.show();
    }
    
    public interface ShapeFactory
    {
        Shape createShape();
    }
    
    public enum Shapes
    {
        CIRCLE(new ImagePatternTilingApp.ShapeFactory() {

            public Shape createShape() 
            {
                Circle circle = new Circle(10, 10, 50);
//                circle.setTranslateX(10);
//                circle.setTranslateY(10);
                return circle; 
            }
        }),
        ELLIPSE(new ImagePatternTilingApp.ShapeFactory() {

            public Shape createShape() 
            {
                return new Ellipse(10, 10, 50, 35);
            }
        }),
        POLYGON(new ImagePatternTilingApp.ShapeFactory() {

            public Shape createShape() 
            {
                return new Polygon(50, 20, 
                                   30, 50, 
                                   70, 80, 
                                   110, 50, 
                                   90, 20);
            }
        }),
        RECTANGLE(new ImagePatternTilingApp.ShapeFactory() {

            public Shape createShape() 
            {
                return new Rectangle(10, 10, 100, 100);
            }
        }),
        TEXT(new ImagePatternTilingApp.ShapeFactory() {

            public Shape createShape() 
            {
                Text text = new Text("Text");
                text.setStyle("-fx-font-size: 60; -fx-font-family: sans-serif; -fx-font-weight: bold;");
                return text;
            }
        }),
        ;

        private Shapes(ImagePatternTilingApp.ShapeFactory factory) 
        {
            this.factory = factory;
        }
        
        public Shape getShape()
        {
            return factory.createShape();
        }
        
        private ImagePatternTilingApp.ShapeFactory factory;
    }
    
}