/*******************************************************************************
* This file is part of logisim-evolution.
*
* logisim-evolution is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* logisim-evolution 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with logisim-evolution. If not, see <http://www.gnu.org/licenses/>.
*
* Original code by Carl Burch (http://www.cburch.com), 2011.
* Subsequent modifications by :
* + Haute École Spécialisée Bernoise
* http://www.bfh.ch
* + Haute École du paysage, d'ingénierie et d'architecture de Genève
* http://hepia.hesge.ch/
* + Haute École d'Ingénierie et de Gestion du Canton de Vaud
* http://www.heig-vd.ch/
* The project is currently maintained by :
* + REDS Institute - HEIG-VD
* Yverdon-les-Bains, Switzerland
* http://reds.heig-vd.ch
*******************************************************************************/
package com.cburch.logisim.gui.main;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Comparator;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import com.cburch.logisim.circuit.Circuit;
import com.cburch.logisim.file.FileStatistics;
import com.cburch.logisim.file.LogisimFile;
import com.cburch.logisim.tools.Library;
import com.cburch.logisim.util.TableSorter;
public class StatisticsDialog extends JDialog implements ActionListener {
private static class CompareString implements Comparator<String> {
private String[] fixedAtBottom;
public CompareString(String... fixedAtBottom) {
this.fixedAtBottom = fixedAtBottom;
}
public int compare(String a, String b) {
for (int i = fixedAtBottom.length - 1; i >= 0; i--) {
String s = fixedAtBottom[i];
if (a.equals(s))
return b.equals(s) ? 0 : 1;
if (b.equals(s))
return -1;
}
return a.compareToIgnoreCase(b);
}
}
private static class StatisticsTable extends JTable {
private static final long serialVersionUID = 1L;
@Override
public void setBounds(int x, int y, int width, int height) {
super.setBounds(x, y, width, height);
setPreferredColumnWidths(new double[] { 0.45, 0.25, 0.1, 0.1, 0.1 });
}
protected void setPreferredColumnWidths(double[] percentages) {
Dimension tableDim = getPreferredSize();
double total = 0;
for (int i = 0; i < getColumnModel().getColumnCount(); i++) {
total += percentages[i];
}
for (int i = 0; i < getColumnModel().getColumnCount(); i++) {
TableColumn column = getColumnModel().getColumn(i);
double width = tableDim.width * (percentages[i] / total);
column.setPreferredWidth((int) width);
}
}
}
private static class StatisticsTableModel extends AbstractTableModel {
private static final long serialVersionUID = 1L;
private FileStatistics stats;
StatisticsTableModel(FileStatistics stats) {
this.stats = stats;
}
@Override
public Class<?> getColumnClass(int column) {
return column < 2 ? String.class : Integer.class;
}
public int getColumnCount() {
return 5;
}
@Override
public String getColumnName(int column) {
switch (column) {
case 0:
return Strings.get("statsComponentColumn");
case 1:
return Strings.get("statsLibraryColumn");
case 2:
return Strings.get("statsSimpleCountColumn");
case 3:
return Strings.get("statsUniqueCountColumn");
case 4:
return Strings.get("statsRecursiveCountColumn");
default:
return "??"; // should never happen
}
}
public int getRowCount() {
return stats.getCounts().size() + 2;
}
public Object getValueAt(int row, int column) {
List<FileStatistics.Count> counts = stats.getCounts();
int countsLen = counts.size();
if (row < 0 || row >= countsLen + 2)
return "";
FileStatistics.Count count;
if (row < countsLen)
count = counts.get(row);
else if (row == countsLen)
count = stats.getTotalWithoutSubcircuits();
else
count = stats.getTotalWithSubcircuits();
switch (column) {
case 0:
if (row < countsLen) {
return count.getFactory().getDisplayName();
} else if (row == countsLen) {
return Strings.get("statsTotalWithout");
} else {
return Strings.get("statsTotalWith");
}
case 1:
if (row < countsLen) {
Library lib = count.getLibrary();
return lib == null ? "-" : lib.getDisplayName();
} else {
return "";
}
case 2:
return Integer.valueOf(count.getSimpleCount());
case 3:
return Integer.valueOf(count.getUniqueCount());
case 4:
return Integer.valueOf(count.getRecursiveCount());
default:
return ""; // should never happen
}
}
}
public static void show(JFrame parent, LogisimFile file, Circuit circuit) {
FileStatistics stats = FileStatistics.compute(file, circuit);
StatisticsDialog dlog = new StatisticsDialog(parent, circuit.getName(),
new StatisticsTableModel(stats));
dlog.setVisible(true);
}
private static final long serialVersionUID = 1L;
private StatisticsDialog(JFrame parent, String circuitName,
StatisticsTableModel model) {
super(parent, true);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setTitle(Strings.get("statsDialogTitle", circuitName));
JTable table = new StatisticsTable();
TableSorter mySorter = new TableSorter(model, table.getTableHeader());
Comparator<String> comp = new CompareString("",
Strings.get("statsTotalWithout"), Strings.get("statsTotalWith"));
mySorter.setColumnComparator(String.class, comp);
table.setModel(mySorter);
JScrollPane tablePane = new JScrollPane(table);
JButton button = new JButton(Strings.get("statsCloseButton"));
button.addActionListener(this);
JPanel buttonPanel = new JPanel();
buttonPanel.add(button);
Container contents = this.getContentPane();
contents.setLayout(new BorderLayout());
contents.add(tablePane, BorderLayout.CENTER);
contents.add(buttonPanel, BorderLayout.PAGE_END);
this.pack();
Dimension pref = contents.getPreferredSize();
if (pref.width > 750 || pref.height > 550) {
if (pref.width > 750)
pref.width = 750;
if (pref.height > 550)
pref.height = 550;
this.setSize(pref);
}
}
public void actionPerformed(ActionEvent e) {
this.dispose();
}
}