/*
* JaamSim Discrete Event Simulation
* Copyright (C) 2013 Ausenco Engineering Canada Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jaamsim.ui;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
import com.jaamsim.basicsim.Entity;
import com.jaamsim.input.Input;
import com.jaamsim.input.InputAgent;
import com.jaamsim.input.OutputHandle;
import com.jaamsim.units.DimensionlessUnit;
import com.jaamsim.units.Unit;
public class OutputBox extends FrameBox {
private static OutputBox myInstance;
private Entity currentEntity;
OutputTableModel tableModel;
private final ArrayList<Object> entries = new ArrayList<>();
public OutputBox() {
super( "Output Viewer" );
setDefaultCloseOperation(FrameBox.DISPOSE_ON_CLOSE);
addWindowListener(FrameBox.getCloseListener("ShowOutputViewer"));
tableModel = new OutputTableModel();
OutputTable table = new OutputTable(tableModel);
JScrollPane scrollPane = new JScrollPane(table);
getContentPane().add( scrollPane );
setLocation(GUIFrame.COL3_START, GUIFrame.LOWER_START);
setSize(GUIFrame.COL3_WIDTH, GUIFrame.LOWER_HEIGHT);
}
/**
* Returns the only instance of the property box
*/
public synchronized static OutputBox getInstance() {
if (myInstance == null)
myInstance = new OutputBox();
return myInstance;
}
@Override
public void setEntity( Entity entity ) {
currentEntity = entity;
if (currentEntity == null) {
setTitle("Output Viewer");
entries.clear();
return;
}
setTitle("Output Viewer - " + currentEntity.getName());
// Build up the row list, leaving extra rows for entity names
Class<?> currClass = null;
entries.clear();
ArrayList<OutputHandle> handles = OutputHandle.getOutputHandleList(currentEntity);
for (OutputHandle h : handles) {
Class<?> klass = h.getDeclaringClass();
if (currClass != klass) {
// This is the first time we've seen this class, add a place holder row
currClass = klass;
entries.add(klass);
}
entries.add(h);
}
}
@Override
public void updateValues(double simTime) {
if (tableModel == null) return;
tableModel.simTime = simTime;
tableModel.fireTableDataChanged();
}
private synchronized static void killInstance() {
myInstance = null;
}
@Override
public void dispose() {
killInstance();
super.dispose();
}
private class OutputTable extends JTable {
public OutputTable(TableModel model) {
super(model);
setDefaultRenderer(Object.class, colRenderer);
getColumnModel().getColumn(0).setWidth(150);
getColumnModel().getColumn(1).setWidth(100);
this.getTableHeader().setFont(FrameBox.boldFont);
this.getTableHeader().setReorderingAllowed(false);
}
@Override
public String getToolTipText(MouseEvent event) {
Point p = event.getPoint();
int row = rowAtPoint(p);
if (currentEntity == null ||
row >= entries.size() ||
entries.get(row) instanceof Class) {
return null;
}
OutputHandle output = (OutputHandle)entries.get(row);
return GUIFrame.formatOutputToolTip(output.getName(), output.getDescription());
}
@Override
public void doLayout() {
FrameBox.fitTableToLastColumn(this);
}
}
private class OutputTableModel extends AbstractTableModel {
double simTime = 0.0d;
@Override
public int getColumnCount() {
return 2;
}
@Override
public String getColumnName(int column) {
switch (column) {
case 0: return "Output";
case 1: return "Value";
}
return "Unknown";
}
@Override
public int getRowCount() {
return entries.size();
}
@Override
public Object getValueAt(int row, int col) {
Object entry = entries.get(row);
switch (col) {
case 0:
if (entry instanceof Class)
return String.format("<HTML><B>%s</B></HTML>", ((Class<?>)entry).getSimpleName());
return String.format(" %s", ((OutputHandle)entry).getName());
case 1:
if (entry instanceof Class)
return "";
try {
// Determine the preferred unit
OutputHandle out = (OutputHandle)entry;
Class<? extends Unit> ut = out.getUnitType();
double factor = Unit.getDisplayedUnitFactor(ut);
// Select the appropriate format
String fmt = "%s";
if (out.isNumericValue()) {
if (out.isIntegerValue() && out.getUnitType() == DimensionlessUnit.class) {
fmt = "%.0f";
}
else {
fmt = "%g";
}
}
// Evaluate the output
StringBuilder sb = new StringBuilder();
sb.append(InputAgent.getValueAsString(out, simTime, fmt, factor));
// Append the appropriate unit
if (ut != Unit.class && ut != DimensionlessUnit.class) {
String unitString = Unit.getDisplayedUnit(ut);
sb.append(Input.SEPARATOR).append(unitString);
}
return sb.toString();
}
catch (Throwable e) {
return "Cannot evaluate";
}
default:
assert false;
return null;
}
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return false;
}
}
}