package io.andrewohara.tinkertime; import java.awt.BorderLayout; import java.awt.Image; import java.awt.SplashScreen; import java.net.MalformedURLException; import java.nio.file.Path; import java.nio.file.Paths; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedList; import java.util.List; import java.util.concurrent.Callable; import javax.swing.JFrame; import javax.swing.JMenuBar; import javax.swing.JToolBar; import org.flywaydb.core.Flyway; import org.flywaydb.core.api.FlywayException; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.j256.ormlite.support.ConnectionSource; import io.andrewohara.common.content.ImageManager; import io.andrewohara.common.version.Version; import io.andrewohara.common.views.Dialogs; import io.andrewohara.tinkertime.controllers.ModManager; import io.andrewohara.tinkertime.controllers.ModUpdateCoordinator; import io.andrewohara.tinkertime.db.DbConnectionString; import io.andrewohara.tinkertime.io.crawlers.CrawlerFactory.UnsupportedHostException; import io.andrewohara.tinkertime.models.ConfigData; import io.andrewohara.tinkertime.views.InstallationSelectorView; import io.andrewohara.tinkertime.views.SelectedInstallationView; import io.andrewohara.tinkertime.views.modSelector.ModListCellRenderer; import io.andrewohara.tinkertime.views.modSelector.ModSelectorPanelController; /** * Main Class for Tinker Time * * @author Andrew O'Hara */ public class TinkerTimeLauncher implements Runnable { public static final String NAME = "Tinker Time", AUTHOR = "oharaandrew314", DOWNLOAD_URL = "https://kerbalstuff.com/mod/243"; public static final Version VERSION = Version.valueOf("2.0.1"); public static final String SAFE_NAME = NAME.replace(" ", ""), FULL_NAME = String.format("%s %s by %s", NAME, VERSION, AUTHOR); private final Collection<Runnable> startupTasks = new LinkedList<>(); @Inject TinkerTimeLauncher(ConfigVerifier configVerifier, SetupListeners setupListeners, LoadModsTask startupModLoader, UpdateChecker updateChecker, MainFrameLauncher mainFrameLauncher){ startupTasks.add(setupListeners); startupTasks.add(configVerifier); startupTasks.add(startupModLoader); startupTasks.add(updateChecker); startupTasks.add(mainFrameLauncher); } @Override public void run() { for (Runnable task : startupTasks){ task.run(); } } public static Path getHomePath(){ return Paths.get(System.getProperty("user.home"), "Documents", TinkerTimeLauncher.NAME); } public static void main(String[] args) { Injector injector = Guice.createInjector(new MainModule()); // Test Database Connection injector.getInstance(TestConnectionTask.class).call(); // Migrate database injector.getInstance(DatabaseMigrator.class).run(); // Launch Application TinkerTimeLauncher launcher = injector.getInstance(TinkerTimeLauncher.class); launcher.run(); } /////////////////// // Startup Tasks // /////////////////// public static class TestConnectionTask implements Callable<Void> { private final ConnectionSource dbConnection; private final Dialogs dialogs; @Inject TestConnectionTask(ConnectionSource dbConnection, Dialogs dialogs){ this.dbConnection = dbConnection; this.dialogs = dialogs; } @Override public Void call() { try { dbConnection.getReadWriteConnection(); } catch (SQLException e) { dialogs.errorDialog(null, "Error Connection to Database", e); } return null; } } public static class DatabaseMigrator implements Runnable { private final DbConnectionString connectionString; @Inject DatabaseMigrator(DbConnectionString connectionString){ this.connectionString = connectionString; } @Override public void run() { // Perform Database Migration Flyway flyway = new Flyway(); flyway.setBaselineOnMigrate(true); flyway.setLocations("io/andrewohara/tinkertime/db/migration"); flyway.setDataSource(connectionString.getUrl(), null, null); try { flyway.migrate(); } catch (FlywayException e){ flyway.repair(); throw e; } } } private static class ConfigVerifier implements Runnable { private final ConfigData config; private final InstallationSelectorView selector; @Inject ConfigVerifier(ConfigData config, InstallationSelectorView selector){ this.config = config; this.selector = selector; } @Override public void run() { if (config.getSelectedInstallation() == null){ selector.toDialog(); } } } private static class SetupListeners implements Runnable { private final ModSelectorPanelController modSelectorPanelController; private final ModListCellRenderer modListCellRenderer; private final ModUpdateCoordinator modUpdateCoordinator; private final SelectedInstallationView installationView; @Inject SetupListeners(ModUpdateCoordinator modUpdateCoordinator, ModSelectorPanelController modSelectorPanelController, ModListCellRenderer modListCellRender, SelectedInstallationView installationView) { this.modUpdateCoordinator = modUpdateCoordinator; this.modSelectorPanelController = modSelectorPanelController; this.modListCellRenderer = modListCellRender; this.installationView = installationView; } @Override public void run() { modUpdateCoordinator.setListeners(modSelectorPanelController, modListCellRenderer, installationView); } } private static class LoadModsTask implements Runnable { private final ModUpdateCoordinator updateCooridnator; private final ConfigData config; @Inject LoadModsTask(ModUpdateCoordinator updateCooridnator, ConfigData config){ this.updateCooridnator = updateCooridnator; this.config = config; } @Override public void run() { updateCooridnator.changeInstallation(config.getSelectedInstallation()); } } private static class UpdateChecker implements Runnable { private final ConfigData config; private final ModManager modManager; private final Dialogs dialogs; @Inject UpdateChecker(ConfigData config, ModManager modManager, Dialogs dialogs){ this.config = config; this.modManager = modManager; this.dialogs = dialogs; } @Override public void run() { // Check for App update on Startup if (config.isCheckForAppUpdatesOnStartup()){ try { modManager.tryUpdateModManager(); } catch (UnsupportedHostException | MalformedURLException | SQLException e) { dialogs.errorDialog(null, "Error Checking for App Updates", e); } } // Check for Mod Updates on Startup if (config.isCheckForModUpdatesOnStartup()){ try { modManager.checkForModUpdates(); } catch (UnsupportedHostException e) { dialogs.errorDialog(null, "Error Checking for Mod Updates", e); } } } } private static class MainFrameLauncher implements Runnable { private final ModSelectorPanelController modSelectorPanelController; private final JMenuBar menuBar; private final JToolBar toolBar; @Inject MainFrameLauncher(ModSelectorPanelController modSelectorPanelController, JMenuBar menuBar, JToolBar toolBar){ this.modSelectorPanelController = modSelectorPanelController; this.menuBar = menuBar; this.toolBar = toolBar; } @Override public void run() { // Get App Icons ImageManager imageManager = new ImageManager(); List<Image> appIcons = new ArrayList<Image>(); appIcons.add(imageManager.getImage("icon/app/icon 128x128.png")); appIcons.add(imageManager.getImage("icon/app/icon 64x64.png")); appIcons.add(imageManager.getImage("icon/app/icon 32x32.png")); appIcons.add(imageManager.getImage("icon/app/icon 16x16.png")); // Hide Splash Screen so the JFrame does not hide when appearing SplashScreen s = SplashScreen.getSplashScreen(); if (s != null){ s.close(); } // Initialize Frame JFrame frame = new JFrame(TinkerTimeLauncher.FULL_NAME); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); frame.setIconImages(appIcons); frame.setJMenuBar(menuBar); frame.add(toolBar, BorderLayout.NORTH); frame.add(modSelectorPanelController.getComponent(), BorderLayout.CENTER); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); frame.toFront(); } } }