/*
* Copyright 2014 Luke Usherwood.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.bettyluke.util.swing.monitor;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.ListSelectionModel;
public class EdtMonitorPanel extends JPanel {
private final EdtMonitorModel model;
private final PerformancePlot plot;
private final JTextArea text;
public EdtMonitorPanel(EdtMonitorModel model) {
super(new BorderLayout());
this.model = model;
plot = adjustSizes(new PerformancePlot(model));
text = createText();
JScrollPane scroll = adjustSizes(new JScrollPane(text));
JSplitPane split = createSplit(plot, scroll);
// TODO: add speed/pause controls
add(split);
updateTextAndFont(null);
listenForSelectionChanges();
}
private static JTextArea createText() {
JTextArea text = new JTextArea();
text.setFont(new Font(Font.MONOSPACED, Font.PLAIN, text.getFont().getSize()));
return text;
}
private static JSplitPane createSplit(JComponent first, JComponent second) {
JSplitPane split = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true, first, second);
split.setDividerLocation(120);
split.setResizeWeight(0.2);
return split;
}
private void listenForSelectionChanges() {
plot.getColumnModel().getSelectionModel().addListSelectionListener(
e -> {
if (!plot.isUpdateInProgress()) {
updateTextArea();
}
});
}
private void updateTextArea() {
ListSelectionModel selection = plot.getColumnModel().getSelectionModel();
int first = selection.getMinSelectionIndex();
int last = selection.getMaxSelectionIndex();
PeriodStatistics stats = (first == last) ? getStat(first) : mergeStats(first, last);
updateTextAndFont(stats);
text.setCaretPosition(0);
}
/**
* @param stats Nullable
*/
private void updateTextAndFont(PeriodStatistics stats) {
if (shouldShowStats(stats)) {
text.setText(stats.toString());
text.setFont(text.getFont().deriveFont(Font.PLAIN));
} else {
text.setText("Select bar(s) to view details");
text.setFont(text.getFont().deriveFont(Font.ITALIC));
}
}
private boolean shouldShowStats(PeriodStatistics stats) {
return stats != null && plot.getSelectedColumnCount() != 0;
}
/**
* @return Can be null!
*/
private PeriodStatistics getStat(int viewIndex) {
return model.getBin(EdtMonitorModel.NUMBER_OF_BINS - viewIndex - 1);
}
private PeriodStatistics mergeStats(int firstIndex, int lastIndex) {
assert lastIndex > firstIndex;
PeriodStatistics summary = new PeriodStatistics(0L);
for (int i = firstIndex; i <= lastIndex; ++i) {
PeriodStatistics bin = getStat(i);
if (bin != null) {
summary.merge(bin);
}
}
return summary;
}
private static <T extends JComponent> T adjustSizes(T comp) {
comp.setPreferredSize(new Dimension(200,200));
comp.setMinimumSize(new Dimension(10,10));
return comp;
}
}