View Javadoc
1   /*******************************************************************************
2    * Copyhacked (H) 2012-2025.
3    * This program and the accompanying materials
4    * are made available under no term at all, use it like
5    * you want, but share and discuss it
6    * every time possible with every body.
7    * 
8    * Contributors:
9    *      ron190 at ymail dot com - initial implementation
10   ******************************************************************************/
11  package com.jsql.view.swing.manager;
12  
13  import com.jsql.util.I18nUtil;
14  import com.jsql.util.bruter.ActionCoder;
15  import com.jsql.util.bruter.Coder;
16  import com.jsql.view.swing.manager.util.CoderListener;
17  import com.jsql.view.swing.text.JPopupTextArea;
18  import com.jsql.view.swing.text.JTextAreaPlaceholder;
19  import com.jsql.view.swing.text.listener.DocumentListenerEditing;
20  import com.jsql.view.swing.util.I18nViewUtil;
21  import com.jsql.view.swing.util.JSplitPaneWithZeroSizeDivider;
22  import com.jsql.view.swing.util.UiUtil;
23  
24  import javax.swing.*;
25  import javax.swing.event.ChangeEvent;
26  import javax.swing.event.ChangeListener;
27  import java.awt.*;
28  import java.awt.event.MouseAdapter;
29  import java.awt.event.MouseEvent;
30  import java.util.Arrays;
31  import java.util.LinkedHashMap;
32  import java.util.Map;
33  
34  /**
35   * Manager to code/decode string in various methods.
36   */
37  public class ManagerCoder extends JPanel {
38  
39      public static final String MENU_METHOD_MANAGER_CODER = "menuMethodManagerCoder";
40      public static final String TEXT_INPUT_MANAGER_CODER = "textInputManagerCoder";
41      public static final String RESULT_MANAGER_CODER = "resultManagerCoder";
42  
43      /**
44       * User input to encode.
45       */
46      private final JTextArea textInput;
47  
48      /**
49       * JTextArea displaying result of encoding/decoding.
50       */
51      private final JTextArea result;
52  
53      /**
54       * Encoding choice by user.
55       */
56      private JLabel menuMethod;
57  
58      private static final String ENCODE_TO = "Encode to ";
59      private final transient CoderListener actionCoder = new CoderListener(this);
60  
61      private class ChangeMenuListener implements ChangeListener {
62          private final String nameMethod;
63          ChangeMenuListener(String nameMethod) {
64              this.nameMethod = nameMethod;
65          }
66          @Override
67          public void stateChanged(ChangeEvent e) {
68              if (e.getSource() instanceof JMenuItem item && (item.isSelected() || item.isArmed())) {
69                  ManagerCoder.this.actionCoder.actionPerformed(this.nameMethod);
70              }
71          }
72      }
73  
74      /**
75       * Create a panel to encode a string.
76       */
77      public ManagerCoder() {
78          super(new BorderLayout());
79  
80          var placeholderInput = new JTextAreaPlaceholder(I18nUtil.valueByKey("CODER_INPUT"));
81          this.textInput = new JPopupTextArea(placeholderInput).getProxy();
82          I18nViewUtil.addComponentForKey("CODER_INPUT", placeholderInput);
83          this.textInput.getCaret().setBlinkRate(500);
84          this.textInput.setLineWrap(true);
85          this.textInput.setName(ManagerCoder.TEXT_INPUT_MANAGER_CODER);
86          this.textInput.getDocument().addDocumentListener(new DocumentListenerEditing() {
87              @Override
88              public void process() {
89                  ManagerCoder.this.actionCoder.actionPerformed();
90              }
91          });
92  
93          JPanel topMixed = this.getTopPanel();
94  
95          var placeholderResult = new JTextAreaPlaceholder(I18nUtil.valueByKey("CODER_RESULT"));
96          this.result = new JPopupTextArea(placeholderResult).getProxy();
97          I18nViewUtil.addComponentForKey("CODER_RESULT", placeholderResult);
98          this.result.setName(ManagerCoder.RESULT_MANAGER_CODER);
99          this.result.setLineWrap(true);
100         this.result.setEditable(false);
101 
102         var bottom = new JPanel(new BorderLayout());
103         bottom.add(new JScrollPane(this.result), BorderLayout.CENTER);
104 
105         var divider = new JSplitPaneWithZeroSizeDivider(JSplitPane.VERTICAL_SPLIT);
106         divider.setResizeWeight(0.5);
107         divider.setTopComponent(topMixed);
108         divider.setBottomComponent(bottom);
109         this.add(divider, BorderLayout.CENTER);
110     }
111 
112     private JPanel getTopPanel() {
113         var comboMenubar = this.getLabelMenu();
114         var topMixed = new JPanel(new BorderLayout());
115         topMixed.add(new JScrollPane(this.textInput), BorderLayout.CENTER);
116         topMixed.add(comboMenubar, BorderLayout.SOUTH);
117         return topMixed;
118     }
119 
120     private JLabel getLabelMenu() {
121         Map<String, JMenu> mapMenus = new LinkedHashMap<>();
122         
123         mapMenus.put(Coder.BASE16.label, new JMenu());
124         mapMenus.put(Coder.BASE32.label, new JMenu());
125         mapMenus.put(Coder.BASE58.label, new JMenu());
126         mapMenus.put(Coder.BASE64.label, new JMenu());
127         mapMenus.put(Coder.HEX.label, new JMenu());
128         mapMenus.put(Coder.URL.label, new JMenu());
129         mapMenus.put(Coder.UNICODE.label, new JMenu());
130         var menuHtml = new JMenu();
131         mapMenus.put(Coder.HTML.label, menuHtml);
132         mapMenus.put(Coder.BASE64_ZIP.label, new JMenu());
133         mapMenus.put(Coder.HEX_ZIP.label, new JMenu());
134 
135         var menuEncodeHtmlDecimal = new JMenuItem(ManagerCoder.ENCODE_TO + Coder.HTML_DECIMAL.label);
136         menuHtml.add(menuEncodeHtmlDecimal);
137         menuEncodeHtmlDecimal.addActionListener(this.actionCoder);
138         menuEncodeHtmlDecimal.addChangeListener(new ChangeMenuListener(ManagerCoder.ENCODE_TO + Coder.HTML_DECIMAL.label));
139         
140         mapMenus.forEach((label, menu) -> {
141             var menuEncode = new JMenuItem(ManagerCoder.ENCODE_TO + label);
142             menuEncode.addActionListener(this.actionCoder);
143             menuEncode.addChangeListener(new ChangeMenuListener(ManagerCoder.ENCODE_TO + label));
144             menuEncode.setName("encodeTo"+ label);
145 
146             var menuDecode = new JMenuItem("Decode from "+ label);
147             menuDecode.addActionListener(this.actionCoder);
148             menuDecode.addChangeListener(new ChangeMenuListener("Decode from "+ label));
149             menuDecode.setName("decodeFrom"+ label);
150 
151             menu.setText(label);
152             menu.add(menuEncode);
153             menu.add(menuDecode);
154             menu.setName(label);
155         });
156 
157         mapMenus.put("Hash", new JMenu("Hash"));
158         mapMenus.get("Hash").setName("Hash");
159 
160         ActionCoder.getHashes().forEach(hash -> {
161             var menuEncode = new JMenuItem("Hash to "+ hash);
162             menuEncode.addActionListener(this.actionCoder);
163             menuEncode.addChangeListener(new ChangeMenuListener("Hash to "+ hash));
164             menuEncode.setName("hashTo"+ hash);
165             mapMenus.get("Hash").add(menuEncode);
166         });
167 
168         JPopupMenu popupMenu = new JPopupMenu();
169         for (JMenu menu: mapMenus.values()) {
170             popupMenu.add(menu);
171         }
172 
173         JLabel labelMenu = new JLabel(UiUtil.ARROW_DOWN.getIcon(), SwingConstants.LEFT);
174         this.menuMethod = labelMenu;
175         labelMenu.setText(ManagerCoder.ENCODE_TO + Coder.BASE64.label);
176         labelMenu.setName(ManagerCoder.MENU_METHOD_MANAGER_CODER);
177         labelMenu.setBorder(UiUtil.BORDER_5PX);
178         labelMenu.addMouseListener(new MouseAdapter() {
179             @Override
180             public void mousePressed(MouseEvent e) {
181                 Arrays.stream(popupMenu.getComponents()).map(JMenu.class::cast).forEach(menu -> {
182                     menu.updateUI();
183                     for (var i = 0 ; i < menu.getItemCount() ; i++) {
184                         menu.getItem(i).updateUI();
185                     }
186                 });  // required: incorrect when dark/light mode switch
187                 popupMenu.updateUI();  // required: incorrect when dark/light mode switch
188                 popupMenu.show(e.getComponent(), e.getComponent().getX(),e.getComponent().getY() + e.getComponent().getHeight());
189                 popupMenu.setLocation(e.getComponent().getLocationOnScreen().x,e.getComponent().getLocationOnScreen().y + e.getComponent().getHeight());
190             }
191         });
192         return labelMenu;
193     }
194     
195     
196     // Getter and setter
197 
198     public JTextArea getTextInput() {
199         return this.textInput;
200     }
201 
202     public JLabel getMenuMethod() {
203         return this.menuMethod;
204     }
205 
206     public JTextArea getResult() {
207         return this.result;
208     }
209 }