001package com.ganteater.ae.desktop.ui;
002
003import java.awt.BorderLayout;
004import java.awt.Component;
005import java.awt.Dimension;
006import java.awt.EventQueue;
007import java.awt.Frame;
008import java.awt.Toolkit;
009import java.awt.datatransfer.Clipboard;
010import java.awt.datatransfer.DataFlavor;
011import java.awt.datatransfer.Transferable;
012import java.awt.datatransfer.UnsupportedFlavorException;
013import java.awt.event.ActionEvent;
014import java.awt.event.ActionListener;
015import java.awt.event.KeyAdapter;
016import java.awt.event.KeyEvent;
017import java.awt.event.MouseAdapter;
018import java.awt.event.MouseEvent;
019import java.io.File;
020import java.io.IOException;
021import java.io.InputStream;
022import java.net.URL;
023import java.util.Arrays;
024import java.util.regex.Matcher;
025import java.util.regex.Pattern;
026
027import javax.swing.BorderFactory;
028import javax.swing.ImageIcon;
029import javax.swing.JComboBox;
030import javax.swing.JComponent;
031import javax.swing.JDialog;
032import javax.swing.JEditorPane;
033import javax.swing.JLabel;
034import javax.swing.JOptionPane;
035import javax.swing.JPanel;
036import javax.swing.JPasswordField;
037import javax.swing.JRootPane;
038import javax.swing.JScrollPane;
039import javax.swing.JTextField;
040import javax.swing.SwingUtilities;
041
042import org.apache.commons.lang.StringUtils;
043
044import com.ganteater.ae.TaskCancelingException;
045import com.ganteater.ae.desktop.InputDialogType;
046import com.ganteater.ae.desktop.util.SoundManager;
047import com.ganteater.ae.desktop.util.UIUtils;
048
049public class OptionPane {
050
051        private static final String SKIP = "Skip";
052
053        private static final String OK = "OK";
054
055        protected static final String[] OPTIONS = new String[] { OK, SKIP };
056
057        private OptionPane() {
058                super();
059        }
060
061        public static int showOptionDialog(Component parentComponent, Object message, String title, int messageType) {
062                return showOptionDialog(parentComponent, message, title, messageType, false, OPTIONS);
063        }
064
065        public static int showOptionDialog(Component parentComponent, Object message, String title, int messageType,
066                        boolean modal, Object[] options) {
067                int result = 0;
068
069                ImageIcon icon = null;
070                if (messageType > 3) {
071                        icon = AEFrame.getIcon("logo.png");
072                }
073
074                JOptionPane pane = new JOptionPane(message, JOptionPane.QUESTION_MESSAGE, JOptionPane.CANCEL_OPTION, icon,
075                                options);
076
077                if (messageType <= 3) {
078                        pane.setMessageType(messageType);
079                }
080
081                JDialog dialog = pane.createDialog(parentComponent, title);
082                dialog.setModal(modal);
083
084                if (!parentComponent.isVisible()) {
085                        dialog.setAlwaysOnTop(true);
086                }
087
088                if (!UIUtils.applyPreferedView(dialog, title)) {
089                        dialog.pack();
090                }
091
092                if (message instanceof JPanel) {
093                        JPanel panel = (JPanel) message;
094                        if (panel.getComponentCount() > 2) {
095                                try {
096                                        Component component = panel.getComponent(2);
097                                        if (component instanceof CheckPointBox) {
098                                                component = panel.getComponent(1);
099                                        }
100                                        if (component instanceof JTextField) {
101                                                JTextField field = (JTextField) component;
102                                                field.addKeyListener(new KeyAdapter() {
103                                                        @Override
104                                                        public void keyPressed(KeyEvent e) {
105                                                                switch (e.getKeyCode()) {
106                                                                case KeyEvent.VK_ENTER:
107                                                                        pane.setValue(OK);
108                                                                        break;
109                                                                case KeyEvent.VK_ESCAPE:
110                                                                        pane.setValue(SKIP);
111                                                                        break;
112                                                                default:
113                                                                }
114                                                        }
115                                                });
116                                                field.addMouseListener(new MouseAdapter() {
117                                                        @Override
118                                                        public void mouseClicked(MouseEvent e) {
119                                                                if (e.getButton() == MouseEvent.BUTTON3) {
120                                                                        Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
121                                                                        Transferable contents = clipboard.getContents(null);
122                                                                        if (contents != null && contents.isDataFlavorSupported(DataFlavor.stringFlavor)) {
123                                                                                try {
124                                                                                        String text = (String) contents.getTransferData(DataFlavor.stringFlavor);
125                                                                                        field.setText(text);
126                                                                                } catch (UnsupportedFlavorException | IOException e1) {
127                                                                                        //
128                                                                                }
129                                                                        }
130                                                                }
131                                                        }
132                                                });
133                                                EventQueue.invokeLater(() -> {
134                                                        field.grabFocus();
135                                                        field.requestFocusInWindow();
136                                                        field.requestFocus();
137                                                        field.selectAll();
138                                                });
139                                                dialog.pack();
140                                        } else if (component instanceof JComboBox) {
141                                                @SuppressWarnings("unchecked")
142                                                JComboBox<String> combo = (JComboBox<String>) component;
143                                                combo.getEditor().addActionListener(new ActionListener() {
144                                                        @Override
145                                                        public void actionPerformed(ActionEvent e) {
146                                                                pane.setValue(OK);
147                                                        }
148                                                });
149
150                                                SwingUtilities.invokeLater(() -> {
151                                                        combo.grabFocus();
152                                                        combo.requestFocus();
153                                                });
154                                                dialog.pack();
155                                        } else {
156                                                dialog.setResizable(true);
157                                        }
158                                } catch (ArrayIndexOutOfBoundsException e) {
159                                        e.printStackTrace();
160                                }
161                        } else {
162                                dialog.pack();
163                                dialog.setResizable(false);
164                        }
165                }
166
167                dialog.setVisible(true);
168
169                Object value = null;
170                do {
171                        value = pane.getValue();
172                        try {
173                                Thread.sleep(100);
174                        } catch (InterruptedException e) {
175                                Thread.currentThread().interrupt();
176                        }
177                } while (value == "uninitializedValue");
178
179                UIUtils.saveDialogPreferedView(dialog, title);
180                dialog.dispose();
181
182                if (value == null) {
183                        result = -1;
184                } else if (SKIP.equals(value)) {
185                        result = JOptionPane.CANCEL_OPTION;
186                } else if (OK.equals(value)) {
187                        result = JOptionPane.OK_OPTION;
188                } else if (value instanceof Integer) {
189                        result = (int) value;
190                } else {
191                        result = Arrays.binarySearch(options, value);
192                }
193
194                SoundManager.stop();
195                return result;
196        }
197
198        public static int showConfirmDialog(Frame frame, JComponent panel, String title) {
199                return showOptionDialog(frame, panel, title, JOptionPane.QUESTION_MESSAGE);
200        }
201
202        public static String showInputDialog(Component rootPane, String message, String title, Object[] list,
203                        String newValueTitle) {
204                JPanel panel = new JPanel(new BorderLayout());
205                JLabel label = new JLabel(message);
206                panel.add(label, BorderLayout.NORTH);
207                @SuppressWarnings({ "rawtypes", "unchecked" })
208                JComboBox inputField = new JComboBox(list);
209
210                inputField.setEditable(true);
211                inputField.setSelectedItem(newValueTitle);
212
213                panel.add(inputField, BorderLayout.CENTER);
214
215                CheckPointBox vip = new CheckPointBox(title, null, InputDialogType.VAR);
216                panel.add(vip, BorderLayout.SOUTH);
217                int showOptionDialog = showOptionDialog(rootPane, panel, title, 3, true, OPTIONS);
218                if (showOptionDialog == -1) {
219                        throw new TaskCancelingException();
220                }
221                return showOptionDialog == 2 ? null : (String) inputField.getSelectedItem();
222        }
223
224        public static String showInputPasswordDialog(String description, String aValue, Component southComp,
225                        int messageType, Object[] options) {
226                String result = null;
227                JPanel panel = new JPanel(new BorderLayout(4, 4));
228                JLabel label = new JLabel(description);
229                JPasswordField pass = new JPasswordField(20);
230                pass.putClientProperty("JPasswordField.cutCopyAllowed", true);
231
232                pass.setText(aValue);
233
234                panel.add(label, BorderLayout.NORTH);
235                panel.add(pass, BorderLayout.CENTER);
236
237                if (southComp != null) {
238                        panel.add(southComp, BorderLayout.SOUTH);
239                }
240
241                Frame rootFrame = JOptionPane.getRootFrame();
242
243                int option = OptionPane.showOptionDialog(rootFrame, panel, "Input a password", messageType, false, options);
244
245                switch (option) {
246                case JOptionPane.OK_OPTION:
247                        char[] password = pass.getPassword();
248                        result = new String(password);
249                        break;
250                case JOptionPane.CANCEL_OPTION:
251                case JOptionPane.NO_OPTION:
252                        result = null;
253                        break;
254                case JOptionPane.CLOSED_OPTION:
255                        throw new TaskCancelingException();
256                default:
257                        result = Integer.toString(option);
258                }
259                return result;
260        }
261
262        public static void showMessageDialog(AEFrame frame, String text, String title, int type) {
263                JEditorPane textPane = new JEditorPane();
264                textPane.setContentType("text/html");
265
266                Pattern pattern = Pattern.compile("\"(http://.*?|https://.*?|file:.*?)\"");
267                Matcher matcher = pattern.matcher(text);
268                while (matcher.find()) {
269                        String group = matcher.group();
270
271                        boolean enable = true;
272                        group = StringUtils.substring(group, 1, group.length() - 1);
273                        group = group.replace("file:", "");
274
275                        File file = new File(group);
276                        if (!file.exists()) {
277                                try (InputStream openStream = new URL(group).openStream()) {
278                                } catch (IOException e) {
279                                        enable = false;
280                                }
281                        }
282
283                        if (enable) {
284                                text = text.replace(group, "<a href=\"" + group + "\">" + group + "</a>");
285                        }
286                }
287                textPane.setText(text.replace("\n", "<br/>"));
288
289                textPane.addHyperlinkListener(new HyperlinkAdapter(frame.getWorkspace()));
290
291                textPane.setOpaque(false);
292                textPane.setEditable(false);
293
294                JOptionPane pane = new JOptionPane(new JScrollPane(textPane), type);
295                JDialog dialog = pane.createDialog(pane, title);
296                dialog.setResizable(true);
297                dialog.setPreferredSize(new Dimension(600, 300));
298
299                if (!UIUtils.applyPreferedView(dialog, title)) {
300                        dialog.pack();
301                }
302
303                dialog.setVisible(true);
304
305                Object value = null;
306                do {
307                        value = pane.getValue();
308                        try {
309                                Thread.sleep(100);
310                        } catch (InterruptedException e) {
311                                Thread.currentThread().interrupt();
312                        }
313                } while (value == "uninitializedValue");
314
315                UIUtils.saveDialogPreferedView(dialog, title);
316                dialog.dispose();
317
318        }
319
320        public static String showInputDialog(JRootPane rootPane, String title, String message, String defaultValue) {
321                JPanel panel = new JPanel(new BorderLayout());
322                JLabel label = new JLabel(message);
323                label.setBorder(BorderFactory.createEmptyBorder(0, 0, 6, 0));
324                panel.add(label, BorderLayout.NORTH);
325                @SuppressWarnings({ "rawtypes", "unchecked" })
326                JTextField inputField = new JTextField(defaultValue);
327
328                inputField.setEditable(true);
329                panel.add(inputField, BorderLayout.CENTER);
330                
331                CheckPointBox vip = new CheckPointBox(title, null, InputDialogType.VAR);
332                panel.add(vip, BorderLayout.SOUTH);
333                
334                int showOptionDialog = showOptionDialog(rootPane, panel, title, 3, true, OPTIONS);
335
336                if (showOptionDialog == -1) {
337                        throw new TaskCancelingException();
338                }
339
340                return showOptionDialog == 2 ? null : (String) inputField.getText();
341        }
342
343}