View Javadoc
1   package edu.jiangxin.apktoolbox.convert.base;
2   
3   import edu.jiangxin.apktoolbox.swing.extend.EasyPanel;
4   import edu.jiangxin.apktoolbox.utils.Constants;
5   import org.apache.commons.lang3.StringUtils;
6   
7   import javax.swing.*;
8   import javax.swing.event.DocumentEvent;
9   import javax.swing.event.DocumentListener;
10  import javax.swing.text.*;
11  import java.awt.*;
12  import java.awt.event.ActionEvent;
13  import java.awt.event.ActionListener;
14  import java.math.BigInteger;
15  import java.util.ArrayList;
16  import java.util.List;
17  
18  public class BaseConvertPanel extends EasyPanel {
19      private static final String PROPERTY_KEY = "name";
20  
21      private static final String DECIMAL = "Decimal";
22  
23      private static final String BINARY = "Binary";
24  
25      private static final String OCTAL = "Octal";
26  
27      private static final String HEX = "Hex";
28  
29      private DocumentListener documentListener;
30  
31      private DocumentFilter documentFilter;
32  
33      private boolean isChangedByUser;
34  
35      private final List<BaseUiObject> baseUiObjects = new ArrayList<>();
36  
37      @Override
38      public void initUI() {
39          BoxLayout boxLayout = new BoxLayout(this, BoxLayout.Y_AXIS);
40          setLayout(boxLayout);
41  
42          documentListener = new TextFieldDocumentListener();
43          documentFilter = new TextFieldDocumentFilter();
44  
45          isChangedByUser = true;
46  
47          baseUiObjects.add(new BaseUiObject(2));
48          baseUiObjects.add(new BaseUiObject(8));
49          baseUiObjects.add(new BaseUiObject(10));
50          baseUiObjects.add(new BaseUiObject(16));
51  
52          for (BaseUiObject baseUiObject : baseUiObjects) {
53              add(baseUiObject.panel);
54              add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
55          }
56  
57          JButton clearBtn = new JButton("Clear");
58          clearBtn.addActionListener(new ClearButtonActionListener());
59          add(clearBtn);
60      }
61  
62  
63      class ClearButtonActionListener implements ActionListener {
64          @Override
65          public void actionPerformed(ActionEvent arg0) {
66              isChangedByUser = false;
67              for (BaseUiObject baseUiObject : baseUiObjects) {
68                  baseUiObject.textField.setText("");
69              }
70              isChangedByUser = true;
71          }
72      }
73  
74      class TextFieldDocumentListener implements DocumentListener {
75          @Override
76          public void changedUpdate(DocumentEvent e) {
77          }
78  
79          @Override
80          public void insertUpdate(DocumentEvent e) {
81              detect(e);
82          }
83  
84          @Override
85          public void removeUpdate(DocumentEvent e) {
86              detect(e);
87          }
88      }
89  
90      class TextFieldDocumentFilter extends DocumentFilter {
91          @Override
92          public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException {
93              Document doc = fb.getDocument();
94              StringBuilder sb = new StringBuilder();
95              sb.append(doc.getText(0, doc.getLength()));
96              sb.insert(offset, string);
97  
98              Object propertyObj = doc.getProperty(PROPERTY_KEY);
99              if (propertyObj == null) {
100                 Toolkit.getDefaultToolkit().beep();
101                 return;
102             }
103             Integer radix = (Integer) doc.getProperty(PROPERTY_KEY);
104             if (isValidText(radix, sb.toString())) {
105                 super.insertString(fb, offset, string, attr);
106             } else {
107                 Toolkit.getDefaultToolkit().beep();
108             }
109         }
110 
111         @Override
112         public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
113             Document doc = fb.getDocument();
114             StringBuilder sb = new StringBuilder();
115             sb.append(doc.getText(0, doc.getLength()));
116             sb.replace(offset, offset + length, text);
117 
118             Object propertyObj = doc.getProperty(PROPERTY_KEY);
119             if (propertyObj == null) {
120                 Toolkit.getDefaultToolkit().beep();
121                 return;
122             }
123             Integer radix = (Integer) doc.getProperty(PROPERTY_KEY);
124             if (isValidText(radix, sb.toString())) {
125                 super.replace(fb, offset, length, text, attrs);
126             } else {
127                 Toolkit.getDefaultToolkit().beep();
128             }
129         }
130     }
131 
132     private void detect(DocumentEvent documentEvent) {
133         Document doc = documentEvent.getDocument();
134         Integer radix = (Integer) doc.getProperty(PROPERTY_KEY);
135         convertMe(radix);
136     }
137 
138     private void convertMe(int radix) {
139         if (!isChangedByUser) {
140             return;
141         }
142 
143         BigInteger value = null;
144         for (BaseUiObject baseUiObject : baseUiObjects) {
145             if (baseUiObject.radix == radix) {
146                 String text = baseUiObject.textField.getText();
147                 if (StringUtils.isEmpty(text)) {
148                     value = null;
149                 } else {
150                     value = new BigInteger(text, radix);
151                 }
152             }
153         }
154         isChangedByUser = false;
155         for (BaseUiObject baseUiObject : baseUiObjects) {
156             if (baseUiObject.radix != radix) {
157                 if (value == null) {
158                     baseUiObject.textField.setText("");
159                 } else {
160                     baseUiObject.textField.setText(value.toString(baseUiObject.radix));
161                 }
162             }
163         }
164         isChangedByUser = true;
165     }
166 
167     private boolean isBinStr(String str) {
168         if (str == null) {
169             return false;
170         }
171         for (int i = 0; i < str.length(); i++) {
172             if ((str.charAt(i) != '1') && (str.charAt(i) != '0')) {
173                 return false;
174             }
175         }
176         return true;
177     }
178 
179     private boolean isDecStr(String str) {
180         if (str == null) {
181             return false;
182         }
183         for (int i = 0; i < str.length(); i++) {
184             if ((str.charAt(i) < '0') || (str.charAt(i) > '9')) {
185                 return false;
186             }
187         }
188         return true;
189     }
190 
191     private boolean isOctStr(String str) {
192         if (str == null) {
193             return false;
194         }
195         for (int i = 0; i < str.length(); i++) {
196             if ((str.charAt(i) < '0') || (str.charAt(i) > '7')) {
197                 return false;
198             }
199         }
200         return true;
201     }
202 
203     private boolean isHexStr(String str) {
204         if (str == null) {
205             return false;
206         }
207         for (int i = 0; i < str.length(); i++) {
208             char c = str.charAt(i);
209             if ((c < '0' || c > '9') && (c < 'A' || c > 'F') && (c < 'a' || c > 'f')) {
210                 return false;
211             }
212         }
213         return true;
214     }
215 
216     private boolean isValidText(int radix, String text) {
217         switch (radix) {
218             case 2 -> {
219                 return isBinStr(text);
220             }
221             case 8 -> {
222                 return isOctStr(text);
223             }
224             case 10 -> {
225                 return isDecStr(text);
226             }
227             case 16 -> {
228                 return isHexStr(text);
229             }
230             default -> {
231                 return false;
232             }
233         }
234     }
235 
236     class BaseUiObject {
237         int radix;
238 
239         JPanel panel;
240 
241         JLabel label;
242 
243         JTextField textField;
244 
245         BaseUiObject(int radix) {
246             this.radix = radix;
247             panel = new JPanel();
248             panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
249 
250             label = new JLabel(this + ":");
251             label.setPreferredSize(new Dimension(50, 25));
252 
253             textField = new JTextField();
254             textField.getDocument().addDocumentListener(documentListener);
255             ((PlainDocument) textField.getDocument()).setDocumentFilter(documentFilter);
256             textField.getDocument().putProperty(PROPERTY_KEY, radix);
257 
258             panel.add(label);
259             panel.add(Box.createHorizontalStrut(Constants.DEFAULT_X_BORDER));
260             panel.add(textField);
261         }
262 
263         @Override
264         public String toString() {
265             switch (radix) {
266                 case 2 -> {
267                     return BINARY;
268                 }
269                 case 8 -> {
270                     return OCTAL;
271                 }
272                 case 10 -> {
273                     return DECIMAL;
274                 }
275                 case 16 -> {
276                     return HEX;
277                 }
278                 default -> {
279                     return String.valueOf(radix);
280                 }
281             }
282         }
283     }
284 }