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