From e91a87e6b129ceed42926da6a8d35304a32728de Mon Sep 17 00:00:00 2001 From: Carl Spain Date: Tue, 19 Sep 2017 09:08:00 -0500 Subject: [PATCH 01/12] Added two classes to replace unit-specific armor allocation view classes: ArmorLocationView deals with the number of points allocated to one location. ArmorAllocationView positions the location views and shows summary statistics. At this point there are combo boxes to set the armor type for the location if using patchwork armor, but they make the controls too wide and even moving the armor allocation to a separate panel wouldn't change the fact that it looks bad. Committing what's been done so far before changing it. --- .../com/ui/Mek/tabs/StructureTab.java | 71 +++-- .../com/ui/view/ArmorAllocationView.java | 246 ++++++++++++++++ .../com/ui/view/ArmorLocationView.java | 262 ++++++++++++++++++ .../com/ui/view/BAProtoArmorView.java | 2 +- .../com/ui/view/FighterChassisView.java | 2 +- src/megameklab/com/ui/view/HeatSinkView.java | 4 +- src/megameklab/com/ui/view/MVFArmorView.java | 2 +- src/megameklab/com/ui/view/MainUIView.java | 2 +- src/megameklab/com/ui/view/MovementView.java | 12 +- src/megameklab/com/util/UnitUtil.java | 119 +++++++- src/megameklab/resources/Views.properties | 9 + 11 files changed, 687 insertions(+), 44 deletions(-) create mode 100644 src/megameklab/com/ui/view/ArmorAllocationView.java create mode 100644 src/megameklab/com/ui/view/ArmorLocationView.java diff --git a/src/megameklab/com/ui/Mek/tabs/StructureTab.java b/src/megameklab/com/ui/Mek/tabs/StructureTab.java index 988c26374..d73212c17 100644 --- a/src/megameklab/com/ui/Mek/tabs/StructureTab.java +++ b/src/megameklab/com/ui/Mek/tabs/StructureTab.java @@ -52,9 +52,10 @@ import megamek.common.loaders.EntityLoadingException; import megamek.common.verifier.TestEntity; import megameklab.com.ui.EntitySource; -import megameklab.com.ui.Mek.views.ArmorView; import megameklab.com.ui.Mek.views.SummaryView; import megameklab.com.ui.util.TechComboBox; +import megameklab.com.ui.view.ArmorAllocationView; +import megameklab.com.ui.view.ArmorLocationView; import megameklab.com.ui.view.BasicInfoView; import megameklab.com.ui.view.HeatSinkView; import megameklab.com.ui.view.MVFArmorView; @@ -66,27 +67,25 @@ public class StructureTab extends ITab implements BasicInfoView.BasicInfoListener, MekChassisView.MekChassisListener, HeatSinkView.HeatSinkListener, MVFArmorView.ArmorListener, - MovementView.MovementListener { + MovementView.MovementListener, ArmorLocationView.ArmorLocationListener { /** * */ private static final long serialVersionUID = -6756011847500605874L; - BasicInfoView panBasicInfo; - MekChassisView panChassis; - MVFArmorView panArmor; - MovementView panMovement; - HeatSinkView panHeat; - SummaryView panSummary; - - private ArmorView armor; + private BasicInfoView panBasicInfo; + private MekChassisView panChassis; + private MVFArmorView panArmor; + private MovementView panMovement; + private HeatSinkView panHeat; + private SummaryView panSummary; + private ArmorAllocationView panArmorAllocation; RefreshListener refresh = null; JPanel masterPanel; public StructureTab(EntitySource eSource) { super(eSource); - armor = new ArmorView(eSource); setLayout(new BorderLayout()); setUpPanels(); this.add(masterPanel, BorderLayout.CENTER); @@ -100,7 +99,10 @@ private void setUpPanels() { panArmor = new MVFArmorView(panBasicInfo); panMovement = new MovementView(panBasicInfo); panHeat = new HeatSinkView(panBasicInfo); + panArmorAllocation = new ArmorAllocationView(panBasicInfo, Entity.ETYPE_MECH); + panArmorAllocation.setPatchwork(getMech().hasPatchworkArmor()); panSummary = new SummaryView(eSource); + GridBagConstraints gbc; @@ -109,6 +111,7 @@ private void setUpPanels() { panArmor.setFromEntity(getMech()); panMovement.setFromEntity(getMech()); panHeat.setFromMech(getMech()); + panArmorAllocation.setFromEntity(getMech()); JPanel leftPanel = new JPanel(); JPanel rightPanel = new JPanel(); @@ -138,7 +141,7 @@ private void setUpPanels() { gbc.gridx = 1; masterPanel.add(rightPanel, gbc); gbc.gridx = 2; - masterPanel.add(armor, gbc); + masterPanel.add(panArmorAllocation, gbc); panBasicInfo.setBorder(BorderFactory.createTitledBorder("Basic Information")); panChassis.setBorder(BorderFactory.createTitledBorder("Chassis")); @@ -146,7 +149,7 @@ private void setUpPanels() { panHeat.setBorder(BorderFactory.createTitledBorder("Heat Sinks")); panArmor.setBorder(BorderFactory.createTitledBorder("Armor")); panSummary.setBorder(BorderFactory.createTitledBorder("Summary")); - armor.setBorder(BorderFactory.createTitledBorder("Armor Allocation")); + panArmorAllocation.setBorder(BorderFactory.createTitledBorder("Armor Allocation")); } @@ -157,8 +160,8 @@ public void refresh() { panArmor.setFromEntity(getMech()); panHeat.setFromMech(getMech()); panMovement.setFromEntity(getMech()); + panArmorAllocation.setFromEntity(getMech()); - armor.refresh(); panSummary.refresh(); addAllListeners(); @@ -358,6 +361,7 @@ public void removeAllListeners() { panHeat.removeListener(this); panArmor.removeListener(this); panMovement.removeListener(this); + panArmorAllocation.removeListener(this); } public void addAllListeners() { @@ -366,11 +370,11 @@ public void addAllListeners() { panHeat.addListener(this); panArmor.addListener(this); panMovement.addListener(this); + panArmorAllocation.addListener(this); } public void addRefreshedListener(RefreshListener l) { refresh = l; - armor.addRefreshedListener(l); } public boolean isQuad() { @@ -655,7 +659,7 @@ public void updateTechLevel() { panHeat.refresh(); panArmor.refresh(); panMovement.refresh(); - armor.resetArmorPoints(); + panArmorAllocation.setFromEntity(getMech()); addAllListeners(); } @@ -770,7 +774,6 @@ public void typeChanged(int baseType, int motiveType, long etype) { } refresh(); - armor.refresh(); refresh.refreshBuild(); refresh.refreshPreview(); refresh.refreshStatus(); @@ -919,12 +922,9 @@ public void armorTypeChanged(int at, int aTechLevel) { if (!getMech().hasPatchworkArmor()) { UnitUtil.removeISorArmorMounts(getMech(), false); } - createArmorMountsAndSetArmorType(at, aTechLevel); - if (!getMech().hasPatchworkArmor()) { - armor.resetArmorPoints(); - } - - armor.refresh(); +// createArmorMountsAndSetArmorType(at, aTechLevel); + panArmorAllocation.setPatchwork(at == EquipmentType.T_ARMOR_PATCHWORK); + panArmorAllocation.setFromEntity(getMech()); panSummary.refresh(); refresh.refreshStatus(); refresh.refreshBuild(); @@ -934,9 +934,7 @@ public void armorTypeChanged(int at, int aTechLevel) { @Override public void armorTonnageChanged(double tonnage) { getMech().setArmorTonnage(Math.round(tonnage * 2) / 2.0); - armor.resetArmorPoints(); - - armor.refresh(); + panArmorAllocation.setFromEntity(getMech()); panSummary.refresh(); refresh.refreshStatus(); refresh.refreshPreview(); @@ -946,12 +944,11 @@ public void armorTonnageChanged(double tonnage) { public void maximizeArmor() { double maxArmor = UnitUtil.getMaximumArmorTonnage(getMech()); getMech().setArmorTonnage(maxArmor); - armor.resetArmorPoints(); panArmor.removeListener(this); panArmor.setFromEntity(getMech()); panArmor.addListener(this); - armor.refresh(); + panArmorAllocation.setFromEntity(getMech()); panSummary.refresh(); refresh.refreshStatus(); refresh.refreshPreview(); @@ -969,12 +966,11 @@ public void useRemainingTonnageArmor() { double maxArmor = Math.min(getMech().getArmorWeight() + remainingTonnage, UnitUtil.getMaximumArmorTonnage(getMech())); getMech().setArmorTonnage(maxArmor); - armor.resetArmorPoints(); panArmor.removeListener(this); panArmor.setFromEntity(getMech()); panArmor.addListener(this); - armor.refresh(); + panArmorAllocation.setFromEntity(getMech()); panSummary.refresh(); refresh.refreshStatus(); refresh.refreshPreview(); @@ -1046,4 +1042,19 @@ public void jumpTypeChanged(final EquipmentType jumpJet) { jumpChanged(panMovement.getJump(), jumpJet); } + @Override + public void armorPointsChanged(int location, int front, int rear) { + getMech().initializeArmor(front, location); + if (getMech().hasRearArmor(location)) { + getMech().initializeRearArmor(rear, location); + } + panArmorAllocation.setFromEntity(getMech()); + } + + @Override + public void patchworkTypeChanged(int location, EquipmentType at) { + getMech().setArmorType(EquipmentType.getArmorType(at)); + getMech().setArmorTechLevel(at.getTechLevel(getTechManager().getGameYear(), at.isClan())); + } + } \ No newline at end of file diff --git a/src/megameklab/com/ui/view/ArmorAllocationView.java b/src/megameklab/com/ui/view/ArmorAllocationView.java new file mode 100644 index 000000000..08f515bd3 --- /dev/null +++ b/src/megameklab/com/ui/view/ArmorAllocationView.java @@ -0,0 +1,246 @@ +/* + * MegaMekLab - Copyright (C) 2017 - The MegaMek Team + * + * This program 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 2 of the License, or (at your option) + * any later version. + * + * This program 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. + */ +package megameklab.com.ui.view; + +import java.awt.Color; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.util.ArrayList; +import java.util.List; +import java.util.ResourceBundle; +import java.util.concurrent.CopyOnWriteArrayList; + +import javax.swing.BoxLayout; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.SwingConstants; + +import megamek.common.Aero; +import megamek.common.Entity; +import megamek.common.EquipmentType; +import megamek.common.ITechManager; +import megamek.common.Mech; +import megamek.common.SuperHeavyTank; +import megamek.common.Tank; +import megamek.common.VTOL; +import megamek.common.util.EncodeControl; +import megameklab.com.util.UnitUtil; + +/** + * Panel for allocating armor to various locations on an Entity. The assignment of armor values for specific + * locations is delegated to ArmorLocationView. This class handles positioning of the subviews to approximate + * the position on the unit and tracking the total amount of armor allocated. + * + * @author Neoancient + * + */ +public class ArmorAllocationView extends MainUIView implements ArmorLocationView.ArmorLocationListener { + + /** + * + */ + private static final long serialVersionUID = 1707528067499186372L; + + private List listeners = new CopyOnWriteArrayList<>(); + public void addListener(ArmorLocationView.ArmorLocationListener l) { + listeners.add(l); + } + public void removeListener(ArmorLocationView.ArmorLocationListener l) { + listeners.remove(l); + } + + private static final int[][] MEK_LAYOUT = { + {-1, -1, Mech.LOC_HEAD, -1, -1}, + {Mech.LOC_LARM, Mech.LOC_LT, Mech.LOC_CT, Mech.LOC_RT, Mech.LOC_RARM}, + {-1, Mech.LOC_LLEG, Mech.LOC_CLEG, Mech.LOC_RLEG, -1} + }; + + private static final int[][] VEE_LAYOUT = { + {-1, SuperHeavyTank.LOC_FRONT, -1}, + {SuperHeavyTank.LOC_FRONTLEFT, SuperHeavyTank.LOC_TURRET, SuperHeavyTank.LOC_FRONTRIGHT}, + {SuperHeavyTank.LOC_REARLEFT, SuperHeavyTank.LOC_TURRET_2, SuperHeavyTank.LOC_REARRIGHT}, + {-1, SuperHeavyTank.LOC_REAR, -1} + }; + + private static final int[][] VTOL_LAYOUT = { + {-1, Tank.LOC_FRONT, -1}, + {Tank.LOC_LEFT, VTOL.LOC_ROTOR, Tank.LOC_RIGHT}, + {-1, Tank.LOC_TURRET, -1}, + {-1, Tank.LOC_REAR, -1} + }; + + private static final int[][] AERODYNE_LAYOUT = { + {-1, Aero.LOC_NOSE, -1}, + {Aero.LOC_LWING, -1, Aero.LOC_RWING}, + {-1, Aero.LOC_AFT, -1} + }; + + private final List locationViews = new ArrayList<>(); + private final ITechManager techManager; + private final long entitytype; + private final JTextField txtUnallocated = new JTextField(); + private final JTextField txtAllocated = new JTextField(); + private final JTextField txtTotal = new JTextField(); + private final JTextField txtMaxPossible = new JTextField(); + private final JTextField txtWasted = new JTextField(); + + private int armorPoints = 0; + private int maxArmorPoints = 0; + private int wastedPoints = 0; + private boolean showPatchwork =false; + + public ArmorAllocationView(ITechManager techManager, long entitytype) { + this.techManager = techManager; + this.entitytype = entitytype; + initUI(); + } + + private void initUI() { + ResourceBundle resourceMap = ResourceBundle.getBundle("megameklab.resources.Views", new EncodeControl()); //$NON-NLS-1$ + setLayout(new GridBagLayout()); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridx = 0; + gbc.gridy = 0; + gbc.gridwidth = GridBagConstraints.REMAINDER; + + int[][] layout; + if ((entitytype & Entity.ETYPE_MECH) != 0) { + layout = MEK_LAYOUT; + } else if ((entitytype & Entity.ETYPE_AERO) != 0) { + // Spheroids use lwing/rwing rear for l/r aft positions + layout = AERODYNE_LAYOUT; + } else if ((entitytype & Entity.ETYPE_VTOL) != 0) { + layout = VTOL_LAYOUT; + } else { + layout = VEE_LAYOUT; + } + for (int row = 0; row < layout.length; row++) { + JPanel panRow = new JPanel(); + panRow.setLayout(new BoxLayout(panRow, BoxLayout.X_AXIS)); + for (int col = 0; col < layout[row].length; col++) { + if (layout[row][col] >= 0) { + ArmorLocationView locView = new ArmorLocationView(layout[row][col]); + locationViews.add(locView); + panRow.add(locView); + locView.addListener(this); + } else { + panRow.add(new JPanel()); + } + } + add(panRow, gbc); + gbc.gridy++; + } + + gbc.gridwidth = 1; + add(new JLabel(resourceMap.getString("ArmorAllocationView.txtUnallocated.text"), SwingConstants.RIGHT), gbc); //$NON-NLS-1$ + gbc.gridx = 1; + txtUnallocated.setEditable(false); + setFieldSize(txtUnallocated, editorSize); + add(txtUnallocated, gbc); + + gbc.gridx = 0; + gbc.gridy++; + add(new JLabel(resourceMap.getString("ArmorAllocationView.txtAllocated.text"), SwingConstants.RIGHT), gbc); //$NON-NLS-1$ + gbc.gridx = 1; + txtAllocated.setEditable(false); + setFieldSize(txtAllocated, editorSize); + add(txtAllocated, gbc); + + gbc.gridx = 0; + gbc.gridy++; + add(new JLabel(resourceMap.getString("ArmorAllocationView.txtTotal.text"), SwingConstants.RIGHT), gbc); //$NON-NLS-1$ + gbc.gridx = 1; + txtTotal.setEditable(false); + setFieldSize(txtTotal, editorSize); + add(txtTotal, gbc); + + gbc.gridx = 0; + gbc.gridy++; + add(new JLabel(resourceMap.getString("ArmorAllocationView.txtMaxPossible.text"), SwingConstants.RIGHT), gbc); //$NON-NLS-1$ + gbc.gridx = 1; + txtMaxPossible.setEditable(false); + setFieldSize(txtMaxPossible, editorSize); + add(txtMaxPossible, gbc); + + gbc.gridx = 0; + gbc.gridy++; + add(new JLabel(resourceMap.getString("ArmorAllocationView.txtWasted.text"), SwingConstants.RIGHT), gbc); //$NON-NLS-1$ + gbc.gridx = 1; + txtWasted.setEditable(false); + setFieldSize(txtWasted, editorSize); + add(txtWasted, gbc); + + } + + public void setFromEntity(Entity en) { + maxArmorPoints = UnitUtil.getMaximumArmorPoints(en); + + for (ArmorLocationView locView : locationViews) { + final int location = locView.getLocationIndex(); + if (location < en.locations()) { + locView.setVisible(true); + locView.updateLocation(en.getLocationAbbr(location), + en.hasRearArmor(location)); + locView.setMaxPoints(UnitUtil.getMaxArmor(en, location)); + locView.setPoints(en.getArmor(location)); + if (en.hasRearArmor(location)) { + locView.setPointsRear(en.getArmor(location, true)); + } else { + locView.setPointsRear(0); + } + } else { + locView.setVisible(false); + locView.setPoints(0); + locView.setPointsRear(0); + } + } + int currentPoints = en.getTotalOArmor(); + int raw = UnitUtil.getRawArmorPoints(en, en.getLabArmorTonnage()); + if (showPatchwork) { + armorPoints = currentPoints; + } else { + armorPoints = Math.min(raw, maxArmorPoints); + } + wastedPoints = Math.max(0, raw - armorPoints); + txtUnallocated.setText(Integer.toString(armorPoints - currentPoints)); + txtAllocated.setText(String.valueOf(currentPoints)); + if (armorPoints != currentPoints) { + txtUnallocated.setForeground(Color.RED); + } else { + txtUnallocated.setForeground(Color.BLACK); + } + txtTotal.setText(String.valueOf(armorPoints)); + txtMaxPossible.setText(String.valueOf(maxArmorPoints)); + txtWasted.setText(String.valueOf(wastedPoints)); + } + + public void setPatchwork(boolean patchwork) { + showPatchwork = patchwork; + for (ArmorLocationView locView : locationViews) { + locView.setPatchwork(patchwork); + } + } + + @Override + public void armorPointsChanged(int location, int front, int rear) { + listeners.forEach(l -> l.armorPointsChanged(location, front, rear)); + } + + @Override + public void patchworkTypeChanged(int location, EquipmentType at) { + listeners.forEach(l -> l.patchworkTypeChanged(location, at)); + } + +} diff --git a/src/megameklab/com/ui/view/ArmorLocationView.java b/src/megameklab/com/ui/view/ArmorLocationView.java new file mode 100644 index 000000000..d907fdf5a --- /dev/null +++ b/src/megameklab/com/ui/view/ArmorLocationView.java @@ -0,0 +1,262 @@ +/* + * MegaMekLab - Copyright (C) 2017 - The MegaMek Team + * + * This program 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 2 of the License, or (at your option) + * any later version. + * + * This program 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. + */ +package megameklab.com.ui.view; + +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; +import java.util.ResourceBundle; +import java.util.concurrent.CopyOnWriteArrayList; + +import javax.swing.BorderFactory; +import javax.swing.JLabel; +import javax.swing.JSpinner; +import javax.swing.SpinnerNumberModel; +import javax.swing.border.TitledBorder; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import megamek.common.EquipmentType; +import megamek.common.annotations.Nullable; +import megamek.common.util.EncodeControl; +import megameklab.com.ui.util.TechComboBox; + +/** + * Panel used to set armor value for a single location. Optionally used for rear location as well, + * and can be used to set the armor type for units with patchwork armor. + * + * @author Neoancient + * + */ +public class ArmorLocationView extends MainUIView implements ActionListener, ChangeListener { + + /** + * + */ + private static final long serialVersionUID = 6663440021651827007L; + + public interface ArmorLocationListener { + void armorPointsChanged(int location, int front, int rear); + void patchworkTypeChanged(int location, EquipmentType at); + } + private final List listeners = new CopyOnWriteArrayList<>(); + public void addListener(ArmorLocationListener l) { + listeners.add(l); + } + public void removeListener(ArmorLocationListener l) { + listeners.remove(l); + } + + private final SpinnerNumberModel spnPointsModel = new SpinnerNumberModel(0, 0, null, 1); + private final SpinnerNumberModel spnPointsRearModel = new SpinnerNumberModel(0, 0, null, 1); + private final JSpinner spnPoints = new JSpinner(spnPointsModel); + private final JSpinner spnPointsRear = new JSpinner(spnPointsRearModel); + private final TechComboBox cbArmorType = new TechComboBox<>(eq -> eq.getName()); + private final JLabel lblRear = new JLabel(); + private final JLabel lblMaxPoints = new JLabel(); + + private final int location; + private final String maxFormat; + private Integer maxPoints; + private boolean hasRear = false; + + ArmorLocationView(int location) { + this.location = location; + + ResourceBundle resourceMap = ResourceBundle.getBundle("megameklab.resources.Views", new EncodeControl()); //$NON-NLS-1$ + lblRear.setText(resourceMap.getString("ArmorLocationView.lblRear.text")); //$NON-NLS-1$ + maxFormat = resourceMap.getString("ArmorLocationView.lblMax.format"); //$NON-NLS-1$ + setBorder(BorderFactory.createTitledBorder( + null, "", + TitledBorder.TOP, + TitledBorder.DEFAULT_POSITION)); + setLayout(new GridBagLayout()); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridx = 0; + gbc.gridy = 0; + setFieldSize(spnPoints, spinnerSize); + add(spnPoints, gbc); + gbc.gridy++; + add(lblRear, gbc); + gbc.gridy++; + setFieldSize(spnPointsRear, spinnerSize); + add(spnPointsRear, gbc); + gbc.gridy++; + add(lblMaxPoints, gbc); + gbc.gridy++; + gbc.weighty = 1.0; + add(cbArmorType, gbc); + spnPoints.addChangeListener(this); + spnPointsRear.addChangeListener(this); + cbArmorType.addActionListener(this); + + } + + /** + * Changes the location name in the title and whether it has a rear armor location. + * + * @param locName + * @param rear + */ + public void updateLocation(String locName, boolean rear) { + ((TitledBorder)getBorder()).setTitle(locName); + hasRear = rear; + lblRear.setVisible(rear); + spnPointsRear.setVisible(rear); + if (!rear) { + spnPointsRear.setValue(0); + } + } + + /** + * @return The index (LOC_* constant) of the location managed by this view. + */ + public int getLocationIndex() { + return location; + } + + /** + * Sets the maximum number of armor points that can be assigned to this location. + * A value of null indicates that there is no maximum. + * + * @param max + */ + public void setMaxPoints(@Nullable Integer max) { + maxPoints = max; + spnPointsModel.setMaximum(max); + spnPointsRearModel.setMaximum(max); + if (null == max) { + lblMaxPoints.setVisible(false); + } else { + lblMaxPoints.setVisible(true); + lblMaxPoints.setText(String.format(maxFormat, max)); + } + } + + /** + * Provide a list of armors available for this location if the unit has patchwork armor. A null + * value for the list means that the unit does not have patchwork armor and the combo box should + * be hidden. + * + * @param ats The list of available armors if the unit has patchwork armor, or null if it does not. + * @param mixedTech If the unit has patchwork armor, this indicates whether the values in the combo + * box should distinguish between Clan and IS. + */ + public void setPatchworkTypes(@Nullable List ats, boolean mixedTech) { + if (null == ats) { + cbArmorType.setVisible(false); + } else { + cbArmorType.removeActionListener(this); + cbArmorType.removeAllItems(); + ats.forEach(at -> cbArmorType.addItem(at)); + cbArmorType.addActionListener(this); + cbArmorType.setVisible(true); + cbArmorType.showTechBase(mixedTech); + } + } + + /** + * Sets the number of points for this location. If the location has rear armor, this sets only the front. + * + * @param points + */ + public void setPoints(int points) { + spnPoints.removeChangeListener(this); + if (null == maxPoints) { + spnPoints.setValue(points); + } else { + spnPoints.setValue(Math.min(points, maxPoints)); + if (hasRear && (getPoints() + getPointsRear() > maxPoints)) { + spnPointsRearModel.setValue(maxPoints - getPoints()); + } + } + spnPoints.addChangeListener(this); + } + + /** + * @return The number of points of armor for this location (front). + */ + public int getPoints() { + return spnPointsModel.getNumber().intValue(); + } + + /** + * Sets the number of points of armor for this location in the rear. + * + * @param points + */ + public void setPointsRear(int points) { + spnPointsRear.removeChangeListener(this); + if (null == maxPoints) { + spnPointsRear.setValue(points); + } else { + spnPointsRear.setValue(Math.min(points, maxPoints)); + if (getPoints() + getPointsRear() > maxPoints) { + spnPointsModel.setValue(maxPoints - getPointsRear()); + } + } + spnPointsRear.addChangeListener(this); + } + + /** + * @return The number of points of rear armor in this location. + */ + public int getPointsRear() { + return spnPointsRearModel.getNumber().intValue(); + } + + /** + * Sets the type of armor for this location in the case of units with patchwork armor. + * + * @param at + */ + public void setArmorType(EquipmentType at) { + cbArmorType.removeActionListener(this); + cbArmorType.setSelectedItem(at); + cbArmorType.addActionListener(this); + if ((cbArmorType.getSelectedIndex() < 0) + && (cbArmorType.getModel().getSize() > 0)) { + cbArmorType.setSelectedIndex(0); + } + } + + /** + * Shows or hides the armor type combobox based on whether the user has selected patchwork armor. + * + * @param patchwork + */ + public void setPatchwork(boolean patchwork) { + cbArmorType.setVisible(patchwork); + } + + /** + * @return The type of armor in this location for units with patchwork armor. + */ + public EquipmentType getPatchworkType() { + return (EquipmentType)cbArmorType.getSelectedItem(); + } + + @Override + public void stateChanged(ChangeEvent e) { + listeners.forEach(l -> l.armorPointsChanged(location, getPoints(), getPointsRear())); + } + + @Override + public void actionPerformed(ActionEvent e) { + listeners.forEach(l -> l.patchworkTypeChanged(location, getPatchworkType())); + } + +} diff --git a/src/megameklab/com/ui/view/BAProtoArmorView.java b/src/megameklab/com/ui/view/BAProtoArmorView.java index 44ed30640..33a8704cf 100644 --- a/src/megameklab/com/ui/view/BAProtoArmorView.java +++ b/src/megameklab/com/ui/view/BAProtoArmorView.java @@ -96,7 +96,7 @@ private void initUI() { add(createLabel(resourceMap.getString("ArmorView.spnArmorPoints.text"), labelSize), gbc); //$NON-NLS-1$ gbc.gridx = 1; gbc.gridy = 1; - setFieldSize(spnArmorPoints.getEditor(), spinnerEditorSize); + setFieldSize(spnArmorPoints.getEditor(), editorSize); spnArmorPoints.setToolTipText(resourceMap.getString("ArmorView.spnArmorPoints.tooltip")); //$NON-NLS-1$ add(spnArmorPoints, gbc); spnArmorPoints.addChangeListener(this); diff --git a/src/megameklab/com/ui/view/FighterChassisView.java b/src/megameklab/com/ui/view/FighterChassisView.java index 8d04df1be..921ad1f60 100644 --- a/src/megameklab/com/ui/view/FighterChassisView.java +++ b/src/megameklab/com/ui/view/FighterChassisView.java @@ -128,7 +128,7 @@ public void initUI() { gbc.gridwidth = 1; gbc.anchor = GridBagConstraints.WEST; add(createLabel(resourceMap.getString("FighterChassisView.txtSI.text"), labelSize),gbc); //$NON-NLS-1$ - setFieldSize(txtSI, spinnerEditorSize); + setFieldSize(txtSI, editorSize); txtSI.setToolTipText(resourceMap.getString("FighterChassisView.txtSI.tooltip")); //$NON-NLS-1$ txtSI.setEditable(false); diff --git a/src/megameklab/com/ui/view/HeatSinkView.java b/src/megameklab/com/ui/view/HeatSinkView.java index a618e3b66..ed6aadae6 100644 --- a/src/megameklab/com/ui/view/HeatSinkView.java +++ b/src/megameklab/com/ui/view/HeatSinkView.java @@ -129,7 +129,7 @@ private void initUI() { add(createLabel(resourceMap.getString("HeatSinkView.spnCount.text"), labelSize), gbc); //$NON-NLS-1$ gbc.gridx = 1; gbc.gridy = 1; - setFieldSize(spnCount.getEditor(), spinnerEditorSize); + setFieldSize(spnCount.getEditor(), editorSize); spnCount.setToolTipText(resourceMap.getString("HeatSinkView.spnCount.tooltip")); //$NON-NLS-1$ add(spnCount, gbc); spnCount.addChangeListener(this); @@ -149,7 +149,7 @@ private void initUI() { add(createLabel(resourceMap.getString("HeatSinkView.spnBaseCount.text"), labelSize), gbc); //$NON-NLS-1$ gbc.gridx = 1; gbc.gridy = 2; - setFieldSize(spnBaseCount.getEditor(), spinnerEditorSize); + setFieldSize(spnBaseCount.getEditor(), editorSize); spnBaseCount.setToolTipText(resourceMap.getString("HeatSinkView.spnBaseCount.tooltip")); //$NON-NLS-1$ add(spnBaseCount, gbc); spnBaseCount.addChangeListener(this); diff --git a/src/megameklab/com/ui/view/MVFArmorView.java b/src/megameklab/com/ui/view/MVFArmorView.java index 40da8da71..c1e6ebd84 100644 --- a/src/megameklab/com/ui/view/MVFArmorView.java +++ b/src/megameklab/com/ui/view/MVFArmorView.java @@ -118,7 +118,7 @@ private void initUI() { add(createLabel(resourceMap.getString("ArmorView.spnTonnage.text"), labelSize), gbc); //$NON-NLS-1$ gbc.gridx = 1; gbc.gridy = 1; - setFieldSize(spnTonnage.getEditor(), spinnerEditorSize); + setFieldSize(spnTonnage.getEditor(), editorSize); spnTonnage.setToolTipText(resourceMap.getString("ArmorView.spnTonnage.tooltip")); //$NON-NLS-1$ add(spnTonnage, gbc); spnTonnage.addChangeListener(this); diff --git a/src/megameklab/com/ui/view/MainUIView.java b/src/megameklab/com/ui/view/MainUIView.java index 7cf40d8f7..9006897b4 100644 --- a/src/megameklab/com/ui/view/MainUIView.java +++ b/src/megameklab/com/ui/view/MainUIView.java @@ -37,7 +37,7 @@ public abstract class MainUIView extends JPanel { final protected Dimension labelSize = new Dimension(110, 25); final protected Dimension controlSize = new Dimension(180, 25); final protected Dimension spinnerSize = new Dimension(55, 25); - final protected Dimension spinnerEditorSize = new Dimension(40, 25); + final protected Dimension editorSize = new Dimension(40, 25); public JLabel createLabel(String text, Dimension maxSize) { JLabel label = new JLabel(text, SwingConstants.RIGHT); diff --git a/src/megameklab/com/ui/view/MovementView.java b/src/megameklab/com/ui/view/MovementView.java index 110444662..9fe58dd2f 100644 --- a/src/megameklab/com/ui/view/MovementView.java +++ b/src/megameklab/com/ui/view/MovementView.java @@ -181,17 +181,17 @@ private void initUI() { add(cbJumpType, gbc); cbJumpType.addActionListener(this); - setFieldSize(spnWalk.getEditor(), spinnerEditorSize); - setFieldSize(txtWalkFinal, spinnerEditorSize); + setFieldSize(spnWalk.getEditor(), editorSize); + setFieldSize(txtWalkFinal, editorSize); txtWalkFinal.setEditable(false); txtWalkFinal.setHorizontalAlignment(SwingConstants.RIGHT); - setFieldSize(txtRunBase, spinnerEditorSize); - setFieldSize(txtRunFinal, spinnerEditorSize); + setFieldSize(txtRunBase, editorSize); + setFieldSize(txtRunFinal, editorSize); txtRunBase.setEditable(false); txtRunFinal.setEditable(false); txtRunFinal.setHorizontalAlignment(SwingConstants.RIGHT); - setFieldSize(spnJump.getEditor(), spinnerEditorSize); - setFieldSize(txtJumpFinal, spinnerEditorSize); + setFieldSize(spnJump.getEditor(), editorSize); + setFieldSize(txtJumpFinal, editorSize); txtJumpFinal.setEditable(false); txtJumpFinal.setHorizontalAlignment(SwingConstants.RIGHT); } diff --git a/src/megameklab/com/util/UnitUtil.java b/src/megameklab/com/util/UnitUtil.java index c56ecda6c..3b942bccd 100644 --- a/src/megameklab/com/util/UnitUtil.java +++ b/src/megameklab/com/util/UnitUtil.java @@ -48,6 +48,8 @@ import megamek.common.BipedMech; import megamek.common.CriticalSlot; import megamek.common.Entity; +import megamek.common.EntityMovementMode; +import megamek.common.EntityWeightClass; import megamek.common.EquipmentType; import megamek.common.ITechManager; import megamek.common.ITechnology; @@ -58,12 +60,15 @@ import megamek.common.MechView; import megamek.common.MiscType; import megamek.common.Mounted; +import megamek.common.Protomech; import megamek.common.QuadMech; +import megamek.common.SimpleTechLevel; import megamek.common.Tank; import megamek.common.TechConstants; import megamek.common.TripodMech; import megamek.common.VTOL; import megamek.common.WeaponType; +import megamek.common.annotations.Nullable; import megamek.common.logging.LogLevel; import megamek.common.logging.MMLogger; import megamek.common.verifier.EntityVerifier; @@ -1343,13 +1348,24 @@ public static double getMaximumArmorTonnage(Entity unit) { * @param armorTons * @return */ - public static int getArmorPoints(Entity unit, double armorTons) { + public static int getRawArmorPoints(Entity unit, double armorTons) { double armorPerTon = 16.0 * EquipmentType.getArmorPointMultiplier( unit.getArmorType(1), unit.getArmorTechLevel(1)); if (unit.getArmorType(1) == EquipmentType.T_ARMOR_HARDENED) { armorPerTon = 8.0; } - return Math.min((int) Math.floor(armorPerTon * armorTons), + return (int)Math.floor(armorPerTon * armorTons); + } + + /** + * NOTE: only use for non-patchwork armor + * + * @param unit + * @param armorTons + * @return + */ + public static int getArmorPoints(Entity unit, double armorTons) { + return Math.min(UnitUtil.getRawArmorPoints(unit, armorTons), UnitUtil.getMaximumArmorPoints(unit)); } @@ -1380,6 +1396,105 @@ public static void compactCriticals(Entity unit) { } } + /** + * Determine the maximum number of armor points that can be mounted in a location. + * + * @param entity + * @param location + * @return The maximum number of armor points for the location, or null if there is no maximum. + */ + public static @Nullable Integer getMaxArmor(Entity entity, int location) { + if ((location < 0) || (location >= entity.locations())) { + return 0; + } + if (entity.hasETypeFlag(Entity.ETYPE_MECH)) { + if (location == Mech.LOC_HEAD) { + return (entity.getWeightClass() == EntityWeightClass.WEIGHT_SUPER_HEAVY)? 12 : 9; + } else { + return entity.getOInternal(location) * 2; + } + } else if (entity.hasETypeFlag(Entity.ETYPE_PROTOMECH)) { + if (location == Protomech.LOC_HEAD) { + return 2 + (int)entity.getWeight() / 2; + } else if (location == Protomech.LOC_MAINGUN) { + return entity.getOInternal(location) * 3; + } else if ((location == Protomech.LOC_LARM) + || (location == Protomech.LOC_RARM)) { + return Math.min(entity.getOInternal(location) * 2, 6); + } else { + return entity.getOInternal(location) * 2; + } + } + return null; + } + + //Types available for industrial mechs, used by legalArmorsFor + private final static int[] INDUSTRIAL_TYPES = { + EquipmentType.T_ARMOR_INDUSTRIAL, EquipmentType.T_ARMOR_HEAVY_INDUSTRIAL, + EquipmentType.T_ARMOR_COMMERCIAL + }; + + /** + * Compiles a list of all armor types legal for the unit under given tech limits + * + * @param en The unit for which to compile the list + * @param techManager Provides era and tech constraints to determine whether the armor is legal + * @return A list of armors legal for the unit type under the tech constaints + */ + public static List legalArmorsFor(Entity en, ITechManager techManager) { + List retVal = new ArrayList<>(); + // IndustrialMechs can only use industrial armor below experimental rules level + if ((en instanceof Mech) && ((Mech)en).isIndustrial() + && (techManager.getTechLevel().ordinal() < SimpleTechLevel.EXPERIMENTAL.ordinal())) { + + for (int at : INDUSTRIAL_TYPES) { + String name = EquipmentType.getArmorTypeName(at, false); + EquipmentType eq = EquipmentType.get(name); + if ((null != eq) && techManager.isLegal(eq)) { + retVal.add(eq); + } + } + } else { + BigInteger flag = MiscType.F_MECH_EQUIPMENT; + if (en.hasETypeFlag(Entity.ETYPE_AERO)) { + flag = MiscType.F_AERO_EQUIPMENT; + } else if (en.hasETypeFlag(Entity.ETYPE_TANK)) { + flag = MiscType.F_TANK_EQUIPMENT; + } + boolean isLAM = en.hasETypeFlag(Entity.ETYPE_LAND_AIR_MECH); + boolean hardenedIllegal = isLAM + || (en.getMovementMode() == EntityMovementMode.VTOL) + || (en.getMovementMode() == EntityMovementMode.WIGE) + || (en.getMovementMode() == EntityMovementMode.HOVER); + + for (int at = 0; at < EquipmentType.armorNames.length; at++) { + if (at == EquipmentType.T_ARMOR_PATCHWORK) { + continue; + } + if ((at == EquipmentType.T_ARMOR_HARDENED) && hardenedIllegal) { + continue; + } + String name = EquipmentType.getArmorTypeName(at, techManager.useClanTechBase()); + EquipmentType eq = EquipmentType.get(name); + if ((null == eq) || (isLAM && ((eq.getCriticals(null) > 0)))) { + continue; + } + if ((null != eq) && eq.hasFlag(flag) && techManager.isLegal(eq)) { + retVal.add(eq); + } + if (techManager.useMixedTech()) { + name = EquipmentType.getArmorTypeName(at, !techManager.useClanTechBase()); + EquipmentType eq2 = EquipmentType.get(name); + if ((null != eq2) && (eq != eq2) && eq2.hasFlag(flag) + && techManager.isLegal(eq2)) { + retVal.add(eq2); + } + } + } + } + return retVal; + } + public static void compactCriticals(Entity unit, int loc) { int firstEmpty = -1; for (int slot = 0; slot < unit.getNumberOfCriticals(loc); slot++) { diff --git a/src/megameklab/resources/Views.properties b/src/megameklab/resources/Views.properties index 9d5d435a3..d15270ba9 100644 --- a/src/megameklab/resources/Views.properties +++ b/src/megameklab/resources/Views.properties @@ -153,6 +153,15 @@ ArmorView.btnRemaining.tooltip=Use all remaining unallocated tonnage for armor, ArmorView.spnArmorPoints.text=Points: ArmorView.spnArmorPoints.tooltip=The number of points of armor for the unit. +ArmorLocationView.lblRear.text=Rear +ArmorLocationView.lblMax.format=Max: %d + +ArmorAllocationView.txtUnallocated.text=Unallocated Armor Points: +ArmorAllocationView.txtAllocated.text=Allocated Armor Points: +ArmorAllocationView.txtTotal.text=Total Armor Points: +ArmorAllocationView.txtMaxPossible.text=Maximum Possible Armor Points: +ArmorAllocationView.txtWasted.text=Wasted Armor Points: + MovementView.lblBase.text=Base MovementView.lblFinal.text=Final MovementView.lblWalk.values=Walk MP:,Cruise MP:,Safe Thrust:,Walk MP: From bf03e85d63ea5ad74546c697ba1af2a111e0c8ae Mon Sep 17 00:00:00 2001 From: Carl Spain Date: Wed, 20 Sep 2017 08:31:35 -0500 Subject: [PATCH 02/12] Added view for patchwork armor as an alternative to the popup, giving the user a persistent indicator of what armor is in which location. --- .../com/ui/Mek/tabs/StructureTab.java | 233 +++++++++--------- .../com/ui/Mek/views/SummaryView.java | 6 +- .../com/ui/view/ArmorAllocationView.java | 55 ++--- .../com/ui/view/ArmorLocationView.java | 74 +----- src/megameklab/com/ui/view/MVFArmorView.java | 14 +- .../com/ui/view/PatchworkArmorView.java | 146 +++++++++++ src/megameklab/com/util/UnitUtil.java | 25 ++ src/megameklab/resources/Views.properties | 1 + 8 files changed, 331 insertions(+), 223 deletions(-) create mode 100644 src/megameklab/com/ui/view/PatchworkArmorView.java diff --git a/src/megameklab/com/ui/Mek/tabs/StructureTab.java b/src/megameklab/com/ui/Mek/tabs/StructureTab.java index d73212c17..8dde8d531 100644 --- a/src/megameklab/com/ui/Mek/tabs/StructureTab.java +++ b/src/megameklab/com/ui/Mek/tabs/StructureTab.java @@ -20,7 +20,6 @@ import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; -import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; @@ -34,7 +33,6 @@ import javax.swing.JPanel; import javax.swing.SwingConstants; -import megamek.client.ui.GBC; import megamek.common.CriticalSlot; import megamek.common.Engine; import megamek.common.Entity; @@ -53,7 +51,6 @@ import megamek.common.verifier.TestEntity; import megameklab.com.ui.EntitySource; import megameklab.com.ui.Mek.views.SummaryView; -import megameklab.com.ui.util.TechComboBox; import megameklab.com.ui.view.ArmorAllocationView; import megameklab.com.ui.view.ArmorLocationView; import megameklab.com.ui.view.BasicInfoView; @@ -61,13 +58,15 @@ import megameklab.com.ui.view.MVFArmorView; import megameklab.com.ui.view.MekChassisView; import megameklab.com.ui.view.MovementView; +import megameklab.com.ui.view.PatchworkArmorView; import megameklab.com.util.ITab; import megameklab.com.util.RefreshListener; import megameklab.com.util.UnitUtil; public class StructureTab extends ITab implements BasicInfoView.BasicInfoListener, MekChassisView.MekChassisListener, HeatSinkView.HeatSinkListener, MVFArmorView.ArmorListener, - MovementView.MovementListener, ArmorLocationView.ArmorLocationListener { + MovementView.MovementListener, ArmorLocationView.ArmorLocationListener, + PatchworkArmorView.PatchworkListener { /** * */ @@ -80,6 +79,7 @@ public class StructureTab extends ITab implements BasicInfoView.BasicInfoListene private HeatSinkView panHeat; private SummaryView panSummary; private ArmorAllocationView panArmorAllocation; + private PatchworkArmorView panPatchwork; RefreshListener refresh = null; JPanel masterPanel; @@ -100,9 +100,13 @@ private void setUpPanels() { panMovement = new MovementView(panBasicInfo); panHeat = new HeatSinkView(panBasicInfo); panArmorAllocation = new ArmorAllocationView(panBasicInfo, Entity.ETYPE_MECH); - panArmorAllocation.setPatchwork(getMech().hasPatchworkArmor()); + panPatchwork = new PatchworkArmorView(panBasicInfo); panSummary = new SummaryView(eSource); - + if (getMech().hasPatchworkArmor()) { + panArmorAllocation.showPatchwork(true); + } else { + panPatchwork.setVisible(false); + } GridBagConstraints gbc; @@ -112,10 +116,13 @@ private void setUpPanels() { panMovement.setFromEntity(getMech()); panHeat.setFromMech(getMech()); panArmorAllocation.setFromEntity(getMech()); + panPatchwork.setFromEntity(getMech()); JPanel leftPanel = new JPanel(); + JPanel centerPanel = new JPanel(); JPanel rightPanel = new JPanel(); leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.Y_AXIS)); + centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.Y_AXIS)); rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.Y_AXIS)); leftPanel.add(panBasicInfo); @@ -125,10 +132,14 @@ private void setUpPanels() { leftPanel.add(panHeat); leftPanel.add(Box.createGlue()); - rightPanel.add(panArmor); - rightPanel.add(panMovement); - rightPanel.add(panSummary); - leftPanel.add(Box.createVerticalGlue()); + centerPanel.add(panArmor); + centerPanel.add(panMovement); + centerPanel.add(panSummary); + centerPanel.add(Box.createVerticalGlue()); + + rightPanel.add(panArmorAllocation); + rightPanel.add(panPatchwork); + rightPanel.add(Box.createVerticalGlue()); gbc = new GridBagConstraints(); gbc.gridx = 0; @@ -139,9 +150,9 @@ private void setUpPanels() { gbc.anchor = GridBagConstraints.NORTHWEST; masterPanel.add(leftPanel, gbc); gbc.gridx = 1; - masterPanel.add(rightPanel, gbc); + masterPanel.add(centerPanel, gbc); gbc.gridx = 2; - masterPanel.add(panArmorAllocation, gbc); + masterPanel.add(rightPanel, gbc); panBasicInfo.setBorder(BorderFactory.createTitledBorder("Basic Information")); panChassis.setBorder(BorderFactory.createTitledBorder("Chassis")); @@ -150,6 +161,7 @@ private void setUpPanels() { panArmor.setBorder(BorderFactory.createTitledBorder("Armor")); panSummary.setBorder(BorderFactory.createTitledBorder("Summary")); panArmorAllocation.setBorder(BorderFactory.createTitledBorder("Armor Allocation")); + panPatchwork.setBorder(BorderFactory.createTitledBorder("Patchwork Armor")); } @@ -161,6 +173,7 @@ public void refresh() { panHeat.setFromMech(getMech()); panMovement.setFromEntity(getMech()); panArmorAllocation.setFromEntity(getMech()); + panPatchwork.setFromEntity(getMech()); panSummary.refresh(); addAllListeners(); @@ -362,6 +375,7 @@ public void removeAllListeners() { panArmor.removeListener(this); panMovement.removeListener(this); panArmorAllocation.removeListener(this); + panPatchwork.removeListener(this); } public void addAllListeners() { @@ -371,6 +385,7 @@ public void addAllListeners() { panArmor.addListener(this); panMovement.addListener(this); panArmorAllocation.addListener(this); + panPatchwork.addListener(this); } public void addRefreshedListener(RefreshListener l) { @@ -474,104 +489,36 @@ private boolean hasCTSpace(Engine engine, int gyroType, int cockpitType) { } private void createArmorMountsAndSetArmorType(int at, int aTechLevel) { + getMech().setArmorTechLevel(aTechLevel); + getMech().setArmorType(at); + final EquipmentType armor = EquipmentType.get(EquipmentType.getArmorTypeName(at, + TechConstants.isClan(aTechLevel))); + int armorCount = armor.getCriticals(getMech()); - if (at == EquipmentType.T_ARMOR_PATCHWORK) { - boolean isMixed = panBasicInfo.useMixedTech(); - List armors = panArmor.getAllArmors(); - List> combos = new ArrayList<>(); - JPanel panel = new JPanel(new GridBagLayout()); - for (int loc = 0; loc < getMech().locations(); loc++) { - TechComboBox cbLoc = new TechComboBox<>(eq -> eq.getName()); - cbLoc.showTechBase(isMixed); - armors.forEach(a -> cbLoc.addItem(a)); - EquipmentType locArmor = EquipmentType.get(EquipmentType - .getArmorTypeName(getMech().getArmorType(loc), - TechConstants.isClan(getMech().getArmorTechLevel(loc)))); - cbLoc.setSelectedItem(locArmor); - combos.add(cbLoc); - JLabel label = new JLabel(getMech().getLocationName(loc)); - panel.add(label, GBC.std()); - panel.add(cbLoc, GBC.eol()); - } - JOptionPane.showMessageDialog(this, panel, - "Please choose the armor types", - JOptionPane.QUESTION_MESSAGE); - UnitUtil.removeISorArmorMounts(getMech(), false); - for (int loc = 0; loc < getMech().locations(); loc++) { - EquipmentType armor = (EquipmentType)combos.get(loc).getSelectedItem(); - getMech().setArmorTechLevel(armor.getTechLevel(panBasicInfo.getGameYear()), loc); - getMech().setArmorType(EquipmentType.getArmorType(armor), loc); - int crits = 0; - switch (EquipmentType.getArmorType(armor)) { - case EquipmentType.T_ARMOR_STEALTH: - case EquipmentType.T_ARMOR_FERRO_LAMELLOR: - crits = 2; - break; - case EquipmentType.T_ARMOR_HEAVY_FERRO: - crits = 3; - break; - case EquipmentType.T_ARMOR_FERRO_FIBROUS: - case EquipmentType.T_ARMOR_REFLECTIVE: - case EquipmentType.T_ARMOR_REACTIVE: - if (armor.isClan()) { - crits = 1; - } else { - crits = 2; - } - break; - } - if (getMech().getEmptyCriticals(loc) < crits) { - JOptionPane .showMessageDialog( - null, armor.getName() - + " does not fit in location " - + getMech().getLocationName(loc) - + ". Resetting to Standard Armor in this location.", - "Error", - JOptionPane.INFORMATION_MESSAGE); - getMech().setArmorTechLevel(TechConstants.T_INTRO_BOXSET, loc); - getMech().setArmorType(EquipmentType.T_ARMOR_STANDARD, loc); - } else { - for (; crits > 0; crits--) { - try { - getMech().addEquipment( new Mounted(getMech(), armor), loc, false); - } catch (LocationFullException ex) { - } - } - } + if (armorCount < 1) { + return; + } + // auto-place stealth crits + if (getMech().getArmorType(0) == EquipmentType.T_ARMOR_STEALTH) { + Mounted mount = UnitUtil.createSpreadMounts( + getMech(), + EquipmentType.get(EquipmentType.getArmorTypeName( + getMech().getArmorType(0), false))); + if (mount == null) { + JOptionPane.showMessageDialog(null, + "Stealth Armor does not fit in location.", + "Resetting to Standard Armor", + JOptionPane.INFORMATION_MESSAGE); + getMech().setArmorType(EquipmentType.T_ARMOR_STANDARD); + getMech().setArmorTechLevel(TechConstants.T_INTRO_BOXSET); + panArmor.setFromEntity(getMech()); } - panArmor.setFromEntity(getMech()); } else { - getMech().setArmorTechLevel(aTechLevel); - getMech().setArmorType(at); - final EquipmentType armor = EquipmentType.get(EquipmentType.getArmorTypeName(at, - TechConstants.isClan(aTechLevel))); - int armorCount = armor.getCriticals(getMech()); - - if (armorCount < 1) { - return; - } - // auto-place stealth crits - if (getMech().getArmorType(0) == EquipmentType.T_ARMOR_STEALTH) { - Mounted mount = UnitUtil.createSpreadMounts( - getMech(), - EquipmentType.get(EquipmentType.getArmorTypeName( - getMech().getArmorType(0), false))); - if (mount == null) { - JOptionPane.showMessageDialog(null, - "Stealth Armor does not fit in location.", - "Resetting to Standard Armor", - JOptionPane.INFORMATION_MESSAGE); - getMech().setArmorType(EquipmentType.T_ARMOR_STANDARD); - getMech().setArmorTechLevel(TechConstants.T_INTRO_BOXSET); - panArmor.setFromEntity(getMech()); - } - } else { - for (; armorCount > 0; armorCount--) { - try { - getMech().addEquipment(new Mounted(getMech(), - armor), Entity.LOC_NONE, false); - } catch (Exception ex) { - } + for (; armorCount > 0; armorCount--) { + try { + getMech().addEquipment(new Mounted(getMech(), + armor), Entity.LOC_NONE, false); + } catch (Exception ex) { } } } @@ -632,7 +579,7 @@ public void updateTechLevel() { if (!getMech().hasPatchworkArmor()) { UnitUtil.removeISorArmorMounts(getMech(), false); } - createArmorMountsAndSetArmorType(getMech().getArmorType(0), getMech().getArmorTechLevel(0)); +// createArmorMountsAndSetArmorType(getMech().getArmorType(0), getMech().getArmorTechLevel(0)); // If we have a large engine, a drop in tech level may make it unavailable and we will need // to reduce speed to a legal value. if (getMech().getEngine().hasFlag(Engine.LARGE_ENGINE) @@ -660,6 +607,7 @@ public void updateTechLevel() { panArmor.refresh(); panMovement.refresh(); panArmorAllocation.setFromEntity(getMech()); + panPatchwork.setFromEntity(getMech()); addAllListeners(); } @@ -919,11 +867,16 @@ public void heatSinkBaseCountChanged(int count) { @Override public void armorTypeChanged(int at, int aTechLevel) { - if (!getMech().hasPatchworkArmor()) { - UnitUtil.removeISorArmorMounts(getMech(), false); + UnitUtil.removeISorArmorMounts(getMech(), false); + if (at != EquipmentType.T_ARMOR_PATCHWORK) { + createArmorMountsAndSetArmorType(at, aTechLevel); + panArmorAllocation.showPatchwork(false); + panPatchwork.setVisible(false); + } else { + panPatchwork.setFromEntity(getMech()); + panArmorAllocation.showPatchwork(true); + panPatchwork.setVisible(true); } -// createArmorMountsAndSetArmorType(at, aTechLevel); - panArmorAllocation.setPatchwork(at == EquipmentType.T_ARMOR_PATCHWORK); panArmorAllocation.setFromEntity(getMech()); panSummary.refresh(); refresh.refreshStatus(); @@ -1049,12 +1002,62 @@ public void armorPointsChanged(int location, int front, int rear) { getMech().initializeRearArmor(rear, location); } panArmorAllocation.setFromEntity(getMech()); + refresh.refreshPreview(); + refresh.refreshSummary(); + refresh.refreshStatus(); } @Override - public void patchworkTypeChanged(int location, EquipmentType at) { - getMech().setArmorType(EquipmentType.getArmorType(at)); - getMech().setArmorTechLevel(at.getTechLevel(getTechManager().getGameYear(), at.isClan())); + public void patchworkChanged(int location, EquipmentType armor) { + UnitUtil.resetArmor(getMech(), location); + + //TODO: move this construction data out of the ui + int crits = 0; + switch (EquipmentType.getArmorType(armor)) { + case EquipmentType.T_ARMOR_STEALTH: + case EquipmentType.T_ARMOR_FERRO_LAMELLOR: + crits = 2; + break; + case EquipmentType.T_ARMOR_HEAVY_FERRO: + crits = 3; + break; + case EquipmentType.T_ARMOR_LIGHT_FERRO: + crits = 1; + break; + case EquipmentType.T_ARMOR_FERRO_FIBROUS: + case EquipmentType.T_ARMOR_REFLECTIVE: + case EquipmentType.T_ARMOR_REACTIVE: + if (armor.isClan()) { + crits = 1; + } else { + crits = 2; + } + break; + } + if (getMech().getEmptyCriticals(location) < crits) { + JOptionPane .showMessageDialog( + null, armor.getName() + + " does not fit in location " + + getMech().getLocationName(location) + + ". Resetting to Standard Armor in this location.", + "Error", + JOptionPane.INFORMATION_MESSAGE); + } else { + getMech().setArmorType(EquipmentType.getArmorType(armor), location); + getMech().setArmorTechLevel(armor.getTechLevel(getTechManager().getGameYear(), armor.isClan())); + for (; crits > 0; crits--) { + try { + getMech().addEquipment( new Mounted(getMech(), armor), location, false); + } catch (LocationFullException ex) { + } + } + } + panArmor.refresh(); + panArmorAllocation.setFromEntity(getMech()); + refresh.refreshBuild(); + refresh.refreshPreview(); + refresh.refreshSummary(); + refresh.refreshStatus(); } } \ No newline at end of file diff --git a/src/megameklab/com/ui/Mek/views/SummaryView.java b/src/megameklab/com/ui/Mek/views/SummaryView.java index 52098a2e9..4a7470591 100644 --- a/src/megameklab/com/ui/Mek/views/SummaryView.java +++ b/src/megameklab/com/ui/Mek/views/SummaryView.java @@ -275,7 +275,11 @@ public void refresh() { txtCockpitTon.setText(Double.toString(testMech.getWeightCockpit())); txtHeatTon.setText(Double.toString(testMech.getWeightHeatSinks())); txtStructTon.setText(Double.toString(testMech.getWeightStructure())); - txtArmorTon.setText(Double.toString(testMech.getWeightArmor())); + if (getMech().hasPatchworkArmor()) { + txtArmorTon.setText(Double.toString(testMech.getWeightAllocatedArmor())); + } else { + txtArmorTon.setText(Double.toString(testMech.getWeightArmor())); + } txtOtherTon.setText(Double.toString(testMech.getWeightPowerAmp() + testMech.getWeightCarryingSpace() + testMech.getWeightMisc())); diff --git a/src/megameklab/com/ui/view/ArmorAllocationView.java b/src/megameklab/com/ui/view/ArmorAllocationView.java index 08f515bd3..9caab5d04 100644 --- a/src/megameklab/com/ui/view/ArmorAllocationView.java +++ b/src/megameklab/com/ui/view/ArmorAllocationView.java @@ -29,7 +29,6 @@ import megamek.common.Aero; import megamek.common.Entity; -import megamek.common.EquipmentType; import megamek.common.ITechManager; import megamek.common.Mech; import megamek.common.SuperHeavyTank; @@ -46,14 +45,15 @@ * @author Neoancient * */ -public class ArmorAllocationView extends MainUIView implements ArmorLocationView.ArmorLocationListener { +public class ArmorAllocationView extends MainUIView implements + ArmorLocationView.ArmorLocationListener { /** * */ private static final long serialVersionUID = 1707528067499186372L; - private List listeners = new CopyOnWriteArrayList<>(); + private final List listeners = new CopyOnWriteArrayList<>(); public void addListener(ArmorLocationView.ArmorLocationListener l) { listeners.add(l); } @@ -88,7 +88,6 @@ public void removeListener(ArmorLocationView.ArmorLocationListener l) { }; private final List locationViews = new ArrayList<>(); - private final ITechManager techManager; private final long entitytype; private final JTextField txtUnallocated = new JTextField(); private final JTextField txtAllocated = new JTextField(); @@ -99,10 +98,9 @@ public void removeListener(ArmorLocationView.ArmorLocationListener l) { private int armorPoints = 0; private int maxArmorPoints = 0; private int wastedPoints = 0; - private boolean showPatchwork =false; + private boolean showPatchwork = false; public ArmorAllocationView(ITechManager techManager, long entitytype) { - this.techManager = techManager; this.entitytype = entitytype; initUI(); } @@ -130,8 +128,9 @@ private void initUI() { JPanel panRow = new JPanel(); panRow.setLayout(new BoxLayout(panRow, BoxLayout.X_AXIS)); for (int col = 0; col < layout[row].length; col++) { - if (layout[row][col] >= 0) { - ArmorLocationView locView = new ArmorLocationView(layout[row][col]); + final int loc = layout[row][col]; + if (loc >= 0) { + ArmorLocationView locView = new ArmorLocationView(loc); locationViews.add(locView); panRow.add(locView); locView.addListener(this); @@ -178,22 +177,35 @@ private void initUI() { gbc.gridy++; add(new JLabel(resourceMap.getString("ArmorAllocationView.txtWasted.text"), SwingConstants.RIGHT), gbc); //$NON-NLS-1$ gbc.gridx = 1; + gbc.gridwidth = GridBagConstraints.REMAINDER; txtWasted.setEditable(false); setFieldSize(txtWasted, editorSize); add(txtWasted, gbc); - } public void setFromEntity(Entity en) { maxArmorPoints = UnitUtil.getMaximumArmorPoints(en); - + int raw = UnitUtil.getRawArmorPoints(en, en.getLabArmorTonnage()); + int currentPoints = en.getTotalOArmor(); + if (showPatchwork) { + armorPoints = currentPoints; + raw = currentPoints; + } else { + armorPoints = Math.min(raw, maxArmorPoints); + } + wastedPoints = Math.max(0, raw - armorPoints); for (ArmorLocationView locView : locationViews) { final int location = locView.getLocationIndex(); if (location < en.locations()) { locView.setVisible(true); locView.updateLocation(en.getLocationAbbr(location), en.hasRearArmor(location)); - locView.setMaxPoints(UnitUtil.getMaxArmor(en, location)); + // If we've already hit the maximum allocated to armor, set the current value as maximum. + if (showPatchwork || (currentPoints < armorPoints)) { + locView.setMaxPoints(UnitUtil.getMaxArmor(en, location)); + } else { + locView.setMaxPoints(en.getArmor(location, false) + en.getArmor(location, true)); + } locView.setPoints(en.getArmor(location)); if (en.hasRearArmor(location)) { locView.setPointsRear(en.getArmor(location, true)); @@ -206,14 +218,6 @@ public void setFromEntity(Entity en) { locView.setPointsRear(0); } } - int currentPoints = en.getTotalOArmor(); - int raw = UnitUtil.getRawArmorPoints(en, en.getLabArmorTonnage()); - if (showPatchwork) { - armorPoints = currentPoints; - } else { - armorPoints = Math.min(raw, maxArmorPoints); - } - wastedPoints = Math.max(0, raw - armorPoints); txtUnallocated.setText(Integer.toString(armorPoints - currentPoints)); txtAllocated.setText(String.valueOf(currentPoints)); if (armorPoints != currentPoints) { @@ -226,21 +230,12 @@ public void setFromEntity(Entity en) { txtWasted.setText(String.valueOf(wastedPoints)); } - public void setPatchwork(boolean patchwork) { - showPatchwork = patchwork; - for (ArmorLocationView locView : locationViews) { - locView.setPatchwork(patchwork); - } + public void showPatchwork(boolean show) { + showPatchwork = show; } @Override public void armorPointsChanged(int location, int front, int rear) { listeners.forEach(l -> l.armorPointsChanged(location, front, rear)); } - - @Override - public void patchworkTypeChanged(int location, EquipmentType at) { - listeners.forEach(l -> l.patchworkTypeChanged(location, at)); - } - } diff --git a/src/megameklab/com/ui/view/ArmorLocationView.java b/src/megameklab/com/ui/view/ArmorLocationView.java index d907fdf5a..beb09775f 100644 --- a/src/megameklab/com/ui/view/ArmorLocationView.java +++ b/src/megameklab/com/ui/view/ArmorLocationView.java @@ -15,8 +15,6 @@ import java.awt.GridBagConstraints; import java.awt.GridBagLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.util.List; import java.util.ResourceBundle; import java.util.concurrent.CopyOnWriteArrayList; @@ -29,10 +27,8 @@ import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; -import megamek.common.EquipmentType; import megamek.common.annotations.Nullable; import megamek.common.util.EncodeControl; -import megameklab.com.ui.util.TechComboBox; /** * Panel used to set armor value for a single location. Optionally used for rear location as well, @@ -41,7 +37,7 @@ * @author Neoancient * */ -public class ArmorLocationView extends MainUIView implements ActionListener, ChangeListener { +public class ArmorLocationView extends MainUIView implements ChangeListener { /** * @@ -50,7 +46,6 @@ public class ArmorLocationView extends MainUIView implements ActionListener, Cha public interface ArmorLocationListener { void armorPointsChanged(int location, int front, int rear); - void patchworkTypeChanged(int location, EquipmentType at); } private final List listeners = new CopyOnWriteArrayList<>(); public void addListener(ArmorLocationListener l) { @@ -64,7 +59,6 @@ public void removeListener(ArmorLocationListener l) { private final SpinnerNumberModel spnPointsRearModel = new SpinnerNumberModel(0, 0, null, 1); private final JSpinner spnPoints = new JSpinner(spnPointsModel); private final JSpinner spnPointsRear = new JSpinner(spnPointsRearModel); - private final TechComboBox cbArmorType = new TechComboBox<>(eq -> eq.getName()); private final JLabel lblRear = new JLabel(); private final JLabel lblMaxPoints = new JLabel(); @@ -95,14 +89,8 @@ public void removeListener(ArmorLocationListener l) { setFieldSize(spnPointsRear, spinnerSize); add(spnPointsRear, gbc); gbc.gridy++; - add(lblMaxPoints, gbc); - gbc.gridy++; gbc.weighty = 1.0; - add(cbArmorType, gbc); - spnPoints.addChangeListener(this); - spnPointsRear.addChangeListener(this); - cbArmorType.addActionListener(this); - + add(lblMaxPoints, gbc); } /** @@ -146,28 +134,6 @@ public void setMaxPoints(@Nullable Integer max) { } } - /** - * Provide a list of armors available for this location if the unit has patchwork armor. A null - * value for the list means that the unit does not have patchwork armor and the combo box should - * be hidden. - * - * @param ats The list of available armors if the unit has patchwork armor, or null if it does not. - * @param mixedTech If the unit has patchwork armor, this indicates whether the values in the combo - * box should distinguish between Clan and IS. - */ - public void setPatchworkTypes(@Nullable List ats, boolean mixedTech) { - if (null == ats) { - cbArmorType.setVisible(false); - } else { - cbArmorType.removeActionListener(this); - cbArmorType.removeAllItems(); - ats.forEach(at -> cbArmorType.addItem(at)); - cbArmorType.addActionListener(this); - cbArmorType.setVisible(true); - cbArmorType.showTechBase(mixedTech); - } - } - /** * Sets the number of points for this location. If the location has rear armor, this sets only the front. * @@ -218,45 +184,9 @@ public int getPointsRear() { return spnPointsRearModel.getNumber().intValue(); } - /** - * Sets the type of armor for this location in the case of units with patchwork armor. - * - * @param at - */ - public void setArmorType(EquipmentType at) { - cbArmorType.removeActionListener(this); - cbArmorType.setSelectedItem(at); - cbArmorType.addActionListener(this); - if ((cbArmorType.getSelectedIndex() < 0) - && (cbArmorType.getModel().getSize() > 0)) { - cbArmorType.setSelectedIndex(0); - } - } - - /** - * Shows or hides the armor type combobox based on whether the user has selected patchwork armor. - * - * @param patchwork - */ - public void setPatchwork(boolean patchwork) { - cbArmorType.setVisible(patchwork); - } - - /** - * @return The type of armor in this location for units with patchwork armor. - */ - public EquipmentType getPatchworkType() { - return (EquipmentType)cbArmorType.getSelectedItem(); - } - @Override public void stateChanged(ChangeEvent e) { listeners.forEach(l -> l.armorPointsChanged(location, getPoints(), getPointsRear())); } - @Override - public void actionPerformed(ActionEvent e) { - listeners.forEach(l -> l.patchworkTypeChanged(location, getPatchworkType())); - } - } diff --git a/src/megameklab/com/ui/view/MVFArmorView.java b/src/megameklab/com/ui/view/MVFArmorView.java index c1e6ebd84..24136f8e0 100644 --- a/src/megameklab/com/ui/view/MVFArmorView.java +++ b/src/megameklab/com/ui/view/MVFArmorView.java @@ -230,17 +230,21 @@ public void refresh() { } } } - cbArmorType.setSelectedItem(prev); - cbArmorType.addActionListener(this); - if (cbArmorType.getSelectedIndex() < 0) { - cbArmorType.setSelectedIndex(0); - } } //TODO: patchwork armor for fighters needs work on the armor allocation view if (((etype & Entity.ETYPE_AERO) == 0) && techManager.isLegal(Entity.getPatchworkArmorAdvancement())) { cbArmorType.addItem(null); } + if (null == prev) { + cbArmorType.setSelectedIndex(cbArmorType.getModel().getSize() - 1); + } else { + cbArmorType.setSelectedItem(prev); + } + cbArmorType.addActionListener(this); + if ((null != prev) && (cbArmorType.getSelectedIndex() < 0)) { + cbArmorType.setSelectedIndex(0); + } cbArmorType.showTechBase(techManager.useMixedTech()); } diff --git a/src/megameklab/com/ui/view/PatchworkArmorView.java b/src/megameklab/com/ui/view/PatchworkArmorView.java new file mode 100644 index 000000000..386c059be --- /dev/null +++ b/src/megameklab/com/ui/view/PatchworkArmorView.java @@ -0,0 +1,146 @@ +/* + * MegaMekLab - Copyright (C) 2017 - The MegaMek Team + * + * This program 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 2 of the License, or (at your option) + * any later version. + * + * This program 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. + */ +package megameklab.com.ui.view; + +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; +import java.util.ResourceBundle; +import java.util.concurrent.CopyOnWriteArrayList; + +import javax.swing.BorderFactory; +import javax.swing.JLabel; +import javax.swing.border.TitledBorder; + +import megamek.common.Entity; +import megamek.common.EquipmentType; +import megamek.common.ITechManager; +import megamek.common.TechConstants; +import megamek.common.util.EncodeControl; +import megameklab.com.ui.util.TechComboBox; +import megameklab.com.util.UnitUtil; + +/** + * Displays a list of comboboxes with labels that displays the current armor type per location for + * patchwork armor and allows it to be changed. + * + * @author Neoancient + * + */ +public class PatchworkArmorView extends MainUIView implements ActionListener { + + /** + * + */ + private static final long serialVersionUID = -16930846399307224L; + + public interface PatchworkListener { + void patchworkChanged(int location, EquipmentType armor); + } + private final List listeners = new CopyOnWriteArrayList<>(); + public void addListener(PatchworkListener l) { + listeners.add(l); + } + public void removeListener(PatchworkListener l) { + listeners.remove(l); + } + + private final static int MAX_LOC = 10; + + private final List labels = new ArrayList<>(); + private final List> combos = new ArrayList<>(); + + private final ITechManager techManager; + private boolean ignoreEvents = false; + + public PatchworkArmorView(ITechManager techManager) { + this.techManager = techManager; + initUI(); + } + + private void initUI() { + ResourceBundle resourceMap = ResourceBundle.getBundle("megameklab.resources.Views", new EncodeControl()); //$NON-NLS-1$ + setLayout(new GridBagLayout()); + + setBorder(BorderFactory.createTitledBorder( + null, resourceMap.getString("ArmorAllocationView.panPatwork.title"), //$NON-NLS-1$ + TitledBorder.TOP, + TitledBorder.DEFAULT_POSITION)); + + setLayout(new GridBagLayout()); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridx = 0; + gbc.gridy = 0; + gbc.insets = new Insets(0, 5, 0, 5); + for (int loc = 0; loc < MAX_LOC; loc++) { + JLabel label = new JLabel(); + TechComboBox combo = new TechComboBox<>(eq -> eq.getName()); + combo.setActionCommand(Integer.toString(loc)); + combo.addActionListener(this); + labels.add(label); + combos.add(combo); + gbc.gridx = 0; + gbc.anchor = GridBagConstraints.EAST; + add(label, gbc); + gbc.gridx = 1; + gbc.anchor = GridBagConstraints.WEST; + add(combo, gbc); + gbc.gridy++; + } + } + + public void setFromEntity(Entity en) { + List armors = UnitUtil.legalArmorsFor(en, techManager); + ignoreEvents = true; + for (int loc = 0; loc < combos.size(); loc++) { + if (loc < en.locations()) { + labels.get(loc).setText(en.getLocationName(loc)); + combos.get(loc).removeAllItems(); + for (EquipmentType eq : armors) { + combos.get(loc).addItem(eq); + } + String name = EquipmentType.getArmorTypeName(en.getArmorType(loc), + TechConstants.isClan(en.getArmorTechLevel(loc))); + combos.get(loc).setSelectedItem(EquipmentType.get(name)); + labels.get(loc).setVisible(true); + combos.get(loc).setVisible(true); + } else { + labels.get(loc).setVisible(false); + combos.get(loc).setVisible(false); + } + } + ignoreEvents = false; + } + + public EquipmentType getArmor(int location) { + return (EquipmentType)combos.get(location).getSelectedItem(); + } + + public void setArmorType(EquipmentType armor, int location) { + combos.get(location).setSelectedItem(armor); + } + + @Override + public void actionPerformed(ActionEvent e) { + if (!ignoreEvents) { + final int location = Integer.parseInt(e.getActionCommand()); + listeners.forEach(l -> l.patchworkChanged(location, getArmor(location))); + } + } + +} diff --git a/src/megameklab/com/util/UnitUtil.java b/src/megameklab/com/util/UnitUtil.java index 3b942bccd..c1d8d08ff 100644 --- a/src/megameklab/com/util/UnitUtil.java +++ b/src/megameklab/com/util/UnitUtil.java @@ -2984,6 +2984,31 @@ public static void removeISorArmorMounts(Entity unit, } } + /** + * Remove all mounts for the current armor type from a single location on the passed unit + * and sets the armor type in that location to standard. + * + * @param unit The Entity + * @param loc The location from which to remove the armor mounts. + */ + public static void resetArmor(Entity unit, int loc) { + String name = EquipmentType.getArmorTypeName(unit.getArmorType(loc), + TechConstants.isClan(unit.getArmorTechLevel(loc))); + EquipmentType eq = EquipmentType.get(name); + if (null != eq) { + for (int slot = 0; slot < unit.getNumberOfCriticals(loc); slot++) { + final CriticalSlot crit = unit.getCritical(loc, slot); + if ((null != crit) && (crit.getType() == CriticalSlot.TYPE_EQUIPMENT) + && (null != crit.getMount()) && crit.getMount().getType().equals(eq)) { + unit.getMisc().remove(crit.getMount()); + unit.setCritical(loc, slot, null); + } + } + } + unit.setArmorType(EquipmentType.T_ARMOR_STANDARD, loc); + unit.setArmorTechLevel(TechConstants.T_INTRO_BOXSET, loc); + } + public static void checkArmor(Entity unit) { if (!(unit instanceof Mech)) { diff --git a/src/megameklab/resources/Views.properties b/src/megameklab/resources/Views.properties index d15270ba9..5646d311d 100644 --- a/src/megameklab/resources/Views.properties +++ b/src/megameklab/resources/Views.properties @@ -161,6 +161,7 @@ ArmorAllocationView.txtAllocated.text=Allocated Armor Points: ArmorAllocationView.txtTotal.text=Total Armor Points: ArmorAllocationView.txtMaxPossible.text=Maximum Possible Armor Points: ArmorAllocationView.txtWasted.text=Wasted Armor Points: +ArmorAllocationView.panPatwork.title=Patchwork MovementView.lblBase.text=Base MovementView.lblFinal.text=Final From 39cbafb435342d81809f32fb4803b998aeffe0b1 Mon Sep 17 00:00:00 2001 From: Carl Spain Date: Wed, 20 Sep 2017 09:02:19 -0500 Subject: [PATCH 03/12] Added tooltips to armor location views that show points/ton and current tonnage for the location when using patchwork armor. --- .../com/ui/view/ArmorAllocationView.java | 17 ++++++++++- src/megameklab/com/util/UnitUtil.java | 29 +++++++++++++++++++ src/megameklab/resources/Views.properties | 1 + 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/megameklab/com/ui/view/ArmorAllocationView.java b/src/megameklab/com/ui/view/ArmorAllocationView.java index 9caab5d04..637c7e8ab 100644 --- a/src/megameklab/com/ui/view/ArmorAllocationView.java +++ b/src/megameklab/com/ui/view/ArmorAllocationView.java @@ -99,6 +99,7 @@ public void removeListener(ArmorLocationView.ArmorLocationListener l) { private int maxArmorPoints = 0; private int wastedPoints = 0; private boolean showPatchwork = false; + private String tooltipFormat; public ArmorAllocationView(ITechManager techManager, long entitytype) { this.entitytype = entitytype; @@ -107,6 +108,7 @@ public ArmorAllocationView(ITechManager techManager, long entitytype) { private void initUI() { ResourceBundle resourceMap = ResourceBundle.getBundle("megameklab.resources.Views", new EncodeControl()); //$NON-NLS-1$ + tooltipFormat = resourceMap.getString("ArmorAllocationView.locationTooltip.format"); setLayout(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; @@ -204,7 +206,11 @@ public void setFromEntity(Entity en) { if (showPatchwork || (currentPoints < armorPoints)) { locView.setMaxPoints(UnitUtil.getMaxArmor(en, location)); } else { - locView.setMaxPoints(en.getArmor(location, false) + en.getArmor(location, true)); + int max = en.getArmor(location, false); + if (en.hasRearArmor(location)) { + max += en.getArmor(location, true); + } + locView.setMaxPoints(max); } locView.setPoints(en.getArmor(location)); if (en.hasRearArmor(location)) { @@ -212,6 +218,15 @@ public void setFromEntity(Entity en) { } else { locView.setPointsRear(0); } + if (showPatchwork) { + double pointsPerTon = UnitUtil.getArmorPointsPerTon(en, en.getArmorType(location), en.getArmorTechLevel(location)); + double points = en.getArmor(location, false); + if (en.hasRearArmor(location)) { + points += en.getArmor(location, true); + } + locView.setToolTipText(String.format(tooltipFormat, pointsPerTon, + Math.ceil(points / pointsPerTon * 2.0) * 0.5)); + } } else { locView.setVisible(false); locView.setPoints(0); diff --git a/src/megameklab/com/util/UnitUtil.java b/src/megameklab/com/util/UnitUtil.java index c1d8d08ff..7f7a7b7c8 100644 --- a/src/megameklab/com/util/UnitUtil.java +++ b/src/megameklab/com/util/UnitUtil.java @@ -1385,6 +1385,35 @@ public static int getArmorPoints(Entity unit, int loc, double armorTons) { return Math.min((int) Math.floor(armorPerTon * armorTons), UnitUtil.getMaximumArmorPoints(unit, loc)); } + + /** + * Calculate the number of armor points per ton of armor for the given unit. + * + * @param en + * @param at + * @param clanArmor + * @return + */ + // TODO: aerospace and support vehicle armor + public static double getArmorPointsPerTon(Entity en, int at, boolean clanArmor) { + if (at == EquipmentType.T_ARMOR_HARDENED) { + return 8.0; + } else { + return 16.0 * EquipmentType.getArmorPointMultiplier(at, clanArmor); + } + } + + /** + * Calculate the number of armor points per ton of armor for the given unit. + * + * @param en + * @param at + * @param atTechLevel + * @return + */ + public static double getArmorPointsPerTon(Entity en, int at, int techLevel) { + return getArmorPointsPerTon(en, at, TechConstants.isClan(techLevel)); + } public static void compactCriticals(Entity unit) { for (int loc = 0; loc < unit.locations(); loc++) { diff --git a/src/megameklab/resources/Views.properties b/src/megameklab/resources/Views.properties index 5646d311d..04b12b911 100644 --- a/src/megameklab/resources/Views.properties +++ b/src/megameklab/resources/Views.properties @@ -162,6 +162,7 @@ ArmorAllocationView.txtTotal.text=Total Armor Points: ArmorAllocationView.txtMaxPossible.text=Maximum Possible Armor Points: ArmorAllocationView.txtWasted.text=Wasted Armor Points: ArmorAllocationView.panPatwork.title=Patchwork +ArmorAllocationView.locationTooltip.format=Points per ton: %.2f
Current tonnage: %.1f MovementView.lblBase.text=Base MovementView.lblFinal.text=Final From de6ee4a9b1922864f8f88b2f6e3f50688f41c216 Mon Sep 17 00:00:00 2001 From: Carl Spain Date: Wed, 20 Sep 2017 09:56:19 -0500 Subject: [PATCH 04/12] Recalculate and set mech armor tonnage when patchwork values are changed. --- .../com/ui/Mek/tabs/StructureTab.java | 3 +++ .../com/ui/view/ArmorAllocationView.java | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/megameklab/com/ui/Mek/tabs/StructureTab.java b/src/megameklab/com/ui/Mek/tabs/StructureTab.java index 8dde8d531..35237e210 100644 --- a/src/megameklab/com/ui/Mek/tabs/StructureTab.java +++ b/src/megameklab/com/ui/Mek/tabs/StructureTab.java @@ -1001,6 +1001,9 @@ public void armorPointsChanged(int location, int front, int rear) { if (getMech().hasRearArmor(location)) { getMech().initializeRearArmor(rear, location); } + if (panArmor.getArmorType() == EquipmentType.T_ARMOR_PATCHWORK) { + getMech().setArmorTonnage(panArmorAllocation.getTotalArmorWeight(getMech())); + } panArmorAllocation.setFromEntity(getMech()); refresh.refreshPreview(); refresh.refreshSummary(); diff --git a/src/megameklab/com/ui/view/ArmorAllocationView.java b/src/megameklab/com/ui/view/ArmorAllocationView.java index 637c7e8ab..253464dc2 100644 --- a/src/megameklab/com/ui/view/ArmorAllocationView.java +++ b/src/megameklab/com/ui/view/ArmorAllocationView.java @@ -245,6 +245,25 @@ public void setFromEntity(Entity en) { txtWasted.setText(String.valueOf(wastedPoints)); } + /** + * Helper function for patchwork. If used for non-patchwork, it will likely give incorrect values + * due to rounding up by location. + * + * @param en + * @return The total weight of all allocated armor. + */ + public double getTotalArmorWeight(Entity en) { + double weight = 0.0; + for (ArmorLocationView locView : locationViews) { + final int loc = locView.getLocationIndex(); + if (loc < en.locations()) { + double pointsPerTon = UnitUtil.getArmorPointsPerTon(en, en.getArmorType(loc), en.getArmorTechLevel(loc)); + weight += Math.ceil((locView.getPoints() + locView.getPointsRear()) / pointsPerTon * 2.0) * 0.5; + } + } + return weight; + } + public void showPatchwork(boolean show) { showPatchwork = show; } From 5eca25bf70314a784ace9f44724bebd10fd2fbd6 Mon Sep 17 00:00:00 2001 From: Carl Spain Date: Wed, 20 Sep 2017 10:52:13 -0500 Subject: [PATCH 05/12] Consolidated individual listeners for structure tab views into one base listener that is extended by a specialized listener for each unit type. --- .../com/ui/Aero/tabs/StructureTab.java | 21 ++++-- .../com/ui/BattleArmor/tabs/StructureTab.java | 8 +-- .../com/ui/Infantry/tabs/StructureTab.java | 22 +++++-- .../ui/Infantry/views/SpecializationView.java | 12 ++-- .../com/ui/Mek/tabs/StructureTab.java | 7 +- .../com/ui/Vehicle/tabs/StructureTab.java | 19 ++++-- src/megameklab/com/ui/view/AeroFuelView.java | 12 ++-- .../com/ui/view/ArmorAllocationView.java | 9 +-- .../com/ui/view/ArmorLocationView.java | 2 +- src/megameklab/com/ui/view/BAChassisView.java | 17 ++--- .../com/ui/view/BAEnhancementView.java | 12 ++-- .../com/ui/view/BAProtoArmorView.java | 13 ++-- src/megameklab/com/ui/view/BasicInfoView.java | 21 ++---- .../view/{MainUIView.java => BuildView.java} | 2 +- src/megameklab/com/ui/view/CVChassisView.java | 20 ++---- .../com/ui/view/FighterChassisView.java | 18 ++--- src/megameklab/com/ui/view/HeatSinkView.java | 14 ++-- .../com/ui/view/InfantryWeaponView.java | 14 ++-- src/megameklab/com/ui/view/MVFArmorView.java | 15 ++--- .../com/ui/view/MekChassisView.java | 24 ++----- src/megameklab/com/ui/view/MovementView.java | 14 ++-- .../com/ui/view/PatchworkArmorView.java | 12 ++-- .../com/ui/view/PlatoonTypeView.java | 19 ++---- .../ui/view/listeners/AeroBuildListener.java | 36 ++++++++++ .../ui/view/listeners/BABuildListener.java | 36 ++++++++++ .../com/ui/view/listeners/BuildListener.java | 65 +++++++++++++++++++ .../ui/view/listeners/CVBuildListener.java | 37 +++++++++++ .../view/listeners/InfantryBuildListener.java | 39 +++++++++++ .../ui/view/listeners/MekBuildListener.java | 37 +++++++++++ 29 files changed, 382 insertions(+), 195 deletions(-) rename src/megameklab/com/ui/view/{MainUIView.java => BuildView.java} (97%) create mode 100644 src/megameklab/com/ui/view/listeners/AeroBuildListener.java create mode 100644 src/megameklab/com/ui/view/listeners/BABuildListener.java create mode 100644 src/megameklab/com/ui/view/listeners/BuildListener.java create mode 100644 src/megameklab/com/ui/view/listeners/CVBuildListener.java create mode 100644 src/megameklab/com/ui/view/listeners/InfantryBuildListener.java create mode 100644 src/megameklab/com/ui/view/listeners/MekBuildListener.java diff --git a/src/megameklab/com/ui/Aero/tabs/StructureTab.java b/src/megameklab/com/ui/Aero/tabs/StructureTab.java index 7bb5b4450..fa1ca4192 100644 --- a/src/megameklab/com/ui/Aero/tabs/StructureTab.java +++ b/src/megameklab/com/ui/Aero/tabs/StructureTab.java @@ -47,17 +47,12 @@ import megameklab.com.ui.view.HeatSinkView; import megameklab.com.ui.view.MVFArmorView; import megameklab.com.ui.view.MovementView; +import megameklab.com.ui.view.listeners.AeroBuildListener; import megameklab.com.util.ITab; import megameklab.com.util.RefreshListener; import megameklab.com.util.UnitUtil; -public class StructureTab extends ITab implements - BasicInfoView.BasicInfoListener, - FighterChassisView.ChassisListener, - HeatSinkView.HeatSinkListener, - AeroFuelView.FuelListener, - MovementView.MovementListener, - MVFArmorView.ArmorListener { +public class StructureTab extends ITab implements AeroBuildListener { /** * @@ -583,4 +578,16 @@ public void fuelTonnageChanged(double tonnage) { refresh.refreshPreview(); } + @Override + public void armorPointsChanged(int location, int front, int rear) { + // TODO Auto-generated method stub + + } + + @Override + public void patchworkChanged(int location, EquipmentType armor) { + // TODO Auto-generated method stub + + } + } diff --git a/src/megameklab/com/ui/BattleArmor/tabs/StructureTab.java b/src/megameklab/com/ui/BattleArmor/tabs/StructureTab.java index f459ce70d..d6a3cb0ed 100644 --- a/src/megameklab/com/ui/BattleArmor/tabs/StructureTab.java +++ b/src/megameklab/com/ui/BattleArmor/tabs/StructureTab.java @@ -53,16 +53,12 @@ import megameklab.com.ui.view.BAProtoArmorView; import megameklab.com.ui.view.BasicInfoView; import megameklab.com.ui.view.MovementView; +import megameklab.com.ui.view.listeners.BABuildListener; import megameklab.com.util.ITab; import megameklab.com.util.RefreshListener; import megameklab.com.util.UnitUtil; -public class StructureTab extends ITab implements ActionListener, - BasicInfoView.BasicInfoListener, - BAChassisView.ChassisListener, - MovementView.MovementListener, - BAProtoArmorView.ArmorListener, - BAEnhancementView.EnhancementListener { +public class StructureTab extends ITab implements ActionListener, BABuildListener { /** * diff --git a/src/megameklab/com/ui/Infantry/tabs/StructureTab.java b/src/megameklab/com/ui/Infantry/tabs/StructureTab.java index 2f9229ec2..eba1c3638 100644 --- a/src/megameklab/com/ui/Infantry/tabs/StructureTab.java +++ b/src/megameklab/com/ui/Infantry/tabs/StructureTab.java @@ -54,15 +54,12 @@ import megameklab.com.ui.view.BasicInfoView; import megameklab.com.ui.view.InfantryWeaponView; import megameklab.com.ui.view.PlatoonTypeView; +import megameklab.com.ui.view.listeners.InfantryBuildListener; import megameklab.com.util.ITab; import megameklab.com.util.RefreshListener; import megameklab.com.util.UnitUtil; -public class StructureTab extends ITab implements - BasicInfoView.BasicInfoListener, - PlatoonTypeView.PlatoonListener, - InfantryWeaponView.WeaponListener, - SpecializationView.SpecializationListener { +public class StructureTab extends ITab implements InfantryBuildListener { /** * @@ -456,4 +453,19 @@ public void antiMekChanged(final boolean antiMek) { refresh.refreshStatus(); } + @Override + public void walkChanged(int walkMP) { + // not used by conventional infantry + } + + @Override + public void jumpChanged(int jumpMP, EquipmentType jumpJet) { + // not used by conventional infantry + } + + @Override + public void jumpTypeChanged(EquipmentType jumpJet) { + // not used by conventional infantry + } + } \ No newline at end of file diff --git a/src/megameklab/com/ui/Infantry/views/SpecializationView.java b/src/megameklab/com/ui/Infantry/views/SpecializationView.java index 4992663d7..c9bd84576 100644 --- a/src/megameklab/com/ui/Infantry/views/SpecializationView.java +++ b/src/megameklab/com/ui/Infantry/views/SpecializationView.java @@ -37,6 +37,7 @@ import megamek.common.TechAdvancement; import megamek.common.verifier.TestInfantry; import megameklab.com.ui.EntitySource; +import megameklab.com.ui.view.listeners.InfantryBuildListener; import megameklab.com.util.IView; import megameklab.com.util.RefreshListener; import megameklab.com.util.UnitUtil; @@ -52,14 +53,11 @@ public class SpecializationView extends IView implements TableModelListener { private static final long serialVersionUID = -5851020780074510576L; - public interface SpecializationListener { - void specializationsChanged(); - } - private List listeners = new CopyOnWriteArrayList<>(); - public void addListener(SpecializationListener l) { + private List listeners = new CopyOnWriteArrayList<>(); + public void addListener(InfantryBuildListener l) { listeners.add(l); } - public void removeListener(SpecializationListener l) { + public void removeListener(InfantryBuildListener l) { listeners.remove(l); } @@ -124,7 +122,7 @@ public boolean include(Entry e @Override public void tableChanged(TableModelEvent e) { - listeners.forEach(SpecializationListener::specializationsChanged); + listeners.forEach(InfantryBuildListener::specializationsChanged); } private class SpecializationModel extends AbstractTableModel { diff --git a/src/megameklab/com/ui/Mek/tabs/StructureTab.java b/src/megameklab/com/ui/Mek/tabs/StructureTab.java index 35237e210..189a63130 100644 --- a/src/megameklab/com/ui/Mek/tabs/StructureTab.java +++ b/src/megameklab/com/ui/Mek/tabs/StructureTab.java @@ -52,21 +52,18 @@ import megameklab.com.ui.EntitySource; import megameklab.com.ui.Mek.views.SummaryView; import megameklab.com.ui.view.ArmorAllocationView; -import megameklab.com.ui.view.ArmorLocationView; import megameklab.com.ui.view.BasicInfoView; import megameklab.com.ui.view.HeatSinkView; import megameklab.com.ui.view.MVFArmorView; import megameklab.com.ui.view.MekChassisView; import megameklab.com.ui.view.MovementView; import megameklab.com.ui.view.PatchworkArmorView; +import megameklab.com.ui.view.listeners.MekBuildListener; import megameklab.com.util.ITab; import megameklab.com.util.RefreshListener; import megameklab.com.util.UnitUtil; -public class StructureTab extends ITab implements BasicInfoView.BasicInfoListener, - MekChassisView.MekChassisListener, HeatSinkView.HeatSinkListener, MVFArmorView.ArmorListener, - MovementView.MovementListener, ArmorLocationView.ArmorLocationListener, - PatchworkArmorView.PatchworkListener { +public class StructureTab extends ITab implements MekBuildListener { /** * */ diff --git a/src/megameklab/com/ui/Vehicle/tabs/StructureTab.java b/src/megameklab/com/ui/Vehicle/tabs/StructureTab.java index 9330cefa9..765cbdf8a 100644 --- a/src/megameklab/com/ui/Vehicle/tabs/StructureTab.java +++ b/src/megameklab/com/ui/Vehicle/tabs/StructureTab.java @@ -52,15 +52,12 @@ import megameklab.com.ui.view.CVChassisView; import megameklab.com.ui.view.MVFArmorView; import megameklab.com.ui.view.MovementView; +import megameklab.com.ui.view.listeners.CVBuildListener; import megameklab.com.util.ITab; import megameklab.com.util.RefreshListener; import megameklab.com.util.UnitUtil; -public class StructureTab extends ITab implements - BasicInfoView.BasicInfoListener, - CVChassisView.ChassisListener, - MovementView.MovementListener, - MVFArmorView.ArmorListener { +public class StructureTab extends ITab implements CVBuildListener { /** * @@ -619,4 +616,16 @@ public void resetChassis() { refresh.refreshPreview(); refresh.refreshStatus(); } + + @Override + public void armorPointsChanged(int location, int front, int rear) { + // TODO Auto-generated method stub + + } + + @Override + public void patchworkChanged(int location, EquipmentType armor) { + // TODO Auto-generated method stub + + } } diff --git a/src/megameklab/com/ui/view/AeroFuelView.java b/src/megameklab/com/ui/view/AeroFuelView.java index 3c28f5615..778421ce5 100644 --- a/src/megameklab/com/ui/view/AeroFuelView.java +++ b/src/megameklab/com/ui/view/AeroFuelView.java @@ -32,6 +32,7 @@ import megamek.common.Entity; import megamek.common.util.EncodeControl; import megamek.common.verifier.TestAero; +import megameklab.com.ui.view.listeners.AeroBuildListener; /** * Structure tab panel for aero unit fuel @@ -39,21 +40,18 @@ * @author Neoancient * */ -public class AeroFuelView extends MainUIView implements ChangeListener { +public class AeroFuelView extends BuildView implements ChangeListener { /** * */ private static final long serialVersionUID = -3321986392656071192L; - public interface FuelListener { - void fuelTonnageChanged(double tonnage); - } - List listeners = new CopyOnWriteArrayList<>(); - public void addListener(FuelListener l) { + List listeners = new CopyOnWriteArrayList<>(); + public void addListener(AeroBuildListener l) { listeners.add(l); } - public void removeListener(FuelListener l) { + public void removeListener(AeroBuildListener l) { listeners.remove(l); } diff --git a/src/megameklab/com/ui/view/ArmorAllocationView.java b/src/megameklab/com/ui/view/ArmorAllocationView.java index 253464dc2..6c91e2da9 100644 --- a/src/megameklab/com/ui/view/ArmorAllocationView.java +++ b/src/megameklab/com/ui/view/ArmorAllocationView.java @@ -35,6 +35,7 @@ import megamek.common.Tank; import megamek.common.VTOL; import megamek.common.util.EncodeControl; +import megameklab.com.ui.view.listeners.BuildListener; import megameklab.com.util.UnitUtil; /** @@ -45,7 +46,7 @@ * @author Neoancient * */ -public class ArmorAllocationView extends MainUIView implements +public class ArmorAllocationView extends BuildView implements ArmorLocationView.ArmorLocationListener { /** @@ -53,11 +54,11 @@ public class ArmorAllocationView extends MainUIView implements */ private static final long serialVersionUID = 1707528067499186372L; - private final List listeners = new CopyOnWriteArrayList<>(); - public void addListener(ArmorLocationView.ArmorLocationListener l) { + private final List listeners = new CopyOnWriteArrayList<>(); + public void addListener(BuildListener l) { listeners.add(l); } - public void removeListener(ArmorLocationView.ArmorLocationListener l) { + public void removeListener(BuildListener l) { listeners.remove(l); } diff --git a/src/megameklab/com/ui/view/ArmorLocationView.java b/src/megameklab/com/ui/view/ArmorLocationView.java index beb09775f..b5c182add 100644 --- a/src/megameklab/com/ui/view/ArmorLocationView.java +++ b/src/megameklab/com/ui/view/ArmorLocationView.java @@ -37,7 +37,7 @@ * @author Neoancient * */ -public class ArmorLocationView extends MainUIView implements ChangeListener { +public class ArmorLocationView extends BuildView implements ChangeListener { /** * diff --git a/src/megameklab/com/ui/view/BAChassisView.java b/src/megameklab/com/ui/view/BAChassisView.java index f17eee2c2..3f0f11463 100644 --- a/src/megameklab/com/ui/view/BAChassisView.java +++ b/src/megameklab/com/ui/view/BAChassisView.java @@ -35,6 +35,7 @@ import megamek.common.ITechManager; import megamek.common.util.EncodeControl; import megameklab.com.ui.util.CustomComboBox; +import megameklab.com.ui.view.listeners.BABuildListener; /** * Structure tab chassis view for BattleArmor @@ -42,26 +43,18 @@ * @author Neoancient * */ -public class BAChassisView extends MainUIView implements ActionListener, ChangeListener { +public class BAChassisView extends BuildView implements ActionListener, ChangeListener { /** * */ private static final long serialVersionUID = 2230418263440532689L; - public interface ChassisListener { - void chassisTypeChanged(int bodyType); - void weightClassChanged(int weightClass); - void turretChanged(int type, int size); - void exoskeletonChanged(boolean exoskeleton); - void harjelChanged(boolean harjel); - void squadSizeChanged(int squadSize); - } - private final List listeners = new CopyOnWriteArrayList<>(); - public void addListener(ChassisListener l) { + private final List listeners = new CopyOnWriteArrayList<>(); + public void addListener(BABuildListener l) { listeners.add(l); } - public void removeListener(ChassisListener l) { + public void removeListener(BABuildListener l) { listeners.remove(l); } diff --git a/src/megameklab/com/ui/view/BAEnhancementView.java b/src/megameklab/com/ui/view/BAEnhancementView.java index 84fc8388b..76a45ee36 100644 --- a/src/megameklab/com/ui/view/BAEnhancementView.java +++ b/src/megameklab/com/ui/view/BAEnhancementView.java @@ -29,6 +29,7 @@ import megamek.common.ITechManager; import megamek.common.MiscType; import megamek.common.util.EncodeControl; +import megameklab.com.ui.view.listeners.BABuildListener; /** * Structure tab panel for BA movement enhancements @@ -36,21 +37,18 @@ * @author Neoancient * */ -public class BAEnhancementView extends MainUIView implements ActionListener { +public class BAEnhancementView extends BuildView implements ActionListener { /** * */ private static final long serialVersionUID = 6181555446271444880L; - public interface EnhancementListener { - void enhancementChanged(EquipmentType eq, boolean selected); - } - private List listeners = new CopyOnWriteArrayList<>(); - public void addListener(EnhancementListener l) { + private List listeners = new CopyOnWriteArrayList<>(); + public void addListener(BABuildListener l) { listeners.add(l); } - public void removeListener(EnhancementListener l) { + public void removeListener(BABuildListener l) { listeners.remove(l); } diff --git a/src/megameklab/com/ui/view/BAProtoArmorView.java b/src/megameklab/com/ui/view/BAProtoArmorView.java index 33a8704cf..2c2bdfebd 100644 --- a/src/megameklab/com/ui/view/BAProtoArmorView.java +++ b/src/megameklab/com/ui/view/BAProtoArmorView.java @@ -35,6 +35,7 @@ import megamek.common.TechConstants; import megamek.common.util.EncodeControl; import megameklab.com.ui.util.TechComboBox; +import megameklab.com.ui.view.listeners.BuildListener; /** * Structure table armor panel for units that allocate armor by point instead of ton. @@ -42,22 +43,18 @@ * @author Neoancient * */ -public class BAProtoArmorView extends MainUIView implements ActionListener, ChangeListener { +public class BAProtoArmorView extends BuildView implements ActionListener, ChangeListener { /** * */ private static final long serialVersionUID = 14527455823813010L; - public interface ArmorListener { - void armorValueChanged(int points); - void armorTypeChanged(EquipmentType armor); - } - private final List listeners = new CopyOnWriteArrayList<>(); - public void addListener(ArmorListener l) { + private final List listeners = new CopyOnWriteArrayList<>(); + public void addListener(BuildListener l) { listeners.add(l); } - public void removeListener(ArmorListener l) { + public void removeListener(BuildListener l) { listeners.remove(l); } diff --git a/src/megameklab/com/ui/view/BasicInfoView.java b/src/megameklab/com/ui/view/BasicInfoView.java index 272ed63d1..e8abe6a0c 100644 --- a/src/megameklab/com/ui/view/BasicInfoView.java +++ b/src/megameklab/com/ui/view/BasicInfoView.java @@ -37,6 +37,7 @@ import megameklab.com.ui.util.CustomComboBox; import megameklab.com.ui.util.FactionComboBox; import megameklab.com.ui.util.IntRangeTextField; +import megameklab.com.ui.view.listeners.BuildListener; import megameklab.com.util.CConfig; /** @@ -45,32 +46,20 @@ * @author Neoancient * */ -public class BasicInfoView extends MainUIView implements ITechManager, ActionListener, FocusListener { +public class BasicInfoView extends BuildView implements ITechManager, ActionListener, FocusListener { /** * */ private static final long serialVersionUID = -6831478201489228066L; - public interface BasicInfoListener { - void refreshSummary(); - void chassisChanged(String chassis); - void modelChanged(String model); - void yearChanged(int year); - void updateTechLevel(); - void sourceChanged(String source); - void techBaseChanged(boolean clan, boolean mixed); - void techLevelChanged(SimpleTechLevel techLevel); - void manualBVChanged(int manualBV); - } - - private List listeners = new CopyOnWriteArrayList<>(); - public void addListener(BasicInfoListener l) { + private List listeners = new CopyOnWriteArrayList<>(); + public void addListener(BuildListener l) { if (null != l) { listeners.add(l); } } - public void removeListener(BasicInfoListener l) { + public void removeListener(BuildListener l) { listeners.remove(l); } diff --git a/src/megameklab/com/ui/view/MainUIView.java b/src/megameklab/com/ui/view/BuildView.java similarity index 97% rename from src/megameklab/com/ui/view/MainUIView.java rename to src/megameklab/com/ui/view/BuildView.java index 9006897b4..16c560aeb 100644 --- a/src/megameklab/com/ui/view/MainUIView.java +++ b/src/megameklab/com/ui/view/BuildView.java @@ -27,7 +27,7 @@ * @author Neoancient * */ -public abstract class MainUIView extends JPanel { +public abstract class BuildView extends JPanel { /** * diff --git a/src/megameklab/com/ui/view/CVChassisView.java b/src/megameklab/com/ui/view/CVChassisView.java index 12aa109c7..1e714ef50 100644 --- a/src/megameklab/com/ui/view/CVChassisView.java +++ b/src/megameklab/com/ui/view/CVChassisView.java @@ -44,6 +44,7 @@ import megamek.common.util.EncodeControl; import megameklab.com.ui.util.CustomComboBox; import megameklab.com.ui.util.TechComboBox; +import megameklab.com.ui.view.listeners.CVBuildListener; /** * Chassis panel for combat vehicles @@ -51,29 +52,18 @@ * @author Neoancient * */ -public class CVChassisView extends MainUIView implements ActionListener, ChangeListener { +public class CVChassisView extends BuildView implements ActionListener, ChangeListener { /** * */ private static final long serialVersionUID = -5860627963911641227L; - public interface ChassisListener { - void tonnageChanged(double tonnage); - void omniChanged(boolean omni); - void superheavyChanged(boolean superheavy); - void motiveChanged(EntityMovementMode motive); - void engineChanged(Engine engine); - void turretChanged(int turretConfig); - void turretBaseWtChanged(double turret1, double turret2); - void troopSpaceChanged(double fixed, double pod); - void resetChassis(); - } - List listeners = new CopyOnWriteArrayList<>(); - public void addListener(ChassisListener l) { + List listeners = new CopyOnWriteArrayList<>(); + public void addListener(CVBuildListener l) { listeners.add(l); } - public void removeListener(ChassisListener l) { + public void removeListener(CVBuildListener l) { listeners.remove(l); } diff --git a/src/megameklab/com/ui/view/FighterChassisView.java b/src/megameklab/com/ui/view/FighterChassisView.java index 921ad1f60..3bc62661f 100644 --- a/src/megameklab/com/ui/view/FighterChassisView.java +++ b/src/megameklab/com/ui/view/FighterChassisView.java @@ -38,6 +38,7 @@ import megamek.common.util.EncodeControl; import megameklab.com.ui.util.CustomComboBox; import megameklab.com.ui.util.TechComboBox; +import megameklab.com.ui.view.listeners.AeroBuildListener; /** * Structure tab chassis panel for aerospace and conventional fighters. @@ -45,27 +46,18 @@ * @author Neoancient * */ -public class FighterChassisView extends MainUIView implements ActionListener, ChangeListener { +public class FighterChassisView extends BuildView implements ActionListener, ChangeListener { /** * */ private static final long serialVersionUID = -1129246135285707937L; - public interface ChassisListener { - void tonnageChanged(double tonnage); - void omniChanged(boolean omni); - void vstolChanged(boolean vstol); - void fighterTypeChanged(int type); - void engineChanged(Engine engine); - void cockpitChanged(int cockpitType); - void resetChassis(); - } - private final List listeners = new CopyOnWriteArrayList<>(); - public void addListener(ChassisListener l) { + private final List listeners = new CopyOnWriteArrayList<>(); + public void addListener(AeroBuildListener l) { listeners.add(l); } - public void removeListener(ChassisListener l) { + public void removeListener(AeroBuildListener l) { listeners.remove(l); } diff --git a/src/megameklab/com/ui/view/HeatSinkView.java b/src/megameklab/com/ui/view/HeatSinkView.java index ed6aadae6..986be82a1 100644 --- a/src/megameklab/com/ui/view/HeatSinkView.java +++ b/src/megameklab/com/ui/view/HeatSinkView.java @@ -36,6 +36,7 @@ import megamek.common.Mounted; import megamek.common.util.EncodeControl; import megameklab.com.ui.util.CustomComboBox; +import megameklab.com.ui.view.listeners.BuildListener; import megameklab.com.util.UnitUtil; /** @@ -44,23 +45,18 @@ * @author Neoancient * */ -public class HeatSinkView extends MainUIView implements ActionListener, ChangeListener { +public class HeatSinkView extends BuildView implements ActionListener, ChangeListener { /** * */ private static final long serialVersionUID = -3310994380270514088L; - public interface HeatSinkListener { - void heatSinksChanged(int index, int count); - void heatSinksChanged(EquipmentType hsType, int count); - void heatSinkBaseCountChanged(int count); - } - private final List listeners = new CopyOnWriteArrayList<>(); - public void addListener(HeatSinkListener l) { + private final List listeners = new CopyOnWriteArrayList<>(); + public void addListener(BuildListener l) { listeners.add(l); } - public void removeListener(HeatSinkListener l) { + public void removeListener(BuildListener l) { listeners.remove(l); } diff --git a/src/megameklab/com/ui/view/InfantryWeaponView.java b/src/megameklab/com/ui/view/InfantryWeaponView.java index 9a18334cb..5b29eb006 100644 --- a/src/megameklab/com/ui/view/InfantryWeaponView.java +++ b/src/megameklab/com/ui/view/InfantryWeaponView.java @@ -40,6 +40,7 @@ import megamek.common.verifier.TestInfantry; import megamek.common.weapons.artillery.ArtilleryCannonWeapon; import megamek.common.weapons.artillery.ArtilleryWeapon; +import megameklab.com.ui.view.listeners.InfantryBuildListener; import megameklab.com.util.UnitUtil; /** @@ -49,23 +50,18 @@ * @author Neoancient * */ -public class InfantryWeaponView extends MainUIView implements ActionListener { +public class InfantryWeaponView extends BuildView implements ActionListener { /** * */ private static final long serialVersionUID = 6150492212690074504L; - public interface WeaponListener { - void numSecondaryChanged(int count); - void numFieldGunsChanged(int count); - void antiMekChanged(boolean antiMek); - } - private List listeners = new CopyOnWriteArrayList<>(); - public void addListener(WeaponListener l) { + private List listeners = new CopyOnWriteArrayList<>(); + public void addListener(InfantryBuildListener l) { listeners.add(l); } - public void removeListener(WeaponListener l) { + public void removeListener(InfantryBuildListener l) { listeners.remove(l); } diff --git a/src/megameklab/com/ui/view/MVFArmorView.java b/src/megameklab/com/ui/view/MVFArmorView.java index 24136f8e0..d009cc9b9 100644 --- a/src/megameklab/com/ui/view/MVFArmorView.java +++ b/src/megameklab/com/ui/view/MVFArmorView.java @@ -39,6 +39,7 @@ import megamek.common.TechConstants; import megamek.common.util.EncodeControl; import megameklab.com.ui.util.TechComboBox; +import megameklab.com.ui.view.listeners.BuildListener; import megameklab.com.util.UnitUtil; /** @@ -47,24 +48,18 @@ * @author Neoancient * */ -public class MVFArmorView extends MainUIView implements ActionListener, ChangeListener { +public class MVFArmorView extends BuildView implements ActionListener, ChangeListener { /** * */ private static final long serialVersionUID = 1246552271894765543L; - public interface ArmorListener { - void armorTypeChanged(int at, int armorTechLevel); - void armorTonnageChanged(double tonnage); - void maximizeArmor(); - void useRemainingTonnageArmor(); - } - private final List listeners = new CopyOnWriteArrayList<>(); - public void addListener(ArmorListener l) { + private final List listeners = new CopyOnWriteArrayList<>(); + public void addListener(BuildListener l) { listeners.add(l); } - public void removeListener(ArmorListener l) { + public void removeListener(BuildListener l) { listeners.remove(l); } diff --git a/src/megameklab/com/ui/view/MekChassisView.java b/src/megameklab/com/ui/view/MekChassisView.java index f8d880d44..cd6a62709 100644 --- a/src/megameklab/com/ui/view/MekChassisView.java +++ b/src/megameklab/com/ui/view/MekChassisView.java @@ -48,6 +48,7 @@ import megamek.common.util.EncodeControl; import megameklab.com.ui.util.CustomComboBox; import megameklab.com.ui.util.TechComboBox; +import megameklab.com.ui.view.listeners.MekBuildListener; /** * Construction options and systems for Meks. @@ -55,31 +56,18 @@ * @author Neoancient * */ -public class MekChassisView extends MainUIView implements ActionListener, ChangeListener { +public class MekChassisView extends BuildView implements ActionListener, ChangeListener { /** * */ private static final long serialVersionUID = -2620071922845931509L; - public interface MekChassisListener { - void refreshSummary(); - void tonnageChanged(double tonnage); - void omniChanged(boolean omni); - void typeChanged(int baseType, int motiveType, long etype); - void structureChanged(EquipmentType structure); - void engineChanged(Engine engine); - void gyroChanged(int gyroType); - void cockpitChanged(int cockpitType); - void enhancementChanged(EquipmentType enhancement); - void fullHeadEjectChanged(boolean eject); - void resetChassis(); - } - List listeners = new CopyOnWriteArrayList<>(); - public void addListener(MekChassisListener l) { + List listeners = new CopyOnWriteArrayList<>(); + public void addListener(MekBuildListener l) { listeners.add(l); } - public void removeListener(MekChassisListener l) { + public void removeListener(MekBuildListener l) { listeners.remove(l); } @@ -764,7 +752,7 @@ public void actionPerformed(ActionEvent e) { } else if (e.getSource() == chkFullHeadEject) { listeners.forEach(l -> l.fullHeadEjectChanged(chkFullHeadEject.isSelected())); } else if (e.getSource() == btnResetChassis) { - listeners.forEach(MekChassisListener::resetChassis); + listeners.forEach(MekBuildListener::resetChassis); } refresh(); } diff --git a/src/megameklab/com/ui/view/MovementView.java b/src/megameklab/com/ui/view/MovementView.java index 9fe58dd2f..486f7d848 100644 --- a/src/megameklab/com/ui/view/MovementView.java +++ b/src/megameklab/com/ui/view/MovementView.java @@ -45,6 +45,7 @@ import megamek.common.verifier.TestEntity; import megamek.common.verifier.TestMech; import megameklab.com.ui.util.TechComboBox; +import megameklab.com.ui.view.listeners.BuildListener; /** * Controls for setting a unit's speed @@ -52,23 +53,18 @@ * @author Neoancient * */ -public class MovementView extends MainUIView implements ActionListener, ChangeListener { +public class MovementView extends BuildView implements ActionListener, ChangeListener { /** * */ private static final long serialVersionUID = 9047797409742756926L; - public interface MovementListener { - void walkChanged(int walkMP); - void jumpChanged(int jumpMP, EquipmentType jumpJet); - void jumpTypeChanged(EquipmentType jumpJet); - } - private final List listeners = new CopyOnWriteArrayList<>(); - public void addListener(MovementListener l) { + private final List listeners = new CopyOnWriteArrayList<>(); + public void addListener(BuildListener l) { listeners.add(l); } - public void removeListener(MovementListener l) { + public void removeListener(BuildListener l) { listeners.remove(l); } diff --git a/src/megameklab/com/ui/view/PatchworkArmorView.java b/src/megameklab/com/ui/view/PatchworkArmorView.java index 386c059be..94c8ca467 100644 --- a/src/megameklab/com/ui/view/PatchworkArmorView.java +++ b/src/megameklab/com/ui/view/PatchworkArmorView.java @@ -33,6 +33,7 @@ import megamek.common.TechConstants; import megamek.common.util.EncodeControl; import megameklab.com.ui.util.TechComboBox; +import megameklab.com.ui.view.listeners.BuildListener; import megameklab.com.util.UnitUtil; /** @@ -42,21 +43,18 @@ * @author Neoancient * */ -public class PatchworkArmorView extends MainUIView implements ActionListener { +public class PatchworkArmorView extends BuildView implements ActionListener { /** * */ private static final long serialVersionUID = -16930846399307224L; - public interface PatchworkListener { - void patchworkChanged(int location, EquipmentType armor); - } - private final List listeners = new CopyOnWriteArrayList<>(); - public void addListener(PatchworkListener l) { + private final List listeners = new CopyOnWriteArrayList<>(); + public void addListener(BuildListener l) { listeners.add(l); } - public void removeListener(PatchworkListener l) { + public void removeListener(BuildListener l) { listeners.remove(l); } diff --git a/src/megameklab/com/ui/view/PlatoonTypeView.java b/src/megameklab/com/ui/view/PlatoonTypeView.java index a46ab71d9..5fae4fc0f 100644 --- a/src/megameklab/com/ui/view/PlatoonTypeView.java +++ b/src/megameklab/com/ui/view/PlatoonTypeView.java @@ -34,6 +34,7 @@ import megamek.common.util.EncodeControl; import megamek.common.verifier.TestInfantry; import megameklab.com.ui.util.CustomComboBox; +import megameklab.com.ui.view.listeners.InfantryBuildListener; /** * Infantry structure tab panel for selecting platoon movement type and number/size of squads. @@ -41,28 +42,18 @@ * @author Neoancient * */ -public class PlatoonTypeView extends MainUIView implements ActionListener, ChangeListener { +public class PlatoonTypeView extends BuildView implements ActionListener, ChangeListener { /** * */ private static final long serialVersionUID = -7227731728613831387L; - public interface PlatoonListener { - /** - * @param motiveType The selected motive type - * @param alt If motiveType is VTOL or INF_UMU, alt is true for microlite and motorized scuba - * respectively, false for microcopter and foot scuba. It has no meaning for other - * motive types. - */ - void motiveTypeChanged(EntityMovementMode motiveType, boolean alt); - void platoonSizeChanged(int numSquads, int squadSize); - } - List listeners = new CopyOnWriteArrayList<>(); - public void addListener(PlatoonListener l) { + List listeners = new CopyOnWriteArrayList<>(); + public void addListener(InfantryBuildListener l) { listeners.add(l); } - public void removeListener(PlatoonListener l) { + public void removeListener(InfantryBuildListener l) { listeners.remove(l); } diff --git a/src/megameklab/com/ui/view/listeners/AeroBuildListener.java b/src/megameklab/com/ui/view/listeners/AeroBuildListener.java new file mode 100644 index 000000000..7945d8ee1 --- /dev/null +++ b/src/megameklab/com/ui/view/listeners/AeroBuildListener.java @@ -0,0 +1,36 @@ +/* + * MegaMekLab - Copyright (C) 2017 - The MegaMek Team + * + * This program 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 2 of the License, or (at your option) + * any later version. + * + * This program 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. + */ +package megameklab.com.ui.view.listeners; + +import megamek.common.Engine; + +/** + * Listener for views used by aerospace units. + * + * @author Neoancient + * + */ +public interface AeroBuildListener extends BuildListener { + + void tonnageChanged(double tonnage); + void omniChanged(boolean omni); + void vstolChanged(boolean vstol); + void fighterTypeChanged(int type); + void engineChanged(Engine engine); + void cockpitChanged(int cockpitType); + void resetChassis(); + + void fuelTonnageChanged(double tonnage); + +} diff --git a/src/megameklab/com/ui/view/listeners/BABuildListener.java b/src/megameklab/com/ui/view/listeners/BABuildListener.java new file mode 100644 index 000000000..e675d9a46 --- /dev/null +++ b/src/megameklab/com/ui/view/listeners/BABuildListener.java @@ -0,0 +1,36 @@ +/* + * MegaMekLab - Copyright (C) 2017 - The MegaMek Team + * + * This program 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 2 of the License, or (at your option) + * any later version. + * + * This program 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. + */ + +package megameklab.com.ui.view.listeners; + +import megamek.common.EquipmentType; + +/** + * Listener for views used by BattleArmor. + * + * @author Neoancient + * + */ +public interface BABuildListener extends BuildListener { + void chassisTypeChanged(int bodyType); + void weightClassChanged(int weightClass); + void turretChanged(int type, int size); + void exoskeletonChanged(boolean exoskeleton); + void harjelChanged(boolean harjel); + void squadSizeChanged(int squadSize); + void enhancementChanged(EquipmentType eq, boolean selected); + + void armorValueChanged(int points); + void armorTypeChanged(EquipmentType armor); +} diff --git a/src/megameklab/com/ui/view/listeners/BuildListener.java b/src/megameklab/com/ui/view/listeners/BuildListener.java new file mode 100644 index 000000000..09dc925bd --- /dev/null +++ b/src/megameklab/com/ui/view/listeners/BuildListener.java @@ -0,0 +1,65 @@ +/* + * MegaMekLab - Copyright (C) 2017 - The MegaMek Team + * + * This program 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 2 of the License, or (at your option) + * any later version. + * + * This program 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. + */ +package megameklab.com.ui.view.listeners; + +import megamek.common.EquipmentType; +import megamek.common.SimpleTechLevel; + +/** + * Combined listener interface for the various subviews of the structure tab. Includes callbacks + * used by multiple unit types. Listeners for specific unit types extend this one. + * + * @author Neoancient + * + */ +public interface BuildListener { + + void refreshSummary(); + void chassisChanged(String chassis); + void modelChanged(String model); + void yearChanged(int year); + void updateTechLevel(); + void sourceChanged(String source); + void techBaseChanged(boolean clan, boolean mixed); + void techLevelChanged(SimpleTechLevel techLevel); + void manualBVChanged(int manualBV); + + void walkChanged(int walkMP); + void jumpChanged(int jumpMP, EquipmentType jumpJet); + void jumpTypeChanged(EquipmentType jumpJet); + + /* + * Methods used by multiple unit types but not all are given default implementations that + * ignore them. + */ + + default void heatSinksChanged(int index, int count) {}; + default void heatSinksChanged(EquipmentType hsType, int count) {}; + default void heatSinkBaseCountChanged(int count) {}; + + // For units that allocate armor by tonnage + default void armorTypeChanged(int at, int armorTechLevel) {}; + default void armorTonnageChanged(double tonnage) {}; + default void maximizeArmor() {}; + default void useRemainingTonnageArmor() {}; + + // For units that allocate armor by point + default void armorValueChanged(int points) {}; + default void armorTypeChanged(EquipmentType armor) {}; + + // For units that allocate armor to location + default void armorPointsChanged(int location, int front, int rear) {}; + default void patchworkChanged(int location, EquipmentType armor) {}; + +} diff --git a/src/megameklab/com/ui/view/listeners/CVBuildListener.java b/src/megameklab/com/ui/view/listeners/CVBuildListener.java new file mode 100644 index 000000000..589f25ebb --- /dev/null +++ b/src/megameklab/com/ui/view/listeners/CVBuildListener.java @@ -0,0 +1,37 @@ +/* + * MegaMekLab - Copyright (C) 2017 - The MegaMek Team + * + * This program 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 2 of the License, or (at your option) + * any later version. + * + * This program 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. + */ +package megameklab.com.ui.view.listeners; + +import megamek.common.Engine; +import megamek.common.EntityMovementMode; + +/** + * Listener for views used by combat vehicles. + * + * @author Neoancient + * + */ +public interface CVBuildListener extends BuildListener { + + void tonnageChanged(double tonnage); + void omniChanged(boolean omni); + void superheavyChanged(boolean superheavy); + void motiveChanged(EntityMovementMode motive); + void engineChanged(Engine engine); + void turretChanged(int turretConfig); + void turretBaseWtChanged(double turret1, double turret2); + void troopSpaceChanged(double fixed, double pod); + void resetChassis(); + +} diff --git a/src/megameklab/com/ui/view/listeners/InfantryBuildListener.java b/src/megameklab/com/ui/view/listeners/InfantryBuildListener.java new file mode 100644 index 000000000..915ba9196 --- /dev/null +++ b/src/megameklab/com/ui/view/listeners/InfantryBuildListener.java @@ -0,0 +1,39 @@ +/* + * MegaMekLab - Copyright (C) 2017 - The MegaMek Team + * + * This program 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 2 of the License, or (at your option) + * any later version. + * + * This program 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. + */ +package megameklab.com.ui.view.listeners; + +import megamek.common.EntityMovementMode; + +/** + * Listener for views used by conventional infantry. + * + * @author Neoancient + * + */ +public interface InfantryBuildListener extends BuildListener { + void numSecondaryChanged(int count); + void numFieldGunsChanged(int count); + void antiMekChanged(boolean antiMek); + + /** + * @param motiveType The selected motive type + * @param alt If motiveType is VTOL or INF_UMU, alt is true for microlite and motorized scuba + * respectively, false for microcopter and foot scuba. It has no meaning for other + * motive types. + */ + void motiveTypeChanged(EntityMovementMode motiveType, boolean alt); + void platoonSizeChanged(int numSquads, int squadSize); + + void specializationsChanged(); +} diff --git a/src/megameklab/com/ui/view/listeners/MekBuildListener.java b/src/megameklab/com/ui/view/listeners/MekBuildListener.java new file mode 100644 index 000000000..5733edec9 --- /dev/null +++ b/src/megameklab/com/ui/view/listeners/MekBuildListener.java @@ -0,0 +1,37 @@ +/* + * MegaMekLab - Copyright (C) 2017 - The MegaMek Team + * + * This program 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 2 of the License, or (at your option) + * any later version. + * + * This program 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. + */ +package megameklab.com.ui.view.listeners; + +import megamek.common.Engine; +import megamek.common.EquipmentType; + +/** + * Listener for views used by Meks. + * + * @author Neoancient + * + */ +public interface MekBuildListener extends BuildListener { + void tonnageChanged(double tonnage); + void omniChanged(boolean omni); + void typeChanged(int baseType, int motiveType, long etype); + void structureChanged(EquipmentType structure); + void engineChanged(Engine engine); + void gyroChanged(int gyroType); + void cockpitChanged(int cockpitType); + void enhancementChanged(EquipmentType enhancement); + void fullHeadEjectChanged(boolean eject); + void resetChassis(); + +} From b43209a5b7c4d4678eeaaa46007280d73b942c9c Mon Sep 17 00:00:00 2001 From: Carl Spain Date: Wed, 20 Sep 2017 11:46:47 -0500 Subject: [PATCH 06/12] Switch aero structure tab to new armor allocation views. --- .../com/ui/Aero/tabs/StructureTab.java | 158 ++++++++++-------- .../com/ui/Mek/tabs/StructureTab.java | 1 - src/megameklab/com/ui/view/MVFArmorView.java | 4 +- .../com/ui/view/PatchworkArmorView.java | 6 +- src/megameklab/com/util/UnitUtil.java | 12 +- 5 files changed, 103 insertions(+), 78 deletions(-) diff --git a/src/megameklab/com/ui/Aero/tabs/StructureTab.java b/src/megameklab/com/ui/Aero/tabs/StructureTab.java index fa1ca4192..98dfb5dc7 100644 --- a/src/megameklab/com/ui/Aero/tabs/StructureTab.java +++ b/src/megameklab/com/ui/Aero/tabs/StructureTab.java @@ -35,18 +35,21 @@ import megamek.common.Entity; import megamek.common.EquipmentType; import megamek.common.ITechManager; +import megamek.common.LocationFullException; +import megamek.common.Mounted; import megamek.common.SimpleTechLevel; import megamek.common.verifier.TestAero; import megamek.common.verifier.TestEntity; import megameklab.com.ui.EntitySource; -import megameklab.com.ui.Aero.views.ArmorView; import megameklab.com.ui.Aero.views.SummaryView; import megameklab.com.ui.view.AeroFuelView; +import megameklab.com.ui.view.ArmorAllocationView; import megameklab.com.ui.view.BasicInfoView; import megameklab.com.ui.view.FighterChassisView; import megameklab.com.ui.view.HeatSinkView; import megameklab.com.ui.view.MVFArmorView; import megameklab.com.ui.view.MovementView; +import megameklab.com.ui.view.PatchworkArmorView; import megameklab.com.ui.view.listeners.AeroBuildListener; import megameklab.com.util.ITab; import megameklab.com.util.RefreshListener; @@ -67,13 +70,13 @@ public class StructureTab extends ITab implements AeroBuildListener { private AeroFuelView panFuel; private HeatSinkView panHeat; private SummaryView panSummary; - private ArmorView armorView; + private ArmorAllocationView panArmorAllocation; + private PatchworkArmorView panPatchwork; RefreshListener refresh = null; public StructureTab(EntitySource eSource) { super(eSource); - armorView = new ArmorView(eSource); setLayout(new BorderLayout()); setUpPanels(); this.add(masterPanel, BorderLayout.CENTER); @@ -88,7 +91,14 @@ private void setUpPanels() { panMovement = new MovementView(panInfo); panFuel = new AeroFuelView(); panHeat = new HeatSinkView(panInfo); + panArmorAllocation = new ArmorAllocationView(panInfo, Entity.ETYPE_AERO); + panPatchwork = new PatchworkArmorView(panInfo); panSummary = new SummaryView(eSource); + if (getAero().hasPatchworkArmor()) { + panArmorAllocation.showPatchwork(true); + } else { + panPatchwork.setVisible(false); + } GridBagConstraints gbc = new GridBagConstraints(); @@ -112,7 +122,8 @@ private void setUpPanels() { midPanel.add(Box.createHorizontalStrut(300)); rightPanel.add(panArmor); - rightPanel.add(armorView); + rightPanel.add(panArmorAllocation); + rightPanel.add(panPatchwork); gbc = new GridBagConstraints(); gbc.gridx = 0; @@ -134,7 +145,8 @@ private void setUpPanels() { panHeat.setBorder(BorderFactory.createTitledBorder("Heat Sinks")); panArmor.setBorder(BorderFactory.createTitledBorder("Armor")); panSummary.setBorder(BorderFactory.createTitledBorder("Summary")); - armorView.setBorder(BorderFactory.createTitledBorder("Armor Allocation")); + panArmorAllocation.setBorder(BorderFactory.createTitledBorder("Armor Allocation")); + panPatchwork.setBorder(BorderFactory.createTitledBorder("Patchwork Armor")); } public ITechManager getTechManager() { @@ -150,12 +162,13 @@ public void refresh() { panFuel.setFromEntity(getAero()); panMovement.setFromEntity(getAero()); panArmor.setFromEntity(getAero()); + panArmorAllocation.setFromEntity(getAero()); + panPatchwork.setFromEntity(getAero()); panHeat.setVisible(!getAero().hasETypeFlag(Entity.ETYPE_CONV_FIGHTER)); setAeroStructuralIntegrity(); - armorView.refresh(); panSummary.refresh(); addAllListeners(); @@ -220,6 +233,8 @@ public void removeAllListeners() { panFuel.removeListener(this); panMovement.removeListener(this); panArmor.removeListener(this); + panArmorAllocation.removeListener(this); + panPatchwork.removeListener(this); } public void addAllListeners() { @@ -229,52 +244,12 @@ public void addAllListeners() { panFuel.addListener(this); panMovement.addListener(this); panArmor.addListener(this); + panArmorAllocation.addListener(this); + panPatchwork.addListener(this); } public void addRefreshedListener(RefreshListener l) { refresh = l; - armorView.addRefreshedListener(l); - } - - private void createArmorMountsAndSetArmorType(int at, int aTechLevel) { - /* TODO: Patchwork armor needs support from ArmorView - if (EquipmentType.T_ARMOR_PATCHWORK == at) { - boolean isMixed = panInfo.isMixedTech(); - List armors = panArmor.getAllArmors(); - List> combos = new ArrayList<>(); - JPanel panel = new JPanel(new GridBagLayout()); - // Start with 1 to skip body - for (int loc = 0; loc < Aero.LOC_WINGS; loc++) { - TechComboBox cbLoc = new TechComboBox<>(eq -> eq.getName()); - cbLoc.showTechBase(isMixed); - armors.forEach(a -> cbLoc.addItem(a)); - EquipmentType locArmor = EquipmentType.get(EquipmentType - .getArmorTypeName(getAero().getArmorType(loc), - TechConstants.isClan(getAero().getArmorTechLevel(loc)))); - cbLoc.setSelectedItem(locArmor); - combos.add(cbLoc); - JLabel label = new JLabel(getAero().getLocationName(loc)); - panel.add(label, GBC.std()); - panel.add(cbLoc, GBC.eol()); - } - JOptionPane.showMessageDialog(this, panel, - "Please choose the armor types", - JOptionPane.QUESTION_MESSAGE); - UnitUtil.removeISorArmorMounts(getAero(), false); - for (int loc = 0; loc < Aero.LOC_WINGS; loc++) { - EquipmentType armor = (EquipmentType)combos.get(loc).getSelectedItem(); - getAero().setArmorTechLevel(armor.getTechLevel(panInfo.getTechYear()), loc); - getAero().setArmorType(EquipmentType.getArmorType(armor), loc); - } - panArmor.removeListener(this); - panArmor.setFromEntity(getAero()); - panArmor.addListener(this); - } else { - * - */ - getAero().setArmorTechLevel(aTechLevel); - getAero().setArmorType(at); - //} } public void setAsCustomization() { @@ -343,7 +318,6 @@ public void updateTechLevel() { if (!getAero().hasPatchworkArmor()) { UnitUtil.removeISorArmorMounts(getAero(), false); } - createArmorMountsAndSetArmorType(getAero().getArmorType(0), getAero().getArmorTechLevel(0)); // If we have a large engine, a drop in tech level may make it unavailable and we will need // to reduce speed to a legal value. if (getAero().getEngine().hasFlag(Engine.LARGE_ENGINE) @@ -373,7 +347,8 @@ public void updateTechLevel() { panHeat.refresh(); panArmor.refresh(); panMovement.refresh(); - armorView.resetArmorPoints(); + panArmorAllocation.setFromEntity(getAero()); + panPatchwork.setFromEntity(getAero()); addAllListeners(); } @@ -406,15 +381,18 @@ public void heatSinkBaseCountChanged(int count) { @Override public void armorTypeChanged(int at, int aTechLevel) { - if (!getAero().hasPatchworkArmor()) { - UnitUtil.removeISorArmorMounts(getAero(), false); - } - createArmorMountsAndSetArmorType(at, aTechLevel); - if (!getAero().hasPatchworkArmor()) { - armorView.resetArmorPoints(); + UnitUtil.removeISorArmorMounts(getAero(), false); + if (at != EquipmentType.T_ARMOR_PATCHWORK) { + getAero().setArmorTechLevel(aTechLevel); + getAero().setArmorType(at); + panArmorAllocation.showPatchwork(false); + panPatchwork.setVisible(false); + } else { + panPatchwork.setFromEntity(getAero()); + panArmorAllocation.showPatchwork(true); + panPatchwork.setVisible(true); } - - armorView.refresh(); + panArmorAllocation.setFromEntity(getAero()); panSummary.refresh(); refresh.refreshStatus(); refresh.refreshBuild(); @@ -424,9 +402,7 @@ public void armorTypeChanged(int at, int aTechLevel) { @Override public void armorTonnageChanged(double tonnage) { getAero().setArmorTonnage(Math.round(tonnage * 2) / 2.0); - armorView.resetArmorPoints(); - - armorView.refresh(); + panArmorAllocation.setFromEntity(getAero()); panSummary.refresh(); refresh.refreshStatus(); refresh.refreshPreview(); @@ -436,12 +412,11 @@ public void armorTonnageChanged(double tonnage) { public void maximizeArmor() { double maxArmor = UnitUtil.getMaximumArmorTonnage(getAero()); getAero().setArmorTonnage(maxArmor); - armorView.resetArmorPoints(); panArmor.removeListener(this); panArmor.setFromEntity(getAero()); panArmor.addListener(this); - armorView.refresh(); + panArmorAllocation.setFromEntity(getAero()); panSummary.refresh(); refresh.refreshStatus(); refresh.refreshPreview(); @@ -459,12 +434,11 @@ public void useRemainingTonnageArmor() { double maxArmor = Math.min(getAero().getArmorWeight() + remainingTonnage, UnitUtil.getMaximumArmorTonnage(getAero())); getAero().setArmorTonnage(maxArmor); - armorView.resetArmorPoints(); panArmor.removeListener(this); panArmor.setFromEntity(getAero()); panArmor.addListener(this); - armorView.refresh(); + panArmorAllocation.setFromEntity(getAero()); panSummary.refresh(); refresh.refreshStatus(); refresh.refreshPreview(); @@ -580,14 +554,60 @@ public void fuelTonnageChanged(double tonnage) { @Override public void armorPointsChanged(int location, int front, int rear) { - // TODO Auto-generated method stub - + getAero().initializeArmor(front, location); + if (panArmor.getArmorType() == EquipmentType.T_ARMOR_PATCHWORK) { + getAero().setArmorTonnage(panArmorAllocation.getTotalArmorWeight(getAero())); + } + panArmorAllocation.setFromEntity(getAero()); + refresh.refreshPreview(); + refresh.refreshSummary(); + refresh.refreshStatus(); } @Override public void patchworkChanged(int location, EquipmentType armor) { - // TODO Auto-generated method stub - + UnitUtil.resetArmor(getAero(), location); + + //TODO: move this construction data out of the ui + int crits = 0; + switch (EquipmentType.getArmorType(armor)) { + case EquipmentType.T_ARMOR_STEALTH_VEHICLE: + case EquipmentType.T_ARMOR_LIGHT_ALUM: + case EquipmentType.T_ARMOR_ALUM: + case EquipmentType.T_ARMOR_FERRO_ALUM_PROTO: + case EquipmentType.T_ARMOR_FERRO_LAMELLOR: + case EquipmentType.T_ARMOR_REFLECTIVE: + case EquipmentType.T_ARMOR_REACTIVE: + crits = 1; + break; + case EquipmentType.T_ARMOR_HEAVY_ALUM: + crits = 2; + break; + } + if (getAero().getEmptyCriticals(location) < crits) { + JOptionPane .showMessageDialog( + null, armor.getName() + + " does not fit in location " + + getAero().getLocationName(location) + + ". Resetting to Standard Armor in this location.", + "Error", + JOptionPane.INFORMATION_MESSAGE); + } else { + getAero().setArmorType(EquipmentType.getArmorType(armor), location); + getAero().setArmorTechLevel(armor.getTechLevel(getTechManager().getGameYear(), armor.isClan())); + for (; crits > 0; crits--) { + try { + getAero().addEquipment( new Mounted(getAero(), armor), location, false); + } catch (LocationFullException ex) { + } + } + } + panArmor.refresh(); + panArmorAllocation.setFromEntity(getAero()); + refresh.refreshBuild(); + refresh.refreshPreview(); + refresh.refreshSummary(); + refresh.refreshStatus(); } } diff --git a/src/megameklab/com/ui/Mek/tabs/StructureTab.java b/src/megameklab/com/ui/Mek/tabs/StructureTab.java index 189a63130..99e0771b5 100644 --- a/src/megameklab/com/ui/Mek/tabs/StructureTab.java +++ b/src/megameklab/com/ui/Mek/tabs/StructureTab.java @@ -576,7 +576,6 @@ public void updateTechLevel() { if (!getMech().hasPatchworkArmor()) { UnitUtil.removeISorArmorMounts(getMech(), false); } -// createArmorMountsAndSetArmorType(getMech().getArmorType(0), getMech().getArmorTechLevel(0)); // If we have a large engine, a drop in tech level may make it unavailable and we will need // to reduce speed to a legal value. if (getMech().getEngine().hasFlag(Engine.LARGE_ENGINE) diff --git a/src/megameklab/com/ui/view/MVFArmorView.java b/src/megameklab/com/ui/view/MVFArmorView.java index d009cc9b9..9f68ea13f 100644 --- a/src/megameklab/com/ui/view/MVFArmorView.java +++ b/src/megameklab/com/ui/view/MVFArmorView.java @@ -226,9 +226,7 @@ public void refresh() { } } } - //TODO: patchwork armor for fighters needs work on the armor allocation view - if (((etype & Entity.ETYPE_AERO) == 0) - && techManager.isLegal(Entity.getPatchworkArmorAdvancement())) { + if (techManager.isLegal(Entity.getPatchworkArmorAdvancement())) { cbArmorType.addItem(null); } if (null == prev) { diff --git a/src/megameklab/com/ui/view/PatchworkArmorView.java b/src/megameklab/com/ui/view/PatchworkArmorView.java index 94c8ca467..cb2413816 100644 --- a/src/megameklab/com/ui/view/PatchworkArmorView.java +++ b/src/megameklab/com/ui/view/PatchworkArmorView.java @@ -27,9 +27,11 @@ import javax.swing.JLabel; import javax.swing.border.TitledBorder; +import megamek.common.Aero; import megamek.common.Entity; import megamek.common.EquipmentType; import megamek.common.ITechManager; +import megamek.common.Tank; import megamek.common.TechConstants; import megamek.common.util.EncodeControl; import megameklab.com.ui.util.TechComboBox; @@ -106,7 +108,9 @@ public void setFromEntity(Entity en) { List armors = UnitUtil.legalArmorsFor(en, techManager); ignoreEvents = true; for (int loc = 0; loc < combos.size(); loc++) { - if (loc < en.locations()) { + if ((loc < en.locations()) + && !((en.hasETypeFlag(Entity.ETYPE_TANK) && (loc == Tank.LOC_BODY))) + && !((en.hasETypeFlag(Entity.ETYPE_AERO) && (loc == Aero.LOC_WINGS)))) { labels.get(loc).setText(en.getLocationName(loc)); combos.get(loc).removeAllItems(); for (EquipmentType eq : armors) { diff --git a/src/megameklab/com/util/UnitUtil.java b/src/megameklab/com/util/UnitUtil.java index 7f7a7b7c8..05683149e 100644 --- a/src/megameklab/com/util/UnitUtil.java +++ b/src/megameklab/com/util/UnitUtil.java @@ -1276,16 +1276,20 @@ public static double getUnallocatedAmmoTonnage(Entity unit) { public static int getMaximumArmorPoints(Entity unit) { int points = 0; - if (unit instanceof Mech) { + if (unit.hasETypeFlag(Entity.ETYPE_MECH)) { int headPoints = 3; - if (((Mech)unit).isSuperHeavy()) { + if (unit.getWeightClass() == EntityWeightClass.WEIGHT_SUPER_HEAVY) { headPoints = 4; } points = (unit.getTotalInternal() * 2) + headPoints; - } else if (unit instanceof Tank) { + } else if (unit.hasETypeFlag(Entity.ETYPE_TANK)) { points = (int) Math.floor((unit.getWeight() * 3.5) + 40); - } else if (unit instanceof BattleArmor) { + } else if (unit.hasETypeFlag(Entity.ETYPE_BATTLEARMOR)) { points = (unit.getWeightClass() * 4) + 2; + } else if (unit.hasETypeFlag(Entity.ETYPE_CONV_FIGHTER)) { + points = (int) Math.floor(unit.getWeight()); + } else if (unit.hasETypeFlag(Entity.ETYPE_AERO)) { + points = (int) Math.floor(unit.getWeight() * 8); } return points; } From 3fec931f846511360a9ed6c43b043ba62121ad13 Mon Sep 17 00:00:00 2001 From: Carl Spain Date: Wed, 20 Sep 2017 12:32:06 -0500 Subject: [PATCH 07/12] Use new armor allocation view in vehicle structure tab. --- .../com/ui/Vehicle/tabs/StructureTab.java | 196 ++++++++++-------- .../com/ui/view/ArmorAllocationView.java | 103 ++++++--- 2 files changed, 177 insertions(+), 122 deletions(-) diff --git a/src/megameklab/com/ui/Vehicle/tabs/StructureTab.java b/src/megameklab/com/ui/Vehicle/tabs/StructureTab.java index 765cbdf8a..71012f252 100644 --- a/src/megameklab/com/ui/Vehicle/tabs/StructureTab.java +++ b/src/megameklab/com/ui/Vehicle/tabs/StructureTab.java @@ -17,20 +17,15 @@ package megameklab.com.ui.Vehicle.tabs; import java.awt.BorderLayout; -import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; -import java.util.ArrayList; -import java.util.List; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; -import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; -import megamek.client.ui.GBC; import megamek.common.Engine; import megamek.common.Entity; import megamek.common.EntityMovementMode; @@ -41,17 +36,16 @@ import megamek.common.Mounted; import megamek.common.SimpleTechLevel; import megamek.common.Tank; -import megamek.common.TechConstants; import megamek.common.TroopSpace; import megamek.common.verifier.TestEntity; import megameklab.com.ui.EntitySource; -import megameklab.com.ui.Vehicle.views.ArmorView; import megameklab.com.ui.Vehicle.views.SummaryView; -import megameklab.com.ui.util.TechComboBox; +import megameklab.com.ui.view.ArmorAllocationView; import megameklab.com.ui.view.BasicInfoView; import megameklab.com.ui.view.CVChassisView; import megameklab.com.ui.view.MVFArmorView; import megameklab.com.ui.view.MovementView; +import megameklab.com.ui.view.PatchworkArmorView; import megameklab.com.ui.view.listeners.CVBuildListener; import megameklab.com.util.ITab; import megameklab.com.util.RefreshListener; @@ -64,20 +58,18 @@ public class StructureTab extends ITab implements CVBuildListener { */ private static final long serialVersionUID = -6756011847500605874L; - RefreshListener refresh = null; - Dimension maxSize = new Dimension(); - JPanel masterPanel; - BasicInfoView panBasicInfo; - CVChassisView panChassis; - MVFArmorView panArmor; - MovementView panMovement; - SummaryView panSummary; + private RefreshListener refresh = null; + private JPanel masterPanel; + private BasicInfoView panBasicInfo; + private CVChassisView panChassis; + private MVFArmorView panArmor; + private MovementView panMovement; + private SummaryView panSummary; + private ArmorAllocationView panArmorAllocation; + private PatchworkArmorView panPatchwork; - private ArmorView armor; - public StructureTab(EntitySource eSource) { super(eSource); - armor = new ArmorView(eSource); setLayout(new BorderLayout()); setUpPanels(); this.add(masterPanel, BorderLayout.CENTER); @@ -90,7 +82,14 @@ private void setUpPanels() { panChassis = new CVChassisView(panBasicInfo); panArmor = new MVFArmorView(panBasicInfo); panMovement = new MovementView(panBasicInfo); + panArmorAllocation = new ArmorAllocationView(panBasicInfo, Entity.ETYPE_TANK); + panPatchwork = new PatchworkArmorView(panBasicInfo); panSummary = new SummaryView(eSource); + if (getTank().hasPatchworkArmor()) { + panArmorAllocation.showPatchwork(true); + } else { + panPatchwork.setVisible(false); + } GridBagConstraints gbc; @@ -98,12 +97,16 @@ private void setUpPanels() { panChassis.setFromEntity(getTank()); panMovement.setFromEntity(getTank()); panArmor.setFromEntity(getTank()); + panArmorAllocation.setFromEntity(getTank()); + panPatchwork.setFromEntity(getTank()); gbc = new GridBagConstraints(); JPanel leftPanel = new JPanel(); + JPanel midPanel = new JPanel(); JPanel rightPanel = new JPanel(); leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.Y_AXIS)); + midPanel.setLayout(new BoxLayout(midPanel, BoxLayout.Y_AXIS)); rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.Y_AXIS)); leftPanel.add(panBasicInfo); @@ -113,9 +116,12 @@ private void setUpPanels() { leftPanel.add(panMovement); leftPanel.add(Box.createGlue()); - rightPanel.add(panArmor); - rightPanel.add(panSummary); - rightPanel.add(Box.createVerticalGlue()); + midPanel.add(panArmor); + midPanel.add(panSummary); + midPanel.add(Box.createVerticalGlue()); + + rightPanel.add(panArmorAllocation); + rightPanel.add(panPatchwork); gbc = new GridBagConstraints(); gbc.gridx = 0; @@ -126,16 +132,17 @@ private void setUpPanels() { gbc.anchor = GridBagConstraints.NORTHWEST; masterPanel.add(leftPanel, gbc); gbc.gridx = 1; - masterPanel.add(rightPanel, gbc); + masterPanel.add(midPanel, gbc); gbc.gridx = 2; - masterPanel.add(armor, gbc); + masterPanel.add(rightPanel, gbc); panBasicInfo.setBorder(BorderFactory.createTitledBorder("Basic Information")); panChassis.setBorder(BorderFactory.createTitledBorder("Chassis")); panMovement.setBorder(BorderFactory.createTitledBorder("Movement")); panArmor.setBorder(BorderFactory.createTitledBorder("Armor")); panSummary.setBorder(BorderFactory.createTitledBorder("Summary")); - armor.setBorder(BorderFactory.createTitledBorder("Armor Allocation")); + panArmorAllocation.setBorder(BorderFactory.createTitledBorder("Armor Allocation")); + panPatchwork.setBorder(BorderFactory.createTitledBorder("Patchwork Armor")); } public void refresh() { @@ -145,8 +152,9 @@ public void refresh() { panChassis.setFromEntity(getTank()); panMovement.setFromEntity(getTank()); panArmor.setFromEntity(getTank()); + panArmorAllocation.setFromEntity(getTank()); + panPatchwork.setFromEntity(getTank()); - armor.refresh(); panSummary.refresh(); addAllListeners(); @@ -161,6 +169,8 @@ public void removeAllListeners() { panChassis.removeListener(this); panMovement.removeListener(this); panArmor.removeListener(this); + panArmorAllocation.removeListener(this); + panPatchwork.removeListener(this); } public void addAllListeners() { @@ -168,11 +178,12 @@ public void addAllListeners() { panChassis.addListener(this); panMovement.addListener(this); panArmor.addListener(this); + panArmorAllocation.addListener(this); + panPatchwork.addListener(this); } public void addRefreshedListener(RefreshListener l) { refresh = l; - armor.addRefreshedListener(l); } private void removeTurret(int loc) { @@ -223,44 +234,6 @@ private boolean recalculateEngineRating(int walkMP, double tonnage) { return true; } - private void createArmorMountsAndSetArmorType(int at, int aTechLevel) { - if (EquipmentType.T_ARMOR_PATCHWORK == at) { - boolean isMixed = panBasicInfo.useMixedTech(); - List armors = panArmor.getAllArmors(); - List> combos = new ArrayList<>(); - JPanel panel = new JPanel(new GridBagLayout()); - // Start with 1 to skip body - for (int loc = 1; loc < getTank().locations(); loc++) { - TechComboBox cbLoc = new TechComboBox<>(eq -> eq.getName()); - cbLoc.showTechBase(isMixed); - armors.forEach(a -> cbLoc.addItem(a)); - EquipmentType locArmor = EquipmentType.get(EquipmentType - .getArmorTypeName(getTank().getArmorType(loc), - TechConstants.isClan(getTank().getArmorTechLevel(loc)))); - cbLoc.setSelectedItem(locArmor); - combos.add(cbLoc); - JLabel label = new JLabel(getTank().getLocationName(loc)); - panel.add(label, GBC.std()); - panel.add(cbLoc, GBC.eol()); - } - JOptionPane.showMessageDialog(this, panel, - "Please choose the armor types", - JOptionPane.QUESTION_MESSAGE); - UnitUtil.removeISorArmorMounts(getTank(), false); - for (int loc = 0; loc < getTank().locations(); loc++) { - EquipmentType armor = (EquipmentType)combos.get(loc).getSelectedItem(); - getTank().setArmorTechLevel(armor.getTechLevel(panBasicInfo.getGameYear()), loc); - getTank().setArmorType(EquipmentType.getArmorType(armor), loc); - } - panArmor.removeListener(this); - panArmor.setFromEntity(getTank()); - panArmor.addListener(this); - } else { - getTank().setArmorTechLevel(aTechLevel); - getTank().setArmorType(at); - } - } - public void refreshSummary() { panSummary.refresh(); } @@ -310,7 +283,6 @@ public void updateTechLevel() { if (!getTank().hasPatchworkArmor()) { UnitUtil.removeISorArmorMounts(getTank(), false); } - createArmorMountsAndSetArmorType(getTank().getArmorType(0), getTank().getArmorTechLevel(0)); // If we have a large engine, a drop in tech level may make it unavailable and we will need // to reduce speed to a legal value. if (getTank().getEngine().hasFlag(Engine.LARGE_ENGINE) @@ -333,7 +305,8 @@ public void updateTechLevel() { panChassis.refresh(); panArmor.refresh(); panMovement.refresh(); - armor.resetArmorPoints(); + panArmorAllocation.setFromEntity(getTank()); + panPatchwork.setFromEntity(getTank()); addAllListeners(); } @@ -390,15 +363,18 @@ public void jumpTypeChanged(final EquipmentType jumpJet) { @Override public void armorTypeChanged(int at, int aTechLevel) { - if (!getTank().hasPatchworkArmor()) { - UnitUtil.removeISorArmorMounts(getTank(), false); - } - createArmorMountsAndSetArmorType(at, aTechLevel); - if (!getTank().hasPatchworkArmor()) { - armor.resetArmorPoints(); + UnitUtil.removeISorArmorMounts(getTank(), false); + if (at != EquipmentType.T_ARMOR_PATCHWORK) { + getTank().setArmorTechLevel(aTechLevel); + getTank().setArmorType(at); + panArmorAllocation.showPatchwork(false); + panPatchwork.setVisible(false); + } else { + panPatchwork.setFromEntity(getTank()); + panArmorAllocation.showPatchwork(true); + panPatchwork.setVisible(true); } - - armor.refresh(); + panArmorAllocation.setFromEntity(getTank()); panSummary.refresh(); refresh.refreshStatus(); refresh.refreshBuild(); @@ -408,9 +384,7 @@ public void armorTypeChanged(int at, int aTechLevel) { @Override public void armorTonnageChanged(double tonnage) { getTank().setArmorTonnage(Math.round(tonnage * 2) / 2.0); - armor.resetArmorPoints(); - - armor.refresh(); + panArmorAllocation.setFromEntity(getTank()); panSummary.refresh(); refresh.refreshStatus(); refresh.refreshPreview(); @@ -420,12 +394,11 @@ public void armorTonnageChanged(double tonnage) { public void maximizeArmor() { double maxArmor = UnitUtil.getMaximumArmorTonnage(getTank()); getTank().setArmorTonnage(maxArmor); - armor.resetArmorPoints(); panArmor.removeListener(this); panArmor.setFromEntity(getTank()); panArmor.addListener(this); - armor.refresh(); + panArmorAllocation.setFromEntity(getTank()); panSummary.refresh(); refresh.refreshStatus(); refresh.refreshPreview(); @@ -443,12 +416,11 @@ public void useRemainingTonnageArmor() { double maxArmor = Math.min(getTank().getArmorWeight() + remainingTonnage, UnitUtil.getMaximumArmorTonnage(getTank())); getTank().setArmorTonnage(maxArmor); - armor.resetArmorPoints(); panArmor.removeListener(this); panArmor.setFromEntity(getTank()); panArmor.addListener(this); - armor.refresh(); + panArmorAllocation.setFromEntity(getTank()); panSummary.refresh(); refresh.refreshStatus(); refresh.refreshPreview(); @@ -498,6 +470,7 @@ public void superheavyChanged(boolean superheavy) { } panChassis.refresh(); panSummary.refresh(); + panArmorAllocation.setFromEntity(getTank()); refresh.refreshPreview(); refresh.refreshBuild(); refresh.refreshStatus(); @@ -530,7 +503,8 @@ public void motiveChanged(EntityMovementMode motive) { panMovement.removeListener(this); panMovement.setFromEntity(getTank()); panMovement.addListener(this); - armor.refresh(); + panArmorAllocation.setFromEntity(getTank()); + panPatchwork.setFromEntity(getTank()); panSummary.refresh(); refresh.refreshBuild(); refresh.refreshStatus(); @@ -574,7 +548,7 @@ public void turretChanged(int turretConfig) { initTurretArmor(getTank().getLocTurret2()); } panChassis.setFromEntity(getTank()); - armor.refresh(); + panArmorAllocation.setFromEntity(getTank()); refresh.refreshBuild(); refresh.refreshPreview(); refresh.refreshStatus(); @@ -619,13 +593,59 @@ public void resetChassis() { @Override public void armorPointsChanged(int location, int front, int rear) { - // TODO Auto-generated method stub - + getTank().initializeArmor(front, location); + if (panArmor.getArmorType() == EquipmentType.T_ARMOR_PATCHWORK) { + getTank().setArmorTonnage(panArmorAllocation.getTotalArmorWeight(getTank())); + } + panArmorAllocation.setFromEntity(getTank()); + refresh.refreshPreview(); + refresh.refreshSummary(); + refresh.refreshStatus(); } @Override public void patchworkChanged(int location, EquipmentType armor) { - // TODO Auto-generated method stub - + UnitUtil.resetArmor(getAero(), location); + + //TODO: move this construction data out of the ui + int crits = 0; + switch (EquipmentType.getArmorType(armor)) { + case EquipmentType.T_ARMOR_STEALTH_VEHICLE: + case EquipmentType.T_ARMOR_LIGHT_FERRO: + case EquipmentType.T_ARMOR_FERRO_FIBROUS: + case EquipmentType.T_ARMOR_FERRO_FIBROUS_PROTO: + case EquipmentType.T_ARMOR_FERRO_LAMELLOR: + case EquipmentType.T_ARMOR_REFLECTIVE: + case EquipmentType.T_ARMOR_REACTIVE: + crits = 1; + break; + case EquipmentType.T_ARMOR_HEAVY_FERRO: + crits = 2; + break; + } + if (getAero().getEmptyCriticals(location) < crits) { + JOptionPane .showMessageDialog( + null, armor.getName() + + " does not fit in location " + + getAero().getLocationName(location) + + ". Resetting to Standard Armor in this location.", + "Error", + JOptionPane.INFORMATION_MESSAGE); + } else { + getAero().setArmorType(EquipmentType.getArmorType(armor), location); + getAero().setArmorTechLevel(armor.getTechLevel(getTechManager().getGameYear(), armor.isClan())); + for (; crits > 0; crits--) { + try { + getAero().addEquipment( new Mounted(getAero(), armor), location, false); + } catch (LocationFullException ex) { + } + } + } + panArmor.refresh(); + panArmorAllocation.setFromEntity(getAero()); + refresh.refreshBuild(); + refresh.refreshPreview(); + refresh.refreshSummary(); + refresh.refreshStatus(); } } diff --git a/src/megameklab/com/ui/view/ArmorAllocationView.java b/src/megameklab/com/ui/view/ArmorAllocationView.java index 6c91e2da9..8660d1514 100644 --- a/src/megameklab/com/ui/view/ArmorAllocationView.java +++ b/src/megameklab/com/ui/view/ArmorAllocationView.java @@ -21,6 +21,7 @@ import java.util.ResourceBundle; import java.util.concurrent.CopyOnWriteArrayList; +import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JLabel; import javax.swing.JPanel; @@ -68,7 +69,14 @@ public void removeListener(BuildListener l) { {-1, Mech.LOC_LLEG, Mech.LOC_CLEG, Mech.LOC_RLEG, -1} }; - private static final int[][] VEE_LAYOUT = { + private static final int[][] TANK_LAYOUT = { + {-1, Tank.LOC_FRONT, -1}, + {Tank.LOC_LEFT, Tank.LOC_TURRET, Tank.LOC_RIGHT}, + {-1, Tank.LOC_TURRET_2, -1}, + {-1, Tank.LOC_REAR, -1} + }; + + private static final int[][] SH_TANK_LAYOUT = { {-1, SuperHeavyTank.LOC_FRONT, -1}, {SuperHeavyTank.LOC_FRONTLEFT, SuperHeavyTank.LOC_TURRET, SuperHeavyTank.LOC_FRONTRIGHT}, {SuperHeavyTank.LOC_REARLEFT, SuperHeavyTank.LOC_TURRET_2, SuperHeavyTank.LOC_REARRIGHT}, @@ -76,10 +84,10 @@ public void removeListener(BuildListener l) { }; private static final int[][] VTOL_LAYOUT = { - {-1, Tank.LOC_FRONT, -1}, - {Tank.LOC_LEFT, VTOL.LOC_ROTOR, Tank.LOC_RIGHT}, - {-1, Tank.LOC_TURRET, -1}, - {-1, Tank.LOC_REAR, -1} + {-1, VTOL.LOC_FRONT, -1}, + {VTOL.LOC_LEFT, VTOL.LOC_ROTOR, VTOL.LOC_RIGHT}, + {-1, VTOL.LOC_TURRET, -1}, + {-1, VTOL.LOC_REAR, -1} }; private static final int[][] AERODYNE_LAYOUT = { @@ -89,13 +97,14 @@ public void removeListener(BuildListener l) { }; private final List locationViews = new ArrayList<>(); - private final long entitytype; + private final JPanel panLocations = new JPanel(); private final JTextField txtUnallocated = new JTextField(); private final JTextField txtAllocated = new JTextField(); private final JTextField txtTotal = new JTextField(); private final JTextField txtMaxPossible = new JTextField(); private final JTextField txtWasted = new JTextField(); + private long entitytype; private int armorPoints = 0; private int maxArmorPoints = 0; private int wastedPoints = 0; @@ -112,38 +121,15 @@ private void initUI() { tooltipFormat = resourceMap.getString("ArmorAllocationView.locationTooltip.format"); setLayout(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); + + panLocations.setLayout(new GridBagLayout()); gbc.gridx = 0; gbc.gridy = 0; gbc.gridwidth = GridBagConstraints.REMAINDER; + add(panLocations, gbc); - int[][] layout; - if ((entitytype & Entity.ETYPE_MECH) != 0) { - layout = MEK_LAYOUT; - } else if ((entitytype & Entity.ETYPE_AERO) != 0) { - // Spheroids use lwing/rwing rear for l/r aft positions - layout = AERODYNE_LAYOUT; - } else if ((entitytype & Entity.ETYPE_VTOL) != 0) { - layout = VTOL_LAYOUT; - } else { - layout = VEE_LAYOUT; - } - for (int row = 0; row < layout.length; row++) { - JPanel panRow = new JPanel(); - panRow.setLayout(new BoxLayout(panRow, BoxLayout.X_AXIS)); - for (int col = 0; col < layout[row].length; col++) { - final int loc = layout[row][col]; - if (loc >= 0) { - ArmorLocationView locView = new ArmorLocationView(loc); - locationViews.add(locView); - panRow.add(locView); - locView.addListener(this); - } else { - panRow.add(new JPanel()); - } - } - add(panRow, gbc); - gbc.gridy++; - } + updateLayout(); + gbc.gridy++; gbc.gridwidth = 1; add(new JLabel(resourceMap.getString("ArmorAllocationView.txtUnallocated.text"), SwingConstants.RIGHT), gbc); //$NON-NLS-1$ @@ -187,6 +173,7 @@ private void initUI() { } public void setFromEntity(Entity en) { + setEntityType(en.getEntityType()); maxArmorPoints = UnitUtil.getMaximumArmorPoints(en); int raw = UnitUtil.getRawArmorPoints(en, en.getLabArmorTonnage()); int currentPoints = en.getTotalOArmor(); @@ -246,6 +233,54 @@ public void setFromEntity(Entity en) { txtWasted.setText(String.valueOf(wastedPoints)); } + private void updateLayout() { + int[][] layout; + if ((entitytype & Entity.ETYPE_MECH) != 0) { + layout = MEK_LAYOUT; + } else if ((entitytype & Entity.ETYPE_AERO) != 0) { + // Spheroids use lwing/rwing rear for l/r aft positions + layout = AERODYNE_LAYOUT; + } else if ((entitytype & Entity.ETYPE_VTOL) != 0) { + layout = VTOL_LAYOUT; + } else if ((entitytype & Entity.ETYPE_SUPER_HEAVY_TANK) != 0) { + layout = SH_TANK_LAYOUT; + } else { + layout = TANK_LAYOUT; + } + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridx = 0; + gbc.gridy = 0; + gbc.anchor = GridBagConstraints.CENTER; + gbc.fill = GridBagConstraints.NONE; + gbc.gridwidth = GridBagConstraints.REMAINDER; + for (int row = 0; row < layout.length; row++) { + JPanel panRow = new JPanel(); + panRow.setLayout(new BoxLayout(panRow, BoxLayout.X_AXIS)); + for (int col = 0; col < layout[row].length; col++) { + final int loc = layout[row][col]; + if (loc >= 0) { + ArmorLocationView locView = new ArmorLocationView(loc); + locationViews.add(locView); + panRow.add(locView); + locView.addListener(this); + } else { + panRow.add(Box.createHorizontalGlue()); + } + } + panLocations.add(panRow, gbc); + gbc.gridy++; + } + } + + public void setEntityType(long etype) { + if (etype != entitytype) { + entitytype = etype; + panLocations.removeAll(); + updateLayout(); + panLocations.repaint(); + } + } + /** * Helper function for patchwork. If used for non-patchwork, it will likely give incorrect values * due to rounding up by location. From 1d0916afbe7a98e55c9899a4685576db3ccfb77f Mon Sep 17 00:00:00 2001 From: Carl Spain Date: Wed, 20 Sep 2017 12:33:22 -0500 Subject: [PATCH 08/12] Removed obsolete armor views for mechs, vees, fighters. --- .../com/ui/Aero/views/ArmorView.java | 474 ------- .../com/ui/Mek/views/ArmorView.java | 1104 ----------------- .../com/ui/Vehicle/views/ArmorView.java | 931 -------------- 3 files changed, 2509 deletions(-) delete mode 100644 src/megameklab/com/ui/Aero/views/ArmorView.java delete mode 100644 src/megameklab/com/ui/Mek/views/ArmorView.java delete mode 100644 src/megameklab/com/ui/Vehicle/views/ArmorView.java diff --git a/src/megameklab/com/ui/Aero/views/ArmorView.java b/src/megameklab/com/ui/Aero/views/ArmorView.java deleted file mode 100644 index bc27caa41..000000000 --- a/src/megameklab/com/ui/Aero/views/ArmorView.java +++ /dev/null @@ -1,474 +0,0 @@ -/* - * MegaMekLab - Copyright (C) 2008 - * - * Original author - jtighe (torren@users.sourceforge.net) - * - * This program 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 2 of the License, or (at your option) - * any later version. - * - * This program 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. - */ - -package megameklab.com.ui.Aero.views; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.GridLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.ArrayList; -import java.util.List; -import java.util.Vector; - -import javax.swing.BorderFactory; -import javax.swing.Box; -import javax.swing.BoxLayout; -import javax.swing.JButton; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JSpinner; -import javax.swing.JTextField; -import javax.swing.SpinnerNumberModel; -import javax.swing.SwingConstants; -import javax.swing.border.TitledBorder; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; - -import megamek.common.Aero; -import megamek.common.EquipmentType; -import megamek.common.verifier.TestAero; -import megameklab.com.ui.EntitySource; -import megameklab.com.util.IView; -import megameklab.com.util.RefreshListener; - -public class ArmorView extends IView implements ChangeListener, ActionListener { - - /** - * - */ - private static final long serialVersionUID = 799195356642563937L; - - private JPanel mainPanel = new JPanel(); - - private JPanel nosePanel = new JPanel(); - private JPanel lWingPanel = new JPanel(); - private JPanel rWingPanel = new JPanel(); - private JPanel aftPanel = new JPanel(); - - - public SpinnerNumberModel noseArmorModel = new SpinnerNumberModel(); - public SpinnerNumberModel lwArmorModel = new SpinnerNumberModel(); - public SpinnerNumberModel rwArmorModel = new SpinnerNumberModel(); - public SpinnerNumberModel aftArmorModel = new SpinnerNumberModel(); - - private JSpinner noseArmorField = new JSpinner(noseArmorModel); - private JSpinner lwArmorField = new JSpinner(lwArmorModel); - private JSpinner rwArmorField = new JSpinner(rwArmorModel); - private JSpinner aftArmorField = new JSpinner(aftArmorModel); - - private List armorFieldList = new ArrayList(); - - private JLabel noseArmorMaxLabel = new JLabel("", SwingConstants.CENTER); - private JLabel lwArmorMaxLabel = new JLabel("", SwingConstants.CENTER); - private JLabel rwArmorMaxLabel = new JLabel("", SwingConstants.CENTER); - private JLabel aftArmorMaxLabel = new JLabel("", SwingConstants.CENTER); - - private List armorMaxLabelList = new ArrayList(); - - private JLabel lblAllocatedArmor = new JLabel("Allocated Armor Points:"); - private JTextField valueAllocatedArmor = new JTextField(); - private JLabel lblUnallocatedArmor = new JLabel("Unallocated Armor Points:"); - private JTextField valueUnallocatedArmor = new JTextField(); - private JLabel lblCurrentArmor = new JLabel("Total Armor Points:"); - private JTextField valueCurrentArmor = new JTextField(); - private JLabel lblMaxArmor = new JLabel("Maximum Possible Armor Points:"); - private JTextField valueMaxArmor = new JTextField(); - private JLabel lblWastedArmor = new JLabel("Wasted Armor Points:"); - private JTextField valueWastedArmor = new JTextField(); - - private int armorPoints; - private int wastedArmorPoints; - - private JButton allocateArmorButton = new JButton("Auto-Allocate Armor"); - - private RefreshListener refresh; - - public ArmorView(EntitySource eSource) { - super(eSource); - - setLayout(new GridLayout(1, 1)); - - mainPanel.setLayout(new GridBagLayout()); - GridBagConstraints gbc; - - nosePanel.setLayout(new BoxLayout(nosePanel, BoxLayout.Y_AXIS)); - rWingPanel.setLayout(new BoxLayout(rWingPanel, BoxLayout.Y_AXIS)); - lWingPanel.setLayout(new BoxLayout(lWingPanel, BoxLayout.Y_AXIS)); - aftPanel.setLayout(new BoxLayout(aftPanel, BoxLayout.Y_AXIS)); - - gbc = new GridBagConstraints(); - gbc.gridx = 1; - gbc.gridy = 0; - mainPanel.add(nosePanel, gbc); - gbc.gridx = 0; - gbc.gridy = 1; - gbc.gridheight = 2; - mainPanel.add(lWingPanel, gbc); - gbc.gridx = 1; - mainPanel.add(Box.createHorizontalStrut(nosePanel.getWidth()), gbc); - gbc.gridx = 2; - mainPanel.add(rWingPanel, gbc); - gbc.gridx = 1; - gbc.gridy = 3; - gbc.gridheight = 1; - mainPanel.add(aftPanel, gbc); - - noseArmorField.setName(Integer.toString(Aero.LOC_NOSE)); - rwArmorField.setName(Integer.toString(Aero.LOC_RWING)); - lwArmorField.setName(Integer.toString(Aero.LOC_LWING)); - aftArmorField.setName(Integer.toString(Aero.LOC_AFT)); - - armorFieldList.add(noseArmorField); - armorFieldList.add(rwArmorField); - armorFieldList.add(lwArmorField); - armorFieldList.add(aftArmorField); - - - Dimension size = new Dimension(40, 25); - for (JSpinner spinner : armorFieldList) { - spinner.setToolTipText("Armor"); - // you don't set the size of the jspinner, but rather its internal - // textfield - ((JSpinner.DefaultEditor) spinner.getEditor()).setSize(size); - ((JSpinner.DefaultEditor) spinner.getEditor()).setMaximumSize(size); - ((JSpinner.DefaultEditor) spinner.getEditor()) - .setPreferredSize(size); - ((JSpinner.DefaultEditor) spinner.getEditor()).setMinimumSize(size); - } - - armorMaxLabelList.add(noseArmorMaxLabel); - armorMaxLabelList.add(lwArmorMaxLabel); - armorMaxLabelList.add(rwArmorMaxLabel); - armorMaxLabelList.add(aftArmorMaxLabel); - - Dimension labelSize = new Dimension(80, 20); - for (JLabel label : armorMaxLabelList) { - label.setSize(labelSize); - label.setMaximumSize(labelSize); - label.setPreferredSize(labelSize); - label.setMinimumSize(labelSize); - } - - addAllListeners(); - - JPanel topPanel; - - synchronized (getAero()) { - for (int location = 0; location < getAero().locations(); location++) { - - switch (location) { - case Aero.LOC_NOSE: - topPanel = new JPanel(new GridLayout(2, 0)); - topPanel.add(noseArmorField); - topPanel.add(noseArmorMaxLabel); - nosePanel.add(topPanel); - nosePanel.setBorder(BorderFactory.createTitledBorder( - null, getAero().getLocationAbbr(location), - TitledBorder.TOP, - TitledBorder.DEFAULT_POSITION)); - break; - case Aero.LOC_LWING: - topPanel = new JPanel(new GridLayout(2, 0)); - topPanel.add(lwArmorField); - topPanel.add(lwArmorMaxLabel); - lWingPanel.add(topPanel); - lWingPanel.setBorder(BorderFactory.createTitledBorder( - null, getAero().getLocationAbbr(location), - TitledBorder.TOP, - TitledBorder.DEFAULT_POSITION)); - break; - case Aero.LOC_RWING: - topPanel = new JPanel(new GridLayout(2, 0)); - topPanel.add(rwArmorField); - topPanel.add(rwArmorMaxLabel); - rWingPanel.add(topPanel); - rWingPanel.setBorder(BorderFactory.createTitledBorder( - null, getAero().getLocationAbbr(location), - TitledBorder.TOP, - TitledBorder.DEFAULT_POSITION)); - break; - case Aero.LOC_AFT: - topPanel = new JPanel(new GridLayout(2, 0)); - topPanel.add(aftArmorField); - topPanel.add(aftArmorMaxLabel); - aftPanel.add(topPanel); - aftPanel.setBorder(BorderFactory.createTitledBorder( - null, getAero().getLocationAbbr(location), - TitledBorder.TOP, - TitledBorder.DEFAULT_POSITION)); - break; - } - } - } - - JPanel totalArmorPanel = new JPanel(); - - Vector valueFields = new Vector(); - valueFields.add(valueUnallocatedArmor); - valueFields.add(valueAllocatedArmor); - valueFields.add(valueCurrentArmor); - valueFields.add(valueMaxArmor); - valueFields.add(valueWastedArmor); - - Dimension valueSize = new Dimension(45, 20); - for (JTextField field : valueFields) { - field.setEditable(false); - field.setSize(valueSize); - field.setPreferredSize(valueSize); - field.setMinimumSize(valueSize); - field.setMaximumSize(valueSize); - field.setHorizontalAlignment(SwingConstants.RIGHT); - } - - totalArmorPanel.setLayout(new GridBagLayout()); - gbc = new GridBagConstraints(); - gbc.gridx = 0; - gbc.gridy = 0; - gbc.insets = new Insets(2, 2, 2, 2); - gbc.anchor = GridBagConstraints.WEST; - totalArmorPanel.add(lblUnallocatedArmor, gbc); - gbc.gridx = 1; - totalArmorPanel.add(valueUnallocatedArmor, gbc); - gbc.gridx = 0; - gbc.gridy = 1; - totalArmorPanel.add(lblAllocatedArmor, gbc); - gbc.gridx = 1; - totalArmorPanel.add(valueAllocatedArmor, gbc); - gbc.gridx = 0; - gbc.gridy = 2; - totalArmorPanel.add(lblCurrentArmor, gbc); - gbc.gridx = 1; - totalArmorPanel.add(valueCurrentArmor, gbc); - gbc.gridx = 0; - gbc.gridy = 3; - totalArmorPanel.add(lblMaxArmor, gbc); - gbc.gridx = 1; - totalArmorPanel.add(valueMaxArmor, gbc); - gbc.gridx = 0; - gbc.gridy = 4; - totalArmorPanel.add(lblWastedArmor, gbc); - gbc.gridx = 1; - totalArmorPanel.add(valueWastedArmor, gbc); - gbc.gridx = 0; - gbc.gridy = 5; - gbc.gridwidth = 2; - gbc.anchor = GridBagConstraints.CENTER; - totalArmorPanel.add(allocateArmorButton, gbc); - - gbc = new GridBagConstraints(); - gbc.gridx = 0; - gbc.gridy = 4; - gbc.gridwidth = 5; - gbc.fill = GridBagConstraints.NONE; - gbc.anchor = GridBagConstraints.CENTER; - mainPanel.add(totalArmorPanel, gbc); - this.add(mainPanel); - - resetArmorPoints(); - } - - private void addAllListeners() { - allocateArmorButton.addActionListener(this); - for (JSpinner spinner : armorFieldList) { - spinner.addChangeListener(this); - } - } - - private void removeAllListeners() { - allocateArmorButton.removeActionListener(this); - for (JSpinner spinner : armorFieldList) { - spinner.removeChangeListener(this); - } - } - - public void refresh() { - removeAllListeners(); - for (int location = 0; location < getAero().locations(); location++) { - - int maxArmor = TestAero.maxArmorPoints(getAero(), getAero().getWeight()); - switch (location) { - case Aero.LOC_NOSE: - noseArmorModel.setValue( - Math.min(maxArmor, getAero().getArmor(location))); - if (isFullyAllocated()) { - noseArmorModel.setMaximum( - (Integer) noseArmorModel.getValue()); - } else { - noseArmorModel.setMaximum(maxArmor); - } - noseArmorModel.setStepSize(1); - noseArmorModel.setMinimum(0); - noseArmorMaxLabel.setText("max: " + maxArmor); - break; - case Aero.LOC_LWING: - lwArmorModel.setValue( - Math.min(maxArmor, getAero().getArmor(location))); - if (isFullyAllocated()) { - lwArmorModel.setMaximum( - (Integer) lwArmorModel.getValue()); - } else { - lwArmorModel.setMaximum(maxArmor); - } - lwArmorModel.setStepSize(1); - lwArmorModel.setMinimum(0); - lwArmorMaxLabel.setText("max: " + maxArmor); - break; - case Aero.LOC_RWING: - rwArmorModel.setValue( - Math.min(maxArmor, getAero().getArmor(location))); - if (isFullyAllocated()) { - rwArmorModel.setMaximum( - (Integer) rwArmorModel.getValue()); - } else { - rwArmorModel.setMaximum(maxArmor); - } - rwArmorModel.setStepSize(1); - rwArmorModel.setMinimum(0); - rwArmorMaxLabel.setText("max: " + maxArmor); - break; - case Aero.LOC_AFT: - aftArmorModel.setValue( - Math.min(maxArmor, getAero().getArmor(location))); - if (isFullyAllocated()) { - aftArmorModel.setMaximum( - (Integer) aftArmorModel.getValue()); - } else { - aftArmorModel.setMaximum(maxArmor); - } - aftArmorModel.setStepSize(1); - aftArmorModel.setMinimum(0); - aftArmorMaxLabel.setText("max: " + maxArmor); - break; - } - } - - - valueAllocatedArmor.setText(Integer.toString(getAero().getTotalOArmor())); - valueUnallocatedArmor.setText(Integer.toString(armorPoints - - getAero().getTotalOArmor())); - if (armorPoints != getAero().getTotalOArmor()) { - valueUnallocatedArmor.setForeground(Color.RED); - lblUnallocatedArmor.setForeground(Color.RED); - } else { - valueUnallocatedArmor.setForeground(Color.BLACK); - lblUnallocatedArmor.setForeground(Color.BLACK); - } - valueCurrentArmor.setText(Integer.toString(armorPoints)); - valueMaxArmor.setText("" + TestAero.maxArmorPoints( - getAero(), getAero().getWeight())); - valueWastedArmor.setText(Integer.toString(wastedArmorPoints)); - - addAllListeners(); - } - - public void addRefreshedListener(RefreshListener l) { - refresh = l; - } - - public void allocateArmor() { - double pointsToAllocate = armorPoints; - double totalArmor = TestAero.maxArmorPoints( - getAero(), getAero().getWeight()); - if (pointsToAllocate > totalArmor) { - pointsToAllocate = totalArmor; - } - double percent = pointsToAllocate / totalArmor; - // put 5 times the percentage of total possible armor into the head - for (int location = 0; location < getAero().locations(); location++) { - double IS = (getAero().getInternal(location) * 2); - double allocate = Math.min(IS * percent, pointsToAllocate); - getAero().initializeArmor((int) allocate, location); - pointsToAllocate -= (int) allocate; - } - allocateLeftoverPoints(pointsToAllocate); - - if (refresh != null) { - refresh.refreshStatus(); - } - } - - /** - * allocate any leftover points one-by-one - * - * @param points - * the amount of points left over - */ - private void allocateLeftoverPoints(double points) { - int [] locs = - {Aero.LOC_NOSE, Aero.LOC_AFT, Aero.LOC_LWING, Aero.LOC_RWING}; - - int locIdx = 0; - while (points > 0){ - int armor = getAero().getArmor(locs[locIdx]) + 1; - getAero().initializeArmor(armor, locs[locIdx]); - points--; - locIdx = (locIdx + 1) % locs.length; - } - } - - public void stateChanged(ChangeEvent e) { - removeAllListeners(); - JSpinner field = (JSpinner) e.getSource(); - int location = Integer.parseInt(field.getName()); - int value = (Integer) field.getModel().getValue(); - getAero().initializeArmor(value, location); - if (getAero().hasPatchworkArmor()) { - setArmorPoints(getMech().getTotalArmor()); - } - if (refresh != null) { - addAllListeners(); - refresh.refreshStructure(); - removeAllListeners(); - refresh.refreshStatus(); - } - addAllListeners(); - } - - public void setArmorPoints(int points) { - int maxArmor = TestAero.maxArmorPoints(getAero(), getAero().getWeight()); - wastedArmorPoints = Math.max(points - maxArmor, 0); - armorPoints = Math.min(maxArmor, points); - } - - private boolean isFullyAllocated() { - if (!getAero().hasPatchworkArmor()) { - return armorPoints == getAero().getTotalOArmor(); - } - return false; - } - - @Override - public void actionPerformed(ActionEvent e) { - removeAllListeners(); - if (e.getSource().equals(allocateArmorButton)) { - allocateArmor(); - } - addAllListeners(); - refresh.refreshAll(); - } - - public void resetArmorPoints() { - double armorPerTon = 16.0 * EquipmentType.getArmorPointMultiplier( - getAero().getArmorType(0), getAero().getArmorTechLevel(0)); - setArmorPoints((int) Math - .floor(getAero().getLabArmorTonnage() * armorPerTon)); - } -} \ No newline at end of file diff --git a/src/megameklab/com/ui/Mek/views/ArmorView.java b/src/megameklab/com/ui/Mek/views/ArmorView.java deleted file mode 100644 index ffae1d41b..000000000 --- a/src/megameklab/com/ui/Mek/views/ArmorView.java +++ /dev/null @@ -1,1104 +0,0 @@ -/* - * MegaMekLab - Copyright (C) 2008 - * - * Original author - jtighe (torren@users.sourceforge.net) - * - * This program 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 2 of the License, or (at your option) - * any later version. - * - * This program 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. - */ - -package megameklab.com.ui.Mek.views; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.GridLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.ArrayList; -import java.util.List; -import java.util.Vector; - -import javax.swing.BorderFactory; -import javax.swing.Box; -import javax.swing.BoxLayout; -import javax.swing.JButton; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JSpinner; -import javax.swing.JTextField; -import javax.swing.SpinnerNumberModel; -import javax.swing.SwingConstants; -import javax.swing.border.TitledBorder; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; - -import megamek.common.EquipmentType; -import megamek.common.Mech; -import megamek.common.TripodMech; -import megameklab.com.ui.EntitySource; -import megameklab.com.util.IView; -import megameklab.com.util.RefreshListener; -import megameklab.com.util.UnitUtil; - -public class ArmorView extends IView implements ChangeListener, ActionListener { - - /** - * - */ - private static final long serialVersionUID = 799195356642563937L; - - private JPanel mainPanel = new JPanel(); - - private JPanel headPanel = new JPanel(); - private JPanel laPanel = new JPanel(); - private JPanel raPanel = new JPanel(); - private JPanel llPanel = new JPanel(); - private JPanel rlPanel = new JPanel(); - private JPanel ltPanel = new JPanel(); - private JPanel rtPanel = new JPanel(); - private JPanel ctPanel = new JPanel(); - private JPanel clPanel = new JPanel(); - - public SpinnerNumberModel laArmorModel = new SpinnerNumberModel(); - public SpinnerNumberModel raArmorModel = new SpinnerNumberModel(); - public SpinnerNumberModel llArmorModel = new SpinnerNumberModel(); - public SpinnerNumberModel rlArmorModel = new SpinnerNumberModel(); - public SpinnerNumberModel ltArmorModel = new SpinnerNumberModel(); - public SpinnerNumberModel rtArmorModel = new SpinnerNumberModel(); - public SpinnerNumberModel ctArmorModel = new SpinnerNumberModel(); - public SpinnerNumberModel hdArmorModel = new SpinnerNumberModel(); - public SpinnerNumberModel clArmorModel = new SpinnerNumberModel(); - - private SpinnerNumberModel rtrArmorModel = new SpinnerNumberModel(); - private SpinnerNumberModel ltrArmorModel = new SpinnerNumberModel(); - private SpinnerNumberModel ctrArmorModel = new SpinnerNumberModel(); - - private JSpinner laArmorField = new JSpinner(laArmorModel); - private JSpinner raArmorField = new JSpinner(raArmorModel); - private JSpinner llArmorField = new JSpinner(llArmorModel); - private JSpinner rlArmorField = new JSpinner(rlArmorModel); - private JSpinner ltArmorField = new JSpinner(ltArmorModel); - private JSpinner rtArmorField = new JSpinner(rtArmorModel); - private JSpinner ctArmorField = new JSpinner(ctArmorModel); - private JSpinner hdArmorField = new JSpinner(hdArmorModel); - private JSpinner clArmorField = new JSpinner(clArmorModel); - - private JSpinner rtrArmorField = new JSpinner(rtrArmorModel); - private JSpinner ltrArmorField = new JSpinner(ltrArmorModel); - private JSpinner ctrArmorField = new JSpinner(ctrArmorModel); - private List armorFieldList = new ArrayList(); - - private JLabel hdArmorMaxLabel = new JLabel("", SwingConstants.CENTER); - private JLabel laArmorMaxLabel = new JLabel("", SwingConstants.CENTER); - private JLabel raArmorMaxLabel = new JLabel("", SwingConstants.CENTER); - private JLabel llArmorMaxLabel = new JLabel("", SwingConstants.CENTER); - private JLabel rlArmorMaxLabel = new JLabel("", SwingConstants.CENTER); - private JLabel ltArmorMaxLabel = new JLabel("", SwingConstants.CENTER); - private JLabel rtArmorMaxLabel = new JLabel("", SwingConstants.CENTER); - private JLabel ctArmorMaxLabel = new JLabel("", SwingConstants.CENTER); - private JLabel clArmorMaxLabel = new JLabel("", SwingConstants.CENTER); - private List armorMaxLabelList = new ArrayList(); - - private JLabel lblAllocatedArmor = new JLabel("Allocated Armor Points:"); - private JTextField valueAllocatedArmor = new JTextField(); - private JLabel lblUnallocatedArmor = new JLabel("Unallocated Armor Points:"); - private JTextField valueUnallocatedArmor = new JTextField(); - private JLabel lblCurrentArmor = new JLabel("Total Armor Points:"); - private JTextField valueCurrentArmor = new JTextField(); - private JLabel lblMaxArmor = new JLabel("Maximum Possible Armor Points:"); - private JTextField valueMaxArmor = new JTextField(); - private JLabel lblWastedArmor = new JLabel("Wasted Armor Points:"); - private JTextField valueWastedArmor = new JTextField(); - - private JLabel unallocatedPointsLabelPatchworkHead = new JLabel( - "Unalloc.:", SwingConstants.TRAILING); - private JLabel unallocatedPointsLabelPatchworkLa = new JLabel( - "Unalloc.:", SwingConstants.TRAILING); - private JLabel unallocatedPointsLabelPatchworkLt = new JLabel( - "Unalloc.:", SwingConstants.TRAILING); - private JLabel unallocatedPointsLabelPatchworkCt = new JLabel( - "Unalloc.:", SwingConstants.TRAILING); - private JLabel unallocatedPointsLabelPatchworkRt = new JLabel( - "Unalloc.:", SwingConstants.TRAILING); - private JLabel unallocatedPointsLabelPatchworkRa = new JLabel( - "Unalloc.:", SwingConstants.TRAILING); - private JLabel unallocatedPointsLabelPatchworkLl = new JLabel( - "Unalloc.:", SwingConstants.TRAILING); - private JLabel unallocatedPointsLabelPatchworkRl = new JLabel( - "Unalloc.:", SwingConstants.TRAILING); - private JLabel unallocatedPointsLabelPatchworkCl = new JLabel( - "Unalloc.:", SwingConstants.TRAILING); - private JLabel unallocatedPointsFieldHead = new JLabel(); - private JLabel unallocatedPointsFieldLa = new JLabel(); - private JLabel unallocatedPointsFieldLt = new JLabel(); - private JLabel unallocatedPointsFieldCt = new JLabel(); - private JLabel unallocatedPointsFieldRt = new JLabel(); - private JLabel unallocatedPointsFieldRa = new JLabel(); - private JLabel unallocatedPointsFieldLl = new JLabel(); - private JLabel unallocatedPointsFieldRl = new JLabel(); - private JLabel unallocatedPointsFieldCl = new JLabel(); - - private int armorPoints; - private int wastedArmorPoints; - - private JButton allocateArmorButton = new JButton("Auto-Allocate Armor"); - - private RefreshListener refresh; - - public ArmorView(EntitySource eSource) { - super(eSource); - - setLayout(new GridLayout(1, 1)); - - mainPanel.setLayout(new GridBagLayout()); - GridBagConstraints gbc; - - headPanel.setLayout(new BoxLayout(headPanel, BoxLayout.Y_AXIS)); - laPanel.setLayout(new BoxLayout(laPanel, BoxLayout.Y_AXIS)); - raPanel.setLayout(new BoxLayout(raPanel, BoxLayout.Y_AXIS)); - ltPanel.setLayout(new BoxLayout(ltPanel, BoxLayout.Y_AXIS)); - ctPanel.setLayout(new BoxLayout(ctPanel, BoxLayout.Y_AXIS)); - rtPanel.setLayout(new BoxLayout(rtPanel, BoxLayout.Y_AXIS)); - llPanel.setLayout(new BoxLayout(llPanel, BoxLayout.Y_AXIS)); - rlPanel.setLayout(new BoxLayout(rlPanel, BoxLayout.Y_AXIS)); - clPanel.setLayout(new BoxLayout(clPanel, BoxLayout.Y_AXIS)); - - int mainPanelGridY; - gbc = new GridBagConstraints(); - gbc.gridx = 2; - gbc.gridy = 0; - mainPanel.add(Box.createVerticalStrut(13), gbc); - gbc.gridy++; - mainPanel.add(headPanel, gbc); - gbc.gridx = 0; - gbc.gridy++; - mainPanel.add(laPanel, gbc); - gbc.gridx = 1; - mainPanel.add(ltPanel, gbc); - gbc.gridx = 2; - mainPanel.add(ctPanel, gbc); - gbc.gridx = 3; - mainPanel.add(rtPanel, gbc); - gbc.gridx = 4; - mainPanel.add(raPanel, gbc); - gbc.gridx = 1; - gbc.gridy++; - mainPanel.add(llPanel, gbc); - gbc.gridx = 2; - mainPanel.add(clPanel, gbc); - gbc.gridx = 3; - mainPanel.add(rlPanel, gbc); - mainPanelGridY = gbc.gridy + 1; - - laArmorField.setName(Integer.toString(Mech.LOC_LARM)); - raArmorField.setName(Integer.toString(Mech.LOC_RARM)); - llArmorField.setName(Integer.toString(Mech.LOC_LLEG)); - rlArmorField.setName(Integer.toString(Mech.LOC_RLEG)); - clArmorField.setName(Integer.toString(Mech.LOC_CLEG)); - ltArmorField.setName(Integer.toString(Mech.LOC_LT)); - rtArmorField.setName(Integer.toString(Mech.LOC_RT)); - ctArmorField.setName(Integer.toString(Mech.LOC_CT)); - hdArmorField.setName(Integer.toString(Mech.LOC_HEAD)); - rtrArmorField.setName(Integer.toString(Mech.LOC_RT)); - ltrArmorField.setName(Integer.toString(Mech.LOC_LT)); - ctrArmorField.setName(Integer.toString(Mech.LOC_CT)); - - armorFieldList.add(laArmorField); - armorFieldList.add(raArmorField); - armorFieldList.add(llArmorField); - armorFieldList.add(rlArmorField); - armorFieldList.add(clArmorField); - armorFieldList.add(ltArmorField); - armorFieldList.add(rtArmorField); - armorFieldList.add(ctArmorField); - armorFieldList.add(hdArmorField); - armorFieldList.add(ltrArmorField); - armorFieldList.add(ctrArmorField); - armorFieldList.add(rtrArmorField); - - Dimension size = new Dimension(40, 25); - for (JSpinner spinner : armorFieldList) { - spinner.setToolTipText("Front Armor"); - // you don't set the size of the jspinner, but rather its internal - // textfield - ((JSpinner.DefaultEditor) spinner.getEditor()).setSize(size); - ((JSpinner.DefaultEditor) spinner.getEditor()).setMaximumSize(size); - ((JSpinner.DefaultEditor) spinner.getEditor()) - .setPreferredSize(size); - ((JSpinner.DefaultEditor) spinner.getEditor()).setMinimumSize(size); - } - rtrArmorField.setToolTipText("Rear Armor"); - ltrArmorField.setToolTipText("Rear Armor"); - ctrArmorField.setToolTipText("Rear Armor"); - - armorMaxLabelList.add(hdArmorMaxLabel); - armorMaxLabelList.add(laArmorMaxLabel); - armorMaxLabelList.add(raArmorMaxLabel); - armorMaxLabelList.add(llArmorMaxLabel); - armorMaxLabelList.add(rlArmorMaxLabel); - armorMaxLabelList.add(clArmorMaxLabel); - armorMaxLabelList.add(ltArmorMaxLabel); - armorMaxLabelList.add(rtArmorMaxLabel); - armorMaxLabelList.add(ctArmorMaxLabel); - - Dimension labelSize = new Dimension(40, 20); - for (JLabel label : armorMaxLabelList) { - label.setSize(labelSize); - label.setMaximumSize(labelSize); - label.setPreferredSize(labelSize); - label.setMinimumSize(labelSize); - } - - JPanel topPanel; - JPanel bottomPanel; - - synchronized (getMech()) { - for (int location = 0; location < getMech().locations(); location++) { - - switch (location) { - case Mech.LOC_HEAD: - topPanel = new JPanel(new GridLayout(2, 0)); - topPanel.add(hdArmorField); - topPanel.add(hdArmorMaxLabel); - headPanel.add(topPanel); - - bottomPanel = new JPanel(); - bottomPanel.add(unallocatedPointsLabelPatchworkHead); - bottomPanel.add(unallocatedPointsFieldHead); - - headPanel.add(bottomPanel); - - headPanel - .setBorder(BorderFactory.createTitledBorder( - null, getMech().getLocationAbbr(location), - TitledBorder.TOP, - TitledBorder.DEFAULT_POSITION)); - - hdArmorModel.setStepSize(1); - hdArmorModel.setMinimum(0); - break; - case Mech.LOC_LARM: - topPanel = new JPanel(new GridLayout(2, 0)); - topPanel.add(laArmorField); - topPanel.add(laArmorMaxLabel); - laPanel.add(topPanel); - - bottomPanel = new JPanel(); - bottomPanel.add(unallocatedPointsLabelPatchworkLa); - bottomPanel.add(unallocatedPointsFieldLa); - laPanel.add(bottomPanel); - - laPanel.setBorder(BorderFactory.createTitledBorder( - null, getMech().getLocationAbbr(location), - TitledBorder.TOP, TitledBorder.DEFAULT_POSITION)); - - laArmorModel.setStepSize(1); - laArmorModel.setMinimum(0); - break; - case Mech.LOC_RARM: - topPanel = new JPanel(new GridLayout(2, 0)); - topPanel.add(raArmorField); - topPanel.add(raArmorMaxLabel); - raPanel.add(topPanel); - - bottomPanel = new JPanel(); - bottomPanel.add(unallocatedPointsLabelPatchworkRa); - bottomPanel.add(unallocatedPointsFieldRa); - raPanel.add(bottomPanel); - - raPanel.setBorder(BorderFactory.createTitledBorder( - null, getMech().getLocationAbbr(location), - TitledBorder.TOP, TitledBorder.DEFAULT_POSITION)); - - raArmorModel.setStepSize(1); - raArmorModel.setMinimum(0); - break; - case Mech.LOC_CT: - topPanel = new JPanel(new GridLayout(4, 0)); - topPanel.add(ctArmorField); - topPanel.add(new JLabel("Rear", SwingConstants.CENTER)); - topPanel.add(ctrArmorField); - topPanel.add(ctArmorMaxLabel); - ctPanel.setBorder(BorderFactory.createTitledBorder( - null, getMech().getLocationAbbr(location), - TitledBorder.TOP, TitledBorder.DEFAULT_POSITION)); - ctPanel.add(topPanel); - - bottomPanel = new JPanel(); - bottomPanel.add(unallocatedPointsLabelPatchworkCt); - bottomPanel.add(unallocatedPointsFieldCt); - ctPanel.add(bottomPanel); - - ctArmorModel.setStepSize(1); - ctArmorModel.setMinimum(0); - ctrArmorModel.setStepSize(1); - ctrArmorModel.setMinimum(0); - break; - case Mech.LOC_LT: - topPanel = new JPanel(new GridLayout(4, 0)); - topPanel.add(ltArmorField); - topPanel.add(new JLabel("Rear", SwingConstants.CENTER)); - topPanel.add(ltrArmorField); - topPanel.add(ltArmorMaxLabel); - ltPanel.setBorder(BorderFactory.createTitledBorder( - null, getMech().getLocationAbbr(location), - TitledBorder.TOP, TitledBorder.DEFAULT_POSITION)); - ltPanel.add(topPanel); - - bottomPanel = new JPanel(); - bottomPanel.add(unallocatedPointsLabelPatchworkLt); - bottomPanel.add(unallocatedPointsFieldLt); - ltPanel.add(bottomPanel); - - ltArmorModel.setStepSize(1); - ltArmorModel.setMinimum(0); - ltrArmorModel.setStepSize(1); - ltrArmorModel.setMinimum(0); - break; - case Mech.LOC_RT: - topPanel = new JPanel(new GridLayout(4, 0)); - topPanel.add(rtArmorField); - topPanel.add(new JLabel("Rear", SwingConstants.CENTER)); - topPanel.add(rtrArmorField); - topPanel.add(rtArmorMaxLabel); - rtPanel.setBorder(BorderFactory.createTitledBorder( - null, getMech().getLocationAbbr(location), - TitledBorder.TOP, TitledBorder.DEFAULT_POSITION)); - rtPanel.add(topPanel); - - bottomPanel = new JPanel(); - bottomPanel.add(unallocatedPointsLabelPatchworkRt); - bottomPanel.add(unallocatedPointsFieldRt); - rtPanel.add(bottomPanel); - - rtArmorModel.setStepSize(1); - rtArmorModel.setMinimum(0); - rtrArmorModel.setStepSize(1); - rtrArmorModel.setMinimum(0); - break; - case Mech.LOC_LLEG: - topPanel = new JPanel(new GridLayout(2, 0)); - topPanel.add(llArmorField); - topPanel.add(llArmorMaxLabel); - llPanel.add(topPanel); - - bottomPanel = new JPanel(); - bottomPanel.add(unallocatedPointsLabelPatchworkLl); - bottomPanel.add(unallocatedPointsFieldLl); - llPanel.add(bottomPanel); - - llPanel.setBorder(BorderFactory.createTitledBorder( - null, getMech().getLocationAbbr(location), - TitledBorder.TOP, TitledBorder.DEFAULT_POSITION)); - - llArmorModel.setStepSize(1); - llArmorModel.setMinimum(0); - break; - case Mech.LOC_RLEG: - topPanel = new JPanel(new GridLayout(2, 0)); - topPanel.add(rlArmorField); - topPanel.add(rlArmorMaxLabel); - rlPanel.add(topPanel); - - bottomPanel = new JPanel(); - bottomPanel.add(unallocatedPointsLabelPatchworkRl); - bottomPanel.add(unallocatedPointsFieldRl); - rlPanel.add(bottomPanel); - - rlPanel.setBorder(BorderFactory.createTitledBorder( - null, getMech().getLocationAbbr(location), - TitledBorder.TOP, TitledBorder.DEFAULT_POSITION)); - - rlArmorModel.setStepSize(1); - rlArmorModel.setMinimum(0); - break; - case Mech.LOC_CLEG: - topPanel = new JPanel(new GridLayout(2, 0)); - topPanel.add(clArmorField); - topPanel.add(clArmorMaxLabel); - clPanel.add(topPanel); - - bottomPanel = new JPanel(); - bottomPanel.add(unallocatedPointsLabelPatchworkCl); - bottomPanel.add(unallocatedPointsFieldCl); - clPanel.add(bottomPanel); - - clPanel.setBorder(BorderFactory.createTitledBorder( - null, getMech().getLocationAbbr(location), - TitledBorder.TOP, TitledBorder.DEFAULT_POSITION)); - - clArmorModel.setStepSize(1); - clArmorModel.setMinimum(0); - break; - } - } - } - - JPanel totalArmorPanel = new JPanel(); - - Vector valueFields = new Vector(); - valueFields.add(valueUnallocatedArmor); - valueFields.add(valueAllocatedArmor); - valueFields.add(valueCurrentArmor); - valueFields.add(valueMaxArmor); - valueFields.add(valueWastedArmor); - - Dimension valueSize = new Dimension(45, 20); - for (JTextField field : valueFields) { - field.setEditable(false); - field.setSize(valueSize); - field.setPreferredSize(valueSize); - field.setMinimumSize(valueSize); - field.setMaximumSize(valueSize); - field.setHorizontalAlignment(SwingConstants.RIGHT); - } - - totalArmorPanel.setLayout(new GridBagLayout()); - gbc = new GridBagConstraints(); - gbc.gridx = 0; - gbc.gridy = 0; - gbc.insets = new Insets(2, 2, 2, 2); - gbc.anchor = GridBagConstraints.WEST; - totalArmorPanel.add(Box.createVerticalStrut(18), gbc); - gbc.gridy++; - totalArmorPanel.add(lblUnallocatedArmor, gbc); - gbc.gridx = 1; - totalArmorPanel.add(valueUnallocatedArmor, gbc); - gbc.gridx = 0; - gbc.gridy++; - totalArmorPanel.add(lblAllocatedArmor, gbc); - gbc.gridx = 1; - totalArmorPanel.add(valueAllocatedArmor, gbc); - gbc.gridx = 0; - gbc.gridy++; - totalArmorPanel.add(lblCurrentArmor, gbc); - gbc.gridx = 1; - totalArmorPanel.add(valueCurrentArmor, gbc); - gbc.gridx = 0; - gbc.gridy++; - totalArmorPanel.add(lblMaxArmor, gbc); - gbc.gridx = 1; - totalArmorPanel.add(valueMaxArmor, gbc); - gbc.gridx = 0; - gbc.gridy++; - totalArmorPanel.add(lblWastedArmor, gbc); - gbc.gridx = 1; - totalArmorPanel.add(valueWastedArmor, gbc); - gbc.gridx = 0; - gbc.gridy++; - gbc.gridwidth = 2; - gbc.anchor = GridBagConstraints.CENTER; - totalArmorPanel.add(Box.createVerticalStrut(18), gbc); - gbc.gridy++; - totalArmorPanel.add(allocateArmorButton, gbc); - - gbc = new GridBagConstraints(); - gbc.gridx = 0; - gbc.gridy = mainPanelGridY; - gbc.gridwidth = 5; - gbc.fill = GridBagConstraints.NONE; - gbc.anchor = GridBagConstraints.CENTER; - mainPanel.add(totalArmorPanel, gbc); - this.add(mainPanel); - - resetArmorPoints(); - - addAllListeners(); - } - - private void addAllListeners() { - allocateArmorButton.addActionListener(this); - for (JSpinner spinner : armorFieldList) { - spinner.addChangeListener(this); - } - } - - private void removeAllListeners() { - allocateArmorButton.removeActionListener(this); - for (JSpinner spinner : armorFieldList) { - spinner.removeChangeListener(this); - } - } - - public void refresh() { - removeAllListeners(); - clPanel.setVisible(getMech() instanceof TripodMech); - for (int location = 0; location < getMech().locations(); location++) { - int maxArmor = getMech().getOInternal(location) * 2; - int headMaxArmor = 9; - if (getMech().isSuperHeavy()) { - headMaxArmor = 12; - } - int rearArmor; - switch (location) { - case Mech.LOC_HEAD: - hdArmorModel.setValue(Math.min(headMaxArmor, getMech().getArmor(location))); - hdArmorModel.setMaximum(headMaxArmor); - hdArmorMaxLabel.setText("max: "+headMaxArmor); - break; - case Mech.LOC_LARM: - laArmorModel.setValue(Math.min(maxArmor, - getMech().getArmor(location))); - laArmorModel.setMaximum(maxArmor); - laArmorMaxLabel.setText("max: " - + Integer.toString(maxArmor)); - break; - case Mech.LOC_RARM: - raArmorModel.setValue(Math.min(maxArmor, - getMech().getArmor(location))); - raArmorModel.setMaximum(maxArmor); - raArmorMaxLabel.setText("max: " - + Integer.toString(maxArmor)); - break; - case Mech.LOC_CT: - ctArmorModel.setValue(Math.min(maxArmor, - getMech().getArmor(location))); - ctArmorModel.setMaximum(maxArmor); - ctrArmorModel.setMaximum(maxArmor); - rearArmor = Math.min(getMech().getArmor(location, true), - maxArmor - getMech().getArmor(location)); - ctrArmorModel.setValue(rearArmor); - getMech().initializeRearArmor(rearArmor, location); - - ctArmorMaxLabel.setText("max: " - + Integer.toString(maxArmor)); - break; - case Mech.LOC_LT: - ltArmorModel.setValue(Math.min(maxArmor, - getMech().getArmor(location))); - - ltArmorModel.setMaximum(maxArmor); - ltrArmorModel.setMaximum(maxArmor); - rearArmor = Math.min(getMech().getArmor(location, true), - maxArmor - getMech().getArmor(location)); - ltrArmorModel.setValue(rearArmor); - getMech().initializeRearArmor(rearArmor, location); - - ltArmorMaxLabel.setText("max: " - + Integer.toString(maxArmor)); - break; - case Mech.LOC_RT: - rtArmorModel.setValue(Math.min(maxArmor, - getMech().getArmor(location))); - - rtArmorModel.setMaximum(maxArmor); - rtrArmorModel.setMaximum(maxArmor); - rearArmor = Math.min(getMech().getArmor(location, true), - maxArmor - getMech().getArmor(location)); - rtrArmorModel.setValue(rearArmor); - getMech().initializeRearArmor(rearArmor, location); - - rtArmorMaxLabel.setText("max: " - + Integer.toString(maxArmor)); - break; - case Mech.LOC_LLEG: - llArmorModel.setValue(Math.min(maxArmor, - getMech().getArmor(location))); - llArmorModel.setMaximum(maxArmor); - llArmorMaxLabel.setText("max: " - + Integer.toString(maxArmor)); - break; - case Mech.LOC_RLEG: - rlArmorModel.setValue(Math.min(maxArmor, - getMech().getArmor(location))); - rlArmorModel.setMaximum(maxArmor); - rlArmorMaxLabel.setText("max: " - + Integer.toString(maxArmor)); - break; - case Mech.LOC_CLEG: - clArmorModel.setValue(Math.min(maxArmor, - getMech().getArmor(location))); - clArmorModel.setMaximum(maxArmor); - clArmorMaxLabel.setText("max: " - + Integer.toString(maxArmor)); - break; - } - } - - // unallocated armorpoints - if (getMech().hasPatchworkArmor()) { - valueUnallocatedArmor.setVisible(false); - lblUnallocatedArmor.setVisible(false); - valueAllocatedArmor.setVisible(false); - lblAllocatedArmor.setVisible(false); - valueWastedArmor.setVisible(false); - lblWastedArmor.setVisible(false); - allocateArmorButton.setVisible(false); - unallocatedPointsLabelPatchworkHead.setVisible(true); - unallocatedPointsLabelPatchworkLa.setVisible(true); - unallocatedPointsLabelPatchworkLt.setVisible(true); - unallocatedPointsLabelPatchworkCt.setVisible(true); - unallocatedPointsLabelPatchworkRt.setVisible(true); - unallocatedPointsLabelPatchworkRa.setVisible(true); - unallocatedPointsLabelPatchworkLl.setVisible(true); - unallocatedPointsLabelPatchworkRl.setVisible(true); - unallocatedPointsFieldHead.setVisible(true); - unallocatedPointsFieldLa.setVisible(true); - unallocatedPointsFieldLt.setVisible(true); - unallocatedPointsFieldCt.setVisible(true); - unallocatedPointsFieldRt.setVisible(true); - unallocatedPointsFieldRa.setVisible(true); - unallocatedPointsFieldLl.setVisible(true); - unallocatedPointsFieldRl.setVisible(true); - unallocatedPointsFieldHead.setText(Integer.toString(UnitUtil - .getArmorPoints(getMech(), Mech.LOC_HEAD, - getMech().getArmorWeight(Mech.LOC_HEAD)) - - getMech().getOArmor(Mech.LOC_HEAD))); - unallocatedPointsFieldLa.setText(Integer.toString(UnitUtil - .getArmorPoints(getMech(), Mech.LOC_LARM, - getMech().getArmorWeight(Mech.LOC_LARM)) - - getMech().getOArmor(Mech.LOC_LARM))); - unallocatedPointsFieldLt.setText(Integer.toString(UnitUtil - .getArmorPoints(getMech(), Mech.LOC_LT, - getMech().getArmorWeight(Mech.LOC_LT)) - - getMech().getOArmor(Mech.LOC_LT) - getMech().getOArmor(Mech.LOC_LT, true))); - unallocatedPointsFieldCt.setText(Integer.toString(UnitUtil - .getArmorPoints(getMech(), Mech.LOC_CT, - getMech().getArmorWeight(Mech.LOC_CT)) - - getMech().getOArmor(Mech.LOC_CT) - getMech().getOArmor(Mech.LOC_CT, true))); - unallocatedPointsFieldRt.setText(Integer.toString(UnitUtil - .getArmorPoints(getMech(), Mech.LOC_RT, - getMech().getArmorWeight(Mech.LOC_RT)) - - getMech().getOArmor(Mech.LOC_RT) - getMech().getOArmor(Mech.LOC_RT, true))); - unallocatedPointsFieldRa.setText(Integer.toString(UnitUtil - .getArmorPoints(getMech(), Mech.LOC_RARM, - getMech().getArmorWeight(Mech.LOC_RARM)) - - getMech().getOArmor(Mech.LOC_RARM))); - unallocatedPointsFieldLl.setText(Integer.toString(UnitUtil - .getArmorPoints(getMech(), Mech.LOC_LLEG, - getMech().getArmorWeight(Mech.LOC_LLEG)) - - getMech().getOArmor(Mech.LOC_LLEG))); - unallocatedPointsFieldRl.setText(Integer.toString(UnitUtil - .getArmorPoints(getMech(), Mech.LOC_RLEG, - getMech().getArmorWeight(Mech.LOC_RLEG)) - - getMech().getOArmor(Mech.LOC_RLEG))); - if (getMech() instanceof TripodMech) { - unallocatedPointsFieldCl.setVisible(true); - unallocatedPointsFieldCl.setText(Integer.toString(UnitUtil - .getArmorPoints(getMech(), Mech.LOC_CLEG, - getMech().getArmorWeight(Mech.LOC_CLEG)) - - getMech().getOArmor(Mech.LOC_CLEG))); - } - } else { - valueUnallocatedArmor.setVisible(true); - lblUnallocatedArmor.setVisible(true); - valueAllocatedArmor.setVisible(true); - lblAllocatedArmor.setVisible(true); - allocateArmorButton.setVisible(true); - valueWastedArmor.setVisible(true); - lblWastedArmor.setVisible(true); - unallocatedPointsLabelPatchworkHead.setVisible(false); - unallocatedPointsLabelPatchworkLa.setVisible(false); - unallocatedPointsLabelPatchworkLt.setVisible(false); - unallocatedPointsLabelPatchworkCt.setVisible(false); - unallocatedPointsLabelPatchworkRt.setVisible(false); - unallocatedPointsLabelPatchworkRa.setVisible(false); - unallocatedPointsLabelPatchworkLl.setVisible(false); - unallocatedPointsLabelPatchworkRl.setVisible(false); - unallocatedPointsFieldHead.setVisible(false); - unallocatedPointsFieldLa.setVisible(false); - unallocatedPointsFieldLt.setVisible(false); - unallocatedPointsFieldCt.setVisible(false); - unallocatedPointsFieldRt.setVisible(false); - unallocatedPointsFieldRa.setVisible(false); - unallocatedPointsFieldLl.setVisible(false); - unallocatedPointsFieldRl.setVisible(false); - if (getMech() instanceof TripodMech) { - unallocatedPointsLabelPatchworkCl.setVisible(false); - unallocatedPointsFieldCl.setVisible(false); - } - } - valueAllocatedArmor.setText(Integer.toString(getMech().getTotalOArmor())); - valueUnallocatedArmor.setText(Integer.toString(armorPoints - - getMech().getTotalOArmor())); - if (armorPoints != getMech().getTotalOArmor()) { - valueUnallocatedArmor.setForeground(Color.RED); - lblUnallocatedArmor.setForeground(Color.RED); - } else { - valueUnallocatedArmor.setForeground(Color.BLACK); - lblUnallocatedArmor.setForeground(Color.BLACK); - } - valueCurrentArmor.setText(Integer.toString(armorPoints)); - // Total Possible armor is Internal*2 +3 for the extra 3 armor the head - // can support. - int headArmor = 3; - if (getMech().isSuperHeavy()) { - headArmor = 4; - } - valueMaxArmor.setText(Integer.toString((getMech().getTotalOInternal() * 2) - + headArmor)); - valueWastedArmor.setText(Integer.toString(wastedArmorPoints)); - - addAllListeners(); - } - - public void addRefreshedListener(RefreshListener l) { - refresh = l; - } - - public void allocateArmor() { - double pointsToAllocate = armorPoints; - int headPoints = 3; - if (getMech().isSuperHeavy()) { - headPoints = 4; - } - double totalArmor = (getMech().getTotalOInternal() * 2) + headPoints; - if (pointsToAllocate > totalArmor) { - pointsToAllocate = totalArmor; - } - double percent = pointsToAllocate / totalArmor; - int headMaxArmor = 9; - if (getMech().isSuperHeavy()) { - headMaxArmor = 12; - } - // put 5 times the percentage of total possible armor into the head - int headArmor = (int) Math.min(Math.floor(percent * headMaxArmor * 5), headMaxArmor); - getMech().initializeArmor(headArmor, Mech.LOC_HEAD); - pointsToAllocate -= headArmor; - for (int location = 0; location < getMech().locations(); location++) { - double IS = (getMech().getInternal(location) * 2); - double allocate = Math.min(IS * percent, pointsToAllocate); - switch (location) { - case Mech.LOC_HEAD: - break; - case Mech.LOC_CT: - case Mech.LOC_LT: - case Mech.LOC_RT: - double rear = Math.floor(allocate * .25); - double front = Math.ceil(allocate * .75); - pointsToAllocate -= (int) rear; - pointsToAllocate -= (int) front; - getMech().initializeArmor((int) front, location); - getMech().initializeRearArmor((int) rear, location); - break; - default: - getMech().initializeArmor((int) allocate, location); - pointsToAllocate -= (int) allocate; - break; - } - } - allocateLeftoverPoints(pointsToAllocate); - - if (refresh != null) { - refresh.refreshStatus(); - } - } - - /** - * allocate any leftover points one-by-one - * - * @param points - * the amount of points left over - */ - private void allocateLeftoverPoints(double points) { - int headMaxArmor = 9; - if (getMech().isSuperHeavy()) { - headMaxArmor = 12; - } - while (points >= 1) { - // if two or more are left, add armor to symmetrical locations, - // to torso, legs, arms, in that order - if (points >= 2) { - if (((getMech().getOArmor(Mech.LOC_LT) + getMech().getOArmor(Mech.LOC_LT, - true)) < (getMech().getOInternal(Mech.LOC_LT) * 2)) - && ((getMech().getOArmor(Mech.LOC_RT) + getMech().getOArmor( - Mech.LOC_RT, true)) < (getMech() - .getOInternal(Mech.LOC_RT) * 2))) { - getMech().initializeArmor(getMech().getOArmor(Mech.LOC_LT) + 1, - Mech.LOC_LT); - getMech().initializeArmor(getMech().getOArmor(Mech.LOC_RT) + 1, - Mech.LOC_RT); - points -= 2; - } else if ((getMech().getOArmor(Mech.LOC_LLEG) < (getMech() - .getOInternal(Mech.LOC_LLEG) * 2)) - && (getMech().getOArmor(Mech.LOC_RLEG) < (getMech() - .getOInternal(Mech.LOC_RLEG) * 2))) { - getMech().initializeArmor(getMech().getOArmor(Mech.LOC_LLEG) + 1, - Mech.LOC_LLEG); - getMech().initializeArmor(getMech().getOArmor(Mech.LOC_RLEG) + 1, - Mech.LOC_RLEG); - points -= 2; - } else if ((getMech().getOArmor(Mech.LOC_LARM) < (getMech() - .getOInternal(Mech.LOC_LARM) * 2)) - && (getMech().getOArmor(Mech.LOC_RARM) < (getMech() - .getOInternal(Mech.LOC_RARM) * 2))) { - getMech().initializeArmor(getMech().getOArmor(Mech.LOC_LARM) + 1, - Mech.LOC_LARM); - getMech().initializeArmor(getMech().getOArmor(Mech.LOC_RARM) + 1, - Mech.LOC_RARM); - points -= 2; - } - // otherwise, first add to the head, and then even out uneven - // allocation - } else if (getMech().getOArmor(Mech.LOC_HEAD) < headMaxArmor) { - getMech().initializeArmor(getMech().getOArmor(Mech.LOC_HEAD) + 1, - Mech.LOC_HEAD); - points--; - } else if (getMech().getOArmor(Mech.LOC_LT) < getMech() - .getOArmor(Mech.LOC_RT)) { - getMech().initializeArmor(getMech().getOArmor(Mech.LOC_LT) + 1, - Mech.LOC_LT); - points--; - } else if (getMech().getOArmor(Mech.LOC_RT) < getMech() - .getOArmor(Mech.LOC_LT)) { - getMech().initializeArmor(getMech().getOArmor(Mech.LOC_RT) + 1, - Mech.LOC_RT); - points--; - } else if (getMech().getOArmor(Mech.LOC_RARM) < getMech() - .getOArmor(Mech.LOC_LARM)) { - getMech().initializeArmor(getMech().getOArmor(Mech.LOC_RARM) + 1, - Mech.LOC_RARM); - points--; - } else if (getMech().getOArmor(Mech.LOC_LARM) < getMech() - .getOArmor(Mech.LOC_RARM)) { - getMech().initializeArmor(getMech().getOArmor(Mech.LOC_LARM) + 1, - Mech.LOC_LARM); - points--; - } else if (getMech().getOArmor(Mech.LOC_RLEG) < getMech() - .getArmor(Mech.LOC_LLEG)) { - getMech().initializeArmor(getMech().getOArmor(Mech.LOC_RLEG) + 1, - Mech.LOC_RLEG); - points--; - } else if (getMech().getOArmor(Mech.LOC_LLEG) < getMech() - .getOArmor(Mech.LOC_RLEG)) { - getMech().initializeArmor(getMech().getOArmor(Mech.LOC_LLEG) + 1, - Mech.LOC_LLEG); - points--; - // if nothing is uneven, add to the CT - } else if (((getMech().getOArmor(Mech.LOC_CT) + getMech().getOArmor( - Mech.LOC_CT, true)) < (getMech().getOInternal(Mech.LOC_CT) * 2))) { - getMech().initializeArmor(getMech().getOArmor(Mech.LOC_CT) + 1, - Mech.LOC_CT); - points--; - } - // if only one is left, and head and CT have max, remove one from CT - // so symmetric locations can get extra, unless they are already at - // max - if (points == 1) { - if ((getMech().getOArmor(Mech.LOC_HEAD) == headMaxArmor) - && ((getMech().getOArmor(Mech.LOC_CT) + getMech().getOArmor( - Mech.LOC_CT, true)) == (getMech() - .getOInternal(Mech.LOC_CT) * 2))) { - getMech().initializeArmor(getMech().getOArmor(Mech.LOC_CT) - 1, - Mech.LOC_CT); - points++; - } - } - // if all locations have max, return - boolean toReturn = true; - for (int location = 0; location < getMech().locations(); location++) { - double is = (getMech().getInternal(location) * 2); - switch (location) { - case Mech.LOC_HEAD: - int headPoints = 3; - if (getMech().isSuperHeavy()) { - headPoints = 4; - } - if ((is + headPoints) > getMech().getOArmor(location)) { - toReturn = false; - } - break; - case Mech.LOC_CT: - case Mech.LOC_LT: - case Mech.LOC_RT: - if (is > (getMech().getOArmor(location) + getMech().getOArmor( - location, true))) { - toReturn = false; - } - break; - default: - if (is > getMech().getOArmor(location)) { - toReturn = false; - } - break; - } - } - if (toReturn) { - return; - } - } - } - - public void stateChanged(ChangeEvent e) { - removeAllListeners(); - int allowedArmorPoints = armorPoints; - if (getMech().hasPatchworkArmor()) { - allowedArmorPoints = UnitUtil.getMaximumArmorPoints(getMech()); - } - JSpinner field = (JSpinner) e.getSource(); - boolean isRear = field.equals(ctrArmorField) - || field.equals(ltrArmorField) || field.equals(rtrArmorField); - int location = Integer.parseInt(field.getName()); - int maxArmor = getMech().getOInternal(location) * 2; - int value = (Integer) field.getModel().getValue(); - - // How much armor do we have without the value that was just changed - int totalArmor = 0; - for (int loc = 0; loc < getMech().locations(); loc++) { - if (loc != location) { - totalArmor += getMech().getOArmor(loc); - if (getMech().hasRearArmor(loc)) { - totalArmor += getMech().getOArmor(loc, true); - } - } else if ((loc == location) && getMech().hasRearArmor(loc)) { - totalArmor += getMech().getOArmor(loc, !isRear); - } - } - - // Do we have enough armor points to make this change? - if ((allowedArmorPoints - (totalArmor + value)) < 0) { - // See if we can pull armor from the opposite location - if (getMech().hasRearArmor(location) - && getMech().getOArmor(location,!isRear) > 0) { - stealArmorFromOppositeSide(location, isRear); - } else { // If we can't pull armor, just revert the change and end - field.setValue(value - 1); - addAllListeners(); - return; - } - } - - // If this change would put us over the per-location total, may have to - // steal a point from the other side - if (getMech().hasRearArmor(location) - && ((value + getMech().getOArmor(location, !isRear)) > maxArmor)) { - stealArmorFromOppositeSide(location, isRear); - } - - // Update armor in the changed location - switch (location) { - case Mech.LOC_CT: - if (isRear) { - getMech().initializeRearArmor(value, location); - } else { - getMech().initializeArmor(value, location); - } - break; - case Mech.LOC_RT: - if (isRear) { - getMech().initializeRearArmor(value, location); - } else { - getMech().initializeArmor(value, location); - } - break; - case Mech.LOC_LT: - if (isRear) { - getMech().initializeRearArmor(value, location); - } else { - getMech().initializeArmor(value, location); - } - break; - default: - getMech().initializeArmor(value, location); - break; - } - if (getMech().hasPatchworkArmor()) { - setArmorPoints(getMech().getTotalArmor()); - } - if (refresh != null) { - addAllListeners(); - refresh.refreshStructure(); - removeAllListeners(); - refresh.refreshStatus(); - } - addAllListeners(); - } - - /** - * Given a location and whether it's rear or not, take a point of armor from - * the opposite side. That is, given a rear CT location, reduce the front - * CT by 1 point of armor. - * - * @param location - * @param isRear - */ - private void stealArmorFromOppositeSide(int location, boolean isRear) { - JSpinner opposite = getOppositeSpinner(location, isRear); - int oppositeValue = (Integer)opposite.getValue(); - // "Steal" armor from the opposite side - oppositeValue--; - opposite.setValue(oppositeValue); - // Make sure the Unit reflects the armor update - if (!isRear) { - getMech().initializeRearArmor(oppositeValue, location); - } else { - getMech().initializeArmor(oppositeValue, location); - } - } - - /** - * For swapping armor between front and rear locations, we need to get the - * JSpinner that correspondes to the opposite side of a location. Ie, if - * we are given the front CT, return the rear CT JSpinner. - * - * @param location - * @param isRear - * @return - */ - private JSpinner getOppositeSpinner(int location, boolean isRear) { - JSpinner opposite; - switch (location) { - case Mech.LOC_CT: - if (isRear) { - opposite = ctArmorField; - } else { - opposite = ctrArmorField; - } - break; - case Mech.LOC_LT: - if (isRear) { - opposite = ltArmorField; - } else { - opposite = ltrArmorField; - } - break; - case Mech.LOC_RT: - if (isRear) { - opposite = rtArmorField; - } else { - opposite = rtrArmorField; - } - break; - default : - opposite = null; - } - return opposite; - } - - public void setArmorPoints(int points) { - int headPoints = 3; - if (getMech().isSuperHeavy()) { - headPoints = 4; - } - int maxArmor = (getMech().getTotalOInternal() * 2) + headPoints; - wastedArmorPoints = Math.max(points - maxArmor, 0); - armorPoints = Math.min(maxArmor, points); - } - - @Override - public void actionPerformed(ActionEvent e) { - removeAllListeners(); - if (e.getSource().equals(allocateArmorButton)) { - allocateArmor(); - } - addAllListeners(); - refresh.refreshAll(); - } - - public void resetArmorPoints() { - double armorPerTon = 16.0 * EquipmentType.getArmorPointMultiplier( - getMech().getArmorType(0), getMech().getArmorTechLevel(0)); - setArmorPoints((int) Math - .floor(getMech().getLabArmorTonnage() * armorPerTon)); - } -} \ No newline at end of file diff --git a/src/megameklab/com/ui/Vehicle/views/ArmorView.java b/src/megameklab/com/ui/Vehicle/views/ArmorView.java deleted file mode 100644 index c321ca457..000000000 --- a/src/megameklab/com/ui/Vehicle/views/ArmorView.java +++ /dev/null @@ -1,931 +0,0 @@ -/* - * MegaMekLab - Copyright (C) 2008 - * - * Original author - jtighe (torren@users.sourceforge.net) - * - * This program 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 2 of the License, or (at your option) - * any later version. - * - * This program 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. - */ - -package megameklab.com.ui.Vehicle.views; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.GridLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.ArrayList; -import java.util.List; -import java.util.Vector; - -import javax.swing.BorderFactory; -import javax.swing.Box; -import javax.swing.BoxLayout; -import javax.swing.JButton; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JSpinner; -import javax.swing.JTextField; -import javax.swing.SpinnerNumberModel; -import javax.swing.SwingConstants; -import javax.swing.border.TitledBorder; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; - -import megamek.common.EquipmentType; -import megamek.common.Mech; -import megamek.common.SuperHeavyTank; -import megamek.common.Tank; -import megamek.common.VTOL; -import megamek.common.verifier.TestTank; -import megameklab.com.ui.EntitySource; -import megameklab.com.util.IView; -import megameklab.com.util.RefreshListener; -import megameklab.com.util.UnitUtil; - -public class ArmorView extends IView implements ChangeListener, ActionListener { - - /** - * - */ - private static final long serialVersionUID = 799195356642563937L; - - private JPanel mainPanel = new JPanel(); - - private JPanel frontPanel = new JPanel(); - private JPanel leftPanel = new JPanel(); - private JPanel rightPanel = new JPanel(); - private JPanel rearPanel = new JPanel(); - private JPanel turretPanel = new JPanel(); - private JPanel turret2Panel = new JPanel(); - private JPanel rearLeftPanel = new JPanel(); - private JPanel rearRightPanel = new JPanel(); - - public SpinnerNumberModel leftArmorModel = new SpinnerNumberModel(); - public SpinnerNumberModel rightArmorModel = new SpinnerNumberModel(); - public SpinnerNumberModel rearArmorModel = new SpinnerNumberModel(); - public SpinnerNumberModel turretArmorModel = new SpinnerNumberModel(); - public SpinnerNumberModel turret2ArmorModel = new SpinnerNumberModel(); - public SpinnerNumberModel rearLeftArmorModel = new SpinnerNumberModel(); - public SpinnerNumberModel rearRightArmorModel = new SpinnerNumberModel(); - public SpinnerNumberModel frontArmorModel = new SpinnerNumberModel(); - - private JSpinner leftArmorField = new JSpinner(leftArmorModel); - private JSpinner rightArmorField = new JSpinner(rightArmorModel); - private JSpinner rearArmorField = new JSpinner(rearArmorModel); - private JSpinner turretArmorField = new JSpinner(turretArmorModel); - private JSpinner turret2ArmorField = new JSpinner(turret2ArmorModel); - private JSpinner rearLeftArmorField = new JSpinner(rearLeftArmorModel); - private JSpinner rearRightArmorField = new JSpinner(rearRightArmorModel); - private JSpinner frontArmorField = new JSpinner(frontArmorModel); - - private List armorFieldList = new ArrayList(); - - private JLabel frontArmorMaxLabel = new JLabel("", SwingConstants.CENTER); - private JLabel leftArmorMaxLabel = new JLabel("", SwingConstants.CENTER); - private JLabel rightArmorMaxLabel = new JLabel("", SwingConstants.CENTER); - private JLabel rearArmorMaxLabel = new JLabel("", SwingConstants.CENTER); - private JLabel turretArmorMaxLabel = new JLabel("", SwingConstants.CENTER); - private JLabel turret2ArmorMaxLabel = new JLabel("", SwingConstants.CENTER); - private JLabel rearLeftArmorMaxLabel = new JLabel("", SwingConstants.CENTER); - private JLabel rearRightArmorMaxLabel = new JLabel("", SwingConstants.CENTER); - - private List armorMaxLabelList = new ArrayList(); - - private JLabel lblAllocatedArmor = new JLabel("Allocated Armor Points:"); - private JTextField valueAllocatedArmor = new JTextField(); - private JLabel lblUnallocatedArmor = new JLabel("Unallocated Armor Points:"); - private JTextField valueUnallocatedArmor = new JTextField(); - private JLabel lblCurrentArmor = new JLabel("Total Armor Points:"); - private JTextField valueCurrentArmor = new JTextField(); - private JLabel lblMaxArmor = new JLabel("Maximum Possible Armor Points:"); - private JTextField valueMaxArmor = new JTextField(); - private JLabel lblWastedArmor = new JLabel("Wasted Armor Points:"); - private JTextField valueWastedArmor = new JTextField(); - - private JLabel unallocatedPointsLabelPatchworkFront = new JLabel( - "Unalloc.:", SwingConstants.TRAILING); - private JLabel unallocatedPointsLabelPatchworkLeft = new JLabel( - "Unalloc.:", SwingConstants.TRAILING); - private JLabel unallocatedPointsLabelPatchworkTurret2 = new JLabel( - "Unalloc.:", SwingConstants.TRAILING); - private JLabel unallocatedPointsLabelPatchworkRearRight = new JLabel( - "Unalloc.:", SwingConstants.TRAILING); - private JLabel unallocatedPointsLabelPatchworkRearLeft = new JLabel( - "Unalloc.:", SwingConstants.TRAILING); - private JLabel unallocatedPointsLabelPatchworkRight = new JLabel( - "Unalloc.:", SwingConstants.TRAILING); - private JLabel unallocatedPointsLabelPatchworkRear = new JLabel( - "Unalloc.:", SwingConstants.TRAILING); - private JLabel unallocatedPointsLabelPatchworkTurret = new JLabel( - "Unalloc.:", SwingConstants.TRAILING); - private JLabel unallocatedPointsFieldFront = new JLabel(); - private JLabel unallocatedPointsFieldLeft = new JLabel(); - private JLabel unallocatedPointsFieldTurret2 = new JLabel(); - private JLabel unallocatedPointsFieldRearRight = new JLabel(); - private JLabel unallocatedPointsFieldRearLeft = new JLabel(); - private JLabel unallocatedPointsFieldRight = new JLabel(); - private JLabel unallocatedPointsFieldRear = new JLabel(); - private JLabel unallocatedPointsFieldTurret = new JLabel(); - - private int armorPoints; - private int wastedArmorPoints; - - private JButton allocateArmorButton = new JButton("Auto-Allocate Armor"); - - private RefreshListener refresh; - - public ArmorView(EntitySource eSource) { - super(eSource); - - setLayout(new GridLayout(1, 1)); - - mainPanel.setLayout(new GridBagLayout()); - GridBagConstraints gbc; - - frontPanel.setLayout(new BoxLayout(frontPanel, BoxLayout.Y_AXIS)); - leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.Y_AXIS)); - rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.Y_AXIS)); - turret2Panel.setLayout(new BoxLayout(turret2Panel, BoxLayout.Y_AXIS)); - rearRightPanel.setLayout(new BoxLayout(rearRightPanel, BoxLayout.Y_AXIS)); - rearLeftPanel.setLayout(new BoxLayout(rearLeftPanel, BoxLayout.Y_AXIS)); - rearPanel.setLayout(new BoxLayout(rearPanel, BoxLayout.Y_AXIS)); - turretPanel.setLayout(new BoxLayout(turretPanel, BoxLayout.Y_AXIS)); - - - if (getTank() instanceof SuperHeavyTank) { - gbc = new GridBagConstraints(); - gbc.gridx = 1; - gbc.gridy = 0; - mainPanel.add(frontPanel, gbc); - gbc.gridx = 0; - gbc.gridy = 1; - mainPanel.add(leftPanel, gbc); - gbc.gridx = 1; - mainPanel.add(turret2Panel, gbc); - gbc.gridx = 2; - mainPanel.add(rightPanel, gbc); - gbc.gridx = 0; - gbc.gridy = 2; - mainPanel.add(rearLeftPanel, gbc); - gbc.gridx = 1; - mainPanel.add(turretPanel, gbc); - gbc.gridx = 2; - mainPanel.add(rearRightPanel, gbc); - gbc.gridy = 3; - gbc.gridx = 1; - mainPanel.add(rearPanel, gbc); - - leftArmorField.setName(Integer.toString(SuperHeavyTank.LOC_FRONTLEFT)); - rightArmorField.setName(Integer.toString(SuperHeavyTank.LOC_FRONTRIGHT)); - rearArmorField.setName(Integer.toString(SuperHeavyTank.LOC_REAR)); - turretArmorField.setName(Integer.toString(SuperHeavyTank.LOC_TURRET)); - turret2ArmorField.setName(Integer.toString(SuperHeavyTank.LOC_TURRET_2)); - rearLeftArmorField.setName(Integer.toString(SuperHeavyTank.LOC_REARLEFT)); - rearRightArmorField.setName(Integer.toString(SuperHeavyTank.LOC_REARRIGHT)); - frontArmorField.setName(Integer.toString(Tank.LOC_FRONT)); - armorFieldList.add(leftArmorField); - armorFieldList.add(rightArmorField); - armorFieldList.add(rearArmorField); - armorFieldList.add(turretArmorField); - armorFieldList.add(turret2ArmorField); - armorFieldList.add(rearLeftArmorField); - armorFieldList.add(rearRightArmorField); - armorFieldList.add(frontArmorField); - } else { - gbc = new GridBagConstraints(); - gbc.gridx = 1; - gbc.gridy = 0; - mainPanel.add(frontPanel, gbc); - gbc.gridx = 0; - gbc.gridy = 1; - gbc.gridheight = 2; - mainPanel.add(leftPanel, gbc); - gbc.gridx = 1; - gbc.gridheight = 1; - mainPanel.add(turret2Panel, gbc); - gbc.gridx = 2; - gbc.gridheight = 2; - mainPanel.add(rightPanel, gbc); - gbc.gridx = 1; - gbc.gridy = 2; - gbc.gridheight = 1; - mainPanel.add(turretPanel, gbc); - gbc.gridy = 3; - gbc.gridx = 1; - mainPanel.add(rearPanel, gbc); - leftArmorField.setName(Integer.toString(Tank.LOC_LEFT)); - rightArmorField.setName(Integer.toString(Tank.LOC_RIGHT)); - rearArmorField.setName(Integer.toString(Tank.LOC_REAR)); - turretArmorField.setName(Integer.toString(Tank.LOC_TURRET)); - turret2ArmorField.setName(Integer.toString(Tank.LOC_TURRET_2)); - frontArmorField.setName(Integer.toString(Tank.LOC_FRONT)); - armorFieldList.add(leftArmorField); - armorFieldList.add(rightArmorField); - armorFieldList.add(rearArmorField); - armorFieldList.add(turretArmorField); - armorFieldList.add(turret2ArmorField); - armorFieldList.add(frontArmorField); - } - Dimension size = new Dimension(40, 25); - for (JSpinner spinner : armorFieldList) { - // you don't set the size of the jspinner, but rather its internal - // textfield - ((JSpinner.DefaultEditor) spinner.getEditor()).setSize(size); - ((JSpinner.DefaultEditor) spinner.getEditor()).setMaximumSize(size); - ((JSpinner.DefaultEditor) spinner.getEditor()) - .setPreferredSize(size); - ((JSpinner.DefaultEditor) spinner.getEditor()).setMinimumSize(size); - } - armorMaxLabelList.add(frontArmorMaxLabel); - armorMaxLabelList.add(leftArmorMaxLabel); - armorMaxLabelList.add(rightArmorMaxLabel); - armorMaxLabelList.add(rearArmorMaxLabel); - armorMaxLabelList.add(turretArmorMaxLabel); - armorMaxLabelList.add(turret2ArmorMaxLabel); - armorMaxLabelList.add(rearLeftArmorMaxLabel); - armorMaxLabelList.add(rearRightArmorMaxLabel); - - Dimension labelSize = new Dimension(40, 20); - for (JLabel label : armorMaxLabelList) { - label.setSize(labelSize); - label.setMaximumSize(labelSize); - label.setPreferredSize(labelSize); - label.setMinimumSize(labelSize); - } - - addAllListeners(); - - JPanel topPanel; - JPanel bottomPanel; - - synchronized (getTank()) { - for (int location = 1; location <= getTank().locations(); location++) { - - if (getTank() instanceof SuperHeavyTank) { - switch (location) { - case Tank.LOC_FRONT: - topPanel = new JPanel(new GridLayout(2, 0)); - topPanel.add(frontArmorField); - topPanel.add(frontArmorMaxLabel); - frontPanel.add(topPanel); - - bottomPanel = new JPanel(); - bottomPanel.add(unallocatedPointsLabelPatchworkFront); - bottomPanel.add(unallocatedPointsFieldFront); - - frontPanel.add(bottomPanel); - - frontPanel - .setBorder(BorderFactory.createTitledBorder( - null, getTank().getLocationAbbr(location), - TitledBorder.TOP, - TitledBorder.DEFAULT_POSITION)); - break; - case SuperHeavyTank.LOC_FRONTLEFT: - topPanel = new JPanel(new GridLayout(2, 0)); - topPanel.add(leftArmorField); - topPanel.add(leftArmorMaxLabel); - leftPanel.add(topPanel); - - bottomPanel = new JPanel(); - bottomPanel.add(unallocatedPointsLabelPatchworkLeft); - bottomPanel.add(unallocatedPointsFieldLeft); - leftPanel.add(bottomPanel); - - leftPanel.setBorder(BorderFactory.createTitledBorder( - null, getTank().getLocationAbbr(location), - TitledBorder.TOP, TitledBorder.DEFAULT_POSITION)); - break; - case SuperHeavyTank.LOC_FRONTRIGHT: - topPanel = new JPanel(new GridLayout(2, 0)); - topPanel.add(rightArmorField); - topPanel.add(rightArmorMaxLabel); - rightPanel.add(topPanel); - - bottomPanel = new JPanel(); - bottomPanel.add(unallocatedPointsLabelPatchworkRight); - bottomPanel.add(unallocatedPointsFieldRight); - rightPanel.add(bottomPanel); - - rightPanel.setBorder(BorderFactory.createTitledBorder( - null, getTank().getLocationAbbr(location), - TitledBorder.TOP, TitledBorder.DEFAULT_POSITION)); - break; - case SuperHeavyTank.LOC_REARRIGHT: - topPanel = new JPanel(new GridLayout(2, 0)); - topPanel.add(rearRightArmorField); - topPanel.add(rearRightArmorMaxLabel); - rearRightPanel.setBorder(BorderFactory.createTitledBorder( - null, getTank().getLocationAbbr(location), - TitledBorder.TOP, TitledBorder.DEFAULT_POSITION)); - rearRightPanel.add(topPanel); - - bottomPanel = new JPanel(); - bottomPanel.add(unallocatedPointsLabelPatchworkRearRight); - bottomPanel.add(unallocatedPointsFieldRearRight); - rearRightPanel.add(bottomPanel); - - break; - case SuperHeavyTank.LOC_TURRET_2: - topPanel = new JPanel(new GridLayout(2, 0)); - topPanel.add(turret2ArmorField); - topPanel.add(turret2ArmorMaxLabel); - turret2Panel.setBorder(BorderFactory.createTitledBorder( - null, getTank().getLocationAbbr(location), - TitledBorder.TOP, TitledBorder.DEFAULT_POSITION)); - turret2Panel.add(topPanel); - - bottomPanel = new JPanel(); - bottomPanel.add(unallocatedPointsLabelPatchworkTurret2); - bottomPanel.add(unallocatedPointsFieldTurret2); - turret2Panel.add(bottomPanel); - - break; - case SuperHeavyTank.LOC_REARLEFT: - topPanel = new JPanel(new GridLayout(2, 0)); - topPanel.add(rearLeftArmorField); - topPanel.add(rearLeftArmorMaxLabel); - rearLeftPanel.setBorder(BorderFactory.createTitledBorder( - null, getTank().getLocationAbbr(location), - TitledBorder.TOP, TitledBorder.DEFAULT_POSITION)); - rearLeftPanel.add(topPanel); - - bottomPanel = new JPanel(); - bottomPanel.add(unallocatedPointsLabelPatchworkRearLeft); - bottomPanel.add(unallocatedPointsFieldRearLeft); - rearLeftPanel.add(bottomPanel); - - break; - case SuperHeavyTank.LOC_REAR: - topPanel = new JPanel(new GridLayout(2, 0)); - topPanel.add(rearArmorField); - topPanel.add(rearArmorMaxLabel); - rearPanel.add(topPanel); - - bottomPanel = new JPanel(); - bottomPanel.add(unallocatedPointsLabelPatchworkRear); - bottomPanel.add(unallocatedPointsFieldRear); - rearPanel.add(bottomPanel); - - rearPanel.setBorder(BorderFactory.createTitledBorder( - null, getTank().getLocationAbbr(location), - TitledBorder.TOP, TitledBorder.DEFAULT_POSITION)); - break; - case SuperHeavyTank.LOC_TURRET: - topPanel = new JPanel(new GridLayout(2, 0)); - topPanel.add(turretArmorField); - topPanel.add(turretArmorMaxLabel); - turretPanel.add(topPanel); - - bottomPanel = new JPanel(); - bottomPanel.add(unallocatedPointsLabelPatchworkTurret); - bottomPanel.add(unallocatedPointsFieldTurret); - turretPanel.add(bottomPanel); - - turretPanel.setBorder(BorderFactory.createTitledBorder( - null, getTank().getLocationAbbr(location), - TitledBorder.TOP, TitledBorder.DEFAULT_POSITION)); - break; - } - } else { - switch (location) { - case Tank.LOC_FRONT: - topPanel = new JPanel(new GridLayout(2, 0)); - topPanel.add(frontArmorField); - topPanel.add(frontArmorMaxLabel); - frontPanel.add(topPanel); - - bottomPanel = new JPanel(); - bottomPanel.add(unallocatedPointsLabelPatchworkFront); - bottomPanel.add(unallocatedPointsFieldFront); - - frontPanel.add(bottomPanel); - - frontPanel - .setBorder(BorderFactory.createTitledBorder( - null, getTank().getLocationAbbr(location), - TitledBorder.TOP, - TitledBorder.DEFAULT_POSITION)); - break; - case Tank.LOC_LEFT: - topPanel = new JPanel(new GridLayout(2, 0)); - topPanel.add(leftArmorField); - topPanel.add(leftArmorMaxLabel); - leftPanel.add(topPanel); - - bottomPanel = new JPanel(); - bottomPanel.add(unallocatedPointsLabelPatchworkLeft); - bottomPanel.add(unallocatedPointsFieldLeft); - leftPanel.add(bottomPanel); - - leftPanel.setBorder(BorderFactory.createTitledBorder( - null, getTank().getLocationAbbr(location), - TitledBorder.TOP, TitledBorder.DEFAULT_POSITION)); - break; - case Tank.LOC_RIGHT: - topPanel = new JPanel(new GridLayout(2, 0)); - topPanel.add(rightArmorField); - topPanel.add(rightArmorMaxLabel); - rightPanel.add(topPanel); - - bottomPanel = new JPanel(); - bottomPanel.add(unallocatedPointsLabelPatchworkRight); - bottomPanel.add(unallocatedPointsFieldRight); - rightPanel.add(bottomPanel); - - rightPanel.setBorder(BorderFactory.createTitledBorder( - null, getTank().getLocationAbbr(location), - TitledBorder.TOP, TitledBorder.DEFAULT_POSITION)); - break; - case Tank.LOC_TURRET_2: - topPanel = new JPanel(new GridLayout(2, 0)); - topPanel.add(turret2ArmorField); - topPanel.add(turret2ArmorMaxLabel); - turret2Panel.setBorder(BorderFactory.createTitledBorder( - null, getTank().getLocationAbbr(location), - TitledBorder.TOP, TitledBorder.DEFAULT_POSITION)); - turret2Panel.add(topPanel); - - bottomPanel = new JPanel(); - bottomPanel.add(unallocatedPointsLabelPatchworkTurret2); - bottomPanel.add(unallocatedPointsFieldTurret2); - turret2Panel.add(bottomPanel); - - break; - case Tank.LOC_REAR: - topPanel = new JPanel(new GridLayout(2, 0)); - topPanel.add(rearArmorField); - topPanel.add(rearArmorMaxLabel); - rearPanel.add(topPanel); - - bottomPanel = new JPanel(); - bottomPanel.add(unallocatedPointsLabelPatchworkRear); - bottomPanel.add(unallocatedPointsFieldRear); - rearPanel.add(bottomPanel); - - rearPanel.setBorder(BorderFactory.createTitledBorder( - null, getTank().getLocationAbbr(location), - TitledBorder.TOP, TitledBorder.DEFAULT_POSITION)); - break; - case Tank.LOC_TURRET: - topPanel = new JPanel(new GridLayout(2, 0)); - topPanel.add(turretArmorField); - topPanel.add(turretArmorMaxLabel); - turretPanel.add(topPanel); - - bottomPanel = new JPanel(); - bottomPanel.add(unallocatedPointsLabelPatchworkTurret); - bottomPanel.add(unallocatedPointsFieldTurret); - turretPanel.add(bottomPanel); - - turretPanel.setBorder(BorderFactory.createTitledBorder( - null, getTank().getLocationAbbr(location), - TitledBorder.TOP, TitledBorder.DEFAULT_POSITION)); - break; - } - } - - } - } - - JPanel totalArmorPanel = new JPanel(); - - Vector valueFields = new Vector(); - valueFields.add(valueUnallocatedArmor); - valueFields.add(valueAllocatedArmor); - valueFields.add(valueCurrentArmor); - valueFields.add(valueMaxArmor); - valueFields.add(valueWastedArmor); - - Dimension valueSize = new Dimension(45, 20); - for (JTextField field : valueFields) { - field.setEditable(false); - field.setSize(valueSize); - field.setPreferredSize(valueSize); - field.setMinimumSize(valueSize); - field.setMaximumSize(valueSize); - field.setHorizontalAlignment(SwingConstants.RIGHT); - } - - totalArmorPanel.setLayout(new GridBagLayout()); - gbc = new GridBagConstraints(); - gbc.gridx = 0; - gbc.gridy = 0; - gbc.insets = new Insets(2, 2, 2, 2); - gbc.anchor = GridBagConstraints.WEST; - totalArmorPanel.add(Box.createVerticalStrut(11), gbc); - gbc.gridy++; - totalArmorPanel.add(lblUnallocatedArmor, gbc); - gbc.gridx = 1; - totalArmorPanel.add(valueUnallocatedArmor, gbc); - gbc.gridx = 0; - gbc.gridy++; - totalArmorPanel.add(lblAllocatedArmor, gbc); - gbc.gridx = 1; - totalArmorPanel.add(valueAllocatedArmor, gbc); - gbc.gridx = 0; - gbc.gridy++; - totalArmorPanel.add(lblCurrentArmor, gbc); - gbc.gridx = 1; - totalArmorPanel.add(valueCurrentArmor, gbc); - gbc.gridx = 0; - gbc.gridy++; - totalArmorPanel.add(lblMaxArmor, gbc); - gbc.gridx = 1; - totalArmorPanel.add(valueMaxArmor, gbc); - gbc.gridx = 0; - gbc.gridy++; - totalArmorPanel.add(lblWastedArmor, gbc); - gbc.gridx = 1; - totalArmorPanel.add(valueWastedArmor, gbc); - gbc.gridx = 0; - gbc.gridy++; - gbc.gridwidth = 2; - totalArmorPanel.add(Box.createVerticalStrut(12), gbc); - gbc.gridy++; - gbc.anchor = GridBagConstraints.CENTER; - totalArmorPanel.add(allocateArmorButton, gbc); - - gbc = new GridBagConstraints(); - gbc.gridx = 0; - gbc.gridy = 4; - gbc.gridwidth = 5; - gbc.fill = GridBagConstraints.NONE; - gbc.anchor = GridBagConstraints.CENTER; - mainPanel.add(totalArmorPanel, gbc); - this.add(mainPanel); - - resetArmorPoints(); - } - - private void addAllListeners() { - allocateArmorButton.addActionListener(this); - for (JSpinner spinner : armorFieldList) { - spinner.addChangeListener(this); - } - } - - private void removeAllListeners() { - allocateArmorButton.removeActionListener(this); - for (JSpinner spinner : armorFieldList) { - spinner.removeChangeListener(this); - } - } - - public void refresh() { - turretPanel.setVisible(!getTank().hasNoTurret()||(getTank() instanceof VTOL)); - turret2Panel.setVisible(!getTank().hasNoDualTurret()|| ((getTank() instanceof VTOL) && !getTank().hasNoTurret())); - removeAllListeners(); - int maxArmor = armorPoints; - if (getTank().hasPatchworkArmor()) { - maxArmor = (int)Math.floor((getTank().getWeight() * 3.5) + 40); - } - for (int location = 0; location < getTank().locations(); location++) { - - if (getTank() instanceof SuperHeavyTank) { - switch (location) { - case Tank.LOC_FRONT: - frontArmorModel.setValue(Math.min(maxArmor, getTank().getArmor(location))); - frontArmorModel.setMaximum(maxArmor); - frontArmorModel.setStepSize(1); - frontArmorModel.setMinimum(0); - frontArmorMaxLabel.setText("max: " - + Integer.toString(maxArmor)); - break; - case SuperHeavyTank.LOC_FRONTLEFT: - leftArmorModel.setValue(Math.min(maxArmor, - getTank().getArmor(location))); - leftArmorModel.setMaximum(maxArmor); - leftArmorModel.setStepSize(1); - leftArmorModel.setMinimum(0); - leftArmorMaxLabel.setText("max: " - + Integer.toString(maxArmor)); - break; - case SuperHeavyTank.LOC_FRONTRIGHT: - rightArmorModel.setValue(Math.min(maxArmor, - getTank().getArmor(location))); - rightArmorModel.setMaximum(maxArmor); - rightArmorModel.setStepSize(1); - rightArmorModel.setMinimum(0); - rightArmorMaxLabel.setText("max: " - + Integer.toString(maxArmor)); - break; - case SuperHeavyTank.LOC_REARRIGHT: - rearRightArmorModel.setValue(Math.min(maxArmor, - getTank().getArmor(location))); - rearRightArmorModel.setMaximum(maxArmor); - rearRightArmorModel.setStepSize(1); - rearRightArmorModel.setMinimum(0); - rearRightArmorMaxLabel.setText("max: " - + Integer.toString(maxArmor)); - break; - case SuperHeavyTank.LOC_TURRET_2: - turret2ArmorModel.setValue(Math.min(maxArmor, - getTank().getArmor(location))); - turret2ArmorModel.setMaximum(maxArmor); - turret2ArmorModel.setStepSize(1); - turret2ArmorModel.setMinimum(0); - turret2ArmorMaxLabel.setText("max: " - + Integer.toString(maxArmor)); - break; - case SuperHeavyTank.LOC_REARLEFT: - rearLeftArmorModel.setValue(Math.min(maxArmor, - getTank().getArmor(location))); - rearLeftArmorModel.setMaximum(maxArmor); - rearLeftArmorModel.setStepSize(1); - rearLeftArmorModel.setMinimum(0); - - rearLeftArmorMaxLabel.setText("max: " - + Integer.toString(maxArmor)); - break; - case SuperHeavyTank.LOC_REAR: - rearArmorModel.setValue(Math.min(maxArmor, - getTank().getArmor(location))); - rearArmorModel.setMaximum(maxArmor); - rearArmorModel.setStepSize(1); - rearArmorModel.setMinimum(0); - rearArmorMaxLabel.setText("max: " - + Integer.toString(maxArmor)); - break; - case SuperHeavyTank.LOC_TURRET: - turretArmorModel.setValue(Math.min(maxArmor, - getTank().getArmor(location))); - turretArmorModel.setMaximum(maxArmor); - turretArmorModel.setStepSize(1); - turretArmorModel.setMinimum(0); - turretArmorMaxLabel.setText("max: " - + Integer.toString(maxArmor)); - break; - } - } else { - switch (location) { - case Tank.LOC_FRONT: - frontArmorModel.setValue(Math.min(maxArmor, getTank().getArmor(location))); - frontArmorModel.setMaximum(maxArmor); - frontArmorModel.setStepSize(1); - frontArmorModel.setMinimum(0); - frontArmorMaxLabel.setText("max: " - + Integer.toString(maxArmor)); - break; - case Tank.LOC_LEFT: - leftArmorModel.setValue(Math.min(maxArmor, - getTank().getArmor(location))); - leftArmorModel.setMaximum(maxArmor); - leftArmorModel.setStepSize(1); - leftArmorModel.setMinimum(0); - leftArmorMaxLabel.setText("max: " - + Integer.toString(maxArmor)); - break; - case Tank.LOC_RIGHT: - rightArmorModel.setValue(Math.min(maxArmor, - getTank().getArmor(location))); - rightArmorModel.setMaximum(maxArmor); - rightArmorModel.setStepSize(1); - rightArmorModel.setMinimum(0); - rightArmorMaxLabel.setText("max: " - + Integer.toString(maxArmor)); - break; - case Tank.LOC_TURRET_2: - turret2ArmorModel.setValue(Math.min(maxArmor, - getTank().getArmor(location))); - turret2ArmorModel.setMaximum(maxArmor); - turret2ArmorModel.setStepSize(1); - turret2ArmorModel.setMinimum(0); - turret2ArmorMaxLabel.setText("max: " - + Integer.toString(maxArmor)); - break; - case Tank.LOC_REAR: - rearArmorModel.setValue(Math.min(maxArmor, - getTank().getArmor(location))); - rearArmorModel.setMaximum(maxArmor); - rearArmorModel.setStepSize(1); - rearArmorModel.setMinimum(0); - rearArmorMaxLabel.setText("max: " - + Integer.toString(maxArmor)); - break; - case Tank.LOC_TURRET: - turretArmorModel.setValue(Math.min(maxArmor, - getTank().getArmor(location))); - if (getTank() instanceof VTOL){ - turretArmorModel - .setMaximum(TestTank.VTOL_MAX_ROTOR_ARMOR); - } else { - turretArmorModel.setMaximum(maxArmor); - } - turretArmorModel.setStepSize(1); - turretArmorModel.setMinimum(0); - turretArmorMaxLabel.setText("max: " - + Integer.toString(maxArmor)); - break; - } - } - } - - // unallocated armorpoints - if (getTank().hasPatchworkArmor()) { - valueUnallocatedArmor.setVisible(false); - lblUnallocatedArmor.setVisible(false); - valueAllocatedArmor.setVisible(false); - lblAllocatedArmor.setVisible(false); - valueWastedArmor.setVisible(false); - lblWastedArmor.setVisible(false); - allocateArmorButton.setVisible(false); - unallocatedPointsLabelPatchworkFront.setVisible(true); - unallocatedPointsLabelPatchworkLeft.setVisible(true); - unallocatedPointsLabelPatchworkTurret2.setVisible(true); - unallocatedPointsLabelPatchworkRearRight.setVisible(true); - unallocatedPointsLabelPatchworkRearLeft.setVisible(true); - unallocatedPointsLabelPatchworkRight.setVisible(true); - unallocatedPointsLabelPatchworkRear.setVisible(true); - unallocatedPointsLabelPatchworkTurret.setVisible(true); - unallocatedPointsFieldFront.setVisible(true); - unallocatedPointsFieldLeft.setVisible(true); - unallocatedPointsFieldTurret2.setVisible(true); - unallocatedPointsFieldRearRight.setVisible(true); - unallocatedPointsFieldRearLeft.setVisible(true); - unallocatedPointsFieldRight.setVisible(true); - unallocatedPointsFieldRear.setVisible(true); - unallocatedPointsFieldTurret.setVisible(true); - unallocatedPointsFieldFront.setText(Integer.toString(UnitUtil - .getArmorPoints(getTank(), Tank.LOC_FRONT, - getTank().getArmorWeight(Tank.LOC_FRONT)) - - getTank().getOArmor(Mech.LOC_HEAD))); - unallocatedPointsFieldLeft.setText(Integer.toString(UnitUtil - .getArmorPoints(getTank(), getTank() instanceof SuperHeavyTank?SuperHeavyTank.LOC_FRONTLEFT:Tank.LOC_LEFT, - getTank().getArmorWeight(getTank() instanceof SuperHeavyTank?SuperHeavyTank.LOC_FRONTLEFT:Tank.LOC_LEFT)) - - getTank().getOArmor(getTank() instanceof SuperHeavyTank?SuperHeavyTank.LOC_FRONTLEFT:Tank.LOC_LEFT))); - unallocatedPointsFieldTurret2.setText(Integer.toString(UnitUtil - .getArmorPoints(getTank(), getTank() instanceof SuperHeavyTank?SuperHeavyTank.LOC_TURRET_2:Tank.LOC_TURRET_2, - getTank().getArmorWeight(getTank() instanceof SuperHeavyTank?SuperHeavyTank.LOC_TURRET_2:Tank.LOC_TURRET_2)) - - getTank().getOArmor(getTank() instanceof SuperHeavyTank?SuperHeavyTank.LOC_TURRET_2:Tank.LOC_TURRET_2))); - unallocatedPointsFieldRearRight.setText(Integer.toString(UnitUtil - .getArmorPoints(getTank(), SuperHeavyTank.LOC_REARRIGHT, - getTank().getArmorWeight(SuperHeavyTank.LOC_REARRIGHT)) - - getTank().getOArmor(SuperHeavyTank.LOC_REARRIGHT))); - unallocatedPointsFieldRearLeft.setText(Integer.toString(UnitUtil - .getArmorPoints(getTank(), SuperHeavyTank.LOC_REARLEFT, - getTank().getArmorWeight(SuperHeavyTank.LOC_REARLEFT)) - - getTank().getOArmor(SuperHeavyTank.LOC_REARLEFT))); - unallocatedPointsFieldRight.setText(Integer.toString(UnitUtil - .getArmorPoints(getTank(), getTank() instanceof SuperHeavyTank?SuperHeavyTank.LOC_FRONTRIGHT:Tank.LOC_RIGHT, - getTank().getArmorWeight(getTank() instanceof SuperHeavyTank?SuperHeavyTank.LOC_FRONTRIGHT:Tank.LOC_RIGHT)) - - getTank().getOArmor(getTank() instanceof SuperHeavyTank?SuperHeavyTank.LOC_FRONTRIGHT:Tank.LOC_RIGHT))); - unallocatedPointsFieldRear.setText(Integer.toString(UnitUtil - .getArmorPoints(getTank(), getTank() instanceof SuperHeavyTank?SuperHeavyTank.LOC_REAR:Tank.LOC_REAR, - getTank().getArmorWeight(getTank() instanceof SuperHeavyTank?SuperHeavyTank.LOC_REAR:Tank.LOC_REAR)) - - getTank().getOArmor(getTank() instanceof SuperHeavyTank?SuperHeavyTank.LOC_REAR:Tank.LOC_REAR))); - unallocatedPointsFieldTurret.setText(Integer.toString(UnitUtil - .getArmorPoints(getTank(), getTank() instanceof SuperHeavyTank?SuperHeavyTank.LOC_TURRET:Tank.LOC_TURRET, - getTank().getArmorWeight(getTank() instanceof SuperHeavyTank?SuperHeavyTank.LOC_TURRET:Tank.LOC_TURRET)) - - getTank().getOArmor(getTank() instanceof SuperHeavyTank?SuperHeavyTank.LOC_TURRET:Tank.LOC_TURRET))); - } else { - valueUnallocatedArmor.setVisible(true); - lblUnallocatedArmor.setVisible(true); - valueAllocatedArmor.setVisible(true); - lblAllocatedArmor.setVisible(true); - allocateArmorButton.setVisible(true); - valueWastedArmor.setVisible(true); - lblWastedArmor.setVisible(true); - unallocatedPointsLabelPatchworkFront.setVisible(false); - unallocatedPointsLabelPatchworkLeft.setVisible(false); - unallocatedPointsLabelPatchworkTurret2.setVisible(false); - unallocatedPointsLabelPatchworkRearRight.setVisible(false); - unallocatedPointsLabelPatchworkRearLeft.setVisible(false); - unallocatedPointsLabelPatchworkRight.setVisible(false); - unallocatedPointsLabelPatchworkRear.setVisible(false); - unallocatedPointsLabelPatchworkTurret.setVisible(false); - unallocatedPointsFieldFront.setVisible(false); - unallocatedPointsFieldLeft.setVisible(false); - unallocatedPointsFieldTurret2.setVisible(false); - unallocatedPointsFieldRearRight.setVisible(false); - unallocatedPointsFieldRearLeft.setVisible(false); - unallocatedPointsFieldRight.setVisible(false); - unallocatedPointsFieldRear.setVisible(false); - unallocatedPointsFieldTurret.setVisible(false); - } - valueAllocatedArmor.setText(Integer.toString(getTank().getTotalOArmor())); - valueUnallocatedArmor.setText(Integer.toString(armorPoints - - getTank().getTotalOArmor())); - if (armorPoints != getTank().getTotalOArmor()) { - valueUnallocatedArmor.setForeground(Color.RED); - lblUnallocatedArmor.setForeground(Color.RED); - } else { - valueUnallocatedArmor.setForeground(Color.BLACK); - lblUnallocatedArmor.setForeground(Color.BLACK); - } - valueCurrentArmor.setText(Integer.toString(armorPoints)); - valueMaxArmor - .setText(Integer.toString(maxArmor)); - valueWastedArmor.setText(Integer.toString(wastedArmorPoints)); - - addAllListeners(); - } - - public void addRefreshedListener(RefreshListener l) { - refresh = l; - } - - public void allocateArmor() { - int pointsToAllocate = armorPoints; - - for (int location = 0; location < getTank().locations(); location++) { - getTank().initializeArmor(0, location); - } - - // Make sure that the VTOL rotor has the 2 armor it should have - if (getTank() instanceof VTOL) { - getTank().initializeArmor(Math.min(pointsToAllocate, 2), VTOL.LOC_ROTOR); - pointsToAllocate -= 2; - } - - int numLocations = getTank().locations(); - // Discount rotor for VTOLs - if (getTank() instanceof VTOL) { - numLocations--; - } - // Discount body, as it's not armored - numLocations--; - - // Determine the percentage of total armor each location should get - double otherPercent = 1.0 / numLocations; - double remainingPercent = 1.0 - (otherPercent * (numLocations - 2)); - // Front should be slightly more armored and rear slightly less - double frontPercent = remainingPercent * 0.6; - double rearPercent = remainingPercent * 0.4; - - // With the percentage of total for each location, assign armor - int allocatedPoints = 0; - for (int location = 1; location < getTank().locations(); location++) { - if ((getTank() instanceof VTOL) && (location == VTOL.LOC_ROTOR)) { - continue; - } - int armorToAllocate = 0; - if (location == Tank.LOC_FRONT) { - armorToAllocate = (int)(pointsToAllocate * frontPercent); - } else if (location == Tank.LOC_REAR) { - armorToAllocate = (int)(pointsToAllocate * rearPercent); - } else { - armorToAllocate = (int)(pointsToAllocate * otherPercent); - } - getTank().initializeArmor(armorToAllocate, location); - allocatedPoints += armorToAllocate; - } - - // Because of rounding, may have leftover armor: allocate it to front - int unallocated = pointsToAllocate - allocatedPoints; - int currentFrontArmor = getTank().getOArmor(Tank.LOC_FRONT); - getTank().initializeArmor(currentFrontArmor + unallocated, Tank.LOC_FRONT); - } - - public void stateChanged(ChangeEvent e) { - removeAllListeners(); - JSpinner field = (JSpinner) e.getSource(); - int location = Integer.parseInt(field.getName()); - int value = (Integer) field.getModel().getValue(); - getTank().initializeArmor(value, location); - if (getTank().hasPatchworkArmor()) { - setArmorPoints(getTank().getTotalArmor()); - } - if (refresh != null) { - addAllListeners(); - refresh.refreshStructure(); - removeAllListeners(); - refresh.refreshStatus(); - } - addAllListeners(); - } - - public void setArmorPoints(int points) { - int maxArmor = (int) Math.floor((getTank().getWeight() * 3.5) +40); - wastedArmorPoints = Math.max(points - maxArmor, 0); - armorPoints = Math.min(maxArmor, points); - } - - @Override - public void actionPerformed(ActionEvent e) { - removeAllListeners(); - if (e.getSource().equals(allocateArmorButton)) { - allocateArmor(); - } - addAllListeners(); - refresh.refreshAll(); - } - - public void resetArmorPoints() { - double armorPerTon = 16.0 * EquipmentType.getArmorPointMultiplier( - getTank().getArmorType(0), getTank().getArmorTechLevel(0)); - setArmorPoints((int) Math - .floor(getTank().getLabArmorTonnage() * armorPerTon)); - } -} \ No newline at end of file From 9bdb7f333375c75c515d7892de2a72467d7ea715 Mon Sep 17 00:00:00 2001 From: Carl Spain Date: Thu, 21 Sep 2017 10:36:09 -0500 Subject: [PATCH 09/12] Added auto-allocate button to armor allocation panel and restored old auto-allocation code for mechs. Changed auto-allocation method to recalculate % of total armor after assigning head location to get better distribution. --- .../com/ui/Mek/tabs/StructureTab.java | 254 +++++++++++++++--- .../com/ui/view/ArmorAllocationView.java | 26 +- .../com/ui/view/listeners/BuildListener.java | 1 + src/megameklab/resources/Views.properties | 1 + 4 files changed, 236 insertions(+), 46 deletions(-) diff --git a/src/megameklab/com/ui/Mek/tabs/StructureTab.java b/src/megameklab/com/ui/Mek/tabs/StructureTab.java index e57c0dc58..30b78c4c6 100644 --- a/src/megameklab/com/ui/Mek/tabs/StructureTab.java +++ b/src/megameklab/com/ui/Mek/tabs/StructureTab.java @@ -128,12 +128,12 @@ private void setUpPanels() { leftPanel.add(Box.createVerticalStrut(11)); leftPanel.add(panHeat); leftPanel.add(Box.createGlue()); - + centerPanel.add(panArmor); centerPanel.add(panMovement); centerPanel.add(panSummary); centerPanel.add(Box.createVerticalGlue()); - + rightPanel.add(panArmorAllocation); rightPanel.add(panPatchwork); rightPanel.add(Box.createVerticalGlue()); @@ -176,7 +176,7 @@ public void refresh() { addAllListeners(); } - + public JLabel createLabel(String text, Dimension maxSize) { JLabel label = new JLabel(text, SwingConstants.RIGHT); @@ -190,7 +190,7 @@ public void setFieldSize(JComponent box, Dimension maxSize) { box.setMaximumSize(maxSize); box.setMinimumSize(maxSize); } - + public ITechManager getTechManager() { return panBasicInfo; } @@ -206,7 +206,7 @@ private void resetSystemCrits() { getMech().clearCockpitCrits(); getMech().clearGyroCrits(); getMech().clearEngineCrits(); - + int[] ctEngine = getMech().getEngine().getCenterTorsoCriticalSlots(getMech().getGyroType()); int lastEngine = ctEngine[ctEngine.length - 1]; for (int slot = 0; slot <= lastEngine; slot++) { @@ -218,22 +218,22 @@ private void resetSystemCrits() { } getMech().addEngineCrits(); switch (getMech().getGyroType()) { - case Mech.GYRO_COMPACT: - getMech().addCompactGyro(); - break; - case Mech.GYRO_HEAVY_DUTY: - getMech().addHeavyDutyGyro(); - break; - case Mech.GYRO_XL: - getMech().addXLGyro(); - break; - case Mech.GYRO_NONE: - UnitUtil.compactCriticals(getMech(), Mech.LOC_CT); - break; - default: - getMech().addGyro(); + case Mech.GYRO_COMPACT: + getMech().addCompactGyro(); + break; + case Mech.GYRO_HEAVY_DUTY: + getMech().addHeavyDutyGyro(); + break; + case Mech.GYRO_XL: + getMech().addXLGyro(); + break; + case Mech.GYRO_NONE: + UnitUtil.compactCriticals(getMech(), Mech.LOC_CT); + break; + default: + getMech().addGyro(); } - + switch (getMech().getCockpitType()) { case Mech.COCKPIT_COMMAND_CONSOLE: clearCritsForCockpit(false, true); @@ -302,7 +302,7 @@ && getMech().getCritical(Mech.LOC_RT, i).getType() == CriticalSlot.TYPE_EQUIPMEN } refresh.refreshBuild(); } - + /** * Removes equipment placed in head locations that are needed for a cockpit. For most cockpit * types, this is all but the fourth slot. @@ -418,7 +418,7 @@ private void createISMounts(EquipmentType structure) { int isCount = 0; getMech().setStructureType(EquipmentType.getStructureType(structure)); getMech().setStructureTechLevel(structure.getStaticTechLevel().getCompoundTechLevel(structure.isClan())); - + isCount = structure.getCriticals(getMech()); if (isCount < 1) { return; @@ -433,7 +433,7 @@ private void createISMounts(EquipmentType structure) { } } } - + /** * Calculates required engine rating for speed and tonnage and updates engine if possible. * @return true if the new engine is legal for rating, space, and tech level @@ -469,7 +469,7 @@ private boolean recalculateEngineRating(int walkMP, double tonnage) { } return true; } - + private boolean hasCTSpace(Engine engine, int gyroType, int cockpitType) { if (getMech().isSuperHeavy()) { return true; @@ -491,7 +491,7 @@ private boolean hasCTSpace(Engine engine, int gyroType, int cockpitType) { } return crits <= 12; } - + private void createArmorMountsAndSetArmorType(int at, int aTechLevel) { getMech().setArmorTechLevel(aTechLevel); getMech().setArmorType(at); @@ -537,7 +537,7 @@ public void setAsCustomization() { public void refreshSummary() { panSummary.refresh(); } - + @Override public void chassisChanged(String chassis) { getMech().setChassis(chassis); @@ -575,7 +575,7 @@ public void techBaseChanged(boolean clan, boolean mixed) { public void techLevelChanged(SimpleTechLevel techLevel) { updateTechLevel(); } - + @Override public void updateTechLevel() { removeAllListeners(); @@ -626,7 +626,7 @@ public void tonnageChanged(double tonnage) { return; } boolean changedSuperHeavyStatus = getMech().isSuperHeavy() != tonnage > 100; - + if (changedSuperHeavyStatus) { // if we switch from being superheavy to not being superheavy, // remove crits @@ -705,7 +705,7 @@ public void typeChanged(int baseType, int motiveType, long etype) { if (mount.isPresent()) { UnitUtil.removeMounted(getMech(), mount.get()); } - + if (motiveType == QuadVee.MOTIVE_WHEEL) { ((QuadVee)getMech()).setMotiveType(QuadVee.MOTIVE_WHEEL); UnitUtil.createSpreadMounts(getMech(), EquipmentType.get("Wheels")); @@ -867,7 +867,7 @@ public void heatSinkBaseCountChanged(int count) { refresh.refreshStatus(); refresh.refreshPreview(); } - + @Override public void armorTypeChanged(int at, int aTechLevel) { UnitUtil.removeISorArmorMounts(getMech(), false); @@ -886,7 +886,7 @@ public void armorTypeChanged(int at, int aTechLevel) { refresh.refreshBuild(); refresh.refreshPreview(); } - + @Override public void armorTonnageChanged(double tonnage) { getMech().setArmorTonnage(Math.round(tonnage * 2) / 2.0); @@ -903,13 +903,13 @@ public void maximizeArmor() { panArmor.removeListener(this); panArmor.setFromEntity(getMech()); panArmor.addListener(this); - + panArmorAllocation.setFromEntity(getMech()); panSummary.refresh(); refresh.refreshStatus(); refresh.refreshPreview(); } - + @Override public void useRemainingTonnageArmor() { double currentTonnage = UnitUtil.getEntityVerifier(getMech()) @@ -918,14 +918,14 @@ public void useRemainingTonnageArmor() { double totalTonnage = getMech().getWeight(); double remainingTonnage = TestEntity.floor( totalTonnage - currentTonnage, TestEntity.Ceil.HALFTON); - + double maxArmor = Math.min(getMech().getArmorWeight() + remainingTonnage, UnitUtil.getMaximumArmorTonnage(getMech())); getMech().setArmorTonnage(maxArmor); panArmor.removeListener(this); panArmor.setFromEntity(getMech()); panArmor.addListener(this); - + panArmorAllocation.setFromEntity(getMech()); panSummary.refresh(); refresh.refreshStatus(); @@ -1013,6 +1013,190 @@ public void armorPointsChanged(int location, int front, int rear) { refresh.refreshStatus(); } + @Override + public void autoAllocateArmor() { + double pointsToAllocate = UnitUtil.getArmorPoints(getMech(), getMech().getLabArmorTonnage()); + double maxArmor = UnitUtil.getMaximumArmorPoints(getMech()); + if (pointsToAllocate > maxArmor) { + pointsToAllocate = maxArmor; + } + double percent = pointsToAllocate / maxArmor; + int headMaxArmor = 9; + if (getMech().isSuperHeavy()) { + headMaxArmor = 12; + } + // put 5 times the percentage of total possible armor into the head + int headArmor = (int) Math.min(Math.floor(percent * headMaxArmor * 5), headMaxArmor); + getMech().initializeArmor(headArmor, Mech.LOC_HEAD); + pointsToAllocate -= headArmor; + maxArmor -= headMaxArmor; + // recalculate percentage for remainder + percent = pointsToAllocate / maxArmor; + for (int location = 0; location < getMech().locations(); location++) { + double IS = (getMech().getInternal(location) * 2); + double allocate = Math.min(IS * percent, pointsToAllocate); + switch (location) { + case Mech.LOC_HEAD: + break; + case Mech.LOC_CT: + case Mech.LOC_LT: + case Mech.LOC_RT: + double rear = Math.floor(allocate * .25); + double front = Math.ceil(allocate * .75); + pointsToAllocate -= (int) rear; + pointsToAllocate -= (int) front; + getMech().initializeArmor((int) front, location); + getMech().initializeRearArmor((int) rear, location); + break; + default: + getMech().initializeArmor((int) allocate, location); + pointsToAllocate -= (int) allocate; + break; + } + } + allocateLeftoverPoints(pointsToAllocate); + + panArmorAllocation.setFromEntity(getMech()); + refresh.refreshPreview(); + refresh.refreshSummary(); + refresh.refreshStatus(); + } + + /** + * allocate any leftover points one-by-one + * + * @param points + * the amount of points left over + */ + private void allocateLeftoverPoints(double points) { + int headMaxArmor = 9; + if (getMech().isSuperHeavy()) { + headMaxArmor = 12; + } + while (points >= 1) { + // if two or more are left, add armor to symmetrical locations, + // to torso, legs, arms, in that order + if (points >= 2) { + if (((getMech().getOArmor(Mech.LOC_LT) + getMech().getOArmor(Mech.LOC_LT, + true)) < (getMech().getOInternal(Mech.LOC_LT) * 2)) + && ((getMech().getOArmor(Mech.LOC_RT) + getMech().getOArmor( + Mech.LOC_RT, true)) < (getMech() + .getOInternal(Mech.LOC_RT) * 2))) { + getMech().initializeArmor(getMech().getOArmor(Mech.LOC_LT) + 1, + Mech.LOC_LT); + getMech().initializeArmor(getMech().getOArmor(Mech.LOC_RT) + 1, + Mech.LOC_RT); + points -= 2; + } else if ((getMech().getOArmor(Mech.LOC_LLEG) < (getMech() + .getOInternal(Mech.LOC_LLEG) * 2)) + && (getMech().getOArmor(Mech.LOC_RLEG) < (getMech() + .getOInternal(Mech.LOC_RLEG) * 2))) { + getMech().initializeArmor(getMech().getOArmor(Mech.LOC_LLEG) + 1, + Mech.LOC_LLEG); + getMech().initializeArmor(getMech().getOArmor(Mech.LOC_RLEG) + 1, + Mech.LOC_RLEG); + points -= 2; + } else if ((getMech().getOArmor(Mech.LOC_LARM) < (getMech() + .getOInternal(Mech.LOC_LARM) * 2)) + && (getMech().getOArmor(Mech.LOC_RARM) < (getMech() + .getOInternal(Mech.LOC_RARM) * 2))) { + getMech().initializeArmor(getMech().getOArmor(Mech.LOC_LARM) + 1, + Mech.LOC_LARM); + getMech().initializeArmor(getMech().getOArmor(Mech.LOC_RARM) + 1, + Mech.LOC_RARM); + points -= 2; + } + // otherwise, first add to the head, and then even out uneven + // allocation + } else if (getMech().getOArmor(Mech.LOC_HEAD) < headMaxArmor) { + getMech().initializeArmor(getMech().getOArmor(Mech.LOC_HEAD) + 1, + Mech.LOC_HEAD); + points--; + } else if (getMech().getOArmor(Mech.LOC_LT) < getMech() + .getOArmor(Mech.LOC_RT)) { + getMech().initializeArmor(getMech().getOArmor(Mech.LOC_LT) + 1, + Mech.LOC_LT); + points--; + } else if (getMech().getOArmor(Mech.LOC_RT) < getMech() + .getOArmor(Mech.LOC_LT)) { + getMech().initializeArmor(getMech().getOArmor(Mech.LOC_RT) + 1, + Mech.LOC_RT); + points--; + } else if (getMech().getOArmor(Mech.LOC_RARM) < getMech() + .getOArmor(Mech.LOC_LARM)) { + getMech().initializeArmor(getMech().getOArmor(Mech.LOC_RARM) + 1, + Mech.LOC_RARM); + points--; + } else if (getMech().getOArmor(Mech.LOC_LARM) < getMech() + .getOArmor(Mech.LOC_RARM)) { + getMech().initializeArmor(getMech().getOArmor(Mech.LOC_LARM) + 1, + Mech.LOC_LARM); + points--; + } else if (getMech().getOArmor(Mech.LOC_RLEG) < getMech() + .getArmor(Mech.LOC_LLEG)) { + getMech().initializeArmor(getMech().getOArmor(Mech.LOC_RLEG) + 1, + Mech.LOC_RLEG); + points--; + } else if (getMech().getOArmor(Mech.LOC_LLEG) < getMech() + .getOArmor(Mech.LOC_RLEG)) { + getMech().initializeArmor(getMech().getOArmor(Mech.LOC_LLEG) + 1, + Mech.LOC_LLEG); + points--; + // if nothing is uneven, add to the CT + } else if (((getMech().getOArmor(Mech.LOC_CT) + getMech().getOArmor( + Mech.LOC_CT, true)) < (getMech().getOInternal(Mech.LOC_CT) * 2))) { + getMech().initializeArmor(getMech().getOArmor(Mech.LOC_CT) + 1, + Mech.LOC_CT); + points--; + } + // if only one is left, and head and CT have max, remove one from CT + // so symmetric locations can get extra, unless they are already at + // max + if (points == 1) { + if ((getMech().getOArmor(Mech.LOC_HEAD) == headMaxArmor) + && ((getMech().getOArmor(Mech.LOC_CT) + getMech().getOArmor( + Mech.LOC_CT, true)) == (getMech() + .getOInternal(Mech.LOC_CT) * 2))) { + getMech().initializeArmor(getMech().getOArmor(Mech.LOC_CT) - 1, + Mech.LOC_CT); + points++; + } + } + // if all locations have max, return + boolean toReturn = true; + for (int location = 0; location < getMech().locations(); location++) { + double is = (getMech().getInternal(location) * 2); + switch (location) { + case Mech.LOC_HEAD: + int headPoints = 3; + if (getMech().isSuperHeavy()) { + headPoints = 4; + } + if ((is + headPoints) > getMech().getOArmor(location)) { + toReturn = false; + } + break; + case Mech.LOC_CT: + case Mech.LOC_LT: + case Mech.LOC_RT: + if (is > (getMech().getOArmor(location) + getMech().getOArmor( + location, true))) { + toReturn = false; + } + break; + default: + if (is > getMech().getOArmor(location)) { + toReturn = false; + } + break; + } + } + if (toReturn) { + return; + } + } + } + @Override public void patchworkChanged(int location, EquipmentType armor) { UnitUtil.resetArmor(getMech(), location); diff --git a/src/megameklab/com/ui/view/ArmorAllocationView.java b/src/megameklab/com/ui/view/ArmorAllocationView.java index 8660d1514..a780436a7 100644 --- a/src/megameklab/com/ui/view/ArmorAllocationView.java +++ b/src/megameklab/com/ui/view/ArmorAllocationView.java @@ -23,6 +23,7 @@ import javax.swing.Box; import javax.swing.BoxLayout; +import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; @@ -103,6 +104,7 @@ public void removeListener(BuildListener l) { private final JTextField txtTotal = new JTextField(); private final JTextField txtMaxPossible = new JTextField(); private final JTextField txtWasted = new JTextField(); + private final JButton btnAutoAllocate = new JButton(); private long entitytype; private int armorPoints = 0; @@ -166,10 +168,19 @@ private void initUI() { gbc.gridy++; add(new JLabel(resourceMap.getString("ArmorAllocationView.txtWasted.text"), SwingConstants.RIGHT), gbc); //$NON-NLS-1$ gbc.gridx = 1; - gbc.gridwidth = GridBagConstraints.REMAINDER; txtWasted.setEditable(false); setFieldSize(txtWasted, editorSize); add(txtWasted, gbc); + + btnAutoAllocate.setText(resourceMap.getString("ArmorAllocationView.btnAutoAllocate.text")); //$NON-NLS-1$ + gbc.gridx = 0; + gbc.gridy++; + gbc.gridwidth = 2; + gbc.anchor = GridBagConstraints.CENTER; + add(Box.createVerticalStrut(18), gbc); + gbc.gridy++; + add(btnAutoAllocate, gbc); + btnAutoAllocate.addActionListener(e -> listeners.forEach(BuildListener::autoAllocateArmor)); } public void setFromEntity(Entity en) { @@ -180,8 +191,10 @@ public void setFromEntity(Entity en) { if (showPatchwork) { armorPoints = currentPoints; raw = currentPoints; + btnAutoAllocate.setEnabled(false); } else { armorPoints = Math.min(raw, maxArmorPoints); + btnAutoAllocate.setEnabled(true); } wastedPoints = Math.max(0, raw - armorPoints); for (ArmorLocationView locView : locationViews) { @@ -190,16 +203,7 @@ public void setFromEntity(Entity en) { locView.setVisible(true); locView.updateLocation(en.getLocationAbbr(location), en.hasRearArmor(location)); - // If we've already hit the maximum allocated to armor, set the current value as maximum. - if (showPatchwork || (currentPoints < armorPoints)) { - locView.setMaxPoints(UnitUtil.getMaxArmor(en, location)); - } else { - int max = en.getArmor(location, false); - if (en.hasRearArmor(location)) { - max += en.getArmor(location, true); - } - locView.setMaxPoints(max); - } + locView.setMaxPoints(UnitUtil.getMaxArmor(en, location)); locView.setPoints(en.getArmor(location)); if (en.hasRearArmor(location)) { locView.setPointsRear(en.getArmor(location, true)); diff --git a/src/megameklab/com/ui/view/listeners/BuildListener.java b/src/megameklab/com/ui/view/listeners/BuildListener.java index 09dc925bd..0500137f4 100644 --- a/src/megameklab/com/ui/view/listeners/BuildListener.java +++ b/src/megameklab/com/ui/view/listeners/BuildListener.java @@ -61,5 +61,6 @@ public interface BuildListener { // For units that allocate armor to location default void armorPointsChanged(int location, int front, int rear) {}; default void patchworkChanged(int location, EquipmentType armor) {}; + default void autoAllocateArmor() {}; } diff --git a/src/megameklab/resources/Views.properties b/src/megameklab/resources/Views.properties index 04b12b911..d167a416c 100644 --- a/src/megameklab/resources/Views.properties +++ b/src/megameklab/resources/Views.properties @@ -163,6 +163,7 @@ ArmorAllocationView.txtMaxPossible.text=Maximum Possible Armor Points: ArmorAllocationView.txtWasted.text=Wasted Armor Points: ArmorAllocationView.panPatwork.title=Patchwork ArmorAllocationView.locationTooltip.format=Points per ton: %.2f
Current tonnage: %.1f +ArmorAllocationView.btnAutoAllocate.text=Auto-Allocate Armor MovementView.lblBase.text=Base MovementView.lblFinal.text=Final From 99f964df86658ac013b62e02899c755c8f941abd Mon Sep 17 00:00:00 2001 From: Carl Spain Date: Thu, 21 Sep 2017 11:02:16 -0500 Subject: [PATCH 10/12] Armor point auto-allocation for fighters. --- .../com/ui/Aero/tabs/StructureTab.java | 44 ++++++++++++++++--- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/src/megameklab/com/ui/Aero/tabs/StructureTab.java b/src/megameklab/com/ui/Aero/tabs/StructureTab.java index 8bb9829eb..75dc95931 100644 --- a/src/megameklab/com/ui/Aero/tabs/StructureTab.java +++ b/src/megameklab/com/ui/Aero/tabs/StructureTab.java @@ -30,6 +30,7 @@ import javax.swing.JPanel; import javax.swing.SwingConstants; +import megamek.common.Aero; import megamek.common.CriticalSlot; import megamek.common.Engine; import megamek.common.Entity; @@ -375,11 +376,6 @@ public void heatSinksChanged(int index, int count) { refresh.refreshPreview(); } - @Override - public void heatSinksChanged(EquipmentType hsType, int count) { - // Not used by aerospace units - } - @Override public void heatSinkBaseCountChanged(int count) { getAero().getEngine().setBaseChassisHeatSinks(Math.max(0, count)); @@ -571,6 +567,44 @@ public void armorPointsChanged(int location, int front, int rear) { refresh.refreshStatus(); } + @Override + public void autoAllocateArmor() { + for (int loc = 0; loc < getAero().locations(); loc++) { + getAero().initializeArmor(0, loc); + } + + // divide armor among positions, with more toward the front + int points = UnitUtil.getArmorPoints(getAero(), getAero().getLabArmorTonnage()); + int nose = (int)Math.floor(points * 0.3); + int wing = (int)Math.floor(points * 0.25); + int aft = (int)Math.floor(points * 0.2); + int remainder = points - nose - wing - wing - aft; + + // spread remainder among nose and wings + switch(remainder % 4) { + case 1: + nose++; + break; + case 3: + nose++; + wing++; + break; + case 2: + wing++; + break; + } + getAero().initializeArmor(nose, Aero.LOC_NOSE); + getAero().initializeArmor(wing, Aero.LOC_LWING); + getAero().initializeArmor(wing, Aero.LOC_RWING); + getAero().initializeArmor(aft, Aero.LOC_AFT); + + panArmorAllocation.setFromEntity(getAero()); + refresh.refreshPreview(); + refresh.refreshSummary(); + refresh.refreshStatus(); + + } + @Override public void patchworkChanged(int location, EquipmentType armor) { UnitUtil.resetArmor(getAero(), location); From 57d71b1764709f5617a37e392d4c363bf116276e Mon Sep 17 00:00:00 2001 From: Carl Spain Date: Thu, 21 Sep 2017 11:15:16 -0500 Subject: [PATCH 11/12] Armor point auto-allocation for vehicles. --- .../com/ui/Vehicle/tabs/StructureTab.java | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/src/megameklab/com/ui/Vehicle/tabs/StructureTab.java b/src/megameklab/com/ui/Vehicle/tabs/StructureTab.java index f3129d75e..dcce200d7 100644 --- a/src/megameklab/com/ui/Vehicle/tabs/StructureTab.java +++ b/src/megameklab/com/ui/Vehicle/tabs/StructureTab.java @@ -35,8 +35,10 @@ import megamek.common.MiscType; import megamek.common.Mounted; import megamek.common.SimpleTechLevel; +import megamek.common.SuperHeavyTank; import megamek.common.Tank; import megamek.common.TroopSpace; +import megamek.common.VTOL; import megamek.common.verifier.TestEntity; import megameklab.com.ui.EntitySource; import megameklab.com.ui.Vehicle.views.SummaryView; @@ -510,6 +512,7 @@ public void motiveChanged(EntityMovementMode motive) { panMovement.removeListener(this); panMovement.setFromEntity(getTank()); panMovement.addListener(this); + panArmor.setFromEntity(getTank()); panArmorAllocation.setFromEntity(getTank()); panPatchwork.setFromEntity(getTank()); panSummary.refresh(); @@ -610,6 +613,65 @@ public void armorPointsChanged(int location, int front, int rear) { refresh.refreshStatus(); } + @Override + public void autoAllocateArmor() { + int pointsToAllocate = UnitUtil.getArmorPoints(getTank(), getTank().getLabArmorTonnage()); + + for (int location = 0; location < getTank().locations(); location++) { + getTank().initializeArmor(0, location); + } + + // Discount body, as it's not armored + int numLocations = getTank().locations() - 1; + + // Make sure that the VTOL rotor has the 2 armor it should have + if (getTank().hasETypeFlag(Entity.ETYPE_VTOL)) { + getTank().initializeArmor(Math.min(pointsToAllocate, 2), VTOL.LOC_ROTOR); + pointsToAllocate -= 2; + numLocations--; + } + + // Determine the percentage of total armor each location should get + double otherPercent = 1.0 / numLocations; + double remainingPercent = 1.0 - (otherPercent * (numLocations - 2)); + // Front should be slightly more armored and rear slightly less + double frontPercent = remainingPercent * 0.6; + double rearPercent = remainingPercent * 0.4; + + // With the percentage of total for each location, assign armor + int allocatedPoints = 0; + int rear = Tank.LOC_REAR; + if (getTank().hasETypeFlag(Entity.ETYPE_SUPER_HEAVY_TANK)) { + rear = SuperHeavyTank.LOC_REAR; + } + for (int location = 1; location < getTank().locations(); location++) { + if ((getTank().hasETypeFlag(Entity.ETYPE_VTOL)) && (location == VTOL.LOC_ROTOR)) { + continue; + } + int armorToAllocate = 0; + if (location == Tank.LOC_FRONT) { + armorToAllocate = (int)(pointsToAllocate * frontPercent); + } else if (location == rear) { + armorToAllocate = (int)(pointsToAllocate * rearPercent); + } else { + armorToAllocate = (int)(pointsToAllocate * otherPercent); + } + getTank().initializeArmor(armorToAllocate, location); + allocatedPoints += armorToAllocate; + } + + // Because of rounding, may have leftover armor: allocate it to front + int unallocated = pointsToAllocate - allocatedPoints; + int currentFrontArmor = getTank().getOArmor(Tank.LOC_FRONT); + getTank().initializeArmor(currentFrontArmor + unallocated, Tank.LOC_FRONT); + + + panArmorAllocation.setFromEntity(getTank()); + refresh.refreshPreview(); + refresh.refreshSummary(); + refresh.refreshStatus(); + } + @Override public void patchworkChanged(int location, EquipmentType armor) { UnitUtil.resetArmor(getAero(), location); From d04cdf02a1ac2a23478d7e6c4c7f2ccce2d8d0aa Mon Sep 17 00:00:00 2001 From: Carl Spain Date: Mon, 2 Oct 2017 12:50:13 -0500 Subject: [PATCH 12/12] Brought patchwork armor weight calculations in line with TacOps errata. --- src/megameklab/com/ui/view/ArmorAllocationView.java | 7 ++++--- src/megameklab/resources/Views.properties | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/megameklab/com/ui/view/ArmorAllocationView.java b/src/megameklab/com/ui/view/ArmorAllocationView.java index a780436a7..ed1f48b6a 100644 --- a/src/megameklab/com/ui/view/ArmorAllocationView.java +++ b/src/megameklab/com/ui/view/ArmorAllocationView.java @@ -217,7 +217,7 @@ public void setFromEntity(Entity en) { points += en.getArmor(location, true); } locView.setToolTipText(String.format(tooltipFormat, pointsPerTon, - Math.ceil(points / pointsPerTon * 2.0) * 0.5)); + points / pointsPerTon)); } } else { locView.setVisible(false); @@ -257,6 +257,7 @@ private void updateLayout() { gbc.anchor = GridBagConstraints.CENTER; gbc.fill = GridBagConstraints.NONE; gbc.gridwidth = GridBagConstraints.REMAINDER; + locationViews.clear(); for (int row = 0; row < layout.length; row++) { JPanel panRow = new JPanel(); panRow.setLayout(new BoxLayout(panRow, BoxLayout.X_AXIS)); @@ -298,10 +299,10 @@ public double getTotalArmorWeight(Entity en) { final int loc = locView.getLocationIndex(); if (loc < en.locations()) { double pointsPerTon = UnitUtil.getArmorPointsPerTon(en, en.getArmorType(loc), en.getArmorTechLevel(loc)); - weight += Math.ceil((locView.getPoints() + locView.getPointsRear()) / pointsPerTon * 2.0) * 0.5; + weight += (locView.getPoints() + locView.getPointsRear()) / pointsPerTon; } } - return weight; + return Math.ceil(weight * 2.0) * 0.5; } public void showPatchwork(boolean show) { diff --git a/src/megameklab/resources/Views.properties b/src/megameklab/resources/Views.properties index d167a416c..ab196482d 100644 --- a/src/megameklab/resources/Views.properties +++ b/src/megameklab/resources/Views.properties @@ -162,7 +162,7 @@ ArmorAllocationView.txtTotal.text=Total Armor Points: ArmorAllocationView.txtMaxPossible.text=Maximum Possible Armor Points: ArmorAllocationView.txtWasted.text=Wasted Armor Points: ArmorAllocationView.panPatwork.title=Patchwork -ArmorAllocationView.locationTooltip.format=Points per ton: %.2f
Current tonnage: %.1f +ArmorAllocationView.locationTooltip.format=Points per ton: %.2f
Current tonnage: %.3f ArmorAllocationView.btnAutoAllocate.text=Auto-Allocate Armor MovementView.lblBase.text=Base