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      /**
40       * User input to encode.
41       */
42      private final JTextArea textInput;
43  
44      /**
45       * JTextArea displaying result of encoding/decoding.
46       */
47      private final JTextArea result;
48  
49      /**
50       * Encoding choice by user.
51       */
52      private JLabel menuMethod;
53  
54      private static final String ENCODE_TO = "Encode to ";
55      private final transient CoderListener actionCoder = new CoderListener(this);
56  
57      private class ChangeMenuListener implements ChangeListener {
58          private final String nameMethod;
59          ChangeMenuListener(String nameMethod) {
60              this.nameMethod = nameMethod;
61          }
62          @Override
63          public void stateChanged(ChangeEvent e) {
64              if (e.getSource() instanceof JMenuItem) {
65                  JMenuItem item = (JMenuItem) e.getSource();
66                  if (item.isSelected() || item.isArmed()) {
67                      ManagerCoder.this.actionCoder.actionPerformed(this.nameMethod);
68                  }
69              }
70          }
71      }
72  
73      /**
74       * Create a panel to encode a string.
75       */
76      public ManagerCoder() {
77          super(new BorderLayout());
78  
79          var placeholderInput = new JTextAreaPlaceholder(I18nUtil.valueByKey("CODER_INPUT"));
80          this.textInput = new JPopupTextArea(placeholderInput).getProxy();
81          I18nViewUtil.addComponentForKey("CODER_INPUT", placeholderInput);
82          this.textInput.getCaret().setBlinkRate(500);
83          this.textInput.setLineWrap(true);
84          this.textInput.setName("textInputManagerCoder");
85          this.textInput.getDocument().addDocumentListener(new DocumentListenerEditing() {
86              @Override
87              public void process() {
88                  ManagerCoder.this.actionCoder.actionPerformed();
89              }
90          });
91  
92          JPanel topMixed = this.getTopPanel();
93  
94          var placeholderResult = new JTextAreaPlaceholder(I18nUtil.valueByKey("CODER_RESULT"));
95          this.result = new JPopupTextArea(placeholderResult).getProxy();
96          I18nViewUtil.addComponentForKey("CODER_RESULT", placeholderResult);
97          this.result.setName("resultManagerCoder");
98          this.result.setLineWrap(true);
99          this.result.setEditable(false);
100 
101         var bottom = new JPanel(new BorderLayout());
102         bottom.add(new JScrollPane(this.result), BorderLayout.CENTER);
103 
104         var divider = new JSplitPaneWithZeroSizeDivider(JSplitPane.VERTICAL_SPLIT);
105         divider.setResizeWeight(0.5);
106         divider.setTopComponent(topMixed);
107         divider.setBottomComponent(bottom);
108         this.add(divider, BorderLayout.CENTER);
109     }
110 
111     private JPanel getTopPanel() {
112         var comboMenubar = this.getLabelMenu();
113         var topMixed = new JPanel(new BorderLayout());
114         topMixed.add(new JScrollPane(this.textInput), BorderLayout.CENTER);
115         topMixed.add(comboMenubar, BorderLayout.SOUTH);
116         return topMixed;
117     }
118 
119     private JLabel getLabelMenu() {
120         Map<String, JMenu> mapMenus = new LinkedHashMap<>();
121         
122         mapMenus.put(Coder.BASE16.label, new JMenu());
123         mapMenus.put(Coder.BASE32.label, new JMenu());
124         mapMenus.put(Coder.BASE58.label, new JMenu());
125         mapMenus.put(Coder.BASE64.label, new JMenu());
126         mapMenus.put(Coder.HEX.label, new JMenu());
127         mapMenus.put(Coder.URL.label, new JMenu());
128         mapMenus.put(Coder.UNICODE.label, new JMenu());
129         var menuHtml = new JMenu();
130         mapMenus.put(Coder.HTML.label, menuHtml);
131         mapMenus.put(Coder.BASE64_ZIP.label, new JMenu());
132         mapMenus.put(Coder.HEX_ZIP.label, new JMenu());
133 
134         var menuEncodeHtmlDecimal = new JMenuItem(ManagerCoder.ENCODE_TO + Coder.HTML_DECIMAL.label);
135         menuHtml.add(menuEncodeHtmlDecimal);
136         menuEncodeHtmlDecimal.addActionListener(this.actionCoder);
137         menuEncodeHtmlDecimal.addChangeListener(new ChangeMenuListener(ManagerCoder.ENCODE_TO + Coder.HTML_DECIMAL.label));
138         
139         mapMenus.forEach((label, menu) -> {
140             var menuEncode = new JMenuItem(ManagerCoder.ENCODE_TO + label);
141             menuEncode.addActionListener(this.actionCoder);
142             menuEncode.addChangeListener(new ChangeMenuListener(ManagerCoder.ENCODE_TO + label));
143             menuEncode.setName("encodeTo"+ label);
144 
145             var menuDecode = new JMenuItem("Decode from "+ label);
146             menuDecode.addActionListener(this.actionCoder);
147             menuDecode.addChangeListener(new ChangeMenuListener("Decode from "+ label));
148             menuDecode.setName("decodeFrom"+ label);
149 
150             menu.setText(label);
151             menu.add(menuEncode);
152             menu.add(menuDecode);
153             menu.setName(label);
154         });
155 
156         mapMenus.put("Hash", new JMenu("Hash"));
157         mapMenus.get("Hash").setName("Hash");
158 
159         ActionCoder.getHashes().forEach(hash -> {
160             var menuEncode = new JMenuItem("Hash to "+ hash);
161             menuEncode.addActionListener(this.actionCoder);
162             menuEncode.addChangeListener(new ChangeMenuListener("Hash to "+ hash));
163             menuEncode.setName("hashTo"+ hash);
164             mapMenus.get("Hash").add(menuEncode);
165         });
166 
167         JPopupMenu popupMenu = new JPopupMenu();
168         for (JMenu menu: mapMenus.values()) {
169             popupMenu.add(menu);
170         }
171 
172         JLabel labelMenu = new JLabel(UiUtil.ARROW_DOWN.getIcon(), SwingConstants.LEFT);
173         this.menuMethod = labelMenu;
174         labelMenu.setText(ManagerCoder.ENCODE_TO + Coder.BASE64.label);
175         labelMenu.setName("menuMethodManagerCoder");
176         labelMenu.setBorder(UiUtil.BORDER_5PX);
177         labelMenu.addMouseListener(new MouseAdapter() {
178             @Override
179             public void mousePressed(MouseEvent e) {
180                 Arrays.stream(popupMenu.getComponents()).map(JMenu.class::cast).forEach(menu -> {
181                     menu.updateUI();
182                     for (var i = 0 ; i < menu.getItemCount() ; i++) {
183                         menu.getItem(i).updateUI();
184                     }
185                 });  // required: incorrect when dark/light mode switch
186                 popupMenu.updateUI();  // required: incorrect when dark/light mode switch
187                 popupMenu.show(e.getComponent(), e.getComponent().getX(),e.getComponent().getY() + e.getComponent().getHeight());
188                 popupMenu.setLocation(e.getComponent().getLocationOnScreen().x,e.getComponent().getLocationOnScreen().y + e.getComponent().getHeight());
189             }
190         });
191         return labelMenu;
192     }
193     
194     
195     // Getter and setter
196 
197     public JTextArea getTextInput() {
198         return this.textInput;
199     }
200 
201     public JLabel getMenuMethod() {
202         return this.menuMethod;
203     }
204 
205     public JTextArea getResult() {
206         return this.result;
207     }
208 }