package de.uni_hannover.sra.minimax_simulator;
import de.uni_hannover.sra.minimax_simulator.config.Config;
import de.uni_hannover.sra.minimax_simulator.config.ConfigurationLoader;
import de.uni_hannover.sra.minimax_simulator.config.PropertiesFileConfigLoader;
import de.uni_hannover.sra.minimax_simulator.model.user.Workspace;
import de.uni_hannover.sra.minimax_simulator.resources.DefaultResourceBundleLoader;
import de.uni_hannover.sra.minimax_simulator.resources.PropertyResourceControl;
import de.uni_hannover.sra.minimax_simulator.resources.ResourceBundleLoader;
import de.uni_hannover.sra.minimax_simulator.resources.TextResource;
import de.uni_hannover.sra.minimax_simulator.ui.gui.FXMainController;
import javafx.application.Application;
import javafx.application.HostServices;
import javafx.application.Platform;
import javafx.collections.ObservableList;
import javafx.fxml.FXMLLoader;
import javafx.fxml.JavaFXBuilderFactory;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;
/**
* The main class of the simulator. It initializes and launches the JavaFX application
* and provides some static methods needed by several classes.
*
* @author Philipp Rohde
*/
public class Main extends javafx.application.Application {
/** the primary {@link Stage} of the JavaFX application */
private static Stage primaryStage;
/** the {@link Workspace} used - initializes an empty workspace (no project loaded) */
private static Workspace workspace = new Workspace();
/** object for loading resources */
private static ResourceBundleLoader resourceLoader;
/** version information */
private static Version version;
/** logger */
private static final Logger LOG = setupLogger();
/** {@link HostServices} for opening files with system default application */
private static HostServices hostServices;
/**
* Starts the JavaFX application.
*
* @param primaryStage
* the primary {@link Stage} of the JavaFX application
* @throws Exception
* thrown if an error occurs during start up
*/
@Override
public void start(Stage primaryStage) throws Exception {
Main.primaryStage = primaryStage;
version = new Version(this.getClass());
hostServices = getHostServices();
LOG.info("Starting version " + version.getVersionNumber());
// check if Java 8u40 or higher is available
if (version.isJvmLower(1, 8, 0, 40)) {
String jvmVersion = version.getJvmMajor() + "." + version.getJvmFeature() + "." + version.getJvmUpdate() + "_" + version.getJvmBuild();
LOG.severe("Java 1.8.0_40 or higher needed but found " + jvmVersion);
Platform.exit(); // shut down JavaFX application
return; // prevent further initialization because shutdown needs some time
}
// Initialize config, read from file if existing
try {
new PropertiesFileConfigLoader(PropertiesFileConfigLoader.MissingConfigStrategy.USE_DEFAULT).configure(Config.class);
} catch (ConfigurationLoader.ConfigurationException e) {
LOG.severe("Can not initialize configuration!");
throw e;
}
LOG.info("Configuration loaded.");
// Initialize resource loader for clients (text boxes etc...)
getResourceLoader();
LOG.info("Initializing UI...");
URL location = getClass().getResource("/fxml/minimax-sim.fxml");
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setLocation(location);
fxmlLoader.setBuilderFactory(new JavaFXBuilderFactory());
Parent root = fxmlLoader.load(location.openStream());
Scene scene = new Scene(root, 1200, 705);
scene.getStylesheets().add("css/application.css");
Main.primaryStage.setScene(scene);
FXMainController mainController = fxmlLoader.getController();
Main.primaryStage.setOnCloseRequest((WindowEvent event) -> {
if (!mainController.exitApplication()) {
event.consume(); // do not close the application
}
});
TextResource res = resourceLoader.getTextResource("application");
Main.primaryStage.setTitle(res.format("title", version.getVersionNumber()));
// set application icon
Main.primaryStage.getIcons().add(new Image("images/nuvola/cpu.png"));
Main.primaryStage.getIcons().add(new Image("images/nuvola/cpu-big.png"));
Main.primaryStage.setResizable(true);
Main.primaryStage.show();
}
/**
* Gets the primary {@link Stage} of the application.
*
* @return
* the application's primary {@code Stage}
*/
public static Stage getPrimaryStage() {
return primaryStage;
}
/**
* Gets a list of all icons of the application.
*
* @return
* a list containing all icons of the application
*/
public static ObservableList<Image> getAppIcon() {
return primaryStage.getIcons();
}
/**
* Gets the {@link ResourceBundleLoader} of the application.<br>
* If it does not already exist it will be initialized with the correct language.
* The language setting of the JVM will be set to the same language.
*
* @return
* the {@code ResourceBundleLoader} used by the application
*/
public static ResourceBundleLoader getResourceLoader() {
if (resourceLoader == null) {
Locale locale;
if (Config.getLocale() == null) {
locale = Locale.getDefault();
}
else {
try {
locale = new Locale(Config.getLocale());
Locale.setDefault(locale);
} catch (Exception e) {
// locale not supported
locale = Locale.getDefault();
LOG.log(Level.WARNING, "unsupported locale; fallback to default", e);
}
}
resourceLoader = new DefaultResourceBundleLoader(new PropertyResourceControl("text/"), locale);
}
return resourceLoader;
}
/**
* Gets the {@link TextResource} with the specified bundle name.
*
* @param bundleName
* the name of the resource bundle
* @return
* the {@code TextResource} with the specified bundle name
*/
public static TextResource getTextResource(String bundleName) {
return resourceLoader.getTextResource(bundleName);
}
/**
* Calls {@link Main#launch(String...)} for launching the JavaFX application.
*
* @param args
* the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
/**
* Gets the {@link Workspace} used by the application.
*
* @return
* the application's {@code Workspace}
*/
public static Workspace getWorkspace() {
return workspace;
}
/**
* Gets the version number.
*
* @return
* the version number as {@code String}
*/
public static String getVersionString() {
return version.getVersionNumber();
}
/**
* Initializes the application's logger.
*/
private static Logger setupLogger() {
final InputStream inputStream = Main.class.getResourceAsStream("/logging.properties");
try {
LogManager.getLogManager().readConfiguration(inputStream);
} catch (final IOException e) {
throw new Error("Cannot initialize logging", e);
}
return Logger.getLogger(Main.class.getName());
}
/**
* Gets the {@link HostServices} of the application.<br>
* This method is meant to be a static version of {@link Application#getHostServices()}.
*
* @return
* the {@code HostServices} of the application
*/
public static HostServices getHostServicesStatic() {
return hostServices;
}
}