diff --git a/launcher-fancy/src/main/java/com/skcraft/launcher/FancyLauncherFrame.java b/launcher-fancy/src/main/java/com/skcraft/launcher/FancyLauncherFrame.java index 7b1ea19..0d413dd 100644 --- a/launcher-fancy/src/main/java/com/skcraft/launcher/FancyLauncherFrame.java +++ b/launcher-fancy/src/main/java/com/skcraft/launcher/FancyLauncherFrame.java @@ -26,7 +26,7 @@ setSize(800, 500); setLocationRelativeTo(null); - SwingHelper.removeOpaqueness(getInstancesList()); + SwingHelper.removeOpaqueness(getInstancesTable()); SwingHelper.removeOpaqueness(getInstanceScroll()); getInstanceScroll().setBorder(BorderFactory.createEmptyBorder()); } diff --git a/launcher/src/main/java/com/skcraft/launcher/InstanceList.java b/launcher/src/main/java/com/skcraft/launcher/InstanceList.java index 803320b..8134b99 100644 --- a/launcher/src/main/java/com/skcraft/launcher/InstanceList.java +++ b/launcher/src/main/java/com/skcraft/launcher/InstanceList.java @@ -18,7 +18,6 @@ import lombok.extern.java.Log; import org.apache.commons.io.filefilter.DirectoryFileFilter; -import javax.swing.*; import java.io.File; import java.io.FileFilter; import java.io.IOException; @@ -34,7 +33,7 @@ * Stores the list of instances. */ @Log -public class InstanceList extends AbstractListModel { +public class InstanceList { private final Launcher launcher; @Getter private final List instances = new ArrayList(); @@ -98,17 +97,6 @@ */ public synchronized void sort() { Collections.sort(instances); - fireContentsChanged(this, 0, size()); - } - - @Override - public int getSize() { - return size(); - } - - @Override - public Instance getElementAt(int index) { - return get(index); } public final class Enumerator implements Callable, ProgressObservable { @@ -206,7 +194,6 @@ instances.clear(); instances.addAll(local); instances.addAll(remote); - fireContentsChanged(this, 0, size()); log.info(instances.size() + " instance(s) enumerated."); } diff --git a/launcher/src/main/java/com/skcraft/launcher/dialog/LauncherFrame.java b/launcher/src/main/java/com/skcraft/launcher/dialog/LauncherFrame.java index 75ed9a0..1aa47b0 100644 --- a/launcher/src/main/java/com/skcraft/launcher/dialog/LauncherFrame.java +++ b/launcher/src/main/java/com/skcraft/launcher/dialog/LauncherFrame.java @@ -10,15 +10,10 @@ import com.skcraft.launcher.Instance; import com.skcraft.launcher.InstanceList; import com.skcraft.launcher.Launcher; -import com.skcraft.launcher.dialog.renderer.InstanceCellRenderer; import com.skcraft.launcher.launch.LaunchListener; import com.skcraft.launcher.launch.LaunchOptions; import com.skcraft.launcher.launch.LaunchOptions.UpdatePolicy; -import com.skcraft.launcher.swing.ActionListeners; -import com.skcraft.launcher.swing.DoubleClickToButtonAdapter; -import com.skcraft.launcher.swing.PopupMouseAdapter; -import com.skcraft.launcher.swing.SwingHelper; -import com.skcraft.launcher.swing.WebpagePanel; +import com.skcraft.launcher.swing.*; import com.skcraft.launcher.util.SharedLocale; import com.skcraft.launcher.util.SwingExecutor; import lombok.Getter; @@ -27,6 +22,8 @@ import net.miginfocom.swing.MigLayout; import javax.swing.*; +import javax.swing.event.TableModelEvent; +import javax.swing.event.TableModelListener; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -46,8 +43,11 @@ private final Launcher launcher; - @Getter private final JList instancesList = new JList(); - @Getter private final JScrollPane instanceScroll = new JScrollPane(instancesList); + @Getter + private final InstanceTable instancesTable = new InstanceTable(); + private final InstanceTableModel instancesModel; + @Getter + private final JScrollPane instanceScroll = new JScrollPane(instancesTable); private WebpagePanel webView; private JSplitPane splitPane; private final JButton launchButton = new JButton(SharedLocale.tr("launcher.launch")); @@ -65,6 +65,7 @@ super(tr("launcher.title", launcher.getVersion())); this.launcher = launcher; + instancesModel = new InstanceTableModel(launcher.getInstances()); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setMinimumSize(new Dimension(400, 300)); @@ -101,10 +102,7 @@ }); updateCheck.setSelected(true); - instancesList.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - instancesList.setDragEnabled(false); - instancesList.setCellRenderer(new InstanceCellRenderer()); - instancesList.setModel(launcher.getInstances()); + instancesTable.setModel(instancesModel); launchButton.setFont(launchButton.getFont().deriveFont(Font.BOLD)); splitPane.setDividerLocation(200); splitPane.setDividerSize(4); @@ -119,7 +117,16 @@ add(container, BorderLayout.CENTER); - instancesList.addMouseListener(new DoubleClickToButtonAdapter(launchButton)); + instancesModel.addTableModelListener(new TableModelListener() { + @Override + public void tableChanged(TableModelEvent e) { + if (instancesTable.getRowCount() > 0) { + instancesTable.setRowSelectionInterval(0, 0); + } + } + }); + + instancesTable.addMouseListener(new DoubleClickToButtonAdapter(launchButton)); refreshButton.addActionListener(new ActionListener() { @Override @@ -150,19 +157,16 @@ } }); - instancesList.addMouseListener(new PopupMouseAdapter() { + instancesTable.addMouseListener(new PopupMouseAdapter() { @Override protected void showPopup(MouseEvent e) { - //noinspection unchecked - JList list = ((JList) e.getSource()); - int index = list.locationToIndex(new Point(e.getX(), e.getY())); + int index = instancesTable.rowAtPoint(e.getPoint()); + Instance selected = null; if (index >= 0) { - list.setSelectedIndex(list.locationToIndex(new Point(e.getX(), e.getY()))); - Instance selected = list.getSelectedValue(); - popupInstanceMenu(e.getComponent(), e.getX(), e.getY(), selected); - } else { - list.setSelectedValue(null, false); + instancesTable.setRowSelectionInterval(index, index); + selected = launcher.getInstances().get(index); } + popupInstanceMenu(e.getComponent(), e.getX(), e.getY(), selected); } }); } @@ -245,6 +249,7 @@ public void actionPerformed(ActionEvent e) { selected.setUpdatePending(true); launch(); + instancesModel.update(); } }); popup.add(menuItem); @@ -314,6 +319,7 @@ @Override public void run() { launch(); + instancesModel.update(); } }, SwingExecutor.INSTANCE); } @@ -324,6 +330,10 @@ future.addListener(new Runnable() { @Override public void run() { + instancesModel.update(); + if (instancesTable.getRowCount() > 0) { + instancesTable.setRowSelectionInterval(0, 0); + } requestFocus(); } }, SwingExecutor.INSTANCE); @@ -339,7 +349,7 @@ private void launch() { boolean permitUpdate = updateCheck.isSelected(); - Instance instance = instancesList.getSelectedValue(); + Instance instance = launcher.getInstances().get(instancesTable.getSelectedRow()); LaunchOptions options = new LaunchOptions.Builder() .setInstance(instance) @@ -361,6 +371,10 @@ @Override public void instancesUpdated() { + LauncherFrame frame = frameRef.get(); + if (frame != null) { + frame.instancesModel.update(); + } } @Override diff --git a/launcher/src/main/java/com/skcraft/launcher/dialog/renderer/InstanceCellRenderer.java b/launcher/src/main/java/com/skcraft/launcher/dialog/renderer/InstanceCellRenderer.java deleted file mode 100644 index 344a3c5..0000000 --- a/launcher/src/main/java/com/skcraft/launcher/dialog/renderer/InstanceCellRenderer.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * SK's Minecraft Launcher - * Copyright (C) 2010-2014 Albert Pham and contributors - * Please see LICENSE.txt for license information. - */ - -package com.skcraft.launcher.dialog.renderer; - -import com.skcraft.launcher.Instance; -import com.skcraft.launcher.Launcher; -import com.skcraft.launcher.swing.SwingHelper; - -import javax.swing.*; -import java.awt.*; - -public class InstanceCellRenderer extends DefaultListCellRenderer { - - private final Icon instanceIcon; - private final Icon customInstanceIcon; - private final Icon downloadIcon; - - public InstanceCellRenderer() { - instanceIcon = SwingHelper.createIcon(Launcher.class, "instance_icon.png", 16, 16); - customInstanceIcon = SwingHelper.createIcon(Launcher.class, "custom_instance_icon.png", 16, 16); - downloadIcon = SwingHelper.createIcon(Launcher.class, "download_icon.png", 14, 14); - } - - @Override - public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { - Instance instance = (Instance) value; - JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - // Add some padding to the cell - label.setBorder(BorderFactory.createCompoundBorder(label.getBorder(), BorderFactory.createEmptyBorder(2, 4, 2, 4))); - label.setIcon(getInstanceIcon(instance)); - return label; - } - - private Icon getInstanceIcon(Instance instance) { - if (!instance.isLocal()) { - return downloadIcon; - } else if (instance.getManifestURL() != null) { - return instanceIcon; - } else { - return customInstanceIcon; - } - } - -} diff --git a/launcher/src/main/java/com/skcraft/launcher/swing/InstanceTable.java b/launcher/src/main/java/com/skcraft/launcher/swing/InstanceTable.java new file mode 100644 index 0000000..63643ed --- /dev/null +++ b/launcher/src/main/java/com/skcraft/launcher/swing/InstanceTable.java @@ -0,0 +1,26 @@ +/* + * SK's Minecraft Launcher + * Copyright (C) 2010-2014 Albert Pham and contributors + * Please see LICENSE.txt for license information. + */ + +package com.skcraft.launcher.swing; + +import javax.swing.table.TableModel; + +public class InstanceTable extends DefaultTable { + + public InstanceTable() { + super(); + setTableHeader(null); + } + + @Override + public void setModel(TableModel dataModel) { + super.setModel(dataModel); + try { + getColumnModel().getColumn(0).setMaxWidth(24); + } catch (ArrayIndexOutOfBoundsException e) { + } + } +} diff --git a/launcher/src/main/java/com/skcraft/launcher/swing/InstanceTableModel.java b/launcher/src/main/java/com/skcraft/launcher/swing/InstanceTableModel.java new file mode 100644 index 0000000..583011d --- /dev/null +++ b/launcher/src/main/java/com/skcraft/launcher/swing/InstanceTableModel.java @@ -0,0 +1,115 @@ +/* + * SK's Minecraft Launcher + * Copyright (C) 2010-2014 Albert Pham and contributors + * Please see LICENSE.txt for license information. + */ + +package com.skcraft.launcher.swing; + +import com.skcraft.launcher.Instance; +import com.skcraft.launcher.InstanceList; +import com.skcraft.launcher.Launcher; +import com.skcraft.launcher.util.SharedLocale; + +import javax.swing.*; +import javax.swing.table.AbstractTableModel; + +public class InstanceTableModel extends AbstractTableModel { + + private final InstanceList instances; + private final Icon instanceIcon; + private final Icon customInstanceIcon; + private final Icon downloadIcon; + + public InstanceTableModel(InstanceList instances) { + this.instances = instances; + instanceIcon = SwingHelper.createIcon(Launcher.class, "instance_icon.png", 16, 16); + customInstanceIcon = SwingHelper.createIcon(Launcher.class, "custom_instance_icon.png", 16, 16); + downloadIcon = SwingHelper.createIcon(Launcher.class, "download_icon.png", 14, 14); + } + + public void update() { + instances.sort(); + fireTableDataChanged(); + } + + @Override + public String getColumnName(int columnIndex) { + switch (columnIndex) { + case 0: + return ""; + case 1: + return SharedLocale.tr("launcher.modpackColumn"); + default: + return null; + } + } + + @Override + public Class getColumnClass(int columnIndex) { + switch (columnIndex) { + case 0: + return ImageIcon.class; + case 1: + return String.class; + default: + return null; + } + } + + @Override + public void setValueAt(Object value, int rowIndex, int columnIndex) { + switch (columnIndex) { + case 0: + instances.get(rowIndex).setSelected((boolean) (Boolean) value); + break; + case 1: + default: + break; + } + } + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + switch (columnIndex) { + case 0: + return false; + case 1: + return false; + default: + return false; + } + } + + @Override + public int getRowCount() { + return instances.size(); + } + + @Override + public int getColumnCount() { + return 2; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + Instance instance; + switch (columnIndex) { + case 0: + instance = instances.get(rowIndex); + if (!instance.isLocal()) { + return downloadIcon; + } else if (instance.getManifestURL() != null) { + return instanceIcon; + } else { + return customInstanceIcon; + } + case 1: + instance = instances.get(rowIndex); + return instance.getTitle(); + default: + return null; + } + } + +}