Java tutorial
/* * Argus Installer v2 -- A Better School Zip Alternative Copyright (C) 2014 Matthew * Crocco * * This program 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. * * This program 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 this * program. If not, see <http://www.gnu.org/licenses/>. */ package com.mattc.argus2.gui; import static com.mattc.argus2.Strings.Names.CONFIG_ARCHIVES; import static com.mattc.argus2.Strings.Names.LANG_BORDER_ARCHIVES; import static com.mattc.argus2.Strings.Names.LANG_BORDER_DOWNLOADS; import static com.mattc.argus2.Strings.Names.LANG_BORDER_STATUS; import static com.mattc.argus2.Strings.Names.LANG_BUTTON_ADD; import static com.mattc.argus2.Strings.Names.LANG_BUTTON_CLEAR; import static com.mattc.argus2.Strings.Names.LANG_BUTTON_EXIT; import static com.mattc.argus2.Strings.Names.LANG_BUTTON_INSTALL; import static com.mattc.argus2.Strings.Names.LANG_BUTTON_REMOVE; import static com.mattc.argus2.Strings.Names.LANG_BUTTON_SELECT; import static com.mattc.argus2.Strings.Names.LANG_BUTTON_START; import static com.mattc.argus2.Strings.Names.LANG_COL_ARCHIVES_FORM; import static com.mattc.argus2.Strings.Names.LANG_COL_ARCHIVES_NAME; import static com.mattc.argus2.Strings.Names.LANG_COL_ARCHIVES_SIZE; import static com.mattc.argus2.Strings.Names.LANG_COL_DOWNLOADS_NAME; import static com.mattc.argus2.Strings.Names.LANG_COL_DOWNLOADS_URLL; import static com.mattc.argus2.Strings.Names.LANG_FAILURE; import static com.mattc.argus2.Strings.Names.LANG_MENU_FILE; import static com.mattc.argus2.Strings.Names.LANG_MENU_ITEM_DOWNLOADS; import static com.mattc.argus2.Strings.Names.LANG_MENU_ITEM_EXIT; import static com.mattc.argus2.Strings.Names.LANG_MENU_ITEM_INSTALL_DIR; import static com.mattc.argus2.Strings.Names.LANG_MENU_ITEM_LANGUAGE; import static com.mattc.argus2.Strings.Names.LANG_MENU_ITEM_MUTABLE; import static com.mattc.argus2.Strings.Names.LANG_MENU_ITEM_OPTIMIZE; import static com.mattc.argus2.Strings.Names.LANG_MENU_ITEM_RESTORE_DEF; import static com.mattc.argus2.Strings.Names.LANG_MENU_ITEM_THREAD_USE; import static com.mattc.argus2.Strings.Names.LANG_MENU_SETTINGS; import static com.mattc.argus2.Strings.Names.LANG_MESSAGE_LANGFAIL; import static com.mattc.argus2.Strings.Names.LANG_MESSAGE_LANGSUCCESS; import static com.mattc.argus2.Strings.Names.LANG_NOTIFY_OPTIMIZE; import static com.mattc.argus2.Strings.Names.LANG_NOTIFY_STATADD; import static com.mattc.argus2.Strings.Names.LANG_NOTIFY_STATCLEAR; import static com.mattc.argus2.Strings.Names.LANG_NOTIFY_STATREADY; import static com.mattc.argus2.Strings.Names.LANG_NOTIFY_STATREMOV; import static com.mattc.argus2.Strings.Names.LANG_PROG_LABEL; import static com.mattc.argus2.Strings.Names.LANG_PROMPT_INSTALL; import static com.mattc.argus2.Strings.Names.LANG_PROMPT_SELECT; import static com.mattc.argus2.Strings.Names.LANG_PROPMT_LANGUAGE; import static com.mattc.argus2.Strings.Names.LANG_SUCCESS; import static com.mattc.argus2.Strings.Names.LANG_TITLE_INSTALL; import static com.mattc.argus2.Strings.Names.LANG_TITLE_LANGUAGE; import static com.mattc.argus2.Strings.Names.LANG_TITLE_NUMBER; import static com.mattc.argus2.Strings.Names.LANG_TITLE_SELECT; import static com.mattc.argus2.Strings.Names.LANG_TITLE_STATE; import static com.mattc.argus2.Strings.Names.LANG_TITLE_TEXT; import static com.mattc.argus2.Strings.Names.LANG_TOOLTIP_THREAD_USE; import static com.mattc.argus2.util.OS.MemoryUnit.BYTES; import static com.mattc.argus2.util.OS.MemoryUnit.KILOBYTES; import static com.mattc.argus2.util.OS.MemoryUnit.MEGABYTES; import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE; import static java.nio.file.StandardWatchEventKinds.OVERFLOW; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.EventQueue; import java.awt.FlowLayout; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; import java.io.IOException; import java.nio.file.FileSystems; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.WatchEvent; import java.nio.file.WatchKey; import java.nio.file.WatchService; import java.util.Locale; import java.util.Set; import java.util.TimerTask; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JCheckBoxMenuItem; import javax.swing.JDialog; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JProgressBar; import javax.swing.JScrollPane; import javax.swing.JSpinner; import javax.swing.JTable; import javax.swing.JTextPane; import javax.swing.KeyStroke; import javax.swing.WindowConstants; import javax.swing.border.BevelBorder; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.table.DefaultTableModel; import javax.swing.text.DefaultCaret; import org.joda.time.DateTime; import org.joda.time.format.DateTimeFormatter; import org.joda.time.format.DateTimeFormatterBuilder; import com.google.common.base.Function; import com.google.common.collect.Sets; import com.google.common.io.Files; import com.mattc.argus2.Argus; import com.mattc.argus2.Language; import com.mattc.argus2.Language.LangInfo; import com.mattc.argus2.Ref; import com.mattc.argus2.Settings; import com.mattc.argus2.Settings.Numbers; import com.mattc.argus2.Settings.State; import com.mattc.argus2.Settings.Text; import com.mattc.argus2.concurrent.DecompressProcess; import com.mattc.argus2.io.ArchiveFile; import com.mattc.argus2.io.Configs; import com.mattc.argus2.io.DownloadManager; import com.mattc.argus2.io.DownloadManager.DownloadInfo; import com.mattc.argus2.io.ListFile; import com.mattc.argus2.misc.Disposable; import com.mattc.argus2.misc.LineArray; import com.mattc.argus2.util.Console; import com.mattc.argus2.util.IOUtils; import com.mattc.argus2.util.OS.MemoryUnit; public class InstallerGUI extends JFrame implements Disposable { private static final long serialVersionUID = -1770859866496285087L; private static final DateTimeFormatter dtFormat = new DateTimeFormatterBuilder().appendHourOfHalfday(2) .appendLiteral(':').appendMinuteOfHour(2).appendLiteral(':').appendSecondOfMinute(2).appendLiteral(' ') .appendHalfdayOfDayText().toFormatter(); private static InstallerGUI __instance = null; // Files that were not default and were copied into the directory that can be // deleted safely. private static final Set<File> deletableFiles = Sets.newConcurrentHashSet(); private final LineArray statusLog = new LineArray(); private PopUpManager popups; private WatchService wservice; private WatchKey wkey; public static final InstallerGUI getInstance() { if (__instance == null) { synchronized (InstallerGUI.class) { Console.debug("Creating instance of Installer GUI..."); __instance = new InstallerGUI(); } } return __instance; } private InstallerGUI() { super(Ref.getFullTitle()); EventQueue.invokeLater(new Runnable() { InstallerGUI self = InstallerGUI.this; @Override public void run() { Thread.currentThread().setName("GUI"); // Do nothing, we will make our own. this.self.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); this.self.setLayout(new BoxLayout(this.self.getContentPane(), BoxLayout.Y_AXIS)); this.self.init(); this.self.initMenuBar(); this.self.setSize(1200, 600); this.self.setLocationRelativeTo(null); // Our Own Window Close Action this.self.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent evt) { Argus.shutdown(); } }); this.self.setVisible(true); } }); } /** * Initialize Components */ private void init() { final Container cont = getContentPane(); final String urlColumn = toLocal(LANG_COL_DOWNLOADS_URLL); final JPanel buttonPanel = new JPanel(); // Panel for Start/Exit Buttons final JPanel subPanel = new JPanel(); // Panel Containing Main Content // Panel Inside Sub-Panel containing Archives/Replacements final JPanel innerPanelOne = new JPanel(); // Panel inside Sub-Panel containing the Status Log final JPanel innerPanelTwo = new JPanel(); subPanel.setLayout(new BoxLayout(subPanel, BoxLayout.X_AXIS)); innerPanelOne.setLayout(new BoxLayout(innerPanelOne, BoxLayout.Y_AXIS)); innerPanelTwo.setLayout(new BorderLayout(5, 5)); // Add Inner Panels to Sub Panels with Spacing subPanel.add(Box.createHorizontalStrut(5)); // 5 pixel separator subPanel.add(innerPanelOne); subPanel.add(Box.createHorizontalStrut(5)); subPanel.add(innerPanelTwo); subPanel.add(Box.createHorizontalStrut(5)); final JProgressBar progressBar = new JProgressBar(0, 100); final JLabel curr = new JLabel(String.format(toLocal(LANG_PROG_LABEL), 0)); final JTextPane log = new JTextPane(); final AutoUpdateTablePane archiveScroll = AutoUpdateTablePane.create(new String[] { toLocal(LANG_COL_ARCHIVES_NAME), toLocal(LANG_COL_ARCHIVES_SIZE), toLocal(LANG_COL_ARCHIVES_FORM) }, assembleArchiveData(3), archiveUpdater);// new // JScrollPane(archiveTable); final AutoUpdateTablePane downloadScroll = AutoUpdateTablePane.create( new String[] { toLocal(LANG_COL_DOWNLOADS_NAME), urlColumn }, assembleDownloadData(2), null); final JScrollPane scrollLog = new JScrollPane(log); final JPanel archives = new BorderedPanel(toLocal(LANG_BORDER_ARCHIVES), new BorderLayout(10, 15)); final JPanel downloads = new BorderedPanel(toLocal(LANG_BORDER_DOWNLOADS), new BorderLayout(10, 15)); final JPanel status = new BorderedPanel(toLocal(LANG_BORDER_STATUS), new BorderLayout(10, 20)); final JPanel progress = new BorderedPanel(BorderedPanel.BorderType.ETCHED); downloadScroll.getTable().getColumn(urlColumn).setMinWidth(500); downloadScroll.getTable().getColumn(urlColumn).setCellRenderer(new TooltipRenderer()); downloadScroll.getTable().getTableHeader().setResizingAllowed(false); // Construct Progress Bar Panel with Status Label and Progress Bar progress.setLayout(new BoxLayout(progress, BoxLayout.Y_AXIS)); progress.add(Box.createVerticalStrut(20)); progress.add(curr); progress.add(progressBar); progress.add(Box.createVerticalStrut(20)); progressBar.setBackground(Color.DARK_GRAY); progressBar.setForeground(Color.GREEN); // -- // Set up Status Log Panel log.setForeground(Color.WHITE); log.setBackground(Color.BLACK); log.setCaretColor(log.getBackground()); log.setEditable(false); log.setFont(new Font(Font.DIALOG, Font.BOLD, 12)); final DefaultCaret caret = (DefaultCaret) log.getCaret(); caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE); status.add(scrollLog); scrollLog.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED)); // -- innerPanelOne.add(archives); archives.add(archiveScroll); innerPanelOne.add(downloads); downloads.add(downloadScroll); innerPanelTwo.add(status, BorderLayout.CENTER); // -- // Populate Button Panel final JButton startButton = new SpacedButton(toLocal(LANG_BUTTON_START), 32); final JButton exitButton = new SpacedButton(toLocal(LANG_BUTTON_EXIT), 32); final JButton clearButton = new SpacedButton(toLocal(LANG_BUTTON_CLEAR), 5); startButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { final JFileChooser chooser = new DirectoryChooser( new File(Settings.Text.DEFAULT_INSTALL_DESTINATION)); int val = chooser.showDialog(InstallerGUI.this, toLocal(LANG_BUTTON_INSTALL)); if (val == JFileChooser.APPROVE_OPTION) { final String path = chooser.getSelectedFile().getAbsolutePath(); final String question = String.format(toLocal(LANG_PROMPT_INSTALL), path); val = JOptionPane.showConfirmDialog(InstallerGUI.this, question, toLocal(LANG_TITLE_INSTALL), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); if (val == JOptionPane.YES_OPTION) { Argus.begin(chooser.getSelectedFile()); } } } }); exitButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { Argus.shutdown(); } }); clearButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { InstallerGUI.this.statusLog.clearAll(); writeLine(toLocal(LANG_NOTIFY_STATCLEAR)); } }); buttonPanel.add(startButton); buttonPanel.add(Box.createHorizontalStrut(60)); buttonPanel.add(exitButton); // -- innerPanelTwo.add(clearButton, BorderLayout.SOUTH); addArchiveButtons(archives, archiveScroll.getTable()); // Populate Content Pane cont.add(Box.createVerticalStrut(5)); cont.add(subPanel); cont.add(Box.createVerticalStrut(5)); cont.add(progress); cont.add(buttonPanel); cont.add(Box.createVerticalStrut(5)); // -- // Update Log ONLY When Necessary! this.statusLog.addListener(new LineArray.LineArrayListener() { @Override public void lineAdded(String line) { if (!InstallerGUI.this.statusLog.isEqualTo(log.getText())) { log.setText(InstallerGUI.this.statusLog.getText()); } } }); /* * Attempt to Register WatchKey for Archives directory. * * Listens for Delete Actions and updates Deletable Files and the Archive * List as necessary. */ try { this.wservice = FileSystems.getDefault().newWatchService(); this.wkey = Paths.get(Ref.getArchivesDir().toURI()).register(this.wservice, ENTRY_DELETE); Argus.timer().scheduleAtFixedRate(new TimerTask() { @Override public void run() { for (final WatchEvent<?> evt : InstallerGUI.this.wkey.pollEvents()) { if (evt.kind() == OVERFLOW) { continue; } else if (evt.kind() == ENTRY_DELETE) { @SuppressWarnings("unchecked") final WatchEvent<Path> wPath = (WatchEvent<Path>) evt; final File f = wPath.context().toFile(); // Handle Deletable Files for (final File dFile : deletableFiles) { if (f.getName().equals(dFile.getName())) { deletableFiles.remove(dFile); break; } } // Even if not deletable, we must remove it from the // list! final ListFile archiveListFile = Configs.getFile(CONFIG_ARCHIVES); if (archiveListFile.getItem(f.getName()) != null) { archiveListFile.removeItem(f.getName()); Argus.postEvent(archiveScroll.getTable()); } } } } }, 200, 200); Console.info("Dynamic Archive Directory Watch Enabled!"); } catch (final IOException e) { Console.exception(e, "No Watch Service on the Archives Directory!"); } initPopups(); // Test Line writeLine(toLocal(LANG_NOTIFY_STATREADY)); } private void addArchiveButtons(JPanel panel, final JTable list) { final JPanel bPanel = new JPanel(new FlowLayout()); final JButton add = new SpacedButton(toLocal(LANG_BUTTON_ADD), 10); final JButton remove = new SpacedButton(toLocal(LANG_BUTTON_REMOVE), 7); bPanel.add(add); bPanel.add(Box.createHorizontalStrut(30)); bPanel.add(remove); remove.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (list.getSelectedRow() != -1) { final ListFile archiveList = Configs.getFile(CONFIG_ARCHIVES); for (final int i : list.getSelectedRows()) { final String name = (String) list.getValueAt(i, 0); final File f = new File(Ref.getArchivesDir(), name); archiveList.removeItem(name); Console.info("Removed " + name + " from list..."); writeLine(String.format(toLocal(LANG_NOTIFY_STATREMOV), name)); for (final File dFile : deletableFiles) { if (!f.getAbsolutePath().equals(dFile.getAbsolutePath())) { continue; } deletableFiles.remove(dFile); if (!f.delete()) { f.deleteOnExit(); } } } Argus.postEvent(list); // populateList(list); } } }); add.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { final JFileChooser chooser = new ArchiveChooser(); final int val = chooser.showOpenDialog(InstallerGUI.this); try { if ((val == JFileChooser.APPROVE_OPTION) && (chooser.getSelectedFile() != null)) { final ListFile archiveList = Configs.getFile(CONFIG_ARCHIVES); for (final File selected : chooser.getSelectedFiles()) { File f = selected; if (archiveList.getItem(f.getName()) != null) { continue; } if (!new File(Ref.getArchivesDir(), f.getName()).exists()) { f = IOUtils.copyTo(selected, Ref.getArchivesDir()); deletableFiles.add(f); } archiveList.addItem(f.getName()); Console.info("Added " + selected.getAbsolutePath() + " as " + f.getName() + "..."); writeLine(String.format(toLocal(LANG_NOTIFY_STATADD), f.getName())); } Argus.postEvent(list); } else { Console.info("No File Selected..."); } } catch (final IOException ex) { Console.exception(ex); } } }); panel.add(bPanel, BorderLayout.SOUTH); } private void initMenuBar() { final JMenuBar bar = new JMenuBar(); final JMenu fileMenu = new JMenu(toLocal(LANG_MENU_FILE)); final JMenu setMenu = new JMenu(toLocal(LANG_MENU_SETTINGS)); final JMenuItem exitItem = new JMenuItem(toLocal(LANG_MENU_ITEM_EXIT), KeyEvent.VK_E); final JCheckBoxMenuItem mutableItem = new JCheckBoxMenuItem(toLocal(LANG_MENU_ITEM_MUTABLE), Settings.State.MUTABLE); final JCheckBoxMenuItem downloadItem = new JCheckBoxMenuItem(toLocal(LANG_MENU_ITEM_DOWNLOADS), Settings.State.DOWNLOADS); final JMenuItem langItem = new JMenuItem(toLocal(LANG_MENU_ITEM_LANGUAGE)); final BorderedSpinnerMenuItem threadsItem = new BorderedSpinnerMenuItem(toLocal(LANG_MENU_ITEM_THREAD_USE), 1, 8, Settings.Numbers.MAX_THREAD_COUNT); final JMenuItem optiItem = new JMenuItem(toLocal(LANG_MENU_ITEM_OPTIMIZE), KeyEvent.VK_O); final JMenuItem instItem = new JMenuItem(toLocal(LANG_MENU_ITEM_INSTALL_DIR), KeyEvent.VK_I); final JMenuItem defItem = new JMenuItem(toLocal(LANG_MENU_ITEM_RESTORE_DEF), KeyEvent.VK_D); threadsItem.setToolTipText(toLocal(LANG_TOOLTIP_THREAD_USE)); exitItem.addActionListener(GuiUtils.EXIT_ARGUS_ACTION); exitItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_E, ActionEvent.CTRL_MASK)); mutableItem.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { final JCheckBoxMenuItem comp = (JCheckBoxMenuItem) e.getSource(); Settings.State.MUTABLE = comp.isSelected(); } }); mutableItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_1, ActionEvent.ALT_MASK)); mutableItem.setMnemonic(KeyEvent.VK_1); downloadItem.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { final JCheckBoxMenuItem comp = (JCheckBoxMenuItem) e.getSource(); Settings.State.DOWNLOADS = comp.isSelected(); } }); downloadItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_2, ActionEvent.ALT_MASK)); downloadItem.setMnemonic(KeyEvent.VK_2); threadsItem.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { final JSpinner slider = (JSpinner) e.getSource(); Numbers.MAX_THREAD_COUNT = (Integer) slider.getValue(); Argus.updateExecutors(); } }); threadsItem.getComponent().setBackground(getBackground()); optiItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { final int proc = Runtime.getRuntime().availableProcessors(); if (proc != Numbers.MAX_THREAD_COUNT) { Numbers.MAX_THREAD_COUNT = proc; threadsItem.setValue(proc); // The Spinner ChangeListener will handle Executor Updates InstallerGUI.this.writeLine(toLocal(LANG_NOTIFY_OPTIMIZE)); } } }); optiItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.CTRL_MASK)); defItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { Settings.toDefaults(); // Update Appropriate Components mutableItem.setSelected(State.MUTABLE); downloadItem.setSelected(State.DOWNLOADS); threadsItem.setValue(Numbers.MAX_THREAD_COUNT); } }); instItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { final JFileChooser chooser = new DirectoryChooser(); int val = chooser.showDialog(InstallerGUI.this, toLocal(LANG_BUTTON_SELECT)); if (val == JFileChooser.APPROVE_OPTION) { final String path = chooser.getSelectedFile().getAbsolutePath(); final String question = String.format(toLocal(LANG_PROMPT_SELECT), path, Text.DEFAULT_INSTALL_DESTINATION); val = JOptionPane.showConfirmDialog(InstallerGUI.this, question, toLocal(LANG_TITLE_SELECT), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); if (val == JOptionPane.YES_OPTION) { Settings.Text.DEFAULT_INSTALL_DESTINATION = chooser.getSelectedFile().getPath(); } } } }); instItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_3, ActionEvent.ALT_MASK)); langItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { final Font font = new Font(Font.MONOSPACED, Font.ITALIC, 20); final JOptionPane pane = new JOptionPane(toLocal(LANG_PROPMT_LANGUAGE), JOptionPane.QUESTION_MESSAGE, JOptionPane.OK_CANCEL_OPTION); pane.setWantsInput(true); pane.setSelectionValues(Language.getAllUniqueLocales()); pane.setInitialSelectionValue(new LangInfo(new Locale(Settings.Text.LANGUAGE.getLanguage()))); pane.setFont(font); final JDialog dialog = pane.createDialog(Argus.gui(), toLocal(LANG_TITLE_LANGUAGE)); pane.selectInitialValue(); dialog.setVisible(true); dialog.dispose(); final Object tmp = pane.getInputValue(); if ((tmp == null) || (tmp == JOptionPane.UNINITIALIZED_VALUE)) return; final LangInfo info = (LangInfo) tmp; final Locale loc = info.locale; if (loc != Settings.Text.LANGUAGE) { if (!Settings.Text.setLanguage(loc)) { JOptionPane.showMessageDialog(Argus.gui(), String.format(toLocal(LANG_MESSAGE_LANGFAIL), loc.getDisplayLanguage()), toLocal(LANG_FAILURE), JOptionPane.ERROR_MESSAGE); } else { JOptionPane.showMessageDialog(Argus.gui(), String.format(toLocal(LANG_MESSAGE_LANGSUCCESS), loc.getDisplayLanguage()), toLocal(LANG_SUCCESS), JOptionPane.INFORMATION_MESSAGE); } } } }); fileMenu.add(exitItem); setMenu.add(new TitledSeparator(toLocal(LANG_TITLE_STATE), Color.GRAY)); setMenu.add(mutableItem); setMenu.add(downloadItem); setMenu.add(new TitledSeparator(toLocal(LANG_TITLE_NUMBER), Color.GRAY)); setMenu.add(threadsItem); setMenu.add(optiItem); setMenu.add(new TitledSeparator(toLocal(LANG_TITLE_TEXT), Color.GRAY)); setMenu.add(instItem); setMenu.add(langItem); setMenu.add(new Separator(Color.GRAY)); setMenu.add(defItem); setMenu.add(new Separator(Color.GRAY)); bar.add(fileMenu); bar.add(setMenu); setJMenuBar(bar); } private void initPopups() { this.popups = new PopUpManager(this); this.popups.allowListenersFor(JTable.class); this.popups.addListenersFor(this); } private String toLocal(String langKey) { return Language.getLocalized(langKey); } // Internal Use, Simply uses CODE as the Identifier public void writeLine(String msg) { final DateTime date = new DateTime(); final String time = date.toString(dtFormat); final String text = String.format("%s - [%-5s]: %s%n", time, "CODE", msg); this.statusLog.addLine(text); } /** * Add's a line to the Status Log. * * @param msg * - Actual Message * @param archiveType * - Archive Type Identifier like ZIP or TAR or BZIP */ public void writeLine(String msg, DecompressProcess process) { final DateTime date = new DateTime(); final String time = date.toString(dtFormat); final String text = String.format("%s - [%-5s]: %s%n", time, Files.getFileExtension(process.getArchiveName()).toUpperCase(), msg); this.statusLog.addLine(text); } @Override public void dispose() { Console.debug("Disposing of Installer GUI..."); this.wkey.cancel(); IOUtils.closeSilently(this.wservice); super.dispose(); __instance = null; } public PopUpManager getPopups() { return this.popups; } public void addPopups(JPopupMenu menu, Component comp) { this.popups.register(menu, comp); } public void addPopupsForAll(JPopupMenu menu, Class<? extends Component> componentClass) { this.popups.register(menu, componentClass); } private static final Object[][] assembleDownloadData(int columnCount) { final DownloadInfo[] downloads = DownloadManager.getDownloadList(); final Object[][] data = new Object[downloads.length][columnCount]; for (int i = 0; i < downloads.length; i++) { final DownloadInfo info = downloads[i]; data[i][0] = info.name; data[i][1] = info.url; } return data; } private static final Object[][] assembleArchiveData(int columnCount) { final ArchiveFile[] files = ArchiveFile.getCurrentArchives(); final Object[][] data = new Object[files.length][columnCount]; for (int i = 0; i < files.length; i++) { final ArchiveFile file = files[i]; final MemoryUnit tMem = file.length() < 1_000L ? BYTES : file.length() < 1_000_000 ? KILOBYTES : MEGABYTES; data[i][0] = file.getName(); data[i][1] = String.format("%,5d %-2s", tMem.convert(file.length(), BYTES), tMem.getTag()); data[i][2] = file.getFormatType(); } return data; } private static final Function<DefaultTableModel, Void> archiveUpdater = new Function<DefaultTableModel, Void>() { @Override public Void apply(DefaultTableModel input) { final String[] columns = new String[input.getColumnCount()]; final ArchiveFile[] files = ArchiveFile.getCurrentArchives(); final Object[][] data = new Object[files.length][columns.length]; for (int i = 0; i < columns.length; i++) { columns[i] = input.getColumnName(i); } for (int i = 0; i < files.length; i++) { final ArchiveFile file = files[i]; final MemoryUnit tMem = file.length() < 1_000L ? BYTES : file.length() < 1_000_000 ? KILOBYTES : MEGABYTES; data[i][0] = file.getName(); data[i][1] = String.format("%,5d %-2s", tMem.convert(file.length(), BYTES), tMem.getTag()); data[i][2] = file.getFormatType(); } input.setDataVector(data, columns); return null; } }; // TODO This probably wont work for Localization with EXCEPTIONALLY long names private static class SpacedButton extends JButton { private static final long serialVersionUID = -3902145219557616202L; public SpacedButton(String name, int offset) { super(buildName(name, (name.length() % 2) == 0 ? offset : offset - 1)); } private static String buildName(String name, int offset) { final StringBuilder sb = new StringBuilder(); int mut = -1; for (int i = offset; i < (offset + 1); i += mut) { sb.append(" "); if (i == 0) { mut = 1; sb.append(name); } } return sb.toString(); } } }