source: AE/installer2/src/net/oni2/aeinstaller/gui/MainWin.java@ 618

Last change on this file since 618 was 618, checked in by alloc, 12 years ago

AEI2:

  • Added check for Oni's exe before trying to launch it
File size: 17.7 KB
RevLine 
[591]1package net.oni2.aeinstaller.gui;
2
[608]3import java.awt.Desktop;
4import java.awt.event.ActionEvent;
5import java.awt.event.ActionListener;
6import java.awt.event.MouseAdapter;
7import java.awt.event.MouseEvent;
[604]8import java.io.File;
[605]9import java.io.IOException;
[591]10import java.util.ArrayList;
[605]11import java.util.HashMap;
12import java.util.HashSet;
[591]13import java.util.List;
14import java.util.ResourceBundle;
15import java.util.TreeMap;
[600]16import java.util.TreeSet;
[605]17import java.util.Vector;
[591]18
[600]19import javax.swing.JButton;
[591]20import javax.swing.JComboBox;
[593]21import javax.swing.JComponent;
[604]22import javax.swing.JFileChooser;
[591]23import javax.swing.JFrame;
[592]24import javax.swing.JLabel;
[593]25import javax.swing.JMenu;
[608]26import javax.swing.JMenuItem;
[593]27import javax.swing.JOptionPane;
[608]28import javax.swing.JPopupMenu;
[592]29import javax.swing.JSplitPane;
[591]30import javax.swing.JTable;
31import javax.swing.ListSelectionModel;
32import javax.swing.RowSorter;
33import javax.swing.SortOrder;
34import javax.swing.SwingUtilities;
35import javax.swing.event.ListSelectionEvent;
36import javax.swing.event.ListSelectionListener;
[604]37import javax.swing.filechooser.FileFilter;
[591]38import javax.swing.table.TableRowSorter;
39
[604]40import net.oni2.aeinstaller.backend.Paths;
[591]41import net.oni2.aeinstaller.backend.Settings;
[593]42import net.oni2.aeinstaller.backend.Settings.Platform;
[600]43import net.oni2.aeinstaller.backend.SizeFormatter;
[591]44import net.oni2.aeinstaller.backend.depot.DepotCacheUpdateProgressListener;
45import net.oni2.aeinstaller.backend.depot.DepotManager;
[600]46import net.oni2.aeinstaller.backend.mods.Mod;
47import net.oni2.aeinstaller.backend.mods.ModManager;
48import net.oni2.aeinstaller.backend.mods.Type;
[604]49import net.oni2.aeinstaller.backend.mods.download.ModDownloader;
50import net.oni2.aeinstaller.backend.mods.download.ModDownloader.State;
51import net.oni2.aeinstaller.backend.mods.download.ModDownloaderListener;
[600]52import net.oni2.aeinstaller.backend.oni.InstallProgressListener;
53import net.oni2.aeinstaller.backend.oni.Installer;
[593]54import net.oni2.aeinstaller.gui.about.AboutDialog;
[605]55import net.oni2.aeinstaller.gui.downloadwindow.Downloader;
[600]56import net.oni2.aeinstaller.gui.modtable.DownloadSizeListener;
[591]57import net.oni2.aeinstaller.gui.modtable.ModTableFilter;
58import net.oni2.aeinstaller.gui.modtable.ModTableModel;
59import net.oni2.aeinstaller.gui.settings.SettingsDialog;
60
61import org.javabuilders.BuildResult;
62import org.javabuilders.annotations.DoInBackground;
63import org.javabuilders.event.BackgroundEvent;
64import org.javabuilders.swing.SwingJavaBuilder;
[593]65import org.simplericity.macify.eawt.ApplicationEvent;
66import org.simplericity.macify.eawt.ApplicationListener;
[591]67
68/**
69 * @author Christian Illy
70 */
[600]71public class MainWin extends JFrame implements ApplicationListener,
72 DownloadSizeListener {
[591]73 private static final long serialVersionUID = -4027395051382659650L;
74
75 private ResourceBundle bundle = ResourceBundle.getBundle(getClass()
76 .getName());
77 @SuppressWarnings("unused")
78 private BuildResult result = SwingJavaBuilder.build(this, bundle);
79
[593]80 private JMenu mainMenu;
81
[592]82 private JSplitPane contents;
83
[591]84 private JComboBox cmbModTypes;
85 private JTable tblMods;
86 private ModTableModel model;
87 private TableRowSorter<ModTableModel> sorter;
[600]88 private JLabel lblDownloadSizeVal;
[591]89
[592]90 private JLabel lblSubmitterVal;
91 private JLabel lblCreatorVal;
[606]92 private JLabel lblTypesVal;
93 private JLabel lblPlatformVal;
[592]94 private HTMLLinkLabel lblDescriptionVal;
95
[600]96 private JButton btnInstall;
97
[591]98 /**
99 * Constructor of main window.
100 */
101 public MainWin() {
[593]102 this.setTitle(SwingJavaBuilder.getConfig().getResource("appname")
103 + " - v"
104 + SwingJavaBuilder.getConfig().getResource("appversion"));
[591]105
[592]106 contents.setDividerLocation(400);
[593]107
108 if (Settings.getPlatform() == Platform.MACOS) {
109 mainMenu.setVisible(false);
110 }
[600]111
112 getRootPane().setDefaultButton(btnInstall);
[605]113 lblDownloadSizeVal.setText(SizeFormatter.format(0, 2));
[591]114 }
115
116 private void initModTypeBox() {
[592]117 cmbModTypes.removeAllItems();
118
[600]119 TreeMap<String, Type> types = new TreeMap<String, Type>();
120 for (Type t : ModManager.getInstance().getTypesWithContent()) {
121 types.put(t.getName(), t);
[591]122 }
[600]123 for (Type t : types.values()) {
[591]124 cmbModTypes.addItem(t);
125 }
126 cmbModTypes.setSelectedIndex(0);
127 }
128
129 private void initTable() {
130 tblMods.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
[592]131 tblMods.getSelectionModel().addListSelectionListener(
132 new ListSelectionListener() {
133 @Override
134 public void valueChanged(ListSelectionEvent e) {
135 int viewRow = tblMods.getSelectedRow();
136 if (viewRow < 0) {
137 modSelection(null);
138 } else {
139 int modelRow = tblMods
140 .convertRowIndexToModel(viewRow);
[600]141 Mod mod = (Mod) model.getValueAt(modelRow, -1);
[592]142 modSelection(mod);
143 }
144 }
145 });
[608]146 tblMods.addMouseListener(new MouseAdapter() {
147 private void common(MouseEvent e) {
148 int r = tblMods.rowAtPoint(e.getPoint());
149 if (r >= 0 && r < tblMods.getRowCount())
150 tblMods.setRowSelectionInterval(r, r);
151 else
152 tblMods.clearSelection();
[592]153
[608]154 int rowindex = tblMods.getSelectedRow();
155 if (rowindex >= 0) {
156 if (e.isPopupTrigger()
157 && e.getComponent() instanceof JTable) {
158 int modelRow = tblMods.convertRowIndexToModel(rowindex);
159 final Mod mod = (Mod) model.getValueAt(modelRow, -1);
160
161 if (mod.isLocalAvailable()) {
162 JPopupMenu popup = new JPopupMenu();
163 JMenuItem openModFolder = new JMenuItem(bundle
164 .getString("openModFolder.text"));
165 openModFolder
166 .addActionListener(new ActionListener() {
167 @Override
168 public void actionPerformed(
169 ActionEvent arg0) {
170 try {
171 Desktop.getDesktop().open(
172 mod.getLocalPath());
173 } catch (IOException e) {
174 e.printStackTrace();
175 }
176 }
177 });
178 popup.add(openModFolder);
179 popup.show(e.getComponent(), e.getX(), e.getY());
180 }
181 }
182 }
183 }
184
185 @Override
186 public void mousePressed(MouseEvent e) {
187 common(e);
188 }
189
190 @Override
191 public void mouseReleased(MouseEvent e) {
192 common(e);
193 }
194 });
[593]195 // To get checkbox-cells with background of row
196 ((JComponent) tblMods.getDefaultRenderer(Boolean.class))
197 .setOpaque(true);
198
[591]199 model = new ModTableModel();
[600]200 model.addDownloadSizeListener(this);
[591]201
202 tblMods.setModel(model);
203
204 sorter = new TableRowSorter<ModTableModel>(model);
205 tblMods.setRowSorter(sorter);
206
[600]207 sorter.setRowFilter(new ModTableFilter(null));
[591]208
209 List<RowSorter.SortKey> sortKeys = new ArrayList<RowSorter.SortKey>();
[606]210 sortKeys.add(new RowSorter.SortKey(1, SortOrder.ASCENDING));
[591]211 sorter.setSortKeys(sortKeys);
212
213 for (int i = 0; i < model.getColumnCount(); i++) {
214 model.setColumnConstraints(i, tblMods.getColumnModel().getColumn(i));
215 }
216 }
217
218 private void exit() {
219 dispose();
[608]220 System.exit(0);
[591]221 }
222
223 private void saveLocalData() {
224 Settings.getInstance().serializeToFile();
[596]225 DepotManager.getInstance().saveToFile(Settings.getDepotCacheFilename());
[591]226 }
227
228 @DoInBackground(progressMessage = "updateDepot.title", cancelable = false, indeterminateProgress = false)
229 private void execDepotUpdate(final BackgroundEvent evt) {
230 try {
231 DepotManager.getInstance().updateInformation(false,
232 new DepotCacheUpdateProgressListener() {
233
234 @Override
235 public void cacheUpdateProgress(String stepName,
236 int current, int total) {
237 evt.setProgressEnd(total);
238 evt.setProgressValue(current);
239 evt.setProgressMessage(stepName);
240 }
241 });
[600]242 ModManager.getInstance().init();
243 initTable();
[592]244 initModTypeBox();
[600]245
[592]246 tblMods.setVisible(true);
[591]247 } catch (Exception e) {
248 e.printStackTrace();
249 }
250 }
251
252 @SuppressWarnings("unused")
253 private void checkUpdates() {
254 if (Settings.getInstance().get("notifyupdates", true)) {
[608]255 // TODO
[591]256 }
257 }
258
259 @SuppressWarnings("unused")
260 private void focus() {
261 SwingUtilities.invokeLater(new Runnable() {
262
263 @Override
264 public void run() {
265 toFront();
266 repaint();
267 }
268 });
269
270 }
271
272 private void showSettings() {
[593]273 new SettingsDialog().setVisible(true);
[591]274 }
275
[593]276 private void showAbout() {
277 new AboutDialog().setVisible(true);
278 }
279
[604]280 private JFileChooser getConfigOpenSaveDialog(boolean save) {
281 JFileChooser fc = new JFileChooser();
282 fc.setCurrentDirectory(Paths.getEditionBasePath());
283 if (save)
284 fc.setDialogType(JFileChooser.SAVE_DIALOG);
285 else
286 fc.setDialogType(JFileChooser.OPEN_DIALOG);
287 fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
288 fc.setFileFilter(new FileFilter() {
289 @Override
290 public String getDescription() {
291 return "XML files";
292 }
293
294 @Override
295 public boolean accept(File arg0) {
296 return (arg0.isDirectory())
297 || (arg0.getName().toLowerCase().endsWith(".xml"));
298 }
299 });
300 fc.setMultiSelectionEnabled(false);
301 return fc;
302 }
303
[593]304 @SuppressWarnings("unused")
305 private void loadConfig() {
[604]306 JFileChooser fc = getConfigOpenSaveDialog(false);
307 int res = fc.showOpenDialog(this);
308 if (res == JFileChooser.APPROVE_OPTION) {
309 if (fc.getSelectedFile().exists())
310 model.reloadSelection(fc.getSelectedFile());
311 }
[593]312 }
313
314 @SuppressWarnings("unused")
315 private void saveConfig() {
[604]316 JFileChooser fc = getConfigOpenSaveDialog(true);
317 int res = fc.showSaveDialog(this);
318 if (res == JFileChooser.APPROVE_OPTION) {
319 File f = fc.getSelectedFile();
320 if (!f.getName().endsWith(".xml"))
321 f = new File(f.getParentFile(), f.getName() + ".xml");
322 ModManager.getInstance().saveModSelection(f,
323 model.getSelectedMods());
324 }
[593]325 }
326
[600]327 @DoInBackground(progressMessage = "initializingEdition.title", cancelable = false, indeterminateProgress = false)
328 private void reglobalize(final BackgroundEvent evt) {
329 Installer.initializeEdition(new InstallProgressListener() {
330 @Override
331 public void installProgressUpdate(int done, int total, String step) {
332 evt.setProgressEnd(total);
333 evt.setProgressValue(done);
334 evt.setProgressMessage(step);
335 }
336 });
337 }
338
[593]339 @SuppressWarnings("unused")
[600]340 private void tools() {
341 // TODO method stub
342 JOptionPane.showMessageDialog(this, "tools", "todo",
[593]343 JOptionPane.INFORMATION_MESSAGE);
344 }
[596]345
[593]346 @SuppressWarnings("unused")
347 private void revertSelection() {
[604]348 model.revertSelection();
[593]349 }
350
[602]351 @DoInBackground(progressMessage = "mandatoryFiles.title", cancelable = false, indeterminateProgress = false)
352 private void checkMandatoryFiles(final BackgroundEvent evt) {
[604]353 TreeSet<Mod> mand = new TreeSet<Mod>();
[603]354 for (Mod m : ModManager.getInstance().getMandatoryTools()) {
[604]355 if (m.isNewerAvailable()) {
356 mand.add(m);
357 }
[602]358 }
[603]359 for (Mod m : ModManager.getInstance().getMandatoryMods()) {
[604]360 if (m.isNewerAvailable()) {
361 mand.add(m);
362 }
[602]363 }
[604]364 if (mand.size() > 0) {
365 ModDownloader m = new ModDownloader(mand,
366 new ModDownloaderListener() {
367 @Override
368 public void updateStatus(ModDownloader source,
369 State state, int filesDown, int filesTotal,
[605]370 int bytesDown, int bytesTotal, int duration,
371 int remaining, int speed) {
[604]372 evt.setProgressEnd(filesTotal);
373 evt.setProgressValue(filesDown);
374 }
375 });
376 while (!m.isFinished()) {
377 try {
[606]378 Thread.sleep(10);
[604]379 } catch (InterruptedException e) {
380 // TODO Auto-generated catch block
381 e.printStackTrace();
382 }
383 }
384 }
385 evt.setProgressMessage(bundle.getString("mandatoryToolsInstall.title"));
386 Installer.installTools(ModManager.getInstance().getMandatoryTools());
[602]387 }
388
[600]389 @DoInBackground(progressMessage = "installing.title", cancelable = false, indeterminateProgress = false)
[617]390 private boolean install(final BackgroundEvent evt) {
[600]391 TreeSet<Mod> mods = new TreeSet<Mod>();
[602]392 mods.addAll(ModManager.getInstance().getMandatoryMods());
[600]393 mods.addAll(model.getSelectedMods());
394
[605]395 boolean instReady = false;
396
397 while (!instReady) {
398 System.out.println("Checking downloads:");
399 TreeSet<Mod> toDownload = new TreeSet<Mod>();
400 for (Mod m : mods) {
401 if (!m.isLocalAvailable())
402 toDownload.add(m);
403 }
404 if (toDownload.size() > 0) {
405 System.out.println("Download files: " + toDownload.toString());
406 Downloader dl = new Downloader(toDownload);
[617]407 try {
408 dl.setVisible(true);
409 if (!dl.isFinished())
410 break;
411 } finally {
412 dl.dispose();
413 }
[605]414 }
415 HashMap<Mod, HashSet<Mod>> dependencies = ModManager.getInstance()
416 .checkDependencies(mods);
417 if (dependencies.size() > 0) {
418 System.out.println("Unmet dependencies: "
419 + dependencies.toString());
420 for (Mod m : dependencies.keySet()) {
421 for (Mod mDep : dependencies.get(m))
422 mods.add(mDep);
423 }
424 } else {
425 HashMap<Mod, HashSet<Mod>> conflicts = ModManager.getInstance()
[608]426 .checkIncompabitilites(mods);
[605]427 if (conflicts.size() > 0) {
[608]428 System.err.println("Incompatible mods: "
[605]429 + conflicts.toString());
430 break;
431 } else {
432 instReady = true;
433 }
434 }
[600]435 }
[618]436
[605]437 if (instReady) {
[608]438 System.out.println("Install mods: " + mods.toString());
439
[605]440 Installer.install(mods, new InstallProgressListener() {
441 @Override
442 public void installProgressUpdate(int done, int total,
443 String step) {
444 evt.setProgressEnd(total);
445 evt.setProgressValue(done);
446 evt.setProgressMessage(step);
447 }
448 });
[617]449 return true;
[605]450 }
[617]451 return false;
[600]452 }
[618]453
[617]454 @SuppressWarnings("unused")
455 private void installDone() {
456 JOptionPane.showMessageDialog(this,
457 bundle.getString("installDone.text"),
458 bundle.getString("installDone.title"),
459 JOptionPane.INFORMATION_MESSAGE);
460 }
[600]461
462 private void modSelection(Mod m) {
[592]463 lblSubmitterVal.setText("");
464 lblCreatorVal.setText("");
465 lblDescriptionVal.setText("");
[606]466 lblTypesVal.setText("");
467 lblPlatformVal.setText("");
[600]468 if (m != null) {
469 lblSubmitterVal.setText(m.getName());
470 lblCreatorVal.setText(m.getCreator());
471 lblDescriptionVal.setText(m.getDescription());
[606]472
473 String types = "";
474 for (Type t : m.getTypes()) {
475 if (types.length() > 0)
476 types += ", ";
477 types += t.getName();
478 }
479 lblTypesVal.setText(types);
480 lblPlatformVal.setText(m.getPlatform().toString());
[591]481 }
[592]482 // TODO
[591]483 }
484
485 @SuppressWarnings("unused")
[592]486 private void modTypeSelection() {
[600]487 Type t = (Type) cmbModTypes.getSelectedItem();
[592]488 if (t != null)
[600]489 sorter.setRowFilter(new ModTableFilter(t));
[592]490 else
[600]491 sorter.setRowFilter(new ModTableFilter(null));
[591]492 }
[593]493
494 @Override
[600]495 public void downloadSizeChanged(int newSize) {
496 lblDownloadSizeVal.setText(SizeFormatter.format(newSize, 2));
497 }
498
[616]499 @SuppressWarnings("unused")
500 private void checkInitialize() {
[600]501 if (!Installer.isEditionInitialized()) {
502 int res = JOptionPane.showConfirmDialog(this,
503 bundle.getString("askInitialize.text"),
504 bundle.getString("askInitialize.title"),
505 JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
506 if (res == JOptionPane.NO_OPTION) {
[615]507 saveLocalData();
[600]508 exit();
509 }
510 }
511 }
[606]512
[616]513 @DoInBackground(progressMessage = "initializingEdition.title", cancelable = false, indeterminateProgress = false)
514 private void initialize(final BackgroundEvent evt) {
515 if (!Installer.isEditionInitialized()) {
516 Installer.initializeEdition(new InstallProgressListener() {
517 @Override
518 public void installProgressUpdate(int done, int total,
519 String step) {
520 evt.setProgressEnd(total);
521 evt.setProgressValue(done);
522 evt.setProgressMessage(step);
523 }
524 });
525 }
526 }
527
[605]528 private Vector<String> getBasicOniLaunchParams() {
529 Vector<String> params = new Vector<String>();
[618]530 File exe = null;
[605]531 switch (Settings.getPlatform()) {
532 case WIN:
[618]533 exe = new File(Paths.getEditionBasePath(), "Oni.exe");
534 if (exe.exists())
535 params.add(exe.getPath());
[605]536 break;
537 case MACOS:
[618]538 exe = new File(Paths.getEditionBasePath(),
539 "Oni.app/Contents/MacOS/Oni");
540 if (exe.exists())
541 params.add(exe.getPath());
[605]542 break;
543 case LINUX:
544 String wine = Settings.getWinePath();
[618]545 exe = new File(Paths.getEditionBasePath(), "Oni.exe");
546 if (exe.exists()) {
547 if (wine != null) {
548 params.add(wine);
549 params.add(exe.getPath());
550 }
[605]551 }
552 break;
553 default:
554 }
555 if (params.size() > 0) {
556 params.add("-debugfiles");
557 }
558 return params;
559 }
[600]560
[605]561 @SuppressWarnings("unused")
562 private void oniFull() {
563 Vector<String> params = getBasicOniLaunchParams();
564 if (params.size() > 0) {
565 try {
[606]566 ProcessBuilder pb = new ProcessBuilder(params);
567 pb.directory(Paths.getEditionBasePath());
568 pb.start();
[605]569 } catch (IOException e) {
570 // TODO Auto-generated catch block
571 e.printStackTrace();
572 }
573 }
574 }
575
576 @SuppressWarnings("unused")
577 private void oniWin() {
578 Vector<String> params = getBasicOniLaunchParams();
579 if (params.size() > 0) {
580 params.add("-noswitch");
581 try {
[606]582 ProcessBuilder pb = new ProcessBuilder(params);
583 pb.directory(Paths.getEditionBasePath());
584 pb.start();
[605]585 } catch (IOException e) {
586 // TODO Auto-generated catch block
587 e.printStackTrace();
588 }
589 }
590 }
591
[608]592 @SuppressWarnings("unused")
593 private void openEditionFolder() {
594 try {
595 Desktop.getDesktop().open(Paths.getEditionBasePath());
596 } catch (IOException e) {
597 e.printStackTrace();
598 }
599 }
600
[600]601 @Override
[593]602 public void handleAbout(ApplicationEvent event) {
603 event.setHandled(true);
604 showAbout();
605 }
606
607 @Override
608 public void handleOpenApplication(ApplicationEvent event) {
609 }
610
611 @Override
612 public void handleOpenFile(ApplicationEvent event) {
613 }
614
615 @Override
616 public void handlePreferences(ApplicationEvent event) {
617 showSettings();
618 }
619
620 @Override
621 public void handlePrintFile(ApplicationEvent event) {
622 }
623
624 @Override
625 public void handleQuit(ApplicationEvent event) {
[605]626 event.setHandled(true);
627 saveLocalData();
628 exit();
[593]629 }
630
631 @Override
632 public void handleReOpenApplication(ApplicationEvent event) {
633 }
[600]634
[592]635}
Note: See TracBrowser for help on using the repository browser.