BaseConvertPanel.java
package edu.jiangxin.apktoolbox.convert.base;
import edu.jiangxin.apktoolbox.swing.extend.EasyPanel;
import edu.jiangxin.apktoolbox.utils.Constants;
import org.apache.commons.lang3.StringUtils;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
public class BaseConvertPanel extends EasyPanel {
private static final String PROPERTY_KEY = "name";
private static final String DECIMAL = "Decimal";
private static final String BINARY = "Binary";
private static final String OCTAL = "Octal";
private static final String HEX = "Hex";
private DocumentListener documentListener;
private DocumentFilter documentFilter;
private boolean isChangedByUser;
private final List<BaseUiObject> baseUiObjects = new ArrayList<>();
@Override
public void initUI() {
BoxLayout boxLayout = new BoxLayout(this, BoxLayout.Y_AXIS);
setLayout(boxLayout);
documentListener = new TextFieldDocumentListener();
documentFilter = new TextFieldDocumentFilter();
isChangedByUser = true;
baseUiObjects.add(new BaseUiObject(2));
baseUiObjects.add(new BaseUiObject(8));
baseUiObjects.add(new BaseUiObject(10));
baseUiObjects.add(new BaseUiObject(16));
for (BaseUiObject baseUiObject : baseUiObjects) {
add(baseUiObject.panel);
add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
}
JButton clearBtn = new JButton("Clear");
clearBtn.addActionListener(new ClearButtonActionListener());
add(clearBtn);
}
class ClearButtonActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent arg0) {
isChangedByUser = false;
for (BaseUiObject baseUiObject : baseUiObjects) {
baseUiObject.textField.setText("");
}
isChangedByUser = true;
}
}
class TextFieldDocumentListener implements DocumentListener {
@Override
public void changedUpdate(DocumentEvent e) {
}
@Override
public void insertUpdate(DocumentEvent e) {
detect(e);
}
@Override
public void removeUpdate(DocumentEvent e) {
detect(e);
}
}
class TextFieldDocumentFilter extends DocumentFilter {
@Override
public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException {
Document doc = fb.getDocument();
StringBuilder sb = new StringBuilder();
sb.append(doc.getText(0, doc.getLength()));
sb.insert(offset, string);
Object propertyObj = doc.getProperty(PROPERTY_KEY);
if (propertyObj == null) {
Toolkit.getDefaultToolkit().beep();
return;
}
Integer radix = (Integer) doc.getProperty(PROPERTY_KEY);
if (isValidText(radix, sb.toString())) {
super.insertString(fb, offset, string, attr);
} else {
Toolkit.getDefaultToolkit().beep();
}
}
@Override
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
Document doc = fb.getDocument();
StringBuilder sb = new StringBuilder();
sb.append(doc.getText(0, doc.getLength()));
sb.replace(offset, offset + length, text);
Object propertyObj = doc.getProperty(PROPERTY_KEY);
if (propertyObj == null) {
Toolkit.getDefaultToolkit().beep();
return;
}
Integer radix = (Integer) doc.getProperty(PROPERTY_KEY);
if (isValidText(radix, sb.toString())) {
super.replace(fb, offset, length, text, attrs);
} else {
Toolkit.getDefaultToolkit().beep();
}
}
}
private void detect(DocumentEvent documentEvent) {
Document doc = documentEvent.getDocument();
Integer radix = (Integer) doc.getProperty(PROPERTY_KEY);
convertMe(radix);
}
private void convertMe(int radix) {
if (!isChangedByUser) {
return;
}
BigInteger value = null;
for (BaseUiObject baseUiObject : baseUiObjects) {
if (baseUiObject.radix == radix) {
String text = baseUiObject.textField.getText();
if (StringUtils.isEmpty(text)) {
value = null;
} else {
value = new BigInteger(text, radix);
}
}
}
isChangedByUser = false;
for (BaseUiObject baseUiObject : baseUiObjects) {
if (baseUiObject.radix != radix) {
if (value == null) {
baseUiObject.textField.setText("");
} else {
baseUiObject.textField.setText(value.toString(baseUiObject.radix));
}
}
}
isChangedByUser = true;
}
private boolean isBinStr(String str) {
if (str == null) {
return false;
}
for (int i = 0; i < str.length(); i++) {
if ((str.charAt(i) != '1') && (str.charAt(i) != '0')) {
return false;
}
}
return true;
}
private boolean isDecStr(String str) {
if (str == null) {
return false;
}
for (int i = 0; i < str.length(); i++) {
if ((str.charAt(i) < '0') || (str.charAt(i) > '9')) {
return false;
}
}
return true;
}
private boolean isOctStr(String str) {
if (str == null) {
return false;
}
for (int i = 0; i < str.length(); i++) {
if ((str.charAt(i) < '0') || (str.charAt(i) > '7')) {
return false;
}
}
return true;
}
private boolean isHexStr(String str) {
if (str == null) {
return false;
}
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if ((c < '0' || c > '9') && (c < 'A' || c > 'F') && (c < 'a' || c > 'f')) {
return false;
}
}
return true;
}
private boolean isValidText(int radix, String text) {
switch (radix) {
case 2 -> {
return isBinStr(text);
}
case 8 -> {
return isOctStr(text);
}
case 10 -> {
return isDecStr(text);
}
case 16 -> {
return isHexStr(text);
}
default -> {
return false;
}
}
}
class BaseUiObject {
int radix;
JPanel panel;
JLabel label;
JTextField textField;
BaseUiObject(int radix) {
this.radix = radix;
panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
label = new JLabel(this + ":");
label.setPreferredSize(new Dimension(50, 25));
textField = new JTextField();
textField.getDocument().addDocumentListener(documentListener);
((PlainDocument) textField.getDocument()).setDocumentFilter(documentFilter);
textField.getDocument().putProperty(PROPERTY_KEY, radix);
panel.add(label);
panel.add(Box.createHorizontalStrut(Constants.DEFAULT_X_BORDER));
panel.add(textField);
}
@Override
public String toString() {
switch (radix) {
case 2 -> {
return BINARY;
}
case 8 -> {
return OCTAL;
}
case 10 -> {
return DECIMAL;
}
case 16 -> {
return HEX;
}
default -> {
return String.valueOf(radix);
}
}
}
}
}