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

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

AEI2:

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