/*
* Copyright (c) 2013 by Gerrit Grunwald
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package eu.hansolo.enzo.signaltower.skin;
import eu.hansolo.enzo.common.Util;
import eu.hansolo.enzo.signaltower.SignalTower;
import javafx.scene.control.Skin;
import javafx.scene.control.SkinBase;
import javafx.scene.effect.BlurType;
import javafx.scene.effect.DropShadow;
import javafx.scene.effect.InnerShadow;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Region;
import javafx.scene.paint.Color;
public class SignalTowerSkin extends SkinBase<SignalTower> implements Skin<SignalTower> {
private static final double MINIMUM_WIDTH = 5;
private static final double MINIMUM_HEIGHT = 5;
private static final double MAXIMUM_WIDTH = 1024;
private static final double MAXIMUM_HEIGHT = 1024;
private static final double PREFERRED_WIDTH = 150;
private static final double PREFERRED_HEIGHT = 591;
private double aspectRatio;
private double size;
private double width;
private double height;
private Pane pane;
private Region green;
private Region yellow;
private Region red;
private Region rack;
private Region body;
private Region roof;
private DropShadow bodyDropShadow;
private InnerShadow bodyInnerShadow;
// ******************** Constructors **************************************
public SignalTowerSkin(final SignalTower CONTROL) {
super(CONTROL);
aspectRatio = PREFERRED_HEIGHT / PREFERRED_WIDTH;
init();
initGraphics();
registerListeners();
}
// ******************** Initialization ************************************
private void init() {
if (Double.compare(getSkinnable().getPrefWidth(), 0.0) <= 0 || Double.compare(getSkinnable().getPrefHeight(), 0.0) <= 0 ||
Double.compare(getSkinnable().getWidth(), 0.0) <= 0 || Double.compare(getSkinnable().getHeight(), 0.0) <= 0) {
if (getSkinnable().getPrefWidth() > 0 && getSkinnable().getPrefHeight() > 0) {
getSkinnable().setPrefSize(getSkinnable().getPrefWidth(), getSkinnable().getPrefHeight());
} else {
getSkinnable().setPrefSize(PREFERRED_WIDTH, PREFERRED_HEIGHT);
}
}
if (Double.compare(getSkinnable().getMinWidth(), 0.0) <= 0 || Double.compare(getSkinnable().getMinHeight(), 0.0) <= 0) {
getSkinnable().setMinSize(MINIMUM_WIDTH, MINIMUM_HEIGHT);
}
if (Double.compare(getSkinnable().getMaxWidth(), 0.0) <= 0 || Double.compare(getSkinnable().getMaxHeight(), 0.0) <= 0) {
getSkinnable().setMaxSize(MAXIMUM_WIDTH, MAXIMUM_HEIGHT);
}
}
private void initGraphics() {
green = new Region();
green.getStyleClass().setAll("green");
yellow = new Region();
yellow.getStyleClass().setAll("yellow");
red = new Region();
red.getStyleClass().setAll("red");
rack = new Region();
rack.getStyleClass().setAll("rack");
bodyDropShadow = new DropShadow(BlurType.TWO_PASS_BOX, Color.web("0x000000a6"), 0.0133333333 * PREFERRED_WIDTH, 1.0, 0d, 2d);
bodyInnerShadow = new InnerShadow(BlurType.TWO_PASS_BOX, Color.web("0x000000a6"), 0.0133333333 * PREFERRED_WIDTH, 1.0, 1.4142135623730951, 1.4142135623730951);
bodyInnerShadow.setInput(bodyDropShadow);
body = new Region();
body.getStyleClass().setAll("body");
body.setEffect(bodyInnerShadow);
roof = new Region();
roof.getStyleClass().setAll("roof");
pane = new Pane();
pane.getChildren().setAll(green,
yellow,
red,
rack,
body,
roof);
getChildren().setAll(pane);
resize();
}
private void registerListeners() {
getSkinnable().widthProperty().addListener(observable -> handleControlPropertyChanged("RESIZE") );
getSkinnable().heightProperty().addListener(observable -> handleControlPropertyChanged("RESIZE") );
}
// ******************** Methods *******************************************
protected void handleControlPropertyChanged(final String PROPERTY) {
if ("RESIZE".equals(PROPERTY)) {
resize();
}
}
@Override protected double computeMinWidth(final double HEIGHT, double TOP_INSET, double RIGHT_INSET, double BOTTOM_INSET, double LEFT_INSET) {
return super.computeMinWidth(Math.max(MINIMUM_HEIGHT, HEIGHT - TOP_INSET - BOTTOM_INSET), TOP_INSET, RIGHT_INSET, BOTTOM_INSET, LEFT_INSET);
}
@Override protected double computeMinHeight(final double WIDTH, double TOP_INSET, double RIGHT_INSET, double BOTTOM_INSET, double LEFT_INSET) {
return super.computeMinHeight(Math.max(MINIMUM_WIDTH, WIDTH - LEFT_INSET - RIGHT_INSET), TOP_INSET, RIGHT_INSET, BOTTOM_INSET, LEFT_INSET);
}
@Override protected double computeMaxWidth(final double HEIGHT, double TOP_INSET, double RIGHT_INSET, double BOTTOM_INSET, double LEFT_INSET) {
return super.computeMaxWidth(Math.min(MAXIMUM_HEIGHT, HEIGHT - TOP_INSET - BOTTOM_INSET), TOP_INSET, RIGHT_INSET, BOTTOM_INSET, LEFT_INSET);
}
@Override protected double computeMaxHeight(final double WIDTH, double TOP_INSET, double RIGHT_INSET, double BOTTOM_INSET, double LEFT_INSET) {
return super.computeMaxHeight(Math.min(MAXIMUM_WIDTH, WIDTH - LEFT_INSET - RIGHT_INSET), TOP_INSET, RIGHT_INSET, BOTTOM_INSET, LEFT_INSET);
}
@Override protected double computePrefWidth(final double HEIGHT, double TOP_INSET, double RIGHT_INSET, double BOTTOM_INSET, double LEFT_INSET) {
double prefHeight = PREFERRED_HEIGHT;
if (HEIGHT != -1) {
prefHeight = Math.max(0, HEIGHT - TOP_INSET - BOTTOM_INSET);
}
return super.computePrefWidth(prefHeight, TOP_INSET, RIGHT_INSET, BOTTOM_INSET, LEFT_INSET);
}
@Override protected double computePrefHeight(final double WIDTH, double TOP_INSET, double RIGHT_INSET, double BOTTOM_INSET, double LEFT_INSET) {
double prefWidth = PREFERRED_WIDTH;
if (WIDTH != -1) {
prefWidth = Math.max(0, WIDTH - LEFT_INSET - RIGHT_INSET);
}
return super.computePrefHeight(prefWidth, TOP_INSET, RIGHT_INSET, BOTTOM_INSET, LEFT_INSET);
}
// ******************** Resizing ******************************************
private void resize() {
size = getSkinnable().getWidth() < getSkinnable().getHeight() ? getSkinnable().getWidth() : getSkinnable().getHeight();
width = getSkinnable().getWidth();
height = getSkinnable().getHeight();
if (getSkinnable().isKeepAspect()) {
if (aspectRatio * width > height) {
width = 1 / (aspectRatio / height);
} else if (1 / (aspectRatio / height) > width) {
height = aspectRatio * width;
}
}
if (width > 0 && height > 0) {
green.setPrefSize(0.5333333333333333 * width, 0.11844331641285956 * height);
green.setTranslateX(0.26 * width);
green.setTranslateY(0.350253807106599 * height);
yellow.setPrefSize(0.5333333333333333 * width, 0.11844331641285956 * height);
yellow.setTranslateX(0.26 * width);
yellow.setTranslateY(0.22504230118443316 * height);
red.setPrefSize(0.5333333333333333 * width, 0.11844331641285956 * height);
red.setTranslateX(0.26 * width);
red.setTranslateY(0.09475465313028765 * height);
rack.setPrefSize(0.02666666666666667 * width, 0.3824027072758037 * height);
rack.setTranslateX(0.4266666666666667 * width);
rack.setTranslateY(0.09475465313028765 * height);
bodyDropShadow.setRadius(Util.clamp(1, 3, 0.0133333333 * size));
bodyInnerShadow.setRadius(Util.clamp(1, 3, 0.0133333333 * size));
body.setPrefSize(0.6133333333333333 * width, 0.9111675126903553 * height);
body.setTranslateX(0.22 * width);
body.setTranslateY(0.03976311336717428 * height);
roof.setPrefSize(0.6133333333333333 * width, 0.018612521150592216 * height);
roof.setTranslateX(0.22 * width);
roof.setTranslateY(0.028764805414551606 * height);
}
}
}