/* * ContractMarketDialog.java * * Copyright (c) 2014 Carl Spain. All rights reserved. * * This file is part of MekHQ. * * MekHQ is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * MekHQ is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MekHQ. If not, see <http://www.gnu.org/licenses/>. */ package mekhq.gui.dialog; /** * Presents contract offers generated by ContractMarket * * Code borrowed heavily from PersonnelMarketDialog * * @author Neoancient */ import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Frame; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.util.ArrayList; import java.util.HashMap; import java.util.ResourceBundle; import java.util.Vector; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSpinner; import javax.swing.JSplitPane; import javax.swing.JTable; import javax.swing.ListSelectionModel; import javax.swing.ScrollPaneConstants; import javax.swing.SpinnerNumberModel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.ListSelectionListener; import javax.swing.table.DefaultTableModel; import megamek.common.util.EncodeControl; import mekhq.campaign.Campaign; import mekhq.campaign.finances.Transaction; import mekhq.campaign.market.ContractMarket; import mekhq.campaign.mission.AtBContract; import mekhq.campaign.mission.Contract; import mekhq.campaign.mission.Mission; import mekhq.campaign.universe.Faction; import mekhq.gui.FactionComboBox; import mekhq.gui.view.ContractSummaryPanel; public class ContractMarketDialog extends JDialog { /** * */ private static final long serialVersionUID = 2285074545510057268L; /* Save these settings between instantiations */ private static boolean payMRBC = true; private static int advance = 25; private static int signingBonus = 0; private static int sharePct = 20; private Campaign campaign; private ContractMarket contractMarket; private Contract selectedContract = null; private ArrayList<String> possibleRetainerContracts; private JScrollPane scrollTableContracts; private JScrollPane scrollContractView; private JPanel panelTable; private JPanel panelFees; private JPanel panelRetainer; private JPanel panelOKBtns; private ContractSummaryPanel contractView; private JButton btnGenerate; private JButton btnRemove; private JButton btnAccept; private JButton btnClose; private JSplitPane splitMain; private JCheckBox chkMRBC; private JLabel lblSigningBonus; private JSpinner spnSigningBonus; private JLabel lblAdvance; private JSpinner spnAdvance; private JLabel lblSharePct; private JSpinner spnSharePct; private JTable tblContracts; private JLabel lblCurrentRetainer; private JLabel lblRetainerEmployer; private JButton btnEndRetainer; private JLabel lblRetainerAvailable; private FactionComboBox cbRetainerEmployer; private JButton btnStartRetainer; public ContractMarketDialog(Frame frame, Campaign c) { super(frame, true); campaign = c; contractMarket = c.getContractMarket(); possibleRetainerContracts = new ArrayList<String>(); if (c.getFactionCode().equals("MERC")) { countSuccessfulContracts(); } initComponents(); setLocationRelativeTo(frame); } /* A balance of six or more successful contracts with the same * employer results in the offer of a retainer contract. */ private void countSuccessfulContracts() { HashMap<String, Integer> successfulContracts = new HashMap<String, Integer>(); for (Mission m : campaign.getMissions()) { if (m.isActive() || !(m instanceof AtBContract) || ((AtBContract)m).getEmployerCode().equals(campaign.getRetainerEmployerCode())) { continue; } AtBContract contract = (AtBContract)m; int num; if (successfulContracts.keySet().contains(contract.getEmployerCode())) { num = successfulContracts.get(contract.getEmployerCode()); } else { num = 0; } successfulContracts.put(contract.getEmployerCode(), num + ((contract.getStatus() == Mission.S_SUCCESS)?1:-1)); } for (String key : successfulContracts.keySet()) { if (successfulContracts.get(key) >= 6) { possibleRetainerContracts.add(key); } } } private void initComponents() { scrollTableContracts = new JScrollPane(); scrollContractView = new JScrollPane(); panelTable = new JPanel(); panelFees = new JPanel(); panelRetainer = new JPanel(); panelOKBtns = new JPanel(); contractView = null; btnGenerate = new JButton(); btnRemove = new JButton(); btnAccept = new JButton(); btnClose = new JButton(); chkMRBC = new JCheckBox(); chkMRBC.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent arg0) { payMRBC = chkMRBC.isSelected(); for (Contract c : contractMarket.getContracts()) { c.setMRBCFee(payMRBC); c.calculateContract(campaign); } if (contractView != null) { contractView.refreshAmounts(); } } }); lblAdvance = new JLabel(); spnAdvance = new JSpinner(new SpinnerNumberModel(advance, 0, 25, 5)); spnAdvance.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent arg0) { advance = (Integer)spnAdvance.getValue(); for (Contract c : contractMarket.getContracts()) { c.setAdvancePct(advance); c.calculateContract(campaign); } if (contractView != null) { contractView.refreshAmounts(); } } }); lblSigningBonus = new JLabel(); spnSigningBonus = new JSpinner(new SpinnerNumberModel(signingBonus, 0, 10, 1)); spnSigningBonus.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent arg0) { signingBonus = (Integer)spnSigningBonus.getValue(); for (Contract c : contractMarket.getContracts()) { c.setSigningBonusPct(signingBonus); c.calculateContract(campaign); } if (contractView != null) { contractView.refreshAmounts(); } } }); lblSharePct = new JLabel(); spnSharePct = new JSpinner(new SpinnerNumberModel(sharePct, 20, 50, 10)); spnSharePct.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent arg0) { sharePct = (Integer)spnSharePct.getValue(); for (Contract c : contractMarket.getContracts()) { if (campaign.getCampaignOptions().getUseAtB() && campaign.getCampaignOptions().getUseShareSystem() && c instanceof AtBContract) { ((AtBContract)c).setSharesPct(sharePct); c.calculateContract(campaign); } } if (contractView != null) { contractView.refreshAmounts(); } } }); tblContracts = new JTable(); lblCurrentRetainer = new JLabel(); lblRetainerEmployer = new JLabel(); btnEndRetainer = new JButton(); lblRetainerAvailable = new JLabel(); cbRetainerEmployer = new FactionComboBox(); btnStartRetainer = new JButton(); ResourceBundle resourceMap = ResourceBundle.getBundle("mekhq.resources.ContractMarketDialog", new EncodeControl()); //$NON-NLS-1$ setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); setTitle(resourceMap.getString("Form.title")); // NOI18N setName("Form"); // NOI18N getContentPane().setLayout(new BorderLayout()); scrollTableContracts.setMinimumSize(new java.awt.Dimension(500, 400)); scrollTableContracts.setName("scrollTableContracts"); // NOI18N scrollTableContracts.setPreferredSize(new java.awt.Dimension(500, 400)); chkMRBC.setName("chkMRBC"); chkMRBC.setText(resourceMap.getString("checkMRBC.text")); chkMRBC.setSelected(payMRBC); panelFees.add(chkMRBC); lblAdvance.setText(resourceMap.getString("lblAdvance.text")); panelFees.add(lblAdvance); panelFees.add(spnAdvance); lblSigningBonus.setText(resourceMap.getString("lblSigningBonus.text")); panelFees.add(lblSigningBonus); panelFees.add(spnSigningBonus); lblSharePct.setText(resourceMap.getString("lblSharePct.text")); if (campaign.getCampaignOptions().getUseShareSystem()) { panelFees.add(lblSharePct); panelFees.add(spnSharePct); } Vector<Vector<String>> data = new Vector<Vector<String>>(); Vector<String> colNames = new Vector<String>(); for (Contract c : contractMarket.getContracts()) { /* Changes in rating or force size since creation can alter some * details */ if (c instanceof AtBContract) { ((AtBContract)c).initContractDetails(campaign); ((AtBContract)c).calculatePartsAvailabilityLevel(campaign); ((AtBContract)c).setSharesPct(campaign.getCampaignOptions().getUseShareSystem()? (Integer)spnSharePct.getValue():0); } c.setStartDate(null); c.setMRBCFee(payMRBC); c.setAdvancePct(advance); c.setSigningBonusPct(signingBonus); c.calculateContract(campaign); Vector<String> row = new Vector<String>(); if (c instanceof AtBContract) { row.add(((AtBContract)c).getEmployerName(campaign.getEra())); row.add(((AtBContract)c).getEnemyName(campaign.getEra())); if (((AtBContract)c).isSubcontract()) { row.add(((AtBContract)c).getMissionTypeName() + " (Subcontract)"); } else { row.add(((AtBContract)c).getMissionTypeName()); } } else { row.add(c.getEmployer()); row.add(""); row.add(c.getType()); } data.add(row); } colNames.add("Employer"); colNames.add("Enemy"); colNames.add("Mission Type"); tblContracts.setModel(new DefaultTableModel(data, colNames)); tblContracts.setName("tblContracts"); // NOI18N tblContracts.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); tblContracts.createDefaultColumnsFromModel(); tblContracts.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); tblContracts.getSelectionModel().addListSelectionListener(new ListSelectionListener() { public void valueChanged(javax.swing.event.ListSelectionEvent evt) { if (!evt.getValueIsAdjusting()) { contractChanged(); } } }); tblContracts.setIntercellSpacing(new Dimension(0, 0)); tblContracts.setShowGrid(false); scrollTableContracts.setViewportView(tblContracts); scrollContractView.setMinimumSize(new java.awt.Dimension(500, 600)); scrollContractView.setPreferredSize(new java.awt.Dimension(500, 600)); scrollContractView.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); scrollContractView.setViewportView(null); panelTable.setLayout(new BorderLayout()); panelTable.add(panelFees, BorderLayout.PAGE_START); panelTable.add(scrollTableContracts, BorderLayout.CENTER); panelTable.add(panelRetainer, BorderLayout.PAGE_END); panelRetainer.setLayout(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); lblCurrentRetainer.setText(resourceMap.getString("lblCurrentRetainer.text")); gbc.gridx = 0; gbc.gridy = 0; gbc.anchor = GridBagConstraints.NORTHWEST; gbc.fill = GridBagConstraints.NONE; panelRetainer.add(lblCurrentRetainer, gbc); if (null != campaign.getRetainerEmployerCode()) { lblRetainerEmployer.setText(Faction.getFaction(campaign.getRetainerEmployerCode()).getFullName(campaign.getEra())); } gbc.gridx = 1; gbc.gridy = 0; panelRetainer.add(lblRetainerEmployer, gbc); btnEndRetainer.setText(resourceMap.getString("btnEndRetainer.text")); gbc.gridx = 0; gbc.gridy = 1; panelRetainer.add(btnEndRetainer, gbc); lblCurrentRetainer.setVisible(null != campaign.getRetainerEmployerCode()); lblRetainerEmployer.setVisible(null != campaign.getRetainerEmployerCode()); btnEndRetainer.setVisible(null != campaign.getRetainerEmployerCode()); btnEndRetainer.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent ev) { campaign.setRetainerEmployerCode(null); lblCurrentRetainer.setVisible(false); lblRetainerEmployer.setVisible(false); btnEndRetainer.setVisible(false); //Add faction back to available ones countSuccessfulContracts(); lblRetainerAvailable.setVisible(possibleRetainerContracts.size() > 0); cbRetainerEmployer.setVisible(possibleRetainerContracts.size() > 0); btnStartRetainer.setVisible(possibleRetainerContracts.size() > 0); } }); lblRetainerAvailable.setText(resourceMap.getString("lblRetainerAvailable.text")); gbc.gridx = 0; gbc.gridy = 2; panelRetainer.add(lblRetainerAvailable, gbc); cbRetainerEmployer.addFactionEntries(possibleRetainerContracts, campaign.getEra()); gbc.gridx = 1; gbc.gridy = 2; panelRetainer.add(cbRetainerEmployer, gbc); btnStartRetainer.setText(resourceMap.getString("btnStartRetainer.text")); gbc.gridx = 0; gbc.gridy = 3; panelRetainer.add(btnStartRetainer, gbc); lblRetainerAvailable.setVisible(possibleRetainerContracts.size() > 0); cbRetainerEmployer.setVisible(possibleRetainerContracts.size() > 0); btnStartRetainer.setVisible(possibleRetainerContracts.size() > 0); btnStartRetainer.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { campaign.setRetainerEmployerCode(cbRetainerEmployer.getSelectedItemKey()); lblCurrentRetainer.setVisible(true); lblRetainerEmployer.setVisible(true); btnEndRetainer.setVisible(true); lblRetainerEmployer.setText(Faction.getFaction(campaign.getRetainerEmployerCode()).getFullName(campaign.getEra())); //Remove the selected faction and add the previous one, if any countSuccessfulContracts(); lblRetainerAvailable.setVisible(possibleRetainerContracts.size() > 0); cbRetainerEmployer.setVisible(possibleRetainerContracts.size() > 0); btnStartRetainer.setVisible(possibleRetainerContracts.size() > 0); } }); splitMain = new javax.swing.JSplitPane(JSplitPane.HORIZONTAL_SPLIT,panelTable, scrollContractView); splitMain.setOneTouchExpandable(true); splitMain.setResizeWeight(0.0); getContentPane().add(splitMain, BorderLayout.CENTER); panelOKBtns.setLayout(new java.awt.GridBagLayout()); btnGenerate.setText(resourceMap.getString("btnGenerate.text")); btnGenerate.setName("btnGenerate"); // NOI18N btnGenerate.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { AtBContract c = contractMarket.addAtBContract(campaign); c.initContractDetails(campaign); c.calculatePartsAvailabilityLevel(campaign); c.setSharesPct(campaign.getCampaignOptions().getUseShareSystem()? (Integer)spnSharePct.getValue():0); c.setStartDate(null); c.setMRBCFee(payMRBC); c.setAdvancePct(advance); c.setSigningBonusPct(signingBonus); c.calculateContract(campaign); Vector<String> row = new Vector<String>(); row.add(((AtBContract)c).getEmployerName(campaign.getEra())); row.add(((AtBContract)c).getEnemyName(campaign.getEra())); row.add(((AtBContract)c).getMissionTypeName()); ((DefaultTableModel)tblContracts.getModel()).addRow(row); } }); btnGenerate.setEnabled(campaign.isGM()); panelOKBtns.add(btnGenerate, new java.awt.GridBagConstraints()); btnRemove.setText(resourceMap.getString("btnRemove.text")); btnRemove.setName("btnRemove"); // NOI18N btnRemove.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { contractMarket.removeContract(selectedContract); ((DefaultTableModel)tblContracts.getModel()).removeRow(tblContracts.convertRowIndexToModel(tblContracts.getSelectedRow())); } }); panelOKBtns.add(btnRemove, new java.awt.GridBagConstraints()); btnAccept.setText(resourceMap.getString("btnAccept.text")); btnAccept.setName("btnAccept"); // NOI18N btnAccept.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { acceptContract(evt); } }); panelOKBtns.add(btnAccept, new java.awt.GridBagConstraints()); btnClose.setText(resourceMap.getString("btnClose.text")); // NOI18N btnClose.setName("btnClose"); // NOI18N btnClose.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { btnCloseActionPerformed(evt); } }); panelOKBtns.add(btnClose, new java.awt.GridBagConstraints()); getContentPane().add(panelOKBtns, BorderLayout.PAGE_END); pack(); } public Contract getContract() { return selectedContract; } private void acceptContract(ActionEvent evt) { if(selectedContract != null) { selectedContract.setName(contractView.getContractName()); campaign.getFinances().credit(selectedContract.getTotalAdvanceMonies(), Transaction.C_CONTRACT, "Advance monies for " + selectedContract.getName(), campaign.getCalendar().getTime()); campaign.addMission(selectedContract); contractMarket.removeContract(selectedContract); ((DefaultTableModel)tblContracts.getModel()).removeRow(tblContracts.convertRowIndexToModel(tblContracts.getSelectedRow())); refreshContractView(); } } private void btnCloseActionPerformed(ActionEvent evt) { selectedContract = null; setVisible(false); } private void contractChanged() { int view = tblContracts.getSelectedRow(); if(view < 0) { //selection got filtered away selectedContract = null; refreshContractView(); return; } /* preserve the name given to the previous contract (if any) */ if (selectedContract != null && contractView != null) { selectedContract.setName(contractView.getContractName()); } selectedContract = contractMarket.getContracts().get(tblContracts.convertRowIndexToModel(view)); refreshContractView(); } void refreshContractView() { int row = tblContracts.getSelectedRow(); if(row < 0) { contractView = null; scrollContractView.setViewportView(null); return; } contractView = new ContractSummaryPanel(selectedContract, campaign, campaign.getCampaignOptions().getUseAtB() && selectedContract instanceof AtBContract && !((AtBContract)selectedContract).isSubcontract()); scrollContractView.setViewportView(contractView); //This odd code is to make sure that the scrollbar stays at the top //I cant just call it here, because it ends up getting reset somewhere later javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { scrollContractView.getVerticalScrollBar().setValue(0); } }); } }