bcv-vf/src/main/java/the/bytecode/club/bytecodeviewer/gui/hexviewer/ValuesPanel.java

1015 lines
48 KiB
Java

package the.bytecode.club.bytecodeviewer.gui.hexviewer;
import java.awt.event.KeyEvent;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;
import java.util.InputMismatchException;
import java.util.Objects;
import javax.annotation.ParametersAreNonnullByDefault;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import org.exbin.bined.CaretMovedListener;
import org.exbin.bined.CodeAreaCaretPosition;
import org.exbin.bined.DataChangedListener;
import org.exbin.bined.swing.basic.CodeArea;
import org.exbin.auxiliary.paged_data.BinaryData;
import org.exbin.bined.capability.EditModeCapable;
/**
* Values side panel.
*
* @author hajdam
*/
@ParametersAreNonnullByDefault
public class ValuesPanel extends javax.swing.JPanel {
public static final int UBYTE_MAX_VALUE = 255;
public static final int SWORD_MIN_VALUE = -32768;
public static final int SWORD_MAX_VALUE = 32767;
public static final int UWORD_MAX_VALUE = 65535;
public static final long UINT_MAX_VALUE = 4294967295L;
public static final BigInteger ULONG_MAX_VALUE = new BigInteger("4294967295");
public static final BigInteger BIG_INTEGER_BYTE_MASK = BigInteger.valueOf(255);
public static final String VALUE_OUT_OF_RANGE = "Value is out of range";
public static int CACHE_SIZE = 250;
private CodeArea codeArea;
private long dataPosition;
private DataChangedListener dataChangedListener;
private CaretMovedListener caretMovedListener;
private final byte[] valuesCache = new byte[CACHE_SIZE];
private final ByteBuffer byteBuffer = ByteBuffer.wrap(valuesCache);
private final ValuesUpdater valuesUpdater = new ValuesUpdater();
private javax.swing.JRadioButton bigEndianRadioButton;
private javax.swing.JCheckBox binaryCheckBox0;
private javax.swing.JCheckBox binaryCheckBox1;
private javax.swing.JCheckBox binaryCheckBox2;
private javax.swing.JCheckBox binaryCheckBox3;
private javax.swing.JCheckBox binaryCheckBox4;
private javax.swing.JCheckBox binaryCheckBox5;
private javax.swing.JCheckBox binaryCheckBox6;
private javax.swing.JCheckBox binaryCheckBox7;
private javax.swing.JLabel binaryLabel;
private javax.swing.JLabel byteLabel;
private javax.swing.JTextField byteTextField;
private javax.swing.JLabel characterLabel;
private javax.swing.JTextField characterTextField;
private javax.swing.JLabel doubleLabel;
private javax.swing.JTextField doubleTextField;
private javax.swing.ButtonGroup endianButtonGroup;
private javax.swing.JLabel floatLabel;
private javax.swing.JTextField floatTextField;
private javax.swing.JLabel intLabel;
private javax.swing.JTextField intTextField;
private javax.swing.ButtonGroup integerSignButtonGroup;
private javax.swing.JSeparator jSeparator1;
private javax.swing.JRadioButton littleEndianRadioButton;
private javax.swing.JLabel longLabel;
private javax.swing.JTextField longTextField;
private javax.swing.JRadioButton signedRadioButton;
private javax.swing.JLabel stringLabel;
private javax.swing.JTextField stringTextField;
private javax.swing.JRadioButton unsignedRadioButton;
private javax.swing.JLabel wordLabel;
private javax.swing.JTextField wordTextField;
public ValuesPanel() {
initComponents();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
endianButtonGroup = new javax.swing.ButtonGroup();
integerSignButtonGroup = new javax.swing.ButtonGroup();
binaryLabel = new javax.swing.JLabel();
binaryCheckBox0 = new javax.swing.JCheckBox();
binaryCheckBox1 = new javax.swing.JCheckBox();
binaryCheckBox2 = new javax.swing.JCheckBox();
binaryCheckBox3 = new javax.swing.JCheckBox();
binaryCheckBox4 = new javax.swing.JCheckBox();
binaryCheckBox5 = new javax.swing.JCheckBox();
binaryCheckBox6 = new javax.swing.JCheckBox();
binaryCheckBox7 = new javax.swing.JCheckBox();
byteLabel = new javax.swing.JLabel();
byteTextField = new javax.swing.JTextField();
wordLabel = new javax.swing.JLabel();
wordTextField = new javax.swing.JTextField();
intLabel = new javax.swing.JLabel();
intTextField = new javax.swing.JTextField();
longLabel = new javax.swing.JLabel();
longTextField = new javax.swing.JTextField();
floatLabel = new javax.swing.JLabel();
floatTextField = new javax.swing.JTextField();
doubleLabel = new javax.swing.JLabel();
doubleTextField = new javax.swing.JTextField();
characterLabel = new javax.swing.JLabel();
characterTextField = new javax.swing.JTextField();
stringLabel = new javax.swing.JLabel();
stringTextField = new javax.swing.JTextField();
jSeparator1 = new javax.swing.JSeparator();
bigEndianRadioButton = new javax.swing.JRadioButton();
littleEndianRadioButton = new javax.swing.JRadioButton();
signedRadioButton = new javax.swing.JRadioButton();
unsignedRadioButton = new javax.swing.JRadioButton();
setMaximumSize(new java.awt.Dimension(246, 447));
setMinimumSize(new java.awt.Dimension(246, 447));
binaryLabel.setText("Binary");
binaryCheckBox0.addActionListener(this::binaryCheckBox0ActionPerformed);
binaryCheckBox1.addActionListener(this::binaryCheckBox1ActionPerformed);
binaryCheckBox2.addActionListener(this::binaryCheckBox2ActionPerformed);
binaryCheckBox3.addActionListener(this::binaryCheckBox3ActionPerformed);
binaryCheckBox4.addActionListener(this::binaryCheckBox4ActionPerformed);
binaryCheckBox5.addActionListener(this::binaryCheckBox5ActionPerformed);
binaryCheckBox6.addActionListener(this::binaryCheckBox6ActionPerformed);
binaryCheckBox7.addActionListener(this::binaryCheckBox7ActionPerformed);
byteLabel.setText("Byte");
byteTextField.setEditable(false);
byteTextField.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyReleased(java.awt.event.KeyEvent evt) {
byteTextFieldKeyReleased(evt);
}
});
wordLabel.setText("Word");
wordTextField.setEditable(false);
wordTextField.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyReleased(java.awt.event.KeyEvent evt) {
wordTextFieldKeyReleased(evt);
}
});
intLabel.setText("Integer");
intTextField.setEditable(false);
intTextField.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyReleased(java.awt.event.KeyEvent evt) {
intTextFieldKeyReleased(evt);
}
});
longLabel.setText("Long");
longTextField.setEditable(false);
longTextField.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyReleased(java.awt.event.KeyEvent evt) {
longTextFieldKeyReleased(evt);
}
});
floatLabel.setText("Float");
floatTextField.setEditable(false);
floatTextField.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyReleased(java.awt.event.KeyEvent evt) {
floatTextFieldKeyReleased(evt);
}
});
doubleLabel.setText("Double");
doubleTextField.setEditable(false);
doubleTextField.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyReleased(java.awt.event.KeyEvent evt) {
doubleTextFieldKeyReleased(evt);
}
});
characterLabel.setText("Character");
characterTextField.setEditable(false);
characterTextField.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyReleased(java.awt.event.KeyEvent evt) {
characterTextFieldKeyReleased(evt);
}
});
stringLabel.setText("String");
stringTextField.setEditable(false);
stringTextField.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyReleased(java.awt.event.KeyEvent evt) {
stringTextFieldKeyReleased(evt);
}
});
jSeparator1.setOrientation(javax.swing.SwingConstants.VERTICAL);
endianButtonGroup.add(bigEndianRadioButton);
bigEndianRadioButton.setSelected(true);
bigEndianRadioButton.setText("BE");
bigEndianRadioButton.setToolTipText("Big Endian");
bigEndianRadioButton.addChangeListener(this::bigEndianRadioButtonStateChanged);
endianButtonGroup.add(littleEndianRadioButton);
littleEndianRadioButton.setText("LE");
littleEndianRadioButton.setToolTipText("Little Endian");
littleEndianRadioButton.addChangeListener(this::littleEndianRadioButtonStateChanged);
integerSignButtonGroup.add(signedRadioButton);
signedRadioButton.setSelected(true);
signedRadioButton.setText("Sig");
signedRadioButton.setToolTipText("Signed Integers");
signedRadioButton.addChangeListener(this::signedRadioButtonStateChanged);
integerSignButtonGroup.add(unsignedRadioButton);
unsignedRadioButton.setText("Uns");
unsignedRadioButton.setToolTipText("Unsigned Integers");
unsignedRadioButton.addChangeListener(this::unsignedRadioButtonStateChanged);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(bigEndianRadioButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(littleEndianRadioButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 2, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(signedRadioButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(unsignedRadioButton))
.addComponent(binaryLabel)
.addGroup(layout.createSequentialGroup()
.addComponent(binaryCheckBox0)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(binaryCheckBox1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(binaryCheckBox2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(binaryCheckBox3)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(binaryCheckBox4)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(binaryCheckBox5)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(binaryCheckBox6)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(binaryCheckBox7))
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(byteTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 234, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(wordTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 234, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(intTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 234, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(longTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 234, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(byteLabel)
.addComponent(wordLabel)
.addComponent(intLabel)
.addComponent(longLabel))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(characterTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 234, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(floatTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 234, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(floatLabel)
.addComponent(doubleLabel)
.addComponent(doubleTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 234, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(characterLabel)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(stringTextField, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 234, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(stringLabel)))))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(binaryLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(binaryCheckBox0)
.addComponent(binaryCheckBox1)
.addComponent(binaryCheckBox2)
.addComponent(binaryCheckBox3)
.addComponent(binaryCheckBox4)
.addComponent(binaryCheckBox5)
.addComponent(binaryCheckBox6)
.addComponent(binaryCheckBox7))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(layout.createSequentialGroup()
.addComponent(byteLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(byteTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(wordLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(wordTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(intLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(intTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(longLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(longTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addComponent(floatLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(floatTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(doubleLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(doubleTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(characterLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(characterTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(stringLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(stringTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(bigEndianRadioButton)
.addComponent(littleEndianRadioButton))
.addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 28, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(signedRadioButton)
.addComponent(unsignedRadioButton)))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
private void littleEndianRadioButtonStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_littleEndianRadioButtonStateChanged
updateValues();
}//GEN-LAST:event_littleEndianRadioButtonStateChanged
private void bigEndianRadioButtonStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_bigEndianRadioButtonStateChanged
updateValues();
}//GEN-LAST:event_bigEndianRadioButtonStateChanged
private void signedRadioButtonStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_signedRadioButtonStateChanged
updateValues();
}//GEN-LAST:event_signedRadioButtonStateChanged
private void unsignedRadioButtonStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_unsignedRadioButtonStateChanged
updateValues();
}//GEN-LAST:event_unsignedRadioButtonStateChanged
private void binaryCheckBox0ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_binaryCheckBox0ActionPerformed
if (!valuesUpdater.isUpdateInProgress() && ((valuesCache[0] & 0x80) > 0 != binaryCheckBox0.isSelected())) {
valuesCache[0] = (byte) (valuesCache[0] ^ 0x80);
modifyValues(1);
}
}//GEN-LAST:event_binaryCheckBox0ActionPerformed
private void binaryCheckBox1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_binaryCheckBox1ActionPerformed
if (!valuesUpdater.isUpdateInProgress() && ((valuesCache[0] & 0x40) > 0 != binaryCheckBox1.isSelected())) {
valuesCache[0] = (byte) (valuesCache[0] ^ 0x40);
modifyValues(1);
}
}//GEN-LAST:event_binaryCheckBox1ActionPerformed
private void binaryCheckBox2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_binaryCheckBox2ActionPerformed
if (!valuesUpdater.isUpdateInProgress() && ((valuesCache[0] & 0x20) > 0 != binaryCheckBox2.isSelected())) {
valuesCache[0] = (byte) (valuesCache[0] ^ 0x20);
modifyValues(1);
}
}//GEN-LAST:event_binaryCheckBox2ActionPerformed
private void binaryCheckBox3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_binaryCheckBox3ActionPerformed
if (!valuesUpdater.isUpdateInProgress() && ((valuesCache[0] & 0x10) > 0 != binaryCheckBox3.isSelected())) {
valuesCache[0] = (byte) (valuesCache[0] ^ 0x10);
modifyValues(1);
}
}//GEN-LAST:event_binaryCheckBox3ActionPerformed
private void binaryCheckBox4ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_binaryCheckBox4ActionPerformed
if (!valuesUpdater.isUpdateInProgress() && ((valuesCache[0] & 0x8) > 0 != binaryCheckBox4.isSelected())) {
valuesCache[0] = (byte) (valuesCache[0] ^ 0x8);
modifyValues(1);
}
}//GEN-LAST:event_binaryCheckBox4ActionPerformed
private void binaryCheckBox5ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_binaryCheckBox5ActionPerformed
if (!valuesUpdater.isUpdateInProgress() && ((valuesCache[0] & 0x4) > 0 != binaryCheckBox5.isSelected())) {
valuesCache[0] = (byte) (valuesCache[0] ^ 0x4);
modifyValues(1);
}
}//GEN-LAST:event_binaryCheckBox5ActionPerformed
private void binaryCheckBox6ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_binaryCheckBox6ActionPerformed
if (!valuesUpdater.isUpdateInProgress() && ((valuesCache[0] & 0x2) > 0 != binaryCheckBox6.isSelected())) {
valuesCache[0] = (byte) (valuesCache[0] ^ 0x2);
modifyValues(1);
}
}//GEN-LAST:event_binaryCheckBox6ActionPerformed
private void binaryCheckBox7ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_binaryCheckBox7ActionPerformed
if (!valuesUpdater.isUpdateInProgress() && ((valuesCache[0] & 0x1) > 0 != binaryCheckBox7.isSelected())) {
valuesCache[0] = (byte) (valuesCache[0] ^ 0x1);
modifyValues(1);
}
}//GEN-LAST:event_binaryCheckBox7ActionPerformed
private void byteTextFieldKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_byteTextFieldKeyReleased
if (evt.getKeyCode() == KeyEvent.VK_ENTER && isEditable()) {
try {
int intValue = Integer.parseInt(byteTextField.getText());
if (isSigned()) {
if (intValue < Byte.MIN_VALUE || intValue > Byte.MAX_VALUE) {
throw new NumberFormatException(VALUE_OUT_OF_RANGE);
}
} else {
if (intValue < 0 || intValue > UBYTE_MAX_VALUE) {
throw new NumberFormatException(VALUE_OUT_OF_RANGE);
}
}
valuesCache[0] = (byte) intValue;
modifyValues(1);
updateValues();
} catch (NumberFormatException ex) {
showException(ex);
}
}
}//GEN-LAST:event_byteTextFieldKeyReleased
private void wordTextFieldKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_wordTextFieldKeyReleased
if (evt.getKeyCode() == KeyEvent.VK_ENTER && isEditable()) {
try {
int intValue = Integer.parseInt(wordTextField.getText());
if (isSigned()) {
if (intValue < SWORD_MIN_VALUE || intValue > SWORD_MAX_VALUE) {
throw new NumberFormatException(VALUE_OUT_OF_RANGE);
}
} else {
if (intValue < 0 || intValue > UWORD_MAX_VALUE) {
throw new NumberFormatException(VALUE_OUT_OF_RANGE);
}
}
if (getByteOrder() == ByteOrder.LITTLE_ENDIAN) {
valuesCache[0] = (byte) (intValue & 0xff);
valuesCache[1] = (byte) ((intValue >> 8) & 0xff);
} else {
valuesCache[0] = (byte) ((intValue >> 8) & 0xff);
valuesCache[1] = (byte) (intValue & 0xff);
}
modifyValues(2);
updateValues();
} catch (NumberFormatException ex) {
showException(ex);
}
}
}//GEN-LAST:event_wordTextFieldKeyReleased
private void intTextFieldKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_intTextFieldKeyReleased
if (evt.getKeyCode() == KeyEvent.VK_ENTER && isEditable()) {
try {
long longValue = Long.parseLong(intTextField.getText());
if (isSigned()) {
if (longValue < Integer.MIN_VALUE || longValue > Integer.MAX_VALUE) {
throw new NumberFormatException(VALUE_OUT_OF_RANGE);
}
} else {
if (longValue < 0 || longValue > UINT_MAX_VALUE) {
throw new NumberFormatException(VALUE_OUT_OF_RANGE);
}
}
if (getByteOrder() == ByteOrder.LITTLE_ENDIAN) {
valuesCache[0] = (byte) (longValue & 0xff);
valuesCache[1] = (byte) ((longValue >> 8) & 0xff);
valuesCache[2] = (byte) ((longValue >> 16) & 0xff);
valuesCache[3] = (byte) ((longValue >> 24) & 0xff);
} else {
valuesCache[0] = (byte) ((longValue >> 24) & 0xff);
valuesCache[1] = (byte) ((longValue >> 16) & 0xff);
valuesCache[2] = (byte) ((longValue >> 8) & 0xff);
valuesCache[3] = (byte) (longValue & 0xff);
}
modifyValues(4);
updateValues();
} catch (NumberFormatException ex) {
showException(ex);
}
}
}//GEN-LAST:event_intTextFieldKeyReleased
private void longTextFieldKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_longTextFieldKeyReleased
if (evt.getKeyCode() == KeyEvent.VK_ENTER && isEditable()) {
try {
ByteOrder byteOrder = getByteOrder();
if (isSigned()) {
long longValue = Long.parseLong(longTextField.getText());
byteBuffer.rewind();
if (byteBuffer.order() != byteOrder) {
byteBuffer.order(byteOrder);
}
byteBuffer.putLong(longValue);
} else {
BigInteger bigInteger = new BigInteger(longTextField.getText());
if (bigInteger.signum() == -1 || bigInteger.compareTo(ULONG_MAX_VALUE) > 0) {
throw new NumberFormatException(VALUE_OUT_OF_RANGE);
}
if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
for (int i = 0; i < 7; i++) {
BigInteger nextByte = bigInteger.and(BIG_INTEGER_BYTE_MASK);
valuesCache[7 - i] = nextByte.byteValue();
bigInteger = bigInteger.shiftRight(8);
}
} else {
for (int i = 0; i < 7; i++) {
BigInteger nextByte = bigInteger.and(BIG_INTEGER_BYTE_MASK);
valuesCache[i] = nextByte.byteValue();
bigInteger = bigInteger.shiftRight(8);
}
}
}
modifyValues(8);
updateValues();
} catch (NumberFormatException ex) {
showException(ex);
}
}
}//GEN-LAST:event_longTextFieldKeyReleased
private void floatTextFieldKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_floatTextFieldKeyReleased
if (evt.getKeyCode() == KeyEvent.VK_ENTER && isEditable()) {
try {
ByteOrder byteOrder = getByteOrder();
float floatValue = Float.parseFloat(floatTextField.getText());
byteBuffer.rewind();
if (byteBuffer.order() != byteOrder) {
byteBuffer.order(byteOrder);
}
byteBuffer.putFloat(floatValue);
modifyValues(4);
updateValues();
} catch (NumberFormatException ex) {
showException(ex);
}
}
}//GEN-LAST:event_floatTextFieldKeyReleased
private void doubleTextFieldKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_doubleTextFieldKeyReleased
if (evt.getKeyCode() == KeyEvent.VK_ENTER && isEditable()) {
try {
ByteOrder byteOrder = getByteOrder();
double doubleValue = Double.parseDouble(doubleTextField.getText());
byteBuffer.rewind();
if (byteBuffer.order() != byteOrder) {
byteBuffer.order(byteOrder);
}
byteBuffer.putDouble(doubleValue);
modifyValues(8);
updateValues();
} catch (NumberFormatException ex) {
showException(ex);
}
}
}//GEN-LAST:event_doubleTextFieldKeyReleased
private void characterTextFieldKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_characterTextFieldKeyReleased
if (evt.getKeyCode() == KeyEvent.VK_ENTER && isEditable()) {
try {
String characterText = characterTextField.getText();
if (characterText.length() == 0) {
throw new InputMismatchException("Empty value not valid");
}
if (characterText.length() > 1) {
throw new InputMismatchException("Only single character allowed");
}
byte[] bytes = characterText.getBytes(codeArea.getCharset());
System.arraycopy(bytes, 0, valuesCache, 0, bytes.length);
modifyValues(bytes.length);
updateValues();
} catch (InputMismatchException ex) {
showException(ex);
}
}
}//GEN-LAST:event_characterTextFieldKeyReleased
private void stringTextFieldKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_stringTextFieldKeyReleased
if (evt.getKeyCode() == KeyEvent.VK_ENTER && isEditable()) {
try {
String characterText = stringTextField.getText();
if (characterText.length() == 0) {
throw new InputMismatchException("Empty value not valid");
}
byte[] bytes = characterText.getBytes(codeArea.getCharset());
if (bytes.length > CACHE_SIZE) {
throw new InputMismatchException("String is too long");
}
System.arraycopy(bytes, 0, valuesCache, 0, bytes.length);
modifyValues(bytes.length);
updateValues();
} catch (InputMismatchException ex) {
showException(ex);
}
}
}//GEN-LAST:event_stringTextFieldKeyReleased
public void setCodeArea(CodeArea codeArea) {
this.codeArea = codeArea;
}
public void enableUpdate() {
dataChangedListener = () -> {
updateEditMode();
updateValues();
};
codeArea.addDataChangedListener(dataChangedListener);
caretMovedListener = (CodeAreaCaretPosition caretPosition) -> updateValues();
codeArea.addCaretMovedListener(caretMovedListener);
updateEditMode();
updateValues();
}
public void disableUpdate() {
codeArea.removeDataChangedListener(dataChangedListener);
codeArea.removeCaretMovedListener(caretMovedListener);
}
public void updateEditMode() {
boolean editable = isEditable();
binaryCheckBox0.setEnabled(editable);
binaryCheckBox1.setEnabled(editable);
binaryCheckBox2.setEnabled(editable);
binaryCheckBox3.setEnabled(editable);
binaryCheckBox4.setEnabled(editable);
binaryCheckBox5.setEnabled(editable);
binaryCheckBox6.setEnabled(editable);
binaryCheckBox7.setEnabled(editable);
byteTextField.setEditable(editable);
wordTextField.setEditable(editable);
intTextField.setEditable(editable);
longTextField.setEditable(editable);
floatTextField.setEditable(editable);
doubleTextField.setEditable(editable);
characterTextField.setEditable(editable);
stringTextField.setEditable(editable);
}
public void updateValues() {
CodeAreaCaretPosition caretPosition = codeArea.getCaretPosition();
dataPosition = caretPosition.getDataPosition();
long dataSize = codeArea.getDataSize();
if (dataPosition < dataSize) {
int availableData = dataSize - dataPosition >= CACHE_SIZE ? CACHE_SIZE : (int) (dataSize - dataPosition);
BinaryData contentData = Objects.requireNonNull(codeArea.getContentData());
contentData.copyToArray(dataPosition, valuesCache, 0, availableData);
if (availableData < CACHE_SIZE) {
Arrays.fill(valuesCache, availableData, CACHE_SIZE, (byte) 0);
}
}
valuesUpdater.schedule();
}
private void modifyValues(int bytesCount) {
// Unsupported in this version
}
private boolean isSigned() {
return signedRadioButton.isSelected();
}
private boolean isEditable() {
return ((EditModeCapable) codeArea).isEditable();
}
private ByteOrder getByteOrder() {
return littleEndianRadioButton.isSelected() ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN;
}
private void showException(Exception ex) {
JOptionPane.showMessageDialog(this, ex.getMessage(), "Invalid Input", JOptionPane.ERROR_MESSAGE);
}
public enum ValuesPanelField {
BINARY0,
BINARY1,
BINARY2,
BINARY3,
BINARY4,
BINARY5,
BINARY6,
BINARY7,
BYTE,
WORD,
INTEGER,
LONG,
FLOAT,
DOUBLE,
CHARACTER,
STRING
}
@ParametersAreNonnullByDefault
private class ValuesUpdater {
private boolean updateInProgress = false;
private boolean updateTerminated = false;
private boolean scheduleUpdate = false;
private boolean clearFields = true;
private boolean signed;
private ByteOrder byteOrder;
private byte[] values;
private synchronized void schedule() {
if (updateInProgress) {
updateTerminated = true;
}
if (!scheduleUpdate) {
scheduleUpdate = true;
scheduleNextStep(ValuesPanelField.values()[0]);
}
}
private void scheduleNextStep(final ValuesPanelField valuesPanelField) {
SwingUtilities.invokeLater(() -> updateValue(valuesPanelField));
}
public boolean isUpdateInProgress() {
return updateInProgress;
}
private void updateValue(final ValuesPanelField valuesPanelField) {
if (valuesPanelField.ordinal() == 0) {
long dataSize = codeArea.getDataSize();
clearFields = dataPosition >= dataSize;
byteOrder = littleEndianRadioButton.isSelected() ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN;
byteOrder = getByteOrder();
signed = isSigned();
values = valuesCache;
if (clearFields) {
values[0] = 0;
}
updateStarted();
}
if (updateTerminated) {
stopUpdate();
return;
}
if (clearFields) {
clearField(valuesPanelField);
} else {
updateField(valuesPanelField);
}
final ValuesPanelField[] panelFields = ValuesPanelField.values();
ValuesPanelField lastValue = panelFields[panelFields.length - 1];
if (valuesPanelField == lastValue) {
stopUpdate();
} else {
SwingUtilities.invokeLater(() -> {
ValuesPanelField nextValue = panelFields[valuesPanelField.ordinal() + 1];
updateValue(nextValue);
});
}
}
private void updateField(ValuesPanelField valuesPanelField) {
switch (valuesPanelField) {
case BINARY0: {
binaryCheckBox0.setSelected((values[0] & 0x80) > 0);
break;
}
case BINARY1: {
binaryCheckBox1.setSelected((values[0] & 0x40) > 0);
break;
}
case BINARY2: {
binaryCheckBox2.setSelected((values[0] & 0x20) > 0);
break;
}
case BINARY3: {
binaryCheckBox3.setSelected((values[0] & 0x10) > 0);
break;
}
case BINARY4: {
binaryCheckBox4.setSelected((values[0] & 0x8) > 0);
break;
}
case BINARY5: {
binaryCheckBox5.setSelected((values[0] & 0x4) > 0);
break;
}
case BINARY6: {
binaryCheckBox6.setSelected((values[0] & 0x2) > 0);
break;
}
case BINARY7: {
binaryCheckBox7.setSelected((values[0] & 0x1) > 0);
break;
}
case BYTE: {
byteTextField.setText(String.valueOf(signed ? values[0] : values[0] & 0xff));
break;
}
case WORD: {
int wordValue = signed
? (byteOrder == ByteOrder.LITTLE_ENDIAN
? (values[0] & 0xff) | (values[1] << 8)
: (values[1] & 0xff) | (values[0] << 8))
: (byteOrder == ByteOrder.LITTLE_ENDIAN
? (values[0] & 0xff) | ((values[1] & 0xff) << 8)
: (values[1] & 0xff) | ((values[0] & 0xff) << 8));
wordTextField.setText(String.valueOf(wordValue));
break;
}
case INTEGER: {
long intValue = signed
? (byteOrder == ByteOrder.LITTLE_ENDIAN
? (values[0] & 0xffL) | ((values[1] & 0xffL) << 8) | ((values[2] & 0xffL) << 16) | (values[3] << 24)
: (values[3] & 0xffL) | ((values[2] & 0xffL) << 8) | ((values[1] & 0xffL) << 16) | (values[0] << 24))
: (byteOrder == ByteOrder.LITTLE_ENDIAN
? (values[0] & 0xffL) | ((values[1] & 0xffL) << 8) | ((values[2] & 0xffL) << 16) | ((values[3] & 0xffL) << 24)
: (values[3] & 0xffL) | ((values[2] & 0xffL) << 8) | ((values[1] & 0xffL) << 16) | ((values[0] & 0xffL) << 24));
intTextField.setText(String.valueOf(intValue));
break;
}
case LONG: {
if (signed) {
byteBuffer.rewind();
if (byteBuffer.order() != byteOrder) {
byteBuffer.order(byteOrder);
}
longTextField.setText(String.valueOf(byteBuffer.getLong()));
} else {
long longValue = byteOrder == ByteOrder.LITTLE_ENDIAN
? (values[0] & 0xffL) | ((values[1] & 0xffL) << 8) | ((values[2] & 0xffL) << 16) | ((values[3] & 0xffL) << 24)
| ((values[4] & 0xffL) << 32) | ((values[5] & 0xffL) << 40) | ((values[6] & 0xffL) << 48)
: (values[7] & 0xffL) | ((values[6] & 0xffL) << 8) | ((values[5] & 0xffL) << 16) | ((values[4] & 0xffL) << 24)
| ((values[3] & 0xffL) << 32) | ((values[2] & 0xffL) << 40) | ((values[1] & 0xffL) << 48);
BigInteger bigInt1 = BigInteger.valueOf(values[byteOrder == ByteOrder.LITTLE_ENDIAN ? 7 : 0] & 0xffL);
BigInteger bigInt2 = bigInt1.shiftLeft(56);
BigInteger bigInt3 = bigInt2.add(BigInteger.valueOf(longValue));
longTextField.setText(bigInt3.toString());
}
break;
}
case FLOAT: {
byteBuffer.rewind();
if (byteBuffer.order() != byteOrder) {
byteBuffer.order(byteOrder);
}
floatTextField.setText(String.valueOf(byteBuffer.getFloat()));
break;
}
case DOUBLE: {
byteBuffer.rewind();
if (byteBuffer.order() != byteOrder) {
byteBuffer.order(byteOrder);
}
doubleTextField.setText(String.valueOf(byteBuffer.getDouble()));
break;
}
case CHARACTER: {
String strValue = new String(values, codeArea.getCharset());
if (strValue.length() > 0) {
characterTextField.setText(strValue.substring(0, 1));
} else {
characterTextField.setText("");
}
break;
}
case STRING: {
String strValue = new String(values, codeArea.getCharset());
for (int i = 0; i < strValue.length(); i++) {
char charAt = strValue.charAt(i);
if (charAt == '\r' || charAt == '\n' || charAt == 0) {
strValue = strValue.substring(0, i);
break;
}
}
stringTextField.setText(strValue);
stringTextField.setCaretPosition(0);
break;
}
}
}
private void clearField(ValuesPanelField valuesPanelField) {
switch (valuesPanelField) {
case BINARY0: {
binaryCheckBox0.setSelected(false);
break;
}
case BINARY1: {
binaryCheckBox1.setSelected(false);
break;
}
case BINARY2: {
binaryCheckBox2.setSelected(false);
break;
}
case BINARY3: {
binaryCheckBox3.setSelected(false);
break;
}
case BINARY4: {
binaryCheckBox4.setSelected(false);
break;
}
case BINARY5: {
binaryCheckBox5.setSelected(false);
break;
}
case BINARY6: {
binaryCheckBox6.setSelected(false);
break;
}
case BINARY7: {
binaryCheckBox7.setSelected(false);
break;
}
case BYTE: {
byteTextField.setText("");
break;
}
case WORD: {
wordTextField.setText("");
break;
}
case INTEGER: {
intTextField.setText("");
break;
}
case LONG: {
longTextField.setText("");
break;
}
case FLOAT: {
floatTextField.setText("");
break;
}
case DOUBLE: {
doubleTextField.setText("");
break;
}
case CHARACTER: {
characterTextField.setText("");
break;
}
case STRING: {
stringTextField.setText("");
break;
}
}
}
private synchronized void updateStarted() {
updateInProgress = true;
scheduleUpdate = false;
}
private synchronized void stopUpdate() {
updateInProgress = false;
updateTerminated = false;
}
}
}