diff --git a/megamek/src/megamek/client/ui/advancedsearch/EquipmentFilterToken.java b/megamek/src/megamek/client/ui/advancedsearch/EquipmentFilterToken.java index 267c5d54c34..b4b223bdbca 100644 --- a/megamek/src/megamek/client/ui/advancedsearch/EquipmentFilterToken.java +++ b/megamek/src/megamek/client/ui/advancedsearch/EquipmentFilterToken.java @@ -23,4 +23,6 @@ */ abstract class EquipmentFilterToken implements FilterToken { + int qty; + boolean atleast; } diff --git a/megamek/src/megamek/client/ui/advancedsearch/EquipmentTableModel.java b/megamek/src/megamek/client/ui/advancedsearch/EquipmentTableModel.java index b00bd295bc1..4e6ab4aca3f 100644 --- a/megamek/src/megamek/client/ui/advancedsearch/EquipmentTableModel.java +++ b/megamek/src/megamek/client/ui/advancedsearch/EquipmentTableModel.java @@ -19,11 +19,11 @@ package megamek.client.ui.advancedsearch; import megamek.common.EquipmentType; +import megamek.common.MiscType; import megamek.common.TechConstants; import javax.swing.table.AbstractTableModel; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; /** @@ -31,17 +31,15 @@ */ class EquipmentTableModel extends AbstractTableModel { - static final int COL_QTY = 0; - static final int COL_NAME = 1; - static final int COL_COST = 2; - static final int COL_IS_CLAN = 3; - static final int COL_LEVEL = 4; - static final int N_COL = 5; + static final int COL_NAME = 0; + static final int COL_COST = 1; + static final int COL_IS_CLAN = 2; + static final int COL_LEVEL = 3; + static final int N_COL = 4; static final int COL_INTERNAL_NAME = 5; private final TWAdvancedSearchPanel twAdvancedSearchPanel; - private int[] qty; - private final List equipment = new ArrayList<>(); + private final List equipment = new ArrayList<>(); EquipmentTableModel(TWAdvancedSearchPanel twAdvancedSearchPanel) { this.twAdvancedSearchPanel = twAdvancedSearchPanel; @@ -59,7 +57,6 @@ public int getColumnCount() { int getPreferredWidth(int col) { return switch (col) { - case COL_QTY -> 40; case COL_NAME -> 400; case COL_IS_CLAN -> 75; case COL_COST -> 175; @@ -71,7 +68,6 @@ int getPreferredWidth(int col) { @Override public String getColumnName(int column) { return switch (column) { - case COL_QTY -> "Qty"; case COL_NAME -> "Name"; case COL_IS_CLAN -> "IS/Clan"; case COL_COST -> "Cost"; @@ -85,20 +81,13 @@ public Class getColumnClass(int c) { return getValueAt(0, c).getClass(); } - @Override - public boolean isCellEditable(int row, int col) { - return col == COL_QTY; - } - - void setData(List eq) { + void setData(List eq) { equipment.clear(); equipment.addAll(eq); - qty = new int[eq.size()]; - Arrays.fill(qty, 1); fireTableDataChanged(); } - EquipmentType getEquipmentTypeAt(int row) { + MiscType getEquipmentTypeAt(int row) { return equipment.get(row); } @@ -109,7 +98,6 @@ public Object getValueAt(int row, int col) { } EquipmentType eq = equipment.get(row); return switch (col) { - case COL_QTY -> qty[row] + ""; case COL_NAME -> eq.getName(); case COL_IS_CLAN -> TechConstants.getTechName(eq.getTechLevel(twAdvancedSearchPanel.gameYear)); case COL_COST -> eq.getRawCost(); @@ -119,12 +107,4 @@ public Object getValueAt(int row, int col) { default -> "?"; }; } - - @Override - public void setValueAt(Object value, int row, int col) { - if (col == COL_QTY) { - qty[row] = Integer.parseInt((String) value); - fireTableCellUpdated(row, col); - } - } } diff --git a/megamek/src/megamek/client/ui/advancedsearch/EquipmentTypeFT.java b/megamek/src/megamek/client/ui/advancedsearch/EquipmentTypeFT.java index c7e4d8620c8..b77ec14d926 100644 --- a/megamek/src/megamek/client/ui/advancedsearch/EquipmentTypeFT.java +++ b/megamek/src/megamek/client/ui/advancedsearch/EquipmentTypeFT.java @@ -27,16 +27,20 @@ class EquipmentTypeFT extends EquipmentFilterToken { String internalName; String fullName; - int qty; EquipmentTypeFT(String in, String fn, int q) { + this(in, fn, q, true); + } + + EquipmentTypeFT(String in, String fn, int q, boolean atleast) { internalName = in; fullName = fn; qty = q; + this.atleast = atleast; } @Override public String toString() { - return qty + " " + fullName + ((qty != 1) ? "s" : ""); + return (atleast ? "" : "less than ") + qty + " " + fullName + ((qty != 1) ? "s" : ""); } } diff --git a/megamek/src/megamek/client/ui/advancedsearch/MekSearchFilter.java b/megamek/src/megamek/client/ui/advancedsearch/MekSearchFilter.java index 81bb1d85168..657fd8ef067 100644 --- a/megamek/src/megamek/client/ui/advancedsearch/MekSearchFilter.java +++ b/megamek/src/megamek/client/ui/advancedsearch/MekSearchFilter.java @@ -320,7 +320,7 @@ private ExpNode createFTFromTokensRecursively(Iterator toks, ExpNod if (currNode == null) { currNode = new ExpNode(); } - ExpNode newChild = new ExpNode(ft.internalName, ft.qty); + ExpNode newChild = new ExpNode(ft.internalName, ft.qty, ft.atleast); currNode.children.add(newChild); return createFTFromTokensRecursively(toks, currNode); @@ -331,7 +331,7 @@ private ExpNode createFTFromTokensRecursively(Iterator toks, ExpNod currNode = new ExpNode(); } - ExpNode newChild = new ExpNode(ft.weaponClass, ft.qty); + ExpNode newChild = new ExpNode(ft.weaponClass, ft.qty, ft.atleast); currNode.children.add(newChild); return createFTFromTokensRecursively(toks, currNode); } @@ -988,10 +988,10 @@ private boolean evaluate(List eq, List qty, ExpNode n) { // If the requested quantity is 0, then we match if and only if the total number // of matching equipment is also 0. // Otherwise, we match if the total equals or exceeds the requested amount. - if (n.qty == 0) { - return total == 0; - } else { + if (n.atleast) { return total >= n.qty; + } else { + return total < n.qty; } } else { @@ -1022,9 +1022,9 @@ private boolean evaluate(List eq, List qty, ExpNode n) { // means that the unit isn't a match for the filter, as it has a // weapon/equipment that is required to // NOT be there. - if (currEq.equals(n.name) && n.qty > 0 && currQty >= n.qty) { + if (currEq.equals(n.name) && n.atleast && (currQty >= n.qty)) { return true; - } else if (currEq.equals(n.name) && n.qty == 0) { + } else if (currEq.equals(n.name) && !n.atleast && (currQty >= n.qty)) { return false; } @@ -1035,7 +1035,7 @@ private boolean evaluate(List eq, List qty, ExpNode n) { // If the leaf quantity is 0, that means that the mek is a match. If the leaf // quantity is non-zero, that means the mek isn't // a match. - return n.qty == 0; + return !n.atleast; } } // Otherwise, recurse on all the children and either AND the results @@ -1091,6 +1091,7 @@ public static class ExpNode { public WeaponClass weaponClass; public int qty; public List children; + public boolean atleast; public ExpNode() { operation = BoolOp.NOP; @@ -1118,22 +1119,24 @@ public ExpNode(ExpNode e) { } } - public ExpNode(String n, int q) { + public ExpNode(String n, int q, boolean atleast) { parent = null; name = n; weaponClass = null; qty = q; operation = BoolOp.NOP; children = new LinkedList<>(); + this.atleast = atleast; } - public ExpNode(WeaponClass n, int q) { + public ExpNode(WeaponClass n, int q, boolean atleast) { parent = null; name = null; weaponClass = n; qty = q; operation = BoolOp.NOP; children = new LinkedList<>(); + this.atleast = atleast; } @Override diff --git a/megamek/src/megamek/client/ui/advancedsearch/MiscSearchTab.java b/megamek/src/megamek/client/ui/advancedsearch/MiscSearchTab.java index fa9c0284724..027ff8cdd00 100644 --- a/megamek/src/megamek/client/ui/advancedsearch/MiscSearchTab.java +++ b/megamek/src/megamek/client/ui/advancedsearch/MiscSearchTab.java @@ -199,7 +199,7 @@ private JPanel createBaseComboBoxes() { listTechLevel = new TriStateItemList(SimpleTechLevel.getAllSimpleTechLevelCodeName(), 5); listTechBase = new TriStateItemList(Entity.getTechBaseDescriptions(), 4); - List moveModes = Arrays.stream(EntityMovementMode.values()).map(EntityMovementMode::toString).toList(); + List moveModes = Arrays.stream(EntityMovementMode.values()).map(EntityMovementMode::toString).distinct().toList(); listMoveMode = new TriStateItemList(moveModes, 13); JPanel baseComboBoxesPanel = new JPanel(); diff --git a/megamek/src/megamek/client/ui/swing/table/MegaMekTable.java b/megamek/src/megamek/client/ui/advancedsearch/SearchableTable.java similarity index 67% rename from megamek/src/megamek/client/ui/swing/table/MegaMekTable.java rename to megamek/src/megamek/client/ui/advancedsearch/SearchableTable.java index 876eb9c10d6..f3a56148021 100644 --- a/megamek/src/megamek/client/ui/swing/table/MegaMekTable.java +++ b/megamek/src/megamek/client/ui/advancedsearch/SearchableTable.java @@ -1,4 +1,22 @@ -package megamek.client.ui.swing.table; +/* + * Copyright (c) 2024 - The MegaMek Team. All Rights Reserved. + * + * This file is part of MegaMek. + * + * MegaMek is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * MegaMek is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with MegaMek. If not, see . + */ +package megamek.client.ui.advancedsearch; import javax.swing.*; import javax.swing.table.TableColumnModel; @@ -7,13 +25,11 @@ import java.awt.event.MouseEvent; import java.util.Vector; -public class MegaMekTable extends JTable { - private static final long serialVersionUID = 1L; +class SearchableTable extends JTable { private static final int KEY_TIMEOUT = 1000; private long lastSearch; - StringBuffer searchBuffer; /** @@ -21,57 +37,57 @@ public class MegaMekTable extends JTable { */ protected int searchColumn; - public MegaMekTable() { + public SearchableTable() { super(); lastSearch = 0; searchColumn = 0; searchBuffer = new StringBuffer(); } - public MegaMekTable(int numRows, int numColumns) { + public SearchableTable(int numRows, int numColumns) { super(numRows, numColumns); lastSearch = 0; searchColumn = 0; searchBuffer = new StringBuffer(); } - public MegaMekTable(Object[][] rowData, Object[] columnNames) { + public SearchableTable(Object[][] rowData, Object[] columnNames) { super(rowData, columnNames); lastSearch = 0; searchColumn = 0; searchBuffer = new StringBuffer(); } - public MegaMekTable(TableModel dm) { + public SearchableTable(TableModel dm) { super(dm); lastSearch = 0; searchColumn = 0; searchBuffer = new StringBuffer(); } - public MegaMekTable(TableModel dm, int sc) { + public SearchableTable(TableModel dm, int sc) { super(dm); lastSearch = 0; searchColumn = sc; searchBuffer = new StringBuffer(); } - public MegaMekTable(TableModel dm, TableColumnModel cm) { + public SearchableTable(TableModel dm, TableColumnModel cm) { super(dm, cm); lastSearch = 0; searchColumn = 0; searchBuffer = new StringBuffer(); } - public MegaMekTable(TableModel dm, TableColumnModel cm, - ListSelectionModel sm) { + public SearchableTable(TableModel dm, TableColumnModel cm, + ListSelectionModel sm) { super(dm, cm, sm); lastSearch = 0; searchColumn = 0; searchBuffer = new StringBuffer(); } - public MegaMekTable(Vector> rowData, Vector columnNames) { + public SearchableTable(Vector> rowData, Vector columnNames) { super(rowData, columnNames); lastSearch = 0; searchColumn = 0; @@ -96,7 +112,9 @@ public String getToolTipText(MouseEvent e) { java.awt.Point p = e.getPoint(); int rowIndex = rowAtPoint(p); int colIndex = columnAtPoint(p); - tip = getValueAt(rowIndex, colIndex).toString(); + if (rowIndex >= 0) { + tip = getValueAt(rowIndex, colIndex).toString(); + } return tip; } diff --git a/megamek/src/megamek/client/ui/advancedsearch/WeaponClassFT.java b/megamek/src/megamek/client/ui/advancedsearch/WeaponClassFT.java index e9fd4c16bfb..14d0c988e1b 100644 --- a/megamek/src/megamek/client/ui/advancedsearch/WeaponClassFT.java +++ b/megamek/src/megamek/client/ui/advancedsearch/WeaponClassFT.java @@ -25,19 +25,19 @@ class WeaponClassFT extends EquipmentFilterToken { WeaponClass weaponClass; - int qty; WeaponClassFT(WeaponClass in_class, int in_qty) { + this(in_class, in_qty, true); + } + + WeaponClassFT(WeaponClass in_class, int in_qty, boolean atleast) { weaponClass = in_class; qty = in_qty; + this.atleast = atleast; } @Override public String toString() { - if (qty == 1) { - return qty + " " + weaponClass.toString(); - } else { - return qty + " " + weaponClass.toString() + "s"; - } + return (atleast ? "" : "less than ") + qty + " " + weaponClass.toString() + ((qty != 1) ? "s" : ""); } } diff --git a/megamek/src/megamek/client/ui/advancedsearch/WeaponSearchTab.java b/megamek/src/megamek/client/ui/advancedsearch/WeaponSearchTab.java index afbb3acaa1c..78c02053ec2 100644 --- a/megamek/src/megamek/client/ui/advancedsearch/WeaponSearchTab.java +++ b/megamek/src/megamek/client/ui/advancedsearch/WeaponSearchTab.java @@ -19,7 +19,9 @@ package megamek.client.ui.advancedsearch; import megamek.client.ui.Messages; -import megamek.client.ui.swing.table.MegaMekTable; +import megamek.client.ui.swing.util.FlatLafStyleBuilder; +import megamek.client.ui.swing.util.FontHandler; +import megamek.client.ui.swing.util.UIUtil; import megamek.common.*; import megamek.common.annotations.Nullable; @@ -27,7 +29,6 @@ import javax.swing.border.EmptyBorder; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; -import javax.swing.table.TableColumn; import javax.swing.table.TableRowSorter; import java.awt.*; import java.awt.event.FocusEvent; @@ -44,7 +45,11 @@ class WeaponSearchTab extends JPanel implements KeyListener, DocumentListener, F final JButton btnLeftParen = new JButton("("); final JButton btnRightParen = new JButton(")"); + final JToggleButton btnLessThan = new JToggleButton("<"); + final JToggleButton btnAtLeast = new JToggleButton("\u2265"); final JButton btnAdd = new JButton(Messages.getString("MekSelectorDialog.Search.add")); + final JButton btnAddMultiOr = new JButton("Add [OR]"); + final JButton btnAddMultiAnd = new JButton("Add [AND]"); final JButton btnAnd = new JButton(Messages.getString("MekSelectorDialog.Search.and")); final JButton btnOr = new JButton(Messages.getString("MekSelectorDialog.Search.or")); final JButton btnClear = new JButton(Messages.getString("MekSelectorDialog.Reset")); @@ -55,27 +60,25 @@ class WeaponSearchTab extends JPanel implements KeyListener, DocumentListener, F JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); - final JLabel lblTableFilters = new JLabel(Messages.getString("MekSelectorDialog.Search.TableFilters")); final JLabel lblUnitType = new JLabel(Messages.getString("MekSelectorDialog.Search.UnitType")); final JLabel lblTechClass = new JLabel(Messages.getString("MekSelectorDialog.Search.TechClass")); final JLabel lblTechLevelBase = new JLabel(Messages.getString("MekSelectorDialog.Search.TechLevel")); - final JComboBox cboUnitType = new JComboBox<>(); - final JComboBox cboTechClass = new JComboBox<>(); - final JComboBox cboTechLevel = new JComboBox<>(); + final JList unitTypeSelector = new JList<>(); + final JList techClassSelector = new JList<>(); + final JList techLevelSelector = new JList<>(); final JLabel tableFilterTextLabel = new JLabel(Messages.getString("MekSelectorDialog.Search.TableFilter")); - final JTextField tableFilterText = new JTextField(20); + final JTextField tableFilterText = new JTextField(10); final JLabel lblWeapons = new JLabel(Messages.getString("MekSelectorDialog.Search.Weapons")); final JScrollPane scrTableWeapons = new JScrollPane(); - final MegaMekTable tblWeapons; + final SearchableTable tblWeapons; final WeaponsTableModel weaponsModel; final TableRowSorter weaponsSorter; final JLabel lblEquipment = new JLabel(Messages.getString("MekSelectorDialog.Search.Equipment")); final JScrollPane scrTableEquipment = new JScrollPane(); - final MegaMekTable tblEquipment; + final SearchableTable tblEquipment; final EquipmentTableModel equipmentModel; final TableRowSorter equipmentSorter; - final JComboBox cboQty = new JComboBox<>(); final JLabel lblWeaponClass = new JLabel(Messages.getString("MekSelectorDialog.Search.WeaponClass")); final JSpinner weaponClassCount; @@ -88,84 +91,81 @@ class WeaponSearchTab extends JPanel implements KeyListener, DocumentListener, F WeaponSearchTab(TWAdvancedSearchPanel parentPanel) { this.parentPanel = parentPanel; + ButtonGroup atleastGroup = new ButtonGroup(); + atleastGroup.add(btnAtLeast); + atleastGroup.add(btnLessThan); + var btnStyle = new FlatLafStyleBuilder(FontHandler.notoFont()); + btnStyle.apply(btnAtLeast); + btnStyle.apply(btnLessThan); + btnAnd.addActionListener(e -> addFilterToken(new AndFilterToken())); - btnAdd.addActionListener(e -> addButtonPressed()); + btnAdd.addActionListener(e -> addFilter(true)); + btnAddMultiAnd.addActionListener(e -> addFilter(true)); + btnAddMultiOr.addActionListener(e -> addFilter(false)); btnLeftParen.addActionListener(e -> addFilterToken(new LeftParensFilterToken())); btnRightParen.addActionListener(e -> addFilterToken(new RightParensFilterToken())); btnOr.addActionListener(e -> addFilterToken(new OrFilterToken())); btnClear.addActionListener(e -> clear()); btnBack.addActionListener(e -> backOperation()); + btnAtLeast.setSelected(true); adaptTokenButtons(); - for (int i = 1; i <= 20; i++) { - cboQty.addItem(Integer.toString(i)); - } - cboQty.setSelectedIndex(0); - - // Setup table filter combo boxes - DefaultComboBoxModel unitTypeModel = new DefaultComboBoxModel<>(); - unitTypeModel.addElement(Messages.getString("MekSelectorDialog.All")); - unitTypeModel.addElement(UnitType.getTypeDisplayableName(UnitType.MEK)); - unitTypeModel.addElement(UnitType.getTypeDisplayableName(UnitType.TANK)); - unitTypeModel.addElement(UnitType.getTypeDisplayableName(UnitType.BATTLE_ARMOR)); - unitTypeModel.addElement(UnitType.getTypeDisplayableName(UnitType.INFANTRY)); - unitTypeModel.addElement(UnitType.getTypeDisplayableName(UnitType.PROTOMEK)); - unitTypeModel.addElement(UnitType.getTypeDisplayableName(UnitType.AERO)); - unitTypeModel.setSelectedItem(Messages.getString("MekSelectorDialog.All")); - - cboUnitType.setModel(unitTypeModel); - cboUnitType.addActionListener(e -> filterTables()); - - DefaultComboBoxModel techLevelModel = new DefaultComboBoxModel<>(); - - for (int i = 0; i < TechConstants.SIZE; i++) { - techLevelModel.addElement(TechConstants.getLevelDisplayableName(i)); - } - - techLevelModel.setSelectedItem(TechConstants.getLevelDisplayableName(TechConstants.SIZE - 1)); - cboTechLevel.setModel(techLevelModel); - cboTechLevel.addActionListener(e -> filterTables()); - - DefaultComboBoxModel techClassModel = new DefaultComboBoxModel<>(); - techClassModel.addElement("All"); - techClassModel.addElement("Inner Sphere"); - techClassModel.addElement("Clan"); - techClassModel.addElement("IS/Clan"); - techClassModel.addElement("(Unknown Technology Base)"); - techClassModel.setSelectedItem("All"); - cboTechClass.setModel(techClassModel); - cboTechClass.addActionListener(e -> filterTables()); + unitTypeSelector.setLayoutOrientation(JList.HORIZONTAL_WRAP); + unitTypeSelector.setVisibleRowCount(1); + var model = new DefaultListModel(); + model.addElement("All"); + model.addElement(UnitType.getTypeDisplayableName(UnitType.MEK)); + model.addElement(UnitType.getTypeDisplayableName(UnitType.TANK)); + model.addElement(UnitType.getTypeDisplayableName(UnitType.BATTLE_ARMOR)); + model.addElement(UnitType.getTypeDisplayableName(UnitType.INFANTRY)); + model.addElement(UnitType.getTypeDisplayableName(UnitType.PROTOMEK)); + model.addElement(UnitType.getTypeDisplayableName(UnitType.AERO)); + unitTypeSelector.setModel(model); + unitTypeSelector.setSelectedIndices(new int[]{0, 1, 2, 3, 4, 5}); + unitTypeSelector.addListSelectionListener(e -> filterTables()); + unitTypeSelector.setCellRenderer(new ChoiceRenderer()); + + techLevelSelector.setLayoutOrientation(JList.HORIZONTAL_WRAP); + techLevelSelector.setVisibleRowCount(1); + techLevelSelector.setListData(TechConstants.T_SIMPLE_NAMES); + techLevelSelector.setSelectedIndices(new int[]{0, 1, 2, 3}); // all except unofficial as the default selection + techLevelSelector.addListSelectionListener(e -> filterTables()); + techLevelSelector.setCellRenderer(new ChoiceRenderer()); + + techClassSelector.setLayoutOrientation(JList.HORIZONTAL_WRAP); + techClassSelector.setVisibleRowCount(1); + techClassSelector.setListData(new String[]{"Inner Sphere", "Clan"}); + techClassSelector.setSelectedIndices(new int[]{0, 1}); // all except unofficial as the default selection + techClassSelector.addListSelectionListener(e -> filterTables()); + techClassSelector.setCellRenderer(new ChoiceRenderer()); // Set up Weapon Class chooser weaponClassCount = new JSpinner(new SpinnerNumberModel(1, 1, 20, 1)); - weaponClassCount.addChangeListener(e->spinnerChange()); weaponClassChooser = new JComboBox<>(WeaponClass.values()); weaponClassChooser.addFocusListener(this); // Setup Weapons Table weaponsModel = new WeaponsTableModel(parentPanel); - tblWeapons = new MegaMekTable(weaponsModel, WeaponsTableModel.COL_NAME) { + tblWeapons = new SearchableTable(weaponsModel, WeaponsTableModel.COL_NAME) { @Override public Dimension getPreferredScrollableViewportSize() { - Dimension standardSize = super.getPreferredScrollableViewportSize(); - return new Dimension(standardSize.width, getRowHeight() * 6); + return new Dimension(UIUtil.scaleForGUI(600), getRowHeight() * 6); } }; - TableColumn wpsCol = tblWeapons.getColumnModel().getColumn(WeaponsTableModel.COL_QTY); - wpsCol.setCellEditor(new DefaultCellEditor(cboQty)); - tblWeapons.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + tblWeapons.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); weaponsSorter = new TableRowSorter<>(weaponsModel); tblWeapons.setRowSorter(weaponsSorter); tblWeapons.addKeyListener(this); tblWeapons.addFocusListener(this); + tblWeapons.getSelectionModel().addListSelectionListener(e -> adaptTokenButtons()); var tableDataRenderer = new EquipmentDataRenderer(); - for (int column : List.of(0, 2, 3, 4, 5, 6)) { + for (int column : List.of(1, 2, 3, 4, 5)) { tblWeapons.getColumnModel().getColumn(column).setCellRenderer(tableDataRenderer); } var techBaseRenderer = new TechBaseRenderer(); - tblWeapons.getColumnModel().getColumn(7).setCellRenderer(techBaseRenderer); + tblWeapons.getColumnModel().getColumn(6).setCellRenderer(techBaseRenderer); for (int i = 0; i < weaponsModel.getColumnCount(); i++) { tblWeapons.getColumnModel().getColumn(i).setPreferredWidth(weaponsModel.getPreferredWidth(i)); @@ -175,29 +175,27 @@ public Dimension getPreferredScrollableViewportSize() { // Setup Equipment Table equipmentModel = new EquipmentTableModel(parentPanel); - tblEquipment = new MegaMekTable(equipmentModel, EquipmentTableModel.COL_NAME) { + tblEquipment = new SearchableTable(equipmentModel, EquipmentTableModel.COL_NAME) { @Override public Dimension getPreferredScrollableViewportSize() { Dimension standardSize = super.getPreferredScrollableViewportSize(); return new Dimension(standardSize.width, getRowHeight() * 6); } }; - TableColumn eqCol = tblEquipment.getColumnModel().getColumn(EquipmentTableModel.COL_QTY); - eqCol.setCellEditor(new DefaultCellEditor(cboQty)); - tblEquipment.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + tblEquipment.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); equipmentSorter = new TableRowSorter<>(equipmentModel); tblEquipment.setRowSorter(equipmentSorter); tblEquipment.addKeyListener(this); tblEquipment.addFocusListener(this); + tblEquipment.getSelectionModel().addListSelectionListener(e -> adaptTokenButtons()); for (int i = 0; i < equipmentModel.getColumnCount(); i++) { tblEquipment.getColumnModel().getColumn(i).setPreferredWidth(equipmentModel.getPreferredWidth(i)); } - tblEquipment.getColumnModel().getColumn(0).setCellRenderer(tableDataRenderer); - var costRenderer = new EquipmentCostRenderer(); - tblEquipment.getColumnModel().getColumn(2).setCellRenderer(costRenderer); - tblEquipment.getColumnModel().getColumn(3).setCellRenderer(techBaseRenderer); + var costRenderer = new EquipmentCostRenderer(); + tblEquipment.getColumnModel().getColumn(1).setCellRenderer(costRenderer); + tblEquipment.getColumnModel().getColumn(2).setCellRenderer(techBaseRenderer); scrTableEquipment.setViewportView(tblEquipment); @@ -224,44 +222,44 @@ public Dimension getPreferredScrollableViewportSize() { tableFilterText.getDocument().addDocumentListener(this); - JPanel upperPanel = new JPanel(); - upperPanel.setLayout(new GridBagLayout()); + JPanel upperPanel = new JPanel(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); - gbc.weighty = 0; - gbc.anchor = GridBagConstraints.NORTHWEST; - gbc.fill = GridBagConstraints.NONE; - gbc.insets = new Insets(0, 0, 0, 0); gbc.gridy = 0; - upperPanel.add(lblTableFilters, gbc); - gbc.gridy++; - gbc.gridwidth = 4; - gbc.anchor = GridBagConstraints.CENTER; - JPanel tableTechFilterPanel = new JPanel(); - tableTechFilterPanel.add(lblUnitType); - tableTechFilterPanel.add(cboUnitType); - tableTechFilterPanel.add(lblTechClass); - tableTechFilterPanel.add(cboTechClass); - tableTechFilterPanel.add(lblTechLevelBase); - tableTechFilterPanel.add(cboTechLevel); - upperPanel.add(tableTechFilterPanel, gbc); + gbc.anchor = GridBagConstraints.WEST; + gbc.gridwidth = 1; + upperPanel.add(lblTechClass, gbc); + gbc.gridwidth = GridBagConstraints.REMAINDER; + upperPanel.add(techClassSelector, gbc); gbc.gridy++; - JPanel tableTextFilterPanel = new JPanel(); - tableTextFilterPanel.add(tableFilterTextLabel); - tableTextFilterPanel.add(tableFilterText); - upperPanel.add(tableTextFilterPanel, gbc); + gbc.gridwidth = 1; + upperPanel.add(lblUnitType, gbc); + gbc.gridwidth = GridBagConstraints.REMAINDER; + upperPanel.add(unitTypeSelector, gbc); + gbc.gridy++; gbc.gridwidth = 1; - gbc.insets = new Insets(0, 0, 0, 0); - gbc.fill = GridBagConstraints.NONE; + upperPanel.add(lblTechLevelBase, gbc); + gbc.gridwidth = GridBagConstraints.REMAINDER; + upperPanel.add(techLevelSelector, gbc); + + JPanel filterPanel = new JPanel(); + filterPanel.add(tableFilterTextLabel); + filterPanel.add(tableFilterText); + gbc.gridy++; + gbc.gridwidth = GridBagConstraints.REMAINDER; + upperPanel.add(filterPanel, gbc); + + gbc.gridheight = 1; + gbc.gridx = GridBagConstraints.RELATIVE; gbc.gridy++; gbc.anchor = GridBagConstraints.WEST; upperPanel.add(lblWeapons, gbc); gbc.fill = GridBagConstraints.HORIZONTAL; gbc.anchor = GridBagConstraints.CENTER; - gbc.gridwidth = 5; + gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.gridy++; upperPanel.add(scrTableWeapons, gbc); @@ -276,7 +274,7 @@ public Dimension getPreferredScrollableViewportSize() { gbc.fill = GridBagConstraints.HORIZONTAL; gbc.anchor = GridBagConstraints.CENTER; - gbc.gridwidth = 5; + gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.gridy++; upperPanel.add(scrTableEquipment, gbc); @@ -289,11 +287,17 @@ public Dimension getPreferredScrollableViewportSize() { gbc.insets = new Insets(0, 0, 0, 20); upperPanel.add(lblWeaponClass, gbc); gbc.gridy++; - upperPanel.add(weaponClassCount, gbc); - upperPanel.add(weaponClassChooser, gbc); + JPanel weaponClassPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); + weaponClassPanel.add(weaponClassChooser); + upperPanel.add(weaponClassPanel, gbc); JPanel btnPanel = new JPanel(); + btnPanel.add(btnAtLeast); + btnPanel.add(btnLessThan); + btnPanel.add(weaponClassCount); btnPanel.add(btnAdd); + btnPanel.add(btnAddMultiAnd); + btnPanel.add(btnAddMultiOr); btnPanel.add(btnLeftParen); btnPanel.add(btnRightParen); btnPanel.add(btnAnd); @@ -320,9 +324,9 @@ public Dimension getPreferredScrollableViewportSize() { void filterTables() { RowFilter weaponFilter; - final int techLevel = cboTechLevel.getSelectedIndex(); - final String techClass = (String) cboTechClass.getSelectedItem(); - final int unitType = cboUnitType.getSelectedIndex() - 1; + final int[] techLevels = techLevelSelector.getSelectedIndices(); + final int[] techClass = techClassSelector.getSelectedIndices(); + final int[] unitTypes = unitTypeSelector.getSelectedIndices(); // If current expression doesn't parse, don't update. try { weaponFilter = new RowFilter<>() { @@ -330,13 +334,12 @@ void filterTables() { public boolean include(Entry entry) { WeaponsTableModel weapModel = entry.getModel(); WeaponType wp = weapModel.getWeaponTypeAt(entry.getIdentifier()); - String currTechClass = TechConstants.getTechName(wp.getTechLevel(parentPanel.gameYear)); - - boolean techLvlMatch = matchTechLvl(techLevel, wp.getTechLevel(parentPanel.gameYear)); - boolean techClassMatch = matchTechClass(techClass, currTechClass); - boolean unitTypeMatch = matchUnitType(unitType, wp); + String weaponTechClass = TechConstants.getTechName(wp.getTechLevel(parentPanel.gameYear)); + boolean techLvlMatch = matchTechLvl(techLevels, wp.getTechLevel(parentPanel.gameYear)); + boolean techClassMatch = matchTechClass(techClass, weaponTechClass); + boolean unitTypeMatch = matchUnitTypeToWeapon(unitTypes, wp); boolean textFilterMatch = (tableFilterText.getText() == null) || (tableFilterText.getText().length() < 2) - || matchWeaponTextFilter(entry, WeaponsTableModel.COL_NAME); + || matchWeaponTextFilter(entry); return techLvlMatch && techClassMatch && unitTypeMatch && textFilterMatch; } }; @@ -351,13 +354,13 @@ public boolean include(Entry ent @Override public boolean include(Entry entry) { EquipmentTableModel eqModel = entry.getModel(); - EquipmentType eq = eqModel.getEquipmentTypeAt(entry.getIdentifier()); + MiscType eq = eqModel.getEquipmentTypeAt(entry.getIdentifier()); String currTechClass = TechConstants.getTechName(eq.getTechLevel(parentPanel.gameYear)); - boolean techLvlMatch = matchTechLvl(techLevel, eq.getTechLevel(parentPanel.gameYear)); + boolean techLvlMatch = matchTechLvl(techLevels, eq.getTechLevel(parentPanel.gameYear)); boolean techClassMatch = matchTechClass(techClass, currTechClass); - boolean unitTypeMatch = matchUnitType(unitType, eq); + boolean unitTypeMatch = matchUnitTypeToMisc(unitTypes, eq); boolean textFilterMatch = (tableFilterText.getText() == null) || (tableFilterText.getText().length() < 2) - || matchEquipmentTextFilter(entry, EquipmentTableModel.COL_NAME); + || matchEquipmentTextFilter(entry); return techLvlMatch && techClassMatch && unitTypeMatch && textFilterMatch; } }; @@ -376,26 +379,20 @@ void clear() { } /** - * Creates collections for all the possible WeaponTypes and - * EquipmentTypes. These are used to populate the weapons - * and equipment tables. + * Creates collections for all the possible WeaponTypes and MiscTypes. These are used to populate the weapons and equipment tables. */ private void populateWeaponsAndEquipmentChoices() { List weapons = new ArrayList<>(); - List equipment = new ArrayList<>(); + List equipment = new ArrayList<>(); - for (Enumeration e = EquipmentType.getAllTypes(); e.hasMoreElements();) { - EquipmentType et = e.nextElement(); + for (EquipmentType et : EquipmentType.allTypes()) { if (et instanceof WeaponType) { weapons.add((WeaponType) et); - // Check for C3+Tag and C3 Master Booster - if (et.hasFlag(WeaponType.F_C3M) || et.hasFlag(WeaponType.F_C3MBS)) { - equipment.add(et); - } } else if (et instanceof MiscType) { - equipment.add(et); + equipment.add((MiscType) et); } } + weaponsModel.setData(weapons); equipmentModel.setData(equipment); } @@ -423,57 +420,48 @@ public void keyTyped(KeyEvent evt) { } } - private boolean matchTechClass(String t1, String t2) { - if (t1.equals("All")) { + private boolean matchTechClass(int[] selectedClasses, String t2) { + if (t2.equals("IS/Clan") || (selectedClasses.length != 1)) { return true; - } else if (t1.equals("IS/Clan")) { - return t2.equals("Inner Sphere") || t2.equals("Clan") || t1.equals(t2); } else { - return t1.equals(t2); + if (selectedClasses[0] == 0) { + return t2.equals("Inner Sphere"); + } else { + return t2.equals("Clan"); + } } } - private boolean matchUnitType(int unitTypeFilter, EquipmentType eq) { - // All is selected - if (unitTypeFilter < 0) { + private boolean matchUnitTypeToWeapon(int[] selectedUnitTypes, EquipmentType eq) { + // All or nothing is selected + if (selectedUnitTypes.length == 0 || selectedUnitTypes.length >= 5) { return true; + } else { + List selection = Arrays.stream(selectedUnitTypes).boxed().toList(); + // 5 is the index, not the unit type constant! + return (selection.contains(5) && eq.hasFlag(WeaponType.F_AERO_WEAPON)) + || (selection.contains(UnitType.BATTLE_ARMOR) && eq.hasFlag(WeaponType.F_BA_WEAPON)) + || (selection.contains(UnitType.INFANTRY) && eq.hasFlag(WeaponType.F_INFANTRY)) + || (selection.contains(UnitType.MEK) && eq.hasFlag(WeaponType.F_MEK_WEAPON)) + || (selection.contains(UnitType.TANK) && eq.hasFlag(WeaponType.F_TANK_WEAPON)) + || (selection.contains(UnitType.PROTOMEK) && eq.hasFlag(WeaponType.F_PROTO_WEAPON)); } + } - switch (unitTypeFilter) { - case 5: - if (eq.hasFlag(WeaponType.F_AERO_WEAPON) || eq.hasFlag(MiscType.F_FIGHTER_EQUIPMENT)) { - return true; - } - break; - case UnitType.BATTLE_ARMOR: - if (eq.hasFlag(WeaponType.F_BA_WEAPON) || eq.hasFlag(MiscType.F_BA_EQUIPMENT)) { - return true; - } - break; - case UnitType.INFANTRY: - if (eq.hasFlag(WeaponType.F_INFANTRY)) { - return true; - } - break; - case UnitType.MEK: - if (eq.hasFlag(WeaponType.F_MEK_WEAPON) || eq.hasFlag(MiscType.F_MEK_EQUIPMENT)) { - return true; - } - break; - case UnitType.TANK: - if (eq.hasFlag(WeaponType.F_TANK_WEAPON) || eq.hasFlag(MiscType.F_TANK_EQUIPMENT)) { - return true; - } - break; - case UnitType.PROTOMEK: - if (eq.hasFlag(WeaponType.F_PROTO_WEAPON) || eq.hasFlag(MiscType.F_PROTOMEK_EQUIPMENT)) { - return true; - } - break; - default: - return false; + private boolean matchUnitTypeToMisc(int[] selectedUnitTypes, MiscType eq) { + // All or nothing is selected + if (selectedUnitTypes.length == 0 || selectedUnitTypes.length >= 5) { + return true; + } else { + List selection = Arrays.stream(selectedUnitTypes).boxed().toList(); + // 5 is the index, not the unit type constant! + return (selection.contains(5) && eq.hasFlag(MiscType.F_FIGHTER_EQUIPMENT)) + || (selection.contains(UnitType.BATTLE_ARMOR) && eq.hasFlag(MiscType.F_BA_EQUIPMENT)) + || (selection.contains(UnitType.INFANTRY) && eq.hasFlag(MiscType.F_INF_EQUIPMENT)) + || (selection.contains(UnitType.MEK) && eq.hasFlag(MiscType.F_MEK_EQUIPMENT)) + || (selection.contains(UnitType.TANK) && eq.hasFlag(MiscType.F_TANK_EQUIPMENT)) + || (selection.contains(UnitType.PROTOMEK) && eq.hasFlag(MiscType.F_PROTOMEK_EQUIPMENT)); } - return false; } // Build the string representation of the new expression @@ -485,46 +473,61 @@ String filterExpressionString() { return filterExp.toString(); } - private boolean matchTechLvl(int t1, int t2) { - return ((t1 == TechConstants.T_ALL) || (t1 == t2) - || ((t1 == TechConstants.T_IS_TW_ALL) && (t2 <= TechConstants.T_IS_TW_NON_BOX))) - - || ((t1 == TechConstants.T_TW_ALL) && (t2 <= TechConstants.T_CLAN_TW)) + private boolean matchTechLvl(int[] selectedTechLevels, int equipmentTechLevel) { + int simpleEquipmentLevel = TechConstants.convertFromNormalToSimple(equipmentTechLevel); + return Arrays.stream(selectedTechLevels).anyMatch(selectedLevel -> selectedLevel == simpleEquipmentLevel); + } - || ((t1 == TechConstants.T_ALL_IS) && ((t2 <= TechConstants.T_IS_TW_NON_BOX) - || (t2 == TechConstants.T_IS_ADVANCED) - || (t2 == TechConstants.T_IS_EXPERIMENTAL) - || (t2 == TechConstants.T_IS_UNOFFICIAL))) + private void addEquipmentFilter(int row, int qty, boolean atleast) { + String internalName = (String) tblEquipment.getModel().getValueAt( + tblEquipment.convertRowIndexToModel(row), + EquipmentTableModel.COL_INTERNAL_NAME); + String fullName = (String) tblEquipment.getValueAt(row, EquipmentTableModel.COL_NAME); + filterTokens.add(new EquipmentTypeFT(internalName, fullName, qty, atleast)); + } - || ((t1 == TechConstants.T_ALL_CLAN) - && ((t2 == TechConstants.T_CLAN_TW) - || (t2 == TechConstants.T_CLAN_ADVANCED) - || (t2 == TechConstants.T_CLAN_EXPERIMENTAL) - || (t2 == TechConstants.T_CLAN_UNOFFICIAL))); + private void addWeaponFilter(int row, int qty, boolean atleast) { + String internalName = (String) tblWeapons.getModel().getValueAt( + tblWeapons.convertRowIndexToModel(row), + WeaponsTableModel.COL_INTERNAL_NAME); + String fullName = (String) tblWeapons.getValueAt(row, WeaponsTableModel.COL_NAME); + filterTokens.add(new EquipmentTypeFT(internalName, fullName, qty, atleast)); } - private void addButtonPressed() { - if ((focusedSelector == tblEquipment) && (tblEquipment.getSelectedRow() != -1)) { - int row = tblEquipment.getSelectedRow(); - String internalName = (String) tblEquipment.getModel().getValueAt( - tblEquipment.convertRowIndexToModel(row), - EquipmentTableModel.COL_INTERNAL_NAME); - String fullName = (String) tblEquipment.getValueAt(row, EquipmentTableModel.COL_NAME); - int qty = Integer.parseInt((String) tblEquipment.getValueAt(row, EquipmentTableModel.COL_QTY)); - filterTokens.add(new EquipmentTypeFT(internalName, fullName, qty)); - - } else if ((focusedSelector == tblWeapons) && (tblWeapons.getSelectedRow() != -1)) { - int row = tblWeapons.getSelectedRow(); - String internalName = (String) tblWeapons.getModel().getValueAt( - tblWeapons.convertRowIndexToModel(row), - WeaponsTableModel.COL_INTERNAL_NAME); - String fullName = (String) tblWeapons.getValueAt(row, WeaponsTableModel.COL_NAME); - int qty = Integer.parseInt((String) tblWeapons.getValueAt(row, WeaponsTableModel.COL_QTY)); - filterTokens.add(new EquipmentTypeFT(internalName, fullName, qty)); + private void addFilter(boolean and) { + boolean atleast = btnAtLeast.isSelected(); + int qty = (int) weaponClassCount.getValue(); + if (focusedSelector == tblEquipment) { + int[] rows = tblEquipment.getSelectedRows(); + if (rows.length == 1) { + addEquipmentFilter(rows[0], qty, atleast); + } else if (rows.length > 1) { + addFilterToken(new LeftParensFilterToken()); + for (int row : rows) { + if (row != rows[0]) { + addFilterToken(and ? new AndFilterToken() : new OrFilterToken()); + } + addEquipmentFilter(row, qty, atleast); + } + addFilterToken(new RightParensFilterToken()); + } + } else if (focusedSelector == tblWeapons) { + int[] rows = tblWeapons.getSelectedRows(); + if (rows.length == 1) { + addWeaponFilter(rows[0], qty, atleast); + } else if (rows.length > 1) { + addFilterToken(new LeftParensFilterToken()); + for (int row : rows) { + if (row != rows[0]) { + addFilterToken(and ? new AndFilterToken() : new OrFilterToken()); + } + addWeaponFilter(row, qty, atleast); + } + addFilterToken(new RightParensFilterToken()); + } } else if ((focusedSelector == weaponClassChooser) && (weaponClassChooser.getSelectedItem() != null)) { - int qty = (int) weaponClassCount.getValue(); - filterTokens.add(new WeaponClassFT((WeaponClass) weaponClassChooser.getSelectedItem(), qty)); + filterTokens.add(new WeaponClassFT((WeaponClass) weaponClassChooser.getSelectedItem(), qty, atleast)); } else { // if something else is focused, do nothing @@ -534,13 +537,13 @@ private void addButtonPressed() { adaptTokenButtons(); } - private boolean matchWeaponTextFilter(RowFilter.Entry entry, int column) { - String wp = entry.getModel().getValueAt(entry.getIdentifier(), column).toString(); + private boolean matchWeaponTextFilter(RowFilter.Entry entry) { + String wp = entry.getModel().getValueAt(entry.getIdentifier(), WeaponsTableModel.COL_NAME).toString(); return matchTextFilter(wp); } - private boolean matchEquipmentTextFilter(RowFilter.Entry entry, int column) { - String wp = entry.getModel().getValueAt(entry.getIdentifier(), column).toString(); + private boolean matchEquipmentTextFilter(RowFilter.Entry entry) { + String wp = entry.getModel().getValueAt(entry.getIdentifier(), EquipmentTableModel.COL_NAME).toString(); return matchTextFilter(wp); } @@ -576,10 +579,6 @@ public void focusGained(FocusEvent e) { @Override public void focusLost(FocusEvent e) { } - private void spinnerChange() { - focusWeaponClasschooser(); - } - private void focusWeaponClasschooser() { focusedSelector = weaponClassChooser; tblWeapons.clearSelection(); @@ -601,7 +600,9 @@ void adaptTokenButtons() { boolean canAddEquipment = filterTokens.isEmpty() || (lastToken() instanceof OperatorFT) || (lastToken() instanceof LeftParensFilterToken); - btnAdd.setEnabled(hasFocusedSelector() && canAddEquipment); + btnAdd.setEnabled(hasFocusedSelector() && canAddEquipment && !isMultiSelection()); + btnAddMultiOr.setEnabled(isMultiSelection() && canAddEquipment); + btnAddMultiAnd.setEnabled(isMultiSelection() && canAddEquipment); btnLeftParen.setEnabled(canAddEquipment); boolean canAddOperator = (lastToken() instanceof EquipmentFilterToken) || (lastToken() instanceof RightParensFilterToken); @@ -610,6 +611,11 @@ void adaptTokenButtons() { btnRightParen.setEnabled(canAddOperator); } + private boolean isMultiSelection() { + return ((focusedSelector == tblEquipment) && (tblEquipment != null) && (tblEquipment.getSelectedRows().length > 1)) + || ((focusedSelector == tblWeapons) && (tblWeapons != null) && (tblWeapons.getSelectedRows().length > 1)); + } + private void addFilterToken(FilterToken token) { filterTokens.add(token); txtWEEqExp.setText(filterExpressionString()); @@ -623,4 +629,21 @@ private void backOperation() { adaptTokenButtons(); } } + + private static class ChoiceRenderer extends DefaultListCellRenderer { + + public ChoiceRenderer() { + paddingPanel.add(this); + paddingPanel.setBorder(new EmptyBorder(0, 2, 0, 2)); + } + + JPanel paddingPanel = new JPanel(new GridLayout(1, 1)); + + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, false); + return paddingPanel; + } + } } diff --git a/megamek/src/megamek/client/ui/advancedsearch/WeaponsTableModel.java b/megamek/src/megamek/client/ui/advancedsearch/WeaponsTableModel.java index 841a996f723..9c9d989b018 100644 --- a/megamek/src/megamek/client/ui/advancedsearch/WeaponsTableModel.java +++ b/megamek/src/megamek/client/ui/advancedsearch/WeaponsTableModel.java @@ -23,7 +23,6 @@ import javax.swing.table.AbstractTableModel; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; /** @@ -31,20 +30,18 @@ */ class WeaponsTableModel extends AbstractTableModel { - static final int COL_QTY = 0; - static final int COL_NAME = 1; - static final int COL_DMG = 2; - static final int COL_HEAT = 3; - static final int COL_SHORT = 4; - static final int COL_MED = 5; - static final int COL_LONG = 6; - static final int COL_IS_CLAN = 7; - static final int COL_LEVEL = 8; - static final int N_COL = 9; + static final int COL_NAME = 0; + static final int COL_DMG = 1; + static final int COL_HEAT = 2; + static final int COL_SHORT = 3; + static final int COL_MED = 4; + static final int COL_LONG = 5; + static final int COL_IS_CLAN = 6; + static final int COL_LEVEL = 7; + static final int N_COL = 8; static final int COL_INTERNAL_NAME = 9; private final TWAdvancedSearchPanel twAdvancedSearchPanel; - private int[] qty; private final List weapons = new ArrayList<>(); WeaponsTableModel(TWAdvancedSearchPanel twAdvancedSearchPanel) { @@ -63,7 +60,6 @@ public int getColumnCount() { int getPreferredWidth(int col) { return switch (col) { - case COL_QTY -> 40; case COL_NAME -> 310; case COL_IS_CLAN -> 75; case COL_DMG, COL_HEAT, COL_SHORT, COL_MED, COL_LONG -> 50; @@ -75,7 +71,6 @@ int getPreferredWidth(int col) { @Override public String getColumnName(int column) { return switch (column) { - case COL_QTY -> "Qty"; case COL_NAME -> "Weapon Name"; case COL_IS_CLAN -> "IS/Clan"; case COL_DMG -> "DMG"; @@ -93,16 +88,9 @@ public Class getColumnClass(int c) { return getValueAt(0, c).getClass(); } - @Override - public boolean isCellEditable(int row, int col) { - return col == COL_QTY; - } - void setData(List wps) { weapons.clear(); weapons.addAll(wps); - qty = new int[wps.size()]; - Arrays.fill(qty, 1); fireTableDataChanged(); } @@ -117,7 +105,6 @@ public Object getValueAt(int row, int col) { } WeaponType wp = weapons.get(row); return switch (col) { - case COL_QTY -> qty[row] + ""; case COL_NAME -> wp.getName(); case COL_IS_CLAN -> TechConstants.getTechName(wp.getTechLevel(twAdvancedSearchPanel.gameYear)); case COL_DMG -> wp.getDamage(); @@ -131,12 +118,4 @@ public Object getValueAt(int row, int col) { default -> "?"; }; } - - @Override - public void setValueAt(Object value, int row, int col) { - if (col == COL_QTY) { - qty[row] = Integer.parseInt((String) value); - fireTableCellUpdated(row, col); - } - } }