package mekhq.gui.dialog; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Container; import java.awt.Frame; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Image; import java.awt.Insets; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.swing.BorderFactory; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import megamek.common.util.StringUtil; import mekhq.MekHQ; import mekhq.Utilities; import mekhq.campaign.Campaign; import mekhq.campaign.event.PartChangedEvent; import mekhq.campaign.event.UnitChangedEvent; import mekhq.campaign.mission.AtBContract; import mekhq.campaign.mission.Mission; import mekhq.campaign.parts.MissingPart; import mekhq.campaign.parts.Part; import mekhq.campaign.parts.equipment.AmmoBin; import mekhq.campaign.unit.Unit; import mekhq.campaign.work.IAcquisitionWork; import mekhq.gui.CampaignGUI; import mekhq.gui.GuiTabType; import mekhq.gui.RepairTab; import mekhq.service.PartsAcquisitionService; import mekhq.service.PartsAcquisitionService.PartCountInfo; /** * @author Kipsta * */ public class AcquisitionsDialog extends JDialog { private static final long serialVersionUID = -1942823778220741544L; private CampaignGUI campaignGUI; private Map<String, AcquisitionPanel> partPanelMap = new HashMap<String, AcquisitionPanel>(); private JPanel pnlSummary; private JLabel lblSummary; private JButton btnSummary; int numBonusParts = 0; public AcquisitionsDialog(Frame _parent, boolean _modal, CampaignGUI _campaignGUI) { super(_parent, _modal); this.campaignGUI = _campaignGUI; calculateBonusParts(); initComponents(); setLocationRelativeTo(_parent); } private void initComponents() { setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); setTitle("Parts Acquisition"); final Container content = getContentPane(); content.setLayout(new BorderLayout()); JPanel pnlMain = new JPanel(); pnlMain.setLayout(new GridBagLayout()); GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.fill = GridBagConstraints.BOTH; gridBagConstraints.anchor = GridBagConstraints.NORTHWEST; gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; gridBagConstraints.weightx = 1.0; gridBagConstraints.weighty = 1.0; gridBagConstraints.insets = new Insets(5, 5, 5, 5); pnlMain.add(createSummaryPanel(), gridBagConstraints); int idx = 1; for (String key : PartsAcquisitionService.getAcquisitionMap().keySet()) { gridBagConstraints.gridy++; List<IAcquisitionWork> awList = PartsAcquisitionService.getAcquisitionMap().get(key); AcquisitionPanel pnl = new AcquisitionPanel(awList, idx++); partPanelMap.put(key, pnl); pnlMain.add(pnl, gridBagConstraints); } pnlSummary.firePropertyChange("counts", -1, 0); JScrollPane scrollMain = new JScrollPane(pnlMain); scrollMain.setPreferredSize(new java.awt.Dimension(700, 500)); content.add(scrollMain, BorderLayout.CENTER); pack(); } private JPanel createSummaryPanel() { pnlSummary = new JPanel(); pnlSummary.setLayout(new GridBagLayout()); pnlSummary.setBorder(BorderFactory.createTitledBorder("Acquisition Summary")); pnlSummary.addPropertyChangeListener("counts", new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { PartsAcquisitionService.buildPartsList(campaignGUI.getCampaign()); lblSummary.setText(generateSummaryText()); btnSummary.firePropertyChange("missingCount", -1, PartsAcquisitionService.getMissingCount()); if (campaignGUI.getTab(GuiTabType.REPAIR) != null) { ((RepairTab) campaignGUI.getTab(GuiTabType.REPAIR)).refreshPartsAcquisitionService(false); } } }); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.weighty = 0.0; gbc.weightx = 1.0; gbc.fill = GridBagConstraints.NONE; gbc.anchor = GridBagConstraints.NORTHWEST; gbc.insets = new Insets(0, 0, 10, 0); lblSummary = new JLabel(); lblSummary.setText(generateSummaryText()); pnlSummary.add(lblSummary, gbc); gbc.anchor = GridBagConstraints.NORTHEAST; gbc.gridx++; btnSummary = new JButton(); btnSummary.setText("Order All"); // NOI18N btnSummary.setToolTipText("Order all missing parts"); btnSummary.setName("btnOrderEverything"); // NOI18N btnSummary.addActionListener(ev -> { for (AcquisitionPanel pnl : partPanelMap.values()) { pnl.orderAllMissing(); } }); btnSummary.addPropertyChangeListener("missingCount", new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { boolean visible = false; if ((PartsAcquisitionService.getMissingCount() > 0) && (PartsAcquisitionService .getMissingCount() > PartsAcquisitionService.getUnavailableCount())) { visible = true; } if (!visible) { btnSummary.setVisible(false); } } }); pnlSummary.add(btnSummary, gbc); if ((PartsAcquisitionService.getMissingCount() == 0) || (PartsAcquisitionService.getMissingCount() == PartsAcquisitionService.getUnavailableCount())) { btnSummary.setVisible(false); } return pnlSummary; } private String generateSummaryText() { StringBuilder sbText = new StringBuilder(); sbText.append("<html><font size='3' color='black'>"); sbText.append("Required: "); sbText.append(PartsAcquisitionService.getRequiredCount()); if (PartsAcquisitionService.getMissingCount() > 0) { sbText.append(", "); sbText.append("<font color='red'>"); sbText.append("missing: "); sbText.append(PartsAcquisitionService.getMissingCount()); if (PartsAcquisitionService.getUnavailableCount() > 0) { sbText.append(", unavailable: "); sbText.append(PartsAcquisitionService.getUnavailableCount()); } sbText.append("</font>"); } sbText.append("<br/>"); String inventoryInfo = "Inventory: " + PartsAcquisitionService.getInTransitCount() + " in transit, " + PartsAcquisitionService.getOnOrderCount() + " on order"; if (PartsAcquisitionService.getOmniPodCount() > 0) { inventoryInfo += ", " + PartsAcquisitionService.getOmniPodCount() + " OmniPod"; } sbText.append(inventoryInfo); sbText.append("<br/>"); if (PartsAcquisitionService.getMissingTotalPrice() > 0) { String price = "Missing item price: " + Utilities.getCurrencyString(PartsAcquisitionService.getMissingTotalPrice()); sbText.append(price); sbText.append("<br/>"); } sbText.append("</font></html>"); return sbText.toString(); } private void calculateBonusParts() { Campaign campaign = campaignGUI.getCampaign(); List<Unit> unitList = campaign.getServiceableUnits(); Unit unit = null; if ((null != unitList) && !unitList.isEmpty()) { unit = unitList.get(0); } if (campaign.getCampaignOptions().getUseAtB() && (null != unit)) { numBonusParts = 0; AtBContract contract = campaign.getAttachedAtBContract(unit); if (null == contract) { numBonusParts = campaign.totalBonusParts(); } else { numBonusParts = contract.getNumBonusParts(); } } if (null != partPanelMap) { for (AcquisitionPanel pnl : partPanelMap.values()) { pnl.refresh(); } } } public class AcquisitionPanel extends JPanel { private static final long serialVersionUID = -205430742799527142L; private List<IAcquisitionWork> awList; private int idx; private IAcquisitionWork targetWork; private Part part; private PartCountInfo partCountInfo = new PartCountInfo(); private JButton btnOrderAll = new JButton(); private JButton btnUseBonus = new JButton(); private JButton btnDepod = new JButton(); private JLabel lblText = new JLabel(); public AcquisitionPanel(List<IAcquisitionWork> awList, int idx) { this.awList = awList; this.idx = idx; setLayout(new GridBagLayout()); initComponents(); } public void orderAllMissing() { if (null == partCountInfo) { return; } if ((partCountInfo.getMissingCount() > 0) && partCountInfo.isCanBeAcquired()) { campaignGUI.getCampaign().getShoppingList().addShoppingItem(targetWork, partCountInfo.getMissingCount(), campaignGUI.getCampaign()); refresh(); } } private void useBonusPart() { if (targetWork instanceof AmmoBin) { targetWork = ((AmmoBin) targetWork).getAcquisitionWork(); } String report = targetWork.find(0); if (report.endsWith("0 days.")) { AtBContract contract = campaignGUI.getCampaign().getAttachedAtBContract(targetWork.getUnit()); if (null == contract) { for (Mission m : campaignGUI.getCampaign().getMissions()) { if (m.isActive() && m instanceof AtBContract && ((AtBContract) m).getNumBonusParts() > 0) { contract = (AtBContract) m; break; } } } if (null == contract) { MekHQ.logError("AtB: used bonus part but no contract has bonus parts available."); } else { contract.useBonusPart(); } } refresh(); calculateBonusParts(); } private void refresh() { pnlSummary.firePropertyChange("counts", -1, 0); partCountInfo = PartsAcquisitionService.getPartCountInfoMap().get(targetWork.getAcquisitionDisplayName()); if (null == partCountInfo) { ((AcquisitionPanel) this).setVisible(false); } else { lblText.setText(generateText()); if (partCountInfo.getMissingCount() == 0) { btnOrderAll.setVisible(false); } else { if (partCountInfo.getMissingCount() == 0) { btnOrderAll.setVisible(false); } else { btnOrderAll.setText(String.format("Order All (%s)", partCountInfo.getMissingCount())); btnOrderAll.setVisible(true); } } if (partCountInfo.getOmniPodCount() == 0) { btnDepod.setVisible(false); } else { btnDepod.setVisible(true); } if (numBonusParts == 0) { btnUseBonus.setVisible(false); } else { btnUseBonus.setText(String.format("Use Bonus Part (%s)", numBonusParts)); btnUseBonus.setVisible(true); } } } private String generateText() { StringBuilder sbText = new StringBuilder(); sbText.append("<html><font size='3' color='black'>"); sbText.append("<b>"); sbText.append(targetWork.getAcquisitionDisplayName()); sbText.append("</b><br/>"); sbText.append("Required: "); sbText.append(awList.size()); if (null != partCountInfo) { if (partCountInfo.getMissingCount() > 0) { sbText.append(", "); sbText.append("<font color='red'>"); sbText.append("missing: "); sbText.append(partCountInfo.getMissingCount()); sbText.append("</font>"); } sbText.append("<br/>"); String countModifier = partCountInfo.getCountModifier(); if (!StringUtil.isNullOrEmpty(countModifier)) { countModifier = " " + countModifier; } String inventoryInfo = "Inventory: " + partCountInfo.getInTransitCount() + countModifier + " in transit, " + partCountInfo.getOnOrderCount() + countModifier + " on order"; if (partCountInfo.getOmniPodCount() > 0) { inventoryInfo += ", " + partCountInfo.getOmniPodCount() + countModifier + " OmniPod"; } sbText.append(inventoryInfo); sbText.append("<br/>"); String price = "Item Price: " + Utilities.getCurrencyString(partCountInfo.getStickerPrice()); sbText.append(price); sbText.append("<br/>"); if (partCountInfo.getMissingCount() > 1) { price = "Missing item price: " + Utilities .getCurrencyString(partCountInfo.getStickerPrice() * partCountInfo.getMissingCount()); sbText.append(price); sbText.append("<br/>"); } if (!partCountInfo.isCanBeAcquired()) { sbText.append("<br/><br/><font color='red' size='4'>"); sbText.append(partCountInfo.getFailedMessage()); sbText.append("</font>"); } } sbText.append("</font></html>"); return sbText.toString(); } private void initComponents() { targetWork = awList.get(0); part = targetWork.getAcquisitionPart(); partCountInfo = PartsAcquisitionService.getPartCountInfoMap().get(targetWork.getAcquisitionDisplayName()); // Generate text GridBagConstraints gbcMain = new GridBagConstraints(); gbcMain.gridx = 0; gbcMain.gridy = 0; gbcMain.weighty = 0.0; gbcMain.weightx = 0.0; gbcMain.fill = GridBagConstraints.HORIZONTAL; gbcMain.anchor = GridBagConstraints.NORTH; Insets insetsOriginal = gbcMain.insets; // Set image String[] imgData = Part.findPartImage(part); String imgPath = imgData[0] + imgData[1] + ".png"; Image imgTool = getToolkit().getImage(imgPath); JLabel lblIcon = new JLabel(); lblIcon.setIcon(new ImageIcon(imgTool)); add(lblIcon, gbcMain); gbcMain.anchor = GridBagConstraints.NORTHWEST; gbcMain.gridx = 1; gbcMain.weightx = 1.0; gbcMain.insets = new Insets(0, 10, 0, 0); lblText.setText(generateText()); add(lblText, gbcMain); gbcMain.gridx = 2; add(createActionButtons(), gbcMain); gbcMain.gridy++; gbcMain.gridx = 0; gbcMain.gridwidth = 3; gbcMain.insets = insetsOriginal; Map<Unit, Integer> unitMap = new HashMap<Unit, Integer>(); for (IAcquisitionWork awUnit : awList) { if (!unitMap.containsKey(awUnit.getUnit())) { unitMap.put(awUnit.getUnit(), 1); } else { int count = unitMap.get(awUnit.getUnit()) + 1; unitMap.put(awUnit.getUnit(), count); } } JPanel pnlUnits = new JPanel(); pnlUnits.setLayout(new GridBagLayout()); pnlUnits.setBorder(BorderFactory.createTitledBorder("Units requiring this part (" + unitMap.size() + ")")); GridBagConstraints cUnits = new GridBagConstraints(); cUnits.gridx = 0; cUnits.gridy = 0; cUnits.weighty = 0.0; cUnits.weightx = 1.0; cUnits.fill = GridBagConstraints.HORIZONTAL; cUnits.anchor = GridBagConstraints.NORTHWEST; for (Unit unit : unitMap.keySet()) { int count = unitMap.get(unit); JLabel lblUnit = new JLabel(); lblUnit.setText(unit.getName() + (count > 1 ? " (" + count + " needed)" : "")); pnlUnits.add(lblUnit, cUnits); cUnits.gridy++; } gbcMain.insets = new Insets(10, 0, 10, 0); add(pnlUnits, gbcMain); gbcMain.gridy++; gbcMain.insets = insetsOriginal; if (idx != PartsAcquisitionService.getAcquisitionMap().size()) { this.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.BLACK)); } } private JPanel createActionButtons() { JPanel actionButtons = new JPanel(new GridBagLayout()); GridBagConstraints gbcActions = new java.awt.GridBagConstraints(); gbcActions.gridx = 0; gbcActions.gridy = 0; gbcActions.weightx = 0.5; gbcActions.insets = new Insets(10, 0, 5, 0); gbcActions.fill = java.awt.GridBagConstraints.NONE; gbcActions.anchor = GridBagConstraints.NORTHEAST; btnUseBonus = new JButton(); btnUseBonus.setText(String.format("Use Bonus Part (%s)", numBonusParts)); // NOI18N btnUseBonus.setToolTipText("Use a bonus part to acquire this item"); btnUseBonus.setName("btnUseBonus"); // NOI18N btnUseBonus.addActionListener(ev -> { useBonusPart(); }); if (numBonusParts == 0) { btnUseBonus.setVisible(false); } actionButtons.add(btnUseBonus, gbcActions); gbcActions.gridy++; if (partCountInfo.isCanBeAcquired()) { JButton btnOrderOne = new JButton(); btnOrderOne.setText("Order One"); // NOI18N btnOrderOne.setToolTipText("Order one item"); btnOrderOne.setName("btnOrderOne"); // NOI18N btnOrderOne.addActionListener(ev -> { campaignGUI.getCampaign().getShoppingList().addShoppingItem(targetWork, 1, campaignGUI.getCampaign()); refresh(); }); actionButtons.add(btnOrderOne, gbcActions); gbcActions.gridy++; btnOrderAll.setText("Order All (" + partCountInfo.getMissingCount() + ")"); // NOI18N btnOrderAll.setToolTipText("Order all missing"); btnOrderAll.setName("btnOrderAll"); // NOI18N btnOrderAll.addActionListener(ev -> { orderAllMissing(); }); actionButtons.add(btnOrderAll, gbcActions); gbcActions.gridy++; if (partCountInfo.getMissingCount() <= 1) { btnOrderAll.setVisible(false); } } if (partCountInfo.getOmniPodCount() > 0) { btnDepod.setText("Remove One From Pod"); // NOI18N btnDepod.setToolTipText("Remove replacement from pod"); btnDepod.setName("btnDepod"); // NOI18N btnDepod.addActionListener(ev -> { MissingPart podded = part.getMissingPart(); podded.setOmniPodded(true); Part replacement = podded.findReplacement(false); if (null != replacement) { campaignGUI.getCampaign().depodPart(replacement, 1); MekHQ.triggerEvent(new PartChangedEvent(replacement)); } refresh(); }); actionButtons.add(btnDepod, gbcActions); gbcActions.gridy++; } if (campaignGUI.getCampaign().isGM()) { JButton btnGM = new JButton(); btnGM.setText("[GM] Acquire Instantly"); // NOI18N btnGM.setToolTipText("GM Override - Acquire all missing items instantly"); btnGM.setName("btnGM"); // NOI18N btnGM.addActionListener(ev -> { campaignGUI.getCampaign().addReport(targetWork.find(0)); MekHQ.triggerEvent(new UnitChangedEvent(targetWork.getUnit())); refresh(); }); actionButtons.add(btnGM, gbcActions); gbcActions.gridy++; } return actionButtons; } } }