/*
* 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.logger.ecu.ui.swing.menubar.action;
import static javax.swing.JOptionPane.QUESTION_MESSAGE;
import static javax.swing.JOptionPane.YES_NO_OPTION;
import static javax.swing.JOptionPane.showConfirmDialog;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.ToolTipManager;
import javax.swing.border.EmptyBorder;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import com.romraider.logger.ecu.EcuLogger;
import com.romraider.logger.ecu.definition.Module;
import com.romraider.logger.ecu.definition.Transport;
import com.romraider.swing.menubar.action.AbstractAction;
public final class SelectProtocolAction extends AbstractAction {
public SelectProtocolAction(EcuLogger logger) {
super(logger);
}
@Override
public void actionPerformed(ActionEvent actionEvent) {
try {
logger.stopLogging();
new CommSettings();
} catch (Exception e) {
logger.reportError(e);
}
}
private class CommSettings extends JDialog {
private static final long serialVersionUID = -6226102628115868401L;
private final JButton selectButton = new JButton("Select");
private final Map<String, Map<Transport, Collection<Module>>> protocolList;
private TreePath selectedPath;
private CommSettings() {
this.protocolList = logger.getProtocolList();
setTitle("Communications Settings");
setModalityType(ModalityType.APPLICATION_MODAL);
setIconImage(logger.getIconImage());
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
setBounds(
logger.getX() + (logger.getWidth() / 2) - 250,
logger.getY() + 90,
300,
300);
getContentPane().setLayout(new BorderLayout());
final JPanel contentPanel = new JPanel();
contentPanel.setLayout(new BorderLayout());
contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPanel.add(buildTree(), BorderLayout.CENTER);
getContentPane().add(contentPanel, BorderLayout.CENTER);
final JPanel buttonPane = new JPanel();
buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
getContentPane().add(buttonPane, BorderLayout.SOUTH);
selectButton.setEnabled(false);
selectButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
confirmSelection();
}
});
buttonPane.add(selectButton);
getRootPane().setDefaultButton(selectButton);
final JButton cancelButton = new JButton("Cancel");
cancelButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
closeDialog();
}
});
buttonPane.add(cancelButton);
setVisible(true);
}
private Component buildTree() {
final JTree tree = new JTree(buildNodeTree()) {
private static final long serialVersionUID = 4718749407995133513L;
@Override
protected void setExpandedState(TreePath path, boolean state) {
if (state) {
super.setExpandedState(path, state);
}
}
@Override
public String getToolTipText(MouseEvent e) {
if (e != null) {
final TreePath path = super.getPathForLocation(
e.getX(), e.getY());
if (path != null) {
final DefaultMutableTreeNode node = getTreeNode(path);
if (node != null) {
final Object o = node.getUserObject();
if (o instanceof Transport) {
return String.format("%s [%s]",
((Transport) o).getDescription(),
((Transport) o).getId());
}
}
}
else {
return "Select the transport to use under the desired " +
"protocol to query the target control module";
}
}
return null;
}
};
ToolTipManager.sharedInstance().registerComponent(tree);
final DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer();
renderer.setOpenIcon(null);
renderer.setLeafIcon(null);
tree.setCellRenderer(renderer);
tree.setEditable(true);
tree.setRootVisible(true);
tree.setShowsRootHandles(false);
tree.getSelectionModel().setSelectionMode(
TreeSelectionModel.SINGLE_TREE_SELECTION);
final String currentProtocol = logger.getSettings().getLoggerProtocol();
final String currentTransport = logger.getSettings().getTransportProtocol();
for (int i = 0; i < tree.getRowCount(); i++) {
tree.expandRow(i);
final TreePath path = tree.getPathForRow(i);
final DefaultMutableTreeNode node = getTreeNode(path);
final Object o = node.getUserObject();
if (o instanceof Transport) {
final DefaultMutableTreeNode parent =
(DefaultMutableTreeNode) node.getParent();
final String parentName = (String) parent.getUserObject();
final String transportId = ((Transport) o).getId();
if (currentTransport.equalsIgnoreCase(transportId) &&
currentProtocol.equalsIgnoreCase(parentName)) {
tree.setSelectionPath(path);
}
}
}
tree.addTreeSelectionListener(new TreeSelectionListener() {
@Override
public void valueChanged(TreeSelectionEvent e) {
final DefaultMutableTreeNode node =
(DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
if (node != null) {
if (node.isLeaf()) {
selectButton.setEnabled(true);
selectedPath = tree.getSelectionPath();
}
else {
selectButton.setEnabled(false);
}
}
}
});
final JScrollPane scrollPane = new JScrollPane(tree);
return scrollPane;
}
private MutableTreeNode buildNodeTree() {
final DefaultMutableTreeNode root;
root = new DefaultMutableTreeNode("Protocol and Transport Selection");
for (String protocol : protocolList.keySet()) {
final DefaultMutableTreeNode protocolNode =
new DefaultMutableTreeNode(protocol);
root.add(protocolNode);
final Map<Transport, Collection<Module>> transportMap =
protocolList.get(protocol);
final Set<Transport> trasnports = transportMap.keySet();
for (Transport transport : trasnports) {
final DefaultMutableTreeNode transportNode =
new DefaultMutableTreeNode(transport);
protocolNode.add(transportNode);
}
}
return root;
}
private DefaultMutableTreeNode getTreeNode(TreePath path) {
return (DefaultMutableTreeNode) path.getLastPathComponent();
}
private final void confirmSelection() {
final int result = showConfirmDialog(logger,
"Are you sure you want to change the logging protocol?",
"Confirm new selection",
YES_NO_OPTION,
QUESTION_MESSAGE);
if (result == 0) {
final DefaultMutableTreeNode node = getTreeNode(selectedPath);
final Object o = node.getUserObject();
if (o instanceof Transport) {
final DefaultMutableTreeNode parent =
(DefaultMutableTreeNode) node.getParent();
final String parentName = (String) parent.getUserObject();
logger.getSettings().setLoggerProtocol(parentName);
logger.getSettings().setTransportProtocol(((Transport) o).getId());
}
logger.loadLoggerParams();
closeDialog();
}
}
private final void closeDialog() {
setVisible(false);
dispose();
logger.startLogging();
}
}
}