package net.oni2.aeinstaller.gui.modtable; import java.awt.Desktop; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.ResourceBundle; import java.util.TreeSet; import javax.swing.JComponent; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPopupMenu; import javax.swing.JTable; import javax.swing.JViewport; import javax.swing.ListSelectionModel; import javax.swing.RowSorter; import javax.swing.SortOrder; import javax.swing.event.ListSelectionEvent; import javax.swing.event.RowSorterEvent; import javax.swing.table.TableRowSorter; import net.oni2.aeinstaller.backend.Settings; import net.oni2.aeinstaller.backend.packages.Package; import net.oni2.aeinstaller.backend.packages.Type; /** * @author Christian Illy */ public class ModTable extends JTable { private static final long serialVersionUID = 1L; private ResourceBundle bundle = ResourceBundle .getBundle("net.oni2.aeinstaller.localization.ModTable"); /** * @author Christian Illy */ public enum ETableContentType { /** * Table showing mods */ MODS, /** * Table showing tools */ TOOLS, /** * Table showing core packages */ CORE }; private HashSet modSelListeners = new HashSet(); private ModTableModel model; private TableRowSorter sorter; private ETableContentType contentType = ETableContentType.MODS; /** * Create a new ModTable * * @param contentType * Content to show */ public ModTable(ETableContentType contentType) { super(); this.contentType = contentType; setSelectionMode(ListSelectionModel.SINGLE_SELECTION); getSelectionModel().addListSelectionListener(this); addMouseListener(new MouseEventHandler()); addKeyListener(new KeyEventHandler()); // To get checkbox-cells with background of row ((JComponent) getDefaultRenderer(Boolean.class)).setOpaque(true); model = new ModTableModel(contentType); setModel(model); sorter = new TableRowSorter(model); setRowSorter(sorter); setFilter(null, 0); List sortKeys = new ArrayList(); int sortCol = Settings.getInstance().get("modSortColumn", 1); SortOrder sortOrder = SortOrder.valueOf(Settings.getInstance().get( "modSortOrder", "ASCENDING")); sortKeys.add(new RowSorter.SortKey(sortCol, sortOrder)); sorter.setSortKeys(sortKeys); for (int i = 0; i < model.getColumnCount(); i++) { model.setColumnConstraints(i, getColumnModel().getColumn(i)); } if (contentType != ETableContentType.MODS) { getColumnModel().removeColumn(getColumnModel().getColumn(0)); } } @Override public String getToolTipText(MouseEvent e) { int r = rowAtPoint(e.getPoint()); int c = columnAtPoint(e.getPoint()); if (r >= 0 && r < getRowCount()) { int modelCol = convertColumnIndexToModel(c); if (modelCol == 4) { final Package mod = (Package) getValueAt(r, -1); String tt = ""; tt += String.format("%s: %s
", bundle.getString("state.installed"), bundle.getString((mod.isInstalled() ? "yes" : "no"))); tt += String.format( "%s: %s
", bundle.getString("state.updatable"), bundle.getString((mod.isLocalAvailable() && mod.isNewerAvailable() ? "yes" : "no"))); tt += String.format("%s: %s", bundle .getString("state.downloaded"), bundle.getString((mod .isLocalAvailable() ? "yes" : "no"))); return tt; } } return super.getToolTipText(e); } /** * @param listener * Listener to add */ public void addModSelectionListener(ModSelectionListener listener) { modSelListeners.add(listener); } /** * @param listener * Listener to remove */ public void removeModSelectionListener(ModSelectionListener listener) { modSelListeners.remove(listener); } private void notifyModSelectionListeners(Package m) { for (ModSelectionListener l : modSelListeners) { l.modSelectionChanged(this, m); } } /** * @param listener * Listener to add */ public void addDownloadSizeListener(DownloadSizeListener listener) { model.addDownloadSizeListener(listener); } /** * @param listener * Listener to remove */ public void removeDownloadSizeListener(DownloadSizeListener listener) { model.removeDownloadSizeListener(listener); } /** * Reload the nodes data after an update to the cache */ public void reloadData() { model.reloadData(); } /** * Revert the selection to the mods that are currently installed */ public void revertSelection() { model.revertSelection(); } /** * Reload the selection after a config was loaded * * @param config * Config to load */ public void reloadSelection(File config) { model.reloadSelection(config); } /** * @return Mods selected for installation */ public TreeSet getSelectedMods() { return model.getSelectedMods(); } /** * @param type * Type of mods to show (null for all) * @param downloadState * Show only: 0 = all, 1 = online, 2 = downloaded */ public void setFilter(Type type, int downloadState) { sorter.setRowFilter(new ModTableFilter(type, downloadState, contentType == ETableContentType.CORE, false)); } @Override public void sorterChanged(RowSorterEvent evt) { super.sorterChanged(evt); if (evt.getType() == RowSorterEvent.Type.SORT_ORDER_CHANGED) { @SuppressWarnings("unchecked") RowSorter rs = (RowSorter) getRowSorter(); List keys = rs.getSortKeys(); if (keys.size() > 0) { int col = keys.get(0).getColumn(); SortOrder so = keys.get(0).getSortOrder(); Settings.getInstance().put("modSortColumn", col); Settings.getInstance().put("modSortOrder", so.toString()); } } } /** * Select/Unselect all currently visible items depending on the current * state of selection */ public void unSelectAll() { boolean isAll = true; for (int i = 0; i < getRowCount(); i++) { int modRow = convertRowIndexToModel(i); boolean inst = (Boolean) model.getValueAt(modRow, 0); if (!inst) { isAll = false; break; } } for (int i = 0; i < getRowCount(); i++) { int modRow = convertRowIndexToModel(i); model.setValueAt(!isAll, modRow, 0); } invalidate(); repaint(); } @Override public void valueChanged(ListSelectionEvent e) { super.valueChanged(e); int viewRow = getSelectedRow(); if (viewRow < 0) { notifyModSelectionListeners(null); } else { Package mod = (Package) getValueAt(viewRow, -1); notifyModSelectionListeners(mod); } } private class MouseEventHandler extends MouseAdapter { private void mouseEventProcessing(MouseEvent e) { int r = rowAtPoint(e.getPoint()); if (r >= 0 && r < getRowCount()) setRowSelectionInterval(r, r); else clearSelection(); int rowindex = getSelectedRow(); if (rowindex >= 0) { if (e.isPopupTrigger() && e.getComponent() instanceof JTable) { final Package mod = (Package) getValueAt(rowindex, -1); JPopupMenu popup = new JPopupMenu(); if (mod.isLocalAvailable()) { // Open package folder item JMenuItem openModFolder = new JMenuItem( bundle.getString("openModFolder.text")); openModFolder.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { try { Desktop.getDesktop().open( mod.getLocalPath()); } catch (IOException e) { e.printStackTrace(); } } }); popup.add(openModFolder); } if (mod.getUrl() != null) { // Open Depot page item JMenuItem openDepotPage = new JMenuItem( bundle.getString("openDepotPage.text")); openDepotPage.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { try { Desktop.getDesktop().browse(mod.getUrl()); } catch (IOException e) { e.printStackTrace(); } } }); popup.add(openDepotPage); } if (mod.isLocalAvailable() && contentType != ETableContentType.CORE) { // Delete package folder item JMenuItem deleteModFolder = new JMenuItem( bundle.getString("deletePackage.text")); deleteModFolder.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { if (mod.getNode() == null) { JOptionPane.showMessageDialog( null, bundle.getString("deletePackageLocalOnly.text"), bundle.getString("deletePackageLocalOnly.title"), JOptionPane.INFORMATION_MESSAGE); } else { int res = JOptionPane.showConfirmDialog( null, bundle.getString("deletePackageConfirm.text"), bundle.getString("deletePackageConfirm.title"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); if (res == JOptionPane.YES_OPTION) { mod.deleteLocalPackage(); invalidate(); repaint(); } } } }); popup.add(deleteModFolder); } if (popup.getSubElements().length > 0) popup.show(e.getComponent(), e.getX(), e.getY()); } } } @Override public void mousePressed(MouseEvent e) { mouseEventProcessing(e); } @Override public void mouseReleased(MouseEvent e) { mouseEventProcessing(e); } } private class KeyEventHandler extends KeyAdapter { @Override public void keyTyped(KeyEvent e) { super.keyTyped(e); if (e.getModifiers() == 0) { String key = String.valueOf(e.getKeyChar()).toLowerCase(); for (int i = 0; i < getRowCount(); i++) { Package m = (Package) getValueAt(i, -1); if (m.getName().toLowerCase().startsWith(key)) { setRowSelectionInterval(i, i); JViewport viewport = (JViewport) getParent(); Rectangle rect = getCellRect(i, 0, true); Rectangle r2 = viewport.getVisibleRect(); scrollRectToVisible(new Rectangle(rect.x, rect.y, (int) r2.getWidth(), (int) r2.getHeight())); break; } } } } } }