package com.ibm.nmon.gui.interval;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Font;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.HierarchyListener;
import java.awt.event.HierarchyEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import javax.swing.BorderFactory;
import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.JScrollPane;
import javax.swing.JLabel;
import javax.swing.JButton;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.table.DefaultTableCellRenderer;
import com.ibm.nmon.gui.GUITable;
import com.ibm.nmon.gui.Styles;
import com.ibm.nmon.gui.main.NMONVisualizerGui;
import com.ibm.nmon.gui.table.StringCellRenderer;
import com.ibm.nmon.interval.Interval;
import com.ibm.nmon.util.TimeFormatCache;
/**
* <p>
* Display a list of Intervals in a 3 column table. Also contains a button to clear all the current
* intervals.
* </p>
*
* <p>
* Users can update the interval name directly in the table. Selecting an interval in the table will
* fire an <code>interval</code> property change event.
* </p>
*
* <p>
* The table will update on time zone changes.
* </p>
*/
final class IntervalList extends JPanel implements HierarchyListener, PropertyChangeListener {
private static final long serialVersionUID = -2227815465031324337L;
private final GUITable intervals;
private final NMONVisualizerGui gui;
public IntervalList(NMONVisualizerGui gui) {
super();
setLayout(new BorderLayout());
this.gui = gui;
IntervalTableModel model = new IntervalTableModel(gui);
intervals = new GUITable(gui, model);
// update the interval name
intervals.getCellEditor(0, 0).addCellEditorListener(new CellEditorListener() {
@Override
public void editingStopped(ChangeEvent e) {
int selectedRow = intervals.getSelectedRow();
Interval i = ((IntervalTableModel) intervals.getModel()).getValueAt(selectedRow);
String newName = (String) intervals.getCellEditor(selectedRow, 0).getCellEditorValue();
IntervalList.this.gui.getIntervalManager().renameInterval(i, newName);
}
@Override
public void editingCanceled(ChangeEvent e) {}
});
// make the current interval bold
intervals.setDefaultRenderer(Long.class, new DefaultTableCellRenderer() {
private static final long serialVersionUID = 7101632198507145234L;
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
setText(TimeFormatCache.formatDateTime((Long) value));
Interval i = ((IntervalTableModel) table.getModel()).getValueAt(row);
if (i.equals(IntervalList.this.gui.getIntervalManager().getCurrentInterval())) {
setFont(getFont().deriveFont(Font.BOLD));
}
return this;
}
});
intervals.setDefaultRenderer(String.class, new StringCellRenderer());
intervals.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
// fire an interval change when the table selection changes
intervals.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
int row = intervals.getSelectedRow();
Interval interval = null;
if (row >= 0) {
interval = ((IntervalTableModel) intervals.getModel()).getValueAt(row);
}
else {
// nothing selected => no rows in table => no intervals => default interval
// note that current interval has not been updated yet, so manually set to
// default
interval = Interval.DEFAULT;
}
IntervalList.this.firePropertyChange("interval", null, interval);
}
}
});
JLabel label = new JLabel("Intervals");
label.setFont(Styles.LABEL);
label.setBorder(BorderFactory.createEmptyBorder(5, 5, 2, 0));
add(label, BorderLayout.PAGE_START);
JScrollPane scrollPane = new JScrollPane(intervals);
scrollPane.getViewport().setBackground(java.awt.Color.WHITE);
scrollPane.setPreferredSize(new java.awt.Dimension(600, 150));
scrollPane.setBorder(Styles.DOUBLE_LINE_BORDER);
add(scrollPane, BorderLayout.CENTER);
RemoveAllIntervalsAction removeAllAction = new RemoveAllIntervalsAction(gui, this);
final JButton clear = new JButton("Clear");
clear.setIcon(Styles.CLEAR_ICON);
clear.addActionListener(removeAllAction);
clear.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
IntervalList.this.firePropertyChange("interval", null, IntervalList.this.gui.getIntervalManager()
.getCurrentInterval());
}
});
// temp panel to keep the button from filling the space
JPanel temp = new JPanel();
temp.add(clear);
add(temp, BorderLayout.PAGE_END);
getActionMap().put("clear", new AbstractAction() {
private static final long serialVersionUID = 317117736111534324L;
@Override
public void actionPerformed(ActionEvent e) {
clear.doClick();
}
});
getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, InputEvent.CTRL_DOWN_MASK), "clear");
}
GUITable getTable() {
return intervals;
}
@Override
public void hierarchyChanged(HierarchyEvent e) {
if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0) {
if (e.getChanged().isVisible()) {
gui.addPropertyChangeListener("timeZone", this);
gui.getIntervalManager().addListener((IntervalTableModel) intervals.getModel());
}
else {
gui.removePropertyChangeListener("timeZone", this);
gui.getIntervalManager().removeListener((IntervalTableModel) intervals.getModel());
}
}
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
if ("timeZone".equals(evt.getPropertyName())) {
// force a redraw of the table so it will redisplay the updated times
((IntervalTableModel) intervals.getModel()).fireTableDataChanged();
}
}
}