/**
* This file is part of JSkat.
*
* JSkat is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* JSkat is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with JSkat. If not, see <http://www.gnu.org/licenses/>.
*/
package org.jskat;
import java.awt.Point;
import javax.swing.SwingUtilities;
import org.apache.log4j.PropertyConfigurator;
import org.jskat.control.JSkatEventBus;
import org.jskat.control.JSkatMaster;
import org.jskat.control.command.general.ShowWelcomeInformationCommand;
import org.jskat.data.DesktopSavePathResolver;
import org.jskat.data.JSkatOptions;
import org.jskat.data.JSkatOptions.Option;
import org.jskat.gui.img.JSkatGraphicRepository;
import org.jskat.gui.javafx.JSkatMainWindow;
import org.jskat.gui.javafx.JSkatMenuFactory;
import org.jskat.gui.swing.JSkatViewImpl;
import org.jskat.gui.swing.LookAndFeelSetter;
import org.jskat.util.JSkatResourceBundle;
import org.jskat.util.version.VersionChecker;
import javafx.animation.FadeTransition;
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.concurrent.Worker;
import javafx.geometry.Point2D;
import javafx.geometry.Pos;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.MenuBar;
import javafx.scene.control.ProgressBar;
import javafx.scene.effect.DropShadow;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.util.Duration;
public class JSkatFX extends Application {
private static final String VERSION = "0.16.0";
private static final int SPLASH_WIDTH = 500;
private static final int SPLASH_HEIGHT = 300;
private Pane splashScreenLayout;
private ProgressBar splashScreenProgressBar;
private Label splashScreenProgressText;
public static void main(String[] args) {
PropertyConfigurator.configure(ClassLoader.getSystemResource("org/jskat/config/log4j.properties")); //$NON-NLS-1$
JSkatOptions.instance(new DesktopSavePathResolver());
launch(args);
}
@Override
public void init() {
ImageView splashScreenImage = new ImageView(
new Image(JSkatFX.class.getResource("/org/jskat/gui/img/gui/splash.png").toExternalForm()));
splashScreenProgressBar = new ProgressBar();
splashScreenProgressBar.setPrefWidth(SPLASH_WIDTH);
splashScreenProgressText = new Label("Loading JSkat...");
splashScreenProgressText.setAlignment(Pos.CENTER);
splashScreenLayout = new VBox();
splashScreenLayout.getChildren().addAll(splashScreenImage, splashScreenProgressBar, splashScreenProgressText);
splashScreenLayout.setStyle(
"-fx-padding: 5; " + "-fx-background-color: #e2d9ca; " + "-fx-border-width:2; " + "-fx-border-color: "
+ "linear-gradient(" + "to bottom, " + "chocolate, " + "derive(chocolate, 50%)" + ");");
splashScreenLayout.setEffect(new DropShadow());
}
@Override
public void start(Stage primaryStage) {
Point2D savedScreenPosition = getSavedScreenPosition();
Screen targetScreen = getTargetScreen(savedScreenPosition);
Task<InitializedGuiElements> startupTasks = new Task<InitializedGuiElements>() {
@Override
protected InitializedGuiElements call() throws Exception {
updateMessage(JSkatResourceBundle.INSTANCE.getString("splash_init_application"));
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
LookAndFeelSetter.setLookAndFeel(targetScreen);
}
});
updateProgress(1, 3);
updateMessage(JSkatResourceBundle.INSTANCE.getString("splash_load_card_sets"));
JSkatGraphicRepository.INSTANCE.toString();
updateProgress(2, 3);
updateMessage(JSkatResourceBundle.INSTANCE.getString("splash_look_for_ai_players"));
MenuBar menu = JSkatMenuFactory.build();
JSkatViewImpl jskatView = new JSkatViewImpl(targetScreen, menu, VERSION);
JSkatMaster.INSTANCE.setView(jskatView);
return new InitializedGuiElements(menu, jskatView);
}
};
showSplashScreen(targetScreen, primaryStage, startupTasks,
() -> showJSkatMainWindow(targetScreen, savedScreenPosition, startupTasks.valueProperty().get().menu,
startupTasks.valueProperty().get().jskatView));
new Thread(startupTasks).start();
}
private static void showJSkatMainWindow(Screen targetScreen, Point2D screenPosition, MenuBar menu,
JSkatViewImpl jskatView) {
JSkatMainWindow jskatMainWindow = new JSkatMainWindow(VERSION, menu, jskatView, targetScreen, screenPosition);
jskatMainWindow.show();
if (JSkatOptions.instance().getBoolean(Option.SHOW_TIPS_AT_START_UP)) {
JSkatEventBus.INSTANCE.post(new ShowWelcomeInformationCommand());
}
if (JSkatOptions.instance().getBoolean(Option.CHECK_FOR_NEW_VERSION_AT_START_UP)) {
JSkatMaster.INSTANCE.checkJSkatVersion(VERSION, VersionChecker.getLatestVersion());
}
}
private void showSplashScreen(Screen targetScreen, final Stage splashStage, Task<?> startupTask,
InitializationCompleteHandler initializationCompleteHandler) {
splashScreenProgressText.textProperty().bind(startupTask.messageProperty());
splashScreenProgressBar.progressProperty().bind(startupTask.progressProperty());
startupTask.stateProperty().addListener((progressValue, oldState, newState) -> {
if (Worker.State.SUCCEEDED.equals(newState)) {
splashScreenProgressBar.progressProperty().unbind();
splashScreenProgressBar.setProgress(1);
splashStage.toFront();
FadeTransition fadeSplashScreen = new FadeTransition(Duration.seconds(1), splashScreenLayout);
fadeSplashScreen.setFromValue(1.0);
fadeSplashScreen.setToValue(0.0);
fadeSplashScreen.setOnFinished(actionEvent -> splashStage.hide());
fadeSplashScreen.play();
initializationCompleteHandler.complete();
}
});
Scene splashScene = new Scene(splashScreenLayout);
splashStage.initStyle(StageStyle.UNDECORATED);
splashStage.setScene(splashScene);
final Rectangle2D bounds = targetScreen.getBounds();
splashStage.setX(bounds.getMinX() + bounds.getWidth() / 2 - SPLASH_WIDTH / 2);
splashStage.setY(bounds.getMinY() + bounds.getHeight() / 2 - SPLASH_HEIGHT / 2);
splashStage.show();
}
private static Screen getTargetScreen(Point2D savedScreenPosition) {
for (Screen screen : Screen.getScreens()) {
if (screen.getVisualBounds().contains(savedScreenPosition)) {
return screen;
}
}
return Screen.getPrimary();
}
private static Point2D getSavedScreenPosition() {
Point mainFramePosition = JSkatOptions.instance().getMainFramePosition();
return new Point2D(mainFramePosition.getX(), mainFramePosition.getY());
}
private interface InitializationCompleteHandler {
public void complete();
}
private class InitializedGuiElements {
final MenuBar menu;
final JSkatViewImpl jskatView;
public InitializedGuiElements(MenuBar menu, JSkatViewImpl jskatView) {
this.menu = menu;
this.jskatView = jskatView;
}
}
}