/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2015 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 static com.romraider.Version.ABOUT_ICON;
import static com.romraider.Version.BUILDNUMBER;
import static com.romraider.Version.ECU_DEFS_URL;
import static com.romraider.Version.PRODUCT_NAME;
import static com.romraider.Version.SUPPORT_URL;
import static com.romraider.Version.VERSION;
import static javax.swing.JOptionPane.CANCEL_OPTION;
import static javax.swing.JOptionPane.ERROR_MESSAGE;
import static javax.swing.JOptionPane.INFORMATION_MESSAGE;
import static javax.swing.JOptionPane.showConfirmDialog;
import static javax.swing.JOptionPane.showMessageDialog;
import static javax.swing.WindowConstants.DISPOSE_ON_CLOSE;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import javax.swing.ButtonGroup;
import javax.swing.JFileChooser;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JSeparator;
import com.romraider.Settings;
import com.romraider.editor.ecu.ECUEditor;
import com.romraider.editor.ecu.ECUEditorManager;
import com.romraider.maps.Rom;
import com.romraider.maps.Table;
import com.romraider.net.BrowserControl;
import com.romraider.ramtune.test.RamTuneTestApp;
import com.romraider.util.SettingsManager;
public class ECUEditorMenuBar extends JMenuBar implements ActionListener {
private static final long serialVersionUID = -4777040428837855236L;
private final JMenu fileMenu = new JMenu("File");
private final JMenuItem openImage = new JMenuItem("Open Image...");
private final JMenuItem openImages = new JMenuItem("Open Image(s)...");
private final JMenuItem saveImage = new JMenuItem("Save Image As...");
private final JMenuItem saveAsRepository = new JMenuItem("Save Image As Repository...");
private final JMenuItem refreshImage = new JMenuItem("Refresh Image");
private final JMenuItem closeImage = new JMenuItem("Close Image");
private final JMenuItem closeAll = new JMenuItem("Close All Images");
private final JMenuItem exit = new JMenuItem("Exit");
private final JMenu definitionMenu = new JMenu("ECU Definitions");
private final JMenuItem defManager = new JMenuItem("ECU Definition Manager...");
private final JMenuItem editDefinition = new JMenuItem("Edit ECU Definitions...");
private final JMenuItem updateDefinition = new JMenuItem("Get ECU Definitions...");
private final JMenu editMenu = new JMenu("Edit");
private final JMenuItem settings = new JMenuItem(PRODUCT_NAME + " Settings...");
private final JMenuItem compareImages = new JMenuItem("Compare Images...");
private final JMenu convertRom = new JMenu("Convert Image");
private final JMenuItem convertIncrease = new JMenuItem("160KB --> 192KB...");
private final JMenuItem convertDecrease = new JMenuItem("192KB --> 160KB...");
private final ButtonGroup convertGroup = new ButtonGroup();
private final JMenu viewMenu = new JMenu("View");
private final JMenuItem romProperties = new JMenuItem("ECU Image Properties");
private final ButtonGroup levelGroup = new ButtonGroup();
private final JMenu levelMenu = new JMenu("User Level");
private final JRadioButtonMenuItem level1 = new JRadioButtonMenuItem("1 Beginner");
private final JRadioButtonMenuItem level2 = new JRadioButtonMenuItem("2 Intermediate");
private final JRadioButtonMenuItem level3 = new JRadioButtonMenuItem("3 Advanced");
private final JRadioButtonMenuItem level4 = new JRadioButtonMenuItem("4 Highest");
private final JRadioButtonMenuItem level5 = new JRadioButtonMenuItem("5 Debug Mode");
private final JMenu loggerMenu = new JMenu("Logger");
private final JMenuItem openLogger = new JMenuItem("Launch Logger...");
private final JMenu ramTuneMenu = new JMenu("Tools");
private final JMenuItem launchRamTuneTestApp = new JMenuItem("Launch Test App...");
private final JMenu helpMenu = new JMenu("Help");
private final JMenuItem about = new JMenuItem("About " + PRODUCT_NAME);
public ECUEditorMenuBar() {
// file menu items
add(fileMenu);
fileMenu.setMnemonic('F');
fileMenu.add(openImage);
openImage.addActionListener(this);
openImage.setMnemonic('O');
//fileMenu.add(openImages);
//openImages.addActionListener(this);
//openImages.setMnemonic('I');
fileMenu.add(saveImage);
saveImage.addActionListener(this);
saveImage.setMnemonic('S');
fileMenu.add(saveAsRepository);
saveAsRepository.setMnemonic('D');
saveAsRepository.addActionListener(this);
fileMenu.add(refreshImage);
refreshImage.addActionListener(this);
refreshImage.setMnemonic('R');
fileMenu.add(new JSeparator());
fileMenu.add(closeImage);
closeImage.addActionListener(this);
closeImage.setMnemonic('C');
//fileMenu.add(closeAll);
//closeAll.addActionListener(this);
//closeAll.setMnemonic('A');
fileMenu.add(new JSeparator());
fileMenu.add(exit);
exit.addActionListener(this);
exit.setMnemonic('X');
// edit menu items
add(editMenu);
editMenu.setMnemonic('E');
editMenu.add(settings);
settings.addActionListener(this);
settings.setMnemonic('S');
editMenu.add(compareImages);
compareImages.addActionListener(this);
compareImages.setMnemonic('C');
editMenu.add(convertRom);
convertRom.setMnemonic('O');
convertRom.add(convertIncrease);
convertIncrease.addActionListener(this);
convertIncrease.setMnemonic('I');
convertRom.add(convertDecrease);
convertDecrease.addActionListener(this);
convertDecrease.setMnemonic('D');
convertGroup.add(convertIncrease);
convertGroup.add(convertDecrease);
// ecu def menu items
add(definitionMenu);
definitionMenu.setMnemonic('D');
definitionMenu.add(defManager);
defManager.addActionListener(this);
defManager.setMnemonic('D');
definitionMenu.add(updateDefinition);
updateDefinition.addActionListener(this);
updateDefinition.setMnemonic('U');
//definitionMenu.add(editDefinition);
//editDefinition.setMnemonic('E');
//editDefinition.addActionListener(this);
// view menu items
add(viewMenu);
viewMenu.setMnemonic('V');
viewMenu.add(romProperties);
romProperties.addActionListener(this);
romProperties.setMnemonic('P');
viewMenu.add(levelMenu);
levelMenu.setMnemonic('U');
levelMenu.add(level1);
level1.addActionListener(this);
level1.setMnemonic('1');
levelMenu.add(level2);
level2.addActionListener(this);
level2.setMnemonic('2');
levelMenu.add(level3);
level3.addActionListener(this);
level3.setMnemonic('3');
levelMenu.add(level4);
level4.addActionListener(this);
level4.setMnemonic('4');
levelMenu.add(level5);
level5.addActionListener(this);
level5.setMnemonic('5');
levelGroup.add(level1);
levelGroup.add(level2);
levelGroup.add(level3);
levelGroup.add(level4);
levelGroup.add(level5);
// select correct userlevel button
if (getSettings().getUserLevel() == 1) {
level1.setSelected(true);
} else if (getSettings().getUserLevel() == 2) {
level2.setSelected(true);
} else if (getSettings().getUserLevel() == 3) {
level3.setSelected(true);
} else if (getSettings().getUserLevel() == 4) {
level4.setSelected(true);
} else if (getSettings().getUserLevel() == 5) {
level5.setSelected(true);
}
// logger menu items
add(loggerMenu);
loggerMenu.setMnemonic('L');
loggerMenu.add(openLogger);
openLogger.addActionListener(this);
openLogger.setMnemonic('O');
// ramtune menu items
add(ramTuneMenu);
ramTuneMenu.setMnemonic('R');
ramTuneMenu.add(launchRamTuneTestApp);
launchRamTuneTestApp.addActionListener(this);
launchRamTuneTestApp.setMnemonic('L');
// help menu items
add(helpMenu);
helpMenu.setMnemonic('H');
helpMenu.add(about);
about.addActionListener(this);
about.setMnemonic('A');
updateMenu();
}
public void updateMenu() {
String file = getLastSelectedRomFileName();
if ("".equals(file)) {
saveImage.setEnabled(false);
saveAsRepository.setEnabled(false);
closeImage.setEnabled(false);
//closeAll.setEnabled(false);
romProperties.setEnabled(false);
saveImage.setText("Save As...");
saveAsRepository.setText("Save As Repository...");
compareImages.setEnabled(false);
convertRom.setEnabled(false);
} else {
saveImage.setEnabled(true);
saveAsRepository.setEnabled(true);
closeImage.setEnabled(true);
//closeAll.setEnabled(true);
romProperties.setEnabled(true);
saveImage.setText("Save " + file + " As...");
saveAsRepository.setText("Save "+ file +" As Repository...");
compareImages.setEnabled(true);
convertRom.setEnabled(true);
}
refreshImage.setText("Refresh " + file);
closeImage.setText("Close " + file);
romProperties.setText(file + "Properties");
int lastSelectedRomSize = 0;
Rom lastSelectedRom = ECUEditorManager.getECUEditor().getLastSelectedRom();
if(null != lastSelectedRom) {
lastSelectedRomSize = lastSelectedRom.getRealFileSize();
}
if(Settings.SIXTEENBIT_SMALL_SIZE == lastSelectedRomSize) {
convertIncrease.setEnabled(true);
convertDecrease.setEnabled(false);
} else if (Settings.SIXTEENBIT_LARGE_SIZE == lastSelectedRomSize) {
convertIncrease.setEnabled(false);
convertDecrease.setEnabled(true);
} else {
convertIncrease.setEnabled(false);
convertDecrease.setEnabled(false);
}
openImages.setEnabled(false);
editDefinition.setEnabled(false);
revalidate();
}
@Override
public void actionPerformed(ActionEvent e) {
ECUEditor parent = ECUEditorManager.getECUEditor();
if (e.getSource() == openImage) {
try {
openImageDialog();
} catch (Exception ex) {
showMessageDialog(parent,
new DebugPanel(ex, getSettings().getSupportURL()), "Exception", ERROR_MESSAGE);
}
} else if (e.getSource() == openImages) {
try {
openImagesDialog();
} catch (Exception ex) {
showMessageDialog(parent,
new DebugPanel(ex, getSettings().getSupportURL()), "Exception", ERROR_MESSAGE);
}
} else if (e.getSource() == saveImage) {
try {
this.saveImage();
} catch (Exception ex) {
showMessageDialog(parent,
new DebugPanel(ex, getSettings().getSupportURL()), "Exception", ERROR_MESSAGE);
}
} else if (e.getSource() == saveAsRepository) {
try {
this.saveAsRepository();
} catch(Exception ex) {
showMessageDialog(parent,
new DebugPanel(ex, getSettings().getSupportURL()), "Exception", ERROR_MESSAGE);
}
} else if (e.getSource() == closeImage) {
parent.closeImage();
} else if (e.getSource() == closeAll) {
parent.closeAllImages();
} else if (e.getSource() == exit) {
parent.handleExit();
System.exit(0);
} else if (e.getSource() == romProperties) {
showMessageDialog(parent, new RomPropertyPanel(parent.getLastSelectedRom()),
parent.getLastSelectedRom().getRomIDString() + " Properties", INFORMATION_MESSAGE);
} else if (e.getSource() == refreshImage) {
try {
refreshImage();
} catch (Exception ex) {
showMessageDialog(parent, new DebugPanel(ex,
getSettings().getSupportURL()), "Exception", ERROR_MESSAGE);
}
} else if (e.getSource() == settings) {
SettingsForm form = new SettingsForm();
form.setLocationRelativeTo(parent);
form.setVisible(true);
} else if (e.getSource() == compareImages){
CompareImagesForm form = new CompareImagesForm(parent.getImages(), parent.getIconImage());
form.setLocationRelativeTo(parent);
form.setVisible(true);
} else if (e.getSource() == convertIncrease) {
try {
increaseRomSize();
refreshImage();
} catch (Exception ex) {
showMessageDialog(parent,
new DebugPanel(ex, getSettings().getSupportURL()), "Exception", ERROR_MESSAGE);
}
} else if (e.getSource() == convertDecrease) {
try {
decreaseRomSize();
refreshImage();
} catch (Exception ex) {
showMessageDialog(parent,
new DebugPanel(ex, getSettings().getSupportURL()), "Exception", ERROR_MESSAGE);
}
} else if (e.getSource() == defManager) {
DefinitionManager form = new DefinitionManager();
form.setLocationRelativeTo(parent);
form.setVisible(true);
} else if (e.getSource() == level1) {
parent.setUserLevel(1);
} else if (e.getSource() == level2) {
parent.setUserLevel(2);
} else if (e.getSource() == level3) {
parent.setUserLevel(3);
} else if (e.getSource() == level4) {
parent.setUserLevel(4);
} else if (e.getSource() == level5) {
parent.setUserLevel(5);
} else if (e.getSource() == openLogger) {
parent.launchLogger();
} else if (e.getSource() == updateDefinition) {
BrowserControl.displayURL(ECU_DEFS_URL);
} else if (e.getSource() == launchRamTuneTestApp) {
RamTuneTestApp.startTestApp(DISPOSE_ON_CLOSE);
} else if (e.getSource() == about) {
//TODO: change this to use com.romraider.swing.menubar.action.AboutAction
String message = PRODUCT_NAME + " - ECU Editor\n"
+ "Version: " + VERSION + "\n"
+ "Build #: " + BUILDNUMBER + "\n"
+ SUPPORT_URL;
String title = "About " + PRODUCT_NAME;
showMessageDialog(parent, message, title, INFORMATION_MESSAGE, ABOUT_ICON);
}
}
public void refreshImage() throws Exception {
ECUEditor parent = ECUEditorManager.getECUEditor();
if (parent.getLastSelectedRom() != null) {
File file = parent.getLastSelectedRom().getFullFileName();
parent.closeImage();
parent.openImage(file);
}
}
public void openImageDialog() throws Exception {
ECUEditor parent = ECUEditorManager.getECUEditor();
JFileChooser fc = new JFileChooser(SettingsManager.getSettings().getLastImageDir());
fc.setFileFilter(new ECUImageFilter());
fc.setDialogTitle("Open Image");
if (fc.showOpenDialog(parent) == JFileChooser.APPROVE_OPTION) {
parent.openImage(fc.getSelectedFile());
SettingsManager.getSettings().setLastImageDir(fc.getCurrentDirectory());
}
}
public void openImagesDialog() throws Exception {
ECUEditor parent = ECUEditorManager.getECUEditor();
JFileChooser fc = new JFileChooser(getSettings().getLastImageDir());
fc.setFileFilter(new ECUImageFilter());
fc.setMultiSelectionEnabled(true);
fc.setDialogTitle("Open Image(s)");
if(fc.showOpenDialog(parent) == JFileChooser.APPROVE_OPTION) {
parent.openImages(fc.getSelectedFiles());
SettingsManager.getSettings().setLastImageDir(fc.getCurrentDirectory());
}
}
public void saveImage() throws Exception {
Rom lastSelectedRom = ECUEditorManager.getECUEditor().getLastSelectedRom();
if (lastSelectedRom != null) {
File selectedFile = getImageOutputFile();
if(null != selectedFile){
byte[] output = lastSelectedRom.saveFile();
this.writeImage(output, selectedFile);
}
}
}
private File getImageOutputFile() throws Exception {
ECUEditor parent = ECUEditorManager.getECUEditor();
JFileChooser fc = new JFileChooser(SettingsManager.getSettings().getLastImageDir());
fc.setFileFilter(new ECUImageFilter());
if (fc.showSaveDialog(parent) == JFileChooser.APPROVE_OPTION) {
File selectedFile = fc.getSelectedFile();
if (selectedFile.exists()) {
int option = showConfirmDialog(parent, selectedFile.getName() + " already exists! Overwrite?");
// option: 0 = Cancel, 1 = No
if (option == CANCEL_OPTION || option == 1) {
return null;
}
}
return selectedFile;
}
return null;
}
private void writeImage(byte[] output, File selectedFile) throws Exception {
ECUEditor parent = ECUEditorManager.getECUEditor();
FileOutputStream fos = new FileOutputStream(selectedFile);
try {
fos.write(output);
} finally {
fos.close();
}
parent.getLastSelectedRom().setFullFileName(selectedFile.getAbsoluteFile());
parent.setLastSelectedRom(parent.getLastSelectedRom());
SettingsManager.getSettings().setLastImageDir(selectedFile.getParentFile());
}
private File getRepositoryOutputDir() {
JFileChooser fc = new JFileChooser();
fc.setCurrentDirectory(getSettings().getLastRepositoryDir());
fc.setDialogTitle("Select Repository Directory");
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
// disable the "All files" option
fc.setAcceptAllFileFilterUsed(false);
if (fc.showSaveDialog(ECUEditorManager.getECUEditor()) == JFileChooser.APPROVE_OPTION) {
File selectedDir = fc.getSelectedFile();
if (selectedDir.exists()) {
int option = showConfirmDialog(ECUEditorManager.getECUEditor(), selectedDir.getName() + " already exists! Overwrite?");
// option: 0 = Cancel, 1 = No
if (option == CANCEL_OPTION || option == 1) {
return null;
}
}
return selectedDir;
}
return null;
}
private void saveAsRepository() throws Exception {
File selectedDir = getRepositoryOutputDir();
String separator = System.getProperty("file.separator");
if(null != selectedDir) {
for(TableTreeNode treeNode : ECUEditorManager.getECUEditor().getLastSelectedRom().getTableNodes())
{
Table table = treeNode.getTable();
String category = table.getCategory();
String tableName = table.getName();
String tableDirString = selectedDir.getAbsolutePath() + separator + category;
File tableDir = new File(tableDirString.replace('/', '-'));
tableDir.mkdirs();
String tableFileString = tableDir.getAbsolutePath() + separator + tableName+".txt";
File tableFile = new File(tableFileString.replace('/', '-'));
if(tableFile.exists())
{
tableFile.delete();
}
tableFile.createNewFile();
StringBuffer tableData = table.getTableAsString();
BufferedWriter out = new BufferedWriter(new FileWriter(tableFile));
try {
out.write(tableData.toString());
} finally {
try {
out.close();
} catch(Exception ex) {
;// Do Nothing.
}
}
}
getSettings().setLastRepositoryDir(selectedDir);
}
}
private void increaseRomSize() throws Exception{
Rom lastSelectedRom = ECUEditorManager.getECUEditor().getLastSelectedRom();
if (lastSelectedRom != null) {
File selectedFile = getImageOutputFile();
if(null != selectedFile){
if(lastSelectedRom.getRealFileSize() != Settings.SIXTEENBIT_SMALL_SIZE)
{
showMessageDialog(ECUEditorManager.getECUEditor(), "Error converting image. Image size is invalid.");
} else {
byte[] output = lastSelectedRom.saveFile();
byte[] incOutput = new byte[Settings.SIXTEENBIT_LARGE_SIZE];
System.arraycopy(output, 0, incOutput, 0, Settings.SIXTEENBIT_START_ADDRESS);
System.arraycopy(output, Settings.SIXTEENBIT_START_ADDRESS, incOutput, Settings.SIXTEENBIT_END_ADDRESS, Settings.SIXTEENBIT_SEGMENT_SIZE);
for(int i = Settings.SIXTEENBIT_START_ADDRESS; i < Settings.SIXTEENBIT_END_ADDRESS; i++) {
// Fill space.
incOutput[i] = Settings.SIXTEENBIT_SEGMENT_VALUE;
}
this.writeImage(incOutput, selectedFile);
}
}
}
}
private void decreaseRomSize() throws Exception {
Rom lastSelectedRom = ECUEditorManager.getECUEditor().getLastSelectedRom();
if (lastSelectedRom != null) {
File selectedFile = getImageOutputFile();
if(null != selectedFile){
if(lastSelectedRom.getRealFileSize() != Settings.SIXTEENBIT_LARGE_SIZE)
{
showMessageDialog(ECUEditorManager.getECUEditor(), "Error converting image. Image size is invalid.");
} else {
byte[] output =lastSelectedRom.saveFile();
byte[] decOutput = new byte[Settings.SIXTEENBIT_SMALL_SIZE];
System.arraycopy(output, 0, decOutput, 0, Settings.SIXTEENBIT_START_ADDRESS);
System.arraycopy(output, Settings.SIXTEENBIT_END_ADDRESS, decOutput, Settings.SIXTEENBIT_START_ADDRESS, Settings.SIXTEENBIT_SEGMENT_SIZE);
this.writeImage(decOutput, selectedFile);
}
}
}
}
private String getLastSelectedRomFileName() {
Rom lastSelectedRom = ECUEditorManager.getECUEditor().getLastSelectedRom();
return lastSelectedRom == null ? "" : lastSelectedRom.getFileName() + " ";
}
private Settings getSettings() {
return SettingsManager.getSettings();
}
}