package net.sourceforge.cruisecontrol.distributed;
import org.apache.log4j.Logger;
import javax.swing.JDialog;
import javax.swing.JTable;
import javax.swing.JScrollPane;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JOptionPane;
import javax.swing.Action;
import javax.swing.AbstractAction;
import javax.swing.event.TableModelListener;
import javax.swing.event.TableModelEvent;
import javax.swing.table.AbstractTableModel;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.Dimension;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.ActionEvent;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Properties;
import java.util.List;
/**
* Allow editing of entry overrides for a Build Agent
* @author Dan Rollo
* Date: Apr 3, 2007
* Time: 1:48:11 PM
*/
// @todo Change this class into a Jini ServiceUI component
public class BuildAgentEntryOverrideUI extends JDialog {
private static final Logger LOG = Logger.getLogger(BuildAgentEntryOverrideUI.class);
private static final class PropRow {
private String name;
private String value;
private PropRow(final String name, final String value) {
this.name = name;
this.value = value;
}
public String toString() { return "Name: " + name + "; Value: " + value + ";"; }
}
private static final class PropertyTableModel extends AbstractTableModel {
private final List<PropRow> rows = new ArrayList<PropRow>();
private final int colCount = 2;
private void addRow(final PropRow propRow) {
rows.add(propRow);
fireTableDataChanged();
}
private void clearAll() {
rows.clear();
fireTableDataChanged();
}
public int getRowCount() {
return rows.size();
}
public int getColumnCount() {
return colCount;
}
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
final PropRow row = getPropRow(rowIndex);
if (columnIndex == COL_NAME) {
row.name = (String) aValue;
} else {
row.value = (String) aValue;
}
fireTableDataChanged();
}
public Object getValueAt(int rowIndex, int columnIndex) {
final PropRow row = getPropRow(rowIndex);
return (columnIndex == COL_NAME ? row.name : row.value);
}
private PropRow getPropRow(int rowIndex) {
return rows.get(rowIndex);
}
public boolean isCellEditable(int rowIndex, int columnIndex) { return true; }
}
static final int COL_NAME = 0;
static final int COL_VALUE = 1;
private final JTable tblEntries;
// For unit testing.
void setValueAt(Object aValue, int row, int column) {
tblEntries.setValueAt(aValue, row, column);
}
private final Action atnSave;
// For unit testing.
void doSave() { atnSave.actionPerformed(null); }
boolean isSaveEnabled() { return atnSave.isEnabled(); }
private final Action atnNewRow;
// For unit testing.
void doNewRow() { atnNewRow.actionPerformed(null); }
private final Action atnClearAll;
// For unit testing.
void doClearAll() { atnClearAll.actionPerformed(null); }
/**
* Constructor
* @param owner parent of this dialog
* @param agent the BuildAgentService who's entries we are editing
* @param agentInfo text identifying the agent who's entries we are editing
* @throws RemoteException if an error occurs getting entry overrides from agent
*/
public BuildAgentEntryOverrideUI(final Frame owner, final BuildAgentService agent, final String agentInfo)
throws RemoteException {
super(owner, "Edit Entry Overrides - " + agentInfo);
// populate table with existing entry overrides
final PropertyEntry[] entryOverrides = agent.getEntryOverrides();
final PropertyTableModel mdlTable = new PropertyTableModel();
for (final PropertyEntry entryOverride : entryOverrides) {
mdlTable.addRow(new PropRow(entryOverride.name, entryOverride.value));
}
mdlTable.addTableModelListener(new TableModelListener() {
public void tableChanged(TableModelEvent e) {
atnSave.setEnabled(true);
}
});
tblEntries = new JTable(mdlTable);
tblEntries.getTableHeader().getColumnModel().getColumn(COL_NAME).setHeaderValue("Name");
tblEntries.getTableHeader().getColumnModel().getColumn(COL_VALUE).setHeaderValue("Value");
tblEntries.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
final JScrollPane scrTable = new JScrollPane(tblEntries);
scrTable.setPreferredSize(new Dimension(550, 200));
final JPanel pnlMain = new JPanel();
pnlMain.add(scrTable);
atnSave = new AbstractAction("Save") {
public void actionPerformed(ActionEvent e) {
doSave(mdlTable, agent);
}
};
atnSave.setEnabled(false);
final JPanel pnlButtons = new JPanel(new GridLayout(0, 1));
pnlButtons.add(new JButton(atnSave));
atnNewRow = new AbstractAction("New Row") {
public void actionPerformed(ActionEvent e) {
mdlTable.addRow(new PropRow(null, null));
tblEntries.requestFocusInWindow();
}
};
pnlButtons.add(new JButton(atnNewRow));
atnClearAll = new AbstractAction("Clear All") {
public void actionPerformed(ActionEvent e) {
mdlTable.clearAll();
}
};
pnlButtons.add(new JButton(atnClearAll));
pnlMain.add(pnlButtons);
getContentPane().add(pnlMain);
addWindowListener(new WindowAdapter() {
public void windowClosing(final WindowEvent evt) {
doExit();
}
});
pack();
setLocationRelativeTo(owner);
setVisible(true);
}
private void doSave(final PropertyTableModel mdlTable, final BuildAgentService agent) {
final Properties props = new Properties();
String name;
String value;
for (int i = 0; i < mdlTable.getRowCount(); i++) {
name = (String) mdlTable.getValueAt(i, COL_NAME);
value = (String) mdlTable.getValueAt(i, COL_VALUE);
if (name != null && value != null) {
props.put(name, value);
}
}
try {
agent.setEntryOverrides(SearchablePropertyEntries.getPropertiesAsEntryArray(props));
} catch (RemoteException e1) {
final String msg = "Error saving entry overrides.";
LOG.error(msg, e1);
JOptionPane.showMessageDialog(this, msg + "\n\n" + e1.getMessage(),
"Error Saving Changes", JOptionPane.ERROR_MESSAGE);
throw new RuntimeException(msg, e1);
}
atnSave.setEnabled(false);
}
private void doExit() {
// Prompt if unsaved settings
if (atnSave.isEnabled()) {
final int repsonse = JOptionPane.showConfirmDialog(this,
"You have unsaved changes. Save these changes now?",
"Save Changes?", JOptionPane.YES_NO_OPTION);
if (JOptionPane.YES_NO_OPTION == repsonse) {
atnSave.actionPerformed(null);
}
}
dispose();
}
}