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}