diff --git a/src/main/java/net/vhati/modmanager/core/FTLUtilities.java b/src/main/java/net/vhati/modmanager/core/FTLUtilities.java index 82b52a9..ddad8be 100644 --- a/src/main/java/net/vhati/modmanager/core/FTLUtilities.java +++ b/src/main/java/net/vhati/modmanager/core/FTLUtilities.java @@ -76,7 +76,7 @@ public class FTLUtilities { message += "You will now be prompted to locate FTL manually.\n"; message += "Select '(FTL dir)/resources/data.dat'.\n"; message += "Or 'FTL.app', if you're on OSX."; - JOptionPane.showMessageDialog( parentComponent, message, "Find FTL", JOptionPane.INFORMATION_MESSAGE ); + JOptionPane.showMessageDialog( parentComponent, message, "Find FTL", JOptionPane.INFORMATION_MESSAGE ); final JFileChooser fc = new JFileChooser(); fc.setDialogTitle( "Find data.dat or FTL.app" ); diff --git a/src/main/java/net/vhati/modmanager/ui/ManagerFrame.java b/src/main/java/net/vhati/modmanager/ui/ManagerFrame.java index 9513d07..1e1e8e0 100644 --- a/src/main/java/net/vhati/modmanager/ui/ManagerFrame.java +++ b/src/main/java/net/vhati/modmanager/ui/ManagerFrame.java @@ -10,8 +10,6 @@ import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.BufferedWriter; @@ -37,7 +35,6 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.swing.BorderFactory; import javax.swing.BoxLayout; -import javax.swing.DropMode; import javax.swing.JButton; import javax.swing.JFileChooser; import javax.swing.JFrame; @@ -47,17 +44,14 @@ import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; -import javax.swing.JScrollPane; import javax.swing.JSeparator; import javax.swing.JSplitPane; import javax.swing.JTable; import javax.swing.JTextArea; -import javax.swing.ListSelectionModel; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; -import javax.swing.table.DefaultTableModel; import net.vhati.ftldat.FTLDat; import net.vhati.modmanager.core.AutoUpdateInfo; @@ -76,7 +70,6 @@ import net.vhati.modmanager.core.Report.ReportFormatter; import net.vhati.modmanager.core.SlipstreamConfig; import net.vhati.modmanager.json.JacksonCatalogWriter; import net.vhati.modmanager.json.URLFetcher; -import net.vhati.modmanager.ui.ChecklistTableModel; import net.vhati.modmanager.ui.InertPanel; import net.vhati.modmanager.ui.ManagerInitThread; import net.vhati.modmanager.ui.ModInfoArea; @@ -85,7 +78,7 @@ import net.vhati.modmanager.ui.ModXMLSandbox; import net.vhati.modmanager.ui.SlipstreamConfigDialog; import net.vhati.modmanager.ui.Statusbar; import net.vhati.modmanager.ui.StatusbarMouseListener; -import net.vhati.modmanager.ui.TableRowTransferHandler; +import net.vhati.modmanager.ui.table.ChecklistTablePanel; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -132,8 +125,7 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse private NerfListener nerfListener = new NerfListener( this ); - private ChecklistTableModel localModsTableModel; - private JTable localModsTable; + private ChecklistTablePanel modsTablePanel; private JMenuBar menubar; private JMenu fileMenu; @@ -174,21 +166,8 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse JPanel topPanel = new JPanel( new BorderLayout() ); - localModsTableModel = new ChecklistTableModel(); - - localModsTable = new JTable( localModsTableModel ); - localModsTable.setFillsViewportHeight( true ); - localModsTable.setSelectionMode( ListSelectionModel.SINGLE_SELECTION ); - localModsTable.setTableHeader( null ); - localModsTable.getColumnModel().getColumn(0).setMinWidth(30); - localModsTable.getColumnModel().getColumn(0).setMaxWidth(30); - localModsTable.getColumnModel().getColumn(0).setPreferredWidth(30); - - JScrollPane localModsScroll = new JScrollPane( null, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER ); - localModsScroll.setViewportView( localModsTable ); - //localModsScroll.setColumnHeaderView( null ); // Counterpart to setTableHeader(). - localModsScroll.setPreferredSize( new Dimension(Integer.MIN_VALUE, Integer.MIN_VALUE) ); - topPanel.add( localModsScroll, BorderLayout.CENTER ); + modsTablePanel = new ChecklistTablePanel(); + topPanel.add( modsTablePanel, BorderLayout.CENTER ); JPanel modActionsPanel = new JPanel(); modActionsPanel.setLayout( new BoxLayout(modActionsPanel, BoxLayout.Y_AXIS) ); @@ -281,11 +260,7 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse public void windowClosed( WindowEvent e ) { // dispose() was called. - List sortedMods = new ArrayList(); - - for ( int i=0; i < localModsTableModel.getRowCount(); i++ ) { - sortedMods.add( localModsTableModel.getItem(i) ); - } + List sortedMods = modsTablePanel.getAllItems(); saveModOrder( sortedMods ); SlipstreamConfig appConfig = ManagerFrame.this.appConfig; @@ -318,58 +293,20 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse } }); - // Double-click toggles checkboxes. - localModsTable.addMouseListener(new MouseAdapter() { - int prevRow = -1; - int streak = 0; - - @Override - public void mouseClicked( MouseEvent e ) { - if ( e.getSource() != localModsTable ) return; - int thisRow = localModsTable.rowAtPoint( e.getPoint() ); - - // Reset on first click and when no longer on that row. - if ( e.getClickCount() == 1 ) prevRow = -1; - if ( thisRow != prevRow || thisRow == -1 ) { - streak = 1; - prevRow = thisRow; - return; - } else { - streak++; - } - if ( streak % 2 != 0 ) return; // Respond only to click pairs. - - // Don't further toggle a multi-clicked checkbox. - int viewCol = localModsTable.columnAtPoint( e.getPoint() ); - int modelCol = localModsTable.getColumnModel().getColumn(viewCol).getModelIndex(); - if ( modelCol == 0 ) return; - - int selRow = localModsTable.getSelectedRow(); - if ( selRow != -1 ) { - boolean selected = localModsTableModel.isSelected( selRow ); - localModsTableModel.setSelected( selRow, !selected ); - } - } - }); - // Highlighted row shows mod info. - localModsTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { + modsTablePanel.getTable().getSelectionModel().addListSelectionListener(new ListSelectionListener() { @Override public void valueChanged( ListSelectionEvent e ) { if ( e.getValueIsAdjusting() ) return; - int row = localModsTable.getSelectedRow(); + int row = modsTablePanel.getTable().getSelectedRow(); if ( row == -1 ) return; - ModFileInfo modFileInfo = localModsTableModel.getItem( row ); + ModFileInfo modFileInfo = modsTablePanel.getTableModel().getItem( row ); showLocalModInfo( modFileInfo ); } }); - localModsTable.setTransferHandler( new TableRowTransferHandler( localModsTable ) ); - localModsTable.setDropMode( DropMode.INSERT ); // Drop between rows, not on them. - localModsTable.setDragEnabled( true ); - menubar = new JMenuBar(); fileMenu = new JMenu( "File" ); fileMenu.setMnemonic( KeyEvent.VK_F ); @@ -537,7 +474,7 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse } modFileHashes.clear(); - localModsTableModel.removeAllItems(); + modsTablePanel.clear(); boolean allowZip = appConfig.getProperty( "allow_zip", "false" ).equals( "true" ); File[] modFiles = modsDir.listFiles( new ModFileFilter( allowZip ) ); @@ -550,7 +487,7 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse List sortedMods = reorderMods( unsortedMods, preferredOrder ); for ( ModFileInfo modFileInfo : sortedMods ) { - localModsTableModel.addItem( modFileInfo ); + modsTablePanel.getTableModel().addItem( modFileInfo ); } ModsScanThread scanThread = new ModsScanThread( modFiles, localModDB, this ); @@ -712,10 +649,8 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse if ( source == patchBtn ) { List modFiles = new ArrayList(); - for ( int i=0; i < localModsTableModel.getRowCount(); i++ ) { - if ( localModsTableModel.isSelected(i) ) { - modFiles.add( localModsTableModel.getItem(i).getFile() ); - } + for ( ModFileInfo modFileInfo : modsTablePanel.getSelectedItems() ) { + modFiles.add( modFileInfo.getFile() ); } File datsDir = new File( appConfig.getProperty( "ftl_dats_path" ) ); @@ -746,24 +681,13 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse patchDlg.setVisible( true ); } else if ( source == toggleAllBtn ) { - int selectedCount = 0; - for ( int i = localModsTableModel.getRowCount()-1; i >= 0; i-- ) { - if ( localModsTableModel.isSelected(i) ) selectedCount++; - } - boolean b = ( selectedCount != localModsTableModel.getRowCount() ); - - for ( int i = localModsTableModel.getRowCount()-1; i >= 0; i-- ) { - localModsTableModel.setSelected( i, b ); - } + modsTablePanel.toggleAllItemSelection(); } else if ( source == validateBtn ) { StringBuilder resultBuf = new StringBuilder(); boolean anyInvalid = false; - for ( int i=0; i < localModsTableModel.getRowCount(); i++ ) { - if ( !localModsTableModel.isSelected(i) ) continue; - - ModFileInfo modFileInfo = localModsTableModel.getItem( i ); + for ( ModFileInfo modFileInfo : modsTablePanel.getSelectedItems() ) { Report validateReport = ModUtilities.validateModFile( modFileInfo.getFile() ); ReportFormatter formatter = new ReportFormatter(); @@ -810,8 +734,8 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse List preferredOrder = new ArrayList(); - for ( int i=0; i < localModsTableModel.getRowCount(); i++ ) { - preferredOrder.add( localModsTableModel.getItem(i).getName() ); + for ( ModFileInfo modFileInfo : modsTablePanel.getAllItems() ) { + preferredOrder.add( modFileInfo.getName() ); } rescanMods( preferredOrder ); } diff --git a/src/main/java/net/vhati/modmanager/ui/ChecklistTableModel.java b/src/main/java/net/vhati/modmanager/ui/table/ChecklistTableModel.java similarity index 96% rename from src/main/java/net/vhati/modmanager/ui/ChecklistTableModel.java rename to src/main/java/net/vhati/modmanager/ui/table/ChecklistTableModel.java index 7eee528..83e3c6a 100644 --- a/src/main/java/net/vhati/modmanager/ui/ChecklistTableModel.java +++ b/src/main/java/net/vhati/modmanager/ui/table/ChecklistTableModel.java @@ -1,10 +1,11 @@ -package net.vhati.modmanager.ui; +package net.vhati.modmanager.ui.table; import java.util.ArrayList; import java.util.List; import javax.swing.table.AbstractTableModel; import net.vhati.modmanager.core.ModInfo; +import net.vhati.modmanager.ui.table.Reorderable; public class ChecklistTableModel extends AbstractTableModel implements Reorderable { diff --git a/src/main/java/net/vhati/modmanager/ui/table/ChecklistTablePanel.java b/src/main/java/net/vhati/modmanager/ui/table/ChecklistTablePanel.java new file mode 100644 index 0000000..5e1f5f1 --- /dev/null +++ b/src/main/java/net/vhati/modmanager/ui/table/ChecklistTablePanel.java @@ -0,0 +1,134 @@ +package net.vhati.modmanager.ui.table; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.List; +import javax.swing.DropMode; +import javax.swing.ListSelectionModel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; + +import net.vhati.modmanager.core.ModFileInfo; +import net.vhati.modmanager.ui.table.ChecklistTableModel; +import net.vhati.modmanager.ui.table.TableRowTransferHandler; + + +public class ChecklistTablePanel extends JPanel { + + protected ChecklistTableModeltableModel; + protected JTable table; + + + public ChecklistTablePanel() { + super( new BorderLayout() ); + + tableModel = new ChecklistTableModel(); + + table = new JTable( tableModel ); + table.setFillsViewportHeight( true ); + table.setSelectionMode( ListSelectionModel.SINGLE_SELECTION ); + table.setTableHeader( null ); + table.getColumnModel().getColumn(0).setMinWidth(30); + table.getColumnModel().getColumn(0).setMaxWidth(30); + table.getColumnModel().getColumn(0).setPreferredWidth(30); + + JScrollPane scrollPane = new JScrollPane( null, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER ); + scrollPane.setViewportView( table ); + //scrollPane.setColumnHeaderView( null ); // Counterpart to setTableHeader(). + scrollPane.setPreferredSize( new Dimension(Integer.MIN_VALUE, Integer.MIN_VALUE) ); + this.add( scrollPane, BorderLayout.CENTER ); + + + // Double-click toggles checkboxes. + table.addMouseListener(new MouseAdapter() { + int prevRow = -1; + int streak = 0; + + @Override + public void mouseClicked( MouseEvent e ) { + if ( e.getSource() != table ) return; + int thisRow = table.rowAtPoint( e.getPoint() ); + + // Reset on first click and when no longer on that row. + if ( e.getClickCount() == 1 ) prevRow = -1; + if ( thisRow != prevRow || thisRow == -1 ) { + streak = 1; + prevRow = thisRow; + return; + } else { + streak++; + } + if ( streak % 2 != 0 ) return; // Respond only to click pairs. + + // Don't further toggle a multi-clicked checkbox. + int viewCol = table.columnAtPoint( e.getPoint() ); + int modelCol = table.getColumnModel().getColumn(viewCol).getModelIndex(); + if ( modelCol == 0 ) return; + + int selRow = table.getSelectedRow(); + if ( selRow != -1 ) { + boolean selected = tableModel.isSelected( selRow ); + tableModel.setSelected( selRow, !selected ); + } + } + }); + + table.setTransferHandler( new TableRowTransferHandler( table ) ); + table.setDropMode( DropMode.INSERT ); // Drop between rows, not on them. + table.setDragEnabled( true ); + } + + + public void clear() { + tableModel.removeAllItems(); + } + + + public List getAllItems() { + List results = new ArrayList(); + + for ( int i=0; i < tableModel.getRowCount(); i++ ) { + results.add( tableModel.getItem(i) ); + } + + return results; + } + + public List getSelectedItems() { + List results = new ArrayList(); + + for ( int i=0; i < tableModel.getRowCount(); i++ ) { + if ( tableModel.isSelected(i) ) { + results.add( tableModel.getItem(i) ); + } + } + + return results; + } + + + public void toggleAllItemSelection() { + int selectedCount = 0; + for ( int i = tableModel.getRowCount()-1; i >= 0; i-- ) { + if ( tableModel.isSelected(i) ) selectedCount++; + } + boolean b = ( selectedCount != tableModel.getRowCount() ); + + for ( int i = tableModel.getRowCount()-1; i >= 0; i-- ) { + tableModel.setSelected( i, b ); + } + } + + + public ChecklistTableModel getTableModel() { + return tableModel; + } + + public JTable getTable() { + return table; + } +} diff --git a/src/main/java/net/vhati/modmanager/ui/Reorderable.java b/src/main/java/net/vhati/modmanager/ui/table/Reorderable.java similarity index 78% rename from src/main/java/net/vhati/modmanager/ui/Reorderable.java rename to src/main/java/net/vhati/modmanager/ui/table/Reorderable.java index b6eb0d9..64ce492 100644 --- a/src/main/java/net/vhati/modmanager/ui/Reorderable.java +++ b/src/main/java/net/vhati/modmanager/ui/table/Reorderable.java @@ -1,4 +1,4 @@ -package net.vhati.modmanager.ui; +package net.vhati.modmanager.ui.table; public interface Reorderable { diff --git a/src/main/java/net/vhati/modmanager/ui/TableRowTransferHandler.java b/src/main/java/net/vhati/modmanager/ui/table/TableRowTransferHandler.java similarity index 94% rename from src/main/java/net/vhati/modmanager/ui/TableRowTransferHandler.java rename to src/main/java/net/vhati/modmanager/ui/table/TableRowTransferHandler.java index a00aa32..48c0b8a 100644 --- a/src/main/java/net/vhati/modmanager/ui/TableRowTransferHandler.java +++ b/src/main/java/net/vhati/modmanager/ui/table/TableRowTransferHandler.java @@ -1,4 +1,4 @@ -package net.vhati.modmanager.ui; +package net.vhati.modmanager.ui.table; import java.awt.Cursor; import java.awt.datatransfer.DataFlavor; @@ -8,6 +8,8 @@ import javax.swing.JComponent; import javax.swing.JTable; import javax.swing.TransferHandler; +import net.vhati.modmanager.ui.table.Reorderable; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -27,6 +29,7 @@ public class TableRowTransferHandler extends TransferHandler { public TableRowTransferHandler( JTable table ) { + super(); if ( table.getModel() instanceof Reorderable == false ) { throw new IllegalArgumentException( "The tableModel doesn't implement Reorderable." ); } @@ -79,7 +82,8 @@ public class TableRowTransferHandler extends TransferHandler { target.getSelectionModel().addSelectionInterval( dropRow, dropRow ); return true; } - } catch (Exception e) { + } + catch ( Exception e ) { log.error( e ); } return false; @@ -99,7 +103,7 @@ public class TableRowTransferHandler extends TransferHandler { * from a drag source, to be transformed into a flavor * suitable for the drop target. */ - private class IntegerTransferrable implements Transferable{ + private class IntegerTransferrable implements Transferable { private Integer data; public IntegerTransferrable( Integer data ) {