package org.yamcs.ui.archivebrowser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yamcs.protobuf.Yamcs;
import org.yamcs.ui.CommandHistoryRetrievalGui;
import org.yamcs.ui.PacketRetrievalGui;
import org.yamcs.ui.ParameterRetrievalGui;
import org.yamcs.ui.UiColors;
import org.yamcs.ui.YamcsConnector;
import org.yamcs.utils.TimeEncoding;
import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Collections;
import java.util.List;
/**
* Adds controls to a wrapped {@link org.yamcs.ui.archivebrowser.DataView}
*/
public abstract class DataViewer extends NavigatorItem implements ActionListener {
private ArchivePanel archivePanel;
private DataView dataView;
public JToolBar buttonToolbar;
private JMenu selectionMenu;
private JMenuItem packetRetrieval, parameterRetrieval, cmdHistRetrieval;
JButton zoomInButton, zoomOutButton, showAllButton, newTagButton;
boolean replayEnabled;
private JFormattedTextField mouseLocator;
private JFormattedTextField selectionStart;
private JFormattedTextField selectionStop;
private JLabel mouseLocatorLabel;
private JLabel dottedSquare;
PacketRetrievalGui packetGui;
CommandHistoryRetrievalGui cmdHistGui;
ParameterRetrievalGui parameterGui;
private static Logger log = LoggerFactory.getLogger(DataViewer.class);
public DataViewer(YamcsConnector yconnector, ArchiveIndexReceiver indexReceiver, ArchivePanel archivePanel, boolean replayEnabled) {
super(yconnector, indexReceiver);
this.archivePanel = archivePanel;
this.replayEnabled = replayEnabled;
// Add custom menu items
selectionMenu = new JMenu("Selection");
selectionMenu.setVisible(false);
archivePanel.archiveBrowser.menuBar.add(selectionMenu);
packetRetrieval = new JMenuItem("Export Packets...");
packetRetrieval.setToolTipText("Start packet retrieval of the selected packets");
packetRetrieval.addActionListener(this);
packetRetrieval.setActionCommand("start-packet-retrieval");
packetRetrieval.setEnabled(false);
selectionMenu.add(packetRetrieval);
parameterRetrieval = new JMenuItem("Export Parameters...");
parameterRetrieval.setToolTipText("Start parameter retrieval for the selected time interval");
parameterRetrieval.addActionListener(this);
parameterRetrieval.setActionCommand("start-parameter-retrieval");
parameterRetrieval.setEnabled(false);
selectionMenu.add(parameterRetrieval);
cmdHistRetrieval = new JMenuItem("Export Command History...");
cmdHistRetrieval.setToolTipText("Start command history retrieval for the selected time interval");
cmdHistRetrieval.addActionListener(this);
cmdHistRetrieval.setActionCommand("start-cmdhist-retrieval");
cmdHistRetrieval.setEnabled(false);
selectionMenu.add(cmdHistRetrieval);
}
@Override
public JComponent createContentPanel() {
JPanel contentPanel = new JPanel(new BorderLayout());
contentPanel.setBorder(BorderFactory.createEmptyBorder());
contentPanel.setBackground(Color.WHITE);
contentPanel.add(createButtonToolbar(), BorderLayout.NORTH);
dataView = new DataView(archivePanel, this);
dataView.addActionListener(this);
contentPanel.add(dataView, BorderLayout.CENTER);
return contentPanel;
}
@Override
public void onOpen() {
selectionMenu.setVisible(true);
}
@Override
public void onClose() {
selectionMenu.setVisible(false);
}
/**
* Includes a date range for showing the selected interval,
* and a field that follows the mouse position (similar to
* TT, but without day of the year formatting.)
*/
@Override
public JComponent createNavigatorInset() {
Box vbox = Box.createVerticalBox();
Border outsideBorder = BorderFactory.createMatteBorder(1, 0, 0, 0, UiColors.BORDER_COLOR);
Border insideBorder = BorderFactory.createEmptyBorder(0, 10, 0, 10);
vbox.setBorder(BorderFactory.createCompoundBorder(outsideBorder, insideBorder));
InstantFormat iformat=new InstantFormat();
Box mouseBox = Box.createHorizontalBox();
mouseLocatorLabel = new JLabel("\u27a5");
mouseLocatorLabel.setForeground(Color.LIGHT_GRAY);
mouseLocatorLabel.setToolTipText("Mouse position");
mouseBox.add(mouseLocatorLabel);
mouseLocator = new JFormattedTextField(iformat);
mouseLocator.setHorizontalAlignment(JTextField.CENTER);
mouseLocator.setEditable(false);
mouseLocator.setMaximumSize(new Dimension(150, mouseLocator.getPreferredSize().height));
mouseLocator.setMinimumSize(mouseLocator.getMaximumSize());
mouseLocator.setPreferredSize(mouseLocator.getMaximumSize());
mouseLocator.setFont(mouseLocator.getFont().deriveFont(mouseLocator.getFont().getSize2D() - 3));
mouseBox.add(mouseLocator);
Box selectionStartBox = Box.createHorizontalBox();
dottedSquare = new JLabel("\u2b1a");
dottedSquare.setForeground(Color.GRAY);
dottedSquare.setToolTipText("Selected date range");
selectionStartBox.add(dottedSquare);
selectionStart = new JFormattedTextField(iformat);
selectionStart.setHorizontalAlignment(JTextField.CENTER);
selectionStart.setEditable(false);
selectionStart.setMaximumSize(new Dimension(150, selectionStart.getPreferredSize().height));
selectionStart.setMinimumSize(selectionStart.getMaximumSize());
selectionStart.setPreferredSize(selectionStart.getMaximumSize());
selectionStart.setFont(selectionStart.getFont().deriveFont(selectionStart.getFont().getSize2D() - 3));
selectionStartBox.add(selectionStart);
selectionStart.addPropertyChangeListener("value", new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent e) {
dataView.updateSelection((Long) selectionStart.getValue(), (Long) selectionStop.getValue());
}
});
Box selectionStopBox = Box.createHorizontalBox();
selectionStop = new JFormattedTextField(iformat);
selectionStop.setHorizontalAlignment(JTextField.CENTER);
selectionStop.setEditable(false);
selectionStop.setMaximumSize(new Dimension(150, selectionStop.getPreferredSize().height));
selectionStop.setMinimumSize(selectionStop.getMaximumSize());
selectionStop.setPreferredSize(selectionStop.getMaximumSize());
selectionStop.setFont(selectionStop.getFont().deriveFont(selectionStop.getFont().getSize2D() - 3));
selectionStopBox.add(selectionStop);
selectionStop.addPropertyChangeListener("value", new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent e) {
dataView.updateSelection((Long) selectionStart.getValue(), (Long) selectionStop.getValue());
}
});
mouseBox.setAlignmentX(Component.RIGHT_ALIGNMENT);
vbox.add(mouseBox);
selectionStartBox.setAlignmentX(Component.RIGHT_ALIGNMENT);
vbox.add(selectionStartBox);
selectionStopBox.setAlignmentX(Component.RIGHT_ALIGNMENT);
vbox.add(selectionStopBox);
return vbox;
}
public void signalMousePosition(long instant) {
mouseLocatorLabel.setForeground((instant== TimeEncoding.INVALID_INSTANT) ? Color.LIGHT_GRAY : Color.GRAY);
mouseLocator.setValue(instant);
}
public void signalSelectionChange(Selection selection) {
if (selection != null) {
signalSelectionStartChange(selection.getStartInstant());
signalSelectionStopChange(selection.getStopInstant());
if(selection.getStartInstant()!=TimeEncoding.INVALID_INSTANT
|| selection.getStopInstant()!=TimeEncoding.INVALID_INSTANT) {
dottedSquare.setForeground(Color.BLUE);
} else {
dottedSquare.setForeground(Color.GRAY);
}
if(replayEnabled) {
archivePanel.replayPanel.applySelectionButton.setEnabled(true);
}
} else {
signalSelectionStartChange(TimeEncoding.INVALID_INSTANT);
signalSelectionStopChange(TimeEncoding.INVALID_INSTANT);
if(dottedSquare!=null) { // FIXME gui set-up should not need resetSelection() call
dottedSquare.setForeground(Color.GRAY);
}
if(replayEnabled) {
archivePanel.replayPanel.applySelectionButton.setEnabled(false);
}
}
}
public void signalSelectionStartChange(long startInstant) {
if(selectionStart!=null) { // FIXME Can be null during gui set-up.
selectionStart.setEditable((startInstant != TimeEncoding.INVALID_INSTANT));
selectionStart.setValue(startInstant);
}
}
public void signalSelectionStopChange(long stopInstant) {
if(selectionStop!=null) { // FIXME Can be null during gui set-up.
selectionStop.setEditable((stopInstant != TimeEncoding.INVALID_INSTANT));
selectionStop.setValue(stopInstant);
}
}
public void addIndex(String tableName, String name) {
addIndex(tableName, name, -1);
}
public void addIndex(String tableName, String name, int mergeTime) {
dataView.addIndex(tableName, name, mergeTime);
if (replayEnabled && "tm".equals(tableName)) {
// TODO move up
archivePanel.replayPanel.setDataViewer(this);
}
}
public void addVerticalGlue() {
dataView.addVerticalGlue();
}
private JToolBar createButtonToolbar() {
buttonToolbar = new JToolBar("Button Toolbar");
buttonToolbar.setAlignmentX(Component.LEFT_ALIGNMENT);
buttonToolbar.setBackground(Color.WHITE);
buttonToolbar.setFloatable(false);
buttonToolbar.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
zoomInButton = new JButton("Zoom In");
zoomInButton.setActionCommand("zoomin");
zoomInButton.addActionListener(this);
zoomInButton.setEnabled(false);
buttonToolbar.add(zoomInButton);
zoomOutButton = new JButton("Zoom Out");
zoomOutButton.setActionCommand("zoomout");
zoomOutButton.addActionListener(this);
zoomOutButton.setEnabled(false);
buttonToolbar.add(zoomOutButton);
showAllButton = new JButton("Show All");
showAllButton.setActionCommand("showall");
showAllButton.addActionListener(this);
showAllButton.setEnabled(false);
buttonToolbar.add(showAllButton);
newTagButton=new JButton("New Tag");
newTagButton.setVisible(archivePanel.archiveBrowser.indexReceiver.supportsTags());
newTagButton.setEnabled(false);
newTagButton.setToolTipText("Define a new tag for the current selection");
newTagButton.addActionListener(this);
newTagButton.setActionCommand("new-tag-button");
newTagButton.setVisible(false);
buttonToolbar.add(newTagButton);
return buttonToolbar;
}
@Override
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
if (cmd.equals("showall")) {
dataView.showAll();
zoomOutButton.setEnabled(false);
} else if (cmd.equals("zoomout")) {
dataView.zoomOut();
zoomOutButton.setEnabled(dataView.zoomStack.size() > 1);
} else if (cmd.equals("zoomin")) {
dataView.zoomIn();
zoomOutButton.setEnabled(true);
} else if (cmd.equalsIgnoreCase("completeness_selection_finished")) {
if(indexReceiver.supportsTags()) newTagButton.setEnabled(true);
} else if (cmd.toLowerCase().endsWith("selection_finished")) {
if(indexReceiver.supportsTags()) newTagButton.setEnabled(true);
if(cmd.startsWith("pp") || cmd.startsWith("tm")) {
packetRetrieval.setEnabled(true);
parameterRetrieval.setEnabled(true);
} else if (cmd.startsWith("cmdhist")) {
cmdHistRetrieval.setEnabled(true);
}
} else if(cmd.equalsIgnoreCase("selection_reset")) {
if (newTagButton != null) newTagButton.setEnabled(false);
packetRetrieval.setEnabled(false);
parameterRetrieval.setEnabled(false);
cmdHistRetrieval.setEnabled(false);
} else if (cmd.equalsIgnoreCase("new-tag-button")) {
Selection sel = dataView.getSelection();
dataView.headerPanel.tagBox.createNewTag(sel.getStartInstant(), sel.getStopInstant());
} else if(cmd.equalsIgnoreCase("insert-tag")) {
TagBox.TagEvent te=(TagBox.TagEvent)e;
indexReceiver.insertTag(archivePanel.archiveBrowser.getInstance(), te.newTag);
} else if(cmd.equalsIgnoreCase("update-tag")) {
TagBox.TagEvent te=(TagBox.TagEvent)e;
indexReceiver.updateTag(archivePanel.archiveBrowser.getInstance(), te.oldTag, te.newTag);
} else if(cmd.equalsIgnoreCase("delete-tag")) {
TagBox.TagEvent te=(TagBox.TagEvent)e;
indexReceiver.deleteTag(archivePanel.archiveBrowser.getInstance(), te.oldTag);
} else if (cmd.equals("start-packet-retrieval")) {
List<String> packets = Collections.emptyList();
if(dataView.indexBoxes.containsKey("tm")) {
packets = dataView.getSelectedPackets("tm");
}
Selection sel = dataView.getSelection();
if(packetGui==null) {
packetGui=new PacketRetrievalGui(yconnector.getConnectionParams(), getContentPanel());
}
packetGui.setValues(archivePanel.archiveBrowser.getInstance(), packets, sel.getStartInstant(), sel.getStopInstant());
packetGui.setVisible(true);
} else if (cmd.equals("start-parameter-retrieval")) {
Selection sel = dataView.getSelection();
if(parameterGui==null) {
parameterGui = new ParameterRetrievalGui(yconnector.getConnectionParams(), getContentPanel());
}
parameterGui.setValues(archivePanel.archiveBrowser.getInstance(), sel.getStartInstant(), sel.getStopInstant());
parameterGui.setVisible(true);
} else if (cmd.equals("start-cmdhist-retrieval")) {
Selection sel = dataView.getSelection();
if (cmdHistGui == null) {
cmdHistGui = new CommandHistoryRetrievalGui(yconnector.getConnectionParams(), getContentPanel());
}
cmdHistGui.setValues(archivePanel.archiveBrowser.getInstance(), null, sel.getStartInstant(), sel.getStopInstant());
cmdHistGui.setVisible(true);
}
}
public DataView getDataView() {
return dataView;
}
@Override
public void startReloading() {
log.trace("startReloading. EDT? {} (should be false)", EventQueue.isDispatchThread());
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
zoomInButton.setEnabled(false);
zoomOutButton.setEnabled(false);
showAllButton.setEnabled(false);
if (replayEnabled) {
archivePanel.replayPanel.applySelectionButton.setEnabled(false);
}
}
});
for(IndexBox ib:dataView.indexBoxes.values()) {
ib.startReloading();
}
dataView.headerPanel.tagBox.tags.clear();
}
@Override
public void windowResized() {
if(dataView.zoomStack.isEmpty() || dataView.zoomStack.size() == 1) {
dataView.refreshDisplay(true);
if(!dataView.zoomStack.isEmpty()) {
dataView.setViewLocationFromZoomstack();
}
}
}
@Override
public void receiveArchiveRecords(Yamcs.IndexResult ir) {
log.trace("receiveArchiveRecords. EDT? {} (should be false)", EventQueue.isDispatchThread());
if("completeness".equals(ir.getType())) {
if(dataView.indexBoxes.containsKey("completeness")) {
dataView.indexBoxes.get("completeness").receiveArchiveRecords(ir.getRecordsList());
}
} else if("histogram".equals(ir.getType())) {
String tableName=ir.getTableName();
if(dataView.indexBoxes.containsKey(tableName)) {
dataView.indexBoxes.get(tableName).receiveArchiveRecords(ir.getRecordsList());
}
} else {
System.out.println("Received archive records of type " + ir.getType() + " don't know what to do with them");
}
}
@Override
public void archiveLoadFinished() {
log.trace("archiveLoadFinished. EDT? {} (should be false)", EventQueue.isDispatchThread());
dataView.archiveLoadFinished();
}
@Override
public void receiveTags(List<Yamcs.ArchiveTag> tagList) {
dataView.headerPanel.tagBox.addTags(tagList);
}
@Override
public void tagAdded(Yamcs.ArchiveTag ntag) {
dataView.headerPanel.tagBox.addTag(ntag);
}
@Override
public void tagRemoved(Yamcs.ArchiveTag rtag) {
dataView.headerPanel.tagBox.removeTag(rtag);
}
@Override
public void tagChanged(Yamcs.ArchiveTag oldTag, Yamcs.ArchiveTag newTag) {
dataView.headerPanel.tagBox.updateTag(oldTag, newTag);
}
}