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.dialog;
12  
13  import com.jsql.util.GitUtil.ShowOnConsole;
14  import com.jsql.util.I18nUtil;
15  import com.jsql.util.LogLevelUtil;
16  import com.jsql.view.swing.dialog.translate.Language;
17  import com.jsql.view.swing.dialog.translate.WorkerTranslateInto;
18  import com.jsql.view.swing.popupmenu.JPopupMenuText;
19  import com.jsql.view.swing.text.JPopupTextArea;
20  import com.jsql.view.swing.text.JTextAreaPlaceholder;
21  import com.jsql.view.swing.util.I18nViewUtil;
22  import com.jsql.view.swing.util.MediatorHelper;
23  import com.jsql.view.swing.util.UiUtil;
24  import org.apache.commons.lang3.StringUtils;
25  import org.apache.logging.log4j.LogManager;
26  import org.apache.logging.log4j.Logger;
27  
28  import javax.swing.*;
29  import java.awt.*;
30  import java.awt.event.*;
31  import java.util.Locale;
32  import java.util.ResourceBundle;
33  
34  /**
35   * A dialog displaying current locale translation percentage.
36   */
37  public class DialogTranslate extends JDialog {
38      
39      private static final Logger LOGGER = LogManager.getRootLogger();
40  
41      /**
42       * Button receiving focus.
43       */
44      private final JButton buttonSend = new JButton();  // "Send" text displayed in target locale at runtime
45  
46      private Language languageInto;
47      private final JLabel labelTranslation = new JLabel();
48      private final JTextArea textToTranslate = new JPopupTextArea(new JTextAreaPlaceholder(I18nViewUtil.valueByKey("TRANSLATION_PLACEHOLDER"))).getProxy();
49      private final JProgressBar progressBarTranslation = new JProgressBar();
50      private String textBeforeChange = StringUtils.EMPTY;
51      private final JPanel lastLine;
52  
53      /**
54       * Displays dialog into target locale.
55       * Switching language does not affect this dialog
56       */
57      public DialogTranslate() {
58          super(MediatorHelper.frame(), Dialog.ModalityType.MODELESS);
59          this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
60          this.setIconImages(UiUtil.getIcons());  // Define a small and large app icon
61  
62          ActionListener escapeListener = actionEvent -> this.dispose();  // Action for ESCAPE key
63          this.getRootPane().registerKeyboardAction(
64              escapeListener,
65              KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
66              JComponent.WHEN_IN_FOCUSED_WINDOW
67          );
68  
69          this.lastLine = this.initLastLine();
70  
71          this.labelTranslation.setBorder(UiUtil.BORDER_5PX);
72          var contentPane = this.getContentPane();
73          contentPane.add(this.labelTranslation, BorderLayout.NORTH);
74          contentPane.add(this.lastLine, BorderLayout.SOUTH);
75  
76          this.initTextToTranslate();
77  
78          contentPane.add(new JScrollPane(this.textToTranslate), BorderLayout.CENTER);
79      }
80  
81      /**
82       * Set back default setting for About frame.
83       */
84      public final void initDialog(final Language language) {
85          this.progressBarTranslation.setValue(0);
86          this.progressBarTranslation.setString("Loading...");
87          this.languageInto = language;
88  
89          var bundleInto = ResourceBundle.getBundle(I18nUtil.BASE_NAME, Locale.forLanguageTag(language.getLanguageTag()));
90          var localeInto = Locale.forLanguageTag(language.getLanguageTag());
91          this.labelTranslation.setText(  // set language into
92              String.format(
93                  bundleInto.getString("TRANSLATION_TEXT"),
94                  localeInto.getDisplayLanguage(localeInto),
95                  localeInto.getDisplayLanguage(localeInto)
96              )
97          );
98          ComponentOrientation orientation = ComponentOrientation.getOrientation(Locale.forLanguageTag(language.getLanguageTag()));
99          this.labelTranslation.setComponentOrientation(orientation);
100         this.progressBarTranslation.setComponentOrientation(orientation);
101         this.lastLine.setComponentOrientation(orientation);
102         this.buttonSend.setText(  // display text at runtime
103             ResourceBundle.getBundle(
104                 I18nUtil.BASE_NAME,
105                 Locale.forLanguageTag(language.getLanguageTag())
106             ).getString("TRANSLATION_SEND")
107         );
108 
109         this.textToTranslate.setText(null);
110         this.textToTranslate.setEditable(false);
111         this.buttonSend.setEnabled(false);  // will be enabled when done with GitHub
112         
113         // Ubuntu Regular is compatible with all required languages, this includes Chinese and Arabic,
114         // but it's not a technical Mono Font.
115         // Only Monospaced works both for copy/paste utf8 foreign characters in JTextArea, and
116         // it's a technical Mono Font.
117         this.textToTranslate.setFont(new Font(
118             UiUtil.FONT_NAME_MONOSPACED,
119             Font.PLAIN,
120             UIManager.getDefaults().getFont("TextField.font").getSize()
121         ));
122         
123         new WorkerTranslateInto(this).execute();
124 
125         this.setIconImage(language.getFlag().getImage());
126         this.setTitle(bundleInto.getString("TRANSLATION_TITLE") +" "+ localeInto.getDisplayLanguage(localeInto));
127         if (!this.isVisible()) {  // Center the dialog
128             this.setSize(640, 460);
129             this.setLocationRelativeTo(MediatorHelper.frame());
130             this.getRootPane().setDefaultButton(this.getButtonSend());
131         }
132         this.setVisible(true);
133     }
134 
135     private JPanel initLastLine() {
136         var lastLine = new JPanel();
137         lastLine.setLayout(new BoxLayout(lastLine, BoxLayout.LINE_AXIS));
138         lastLine.setBorder(UiUtil.BORDER_5PX);
139         
140         this.buttonSend.setToolTipText(
141             String.join(
142                 StringUtils.EMPTY,
143                 "<html>",
144                 "<b>Send your translation to the developer</b><br>",
145                 "Your translation will be integrated in the next version of jSQL",
146                 "</html>"
147             )
148         );
149         
150         this.buttonSend.addActionListener(actionEvent -> {
151             if (this.textToTranslate.getText().equals(this.textBeforeChange)) {
152                 LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Nothing changed, translate a piece of text then click on Send");
153                 return;
154             }
155             
156             // Escape Markdown character # for h1 in .properties
157             String clientDescription = this.textToTranslate.getText()
158                 .replace("\\\\", "\\\\\\\\")
159                 .replaceAll("(?m)^#","\\\\#")
160                 .replace("<", "\\<");
161               
162             MediatorHelper.model().getMediatorUtils().getGitUtil().sendReport(
163                 clientDescription,
164                 ShowOnConsole.YES,
165                 this.languageInto +" translation"
166             );
167             this.setVisible(false);
168         });
169 
170         this.setLayout(new BorderLayout());
171         
172         this.progressBarTranslation.setStringPainted(true);
173         this.progressBarTranslation.setValue(0);
174         
175         lastLine.add(this.progressBarTranslation);
176         lastLine.add(Box.createGlue());
177         lastLine.add(this.buttonSend);
178         return lastLine;
179     }
180 
181     private void initTextToTranslate() {
182         this.textToTranslate.addMouseListener(new MouseAdapter() {
183             @Override
184             public void mousePressed(MouseEvent e) {
185                 super.mousePressed(e);
186                 DialogTranslate.this.textToTranslate.requestFocusInWindow();
187             }
188         });
189         this.textToTranslate.addFocusListener(new FocusAdapter() {
190             @Override
191             public void focusGained(FocusEvent focusEvent) {
192                 DialogTranslate.this.textToTranslate.getCaret().setVisible(true);
193                 DialogTranslate.this.textToTranslate.getCaret().setSelectionVisible(true);
194             }
195         });
196         this.textToTranslate.setBorder(UiUtil.BORDER_5PX);
197         this.textToTranslate.setDragEnabled(true);
198         this.textToTranslate.getCaret().setBlinkRate(500);
199         this.textToTranslate.setComponentPopupMenu(new JPopupMenuText(this.textToTranslate));
200     }
201     
202     
203     // Getter / Setter
204 
205     public Language getLanguageInto() {
206         return this.languageInto;
207     }
208 
209     public String getTextBeforeChange() {
210         return this.textBeforeChange;
211     }
212 
213     public void setTextBeforeChange(String textBeforeChange) {
214         this.textBeforeChange = textBeforeChange;
215     }
216 
217     public JButton getButtonSend() {
218         return this.buttonSend;
219     }
220 
221     public JTextArea getTextToTranslate() {
222         return this.textToTranslate;
223     }
224 
225     public JProgressBar getProgressBarTranslation() {
226         return this.progressBarTranslation;
227     }
228 }