
org.bidib.wizard.mvc.debug.view.DebugInterfaceView Maven / Gradle / Ivy
package org.bidib.wizard.mvc.debug.view;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ListModel;
import javax.swing.SwingUtilities;
import javax.swing.filechooser.FileFilter;
import javax.swing.text.BadLocationException;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.SystemUtils;
import org.bidib.jbidibc.serial.exception.InvalidLibraryException;
import org.bidib.jbidibc.serial.util.PortIdentifierUtils;
import org.bidib.wizard.dialog.FileDialog;
import org.bidib.wizard.locale.Resources;
import org.bidib.wizard.mvc.common.model.CommPort;
import org.bidib.wizard.mvc.common.view.DockKeys;
import org.bidib.wizard.mvc.debug.controller.listener.DebugInterfaceControllerListener;
import org.bidib.wizard.mvc.debug.model.DebugInterfaceModel;
import org.bidib.wizard.mvc.debug.view.listener.DebugInterfaceViewListener;
import org.bidib.wizard.mvc.main.view.menu.BasicPopupMenu;
import org.jdesktop.swingx.prompt.PromptSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.jgoodies.binding.adapter.BasicComponentFactory;
import com.jgoodies.binding.adapter.ComboBoxAdapter;
import com.jgoodies.binding.beans.PropertyAdapter;
import com.jgoodies.binding.beans.PropertyConnector;
import com.jgoodies.binding.list.SelectionInList;
import com.jgoodies.binding.value.ConverterValueModel;
import com.jgoodies.binding.value.ValueModel;
import com.jgoodies.forms.builder.ButtonBarBuilder;
import com.jgoodies.forms.builder.DefaultFormBuilder;
import com.jgoodies.forms.debug.FormDebugPanel;
import com.jgoodies.forms.factories.Borders;
import com.jgoodies.forms.layout.FormLayout;
import com.vlsolutions.swing.docking.DockKey;
import com.vlsolutions.swing.docking.Dockable;
import com.vlsolutions.swing.docking.DockableState;
import com.vlsolutions.swing.docking.DockingDesktop;
import com.vlsolutions.swing.docking.event.DockableStateChangeEvent;
import com.vlsolutions.swing.docking.event.DockableStateChangeListener;
public class DebugInterfaceView implements Dockable {
private static final Logger LOGGER = LoggerFactory.getLogger(DebugInterfaceView.class);
private static final String ENCODED_DIALOG_COLUMN_SPECS =
"pref, 3dlu, 50dlu, 3dlu, pref, 3dlu, pref, 3dlu, fill:pref:grow, 3dlu, pref, 3dlu, pref";
private final Collection listeners = new LinkedList<>();
private final DebugInterfaceModel debugInterfaceModel;
private final DockableStateChangeListener dockableStateChangeListener;
private final JPanel contentPanel;
private ValueModel selectionHolderComPort;
private ValueModel sendTextValueModel;
private ValueModel selectionHolderBaudRate;
private ValueModel sendFileValueModel;
private JTextField sendText;
private JTextField sendFile;
private final JButton connectButton = new JButton(Resources.getString(getClass(), "connect"));
private final JButton disconnectButton = new JButton(Resources.getString(getClass(), "disconnect"));
private final JButton transmitButton = new JButton(Resources.getString(getClass(), "transmit"));
private final JButton transmitFileButton = new JButton(Resources.getString(getClass(), "transmit"));
private final JButton selectFileButton = new JButton(Resources.getString(getClass(), "selectFile"));
private final JTextArea logsArea = new JTextArea();
private SelectionInList commPortSelection;
public DebugInterfaceView(final DockingDesktop desktop, final DebugInterfaceControllerListener listener,
final DebugInterfaceModel debugInterfaceModel) {
DockKeys.DOCKKEY_DEBUG_INTERFACE_VIEW.setName(Resources.getString(getClass(), "title"));
DockKeys.DOCKKEY_DEBUG_INTERFACE_VIEW.setFloatEnabled(true);
DockKeys.DOCKKEY_DEBUG_INTERFACE_VIEW.setAutoHideEnabled(false);
dockableStateChangeListener = new DockableStateChangeListener() {
@Override
public void dockableStateChanged(DockableStateChangeEvent event) {
LOGGER.info("The state has changed, newState: {}, prevState: {}", event.getNewState(),
event.getPreviousState());
DockableState newState = event.getNewState();
if (newState.getDockable().equals(DebugInterfaceView.this) && newState.isClosed()) {
LOGGER.info("The DebugInterfaceView is closed.");
// we are closed
desktop.removeDockableStateChangeListener(dockableStateChangeListener);
if (listener != null) {
LOGGER.info("Close the view.");
listener.viewClosed();
}
}
}
};
desktop.addDockableStateChangeListener(dockableStateChangeListener);
LOGGER.info("Create new DebugInterfaceView");
this.debugInterfaceModel = debugInterfaceModel;
loadPortIdentifiers(debugInterfaceModel);
// create form builder
DefaultFormBuilder dialogBuilder = null;
boolean debugDialog = false;
if (debugDialog) {
JPanel panel = new FormDebugPanel();
dialogBuilder = new DefaultFormBuilder(new FormLayout(ENCODED_DIALOG_COLUMN_SPECS), panel);
}
else {
JPanel panel = new JPanel(new BorderLayout());
dialogBuilder = new DefaultFormBuilder(new FormLayout(ENCODED_DIALOG_COLUMN_SPECS), panel);
}
dialogBuilder.border(Borders.DIALOG);
// add some components
commPortSelection =
new SelectionInList((ListModel) debugInterfaceModel.getCommPortsListModel());
selectionHolderComPort =
new PropertyAdapter(debugInterfaceModel, DebugInterfaceModel.PROPERTY_SELECTED_PORT,
true);
ComboBoxAdapter comboBoxAdapterCommPorts =
new ComboBoxAdapter(commPortSelection, selectionHolderComPort);
JComboBox comboCommPorts = new JComboBox();
comboCommPorts.setModel(comboBoxAdapterCommPorts);
dialogBuilder.append(Resources.getString(getClass(), "selectedPort"), comboCommPorts);
List baudRates = new ArrayList<>();
baudRates.add(Integer.valueOf(19200));
baudRates.add(Integer.valueOf(115200));
selectionHolderBaudRate =
new PropertyAdapter(debugInterfaceModel, DebugInterfaceModel.PROPERTY_BAUDRATE, true);
ComboBoxAdapter comboBoxAdapter = new ComboBoxAdapter(baudRates, selectionHolderBaudRate);
JComboBox comboBaudRate = new JComboBox<>();
comboBaudRate.setModel(comboBoxAdapter);
comboBaudRate.setSelectedIndex(1);
dialogBuilder.append(Resources.getString(getClass(), "selectedBaudRate"), comboBaudRate);
connectButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
fireConnect();
}
});
disconnectButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
fireDisconnect();
}
});
disconnectButton.setEnabled(false);
// prepare the connect and disconnect button
JPanel debugInterfaceActionButtons =
new ButtonBarBuilder().addButton(connectButton).addRelatedGap().addButton(disconnectButton).build();
dialogBuilder.append(debugInterfaceActionButtons);
dialogBuilder.appendRow("3dlu");
dialogBuilder.appendRow("fill:200dlu:grow");
dialogBuilder.nextLine(2);
logsArea.setEditable(false);
logsArea.setFont(new Font("Monospaced", Font.PLAIN, 11));
JScrollPane logsPane = new JScrollPane(logsArea);
logsPane.setAutoscrolls(true);
dialogBuilder.append(logsPane, 13);
dialogBuilder.appendRow("3dlu");
dialogBuilder.appendRow("pref");
dialogBuilder.nextLine(2);
// create the textfield for send message to debug
sendTextValueModel =
new PropertyAdapter(debugInterfaceModel, DebugInterfaceModel.PROPERTY_SEND_TEXT, true);
sendText = BasicComponentFactory.createTextField(sendTextValueModel, false);
sendText.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
fireTransmit();
}
});
PromptSupport.init(Resources.getString(getClass(), "transmitText.prompt"), null, null, sendText);
dialogBuilder.append(Resources.getString(getClass(), "transmitText"), sendText, 9);
dialogBuilder.append(transmitButton);
transmitButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
fireTransmit();
}
});
transmitButton.setEnabled(false);
dialogBuilder.appendRow("3dlu");
dialogBuilder.appendRow("pref");
dialogBuilder.nextLine(2);
// create the textfield for filename
sendFileValueModel =
new PropertyAdapter(debugInterfaceModel, DebugInterfaceModel.PROPERTY_SEND_FILE, true);
final ValueModel sendFileConverterModel =
new ConverterValueModel(sendFileValueModel, new FileStringConverter());
sendFile = BasicComponentFactory.createTextField(sendFileConverterModel, true);
sendFile.setEditable(false);
PromptSupport.init(Resources.getString(getClass(), "transmitFile.prompt"), null, null, sendFile);
dialogBuilder.append(Resources.getString(getClass(), "transmitFile"), sendFile, 7);
dialogBuilder.append(selectFileButton);
selectFileButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
fireSelectFile();
}
});
dialogBuilder.append(transmitFileButton);
transmitFileButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
fireTransmitFile();
}
});
transmitFileButton.setEnabled(false);
// add bindings for enable/disable the send button
PropertyConnector.connect(debugInterfaceModel, DebugInterfaceModel.PROPERTY_TRANSMIT_ENABLED, transmitButton,
"enabled");
PropertyConnector.connect(debugInterfaceModel, DebugInterfaceModel.PROPERTY_TRANSMIT_ENABLED,
transmitFileButton, "enabled");
PropertyConnector.connect(debugInterfaceModel, DebugInterfaceModel.PROPERTY_DISCONNECTED, connectButton,
"enabled");
PropertyConnector.connect(debugInterfaceModel, DebugInterfaceModel.PROPERTY_CONNECTED, disconnectButton,
"enabled");
contentPanel = dialogBuilder.build();
JPopupMenu popupMenu = new BasicPopupMenu();
JMenuItem clearConsole = new JMenuItem(Resources.getString(getClass(), "clear_console"));
clearConsole.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
fireClearConsole();
}
});
popupMenu.add(clearConsole);
logsArea.setComponentPopupMenu(popupMenu);
}
private void fireClearConsole() {
LOGGER.info("clear the console.");
logsArea.setText(null);
}
private void fireConnect() {
for (DebugInterfaceViewListener listener : listeners) {
listener.openConnection();
}
}
private void fireDisconnect() {
for (DebugInterfaceViewListener listener : listeners) {
listener.closeConnection();
}
}
private void fireTransmit() {
for (DebugInterfaceViewListener listener : listeners) {
listener.transmit();
}
// clear the text field
sendText.setText(null);
}
private void fireTransmitFile() {
boolean modal = true;
FileTransferProgressDialog progressDialog = new FileTransferProgressDialog(contentPanel, modal, listeners);
}
private void fireSelectFile() {
final FileDialog dialog = new FileDialog(
contentPanel, FileDialog.OPEN, null, ff) {
@Override
public void approve(String selectedFile) {
File file = new File(selectedFile);
selectedFile = file.getName();
// debugInterfaceModel.setSendFile(null);
debugInterfaceModel.setSendFile(file);
}
};
dialog.showDialog();
}
@Override
public DockKey getDockKey() {
return DockKeys.DOCKKEY_DEBUG_INTERFACE_VIEW;
}
@Override
public Component getComponent() {
return contentPanel;
}
public void addDebugInterfaceViewListener(DebugInterfaceViewListener l) {
listeners.add(l);
}
private int currentLineLen;
public void addLog(final String logMessage) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
int lines = logsArea.getLineCount();
if (lines > 500) {
// remove the first 50 lines
int end = logsArea.getLineEndOffset(/* lines - */50);
logsArea.getDocument().remove(0, end);
}
}
catch (BadLocationException ex) {
LOGGER.warn("Remove some lines from logsArea failed.", ex);
}
int index = logMessage.lastIndexOf("\n");
if (index > 0) {
// check if we have text that is following the line break
if ((logMessage.length() - 1) > index) {
currentLineLen += (logMessage.length() - 1) - index;
}
}
else {
currentLineLen += logMessage.length();
}
// Update and scroll pane to the bottom
logsArea.append(logMessage);
if (currentLineLen > 120) {
// break the line
logsArea.append(SystemUtils.LINE_SEPARATOR);
currentLineLen = 0;
}
logsArea.invalidate();
}
});
}
private static final String SUFFIX_HEX = "hex";
private static final String SUFFIX_EEP = "eep";
private final FileFilter ff = new FileFilter() {
@Override
public boolean accept(File file) {
boolean result = false;
if (file != null) {
if (file.isDirectory()) {
result = true;
}
else if (FilenameUtils.wildcardMatch(file.getName(), "*." + SUFFIX_HEX)) {
result = true;
}
else if (FilenameUtils.wildcardMatch(file.getName(), "*." + SUFFIX_EEP)) {
result = true;
}
}
return result;
}
@Override
public String getDescription() {
return Resources.getString(DebugInterfaceView.class, "filter") + " (*." + SUFFIX_HEX + ",*." + SUFFIX_EEP
+ ")";
}
};
private void loadPortIdentifiers(DebugInterfaceModel model) {
LOGGER.info("Load the comm ports, model: {}", model);
Set commPorts = new HashSet();
try {
// use PortIdentifierUtils because we must load the RXTX libraries
List portIdentifiers = PortIdentifierUtils.getPortIdentifiers();
if (portIdentifiers != null) {
for (String id : portIdentifiers) {
LOGGER.info("Add new CommPort with id: {}", id);
commPorts.add(new CommPort(id));
}
}
}
catch (InvalidLibraryException ex) {
LOGGER
.warn(
"Fetch port identifiers failed. This can be caused because the ext/lib directory of the Java installation contains an old RXTXComm.jar!",
ex);
JOptionPane.showMessageDialog(contentPanel, Resources.getString(DebugInterfaceView.class,
"fetch-port-identifiers-failed",
new Object[] { new File(SystemUtils.getJavaHome(), "lib/ext").getPath() }), Resources.getString(
DebugInterfaceView.class, "title-error"), JOptionPane.ERROR_MESSAGE);
}
catch (Exception ex) {
LOGGER.warn("Fetch port identifiers failed.", ex);
}
model.setCommPorts(Arrays.asList(commPorts.toArray(new CommPort[0])));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy