Package se.llbit.chunky.launcher

Source Code of se.llbit.chunky.launcher.ChunkyLauncher

/* Copyright (c) 2013-2014 Jesper Öqvist <jesper@llbit.se>
*
* This file is part of Chunky.
*
* Chunky 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.
*
* Chunky 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 Chunky.  If not, see <http://www.gnu.org/licenses/>.
*/
package se.llbit.chunky.launcher;

import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.File;
import java.net.URL;
import java.util.Scanner;
import java.util.concurrent.CountDownLatch;

import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

import se.llbit.chunky.PersistentSettings;
import se.llbit.chunky.launcher.ui.LaunchErrorDialog;
import se.llbit.chunky.resources.MinecraftFinder;
import se.llbit.chunky.resources.SettingsDirectory;
import se.llbit.ui.Adjuster;

/**
* The main Chunky Launcher window.
* @author Jesper Öqvist <jesper.oqvist@cs.lth.se>
*/
@SuppressWarnings("serial")
public class ChunkyLauncher extends JFrame implements UpdateListener {

  private static final String LAUNCHER_VERSION = "v1.8.8";

  protected String java;
  private final ChunkyDeployer deployer;
  private JTextField minecraftDirField;
  private final LauncherSettings settings;

  private final JCheckBox debugConsoleCB = new JCheckBox("Enable debug console");
  private final JCheckBox verboseLoggingCB = new JCheckBox("Verbose logging");
  private final JCheckBox closeConsoleOnExitCB = new JCheckBox("Close console when Chunky exits");
  private final JCheckBox alwaysShowLauncherCB = new JCheckBox("Always show the launcher");
  private final JTextField jreDirField = new JTextField(20);
  private final JTextField javaOptions = new JTextField(20);
  private final JTextField chunkyOptions = new JTextField(20);
  private final JComboBox versionCB = new JComboBox();
  private final JButton checkForUpdateBtn = new JButton("Check for Update");
  private final JLabel busyLbl = new JLabel();
  private final JCheckBox advancedSettingsToggle = new JCheckBox("Advanced settings");

  private final Object updateLock = new Object();
  private volatile boolean isBusy = false;

  private final Adjuster memoryLimitAdjuster = new Adjuster("Memory limit (MiB)",
      "<html>Maximum Java heap space in megabytes (MiB)<br>"
      + "Do not set this greater than the available memory in your computer!",
      1<<9, 1<<14) {
    {
      setLogarithmicMode();
      setClampMax(false);
    }

    @Override
    public void valueChanged(double newValue) {
      settings.memoryLimit = (int) newValue;
    }

    @Override
    public void update() {
      set(settings.memoryLimit);
    }
  };
  protected UpdateChecker updateThread;


  public ChunkyLauncher(ChunkyDeployer deployer, LauncherSettings settings) {
    super("Chunky Launcher");

    this.deployer = deployer;

    this.settings = settings;
    memoryLimitAdjuster.update();

    buildUI();
  }

  /**
   * Set the busy indicator
   * @param busy
   */
  public void setBusy(final boolean busy) {
    synchronized (updateLock) {
      isBusy = busy;
    }
    SwingUtilities.invokeLater(new Runnable() {
      @Override
      public void run() {
        busyLbl.setVisible(isBusy);
      }
    });
  }

  /**
   * Set the busy indicator on Event Dispatch Thread.
   * @param busy
   */
  public void setBusyEDT(final boolean busy) {
    synchronized (updateLock) {
      isBusy = busy;
    }
    SwingUtilities.invokeLater(new Runnable() {
      @Override
      public void run() {
        busyLbl.setVisible(isBusy);
      }
    });
  }

  private void buildUI() {
    memoryLimitAdjuster.update();

    setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
        KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "Close Dialog");
    getRootPane().getActionMap().put("Close Dialog", new AbstractAction() {
      @Override
      public void actionPerformed(ActionEvent arg0) {
        closeDialog();
      }
    });

    alwaysShowLauncherCB.setSelected(settings.showLauncher);

    JLabel info = new JLabel("<html><b>Chunky startup settings:");

    JLabel versionLbl = new JLabel("Chunky version:");

    updateVersionList();

    final File minecraftDir = MinecraftFinder.getMinecraftDirectory();
    JLabel minecraftDirLbl = new JLabel("Minecraft directory:");
    minecraftDirField = new JTextField(20);
    minecraftDirField.setText(minecraftDir.getAbsolutePath());
    minecraftDirField.setToolTipText("The Minecraft directory is used to find the default textures");
    JButton browseMcBtn = new JButton("Browse...");
    browseMcBtn.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent arg0) {
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setDialogTitle("Select Minecraft Directory");
        fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        if (minecraftDir.isDirectory()) {
          fileChooser.setCurrentDirectory(minecraftDir);
        }
        int result = fileChooser.showOpenDialog(null);
        if (result == JFileChooser.APPROVE_OPTION) {
          File selectedDirectory = fileChooser.getSelectedFile();
          if (MinecraftFinder.getMinecraftJar(selectedDirectory, false) != null) {
            setMinecraftDir(selectedDirectory);
          } else {
            Dialogs.message(ChunkyLauncher.this,
                "<html>Warning: could not find a valid Minecraft installation in the selected directory.<br>"
                + "The default directory will be used.");
          }
        }
      }
    });

    JButton cancelBtn = new JButton("Cancel");
    cancelBtn.setMnemonic(KeyEvent.VK_C);
    cancelBtn.setToolTipText("Close the Chunky launcher");
    cancelBtn.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent arg0) {
        closeDialog();
      }
    });

    JButton launchBtn = new JButton("Launch");
    launchBtn.setMnemonic(KeyEvent.VK_L);
    launchBtn.setToolTipText("Launch Chunky using these settings");
    launchBtn.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent arg0) {
        settings.javaDir = jreDirField.getText();
        settings.debugConsole = debugConsoleCB.isSelected();
        settings.verboseLogging = verboseLoggingCB.isSelected();
        settings.closeConsoleOnExit = closeConsoleOnExitCB.isSelected();
        settings.javaOptions = javaOptions.getText();
        settings.chunkyOptions = chunkyOptions.getText();
        settings.version = ((VersionInfo) versionCB.getSelectedItem()).name;
        settings.showLauncher = alwaysShowLauncherCB.isSelected();
        settings.showAdvancedSettings = advancedSettingsToggle.isSelected();

        // resolve specific version
        VersionInfo version = ChunkyDeployer.resolveVersion(settings.version);
        if (!ChunkyDeployer.canLaunch(version, ChunkyLauncher.this, true)) {
          return;
        }

        PersistentSettings.setMinecraftDirectory(minecraftDirField.getText());
        if (deployer.launchChunky(ChunkyLauncher.this, settings, version,
            ChunkyMode.GUI) == 0) {
          settings.save();
          setVisible(false);
          dispose();
        } else {
          launchError(settings, version);
        }
      }
    });

    checkForUpdateBtn.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        synchronized (updateLock) {
          if (!isBusy) {
            setBusyEDT(true);
            updateThread = new UpdateChecker(settings, ChunkyLauncher.this);
            updateThread.start();
          }
        }
      }
    });

    JLabel logo = new JLabel();
    URL url = getClass().getResource("/chunky-cfg.png");
    if (url != null) {
      Image img = Toolkit.getDefaultToolkit().getImage(url);
      setIconImage(img);
      logo.setIcon(new ImageIcon(img));
    }

    url = getClass().getResource("/busy.gif");
    if (url != null) {
      busyLbl.setIcon(new ImageIcon(Toolkit.getDefaultToolkit().getImage(url)));
    }
    busyLbl.setVisible(false);

    getRootPane().setDefaultButton(launchBtn);

    final JPanel advancedPanel = buildAdvancedPanel();
    advancedPanel.setVisible(settings.showAdvancedSettings);

    advancedSettingsToggle.setSelected(settings.showAdvancedSettings);
    advancedSettingsToggle.setIcon(Icons.expand);
    advancedSettingsToggle.setRolloverIcon(Icons.expandHover);
    advancedSettingsToggle.setSelectedIcon(Icons.collapse);
    advancedSettingsToggle.setRolloverSelectedIcon(Icons.collapseHover);
    advancedSettingsToggle.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        JCheckBox source = (JCheckBox) e.getSource();
        advancedPanel.setVisible(source.isSelected());
        ChunkyLauncher.this.pack();
      }
    });

    JPanel panel = new JPanel();
    GroupLayout layout = new GroupLayout(panel);
    panel.setLayout(layout);

    JLabel launcherVersionLbl = new JLabel(LAUNCHER_VERSION);

    layout.setAutoCreateContainerGaps(true);
    layout.setHorizontalGroup(layout.createSequentialGroup()
      .addGroup(layout.createParallelGroup()
        .addComponent(logo)
        .addComponent(launcherVersionLbl)
      )
      .addPreferredGap(ComponentPlacement.UNRELATED)
      .addGroup(layout.createParallelGroup()
        .addGroup(layout.createSequentialGroup()
          .addComponent(info)
          .addGap(20, 40, Short.MAX_VALUE)
        )
        .addGroup(layout.createSequentialGroup()
          .addComponent(versionLbl)
          .addPreferredGap(ComponentPlacement.RELATED)
          .addComponent(versionCB)
          .addPreferredGap(ComponentPlacement.RELATED)
          .addComponent(checkForUpdateBtn)
          .addComponent(busyLbl)
        )
        .addGroup(layout.createSequentialGroup()
          .addComponent(minecraftDirLbl)
          .addPreferredGap(ComponentPlacement.RELATED)
          .addComponent(minecraftDirField)
          .addPreferredGap(ComponentPlacement.RELATED)
          .addComponent(browseMcBtn)
        )
        .addGroup(memoryLimitAdjuster.horizontalGroup(layout))
        .addComponent(advancedSettingsToggle)
        .addComponent(advancedPanel)
        .addGroup(layout.createSequentialGroup()
          .addComponent(alwaysShowLauncherCB)
          .addPreferredGap(ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
          .addComponent(cancelBtn)
          .addPreferredGap(ComponentPlacement.RELATED)
          .addComponent(launchBtn)
        )
      )
    );
    layout.setVerticalGroup(layout.createSequentialGroup()
      .addGroup(layout.createParallelGroup()
        .addGroup(layout.createSequentialGroup()
          .addComponent(logo)
          .addPreferredGap(ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
          .addComponent(launcherVersionLbl)
        )
        .addGroup(layout.createSequentialGroup()
          .addComponent(info)
          .addPreferredGap(ComponentPlacement.UNRELATED)
          .addGroup(layout.createParallelGroup(Alignment.BASELINE)
            .addComponent(versionLbl)
            .addComponent(versionCB)
            .addComponent(checkForUpdateBtn)
            .addComponent(busyLbl)
          )
          .addPreferredGap(ComponentPlacement.UNRELATED)
          .addGroup(layout.createParallelGroup(Alignment.BASELINE)
            .addComponent(minecraftDirLbl)
            .addComponent(minecraftDirField)
            .addComponent(browseMcBtn)
          )
          .addPreferredGap(ComponentPlacement.UNRELATED)
          .addGroup(memoryLimitAdjuster.verticalGroup(layout))
          .addPreferredGap(ComponentPlacement.UNRELATED)
          .addComponent(advancedSettingsToggle)
          .addComponent(advancedPanel)
          .addPreferredGap(ComponentPlacement.UNRELATED)
          .addGroup(layout.createParallelGroup()
            .addComponent(alwaysShowLauncherCB)
            .addComponent(cancelBtn)
            .addComponent(launchBtn)
          )
        )
      )
    );

    setContentPane(panel);
    pack();
  }

  /**
   * Opens the launch error dialog.
   * @param settings
   * @param version
   */
  protected static void launchError(final LauncherSettings settings,
      final VersionInfo version) {
    if (settings.debugConsole) {
      SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
          LaunchErrorDialog dialog = new LaunchErrorDialog(
            ChunkyDeployer.commandString(
                ChunkyDeployer.buildCommandLine(version, settings)));
          dialog.setVisible(true);
        }
      });
    } else {
      SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
          LaunchErrorDialog dialog = new LaunchErrorDialog(
            ChunkyDeployer.commandString(
                ChunkyDeployer.buildCommandLine(version, settings)));
          dialog.setVisible(true);
        }
      });
    }

  }

  private JPanel buildAdvancedPanel() {
    JLabel jreDirLbl = new JLabel("Java Runtime:");
    jreDirField.setText(getConfiguredJre());

    JButton browseJreBtn = new JButton("Browse...");

    JLabel javaOptionsLbl = new JLabel("Java options:");
    javaOptions.setText(settings.javaOptions);

    JLabel chunkyOptionsLbl = new JLabel("Chunky options:");

    JCheckBox downloadSnapshotsCB = new JCheckBox("Download snapshots");
    downloadSnapshotsCB.setSelected(settings.downloadSnapshots);
    downloadSnapshotsCB.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        JCheckBox source = (JCheckBox) e.getSource();
        settings.downloadSnapshots = source.isSelected();
        settings.save();
      }
    });

    browseJreBtn.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setDialogTitle("Select Java Installation");
        fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        File jreDir = new File(jreDirField.getText());
        if (jreDir.isDirectory()) {
          fileChooser.setCurrentDirectory(jreDir);
        }
        int result = fileChooser.showOpenDialog(null);
        if (result == JFileChooser.APPROVE_OPTION) {
          File selectedDirectory = fileChooser.getSelectedFile();
          File jreSubDir = new File(selectedDirectory, "jre");
          if (JreUtil.isJreDir(selectedDirectory)) {
            jreDirField.setText(selectedDirectory.getAbsolutePath());
          } else if (JreUtil.isJreDir(jreSubDir)) {
            jreDirField.setText(jreSubDir.getAbsolutePath());
          } else {
            Dialogs.message(ChunkyLauncher.this,
                "<html>Warning: could not find a valid Java installation in the selected directory.<br>"
                + "The default directory will be used.");
          }
        }
      }
    });

    debugConsoleCB.setToolTipText("Displays a debug console when Chunky is started");
    debugConsoleCB.setSelected(settings.debugConsole);

    verboseLoggingCB.setToolTipText("Enable verbose log output");
    verboseLoggingCB.setSelected(settings.verboseLogging);

    closeConsoleOnExitCB.setSelected(settings.closeConsoleOnExit);

    JLabel settingsDirLbl = new JLabel("Settings directory: ");
    JTextField settingsDir = new JTextField();
    settingsDir.setText(SettingsDirectory.defaultSettingsDirectory().getAbsolutePath());
    settingsDir.setEditable(false);

    JPanel panel = new JPanel();
    GroupLayout layout = new GroupLayout(panel);
    panel.setLayout(layout);

    layout.setHorizontalGroup(
      layout.createSequentialGroup()
      .addContainerGap()
      .addGroup(layout.createParallelGroup()
        .addGroup(layout.createSequentialGroup()
          .addComponent(jreDirLbl)
          .addPreferredGap(ComponentPlacement.RELATED)
          .addComponent(jreDirField)
          .addPreferredGap(ComponentPlacement.RELATED)
          .addComponent(browseJreBtn)
        )
        .addGroup(layout.createSequentialGroup()
          .addComponent(javaOptionsLbl)
          .addPreferredGap(ComponentPlacement.RELATED)
          .addComponent(javaOptions)
        )
        .addGroup(layout.createSequentialGroup()
          .addComponent(chunkyOptionsLbl)
          .addPreferredGap(ComponentPlacement.RELATED)
          .addComponent(chunkyOptions)
        )
        .addComponent(debugConsoleCB)
        .addComponent(verboseLoggingCB)
        .addComponent(closeConsoleOnExitCB)
        .addComponent(downloadSnapshotsCB)
        .addGroup(layout.createSequentialGroup()
          .addComponent(settingsDirLbl)
          .addPreferredGap(ComponentPlacement.RELATED)
          .addComponent(settingsDir)
        )
      )
      .addContainerGap()
    );
    layout.setVerticalGroup(
      layout.createSequentialGroup()
        .addContainerGap()
        .addPreferredGap(ComponentPlacement.UNRELATED)
        .addGroup(layout.createParallelGroup(Alignment.BASELINE)
          .addComponent(jreDirLbl)
          .addComponent(jreDirField)
          .addComponent(browseJreBtn)
        )
        .addPreferredGap(ComponentPlacement.UNRELATED)
        .addGroup(layout.createParallelGroup(Alignment.BASELINE)
          .addComponent(javaOptionsLbl)
          .addComponent(javaOptions)
        )
        .addPreferredGap(ComponentPlacement.UNRELATED)
        .addGroup(layout.createParallelGroup(Alignment.BASELINE)
          .addComponent(chunkyOptionsLbl)
          .addComponent(chunkyOptions)
        )
        .addPreferredGap(ComponentPlacement.UNRELATED)
        .addComponent(debugConsoleCB)
        .addPreferredGap(ComponentPlacement.RELATED)
        .addComponent(verboseLoggingCB)
        .addPreferredGap(ComponentPlacement.RELATED)
        .addComponent(closeConsoleOnExitCB)
        .addPreferredGap(ComponentPlacement.UNRELATED)
        .addComponent(downloadSnapshotsCB)
        .addPreferredGap(ComponentPlacement.UNRELATED)
        .addGroup(layout.createParallelGroup(Alignment.BASELINE)
          .addComponent(settingsDir)
          .addComponent(settingsDirLbl)
        )
        .addContainerGap()
    );
    panel.setBorder(BorderFactory.createTitledBorder("Advanced"));
    return panel;
  }

  private String getConfiguredJre() {
    String configuredJre = settings.javaDir;
    if (!configuredJre.isEmpty() && JreUtil.isJreDir(new File(configuredJre))) {
      return configuredJre;
    } else {
      return System.getProperty("java.home");
    }
  }

  protected void setMinecraftDir(File directory) {
    if (directory.isDirectory()) {
      minecraftDirField.setText(directory.getAbsolutePath());
      PersistentSettings.setMinecraftDirectory(directory.getAbsolutePath());
    }
  }

  protected void closeDialog() {
    dispose();
  }

  public static void main(String[] args) {
    LauncherSettings settings = new LauncherSettings();
    settings.load();

    /*
     * If there are command line arguments then we assume that Chunky should run
     * in headless mode, unless the --nolauncher command is present in which case
     * we strip that and start regularly, but without launcher. The --launcher
     * option overrides everything else and forces the launcher to appear.
     */

    boolean forceLauncher = false;
    ChunkyMode mode = ChunkyMode.GUI;
    String headlessOptions = "";

    if (args.length > 0) {
      mode = ChunkyMode.HEADLESS;
      for (String arg: args) {
        if (arg.equals("--nolauncher")) {
          mode = ChunkyMode.GUI;
        } else if (arg.equals("--launcher")) {
          forceLauncher = true;
        } else if (arg.equals("--version")) {
          System.out.println("Chunky Launcher " + LAUNCHER_VERSION);
          return;
        } else if (arg.equals("--verbose")) {
          settings.verboseLauncher = true;
        } else if (arg.equals("--update")) {
          UpdateChecker updateThread = new UpdateChecker(settings,
              new UpdateListener() {
                @Override
                public void updateError(String message) {
                }

                @Override
                public void updateAvailable(VersionInfo latest) {
                  System.out.println("Downloading Chunky " + latest + "...");
                  ConsoleUpdater.update(latest);
                }

                @Override
                public void noUpdateAvailable() {
                  System.out.println("Chunky is up to date");
                }
              });
          updateThread.start();
          return;
        } else if (arg.equals("--setup")) {
          // configure launcher settings
          doSetup(settings);
          settings.save();
          return;
        } else {
          if (!headlessOptions.isEmpty()) {
            headlessOptions += " ";
          }
          headlessOptions += arg;
        }
      }
      if (forceLauncher) {
        mode = ChunkyMode.GUI;
      }
    }

    if (mode == ChunkyMode.HEADLESS) {
      // Chunky is being run from the console => headless
      settings.debugConsole = true;
      settings.headless = true;
      settings.chunkyOptions = headlessOptions;
      ChunkyDeployer deployer = new ChunkyDeployer();
      deployer.deploy();
      VersionInfo version = ChunkyDeployer.resolveVersion(settings.version);
      if (ChunkyDeployer.canLaunch(version, null, false)) {
        int exitCode = deployer.launchChunky(null, settings, version,
            ChunkyMode.HEADLESS);
        if (exitCode != 0) {
          System.exit(exitCode);
        }
      } else {
        System.err.println("Failed to start Chunky. Command used:");
        System.err.println(ChunkyDeployer.commandString(
            ChunkyDeployer.buildCommandLine(version, settings)));
        System.exit(1);
      }
    } else {
      // Set up Look and Feel
      try {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        UIManager.put("Slider.paintValue", Boolean.FALSE);
      } catch (Exception e) {
        System.out.println("Failed to set native Look and Feel");
      }

      if (firstTimeSetup()) {
        ChunkyDeployer deployer = new ChunkyDeployer();
        boolean showLauncher = true;
        if (!forceLauncher && !settings.showLauncher) {
          // skip launcher only if we can launch this version
          VersionInfo version = ChunkyDeployer.resolveVersion(settings.version);
          if (ChunkyDeployer.canLaunch(version, null, false)) {
            if (deployer.launchChunky(null, settings, version,
                ChunkyMode.GUI) == 0) {
              showLauncher = false;
              return;
            } else {
              launchError(settings, version);
            }
          }
        }
        if (showLauncher) {
          deployer.deploy();
          JFrame launcher = new ChunkyLauncher(deployer, settings);
          //launcher.setLocationByPlatform(true);
          launcher.setLocationRelativeTo(null);
          launcher.setVisible(true);
        }
      }
    }
  }

  private static void doSetup(LauncherSettings settings) {
    System.out.print("memory limit (MiB): ");
    Scanner in = new Scanner(System.in);
    settings.memoryLimit = in.nextInt();
    in.nextLine();
    System.out.print("Java options: ");
    settings.javaOptions = in.nextLine();
  }

  private static boolean firstTimeSetup() {
    if (!SettingsDirectory.findSettingsDirectory()) {
      CountDownLatch latch = new CountDownLatch(1);
      FirstTimeSetupDialog picker = new FirstTimeSetupDialog(latch);
      picker.setVisible(true);
      try {
        latch.await();
      } catch (InterruptedException e) {
      }
      return picker.accepted();
    }
    return true;
  }

  /**
   * Must be called from the Event Dispatch Thread.
   */
  public void updateVersionList() {
    versionCB.removeAllItems();
    versionCB.addItem(VersionInfo.LATEST);
    for (VersionInfo version: ChunkyDeployer.availableVersions()) {
      versionCB.addItem(version);
      if (version.name.equals(settings.version)) {
        versionCB.setSelectedIndex(versionCB.getItemCount()-1);
      }
    }

  }

  /**
   * Select the latest version (always the first element of the version list).
   */
  public void selectLatestVersion() {
    versionCB.setSelectedIndex(0);
  }

  @Override
  public void updateError(String message) {
    Dialogs.error(this, message);
    setBusy(false);
  }

  @Override
  public void updateAvailable(VersionInfo latest) {
    UpdateDialog dialog = new UpdateDialog(this, latest);
    dialog.setVisible(true);
  }

  @Override
  public void noUpdateAvailable() {
    setBusy(false);
  }
}
TOP

Related Classes of se.llbit.chunky.launcher.ChunkyLauncher

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.