source: java/installer2/src/net/oni2/aeinstaller/gui/modtable/ModTable.java@ 1138

Last change on this file since 1138 was 1018, checked in by alloc, 10 years ago

AEI 2.20: Center download window on parent window

File size: 14.6 KB
Line 
1package net.oni2.aeinstaller.gui.modtable;
2
3import java.awt.Component;
4import java.awt.Desktop;
5import java.awt.Rectangle;
6import java.awt.event.ActionEvent;
7import java.awt.event.ActionListener;
8import java.awt.event.KeyAdapter;
9import java.awt.event.KeyEvent;
10import java.awt.event.MouseAdapter;
11import java.awt.event.MouseEvent;
12import java.io.File;
13import java.io.IOException;
14import java.util.ArrayList;
15import java.util.HashSet;
16import java.util.List;
17import java.util.ResourceBundle;
18import java.util.TreeSet;
19import java.util.Vector;
20
21import javax.swing.JCheckBoxMenuItem;
22import javax.swing.JComponent;
23import javax.swing.JMenuItem;
24import javax.swing.JOptionPane;
25import javax.swing.JPopupMenu;
26import javax.swing.JTable;
27import javax.swing.JViewport;
28import javax.swing.ListSelectionModel;
29import javax.swing.RowSorter;
30import javax.swing.SortOrder;
31import javax.swing.event.ListSelectionEvent;
32import javax.swing.event.RowSorterEvent;
33import javax.swing.table.JTableHeader;
34import javax.swing.table.TableColumn;
35import javax.swing.table.TableColumnModel;
36import javax.swing.table.TableRowSorter;
37
38import net.oni2.SettingsManager;
39import net.oni2.aeinstaller.backend.packages.Package;
40import net.oni2.aeinstaller.backend.packages.Type;
41import net.oni2.aeinstaller.gui.downloadwindow.Downloader;
42import net.oni2.resourcebundle.UTF8ResourceBundleLoader;
43
44/**
45 * @author Christian Illy
46 */
47public class ModTable extends JTable {
48 private static final long serialVersionUID = 1L;
49
50 private ResourceBundle bundle = UTF8ResourceBundleLoader
51 .getBundle("net.oni2.aeinstaller.localization.ModTable");
52
53 /**
54 * @author Christian Illy
55 */
56 public enum ETableContentType {
57 /**
58 * Table showing mods
59 */
60 MODS,
61 /**
62 * Table showing tools
63 */
64 TOOLS,
65 /**
66 * Table showing core packages
67 */
68 CORE
69 };
70
71 private HashSet<ModSelectionListener> modSelListeners = new HashSet<ModSelectionListener>();
72
73 private ModTableModel model;
74 private TableRowSorter<ModTableModel> sorter;
75
76 private ETableContentType contentType = ETableContentType.MODS;
77
78 /**
79 * Create a new ModTable
80 *
81 * @param contentType
82 * Content to show
83 */
84 public ModTable(ETableContentType contentType) {
85 super();
86
87 this.contentType = contentType;
88
89 setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
90 getSelectionModel().addListSelectionListener(this);
91 addMouseListener(new MouseEventHandler(this));
92 addKeyListener(new KeyEventHandler());
93 // To get checkbox-cells with background of row
94 ((JComponent) getDefaultRenderer(Boolean.class)).setOpaque(true);
95
96 model = new ModTableModel(contentType);
97
98 setModel(model);
99
100 sorter = new TableRowSorter<ModTableModel>(model);
101 setRowSorter(sorter);
102
103 setFilter(null, 0, null, EApplyFilterTo.ALL);
104
105 List<RowSorter.SortKey> sortKeys = new ArrayList<RowSorter.SortKey>();
106
107 int sortCol = SettingsManager.getInstance().get("modSortColumn", 1);
108 SortOrder sortOrder = SortOrder.valueOf(SettingsManager.getInstance()
109 .get("modSortOrder", "ASCENDING"));
110
111 sortKeys.add(new RowSorter.SortKey(sortCol, sortOrder));
112 sorter.setSortKeys(sortKeys);
113
114 for (int i = 0; i < model.getColumnCount(); i++) {
115 model.setColumnConstraints(i, getColumnModel().getColumn(i));
116 }
117
118 getTableHeader().addMouseListener(new HeaderMouseEventHandler());
119
120 if (contentType != ETableContentType.MODS) {
121 getColumnModel().removeColumn(getColumnModel().getColumn(0));
122 }
123 }
124
125 @Override
126 public String getToolTipText(MouseEvent e) {
127 int r = rowAtPoint(e.getPoint());
128 int c = columnAtPoint(e.getPoint());
129 if (r >= 0 && r < getRowCount()) {
130 int modelCol = convertColumnIndexToModel(c);
131 if (modelCol == 4) {
132 final Package mod = (Package) getValueAt(r, -1);
133
134 String tt = "<html>";
135 tt += String.format("%s: %s<br>",
136 bundle.getString("state.installed"),
137 bundle.getString((mod.isInstalled() ? "yes" : "no")));
138 tt += String.format(
139 "%s: %s<br>",
140 bundle.getString("state.updatable"),
141 bundle.getString((mod.isLocalAvailable()
142 && mod.isNewerAvailable() ? "yes" : "no")));
143 tt += String.format("%s: %s</html>", bundle
144 .getString("state.downloaded"), bundle.getString((mod
145 .isLocalAvailable() ? "yes" : "no")));
146 return tt;
147 }
148 }
149 return super.getToolTipText(e);
150 }
151
152 /**
153 * @param listener
154 * Listener to add
155 */
156 public void addModSelectionListener(ModSelectionListener listener) {
157 modSelListeners.add(listener);
158 }
159
160 /**
161 * @param listener
162 * Listener to remove
163 */
164 public void removeModSelectionListener(ModSelectionListener listener) {
165 modSelListeners.remove(listener);
166 }
167
168 private void notifyModSelectionListeners(Package m) {
169 for (ModSelectionListener l : modSelListeners) {
170 l.modSelectionChanged(this, m);
171 }
172 }
173
174 /**
175 * @param listener
176 * Listener to add
177 */
178 public void addDownloadSizeListener(ModInstallSelectionListener listener) {
179 model.addDownloadSizeListener(listener);
180 }
181
182 /**
183 * @param listener
184 * Listener to remove
185 */
186 public void removeDownloadSizeListener(ModInstallSelectionListener listener) {
187 model.removeDownloadSizeListener(listener);
188 }
189
190 /**
191 * Reload the nodes data after an update to the cache
192 */
193 public void reloadData() {
194 model.reloadData();
195 }
196
197 /**
198 * Revert the selection to the mods that are currently installed
199 */
200 public void revertSelection() {
201 model.revertSelection();
202 }
203
204 /**
205 * Reload the selection after a config was loaded
206 *
207 * @param config
208 * Config to load
209 */
210 public void reloadSelection(File config) {
211 model.reloadSelection(config);
212 }
213
214 /**
215 * @return Mods selected for installation
216 */
217 public TreeSet<Package> getSelectedMods() {
218 return model.getSelectedMods();
219 }
220
221 /**
222 * @param type
223 * Type of mods to show (null for all)
224 * @param downloadState
225 * Show only: 0 = all, 1 = online, 2 = downloaded, 3 = installed
226 * @param filterString
227 * String to filter on
228 * @param filterTo
229 * Fields to use string filter on
230 */
231 public void setFilter(Type type, int downloadState, String filterString,
232 EApplyFilterTo filterTo) {
233 sorter.setRowFilter(new ModTableFilter(type, downloadState,
234 filterString, filterTo, contentType == ETableContentType.CORE,
235 false));
236 }
237
238 @Override
239 public void sorterChanged(RowSorterEvent evt) {
240 super.sorterChanged(evt);
241 if (evt.getType() == RowSorterEvent.Type.SORT_ORDER_CHANGED) {
242 @SuppressWarnings("unchecked")
243 RowSorter<ModTableModel> rs = (RowSorter<ModTableModel>) getRowSorter();
244 List<? extends RowSorter.SortKey> keys = rs.getSortKeys();
245 if (keys.size() > 0) {
246 int col = keys.get(0).getColumn();
247 SortOrder so = keys.get(0).getSortOrder();
248 SettingsManager.getInstance().put("modSortColumn", col);
249 SettingsManager.getInstance()
250 .put("modSortOrder", so.toString());
251 }
252 }
253 }
254
255 /**
256 * Select/Unselect all currently visible items depending on the current
257 * state of selection
258 */
259 public void unSelectAll() {
260 boolean isAll = true;
261 for (int i = 0; i < getRowCount(); i++) {
262 int modRow = convertRowIndexToModel(i);
263 boolean inst = (Boolean) model.getValueAt(modRow, 0);
264 if (!inst) {
265 isAll = false;
266 break;
267 }
268 }
269
270 for (int i = 0; i < getRowCount(); i++) {
271 int modRow = convertRowIndexToModel(i);
272 model.selectPackage(modRow, !isAll);
273 }
274 model.updateDownloadSize();
275 invalidate();
276 repaint();
277 }
278
279 @Override
280 public void valueChanged(ListSelectionEvent e) {
281 super.valueChanged(e);
282 int viewRow = getSelectedRow();
283 if (viewRow < 0) {
284 notifyModSelectionListeners(null);
285 } else {
286 Package mod = (Package) getValueAt(viewRow, -1);
287 notifyModSelectionListeners(mod);
288 }
289 }
290
291 private class MouseEventHandler extends MouseAdapter {
292 private final Component parent;
293
294 public MouseEventHandler(Component parent) {
295 this.parent = parent;
296 }
297
298 private void mouseEventProcessing(MouseEvent e) {
299 int r = rowAtPoint(e.getPoint());
300 if (r >= 0 && r < getRowCount())
301 setRowSelectionInterval(r, r);
302 else
303 clearSelection();
304
305 int rowindex = getSelectedRow();
306 if (rowindex >= 0) {
307 if (e.isPopupTrigger() && e.getComponent() instanceof JTable) {
308 final Package mod = (Package) getValueAt(rowindex, -1);
309
310 JPopupMenu popup = new JPopupMenu();
311
312 if (mod.isLocalAvailable()) {
313 // Open package folder item
314 JMenuItem openModFolder = new JMenuItem(
315 bundle.getString("openModFolder.text"));
316 openModFolder.addActionListener(new ActionListener() {
317 @Override
318 public void actionPerformed(ActionEvent arg0) {
319 try {
320 Desktop.getDesktop().open(
321 mod.getLocalPath());
322 } catch (IOException e) {
323 e.printStackTrace();
324 }
325 }
326 });
327 popup.add(openModFolder);
328 }
329
330 if (mod.getUrl() != null) {
331 // Open Depot page item
332 JMenuItem openDepotPage = new JMenuItem(
333 bundle.getString("openDepotPage.text"));
334 openDepotPage.addActionListener(new ActionListener() {
335 @Override
336 public void actionPerformed(ActionEvent arg0) {
337 try {
338 Desktop.getDesktop().browse(mod.getUrl());
339 } catch (IOException e) {
340 e.printStackTrace();
341 }
342 }
343 });
344 popup.add(openDepotPage);
345 }
346
347 if (!mod.isLocalOnly()) {
348 // Download package
349 JMenuItem downloadPackage = new JMenuItem(
350 bundle.getString("downloadPackage.text"));
351 downloadPackage.addActionListener(new ActionListener() {
352 @Override
353 public void actionPerformed(ActionEvent arg0) {
354 TreeSet<Package> toDo = new TreeSet<Package>();
355 TreeSet<Package> deps = new TreeSet<Package>();
356 toDo.add(mod);
357 Downloader dl = new Downloader(toDo, deps,
358 false, parent);
359 try {
360 dl.setVisible(true);
361 } finally {
362 dl.dispose();
363 }
364 model.fireTableDataChanged();
365 invalidate();
366 repaint();
367 }
368 });
369 popup.add(downloadPackage);
370 }
371
372 if (mod.isLocalAvailable()
373 && contentType != ETableContentType.CORE) {
374 // Delete package folder item
375 JMenuItem deleteModFolder = new JMenuItem(
376 bundle.getString("deletePackage.text"));
377 deleteModFolder.addActionListener(new ActionListener() {
378 @Override
379 public void actionPerformed(ActionEvent arg0) {
380 if (mod.isLocalOnly()) {
381 JOptionPane.showMessageDialog(
382 null,
383 bundle.getString("deletePackageLocalOnly.text"),
384 bundle.getString("deletePackageLocalOnly.title"),
385 JOptionPane.INFORMATION_MESSAGE);
386 } else {
387 int res = JOptionPane.showConfirmDialog(
388 null,
389 bundle.getString("deletePackageConfirm.text"),
390 bundle.getString("deletePackageConfirm.title"),
391 JOptionPane.YES_NO_OPTION,
392 JOptionPane.WARNING_MESSAGE);
393 if (res == JOptionPane.YES_OPTION) {
394 mod.deleteLocalPackage();
395 model.fireTableDataChanged();
396 invalidate();
397 repaint();
398 }
399 }
400 }
401 });
402 popup.add(deleteModFolder);
403 }
404
405 if (popup.getSubElements().length > 0)
406 popup.show(e.getComponent(), e.getX(), e.getY());
407 }
408 }
409 }
410
411 @Override
412 public void mousePressed(MouseEvent e) {
413 mouseEventProcessing(e);
414 }
415
416 @Override
417 public void mouseReleased(MouseEvent e) {
418 mouseEventProcessing(e);
419 }
420 }
421
422 private class KeyEventHandler extends KeyAdapter {
423 private void goToRow(int row) {
424 setRowSelectionInterval(row, row);
425 JViewport viewport = (JViewport) getParent();
426 Rectangle rect = getCellRect(row, 0, true);
427 Rectangle r2 = viewport.getVisibleRect();
428 scrollRectToVisible(new Rectangle(rect.x, rect.y,
429 (int) r2.getWidth(), (int) r2.getHeight()));
430 }
431
432 @Override
433 public void keyTyped(KeyEvent e) {
434 super.keyTyped(e);
435
436 if (e.getModifiers() == 0) {
437 String key = String.valueOf(e.getKeyChar()).toLowerCase();
438 int row = getSelectedRow();
439 if (row == (getRowCount() - 1))
440 row = -1;
441 for (int i = row + 1; i < getRowCount(); i++) {
442 Package m = (Package) getValueAt(i, -1);
443 if (m.getName().toLowerCase().startsWith(key)) {
444 goToRow(i);
445 return;
446 }
447 }
448 if (row > 0) {
449 for (int i = 0; i < row; i++) {
450 Package m = (Package) getValueAt(i, -1);
451 if (m.getName().toLowerCase().startsWith(key)) {
452 goToRow(i);
453 return;
454 }
455 }
456 }
457 }
458 }
459 }
460
461 private class HeaderMouseEventHandler extends MouseAdapter {
462 private Vector<TableColumn> columns = new Vector<TableColumn>();
463 private TableColumnModel tcm = getColumnModel();
464
465 public HeaderMouseEventHandler() {
466 super();
467
468 for (int i = 1; i < tcm.getColumnCount(); i++) {
469 columns.add(tcm.getColumn(i));
470 }
471
472 for (int i = 1; i < columns.size(); i++) {
473 TableColumn tc = columns.get(i);
474 if (!SettingsManager.getInstance().get(
475 String.format("modShowColumn%02d", tc.getModelIndex()),
476 true))
477 tcm.removeColumn(tc);
478 }
479 }
480
481 private TableColumn getColumn(String name) {
482 for (TableColumn tc : columns) {
483 if (tc.getHeaderValue().equals(name)) {
484 return tc;
485 }
486 }
487 return null;
488 }
489
490 private int headerContains(TableColumn tc) {
491 for (int col = 0; col < tcm.getColumnCount(); col++) {
492 if (tcm.getColumn(col).equals(tc))
493 return col;
494 }
495 return -1;
496 }
497
498 private void mouseEventProcessing(MouseEvent e) {
499 if (e.isPopupTrigger() && e.getComponent() instanceof JTableHeader) {
500 JPopupMenu popup = new JPopupMenu();
501
502 ActionListener al = new ActionListener() {
503 @Override
504 public void actionPerformed(ActionEvent e) {
505 JCheckBoxMenuItem itm = (JCheckBoxMenuItem) e
506 .getSource();
507 TableColumn col = getColumn(itm.getText());
508 if (itm.isSelected()) {
509 tcm.addColumn(col);
510 for (int i = columns.indexOf(col) - 1; i >= 0; i--) {
511 int pos = headerContains(columns.get(i));
512 if (pos >= 0) {
513 tcm.moveColumn(tcm.getColumnCount() - 1,
514 pos + 1);
515 break;
516 }
517 }
518 } else {
519 tcm.removeColumn(col);
520 }
521 SettingsManager.getInstance().put(
522 String.format("modShowColumn%02d",
523 col.getModelIndex()), itm.isSelected());
524 }
525 };
526
527 for (int i = 1; i < columns.size(); i++) {
528 JCheckBoxMenuItem itm = new JCheckBoxMenuItem(
529 (String) columns.get(i).getHeaderValue());
530 itm.setSelected(headerContains(columns.get(i)) >= 0);
531
532 itm.addActionListener(al);
533 popup.add(itm);
534 }
535
536 if (popup.getSubElements().length > 0)
537 popup.show(e.getComponent(), e.getX(), e.getY());
538 }
539 }
540
541 @Override
542 public void mousePressed(MouseEvent e) {
543 mouseEventProcessing(e);
544 }
545
546 @Override
547 public void mouseReleased(MouseEvent e) {
548 mouseEventProcessing(e);
549 }
550 }
551
552}
Note: See TracBrowser for help on using the repository browser.