/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 com.jfoenix.skins;
import com.jfoenix.controls.JFXPopup;
import com.jfoenix.controls.JFXPopup.PopupHPosition;
import com.jfoenix.controls.JFXPopup.PopupVPosition;
import com.jfoenix.effects.JFXDepthManager;
import com.jfoenix.transitions.CacheMomento;
import com.jfoenix.transitions.CachedTransition;
import javafx.animation.Animation.Status;
import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.control.Skin;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.transform.Scale;
import javafx.util.Duration;
/**
* <h1>Material Design Popup Skin</h1>
*
* @author Shadi Shaheen
* @version 2.0
* @since 2017-03-01
*/
public class JFXPopupSkin implements Skin<JFXPopup> {
private final JFXPopup control;
private final StackPane container = new StackPane();
private Node root;
private PopupTransition t;
private Scale scale;
private Region popupContent;
public JFXPopupSkin(JFXPopup control) {
this.control = control;
scale = new Scale(1, 0, 0, 0);
popupContent = control.getPopupContent();
container.getStyleClass().add("jfx-popup-container");
container.setBackground(new Background(new BackgroundFill(Color.WHITE, CornerRadii.EMPTY, Insets.EMPTY)));
container.getChildren().add(popupContent);
container.getTransforms().add(scale);
container.setOpacity(0);
root = JFXDepthManager.createMaterialNode(container, 4);
t = new PopupTransition();
}
public void reset(PopupVPosition vAlign, PopupHPosition hAlign, double offsetX, double offsetY) {
// postion the popup according to its animation
scale.setPivotX(hAlign == PopupHPosition.RIGHT ? container.getWidth() : 0);
scale.setPivotY(vAlign == PopupVPosition.BOTTOM ? container.getHeight() : 0);
root.setTranslateX(hAlign == PopupHPosition.RIGHT ? -container.getWidth() + offsetX : offsetX);
root.setTranslateY(vAlign == PopupVPosition.BOTTOM ? -container.getHeight() + offsetY : offsetY);
}
public void animate() {
if (t.getStatus() == Status.STOPPED) {
t.play();
}
}
@Override
public JFXPopup getSkinnable() {
return control;
}
@Override
public Node getNode() {
return root;
}
@Override
public void dispose() {
}
private final class PopupTransition extends CachedTransition {
PopupTransition() {
super(root, new Timeline(
new KeyFrame(
Duration.ZERO,
new KeyValue(popupContent.opacityProperty(), 0, Interpolator.EASE_BOTH),
new KeyValue(scale.xProperty(), 0, Interpolator.EASE_BOTH),
new KeyValue(scale.yProperty(), 0, Interpolator.EASE_BOTH)
),
new KeyFrame(Duration.millis(700),
new KeyValue(scale.xProperty(), 1, Interpolator.EASE_BOTH),
new KeyValue(popupContent.opacityProperty(), 0, Interpolator.EASE_BOTH)
),
new KeyFrame(Duration.millis(1000),
new KeyValue(popupContent.opacityProperty(), 1, Interpolator.EASE_BOTH),
new KeyValue(scale.yProperty(), 1, Interpolator.EASE_BOTH)
)
)
, new CacheMomento(popupContent));
setCycleDuration(Duration.seconds(.4));
setDelay(Duration.seconds(0));
}
@Override
protected void starting() {
container.setOpacity(1);
super.starting();
}
}
public void init() {
t.stop();
container.setOpacity(0);
scale.setX(0);
scale.setY(0);
}
}