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