diff --git a/megamek/i18n/megamek/client/messages.properties b/megamek/i18n/megamek/client/messages.properties
index 74e35376313..0c3d2477ca6 100644
--- a/megamek/i18n/megamek/client/messages.properties
+++ b/megamek/i18n/megamek/client/messages.properties
@@ -2162,6 +2162,7 @@ MekSelectorDialog.Search.ArmorType=Armor Type:
MekSelectorDialog.Search.Any=Any
MekSelectorDialog.Search.or=Or
MekSelectorDialog.Search.and=And
+MekSelectorDialog.Search.Combine=Note: TW and AS search filters can be used at the same time!
MekSelectorDialog.Search.AtLeast=at least
MekSelectorDialog.Search.EqualTo=equal to
MekSelectorDialog.Search.NoMoreThan=no more than
@@ -2174,7 +2175,7 @@ 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=Weapon Type
+MekSelectorDialog.Search.WeaponClass=Equipment Group
MekSelectorDialog.Search.Weapons=Weapons
MekSelectorDialog.Search.Equipment=Equipment
MekSelectorDialog.Search.Year=Design year:
diff --git a/megamek/src/megamek/client/ui/advancedsearch/ASAdvancedSearchPanel.java b/megamek/src/megamek/client/ui/advancedsearch/ASAdvancedSearchPanel.java
index bc2b37d913f..29dee41b274 100644
--- a/megamek/src/megamek/client/ui/advancedsearch/ASAdvancedSearchPanel.java
+++ b/megamek/src/megamek/client/ui/advancedsearch/ASAdvancedSearchPanel.java
@@ -571,6 +571,7 @@ private void updateEnabled() {
pvTo.setEnabled(usePV.isSelected());
mvBetween.setEnabled(useMV.isSelected());
+ mvMode.setEnabled(useMV.isSelected());
mvFrom.setEnabled(useMV.isSelected());
mvAnd.setEnabled(useMV.isSelected());
mvTo.setEnabled(useMV.isSelected());
diff --git a/megamek/src/megamek/client/ui/advancedsearch/AdvancedSearchDialog2.java b/megamek/src/megamek/client/ui/advancedsearch/AdvancedSearchDialog2.java
index 6f46b8e51bc..2bd98d2cc28 100644
--- a/megamek/src/megamek/client/ui/advancedsearch/AdvancedSearchDialog2.java
+++ b/megamek/src/megamek/client/ui/advancedsearch/AdvancedSearchDialog2.java
@@ -18,6 +18,10 @@
*/
package megamek.client.ui.advancedsearch;
+import com.formdev.flatlaf.FlatClientProperties;
+import com.formdev.flatlaf.FlatIconColors;
+import com.formdev.flatlaf.extras.FlatSVGIcon;
+import com.formdev.flatlaf.extras.components.FlatButton;
import megamek.client.ui.Messages;
import megamek.client.ui.baseComponents.AbstractButtonDialog;
import megamek.client.ui.swing.ButtonEsc;
@@ -45,7 +49,7 @@ public AdvancedSearchDialog2(JFrame parent, int allowedYear) {
year = allowedYear;
totalWarTab = new TWAdvancedSearchPanel(year);
advancedSearchPane.addTab("Total Warfare", totalWarTab);
- advancedSearchPane.addTab("Alpha Strike", alphaStrikeTab);
+ advancedSearchPane.addTab("Alpha Strike", new TWAdvancedSearchPanel.StandardScrollPane(alphaStrikeTab));
initialize();
}
@@ -74,13 +78,24 @@ protected JPanel createButtonPanel() {
okButton.addActionListener(this::okButtonActionPerformed);
getRootPane().setDefaultButton(okButton);
+ JPanel notePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
+ notePanel.add(Box.createHorizontalStrut(20));
+ var noteLabel = new JLabel(Messages.getString("MekSelectorDialog.Search.Combine"));
+ noteLabel.putClientProperty(FlatClientProperties.STYLE, "foreground: mix($Label.foreground, #afa, 60%)");
+ notePanel.add(noteLabel);
+
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 20, 0));
- buttonPanel.setBorder(BorderFactory.createCompoundBorder(
- new MatteBorder(1, 0, 0, 0, UIManager.getColor("Separator.foreground")),
- new EmptyBorder(10, 0, 10, 0)));
buttonPanel.add(okButton);
buttonPanel.add(cancelButton);
- return buttonPanel;
+
+ JPanel outerPanel = new JPanel(new GridLayout(1,1));
+ outerPanel.setBorder(BorderFactory.createCompoundBorder(
+ new MatteBorder(1, 0, 0, 0, UIManager.getColor("Separator.foreground")),
+ new EmptyBorder(10, 0, 10, 0)));
+ outerPanel.add(notePanel);
+ outerPanel.add(buttonPanel);
+
+ return outerPanel;
}
@Override
diff --git a/megamek/src/megamek/client/ui/advancedsearch/AdvancedSearchEquipmentClass.java b/megamek/src/megamek/client/ui/advancedsearch/AdvancedSearchEquipmentClass.java
new file mode 100644
index 00000000000..568cebc7e35
--- /dev/null
+++ b/megamek/src/megamek/client/ui/advancedsearch/AdvancedSearchEquipmentClass.java
@@ -0,0 +1,99 @@
+/*
+ * 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 java.util.Locale;
+
+enum AdvancedSearchEquipmentClass {
+ EMPTY, AUTOCANNON, RAC, ULTRA, LIGHT, MACHINE_GUN, GAUSS, BALLISTIC, PLASMA, ENERGY, LASER, PULSE, RE_ENGINEERED, PPC, TASER, FLAMER, MISSILE,
+ LRM, MRM, SRM, PHYSICAL, AMS, PRACTICAL_PHYSICAL, INFANTRY_SUIT, PROBE;
+
+ public boolean matches(String name) {
+ if (this == EMPTY) {
+ return true;
+ }
+ name = name.toLowerCase(Locale.ROOT);
+ if (name.contains("ammo")) {
+ return false;
+ }
+ if (this == PHYSICAL) {
+ return name.contains("backhoe") || name.contains("saw") || name.contains("whip") || name.contains("claw") ||
+ name.contains("combine") || name.contains("flail") || name.contains("hatchet") || name.contains("driver") ||
+ name.contains("lance") || name.contains("mace") || name.contains("drill") || name.contains("ram") ||
+ name.contains("blade") || name.contains("cutter") || name.contains("shield") || name.contains("welder") ||
+ name.contains("sword") || name.contains("talons") || name.contains("wrecking");
+ } else if (this == PRACTICAL_PHYSICAL) {
+ return name.contains("claw") || name.contains("flail") || name.contains("hatchet") || name.contains("lance")
+ || name.contains("mace") || name.contains("blade") || name.contains("shield") || name.contains("sword")
+ || name.contains("talons");
+ } else if (this == MISSILE) {
+ return name.contains("lrm") || name.contains("mrm") || name.contains("srm");
+ } else if (this == RE_ENGINEERED) {
+ return name.contains("engineered");
+ } else if (this == ENERGY) {
+ return LASER.matches(name) || PPC.matches(name) || FLAMER.matches(name);
+ } else if (this == MACHINE_GUN) {
+ return (name.contains("mg") || name.contains("machine")) && !name.contains("ammo");
+ } else if (this == BALLISTIC) {
+ return AUTOCANNON.matches(name) || GAUSS.matches(name) || MACHINE_GUN.matches(name);
+ } else if (this == RAC) {
+ return name.contains("rotary");
+ } else if (this == ULTRA) {
+ return name.contains("ultraa");
+ } else if (this == INFANTRY_SUIT) {
+ return (name.contains("suit") || name.contains(" kit") || name.contains(", standard") || name.contains(", concealed")
+ || name.contains("clothing") || name.contains("vest") || name.contains("chainmail") || name.contains("parka"))
+ && !name.contains("ecm") && !name.contains("generic") && !name.contains("suite");
+ } else if (this == AMS) {
+ return name.contains("ams") || name.contains("antimiss");
+ } else if (this == PROBE) {
+ return name.contains("probe");
+ } else if (name.contains(name().toLowerCase(Locale.ROOT)) && !name.contains("ammo")) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return switch (this) {
+ case EMPTY -> "";
+ case AUTOCANNON -> "Autocannon";
+ case ULTRA -> "Ultra A/C";
+ case LIGHT -> "Light A/C";
+ case MACHINE_GUN -> "Machine Gun";
+ case GAUSS -> "Gauss";
+ case BALLISTIC -> "Ballistic";
+ case PLASMA -> "Plasma";
+ case ENERGY -> "Energy";
+ case LASER -> "Laser";
+ case PULSE -> "Pulse Laser";
+ case RE_ENGINEERED -> "Re-Engineered Laser";
+ case PPC -> "PPC";
+ case TASER -> "Taser";
+ case FLAMER -> "Flamer";
+ case MISSILE -> "Missile";
+ case PHYSICAL -> "Physical (inc. industrial equipment)";
+ case PRACTICAL_PHYSICAL -> "Physical (weapons only)";
+ case INFANTRY_SUIT -> "Infantry Armor Suits";
+ case PROBE -> "Active Probes";
+ default -> super.toString();
+ };
+ }
+}
diff --git a/megamek/src/megamek/client/ui/advancedsearch/MekSearchFilter.java b/megamek/src/megamek/client/ui/advancedsearch/MekSearchFilter.java
index 657fd8ef067..490fcd74c9c 100644
--- a/megamek/src/megamek/client/ui/advancedsearch/MekSearchFilter.java
+++ b/megamek/src/megamek/client/ui/advancedsearch/MekSearchFilter.java
@@ -331,7 +331,7 @@ private ExpNode createFTFromTokensRecursively(Iterator toks, ExpNod
currNode = new ExpNode();
}
- ExpNode newChild = new ExpNode(ft.weaponClass, ft.qty, ft.atleast);
+ ExpNode newChild = new ExpNode(ft.equipmentClass, ft.qty, ft.atleast);
currNode.children.add(newChild);
return createFTFromTokensRecursively(toks, currNode);
}
@@ -969,7 +969,7 @@ private boolean evaluate(List eq, List qty, ExpNode n) {
// Base Case: See if any of the equipment matches the leaf node in
// sufficient quantity
if (n.children.isEmpty()) {
- if (n.weaponClass != null) {
+ if (n.equipmentClass != null) {
// Since weapon classes can match across different types of equipment, we have
// to sum up
// all equipment that matches the weaponClass value.
@@ -981,7 +981,7 @@ private boolean evaluate(List eq, List qty, ExpNode n) {
// Now, stream that map, filtering on a match with the WeaponClass, then extract
// the quantities and sum them up.
int total = nameQtyPairs.stream()
- .filter(p -> n.weaponClass.matches(p.getKey()))
+ .filter(p -> n.equipmentClass.matches(p.getKey()))
.map(Map.Entry::getValue)
.reduce(0, Integer::sum);
@@ -1088,7 +1088,7 @@ public static class ExpNode {
public ExpNode parent;
public BoolOp operation;
public String name;
- public WeaponClass weaponClass;
+ public AdvancedSearchEquipmentClass equipmentClass;
public int qty;
public List children;
public boolean atleast;
@@ -1111,7 +1111,7 @@ public ExpNode(ExpNode e) {
// if (e.name != null) {
name = e.name;
// }
- weaponClass = e.weaponClass;
+ equipmentClass = e.equipmentClass;
Iterator nodeIter = e.children.iterator();
children = new LinkedList<>();
while (nodeIter.hasNext()) {
@@ -1122,17 +1122,17 @@ public ExpNode(ExpNode e) {
public ExpNode(String n, int q, boolean atleast) {
parent = null;
name = n;
- weaponClass = null;
+ equipmentClass = null;
qty = q;
operation = BoolOp.NOP;
children = new LinkedList<>();
this.atleast = atleast;
}
- public ExpNode(WeaponClass n, int q, boolean atleast) {
+ public ExpNode(AdvancedSearchEquipmentClass n, int q, boolean atleast) {
parent = null;
name = null;
- weaponClass = n;
+ equipmentClass = n;
qty = q;
operation = BoolOp.NOP;
children = new LinkedList<>();
@@ -1149,11 +1149,11 @@ public String toString() {
} else {
return qty + " " + name + "s";
}
- } else if (weaponClass != null) {
+ } else if (equipmentClass != null) {
if (qty == 1) {
- return qty + " " + weaponClass.toString();
+ return qty + " " + equipmentClass.toString();
} else {
- return qty + " " + weaponClass.toString() + "s";
+ return qty + " " + equipmentClass.toString() + "s";
}
}
}
diff --git a/megamek/src/megamek/client/ui/advancedsearch/QuirksSearchTab.java b/megamek/src/megamek/client/ui/advancedsearch/QuirksSearchTab.java
index 0982e7fd925..639324b7c61 100644
--- a/megamek/src/megamek/client/ui/advancedsearch/QuirksSearchTab.java
+++ b/megamek/src/megamek/client/ui/advancedsearch/QuirksSearchTab.java
@@ -48,7 +48,7 @@ class QuirksSearchTab extends JPanel {
listWeaponQuirkType = new TriStateItemList(new WeaponQuirks(), 17);
JPanel unitQuirksPanel = new JPanel(new BorderLayout());
- JPanel quirkIEPanel = new JPanel(new FlowLayout());
+ JPanel quirkIEPanel = new JPanel();
quirkIEPanel.add(new JLabel(Messages.getString("MekSelectorDialog.Search.Quirk")));
quirkIEPanel.add(Box.createHorizontalStrut(15));
quirkIEPanel.add(new JLabel("\u2611"));
@@ -57,9 +57,12 @@ class QuirksSearchTab extends JPanel {
quirkIEPanel.add(cQuirkExclude);
unitQuirksPanel.add(quirkIEPanel, BorderLayout.NORTH);
unitQuirksPanel.add(new JScrollPane(listQuirkType.getComponent()), BorderLayout.CENTER);
+ JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
+ buttonPanel.add(btnQuirksClear);
+ unitQuirksPanel.add(buttonPanel, BorderLayout.SOUTH);
JPanel weaponQuirkPanel = new JPanel(new BorderLayout());
- JPanel weaponQuirkIEPanel = new JPanel(new FlowLayout());
+ JPanel weaponQuirkIEPanel = new JPanel();
weaponQuirkIEPanel.add(new JLabel(Messages.getString("MekSelectorDialog.Search.WeaponQuirk")));
weaponQuirkIEPanel.add(Box.createHorizontalStrut(15));
weaponQuirkIEPanel.add(new JLabel("\u2611"));
diff --git a/megamek/src/megamek/client/ui/advancedsearch/WeaponClass.java b/megamek/src/megamek/client/ui/advancedsearch/WeaponClass.java
deleted file mode 100644
index 3ce1377c355..00000000000
--- a/megamek/src/megamek/client/ui/advancedsearch/WeaponClass.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * 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;
-
-enum WeaponClass {
- AUTOCANNON {
- public String toString() {
- return "Autocannon";
- }
- },
- RAC,
- ULTRA {
- public String toString() {
- return "Ultra A/C";
- }
- },
- LIGHT {
- public String toString() {
- return "Light A/C";
- }
- },
- MACHINE_GUN {
- public String toString() {
- return "Machine Gun";
- }
- },
- GAUSS {
- public String toString() {
- return "Gauss";
- }
- },
- BALLISTIC {
- public String toString() {
- return "Ballistic";
- }
- },
- PLASMA {
- public String toString() {
- return "Plasma";
- }
- },
- ENERGY {
- public String toString() {
- return "Energy";
- }
- },
- LASER {
- public String toString() {
- return "Laser";
- }
- },
- PULSE {
- public String toString() {
- return "Pulse Laser";
- }
- },
- RE_ENGINEERED {
- public String toString() {
- return "Re-Engineered Laser";
- }
- },
- PPC {
- public String toString() {
- return "PPC";
- }
- },
- TASER {
- public String toString() {
- return "Taser";
- }
- },
- FLAMER {
- public String toString() {
- return "Flamer";
- }
- },
- MISSILE {
- public String toString() {
- return "Missile";
- }
- },
- LRM,
- MRM,
- SRM,
- PHYSICAL {
- public String toString() {
- return "Physical (inc. industrial equipment)";
- }
- },
- AMS,
- PRACTICAL_PHYSICAL {
- public String toString() {
- return "Physical (weapons only)";
- }
- };
-
- public boolean matches(String name) {
- if (name.toLowerCase().contains("ammo")) {
- return false;
- }
- if (this == PHYSICAL) {
- String lName = name.toLowerCase();
-
- if (lName.contains("backhoe") ||
- lName.contains("saw") ||
- lName.contains("whip") ||
- lName.contains("claw") ||
- lName.contains("combine") ||
- lName.contains("flail") ||
- lName.contains("hatchet") ||
- lName.contains("driver") ||
- lName.contains("lance") ||
- lName.contains("mace") ||
- lName.contains("drill") ||
- lName.contains("ram") ||
- lName.contains("blade") ||
- lName.contains("cutter") ||
- lName.contains("shield") ||
- lName.contains("welder") ||
- lName.contains("sword") ||
- lName.contains("talons") ||
- lName.contains("wrecking")) {
- return true;
- }
- } else if (this == PRACTICAL_PHYSICAL) {
- String lName = name.toLowerCase();
-
- if (lName.contains("claw") ||
- lName.contains("flail") ||
- lName.contains("hatchet") ||
- lName.contains("lance") ||
- lName.contains("mace") ||
- lName.contains("blade") ||
- lName.contains("shield") ||
- lName.contains("sword") ||
- lName.contains("talons")) {
- return true;
- }
- } else if (this == MISSILE) {
- if ((name.toLowerCase().contains("lrm") ||
- name.toLowerCase().contains("mrm") ||
- name.toLowerCase().contains("srm")) &&
- !name.toLowerCase().contains("ammo")) {
- return true;
- }
- } else if (this == RE_ENGINEERED) {
- if (name.toLowerCase().contains("engineered")) {
- return true;
- }
- } else if (this == ENERGY) {
- if (WeaponClass.LASER.matches(name) || WeaponClass.PPC.matches(name) || WeaponClass.FLAMER.matches(name)) {
- return true;
- }
- } else if (this == MACHINE_GUN) {
- if ((name.toLowerCase().contains("mg") || name.toLowerCase().contains("machine")) && !name.toLowerCase().contains("ammo")) {
- return true;
- }
- } else if (this == BALLISTIC) {
- return WeaponClass.AUTOCANNON.matches(name) ||
- WeaponClass.GAUSS.matches(name) ||
- WeaponClass.MACHINE_GUN.matches(name);
- } else if (this == RAC) {
- if (name.toLowerCase().contains("rotary")) {
- return true;
- }
- } else if (this == ULTRA) {
- if (name.toLowerCase().contains("ultraa")) {
- return true;
- }
- } else if (name.toLowerCase().contains(name().toLowerCase()) && !name.toLowerCase().contains("ammo")) {
- return true;
- }
- return false;
- }
-}
diff --git a/megamek/src/megamek/client/ui/advancedsearch/WeaponClassFT.java b/megamek/src/megamek/client/ui/advancedsearch/WeaponClassFT.java
index 14d0c988e1b..90a148bc44c 100644
--- a/megamek/src/megamek/client/ui/advancedsearch/WeaponClassFT.java
+++ b/megamek/src/megamek/client/ui/advancedsearch/WeaponClassFT.java
@@ -24,20 +24,20 @@
*/
class WeaponClassFT extends EquipmentFilterToken {
- WeaponClass weaponClass;
+ AdvancedSearchEquipmentClass equipmentClass;
- WeaponClassFT(WeaponClass in_class, int in_qty) {
+ WeaponClassFT(AdvancedSearchEquipmentClass in_class, int in_qty) {
this(in_class, in_qty, true);
}
- WeaponClassFT(WeaponClass in_class, int in_qty, boolean atleast) {
- weaponClass = in_class;
+ WeaponClassFT(AdvancedSearchEquipmentClass in_class, int in_qty, boolean atleast) {
+ equipmentClass = in_class;
qty = in_qty;
this.atleast = atleast;
}
@Override
public String toString() {
- return (atleast ? "" : "less than ") + qty + " " + weaponClass.toString() + ((qty != 1) ? "s" : "");
+ return (atleast ? "" : "less than ") + qty + " " + equipmentClass.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 f40a327fc28..497e4d7ea3a 100644
--- a/megamek/src/megamek/client/ui/advancedsearch/WeaponSearchTab.java
+++ b/megamek/src/megamek/client/ui/advancedsearch/WeaponSearchTab.java
@@ -41,24 +41,21 @@ class WeaponSearchTab extends JPanel implements KeyListener, DocumentListener, F
final List filterTokens = new ArrayList<>();
- 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"));
- final JButton btnBack = new JButton("Back");
- final JLabel lblWEEqExpTxt = new JLabel(Messages.getString("MekSelectorDialog.Search.FilterExpression"));
+ private final JButton btnLeftParen = new JButton("(");
+ private final JButton btnRightParen = new JButton(")");
+ private final JSpinner equipmentCount;
+ private final JToggleButton btnLessThan = new JToggleButton("<");
+ private final JToggleButton btnAtLeast = new JToggleButton("\u2265");
+ private final JButton btnAdd = new JButton(Messages.getString("MekSelectorDialog.Search.add"));
+ private final JButton btnAddMultiOr = new JButton("Add [OR]");
+ private final JButton btnAddMultiAnd = new JButton("Add [AND]");
+ private final JButton btnAnd = new JButton(Messages.getString("MekSelectorDialog.Search.and"));
+ private final JButton btnOr = new JButton(Messages.getString("MekSelectorDialog.Search.or"));
+ private final JButton btnClear = new JButton(Messages.getString("MekSelectorDialog.Reset"));
+ private final JButton btnBack = new JButton("Back");
+ private 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 lblUnitType = new JLabel(Messages.getString("MekSelectorDialog.Search.UnitType"));
private final JButton btnUnitTypeAll = new JButton("All");
private final JToggleButton btnUnitTypeMek = new JToggleButton("Mek");
private final JToggleButton btnUnitTypeVee = new JToggleButton("Veh");
@@ -69,12 +66,9 @@ class WeaponSearchTab extends JPanel implements KeyListener, DocumentListener, F
private final List unitTypeButtons =
List.of(btnUnitTypeMek, btnUnitTypePM, btnUnitTypeBA, btnUnitTypeCI, btnUnitTypeAero, btnUnitTypeVee);
- final JLabel lblTechClass = new JLabel(Messages.getString("MekSelectorDialog.Search.TechClass"));
private final JToggleButton btnTechClassIS = new JToggleButton("Inner Sphere");
private final JToggleButton btnTechClassClan = new JToggleButton("Clan");
- final JLabel lblTechLevelBase = new JLabel(Messages.getString("MekSelectorDialog.Search.TechLevel"));
-// final JList techLevelSelector = new JList<>();
private final JButton btnTechLevelOfficial = new JButton("Official");
private final JToggleButton btnTechLevelIntro = new JToggleButton("Intro");
private final JToggleButton btnTechLevelStd = new JToggleButton("Standard");
@@ -84,25 +78,19 @@ class WeaponSearchTab extends JPanel implements KeyListener, DocumentListener, F
private final List techLevelButtons =
List.of(btnTechLevelIntro, btnTechLevelStd, btnTechLevelAdv, btnTechLevelExp, btnTechLevelUnoff);
- final JLabel tableFilterTextLabel = new JLabel(Messages.getString("MekSelectorDialog.Search.TableFilter"));
- final JTextField tableFilterText = new JTextField(10);
+ private final JTextField tableFilterText = new JTextField(10);
private final JButton filterClearButton = new JButton("X");
+ private final JComboBox weaponClassFilter = new JComboBox<>(AdvancedSearchEquipmentClass.values());
- final JLabel lblWeapons = new JLabel(Messages.getString("MekSelectorDialog.Search.Weapons"));
- final JScrollPane scrTableWeapons = new JScrollPane();
- final SearchableTable tblWeapons;
- final WeaponsTableModel weaponsModel;
- final TableRowSorter weaponsSorter;
+ private final SearchableTable tblWeapons;
+ private final WeaponsTableModel weaponsModel;
+ private final TableRowSorter weaponsSorter;
- final JLabel lblEquipment = new JLabel(Messages.getString("MekSelectorDialog.Search.Equipment"));
- final JScrollPane scrTableEquipment = new JScrollPane();
- final SearchableTable tblEquipment;
- final EquipmentTableModel equipmentModel;
- final TableRowSorter equipmentSorter;
+ private final SearchableTable tblEquipment;
+ private final EquipmentTableModel equipmentModel;
+ private final TableRowSorter equipmentSorter;
- final JLabel lblWeaponClass = new JLabel(Messages.getString("MekSelectorDialog.Search.WeaponClass"));
- final JSpinner weaponClassCount;
- final JComboBox weaponClassChooser;
+ private final JComboBox weaponClassChooser = new JComboBox<>(AdvancedSearchEquipmentClass.values());
private JComponent focusedSelector = null;
private final TWAdvancedSearchPanel parentPanel;
@@ -132,13 +120,6 @@ class WeaponSearchTab extends JPanel implements KeyListener, DocumentListener, F
btnUnitTypeAll.addActionListener(e -> allUnitTypesClicked());
unitTypeButtons.forEach(button -> button.setSelected(true));
-// 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());
-
btnTechClassClan.setSelected(true);
btnTechClassIS.setSelected(true);
@@ -146,9 +127,7 @@ class WeaponSearchTab extends JPanel implements KeyListener, DocumentListener, F
techLevelButtons.forEach(button -> button.setSelected(button != btnTechLevelUnoff));
addToggleActionListeners();
- // Set up Weapon Class chooser
- weaponClassCount = new JSpinner(new SpinnerNumberModel(1, 1, 20, 1));
- weaponClassChooser = new JComboBox<>(WeaponClass.values());
+ equipmentCount = new JSpinner(new SpinnerNumberModel(1, 1, 20, 1));
weaponClassChooser.addFocusListener(this);
// Setup Weapons Table
@@ -181,8 +160,6 @@ public Dimension getPreferredScrollableViewportSize() {
tblWeapons.getColumnModel().getColumn(i).setPreferredWidth(weaponsModel.getPreferredWidth(i));
}
- scrTableWeapons.setViewportView(tblWeapons);
-
// Setup Equipment Table
equipmentModel = new EquipmentTableModel(parentPanel);
tblEquipment = new SearchableTable(equipmentModel, EquipmentTableModel.COL_NAME) {
@@ -207,8 +184,6 @@ public Dimension getPreferredScrollableViewportSize() {
tblEquipment.getColumnModel().getColumn(1).setCellRenderer(costRenderer);
tblEquipment.getColumnModel().getColumn(2).setCellRenderer(techBaseRenderer);
- scrTableEquipment.setViewportView(tblEquipment);
-
// Populate Tables
populateWeaponsAndEquipmentChoices();
@@ -234,6 +209,7 @@ public Dimension getPreferredScrollableViewportSize() {
filterClearButton.addActionListener(e -> tableFilterText.setText(""));
filterClearButton.setToolTipText("Clear the filter text");
filterClearButton.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
+ weaponClassFilter.addActionListener(e -> filterTables());
JPanel upperPanel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
@@ -241,10 +217,11 @@ public Dimension getPreferredScrollableViewportSize() {
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.WEST;
gbc.gridwidth = 1;
- gbc.insets = new Insets(5, 0, 5, 0);
- upperPanel.add(lblTechClass, gbc);
+ gbc.insets = new Insets(2, 0, 2, 0);
+ upperPanel.add(new JLabel(Messages.getString("MekSelectorDialog.Search.TechClass")), gbc);
gbc.gridwidth = GridBagConstraints.REMAINDER;
JPanel techClassButtonPanel = new JPanel(new GridLayout(1, 2, 10, 0));
+ techClassButtonPanel.setBorder(new EmptyBorder(0, 20, 0, 0));
gbc.weightx = 0;
techClassButtonPanel.add(btnTechClassIS);
techClassButtonPanel.add(btnTechClassClan);
@@ -253,9 +230,10 @@ public Dimension getPreferredScrollableViewportSize() {
gbc.gridy++;
gbc.gridwidth = 1;
gbc.weightx = 0;
- upperPanel.add(lblUnitType, gbc);
+ upperPanel.add(new JLabel(Messages.getString("MekSelectorDialog.Search.UnitType")), gbc);
gbc.gridwidth = GridBagConstraints.REMAINDER;
JPanel unitTypeButtonPanel = new JPanel(new GridLayout(1, 7, 10, 0));
+ unitTypeButtonPanel.setBorder(new EmptyBorder(0, 20, 0, 0));
unitTypeButtonPanel.add(btnUnitTypeAll);
unitTypeButtonPanel.add(btnUnitTypeMek);
unitTypeButtonPanel.add(btnUnitTypeVee);
@@ -268,9 +246,10 @@ public Dimension getPreferredScrollableViewportSize() {
gbc.gridy++;
gbc.gridwidth = 1;
gbc.weightx = 0;
- upperPanel.add(lblTechLevelBase, gbc);
+ upperPanel.add(new JLabel(Messages.getString("MekSelectorDialog.Search.TechLevel")), gbc);
gbc.gridwidth = GridBagConstraints.REMAINDER;
JPanel techLevelButtonPanel = new JPanel(new GridLayout(1, 6, 10, 0));
+ techLevelButtonPanel.setBorder(new EmptyBorder(0, 20, 0, 0));
techLevelButtonPanel.add(btnTechLevelOfficial);
techLevelButtonPanel.add(btnTechLevelIntro);
techLevelButtonPanel.add(btnTechLevelStd);
@@ -281,9 +260,12 @@ public Dimension getPreferredScrollableViewportSize() {
gbc.weightx = 0;
JPanel filterPanel = new JPanel();
- filterPanel.add(tableFilterTextLabel);
+ filterPanel.add(new JLabel(Messages.getString("MekSelectorDialog.Search.TableFilter")));
filterPanel.add(tableFilterText);
filterPanel.add(filterClearButton);
+ filterPanel.add(Box.createHorizontalStrut(10));
+ filterPanel.add(new JLabel("Equipment Group:"));
+ filterPanel.add(weaponClassFilter);
gbc.gridy++;
gbc.gridwidth = GridBagConstraints.REMAINDER;
upperPanel.add(filterPanel, gbc);
@@ -292,65 +274,67 @@ public Dimension getPreferredScrollableViewportSize() {
gbc.gridx = GridBagConstraints.RELATIVE;
gbc.gridy++;
gbc.anchor = GridBagConstraints.WEST;
- upperPanel.add(lblWeapons, gbc);
+ upperPanel.add(new JLabel(Messages.getString("MekSelectorDialog.Search.Weapons")), gbc);
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.anchor = GridBagConstraints.CENTER;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.gridy++;
- upperPanel.add(scrTableWeapons, gbc);
+ upperPanel.add(new JScrollPane(tblWeapons), gbc);
gbc.gridy++;
- upperPanel.add(Box.createVerticalStrut(20), gbc);
+ upperPanel.add(Box.createVerticalStrut(10), gbc);
gbc.fill = GridBagConstraints.NONE;
gbc.gridwidth = 1;
gbc.gridy++;
gbc.anchor = GridBagConstraints.WEST;
- upperPanel.add(lblEquipment, gbc);
+ upperPanel.add(new JLabel(Messages.getString("MekSelectorDialog.Search.Equipment")), gbc);
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.anchor = GridBagConstraints.CENTER;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.gridy++;
- upperPanel.add(scrTableEquipment, gbc);
+ upperPanel.add(new JScrollPane(tblEquipment), gbc);
gbc.gridy++;
- upperPanel.add(Box.createVerticalStrut(20), gbc);
+ upperPanel.add(Box.createVerticalStrut(10), gbc);
- gbc.gridwidth = 1;
gbc.gridy++;
gbc.anchor = GridBagConstraints.WEST;
gbc.insets = new Insets(0, 0, 0, 20);
- upperPanel.add(lblWeaponClass, gbc);
+ upperPanel.add(new JLabel(Messages.getString("MekSelectorDialog.Search.WeaponClass")), gbc);
gbc.gridy++;
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);
- btnPanel.add(btnOr);
- btnPanel.add(btnBack);
- btnPanel.add(btnClear);
+ JPanel addBtnPanel = new JPanel();
+ addBtnPanel.add(equipmentCount);
+ addBtnPanel.add(btnAtLeast);
+ addBtnPanel.add(btnLessThan);
+ addBtnPanel.add(btnAdd);
+ addBtnPanel.add(btnAddMultiAnd);
+ addBtnPanel.add(btnAddMultiOr);
+
+ JPanel controlBtnPanel = new JPanel();
+ controlBtnPanel.add(btnLeftParen);
+ controlBtnPanel.add(btnRightParen);
+ controlBtnPanel.add(btnAnd);
+ controlBtnPanel.add(btnOr);
+ controlBtnPanel.add(btnBack);
+ controlBtnPanel.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);
+ filterExpressionPanel.add(new JScrollPane(txtWEEqExp));
Box filterAssemblyPanel = Box.createVerticalBox();
filterAssemblyPanel.add(Box.createVerticalStrut(10));
- filterAssemblyPanel.add(btnPanel);
+ filterAssemblyPanel.add(addBtnPanel);
+ filterAssemblyPanel.add(controlBtnPanel);
filterAssemblyPanel.add(filterExpressionPanel);
filterAssemblyPanel.add(Box.createVerticalStrut(10));
@@ -374,7 +358,9 @@ public boolean include(Entry extends WeaponsTableModel, ? extends Integer> ent
boolean unitTypeMatch = matchUnitTypeToWeapon(wp);
boolean textFilterMatch = (tableFilterText.getText() == null) || (tableFilterText.getText().length() < 2)
|| matchWeaponTextFilter(entry);
- return techLvlMatch && techClassMatch && unitTypeMatch && textFilterMatch;
+ boolean equipmentClassMatch = (weaponClassFilter.getSelectedItem() instanceof AdvancedSearchEquipmentClass equipmentclass)
+ && equipmentclass.matches(wp.getInternalName());
+ return techLvlMatch && techClassMatch && unitTypeMatch && textFilterMatch && equipmentClassMatch;
}
};
} catch (PatternSyntaxException ignored) {
@@ -395,7 +381,9 @@ public boolean include(Entry extends EquipmentTableModel, ? extends Integer> e
boolean unitTypeMatch = matchUnitTypeToMisc(eq);
boolean textFilterMatch = (tableFilterText.getText() == null) || (tableFilterText.getText().length() < 2)
|| matchEquipmentTextFilter(entry);
- return techLvlMatch && techClassMatch && unitTypeMatch && textFilterMatch;
+ boolean equipmentClassMatch = (weaponClassFilter.getSelectedItem() instanceof AdvancedSearchEquipmentClass equipmentclass)
+ && equipmentclass.matches(eq.getInternalName());
+ return techLvlMatch && techClassMatch && unitTypeMatch && textFilterMatch && equipmentClassMatch;
}
};
} catch (PatternSyntaxException ignored) {
@@ -532,7 +520,7 @@ private void addWeaponFilter(int row, int qty, boolean atleast) {
private void addFilter(boolean and) {
boolean atleast = btnAtLeast.isSelected();
- int qty = (int) weaponClassCount.getValue();
+ int qty = (int) equipmentCount.getValue();
if (focusedSelector == tblEquipment) {
int[] rows = tblEquipment.getSelectedRows();
if (rows.length == 1) {
@@ -563,7 +551,7 @@ private void addFilter(boolean and) {
addFilterToken(new RightParensFilterToken());
}
} else if ((focusedSelector == weaponClassChooser) && (weaponClassChooser.getSelectedItem() != null)) {
- filterTokens.add(new WeaponClassFT((WeaponClass) weaponClassChooser.getSelectedItem(), qty, atleast));
+ filterTokens.add(new WeaponClassFT((AdvancedSearchEquipmentClass) weaponClassChooser.getSelectedItem(), qty, atleast));
} else {
// if something else is focused, do nothing
@@ -659,7 +647,8 @@ private void focusWeaponClasschooser() {
}
private boolean hasFocusedSelector() {
- return (focusedSelector == weaponClassChooser) || (focusedSelector == tblEquipment) || (focusedSelector == tblWeapons);
+ return (focusedSelector != null)
+ && ((focusedSelector == weaponClassChooser) || (focusedSelector == tblEquipment) || (focusedSelector == tblWeapons));
}
void adaptTokenButtons() {
@@ -709,6 +698,11 @@ private void backOperation() {
removeToggleActionListeners();
techLevelButtons.forEach(button -> button.setSelected(e.getSource() == button));
addToggleActionListeners();
+ } else if ((source == btnTechClassClan || source == btnTechClassIS) && ((e.getModifiers() & Event.SHIFT_MASK) == 0)) {
+ removeToggleActionListeners();
+ btnTechClassClan.setSelected(source == btnTechClassClan);
+ btnTechClassIS.setSelected(source == btnTechClassIS);
+ addToggleActionListeners();
}
filterTables();
};
diff --git a/megamek/src/megamek/client/ui/swing/util/FlatLafStyleBuilder.java b/megamek/src/megamek/client/ui/swing/util/FlatLafStyleBuilder.java
index b7a4739cf62..557427c2be2 100644
--- a/megamek/src/megamek/client/ui/swing/util/FlatLafStyleBuilder.java
+++ b/megamek/src/megamek/client/ui/swing/util/FlatLafStyleBuilder.java
@@ -18,6 +18,7 @@
*/
package megamek.client.ui.swing.util;
+import com.formdev.flatlaf.FlatClientProperties;
import megamek.common.annotations.Nullable;
import javax.swing.*;
@@ -106,6 +107,6 @@ public void apply(JComponent component) {
if ((fontName != null) && !fontName.isBlank()) {
styleText += " \"" + fontName + "\"";
}
- component.putClientProperty("FlatLaf.style", styleText);
+ component.putClientProperty(FlatClientProperties.STYLE, styleText);
}
}