diff --git a/megamek/i18n/megamek/client/messages.properties b/megamek/i18n/megamek/client/messages.properties index d11b943ffd..2753c8c183 100644 --- a/megamek/i18n/megamek/client/messages.properties +++ b/megamek/i18n/megamek/client/messages.properties @@ -2174,15 +2174,15 @@ MekSelectorDialog.Search.Armor25=25% of maximum MekSelectorDialog.Search.Armor50=50% of maximum MekSelectorDialog.Search.Armor75=75% of maximum MekSelectorDialog.Search.Armor90=90% of maximum -MekSelectorDialog.Search.WeaponClass=Has Weapon Type: -MekSelectorDialog.Search.Weapons=Has weapons: -MekSelectorDialog.Search.WeaponsAtLeast=At least -MekSelectorDialog.Search.Equipment=Has equipment: +MekSelectorDialog.Search.WeaponClass=Weapon Type +MekSelectorDialog.Search.Weapons=Weapons +MekSelectorDialog.Search.Equipment=Equipment MekSelectorDialog.Search.Year=Design year: MekSelectorDialog.Search.TableFilters=Table filters: MekSelectorDialog.Search.UnitType=Unit Type: MekSelectorDialog.Search.TechClass=Tech Class: MekSelectorDialog.Search.TechLevel=Tech Level: +MekSelectorDialog.Search.TableFilter=Filter Text: MekSelectorDialog.Search.Quirk=Quirk: MekSelectorDialog.Search.Quirks=Quirks MekSelectorDialog.Search.WeaponQuirk=Weapon Quirk: diff --git a/megamek/src/megamek/client/ui/advancedsearch/AndFilterToken.java b/megamek/src/megamek/client/ui/advancedsearch/AndFilterToken.java new file mode 100644 index 0000000000..428cb81d70 --- /dev/null +++ b/megamek/src/megamek/client/ui/advancedsearch/AndFilterToken.java @@ -0,0 +1,28 @@ +/* + * 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 megamek.common.MekSearchFilter; + +public class AndFilterToken extends OperatorFT { + + public AndFilterToken() { + super(MekSearchFilter.BoolOp.AND); + } +} diff --git a/megamek/src/megamek/client/ui/advancedsearch/EquipmentFilterToken.java b/megamek/src/megamek/client/ui/advancedsearch/EquipmentFilterToken.java new file mode 100644 index 0000000000..b40b767108 --- /dev/null +++ b/megamek/src/megamek/client/ui/advancedsearch/EquipmentFilterToken.java @@ -0,0 +1,25 @@ +/* + * 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; + +public class EquipmentFilterToken implements FilterToken { + + +} diff --git a/megamek/src/megamek/client/ui/advancedsearch/EquipmentTableModel.java b/megamek/src/megamek/client/ui/advancedsearch/EquipmentTableModel.java index 693acbbbfd..f94005fd3f 100644 --- a/megamek/src/megamek/client/ui/advancedsearch/EquipmentTableModel.java +++ b/megamek/src/megamek/client/ui/advancedsearch/EquipmentTableModel.java @@ -22,11 +22,12 @@ import megamek.common.TechConstants; import javax.swing.table.AbstractTableModel; +import java.util.ArrayList; import java.util.Arrays; -import java.util.Vector; +import java.util.List; /** - * A table model for displaying equipment + * A table model for the advanced search weapon tab's equipment list */ public class EquipmentTableModel extends AbstractTableModel { @@ -40,7 +41,7 @@ public class EquipmentTableModel extends AbstractTableModel { private final TWAdvancedSearchPanel twAdvancedSearchPanel; private int[] qty; - private Vector equipment = new Vector<>(); + private List equipment = new ArrayList<>(); public EquipmentTableModel(TWAdvancedSearchPanel twAdvancedSearchPanel) { this.twAdvancedSearchPanel = twAdvancedSearchPanel; @@ -57,38 +58,26 @@ public int getColumnCount() { } public int getPreferredWidth(int col) { - switch (col) { - case COL_QTY: - return 40; - case COL_NAME: - return 400; - case COL_IS_CLAN: - return 75; - case COL_COST: - return 175; - case COL_LEVEL: - return 100; - default: - return 0; - } + return switch (col) { + case COL_QTY -> 40; + case COL_NAME -> 400; + case COL_IS_CLAN -> 75; + case COL_COST -> 175; + case COL_LEVEL -> 100; + default -> 0; + }; } @Override public String getColumnName(int column) { - switch (column) { - case COL_QTY: - return "Qty"; - case COL_NAME: - return "Name"; - case COL_IS_CLAN: - return "IS/Clan"; - case COL_COST: - return "Cost"; - case COL_LEVEL: - return "Lvl"; - default: - return "?"; - } + return switch (column) { + case COL_QTY -> "Qty"; + case COL_NAME -> "Name"; + case COL_IS_CLAN -> "IS/Clan"; + case COL_COST -> "Cost"; + case COL_LEVEL -> "Lvl"; + default -> "?"; + }; } @Override @@ -98,16 +87,10 @@ public Class getColumnClass(int c) { @Override public boolean isCellEditable(int row, int col) { - switch (col) { - case COL_QTY: - return true; - default: - return false; - } + return col == COL_QTY; } - // fill table with values - public void setData(Vector eq) { + public void setData(List eq) { equipment = eq; qty = new int[eq.size()]; Arrays.fill(qty, 1); @@ -115,7 +98,7 @@ public void setData(Vector eq) { } public EquipmentType getEquipmentTypeAt(int row) { - return equipment.elementAt(row); + return equipment.get(row); } @Override @@ -123,36 +106,24 @@ public Object getValueAt(int row, int col) { if (row >= equipment.size()) { return null; } - EquipmentType eq = equipment.elementAt(row); - switch (col) { - case COL_QTY: - return qty[row] + ""; - case COL_NAME: - return eq.getName(); - case COL_IS_CLAN: - return TechConstants.getTechName(eq.getTechLevel(twAdvancedSearchPanel.gameYear)); - case COL_COST: - return eq.getRawCost(); - case COL_LEVEL: - return TechConstants.getSimpleLevelName(TechConstants - .convertFromNormalToSimple(eq - .getTechLevel(twAdvancedSearchPanel.gameYear))); - case COL_INTERNAL_NAME: - return eq.getInternalName(); - default: - return "?"; - } + 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(); + case COL_LEVEL -> TechConstants.getSimpleLevelName( + TechConstants.convertFromNormalToSimple(eq.getTechLevel(twAdvancedSearchPanel.gameYear))); + case COL_INTERNAL_NAME -> eq.getInternalName(); + default -> "?"; + }; } @Override public void setValueAt(Object value, int row, int col) { - switch (col) { - case COL_QTY: - qty[row] = Integer.parseInt((String) value); - fireTableCellUpdated(row, col); - break; - default: - break; + if (col == COL_QTY) { + qty[row] = Integer.parseInt((String) value); + fireTableCellUpdated(row, col); } } } diff --git a/megamek/src/megamek/client/ui/advancedsearch/EquipmentFT.java b/megamek/src/megamek/client/ui/advancedsearch/EquipmentTypeFT.java similarity index 76% rename from megamek/src/megamek/client/ui/advancedsearch/EquipmentFT.java rename to megamek/src/megamek/client/ui/advancedsearch/EquipmentTypeFT.java index 9529cb411e..7f7f8294e9 100644 --- a/megamek/src/megamek/client/ui/advancedsearch/EquipmentFT.java +++ b/megamek/src/megamek/client/ui/advancedsearch/EquipmentTypeFT.java @@ -5,12 +5,13 @@ * * @author Arlith */ -public class EquipmentFT extends FilterTokens { +public class EquipmentTypeFT extends EquipmentFilterToken { + public String internalName; public String fullName; public int qty; - public EquipmentFT(String in, String fn, int q) { + public EquipmentTypeFT(String in, String fn, int q) { internalName = in; fullName = fn; qty = q; diff --git a/megamek/src/megamek/client/ui/advancedsearch/FilterToken.java b/megamek/src/megamek/client/ui/advancedsearch/FilterToken.java new file mode 100644 index 0000000000..17ece989cc --- /dev/null +++ b/megamek/src/megamek/client/ui/advancedsearch/FilterToken.java @@ -0,0 +1,28 @@ +/* + * 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; + +/** + * Marker interface for different tokens that can be in a filter expression. + * + * @author Arlith + */ +public interface FilterToken { + +} diff --git a/megamek/src/megamek/client/ui/advancedsearch/FilterTokens.java b/megamek/src/megamek/client/ui/advancedsearch/FilterTokens.java deleted file mode 100644 index f786d86784..0000000000 --- a/megamek/src/megamek/client/ui/advancedsearch/FilterTokens.java +++ /dev/null @@ -1,10 +0,0 @@ -package megamek.client.ui.advancedsearch; - -/** - * Base class for different tokens that can be in a filter expression. - * - * @author Arlith - */ -public class FilterTokens { - -} diff --git a/megamek/src/megamek/client/ui/advancedsearch/LeftParensFilterToken.java b/megamek/src/megamek/client/ui/advancedsearch/LeftParensFilterToken.java new file mode 100644 index 0000000000..da69edea0e --- /dev/null +++ b/megamek/src/megamek/client/ui/advancedsearch/LeftParensFilterToken.java @@ -0,0 +1,26 @@ +/* + * 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; + +public class LeftParensFilterToken extends ParensFT { + + public LeftParensFilterToken() { + super("("); + } +} diff --git a/megamek/src/megamek/client/ui/advancedsearch/MiscSearchTab.java b/megamek/src/megamek/client/ui/advancedsearch/MiscSearchTab.java index 7df03516eb..071b9177cf 100644 --- a/megamek/src/megamek/client/ui/advancedsearch/MiscSearchTab.java +++ b/megamek/src/megamek/client/ui/advancedsearch/MiscSearchTab.java @@ -24,7 +24,6 @@ import javax.swing.*; import java.awt.*; -import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.List; @@ -76,25 +75,25 @@ public class MiscSearchTab extends JPanel { JTextField tStartBV = new JTextField(4); JTextField tEndBV = new JTextField(4); JLabel lblCockpitType = new JLabel(Messages.getString("MekSelectorDialog.Search.CockpitType")); - JList listCockpitType = new JList<>(new DefaultListModel()); + JList listCockpitType = new JList<>(new DefaultListModel<>()); JScrollPane spCockpitType = new JScrollPane(listCockpitType); JLabel lblArmorType = new JLabel(Messages.getString("MekSelectorDialog.Search.ArmorType")); - JList listArmorType = new JList<>(new DefaultListModel()); + JList listArmorType = new JList<>(new DefaultListModel<>()); JScrollPane spArmorType = new JScrollPane(listArmorType); JLabel lblInternalsType = new JLabel(Messages.getString("MekSelectorDialog.Search.InternalsType")); - JList listInternalsType = new JList<>(new DefaultListModel()); + JList listInternalsType = new JList<>(new DefaultListModel<>()); JScrollPane spInternalsType = new JScrollPane(listInternalsType); JLabel lblEngineType = new JLabel(Messages.getString("MekSelectorDialog.Search.Engine")); - JList listEngineType = new JList<>(new DefaultListModel()); + JList listEngineType = new JList<>(new DefaultListModel<>()); JScrollPane spEngineType = new JScrollPane(listEngineType); JLabel lblGyroType = new JLabel(Messages.getString("MekSelectorDialog.Search.Gyro")); - JList listGyroType = new JList<>(new DefaultListModel()); + JList listGyroType = new JList<>(new DefaultListModel<>()); JScrollPane spGyroType = new JScrollPane(listGyroType); JLabel lblTechLevel = new JLabel(Messages.getString("MekSelectorDialog.Search.TechLevel")); - JList listTechLevel = new JList<>(new DefaultListModel()); + JList listTechLevel = new JList<>(new DefaultListModel<>()); JScrollPane spTechLevel = new JScrollPane(listTechLevel); JLabel lblTechBase = new JLabel(Messages.getString("MekSelectorDialog.Search.TechBase")); - JList listTechBase = new JList<>(new DefaultListModel()); + JList listTechBase = new JList<>(new DefaultListModel<>()); JScrollPane spTechBase = new JScrollPane(listTechBase); private JPanel createBaseAttributes() { @@ -267,7 +266,7 @@ private JPanel createBaseComboBoxes() { gyroPanel.add(spGyroType, BorderLayout.CENTER); baseComboBoxesPanel.add(gyroPanel, c); - c.gridx = 0; c.gridy++;; + c.gridx = 0; c.gridy++; JPanel armorTypePanel = new JPanel(new BorderLayout()); armorTypePanel.add(lblArmorType, BorderLayout.NORTH); armorTypePanel.add(spArmorType, BorderLayout.CENTER); @@ -282,7 +281,7 @@ private JPanel createBaseComboBoxes() { internalsPanel.add(spInternalsType, BorderLayout.CENTER); baseComboBoxesPanel.add(internalsPanel, c); - c.gridx = 0; c.gridy++;; + c.gridx = 0; c.gridy++; JPanel techLevelPanel = new JPanel(new BorderLayout()); techLevelPanel.add(lblTechLevel, BorderLayout.NORTH); techLevelPanel.add(spTechLevel, BorderLayout.CENTER); @@ -296,8 +295,8 @@ private JPanel createBaseComboBoxes() { return baseComboBoxesPanel; } - MiscSearchTab(ActionListener listener) { - btnBaseClear.addActionListener(listener); + MiscSearchTab() { + btnBaseClear.addActionListener(e -> clear()); GridBagConstraints c = new GridBagConstraints(); setLayout(new GridBagLayout()); @@ -310,12 +309,12 @@ private JPanel createBaseComboBoxes() { c.gridx = 0; c.gridy = 0; add(createBaseAttributes(), c); - c.gridx = 0; c.gridy++;; + c.gridx = 0; c.gridy++; add(createBaseComboBoxes(), c); c.weighty = 1; JPanel clearPanel = new JPanel(); - c.gridx = 0; c.gridy++;; + c.gridx = 0; c.gridy++; clearPanel.add(btnBaseClear, c); add(clearPanel, c); } @@ -380,4 +379,52 @@ private void toggleText(JList list, int index) { list.setModel(m); list.repaint(); } + + void clear() { + tStartWalk.setText(""); + tEndWalk.setText(""); + tStartJump.setText(""); + tEndJump.setText(""); + cArmor.setSelectedIndex(0); + cOfficial.setSelectedIndex(0); + cCanon.setSelectedIndex(0); + cPatchwork.setSelectedIndex(0); + cInvalid.setSelectedIndex(0); + cFailedToLoadEquipment.setSelectedIndex(0); + cClanEngine.setSelectedIndex(0); + tStartTankTurrets.setText(""); + tEndTankTurrets.setText(""); + tStartLowerArms.setText(""); + tEndLowerArms.setText(""); + tStartHands.setText(""); + tEndHands.setText(""); + tStartYear.setText(""); + tEndYear.setText(""); + tStartTons.setText(""); + tEndTons.setText(""); + tStartBV.setText(""); + tEndBV.setText(""); + tSource.setText(""); + tMULId.setText(""); + + clearTriStateItem(listArmorType); + clearTriStateItem(listCockpitType); + clearTriStateItem(listEngineType); + clearTriStateItem(listGyroType); + clearTriStateItem(listInternalsType); + clearTriStateItem(listTechLevel); + clearTriStateItem(listTechBase); + } + + void clearTriStateItem(JList l) { + ListModel m = l.getModel(); + + for (int i = 0; i < m.getSize(); i++) { + TriStateItem ms = m.getElementAt(i); + ms.state = "\u2610"; + } + + l.setModel(m); + l.repaint(); + } } diff --git a/megamek/src/megamek/client/ui/advancedsearch/OperationFT.java b/megamek/src/megamek/client/ui/advancedsearch/OperatorFT.java similarity index 81% rename from megamek/src/megamek/client/ui/advancedsearch/OperationFT.java rename to megamek/src/megamek/client/ui/advancedsearch/OperatorFT.java index 1aea114fd6..769b3e6283 100644 --- a/megamek/src/megamek/client/ui/advancedsearch/OperationFT.java +++ b/megamek/src/megamek/client/ui/advancedsearch/OperatorFT.java @@ -7,10 +7,10 @@ * * @author Arlith */ -public class OperationFT extends FilterTokens { +public abstract class OperatorFT implements FilterToken { public MekSearchFilter.BoolOp op; - public OperationFT(MekSearchFilter.BoolOp o) { + protected OperatorFT(MekSearchFilter.BoolOp o) { op = o; } diff --git a/megamek/src/megamek/client/ui/advancedsearch/OrFilterToken.java b/megamek/src/megamek/client/ui/advancedsearch/OrFilterToken.java new file mode 100644 index 0000000000..93c304fd00 --- /dev/null +++ b/megamek/src/megamek/client/ui/advancedsearch/OrFilterToken.java @@ -0,0 +1,28 @@ +/* + * 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 megamek.common.MekSearchFilter; + +public class OrFilterToken extends OperatorFT { + + public OrFilterToken() { + super(MekSearchFilter.BoolOp.OR); + } +} diff --git a/megamek/src/megamek/client/ui/advancedsearch/ParensFT.java b/megamek/src/megamek/client/ui/advancedsearch/ParensFT.java index f5ec7906a5..b31558a22c 100644 --- a/megamek/src/megamek/client/ui/advancedsearch/ParensFT.java +++ b/megamek/src/megamek/client/ui/advancedsearch/ParensFT.java @@ -5,7 +5,7 @@ * * @author Arlith */ -public class ParensFT extends FilterTokens { +public abstract class ParensFT implements FilterToken { public String parens; public ParensFT(String p) { diff --git a/megamek/src/megamek/client/ui/advancedsearch/QuirksSearchTab.java b/megamek/src/megamek/client/ui/advancedsearch/QuirksSearchTab.java index 4b51dcef08..f117d6e654 100644 --- a/megamek/src/megamek/client/ui/advancedsearch/QuirksSearchTab.java +++ b/megamek/src/megamek/client/ui/advancedsearch/QuirksSearchTab.java @@ -23,7 +23,6 @@ import javax.swing.*; import java.awt.*; -import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; @@ -40,18 +39,18 @@ class QuirksSearchTab extends JPanel { JLabel lblQuirkExclude = new JLabel("\u2612"); JComboBox cQuirkExclude = new JComboBox<>(); JLabel lblQuirkType = new JLabel(Messages.getString("MekSelectorDialog.Search.Quirk")); - JList listQuirkType = new JList<>(new DefaultListModel()); + JList listQuirkType = new JList<>(new DefaultListModel<>()); JScrollPane spQuirkType = new JScrollPane(listQuirkType); JLabel lblWeaponQuirkInclude = new JLabel("\u2611"); JComboBox cWeaponQuirkInclue = new JComboBox<>(); JLabel lblWeaponQuirkExclude = new JLabel("\u2612"); JComboBox cWeaponQuirkExclude = new JComboBox<>(); JLabel lblWeaponQuirkType = new JLabel(Messages.getString("MekSelectorDialog.Search.WeaponQuirk")); - JList listWeaponQuirkType = new JList<>(new DefaultListModel()); + JList listWeaponQuirkType = new JList<>(new DefaultListModel<>()); JScrollPane spWeaponQuirkType = new JScrollPane(listWeaponQuirkType); - QuirksSearchTab(ActionListener listener) { - btnQuirksClear.addActionListener(listener); + QuirksSearchTab() { + btnQuirksClear.addActionListener(e -> clear()); loadAndOr(cQuirkInclue, 0); loadAndOr(cQuirkExclude, 1); @@ -70,7 +69,7 @@ class QuirksSearchTab extends JPanel { c.anchor = GridBagConstraints.NORTHWEST; c.fill = GridBagConstraints.NONE; c.insets = new Insets(20, 10, 0, 0); - c.gridx = 0; c.gridy++;; + c.gridx = 0; c.gridy++; JPanel quirkPanel = new JPanel(new BorderLayout()); JPanel quirkIEPanel = new JPanel(new FlowLayout()); quirkIEPanel.add(lblQuirkType); @@ -96,7 +95,7 @@ class QuirksSearchTab extends JPanel { add(weaponQuirkPanel, c); c.weighty = 1; JPanel blankPanel = new JPanel(); - c.gridx = 0; c.gridy++;; + c.gridx = 0; c.gridy++; blankPanel.add(btnQuirksClear, c); add(blankPanel, c); } @@ -167,4 +166,26 @@ private void toggleText(JList list, int index) { list.setModel(m); list.repaint(); } + + void clear() { + cQuirkInclue.setSelectedIndex(0); + cQuirkExclude.setSelectedIndex(1); + clearTriStateItem(listQuirkType); + + cWeaponQuirkInclue.setSelectedIndex(0); + cWeaponQuirkExclude.setSelectedIndex(1); + clearTriStateItem(listWeaponQuirkType); + } + + void clearTriStateItem(JList l) { + ListModel m = l.getModel(); + + for (int i = 0; i < m.getSize(); i++) { + TriStateItem ms = m.getElementAt(i); + ms.state = "\u2610"; + } + + l.setModel(m); + l.repaint(); + } } diff --git a/megamek/src/megamek/client/ui/advancedsearch/RightParensFilterToken.java b/megamek/src/megamek/client/ui/advancedsearch/RightParensFilterToken.java new file mode 100644 index 0000000000..73c48c889b --- /dev/null +++ b/megamek/src/megamek/client/ui/advancedsearch/RightParensFilterToken.java @@ -0,0 +1,26 @@ +/* + * 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; + +public class RightParensFilterToken extends ParensFT { + + public RightParensFilterToken() { + super(")"); + } +} diff --git a/megamek/src/megamek/client/ui/advancedsearch/TWAdvancedSearchPanel.java b/megamek/src/megamek/client/ui/advancedsearch/TWAdvancedSearchPanel.java index f6465f8e27..66ff10426e 100644 --- a/megamek/src/megamek/client/ui/advancedsearch/TWAdvancedSearchPanel.java +++ b/megamek/src/megamek/client/ui/advancedsearch/TWAdvancedSearchPanel.java @@ -20,8 +20,6 @@ package megamek.client.ui.advancedsearch; import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.util.List; import javax.swing.*; @@ -37,7 +35,7 @@ * @author Jay Lawson * @author Simon (Juliez) */ -public class TWAdvancedSearchPanel extends JTabbedPane implements ActionListener { +public class TWAdvancedSearchPanel extends JTabbedPane { public MekSearchFilter mekFilter = new MekSearchFilter(); @@ -57,11 +55,11 @@ public class TWAdvancedSearchPanel extends JTabbedPane implements ActionListener public TWAdvancedSearchPanel(int year) { gameYear = year; - basePanel = new MiscSearchTab(this); + basePanel = new MiscSearchTab(); weaponEqPanel = new WeaponSearchTab(this); unitTypePanel = new UnitTypeSearchTab(); - quirkPanel = new QuirksSearchTab(this); - transportsPanel = new TransportsSearchTab(this); + quirkPanel = new QuirksSearchTab(); + transportsPanel = new TransportsSearchTab(); String msg_base = Messages.getString("MekSelectorDialog.Search.Base"); String msg_weaponEq = Messages.getString("MekSelectorDialog.Search.WeaponEq"); @@ -71,7 +69,8 @@ public TWAdvancedSearchPanel(int year) { addTab(msg_unitType, new StandardScrollPane(unitTypePanel)); addTab(msg_base, new StandardScrollPane(basePanel)); - addTab(msg_weaponEq, new StandardScrollPane(weaponEqPanel)); + // The weapon panel must manage its own scrollpane! + addTab(msg_weaponEq, weaponEqPanel); addTab(msg_transports, new StandardScrollPane(transportsPanel)); addTab(msg_quirkType, new StandardScrollPane(quirkPanel)); } @@ -88,14 +87,7 @@ public MekSearchFilter showDialog() { MekSearchFilter currFilter = mekFilter; mekFilter = new MekSearchFilter(currFilter); weaponEqPanel.txtWEEqExp.setText(mekFilter.getEquipmentExpression()); - if ((weaponEqPanel.filterToks == null) || weaponEqPanel.filterToks.isEmpty() - || (weaponEqPanel.filterToks.get(weaponEqPanel.filterToks.size() - 1) instanceof OperationFT)) { - weaponEqPanel.disableOperationButtons(); - weaponEqPanel.enableSelectionButtons(); - } else { - weaponEqPanel.enableOperationButtons(); - weaponEqPanel.disableSelectionButtons(); - } + weaponEqPanel.adaptTokenButtons(); setVisible(true); if (isCanceled) { mekFilter = currFilter; @@ -108,7 +100,7 @@ public MekSearchFilter showDialog() { public void prepareFilter() { try { mekFilter = new MekSearchFilter(mekFilter); - mekFilter.createFilterExpressionFromTokens(weaponEqPanel.filterToks); + mekFilter.createFilterExpressionFromTokens(weaponEqPanel.filterTokens); updateMekSearchFilter(); } catch (MekSearchFilter.FilterParsingException e) { JOptionPane.showMessageDialog(this, @@ -118,190 +110,13 @@ public void prepareFilter() { } } - /** - * Listener for button presses. - */ - @Override - public void actionPerformed(ActionEvent ev) { - if (ev.getSource().equals(weaponEqPanel.cboUnitType) - || ev.getSource().equals(weaponEqPanel.cboTechLevel) - || ev.getSource().equals(weaponEqPanel.cboTechClass)) { - weaponEqPanel.filterTables(); - } else if (ev.getSource().equals(weaponEqPanel.btnWEAdd)) { - int row = weaponEqPanel.tblEquipment.getSelectedRow(); - if (row >= 0) { - String internalName = (String) - weaponEqPanel.tblEquipment.getModel().getValueAt( - weaponEqPanel.tblEquipment.convertRowIndexToModel(row), - EquipmentTableModel.COL_INTERNAL_NAME); - String fullName = (String) weaponEqPanel.tblEquipment.getValueAt(row, EquipmentTableModel.COL_NAME); - int qty = Integer.parseInt((String) - weaponEqPanel.tblEquipment.getValueAt(row, EquipmentTableModel.COL_QTY)); - weaponEqPanel.filterToks.add(new EquipmentFT(internalName, fullName, qty)); - weaponEqPanel.txtWEEqExp.setText(weaponEqPanel.filterExpressionString()); - weaponEqPanel.btnWEBack.setEnabled(true); - weaponEqPanel.enableOperationButtons(); - weaponEqPanel.disableSelectionButtons(); - } - row = weaponEqPanel.tblWeapons.getSelectedRow(); - if (row >= 0) { - String internalName = (String) - weaponEqPanel.tblWeapons.getModel().getValueAt( - weaponEqPanel.tblWeapons.convertRowIndexToModel(row), - WeaponsTableModel.COL_INTERNAL_NAME); - String fullName = (String) weaponEqPanel.tblWeapons.getValueAt(row, WeaponsTableModel.COL_NAME); - int qty = Integer.parseInt((String) - weaponEqPanel.tblWeapons.getValueAt(row, WeaponsTableModel.COL_QTY)); - weaponEqPanel.filterToks.add(new EquipmentFT(internalName, fullName, qty)); - weaponEqPanel.txtWEEqExp.setText(weaponEqPanel.filterExpressionString()); - weaponEqPanel.btnWEBack.setEnabled(true); - weaponEqPanel.enableOperationButtons(); - weaponEqPanel.disableSelectionButtons(); - } - row = weaponEqPanel.tblWeaponType.getSelectedRow(); - if (row >= 0) { - int qty = Integer.parseInt((String)weaponEqPanel.tblWeaponType.getValueAt(row, WeaponClassTableModel.COL_QTY)); - weaponEqPanel.filterToks.add(new WeaponClassFT((WeaponClass)weaponEqPanel.tblWeaponType.getModel().getValueAt(weaponEqPanel.tblWeaponType.convertRowIndexToModel(row), WeaponClassTableModel.COL_VAL), qty)); - weaponEqPanel.txtWEEqExp.setText(weaponEqPanel.filterExpressionString()); - weaponEqPanel.btnWEBack.setEnabled(true); - weaponEqPanel.enableOperationButtons(); - weaponEqPanel.disableSelectionButtons(); - } - } else if (ev.getSource().equals(weaponEqPanel.btnWELeftParen)) { - weaponEqPanel.filterToks.add(new ParensFT("(")); - weaponEqPanel.txtWEEqExp.setText(weaponEqPanel.filterExpressionString()); - weaponEqPanel.btnWEBack.setEnabled(true); - weaponEqPanel.disableOperationButtons(); - weaponEqPanel.enableSelectionButtons(); - weaponEqPanel.btnWELeftParen.setEnabled(false); - weaponEqPanel.btnWERightParen.setEnabled(false); - } else if (ev.getSource().equals(weaponEqPanel.btnWERightParen)) { - weaponEqPanel.filterToks.add(new ParensFT(")")); - weaponEqPanel.txtWEEqExp.setText(weaponEqPanel.filterExpressionString()); - weaponEqPanel.btnWEBack.setEnabled(true); - weaponEqPanel.enableOperationButtons(); - weaponEqPanel.disableSelectionButtons(); - weaponEqPanel.btnWELeftParen.setEnabled(false); - weaponEqPanel.btnWERightParen.setEnabled(false); - } else if (ev.getSource().equals(weaponEqPanel.btnWEAnd)) { - weaponEqPanel.filterToks.add(new OperationFT(MekSearchFilter.BoolOp.AND)); - weaponEqPanel.txtWEEqExp.setText(weaponEqPanel.filterExpressionString()); - weaponEqPanel.btnWEBack.setEnabled(true); - weaponEqPanel.disableOperationButtons(); - weaponEqPanel.enableSelectionButtons(); - } else if (ev.getSource().equals(weaponEqPanel.btnWEOr)) { - weaponEqPanel.filterToks.add(new OperationFT(MekSearchFilter.BoolOp.OR)); - weaponEqPanel.txtWEEqExp.setText(weaponEqPanel.filterExpressionString()); - weaponEqPanel.btnWEBack.setEnabled(true); - weaponEqPanel.disableOperationButtons(); - weaponEqPanel.enableSelectionButtons(); - } else if (ev.getSource().equals(weaponEqPanel.btnWEBack)) { - if (!weaponEqPanel.filterToks.isEmpty()) { - weaponEqPanel.filterToks.remove(weaponEqPanel.filterToks.size() - 1); - weaponEqPanel.txtWEEqExp.setText(weaponEqPanel.filterExpressionString()); - if (weaponEqPanel.filterToks.isEmpty()) { - weaponEqPanel.btnWEBack.setEnabled(false); - } - - if ((weaponEqPanel.filterToks.isEmpty()) || (weaponEqPanel.filterToks.get(weaponEqPanel.filterToks.size() - 1) instanceof OperationFT)) { - weaponEqPanel.disableOperationButtons(); - weaponEqPanel.enableSelectionButtons(); - } else { - weaponEqPanel.enableOperationButtons(); - weaponEqPanel.disableSelectionButtons(); - } - } - } else if (ev.getSource().equals(weaponEqPanel.btnWEClear)) { - weaponEqPanel.clearWeaponsEquipment(); - } else if (ev.getSource().equals(basePanel.btnBaseClear)) { - clearBase(); - } else if (ev.getSource().equals(transportsPanel.btnTransportsClear)) { - transportsPanel.clearTransports(); - } else if (ev.getSource().equals(quirkPanel.btnQuirksClear)) { - clearQuirks(); - } - } - - private void toggleText(JButton b) { - if (b.getText().equals("\u2610")) { - b.setText("\u2611"); - } else if (b.getText().equals("\u2611")) { - b.setText("\u2612"); - } else if (b.getText().equals("\u2612")) { - b.setText("\u2610"); - } else { - b.setText("\u2610"); - } - } - - private void clearTriStateItem(JList l) { - ListModel m = l.getModel(); - - for (int i = 0; i < m.getSize(); i++) { - TriStateItem ms = m.getElementAt(i); - ms.state = "\u2610"; - } - - l.setModel(m); - l.repaint(); - } - - private void clearBase() { - basePanel.tStartWalk.setText(""); - basePanel.tEndWalk.setText(""); - basePanel.tStartJump.setText(""); - basePanel.tEndJump.setText(""); - basePanel.cArmor.setSelectedIndex(0); - basePanel.cOfficial.setSelectedIndex(0); - basePanel.cCanon.setSelectedIndex(0); - basePanel.cPatchwork.setSelectedIndex(0); - basePanel.cInvalid.setSelectedIndex(0); - basePanel.cFailedToLoadEquipment.setSelectedIndex(0); - basePanel.cClanEngine.setSelectedIndex(0); - basePanel.tStartTankTurrets.setText(""); - basePanel.tEndTankTurrets.setText(""); - basePanel.tStartLowerArms.setText(""); - basePanel.tEndLowerArms.setText(""); - basePanel.tStartHands.setText(""); - basePanel.tEndHands.setText(""); - basePanel.tStartYear.setText(""); - basePanel.tEndYear.setText(""); - basePanel.tStartTons.setText(""); - basePanel.tEndTons.setText(""); - basePanel.tStartBV.setText(""); - basePanel.tEndBV.setText(""); - basePanel.tSource.setText(""); - basePanel.tMULId.setText(""); - - clearTriStateItem(basePanel.listArmorType); - clearTriStateItem(basePanel.listCockpitType); - clearTriStateItem(basePanel.listEngineType); - clearTriStateItem(basePanel.listGyroType); - clearTriStateItem(basePanel.listInternalsType); - clearTriStateItem(basePanel.listTechLevel); - clearTriStateItem(basePanel.listTechBase); - } - - private void clearQuirks() { - quirkPanel.cQuirkInclue.setSelectedIndex(0); - quirkPanel.cQuirkExclude.setSelectedIndex(1); - clearTriStateItem(quirkPanel.listQuirkType); - - quirkPanel.cWeaponQuirkInclue.setSelectedIndex(0); - quirkPanel.cWeaponQuirkExclude.setSelectedIndex(1); - clearTriStateItem(quirkPanel.listWeaponQuirkType); - } - - /** - * Clear the filter. - */ public void clearValues() { mekFilter = null; unitTypePanel.clear(); - clearBase(); - transportsPanel.clearTransports(); - clearQuirks(); - weaponEqPanel.clearWeaponsEquipment(); + basePanel.clear(); + transportsPanel.clear(); + quirkPanel.clear(); + weaponEqPanel.clear(); } public MekSearchFilter getMekSearchFilter() { diff --git a/megamek/src/megamek/client/ui/advancedsearch/TransportsSearchTab.java b/megamek/src/megamek/client/ui/advancedsearch/TransportsSearchTab.java index 1f9de13742..3b64d76aa6 100644 --- a/megamek/src/megamek/client/ui/advancedsearch/TransportsSearchTab.java +++ b/megamek/src/megamek/client/ui/advancedsearch/TransportsSearchTab.java @@ -22,7 +22,6 @@ import javax.swing.*; import java.awt.*; -import java.awt.event.ActionListener; class TransportsSearchTab extends JPanel { @@ -133,8 +132,8 @@ class TransportsSearchTab extends JPanel { JTextField tStartNavalRepairFacilities = new JTextField(4); JTextField tEndNavalRepairFacilities = new JTextField(4); - TransportsSearchTab(ActionListener listener) { - btnTransportsClear.addActionListener(listener); + TransportsSearchTab() { + btnTransportsClear.addActionListener(e -> clear()); GridBagConstraints c = new GridBagConstraints(); setLayout(new GridBagLayout()); @@ -339,7 +338,7 @@ class TransportsSearchTab extends JPanel { add(blankPanel, c); } - void clearTransports() { + void clear() { tStartTroopSpace.setText(""); tEndTroopSpace.setText(""); tStartASFBays.setText(""); diff --git a/megamek/src/megamek/client/ui/advancedsearch/WeaponClass.java b/megamek/src/megamek/client/ui/advancedsearch/WeaponClass.java index 815f49d41b..37fe092897 100644 --- a/megamek/src/megamek/client/ui/advancedsearch/WeaponClass.java +++ b/megamek/src/megamek/client/ui/advancedsearch/WeaponClass.java @@ -1,3 +1,22 @@ + +/* + * 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; public enum WeaponClass { @@ -156,7 +175,6 @@ public boolean matches(String name) { } else if (this == BALLISTIC) { return WeaponClass.AUTOCANNON.matches(name) || WeaponClass.GAUSS.matches(name) || - WeaponClass.MISSILE.matches(name) || WeaponClass.MACHINE_GUN.matches(name); } else if (this == RAC) { if (name.toLowerCase().contains("rotary")) { diff --git a/megamek/src/megamek/client/ui/advancedsearch/WeaponClassFT.java b/megamek/src/megamek/client/ui/advancedsearch/WeaponClassFT.java index 1e0ace9e48..5eaa09152a 100644 --- a/megamek/src/megamek/client/ui/advancedsearch/WeaponClassFT.java +++ b/megamek/src/megamek/client/ui/advancedsearch/WeaponClassFT.java @@ -1,6 +1,6 @@ package megamek.client.ui.advancedsearch; -public class WeaponClassFT extends FilterTokens { +public class WeaponClassFT extends EquipmentFilterToken { public WeaponClass weaponClass; public int qty; diff --git a/megamek/src/megamek/client/ui/advancedsearch/WeaponSearchTab.java b/megamek/src/megamek/client/ui/advancedsearch/WeaponSearchTab.java index fa60c28e05..f9cf4324db 100644 --- a/megamek/src/megamek/client/ui/advancedsearch/WeaponSearchTab.java +++ b/megamek/src/megamek/client/ui/advancedsearch/WeaponSearchTab.java @@ -18,52 +18,53 @@ */ package megamek.client.ui.advancedsearch; -import megamek.MMConstants; import megamek.client.ui.Messages; import megamek.client.ui.swing.table.MegaMekTable; import megamek.common.*; +import megamek.common.annotations.Nullable; import javax.swing.*; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; +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; +import java.awt.event.FocusListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; -import java.util.ArrayList; -import java.util.Enumeration; +import java.util.*; import java.util.List; -import java.util.Vector; +import java.util.regex.PatternSyntaxException; -public class WeaponSearchTab extends JPanel implements KeyListener, ListSelectionListener { +public class WeaponSearchTab extends JPanel implements KeyListener, DocumentListener, FocusListener { - final List filterToks = new ArrayList<>(); + final List filterTokens = new ArrayList<>(); - final JLabel lblTableFilters = new JLabel(Messages.getString("MekSelectorDialog.Search.TableFilters")); - final JButton btnWELeftParen = new JButton("("); - final JButton btnWERightParen = new JButton(")"); - final JButton btnWEAdd = new JButton(Messages.getString("MekSelectorDialog.Search.add")); - final JButton btnWEAnd = new JButton(Messages.getString("MekSelectorDialog.Search.and")); - final JButton btnWEOr = new JButton(Messages.getString("MekSelectorDialog.Search.or")); - final JButton btnWEClear = new JButton(Messages.getString("MekSelectorDialog.Reset")); - final JButton btnWEBack = new JButton("Back"); - final JLabel lblWEEqExpTxt = new JLabel(Messages.getString("MekSelectorDialog.Search.FilterExpression")); - final JTextArea txtWEEqExp = new JTextArea(""); + final JButton btnLeftParen = new JButton("("); + final JButton btnRightParen = new JButton(")"); + final JButton btnAdd = new JButton(Messages.getString("MekSelectorDialog.Search.add")); + 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")); + final JButton btnBack = new JButton("Back"); + final JLabel lblWEEqExpTxt = new JLabel(Messages.getString("MekSelectorDialog.Search.FilterExpression")); + final JTextArea txtWEEqExp = new JTextArea("", 2, 40); final JScrollPane expWEScroller = new JScrollPane(txtWEEqExp, 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 JLabel lblWeaponClass = new JLabel(Messages.getString("MekSelectorDialog.Search.WeaponClass")); - final JScrollPane scrTableWeaponType = new JScrollPane(); - final MegaMekTable tblWeaponType; - final WeaponClassTableModel weaponTypesModel; - final TableRowSorter weaponTypesSorter; + final JLabel tableFilterTextLabel = new JLabel(Messages.getString("MekSelectorDialog.Search.TableFilter")); + final JTextField tableFilterText = new JTextField(20); + final JLabel lblWeapons = new JLabel(Messages.getString("MekSelectorDialog.Search.Weapons")); final JScrollPane scrTableWeapons = new JScrollPane(); final MegaMekTable tblWeapons; @@ -76,21 +77,25 @@ public class WeaponSearchTab extends JPanel implements KeyListener, ListSelectio final TableRowSorter equipmentSorter; final JComboBox cboQty = new JComboBox<>(); + final JLabel lblWeaponClass = new JLabel(Messages.getString("MekSelectorDialog.Search.WeaponClass")); + final JSpinner weaponClassCount; + final JComboBox weaponClassChooser; + + JComponent focusedSelector = null; + private final TWAdvancedSearchPanel parentPanel; WeaponSearchTab(TWAdvancedSearchPanel parentPanel) { this.parentPanel = parentPanel; - // Initialize Items - btnWEAnd.addActionListener(parentPanel); - btnWEAdd.addActionListener(parentPanel); - btnWELeftParen.addActionListener(parentPanel); - btnWERightParen.addActionListener(parentPanel); - btnWEOr.addActionListener(parentPanel); - btnWEClear.addActionListener(parentPanel); - btnWEBack.addActionListener(parentPanel); - - btnWEBack.setEnabled(false); - btnWEAdd.setEnabled(false); + + btnAnd.addActionListener(e -> addFilterToken(new AndFilterToken())); + btnAdd.addActionListener(e -> addButtonPressed()); + 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()); + adaptTokenButtons(); for (int i = 1; i <= 20; i++) { cboQty.addItem(Integer.toString(i)); @@ -109,7 +114,7 @@ public class WeaponSearchTab extends JPanel implements KeyListener, ListSelectio unitTypeModel.setSelectedItem(Messages.getString("MekSelectorDialog.All")); cboUnitType.setModel(unitTypeModel); - cboUnitType.addActionListener(parentPanel); + cboUnitType.addActionListener(e -> filterTables()); DefaultComboBoxModel techLevelModel = new DefaultComboBoxModel<>(); @@ -119,7 +124,7 @@ public class WeaponSearchTab extends JPanel implements KeyListener, ListSelectio techLevelModel.setSelectedItem(TechConstants.getLevelDisplayableName(TechConstants.SIZE - 1)); cboTechLevel.setModel(techLevelModel); - cboTechLevel.addActionListener(parentPanel); + cboTechLevel.addActionListener(e -> filterTables()); DefaultComboBoxModel techClassModel = new DefaultComboBoxModel<>(); techClassModel.addElement("All"); @@ -129,37 +134,30 @@ public class WeaponSearchTab extends JPanel implements KeyListener, ListSelectio techClassModel.addElement("(Unknown Technology Base)"); techClassModel.setSelectedItem("All"); cboTechClass.setModel(techClassModel); - cboTechClass.addActionListener(parentPanel); - - // Set up Weapon Class table - weaponTypesModel = new WeaponClassTableModel(); - tblWeaponType = new MegaMekTable(weaponTypesModel, WeaponClassTableModel.COL_NAME); - TableColumn wpsTypeCol = tblWeaponType.getColumnModel().getColumn(WeaponClassTableModel.COL_QTY); - wpsTypeCol.setCellEditor(new DefaultCellEditor(cboQty)); - tblWeaponType.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - weaponTypesSorter = new TableRowSorter<>(weaponTypesModel); - tblWeaponType.setRowSorter(weaponTypesSorter); - tblWeaponType.addKeyListener(this); - tblWeaponType.setFont(new Font(MMConstants.FONT_MONOSPACED, Font.PLAIN, 12)); - tblWeaponType.getSelectionModel().addListSelectionListener(this); - - for (int i = 0; i < weaponTypesModel.getColumnCount(); i++) { - tblWeaponType.getColumnModel().getColumn(i).setPreferredWidth(weaponTypesModel.getPreferredWidth(i)); - } + cboTechClass.addActionListener(e -> filterTables()); - scrTableWeaponType.setViewportView(tblWeaponType); + // 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 MegaMekTable(weaponsModel, WeaponsTableModel.COL_NAME) { + @Override + public Dimension getPreferredScrollableViewportSize() { + Dimension standardSize = super.getPreferredScrollableViewportSize(); + return new Dimension(standardSize.width, getRowHeight() * 6); + } + }; TableColumn wpsCol = tblWeapons.getColumnModel().getColumn(WeaponsTableModel.COL_QTY); wpsCol.setCellEditor(new DefaultCellEditor(cboQty)); tblWeapons.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); weaponsSorter = new TableRowSorter<>(weaponsModel); tblWeapons.setRowSorter(weaponsSorter); tblWeapons.addKeyListener(this); - tblWeapons.setFont(new Font(MMConstants.FONT_MONOSPACED, Font.PLAIN, 12)); - tblWeapons.getSelectionModel().addListSelectionListener(this); + tblWeapons.addFocusListener(this); for (int i = 0; i < weaponsModel.getColumnCount(); i++) { tblWeapons.getColumnModel().getColumn(i).setPreferredWidth(weaponsModel.getPreferredWidth(i)); @@ -169,15 +167,20 @@ public class WeaponSearchTab extends JPanel implements KeyListener, ListSelectio // Setup Equipment Table equipmentModel = new EquipmentTableModel(parentPanel); - tblEquipment = new MegaMekTable(equipmentModel, EquipmentTableModel.COL_NAME); + tblEquipment = new MegaMekTable(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); equipmentSorter = new TableRowSorter<>(equipmentModel); tblEquipment.setRowSorter(equipmentSorter); tblEquipment.addKeyListener(this); - tblEquipment.setFont(new Font(MMConstants.FONT_MONOSPACED, Font.PLAIN, 12)); - tblEquipment.getSelectionModel().addListSelectionListener(this); + tblEquipment.addFocusListener(this); for (int i = 0; i < equipmentModel.getColumnCount(); i++) { tblEquipment.getColumnModel().getColumn(i).setPreferredWidth(equipmentModel.getPreferredWidth(i)); @@ -206,98 +209,104 @@ public class WeaponSearchTab extends JPanel implements KeyListener, ListSelectio txtWEEqExp.setLineWrap(true); txtWEEqExp.setWrapStyleWord(true); - setLayout(new GridBagLayout()); - GridBagConstraints c = new GridBagConstraints(); - - c.weighty = 0; - c.anchor = GridBagConstraints.NORTHWEST; - c.fill = GridBagConstraints.NONE; - c.insets = new Insets(0, 0, 0, 0); - c.gridx = 0; c.gridy++; - add(lblTableFilters, c); - c.gridx = 0; c.gridy++; - c.gridwidth = 4; - c.anchor = GridBagConstraints.CENTER; - c.insets = new Insets(0, 40, 0, 0); - JPanel cboPanel = new JPanel(); - cboPanel.add(lblUnitType); - cboPanel.add(cboUnitType); - cboPanel.add(lblTechClass); - cboPanel.add(cboTechClass); - cboPanel.add(lblTechLevelBase, c); - cboPanel.add(cboTechLevel, c); - add(cboPanel, c); - c.gridwidth = 1; - - c.gridx = 0; c.gridy++; - c.anchor = GridBagConstraints.WEST; - c.insets = new Insets(0, 0, 0, 0); - add(lblWeaponClass, c); - - c.fill = GridBagConstraints.HORIZONTAL; - c.anchor = GridBagConstraints.CENTER; - c.gridwidth = 5; - c.gridx = 0; c.gridy++; - add(scrTableWeaponType, c); - c.gridwidth = 1; - - c.fill = GridBagConstraints.NONE; - c.gridx = 0; c.gridy++; - c.anchor = GridBagConstraints.WEST; - add(lblWeapons, c); - - c.fill = GridBagConstraints.HORIZONTAL; - c.anchor = GridBagConstraints.CENTER; - c.gridwidth = 5; - c.gridx = 0; c.gridy++; - add(scrTableWeapons, c); - - c.fill = GridBagConstraints.NONE; - c.gridwidth = 1; - c.gridx = 0; c.gridy++; - c.anchor = GridBagConstraints.WEST; - add(lblEquipment, c); - - c.fill = GridBagConstraints.HORIZONTAL; - c.anchor = GridBagConstraints.CENTER; - c.gridwidth = 5; - c.gridx = 0; c.gridy++; - add(scrTableEquipment, c); - - c.insets = new Insets(0, 50, 0, 0); - c.fill = GridBagConstraints.NONE; - c.gridx = 0; c.gridy++; - c.gridwidth = 4; + tableFilterText.getDocument().addDocumentListener(this); + + JPanel upperPanel = new JPanel(); + upperPanel.setLayout(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.gridy++; + JPanel tableTextFilterPanel = new JPanel(); + tableTextFilterPanel.add(tableFilterTextLabel); + tableTextFilterPanel.add(tableFilterText); + upperPanel.add(tableTextFilterPanel, gbc); + + gbc.gridwidth = 1; + gbc.insets = new Insets(0, 0, 0, 0); + gbc.fill = GridBagConstraints.NONE; + gbc.gridy++; + gbc.anchor = GridBagConstraints.WEST; + upperPanel.add(lblWeapons, gbc); + + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.anchor = GridBagConstraints.CENTER; + gbc.gridwidth = 5; + gbc.gridy++; + upperPanel.add(scrTableWeapons, gbc); + + gbc.gridy++; + upperPanel.add(Box.createVerticalStrut(20), gbc); + + gbc.fill = GridBagConstraints.NONE; + gbc.gridwidth = 1; + gbc.gridy++; + gbc.anchor = GridBagConstraints.WEST; + upperPanel.add(lblEquipment, gbc); + + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.anchor = GridBagConstraints.CENTER; + gbc.gridwidth = 5; + gbc.gridy++; + upperPanel.add(scrTableEquipment, gbc); + + gbc.gridy++; + upperPanel.add(Box.createVerticalStrut(20), gbc); + + gbc.gridwidth = 1; + gbc.gridy++; + gbc.anchor = GridBagConstraints.WEST; + gbc.insets = new Insets(0, 0, 0, 20); + upperPanel.add(lblWeaponClass, gbc); + gbc.gridy++; + upperPanel.add(weaponClassCount, gbc); + upperPanel.add(weaponClassChooser, gbc); + JPanel btnPanel = new JPanel(); - btnPanel.add(btnWEAdd, c); - btnPanel.add(btnWELeftParen, c); - btnPanel.add(btnWERightParen, c); - btnPanel.add(btnWEAnd, c); - btnPanel.add(btnWEOr, c); - btnPanel.add(btnWEBack, c); - btnPanel.add(btnWEClear, c); - add(btnPanel, c); - - // Filter Expression - c.insets = new Insets(0, 0, 0, 0); - c.gridx = 0; c.gridy++; - c.gridwidth = 1; - c.anchor = GridBagConstraints.WEST; - c.fill = GridBagConstraints.NONE; - add(lblWEEqExpTxt, c); - c.anchor = GridBagConstraints.CENTER; - c.fill = GridBagConstraints.HORIZONTAL; - c.gridx = 1; - c.gridwidth = 3; - add(expWEScroller, c); - c.weighty = 1; - JPanel blankPanel = new JPanel(); - add(blankPanel, c); + btnPanel.add(btnAdd); + btnPanel.add(btnLeftParen); + btnPanel.add(btnRightParen); + btnPanel.add(btnAnd); + btnPanel.add(btnOr); + btnPanel.add(btnBack); + btnPanel.add(btnClear); + + Box filterExpressionPanel = Box.createHorizontalBox(); + filterExpressionPanel.setBorder(new EmptyBorder(0, 20, 0, 20)); + filterExpressionPanel.add(lblWEEqExpTxt); + filterExpressionPanel.add(Box.createHorizontalStrut(20)); + filterExpressionPanel.add(expWEScroller); + + Box filterAssemblyPanel = Box.createVerticalBox(); + filterAssemblyPanel.add(Box.createVerticalStrut(10)); + filterAssemblyPanel.add(btnPanel); + filterAssemblyPanel.add(filterExpressionPanel); + filterAssemblyPanel.add(Box.createVerticalStrut(10)); + + setLayout(new BorderLayout()); + add(new TWAdvancedSearchPanel.StandardScrollPane(upperPanel), BorderLayout.CENTER); + add(filterAssemblyPanel, BorderLayout.PAGE_END); } void filterTables() { RowFilter weaponFilter; - RowFilter equipmentFilter; final int techLevel = cboTechLevel.getSelectedIndex(); final String techClass = (String) cboTechClass.getSelectedItem(); final int unitType = cboUnitType.getSelectedIndex() - 1; @@ -313,14 +322,17 @@ public boolean include(Entry ent boolean techLvlMatch = matchTechLvl(techLevel, wp.getTechLevel(parentPanel.gameYear)); boolean techClassMatch = matchTechClass(techClass, currTechClass); boolean unitTypeMatch = matchUnitType(unitType, wp); - return techLvlMatch && techClassMatch && unitTypeMatch; + boolean textFilterMatch = (tableFilterText.getText() == null) || (tableFilterText.getText().length() < 2) + || matchWeaponTextFilter(entry, WeaponsTableModel.COL_NAME); + return techLvlMatch && techClassMatch && unitTypeMatch && textFilterMatch; } }; - } catch (java.util.regex.PatternSyntaxException ignored) { + } catch (PatternSyntaxException ignored) { return; } weaponsSorter.setRowFilter(weaponFilter); + RowFilter equipmentFilter; try { equipmentFilter = new RowFilter<>() { @Override @@ -331,24 +343,23 @@ public boolean include(Entry e boolean techLvlMatch = matchTechLvl(techLevel, eq.getTechLevel(parentPanel.gameYear)); boolean techClassMatch = matchTechClass(techClass, currTechClass); boolean unitTypeMatch = matchUnitType(unitType, eq); - return techLvlMatch && techClassMatch && unitTypeMatch; + boolean textFilterMatch = (tableFilterText.getText() == null) || (tableFilterText.getText().length() < 2) + || matchEquipmentTextFilter(entry, EquipmentTableModel.COL_NAME); + return techLvlMatch && techClassMatch && unitTypeMatch && textFilterMatch; } }; - } catch (java.util.regex.PatternSyntaxException ignored) { + } catch (PatternSyntaxException ignored) { return; } equipmentSorter.setRowFilter(equipmentFilter); } - - void clearWeaponsEquipment() { - filterToks.clear(); + void clear() { + filterTokens.clear(); tblWeapons.clearSelection(); tblEquipment.clearSelection(); txtWEEqExp.setText(""); - btnWEBack.setEnabled(false); - disableOperationButtons(); - enableSelectionButtons(); + adaptTokenButtons(); } /** @@ -357,8 +368,8 @@ void clearWeaponsEquipment() { * and equipment tables. */ private void populateWeaponsAndEquipmentChoices() { - Vector weapons = new Vector<>(); - Vector equipment = new Vector<>(); + List weapons = new ArrayList<>(); + List equipment = new ArrayList<>(); for (Enumeration e = EquipmentType.getAllTypes(); e.hasMoreElements();) { EquipmentType et = e.nextElement(); @@ -388,7 +399,7 @@ public void keyTyped(KeyEvent evt) { char keyChar = evt.getKeyChar(); // Ensure we've got a number or letter pressed if (!(((keyChar >= '0') && (keyChar <= '9')) || - ((keyChar >= 'a') && (keyChar <='z')) || (keyChar == ' '))) { + ((keyChar >= 'a') && (keyChar <= 'z')) || (keyChar == ' '))) { return; } @@ -399,7 +410,6 @@ public void keyTyped(KeyEvent evt) { } } - private boolean matchTechClass(String t1, String t2) { if (t1.equals("All")) { return true; @@ -418,14 +428,12 @@ private boolean matchUnitType(int unitTypeFilter, EquipmentType eq) { switch (unitTypeFilter) { case 5: - if (eq.hasFlag(WeaponType.F_AERO_WEAPON) - || eq.hasFlag(MiscType.F_FIGHTER_EQUIPMENT)) { + 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)) { + if (eq.hasFlag(WeaponType.F_BA_WEAPON) || eq.hasFlag(MiscType.F_BA_EQUIPMENT)) { return true; } break; @@ -435,20 +443,17 @@ private boolean matchUnitType(int unitTypeFilter, EquipmentType eq) { } break; case UnitType.MEK: - if (eq.hasFlag(WeaponType.F_MEK_WEAPON) - || eq.hasFlag(MiscType.F_MEK_EQUIPMENT)) { + 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)) { + 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)) { + if (eq.hasFlag(WeaponType.F_PROTO_WEAPON) || eq.hasFlag(MiscType.F_PROTOMEK_EQUIPMENT)) { return true; } break; @@ -458,93 +463,15 @@ private boolean matchUnitType(int unitTypeFilter, EquipmentType eq) { return false; } - @Override - public void valueChanged(ListSelectionEvent evt) { - boolean lastTokIsOperation; - int tokSize = filterToks.size(); - lastTokIsOperation = ((tokSize == 0) || - (filterToks.get(tokSize - 1) instanceof OperationFT)); - if (evt.getSource().equals(tblWeapons.getSelectionModel())) { - if ((tblWeapons.getSelectedRow() >= 0) && lastTokIsOperation) { - tblEquipment.clearSelection(); - tblWeaponType.clearSelection(); - btnWEAdd.setEnabled(true); - } else if (tblWeapons.getSelectedRow() >= 0) { - tblEquipment.clearSelection(); - tblWeaponType.clearSelection(); - } - } else if (evt.getSource().equals(tblEquipment.getSelectionModel())) { - if ((tblEquipment.getSelectedRow() >= 0) && lastTokIsOperation) { - tblWeapons.clearSelection(); - tblWeaponType.clearSelection(); - btnWEAdd.setEnabled(true); - } else if (tblEquipment.getSelectedRow() >= 0) { - tblWeapons.clearSelection(); - tblWeaponType.clearSelection(); - } - } else if (evt.getSource().equals(tblWeaponType.getSelectionModel())) { - if ((tblWeaponType.getSelectedRow() >= 0) && lastTokIsOperation) { - tblWeapons.clearSelection(); - tblEquipment.clearSelection(); - btnWEAdd.setEnabled(true); - } else if (tblWeaponType.getSelectedRow() >= 0) { - tblWeapons.clearSelection(); - tblEquipment.clearSelection(); - } - } - } - + // Build the string representation of the new expression String filterExpressionString() { - // Build the string representation of the new expression StringBuilder filterExp = new StringBuilder(); - for (int i = 0; i < filterToks.size(); i++) { - filterExp.append(" ").append(filterToks.get(i).toString()).append(" "); + for (FilterToken filterTok : filterTokens) { + filterExp.append(" ").append(filterTok.toString()).append(" "); } return filterExp.toString(); } - /** - * Convenience method for enabling the buttons related to weapon/equipment - * selection for filtering (btnAddEquipment, btnAddWeapon, etc) - */ - void enableSelectionButtons() { - if ((tblWeapons.getSelectedRow() != -1) || - (tblEquipment.getSelectedRow() != -1) || - (tblWeaponType.getSelectedRow() != -1)) { - btnWEAdd.setEnabled(true); - } - btnWELeftParen.setEnabled(true); - } - - /** - * Convenience method for disabling the buttons related to weapon/equipment - * selection for filtering (btnAddEquipment, btnAddWeapon, etc) - */ - void disableSelectionButtons() { - btnWEAdd.setEnabled(false); - btnWELeftParen.setEnabled(false); - } - - /** - * Convenience method for enabling the buttons related to filter operations - * for filtering (btnAnd, btnOr, etc) - */ - void enableOperationButtons() { - btnWEOr.setEnabled(true); - btnWEAnd.setEnabled(true); - btnWERightParen.setEnabled(true); - } - - /** - * Convenience method for disabling the buttons related to filter operations - * for filtering (btnAnd, btnOr, etc) - */ - void disableOperationButtons() { - btnWEOr.setEnabled(false); - btnWEAnd.setEnabled(false); - btnWERightParen.setEnabled(false); - } - 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))) @@ -562,4 +489,125 @@ private boolean matchTechLvl(int t1, int t2) { || (t2 == TechConstants.T_CLAN_EXPERIMENTAL) || (t2 == TechConstants.T_CLAN_UNOFFICIAL))); } + + 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)); + + } else if ((focusedSelector == weaponClassChooser) && (weaponClassChooser.getSelectedItem() != null)) { + int qty = (int) weaponClassCount.getValue(); + filterTokens.add(new WeaponClassFT((WeaponClass) weaponClassChooser.getSelectedItem(), qty)); + + } else { + // if something else is focused, do nothing + return; + } + txtWEEqExp.setText(filterExpressionString()); + adaptTokenButtons(); + } + + private boolean matchWeaponTextFilter(RowFilter.Entry entry, int column) { + String wp = entry.getModel().getValueAt(entry.getIdentifier(), column).toString(); + return matchTextFilter(wp); + } + + private boolean matchEquipmentTextFilter(RowFilter.Entry entry, int column) { + String wp = entry.getModel().getValueAt(entry.getIdentifier(), column).toString(); + return matchTextFilter(wp); + } + + private boolean matchTextFilter(String tableText) { + return tableText.toLowerCase(Locale.ROOT).contains(tableFilterText.getText().toLowerCase(Locale.ROOT)); + } + + @Override + public void insertUpdate(DocumentEvent e) { + filterTables(); + } + + @Override + public void removeUpdate(DocumentEvent e) { + filterTables(); + } + + @Override + public void changedUpdate(DocumentEvent e) { + filterTables(); + } + + @Override + public void focusGained(FocusEvent e) { + if ((e.getSource() == tblEquipment) || (e.getSource() == tblWeapons)) { + focusedSelector = (JComponent) e.getSource(); + adaptTokenButtons(); + } else if (e.getSource() == weaponClassChooser) { + focusWeaponClasschooser(); + } + } + + @Override + public void focusLost(FocusEvent e) { } + + private void spinnerChange() { + focusWeaponClasschooser(); + } + + private void focusWeaponClasschooser() { + focusedSelector = weaponClassChooser; + tblWeapons.clearSelection(); + tblEquipment.clearSelection(); + adaptTokenButtons(); + } + + private @Nullable FilterToken lastToken() { + return filterTokens.isEmpty() ? null : filterTokens.get(filterTokens.size() - 1); + } + + private boolean hasFocusedSelector() { + return (focusedSelector == weaponClassChooser) || (focusedSelector == tblEquipment) || (focusedSelector == tblWeapons); + } + + void adaptTokenButtons() { + btnBack.setEnabled(!filterTokens.isEmpty()); + btnClear.setEnabled(!filterTokens.isEmpty()); + + boolean canAddEquipment = filterTokens.isEmpty() || (lastToken() instanceof OperatorFT) + || (lastToken() instanceof LeftParensFilterToken); + btnAdd.setEnabled(hasFocusedSelector() && canAddEquipment); + btnLeftParen.setEnabled(canAddEquipment); + + boolean canAddOperator = (lastToken() instanceof EquipmentFilterToken) || (lastToken() instanceof RightParensFilterToken); + btnAnd.setEnabled(canAddOperator); + btnOr.setEnabled(canAddOperator); + btnRightParen.setEnabled(canAddOperator); + } + + private void addFilterToken(FilterToken token) { + filterTokens.add(token); + txtWEEqExp.setText(filterExpressionString()); + adaptTokenButtons(); + } + + private void backOperation() { + if (!filterTokens.isEmpty()) { + filterTokens.remove(filterTokens.size() - 1); + txtWEEqExp.setText(filterExpressionString()); + adaptTokenButtons(); + } + } } diff --git a/megamek/src/megamek/client/ui/advancedsearch/WeaponsTableModel.java b/megamek/src/megamek/client/ui/advancedsearch/WeaponsTableModel.java index 7e6e79a297..04bfe77469 100644 --- a/megamek/src/megamek/client/ui/advancedsearch/WeaponsTableModel.java +++ b/megamek/src/megamek/client/ui/advancedsearch/WeaponsTableModel.java @@ -22,8 +22,9 @@ import megamek.common.WeaponType; import javax.swing.table.AbstractTableModel; +import java.util.ArrayList; import java.util.Arrays; -import java.util.Vector; +import java.util.List; /** * A table model for displaying weapons @@ -45,7 +46,7 @@ public class WeaponsTableModel extends AbstractTableModel { private final TWAdvancedSearchPanel twAdvancedSearchPanel; private int[] qty; - private Vector weapons = new Vector<>(); + private List weapons = new ArrayList<>(); public WeaponsTableModel(TWAdvancedSearchPanel twAdvancedSearchPanel) { this.twAdvancedSearchPanel = twAdvancedSearchPanel; @@ -98,8 +99,7 @@ public boolean isCellEditable(int row, int col) { return col == COL_QTY; } - // fill table with values - public void setData(Vector wps) { + public void setData(List wps) { weapons = wps; qty = new int[wps.size()]; Arrays.fill(qty, 1); @@ -107,7 +107,7 @@ public void setData(Vector wps) { } public WeaponType getWeaponTypeAt(int row) { - return weapons.elementAt(row); + return weapons.get(row); } @Override @@ -115,7 +115,7 @@ public Object getValueAt(int row, int col) { if (row >= weapons.size()) { return null; } - WeaponType wp = weapons.elementAt(row); + WeaponType wp = weapons.get(row); return switch (col) { case COL_QTY -> qty[row] + ""; case COL_NAME -> wp.getName(); diff --git a/megamek/src/megamek/common/MekSearchFilter.java b/megamek/src/megamek/common/MekSearchFilter.java index b3c86d9e5e..073ac85774 100644 --- a/megamek/src/megamek/common/MekSearchFilter.java +++ b/megamek/src/megamek/common/MekSearchFilter.java @@ -21,7 +21,6 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Vector; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -232,7 +231,7 @@ public MekSearchFilter(MekSearchFilter sf) { /** * Creates an Expressiontree from a collection of tokens. */ - public void createFilterExpressionFromTokens(List toks) throws FilterParsingException { + public void createFilterExpressionFromTokens(List toks) throws FilterParsingException { equipmentCriteria = new ExpressionTree(); if (!toks.isEmpty()) { equipmentCriteria.root = createFTFromTokensRecursively(toks.iterator(), null); @@ -242,14 +241,14 @@ public void createFilterExpressionFromTokens(List toks) throws Fil } } - private ExpNode createFTFromTokensRecursively(Iterator toks, + private ExpNode createFTFromTokensRecursively(Iterator toks, ExpNode currNode) { // Base case. We're out of tokens, so we're done. if (!toks.hasNext()) { return currNode; } - FilterTokens filterTok = toks.next(); + FilterToken filterTok = toks.next(); // Parsing Parenthesis if (filterTok instanceof ParensFT) { @@ -273,8 +272,8 @@ private ExpNode createFTFromTokensRecursively(Iterator toks, } // Parsing an Operation - if (filterTok instanceof OperationFT) { - OperationFT ft = (OperationFT) filterTok; + if (filterTok instanceof OperatorFT) { + OperatorFT ft = (OperatorFT) filterTok; ExpNode newNode = new ExpNode(); // If currNode is null, we came from a right paren if (currNode == null) { @@ -317,11 +316,11 @@ private ExpNode createFTFromTokensRecursively(Iterator toks, } // Parsing an Operand - if (filterTok instanceof EquipmentFT) { + if (filterTok instanceof EquipmentTypeFT) { if (currNode == null) { currNode = new ExpNode(); } - EquipmentFT ft = (EquipmentFT) filterTok; + EquipmentTypeFT ft = (EquipmentTypeFT) filterTok; ExpNode newChild = new ExpNode(ft.internalName, ft.qty); currNode.children.add(newChild); return createFTFromTokensRecursively(toks, currNode);