package io.andrewohara.tinkertime.views; import java.awt.Desktop; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.FileNotFoundException; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import java.nio.file.Path; import java.nio.file.Paths; import java.sql.SQLException; import java.util.Arrays; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.JCheckBox; import javax.swing.JComponent; import javax.swing.JOptionPane; import org.apache.commons.io.FilenameUtils; import io.andrewohara.common.Util; import io.andrewohara.common.content.ImageManager; import io.andrewohara.common.views.Dialogs; import io.andrewohara.common.views.UrlLabels; import io.andrewohara.tinkertime.TinkerTimeLauncher; import io.andrewohara.tinkertime.controllers.ImportController; import io.andrewohara.tinkertime.controllers.ModManager; import io.andrewohara.tinkertime.controllers.ModManager.NoModSelectedException; import io.andrewohara.tinkertime.io.crawlers.CrawlerFactory; import io.andrewohara.tinkertime.io.kspLauncher.GameLauncher; import io.andrewohara.tinkertime.models.ConfigData; import io.andrewohara.tinkertime.models.mod.Mod; public class Actions { // -- Helpers --------------------------------------------------------- @SuppressWarnings("serial") public static abstract class TinkerAction extends AbstractAction { protected static final ImageManager IMAGE_MANAGER = new ImageManager();; protected final JComponent parent; protected final ModManager mm; private final Dialogs dialogs; private TinkerAction(String title, String iconName, JComponent parent, ModManager mm, Dialogs dialogs){ super(title, iconName != null ? IMAGE_MANAGER.getIcon(iconName): null); this.parent = parent; this.mm = mm; this.dialogs = dialogs; putValue(Action.SHORT_DESCRIPTION, title); } @Override public void actionPerformed(ActionEvent evt) { try { call(); } catch (Exception e){ dialogs.errorDialog(parent, e); } } public TinkerAction withoutIcon(){ putValue(Action.SMALL_ICON, null); return this; } protected abstract void call() throws Exception; } @SuppressWarnings("serial") private static final class GoToUrlAction extends TinkerAction { private final URL url; GoToUrlAction(String title, String url, String iconPath, JComponent parent, Dialogs dialogs) { super(title, iconPath, parent, null, dialogs); try { this.url = new URL(url); } catch (MalformedURLException e) { throw new RuntimeException(e); } } @Override protected void call() throws Exception { Util.goToHyperlink(url); } } // -- Actions ----------------------------------------------------------- @SuppressWarnings("serial") public static class AddModAction extends TinkerAction { public AddModAction(JComponent parent, ModManager mm, Dialogs dialogs){ super("Add Mod", "icon/glyphicons_432_plus.png", parent, mm, dialogs); } @Override protected void call() throws Exception { // Get URL from user String urlString = JOptionPane.showInputDialog( parent, "Please enter the URL of the mod you would like to" + " add.\ne.g. http://www.curse.com/ksp-mods/kerbal/220221-mechjeb\n\n" + "Supported Hosts are " + Arrays.asList(CrawlerFactory.ACCEPTED_MOD_HOSTS), "Enter Mod Page URL", JOptionPane.QUESTION_MESSAGE ); if (urlString == null || urlString.trim().isEmpty()){ return; } // Try to add Mod try { mm.downloadNewMod(new URL(urlString)); } catch(MalformedURLException ex){ mm.downloadNewMod(new URL("http://" + urlString)); } } } @SuppressWarnings("serial") public static class DeleteModAction extends TinkerAction { public DeleteModAction(JComponent parent, ModManager mm, Dialogs dialogs){ super("Delete Mod", "icon/glyphicons_433_minus.png", parent, mm, dialogs); } @Override protected void call() throws Exception { try { Mod selectedMod = mm.getSelectedMod(); if (TinkerDialogs.confirmDeleteMod(parent, selectedMod.getName())){ mm.deleteMod(selectedMod); } } catch (NoModSelectedException ex){ // Do Nothing } } } @SuppressWarnings("serial") public static class UpdateModAction extends TinkerAction { public UpdateModAction(JComponent parent, ModManager mm, Dialogs dialogs){ this("Update Mod", parent, mm, dialogs); } private UpdateModAction(String title, JComponent parent, ModManager mm, Dialogs dialogs){ super(title, "icon/glyphicons_181_download_alt.png", parent, mm, dialogs); } @Override protected void call() throws Exception { try { mm.updateMod(mm.getSelectedMod(), true); } catch (NoModSelectedException ex){ // Do Nothing } } } @SuppressWarnings("serial") public static class UpdateAllAction extends UpdateModAction { public UpdateAllAction(JComponent parent, ModManager mm, Dialogs dialogs) { super("Update All", parent, mm, dialogs); } @Override protected void call() throws Exception { mm.updateMods(); } } @SuppressWarnings("serial") public static class CheckforUpdatesAction extends TinkerAction { public CheckforUpdatesAction(JComponent parent, ModManager mm, Dialogs dialogs){ super("Check for Mod Updates", "icon/glyphicons_027_search.png", parent, mm, dialogs); } @Override protected void call() throws Exception { mm.checkForModUpdates(); } } @SuppressWarnings("serial") public static class EnableDisableModAction extends TinkerAction { public EnableDisableModAction(JComponent parent, ModManager mm, Dialogs dialogs){ super("Enable/Disable", "icon/glyphicons_457_transfer.png", parent, mm, dialogs); } @Override protected void call() throws Exception { try { mm.toggleMod(mm.getSelectedMod()); } catch (NoModSelectedException ex){ // Do Nothing } } } public static TinkerAction newHelpAction(JComponent parent, Dialogs dialogs){ return new GoToUrlAction( "Help", "https://github.com/oharaandrew314/TinkerTime/wiki", "icon/glyphicons_194_circle_question_mark.png", parent, dialogs ); } public static TinkerAction newWebsiteAction(JComponent parent, Dialogs dialogs){ return new GoToUrlAction("Website", "http://andrewohara.io/TinkerTime", null, parent, dialogs); } @SuppressWarnings("serial") public static class AboutAction extends TinkerAction { public AboutAction(JComponent parent, ModManager mm, Dialogs dialogs){ super("About", "icon/glyphicons_003_user.png", parent, mm, dialogs); } @Override protected void call() throws Exception { Object[] message = { TinkerTimeLauncher.FULL_NAME, "\n", "This work is licensed under the GNU GPL v3.0 License\n", new UrlLabels.UrlLink("View a copy of this license", new URL("http://opensource.org/licenses/gpl-3.0")).getComponent(), "\n", TinkerTimeLauncher.NAME + " uses Glyphicons (glyphicons.com)", "\n", new UrlLabels.UrlLink(TinkerTimeLauncher.NAME + " Website", new URL("http://andrewohara.io/TinkerTime")).getComponent(), }; JOptionPane.showMessageDialog( parent, message, "About " + TinkerTimeLauncher.NAME, JOptionPane.INFORMATION_MESSAGE, IMAGE_MANAGER.getIcon("icon/app/icon 128x128.png") ); } } @SuppressWarnings("serial") public static class ContactAction extends TinkerAction { public ContactAction(JComponent parent, ModManager mm, Dialogs dialogs){ super("Contact Me", "icon/glyphicons_010_envelope.png", parent, mm, dialogs); } @Override protected void call() throws Exception { Desktop desktop = Desktop.getDesktop(); String message = "mailto:[email protected]?subject=TinkerTime%20Support%20Request"; URI uri = URI.create(message); desktop.mail(uri); } } @SuppressWarnings("serial") public static class ExportMods extends TinkerAction { private final ImportController importController; private static final String ALL = "Export All Mods", ENABLED = "Export Enabled Mods"; public ExportMods(JComponent parent, ImportController importController, Dialogs dialogs){ super("Export Mods", "icon/glyphicons_359_file_export.png", parent, null, dialogs); this.importController = importController; } @Override protected void call() throws Exception { Object result = JOptionPane.showInputDialog( parent, "Which mods would you like to export?", "Export Mods", JOptionPane.QUESTION_MESSAGE, null, new String[] { ALL, ENABLED }, ALL); boolean enabledOnly = true; if (result == null){ return; } else if (result.equals(ALL)){ enabledOnly = false; } // Set default file extension if not set Path exportPath = FileChoosers.chooseImportExportFile(true); if (FilenameUtils.getExtension(exportPath.toString()).isEmpty()){ exportPath = Paths.get(exportPath.toString() + ".txt"); } int exported = importController.exportMods(exportPath, enabledOnly); JOptionPane.showMessageDialog( parent, String.format("%d Mods have been exported.", exported), "Exported", JOptionPane.INFORMATION_MESSAGE ); } } @SuppressWarnings("serial") public static class ImportMods extends TinkerAction { private final ImportController importController; public ImportMods(JComponent parent, ImportController importController, Dialogs dialogs){ super("Import Mods", "icon/glyphicons-359-file-import.png", parent, null, dialogs); this.importController = importController; } @Override protected void call() throws Exception { int imported = importController.importMods(FileChoosers.chooseImportExportFile(false)); JOptionPane.showMessageDialog( parent, String.format("%d Mod(s) have been imported.", imported), "Imported", JOptionPane.INFORMATION_MESSAGE ); } } @SuppressWarnings("serial") public static class UpdateTinkerTime extends TinkerAction { public UpdateTinkerTime(JComponent parent, ModManager mm, Dialogs dialogs){ super("Check for Tinker Time Update", null, parent, mm, dialogs); } @Override protected void call() throws Exception { mm.tryUpdateModManager(); } } @SuppressWarnings("serial") public static class AddModZip extends TinkerAction { public AddModZip(JComponent parent, ModManager mm, Dialogs dialogs){ super("Add Mod from Zip File", "icon/glyphicons_410_compressed.png", parent, mm, dialogs); } @Override protected void call() throws Exception { try { mm.addModZip(FileChoosers.chooseModZip()); } catch (FileNotFoundException e){ // Do nothing if file was not chosen } } } @SuppressWarnings("serial") public static class LaunchKspAction extends TinkerAction { private final GameLauncher launcher; public LaunchKspAction(JComponent parent, ModManager mm, GameLauncher launcher, Dialogs dialogs){ super("Launch KSP", "icon/rocket.png", parent, mm, dialogs); this.launcher = launcher; } @Override protected void call() throws Exception { launcher.launchGame(); } } @SuppressWarnings("serial") public static class OpenGameDataFolder extends TinkerAction { private final ConfigData config; public OpenGameDataFolder(JComponent parent, ModManager mm, ConfigData config, Dialogs dialogs) { super("Open GameData Folder", "icon/glyphicons_144_folder_open.png", parent, mm, dialogs); this.config = config; } @Override protected void call() throws Exception { Desktop.getDesktop().open(config.getSelectedInstallation().getGameDataPath().toFile()); } } @SuppressWarnings("serial") public static class LaunchInstallationSelector extends TinkerAction { private final InstallationSelectorView selector; public LaunchInstallationSelector(JComponent parent, ModManager mm, InstallationSelectorView selector, Dialogs dialogs) { super("Select KSP Installation", "icon/glyphicons_342_hdd.png", parent, mm, dialogs); this.selector = selector; } @Override protected void call() throws Exception { selector.toDialog(); } } ////////////////////////////// // Options Action Listeners // ////////////////////////////// public static class CheckForAppUpdatesAction implements ActionListener { private final JCheckBox checkBox; private final ConfigData config; private final Dialogs dialogs; public CheckForAppUpdatesAction(JCheckBox checkBox, ConfigData config, Dialogs dialogs){ this.checkBox = checkBox; this.config = config; this.dialogs = dialogs; } @Override public void actionPerformed(ActionEvent e) { try { config.setCheckForAppUpdatesOnStartup(checkBox.isSelected()); } catch (SQLException e1) { dialogs.errorDialog(checkBox, e1); } } } public static class CheckForModUpdatesAction implements ActionListener { private final JCheckBox checkBox; private final ConfigData config; private final Dialogs dialogs; public CheckForModUpdatesAction(JCheckBox checkBox, ConfigData config, Dialogs dialogs){ this.checkBox = checkBox; this.config = config; this.dialogs = dialogs; } @Override public void actionPerformed(ActionEvent e) { try { config.setCheckForModUpdatesOnStartup(checkBox.isSelected()); } catch (SQLException e1) { dialogs.errorDialog(checkBox, e1); } } } @SuppressWarnings("serial") public static class UpdateLaunchArgsAction extends AbstractAction { private final ConfigData config; private final Dialogs dialogs; public UpdateLaunchArgsAction(ConfigData config, Dialogs dialogs){ super("KSP Launch Args"); this.config = config; this.dialogs = dialogs; } @Override public void actionPerformed(ActionEvent e) { try { String curArgs = config.getLaunchArguments(); String newArgs = JOptionPane.showInputDialog(null, "Modify the Launch Args for KSP", curArgs); if (newArgs != null && !newArgs.equals(curArgs)){ config.setLaunchArguments(newArgs); } } catch (SQLException e1){ dialogs.errorDialog(null, "Error updating KSP Launch Args", e1); } } } }