/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2012 RomRaider.com
*
* This program 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 2 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package com.romraider.swing;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListCellRenderer;
import javax.swing.ListSelectionModel;
import javax.swing.border.EmptyBorder;
import javax.swing.border.EtchedBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import com.romraider.Settings;
import com.romraider.editor.ecu.ECUEditorManager;
import com.romraider.maps.Rom;
import com.romraider.maps.Table;
public class CompareImagesForm extends JFrame implements ActionListener {
private static final long serialVersionUID = -8937472127815934398L;
private final Vector<Rom> roms;
private final JPanel contentPane;
private final JComboBox comboBoxImageLeft;
private final JComboBox comboBoxImageRight;
private final JButton btnCompare;
private final JList listChanges;
private final DefaultListModel listModelChanges = new DefaultListModel();
private final ChangeListCellRenderer changeRenderer = new ChangeListCellRenderer();
private final JScrollPane scrollPaneResults;
private final JLabel lblImageResultString;
public CompareImagesForm(Vector<Rom> roms, Image parentImage) {
this.setIconImage(parentImage);
setResizable(false);
this.roms = roms;
setTitle("Compare Images");
setBounds(100, 100, 600, 450);
this.contentPane = new JPanel();
this.contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(this.contentPane);
JLabel lblSelectImages = new JLabel("Selected Images");
lblSelectImages.setBounds(10, 11, 79, 14);
contentPane.setLayout(null);
JPanel panelImageSelector = new JPanel();
panelImageSelector.setBounds(10, 36, 574, 94);
panelImageSelector.setBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null));
panelImageSelector.setLayout(null);
this.comboBoxImageLeft = new JComboBox();
this.comboBoxImageLeft.setBounds(10, 7, 554, 20);
this.comboBoxImageLeft.setToolTipText("Select an image to compare.");
this.comboBoxImageLeft.setRenderer( new ComboBoxRenderer() );
panelImageSelector.add(this.comboBoxImageLeft);
this.comboBoxImageRight = new JComboBox();
this.comboBoxImageRight.setBounds(10, 32, 554, 20);
this.comboBoxImageRight.setToolTipText("Select an image to compare.");
this.comboBoxImageRight.setRenderer( new ComboBoxRenderer() );
panelImageSelector.add(this.comboBoxImageRight);
this.btnCompare = new JButton("Compare");
this.btnCompare.addActionListener(this);
this.btnCompare.setBounds(10, 64, 89, 23);
panelImageSelector.add(this.btnCompare);
this.contentPane.add(panelImageSelector);
this.contentPane.add(lblSelectImages);
JLabel lblResults = new JLabel("Results:");
lblResults.setBounds(10, 141, 46, 14);
contentPane.add(lblResults);
lblImageResultString = new JLabel("Compare images...");
lblImageResultString.setBounds(66, 141, 518, 14);
contentPane.add(lblImageResultString);
scrollPaneResults = new JScrollPane();
scrollPaneResults.setBounds(10, 166, 574, 245);
contentPane.add(scrollPaneResults);
this.listChanges = new JList(this.listModelChanges);
scrollPaneResults.setViewportView(this.listChanges);
listChanges.setCellRenderer(changeRenderer);
listChanges.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
listChanges.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent arg0) {
if (!arg0.getValueIsAdjusting()) {
ListItem selectedTableName = (ListItem) listChanges.getSelectedValue();
String tableName = selectedTableName.getValue();
Rom leftRom = (Rom) comboBoxImageLeft.getSelectedItem();
Rom rightRom = (Rom) comboBoxImageRight.getSelectedItem();
// Display Tables
TableTreeNode leftNode = findAndShowTable(leftRom, tableName);
TableTreeNode rightNode = findAndShowTable(rightRom, tableName);
// Set Comparison
if(leftNode != null && rightNode != null) {
leftNode.getFrame().compareByTable(rightNode.getTable());
// Update menu bar
for(int i = 0; i< leftNode.getFrame().getTableMenuBar().getSimilarOpenTables().getItemCount(); i++) {
JMenuItem leftItem = leftNode.getFrame().getTableMenuBar().getSimilarOpenTables().getItem(i);
String romFileName = leftItem.getText();
if(rightRom.getFileName().equalsIgnoreCase(romFileName)) {
leftItem.setSelected(true);
break;
}
}
}
}
}
});
populateComboBoxes();
}
private TableTreeNode findAndShowTable(Rom rom, String tableName) {
for(TableTreeNode node : rom.getTableNodes()) {
if(node != null && node.getTable().getName().equals(tableName)){
ECUEditorManager.getECUEditor().displayTable(node.getFrame());
return node;
}
}
return null;
}
public void populateComboBoxes()
{
for(int i=0; i<roms.size(); i++) {
Rom curRom = roms.get(i);
comboBoxImageLeft.addItem(curRom);
comboBoxImageRight.addItem(curRom);
}
if(comboBoxImageRight.getItemCount() > 1) {
comboBoxImageRight.setSelectedIndex(1);
}
}
public void compareTables(Rom left, Rom right)
{
listModelChanges.clear();
int equal = 0;
int different = 0;
int missing = 0;
for(TableTreeNode leftNode : left.getTableNodes())
{
Boolean found = false;
Table leftTable = leftNode.getTable();
for(TableTreeNode rightNode : right.getTableNodes())
{
Table rightTable = rightNode.getTable();
if(leftTable.getName().equalsIgnoreCase(rightTable.getName()))
{
if(leftTable.equals(rightTable)) {
equal++;
listModelChanges.addElement(new ListItem(1, leftTable.getName()));
}
else {
different++;
listModelChanges.addElement(new ListItem(2, leftTable.getName()));
}
found = true;
break;
}
}
if(!found) {
missing++;
listModelChanges.addElement(new ListItem(3, leftTable.getName()));
}
}
// Check if rightTables has tables that do not exist in left table.
for(TableTreeNode rightFrame : right.getTableNodes()) {
Boolean found = false;
for(TableTreeNode leftFrame : left.getTableNodes()) {
if(leftFrame.getTable().getName().equalsIgnoreCase(rightFrame.getTable().getName()))
{
found = true;
break;
}
}
if(!found) {
missing++;
listModelChanges.addElement(new ListItem(3, rightFrame.getTable().getName()));
}
}
// Fill out the result string.
if(equal > 0 && different == 0 && missing == 0) {
lblImageResultString.setText("Images are equal.");
lblImageResultString.setForeground(Settings.TABLE_EQUAL_COLOR);
} else if(different > 0) {
lblImageResultString.setText("Images are NOT equal. Equal Tables: "+equal+", Changed Tables: "+different+", Missing Tables: "+missing);
lblImageResultString.setForeground(Settings.TABLE_DIFFERENT_COLOR);
} else {
lblImageResultString.setText("Images are NOT equal. Equal Tables: "+equal+", Changed Tables: "+different+", Missing Tables: "+missing);
lblImageResultString.setForeground(Settings.TABLE_MISSING_COLOR);
}
// Check if the list has items.
if(listModelChanges.size() < 1)
{
listModelChanges.addElement(new ListItem(0, "No tables are equal, different, or missing."));
lblImageResultString.setText("Unable to compare images.");
lblImageResultString.setForeground(Color.RED);
return;
}
// Add list items for 0 counts.
if(equal == 0)
{
listModelChanges.addElement(new ListItem(1, "No Equal Tables."));
}
if(different == 0)
{
listModelChanges.addElement(new ListItem(2, "No Changed Tables."));
}
if(missing == 0)
{
listModelChanges.addElement(new ListItem(3, "No Missing Tables."));
}
}
@Override
public void actionPerformed(ActionEvent e) {
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
if (e.getSource() == this.btnCompare) {
if(this.comboBoxImageLeft.getItemCount() > 0 && this.comboBoxImageRight.getItemCount() > 0)
{
Rom leftRom = (Rom)this.comboBoxImageLeft.getSelectedItem();
Rom rightRom = (Rom)this.comboBoxImageRight.getSelectedItem();
if(leftRom != null && rightRom != null)
{
compareTables(leftRom, rightRom);
}
}
}
this.setCursor(Cursor.getDefaultCursor());
}
class ComboBoxRenderer extends JLabel implements ListCellRenderer
{
private static final long serialVersionUID = 831689602429105854L;
public ComboBoxRenderer() {
setOpaque(true);
setHorizontalAlignment(LEFT);
setVerticalAlignment(CENTER);
}
@Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
if(isSelected) {
setBackground(list.getSelectionBackground());
setForeground(list.getSelectionForeground());
} else {
setBackground(list.getBackground());
setForeground(list.getForeground());
}
if(value != null)
{
// Set the text to the rom file name.
Rom rom = (Rom)value;
setText(rom.getFileName());
setFont(list.getFont());
}
return this;
}
}
class ChangeListCellRenderer extends JLabel implements ListCellRenderer {
private static final long serialVersionUID = -3645192077787635239L;
public ChangeListCellRenderer()
{
setOpaque(true);
setHorizontalAlignment(LEFT);
setVerticalAlignment(CENTER);
}
@Override
public Component getListCellRendererComponent(JList paramList, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
// Set the background color.
if(isSelected) {
setBackground(paramList.getSelectionBackground());
} else {
setBackground(paramList.getBackground());
}
// Set the foreground color based on the item type.
ListItem item = (ListItem)value;
switch(item.getType()) {
case 1:
// equal - default green
setForeground(Settings.TABLE_EQUAL_COLOR);
break;
case 2:
// different - default red
setForeground(Settings.TABLE_DIFFERENT_COLOR);
break;
case 3:
// missing - default yellow
setForeground(Settings.TABLE_MISSING_COLOR);
break;
default:
setForeground(paramList.getForeground());
break;
}
setText(item.getValue());
return this;
}
}
class ListItem {
private int type;
private String value;
public ListItem(int type, String value) {
this.type = type;
this.value = value;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
}