All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jfoenix.transitions.template.JFXAnimationTemplateAction Maven / Gradle / Ivy

There is a newer version: 9.0.10
Show newest version
/*
 * 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.transitions.template;

import javafx.animation.Interpolator;
import javafx.beans.value.WritableValue;
import javafx.event.ActionEvent;
import javafx.scene.Node;

import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.IntFunction;
import java.util.function.Predicate;
import java.util.stream.Stream;

/**
 * Class which represents a builder and the configuration of animation keyframes. The configuration
 * methods are based on the methods of a {@link javafx.animation.KeyFrame} and {@link
 * javafx.animation.KeyValue}.
* It is possible that not all methods supported because the specific implementation of an animation * can diverge from general {@link javafx.animation.KeyFrame} and {@link javafx.animation.KeyValue} * implementations. * * @author Marcel Schlegel (schlegel11) * @version 1.0 * @since 2018-09-22 */ public final class JFXAnimationTemplateAction { public static final int INFINITE_EXECUTIONS = -1; private final Collection>> targetFunctions; private final Function endValueSupplier; private final Function interpolatorSupplier; private final Predicate executeWhenPredicate; private final BiConsumer onFinish; private final Function executionsFunction; private final N animationObject; private int executionsCounter; private JFXAnimationTemplateAction(Builder builder) { targetFunctions = builder.targetFunctions; endValueSupplier = builder.endValueFunction; interpolatorSupplier = builder.interpolatorFunction; animationObject = builder.animationObject; executeWhenPredicate = builder.executeWhenPredicate; onFinish = builder.onFinish; executionsFunction = builder.executionsFunction; } public static InitBuilder builder(Class animationObjectType) { return new InitBuilder<>( animationObjectType, JFXTemplateBuilder.JFXAnimationObjectMapBuilder.DEFAULT_ANIMATION_OBJECT_NAME); } public static InitBuilder builder() { return builder(Node.class); } public Collection>> getTargetFunctions() { return targetFunctions; } public Optional> getFirstTarget() { return getTargetFunctions() .stream() .findFirst() .map(function -> function.apply(animationObject)); } public T getEndValue() { return endValueSupplier.apply(animationObject); } public Optional getInterpolator() { return Optional.ofNullable(interpolatorSupplier.apply(animationObject)); } public boolean isExecuteWhen() { return executeWhenPredicate.test(animationObject); } public int getExecutions() { return Math.max(executionsFunction.apply(animationObject), INFINITE_EXECUTIONS); } public void addExecution(int count) { int maxExecutions = getExecutions(); if (count >= 0 && executionsCounter < maxExecutions) { executionsCounter = Math.min(executionsCounter + count, maxExecutions); } } public int getRemainingExecutions() { int maxExecutions = getExecutions(); return maxExecutions == INFINITE_EXECUTIONS ? INFINITE_EXECUTIONS : Math.max(0, maxExecutions - executionsCounter); } public boolean hasRemainingExecutions() { return getRemainingExecutions() > 0 || getRemainingExecutions() == INFINITE_EXECUTIONS; } /** * True if {@link #hasRemainingExecutions()} and {@link #isExecuteWhen()} is {@code true}. * * @return a boolean. */ public boolean isExecuted() { return hasRemainingExecutions() && isExecuteWhen(); } public void handleOnFinish(ActionEvent actionEvent) { onFinish.accept(animationObject, actionEvent); } @SuppressWarnings("unchecked") public Stream mapTo(Function, M> mappingFunction) { return getTargetFunctions() .stream() .map( function -> mappingFunction.apply((WritableValue) function.apply(animationObject))); } public static final class Builder { private final Collection>> targetFunctions; private final InitBuilder initBuilder; private Function endValueFunction = node -> null; private Function interpolatorFunction = node -> null; private Predicate executeWhenPredicate = node -> true; private BiConsumer onFinish = (node, event) -> {}; private Function executionsFunction = node -> INFINITE_EXECUTIONS; private N animationObject; private Builder( InitBuilder initBuilder, Collection>> targetFunctions) { this.initBuilder = initBuilder; this.targetFunctions = targetFunctions; } private Builder(InitBuilder initBuilder) { this(initBuilder, Collections.emptyList()); } /** * The end value of the interpolation. * * @param endValue the end value. * @return the {@link Builder} instance. */ public Builder endValue(T endValue) { return endValue(node -> endValue); } /** * The lazy version of {@link #endValue(Object)} which is computed when the {@link * JFXAnimationTemplateAction} is build.
* The {@link Function} provides also a reference of the current animation object. * * @see #endValue(Object) * @param endValueFunction the end value {@link Function}. * @return the {@link Builder} instance. */ public Builder endValue(Function endValueFunction) { this.endValueFunction = endValueFunction; return this; } /** * The {@link Interpolator} of the animation. * * @param interpolator the {@link Interpolator}. * @return the {@link Builder} instance. */ public Builder interpolator(Interpolator interpolator) { return interpolator(node -> interpolator); } /** * The lazy version of {@link #interpolator(Interpolator)} which is computed when the {@link * JFXAnimationTemplateAction} is build.
* The {@link Function} provides also a reference of the current animation object. * * @see #interpolator(Interpolator) * @param interpolatorFunction the interpolator {@link Function}. * @return the {@link Builder} instance. */ public Builder interpolator(Function interpolatorFunction) { this.interpolatorFunction = interpolatorFunction; return this; } /** * Executes the {@link JFXTemplateAction} if the condition is true. * * @param executeWhen the execute condition. * @return the {@link Builder} instance. */ public Builder executeWhen(boolean executeWhen) { return executeWhen(n -> executeWhen); } /** * The lazy version of {@link #executeWhen(boolean)} which is computed when the {@link * JFXAnimationTemplateAction} is build.
* The {@link Predicate} provides also a reference of the current animation object. * * @see #executeWhen(boolean) * @param executeWhenPredicate the condition {@link Predicate}. * @return the {@link Builder} instance. */ public Builder executeWhen(Predicate executeWhenPredicate) { this.executeWhenPredicate = executeWhenPredicate; return this; } /** * Ignores the current {@link JFXTemplateAction} so the action is never executed. * * @return the {@link Builder} instance. */ public Builder ignore() { return executeWhen(false).executions(0); } /** * The on finish {@link ActionEvent} which is executed at the end of the current {@link * JFXTemplateAction}.
* The {@link BiConsumer} provides beside the {@link ActionEvent} also a reference of the * current animation object. * * @param onFinish the on finish {@link ActionEvent}. * @return the {@link Builder} instance. */ public Builder onFinish(BiConsumer onFinish) { this.onFinish = onFinish; return this; } /** * The lazy version of {@link #executions(int)} which is computed when the {@link * JFXAnimationTemplateAction} is build.
* The {@link Function} provides also a reference of the current animation object. * * @see #executions(int) * @param executionsFunction the number of executions {@link Function}. * @return the {@link Builder} instance. */ public Builder executions(Function executionsFunction) { this.executionsFunction = executionsFunction; return this; } /** * Executes the current {@link JFXTemplateAction} N times, until the given number of executions * is reached. * * @param executions the number of executions. * @return the {@link Builder} instance. */ public Builder executions(int executions) { return executions(node -> executions); } public JFXAnimationTemplateAction build( Function, Object> buildFunction) { this.animationObject = initBuilder.animationObjectType.cast( buildFunction.apply(initBuilder.animationObjectNames)); return new JFXAnimationTemplateAction<>(this); } public Stream> buildActions( Function, Collection> buildFunction) { return buildFunction .apply(initBuilder.animationObjectNames) .stream() .map( animationObject -> { this.animationObject = initBuilder.animationObjectType.cast(animationObject); return new JFXAnimationTemplateAction<>(this); }); } public JFXAnimationTemplateAction build() { return new JFXAnimationTemplateAction<>(this); } } public static final class InitBuilder { private final Class animationObjectType; private final Collection animationObjectNames = new ArrayList<>(); private InitBuilder( Class animationObjectType, String animationObjectId, String... animationObjectNames) { this.animationObjectType = animationObjectType; this.animationObjectNames.add(animationObjectId); this.animationObjectNames.addAll(Arrays.asList(animationObjectNames)); } /** * The target or targets of the interpolation. * * @param target the interpolation target. * @param targets the interpolation targets. * @param the target {@link WritableValue} type. * @return the {@link Builder} instance. */ @SafeVarargs public final Builder target(WritableValue target, WritableValue... targets) { Function>[] targetFunctions = Stream.of(targets) .map(value -> (Function>) n -> value) .toArray((IntFunction>[]>) Function[]::new); return target(node -> target, targetFunctions); } /** * The lazy version of {@link #target(WritableValue, WritableValue[])} which is computed when * the {@link JFXAnimationTemplateAction} is build.
* The {@link Function} provides also a reference of the current animation object. * * @param targetFunction the interpolation target. * @param targetFunctions the interpolation targets. * @param the target {@link WritableValue} type. * @return the {@link Builder} instance. */ @SafeVarargs public final Builder target( Function> targetFunction, Function>... targetFunctions) { Collection>> functions = new ArrayList<>(); functions.add(targetFunction); functions.addAll(Arrays.asList(targetFunctions)); return new Builder<>(this, functions); } /** @see Builder#executeWhen(boolean) */ public final Builder executeWhen(boolean animateWhen) { return new Builder<>(this).executeWhen(animateWhen); } /** @see Builder#executeWhen(Predicate) */ public final Builder executeWhen(Predicate executeWhenPredicate) { return new Builder<>(this).executeWhen(executeWhenPredicate); } /** @see Builder#ignore() */ public Builder ignore() { return new Builder<>(this).ignore(); } /** @see Builder#onFinish(BiConsumer) */ public Builder onFinish(BiConsumer onFinish) { return new Builder<>(this).onFinish(onFinish); } /** @see Builder#executions(Function) */ public Builder executions(Function executionsFunction) { return new Builder<>(this).executions(executionsFunction); } /** @see Builder#executions(int) */ public Builder executions(int executions) { return new Builder<>(this).executions(executions); } /** * Call named animation objects with a specific {@link Class} type and a name.
* The named animation objects are set when the {@link JFXAnimationTemplate} is build. * * @param clazz the specific type of the named animation objects. * @param animationObjectName the named animation object name. * @param animationObjectNames the named animation object names. * @param the specific named animation object type. * @return the {@link InitBuilder} instance. */ public InitBuilder withAnimationObject( Class clazz, String animationObjectName, String... animationObjectNames) { return new InitBuilder<>(clazz, animationObjectName, animationObjectNames); } /** * Same as {@link #withAnimationObject(Class, String, String...)} but with a default type {@link * Node}. * * @see #withAnimationObject(Class, String, String...) * @param animationObjectName the named animation object name. * @param animationObjectNames the named animation object names. * @return the {@link InitBuilder} instance. */ public InitBuilder withAnimationObject( String animationObjectName, String... animationObjectNames) { return withAnimationObject(Node.class, animationObjectName, animationObjectNames); } } }