/* * Copyright 2014 michael-simons.eu. * * 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 ac.simons.bikingFX.bikingPictures; import ac.simons.bikingFX.RootController.LoadedImageFilter; import java.util.List; import java.util.Random; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; import javafx.animation.ScaleTransition; import javafx.collections.ObservableList; import javafx.concurrent.ScheduledService; import javafx.concurrent.Task; import javafx.scene.Node; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.Pane; import javafx.scene.layout.StackPane; import javafx.util.Duration; /** * @author Michael J. Simons, 2014-10-17 */ public class FlipImageService extends ScheduledService<ImageView> { private static final Logger logger = Logger.getLogger(FlipImageService.class.getName()); private final ObservableList<BikingPicture> bikingPictures; private final Random random; private final Pane container; public FlipImageService(ObservableList<BikingPicture> bikingPictures, final Pane container, final Random random) { this.bikingPictures = bikingPictures; this.container = container; this.random = random; this.setPeriod(Duration.seconds(10)); this.setDelay(this.getPeriod()); this.setOnSucceeded(state -> { // Check if images are loaded... final List<Node> currentImageViews = this.container.getChildren().filtered(node -> node instanceof StackPane && ((StackPane)node).getChildren().get(0) instanceof ImageView); if(currentImageViews.size() > 0) { final StackPane pickedNoded = (StackPane) currentImageViews.get(this.random.nextInt(currentImageViews.size())); final Node back = (Node)state.getSource().getValue(); back.setScaleX(0); pickedNoded.getChildren().add(back); final Duration animDuration = Duration.millis(500); final ScaleTransition hideFront = new ScaleTransition(animDuration, pickedNoded.getChildren().get(0)); hideFront.setFromX(1); hideFront.setToX(0); final ScaleTransition showBack = new ScaleTransition(animDuration, back); showBack.setFromX(0); showBack.setToX(1); hideFront.setOnFinished(event -> showBack.play()); showBack.setOnFinished(event -> pickedNoded.getChildren().remove(0)); hideFront.play(); } }); this.setOnFailed(state -> logger.log(Level.INFO, "Could not create ImageView: {0}.", state.getSource().getException().getMessage())); } @Override protected Task<ImageView> createTask() { return new Task<ImageView>() { @Override protected ImageView call() throws Exception { // Create fresh filtered list final Set<BikingPicture> loadedBikingPictures = container .getChildren().stream() .filter(new LoadedImageFilter()) .map(node -> (BikingPicture)((StackPane)node).getChildren().get(0).getUserData()) .collect(Collectors.toSet()); final List<BikingPicture> availableBikingPictures = bikingPictures.filtered(bikingPicture -> !loadedBikingPictures.contains(bikingPicture)); if(availableBikingPictures.size() <= 0) { throw new RuntimeException("No more pictures available"); } final BikingPicture bikingPicture = availableBikingPictures.get(random.nextInt(availableBikingPictures.size())); final ImageView imageView = new ImageView(new Image(bikingPicture.getSrc(), 150, 113, true, true, false)); imageView.setUserData(bikingPicture); return imageView; } }; } }