1 /* 2 * $Id$ 3 * 4 * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved. 5 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6 * 7 * This code is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License version 2 only, as 9 * published by the Free Software Foundation. Oracle designates this 10 * particular file as subject to the "Classpath" exception as provided 11 * by Oracle in the LICENSE file that accompanied this code. 12 * 13 * This code is distributed in the hope that it will be useful, but WITHOUT 14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16 * version 2 for more details (a copy is included in the LICENSE file that 17 * accompanied this code). 18 * 19 * You should have received a copy of the GNU General Public License version 20 * 2 along with this work; if not, write to the Free Software Foundation, 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 22 * 23 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 24 * or visit www.oracle.com if you need additional information or have any 25 * questions. 26 */ 27 package com.sun.interview.wizard; 28 29 import java.awt.BorderLayout; 30 import java.awt.Component; 31 import java.awt.Container; 32 import java.awt.Dialog; 33 import java.awt.Frame; 34 import java.awt.GridBagConstraints; 35 import java.awt.GridBagLayout; 36 import java.awt.event.ActionEvent; 37 import java.awt.event.ActionListener; 38 import java.util.Hashtable; 39 import java.util.Map; 40 import javax.accessibility.AccessibleContext; 41 import javax.swing.BorderFactory; 42 import javax.swing.DefaultListCellRenderer; 43 import javax.swing.JButton; 44 import javax.swing.JCheckBox; 45 import javax.swing.JComboBox; 46 import javax.swing.JComponent; 47 import javax.swing.JDialog; 48 import javax.swing.JLabel; 49 import javax.swing.JList; 50 import javax.swing.JPanel; 51 import javax.swing.JTextField; 52 import javax.swing.KeyStroke; 53 import javax.swing.SwingUtilities; 54 import com.sun.interview.Interview; 55 import com.sun.interview.Question; 56 import com.sun.javatest.tool.jthelp.HelpBroker; 57 58 class SearchDialog extends JDialog 59 { 60 static SearchDialog create(Component parent, Interview i, 61 HelpBroker helpBroker, String helpPrefix) { 62 Dialog d = (Dialog)(SwingUtilities.getAncestorOfClass(Dialog.class, parent)); 63 if (d != null) 64 return new SearchDialog(d, i, helpBroker, helpPrefix); 65 else { 66 Frame f = (Frame)(SwingUtilities.getAncestorOfClass(Frame.class, parent)); 67 return new SearchDialog(f, i, helpBroker, helpPrefix); 68 } 69 } 70 71 SearchDialog(Frame parent, Interview i, HelpBroker helpBroker, String helpPrefix) { 72 super(parent); 73 init(parent, i, helpBroker, helpPrefix); 74 } 75 76 SearchDialog(Dialog parent, Interview i, HelpBroker helpBroker, String helpPrefix) { 77 super(parent); 78 init(parent, i, helpBroker, helpPrefix); 79 } 80 81 private void init(Component parent, Interview i, HelpBroker helpBroker, String helpPrefix) { 82 interview = i; 83 this.helpBroker = helpBroker; 84 this.helpPrefix = helpPrefix; 85 86 setName("find"); 87 setTitle(i18n.getString("find.title")); 88 AccessibleContext ac = getAccessibleContext(); 89 ac.setAccessibleName(i18n.getString("find.name")); 90 ac.setAccessibleDescription(i18n.getString("find.desc")); 91 92 Container contentPane = getContentPane(); 93 contentPane.setName("content"); 94 contentPane.setFocusable(false); 95 contentPane.setLayout(new BorderLayout()); 96 97 JPanel p = new JPanel(new GridBagLayout()); 98 p.setName("main"); 99 p.setFocusable(false); 100 101 GridBagConstraints lc = new GridBagConstraints(); 102 lc.anchor = GridBagConstraints.EAST; 103 lc.insets.right = 10; 104 105 GridBagConstraints c = new GridBagConstraints(); 106 c.fill = GridBagConstraints.HORIZONTAL; 107 c.gridwidth = GridBagConstraints.REMAINDER; 108 c.weightx = 1; 109 110 JLabel textLbl = createLabel("find.field", true); 111 p.add(textLbl, lc); 112 113 textField = new JTextField("", 32); 114 textField.setName("find.text"); 115 textField.addActionListener(listener); 116 textField.setActionCommand(FIND); 117 textField.setToolTipText(textLbl.getAccessibleContext().getAccessibleDescription()); 118 textLbl.setLabelFor(textField); 119 c.insets.bottom = 10; 120 p.add(textField, c); 121 122 JLabel whereLbl = createLabel("find.where", true); 123 p.add(whereLbl, lc); 124 125 String[] choices = {TITLE, QUESTION, ANSWER, ANYWHERE}; 126 whereChoice = createChoice("find.where", choices); 127 whereLbl.setLabelFor(whereChoice); 128 c.anchor = GridBagConstraints.WEST; 129 c.fill = GridBagConstraints.NONE; 130 c.insets.bottom = 0; 131 p.add(whereChoice, c); 132 133 JLabel optionsLbl = createLabel("find.options", false); 134 p.add(optionsLbl, lc); 135 136 JPanel p2 = new JPanel(); 137 p2.setName("options"); 138 p2.setFocusable(false); 139 140 caseChk = createCheckBox("find.case"); 141 p2.add(caseChk); 142 wordChk = createCheckBox("find.word"); 143 p2.add(wordChk); 144 p.add(p2, c); 145 146 p.registerKeyboardAction(listener, CLOSE, escapeKey, 147 JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); 148 p.setBorder(BorderFactory.createEmptyBorder(/*top*/12, /*left*/12, /*bottom*/0, /*right*/11)); 149 150 contentPane.add(p, BorderLayout.CENTER); 151 152 JPanel btns = new JPanel(new GridBagLayout()); 153 btns.setName("btns"); 154 btns.setFocusable(false); 155 c = new GridBagConstraints(); 156 c.weightx = 1; 157 c.anchor = GridBagConstraints.EAST; 158 btns.add(createButton("find.find", FIND, listener), c); 159 c.insets.left = 5; 160 c.weightx = 0; 161 btns.add(createButton("find.close", CLOSE, listener), c); 162 if (helpBroker != null) 163 btns.add(createButton("find.help", HELP, listener), c); 164 165 btns.setBorder(BorderFactory.createEmptyBorder(/*top*/11, /*left*/12, /*bottom*/11, /*right*/11)); 166 167 contentPane.add(btns, BorderLayout.SOUTH); 168 169 if (helpBroker != null) 170 helpBroker.enableHelpKey(getRootPane(), helpPrefix + "search.csh"); 171 172 pack(); 173 setLocationRelativeTo(parent); 174 } 175 176 public void setVisible(boolean b) { 177 super.setVisible(b); 178 if (b) 179 textField.requestFocus(); 180 } 181 182 public void find() { 183 if (textField.getText().length() == 0) 184 setVisible(true); 185 else { 186 // just get this once for the query 187 Map<String, String> answers = new Hashtable<>(); 188 interview.save(answers); 189 Question[] path = interview.getPath(); 190 Question curr = interview.getCurrentQuestion(); 191 for (int i = 0; i < path.length; i++) { 192 if (path[i] == curr) { 193 for (int j = 0; j < path.length; j++) { 194 Question q = path[(i + 1 + j)%path.length]; 195 String answer = answers.get(q.getTag()); 196 if (matches(q, answer, caseChk.isSelected(), wordChk.isSelected())) { 197 try { 198 interview.setCurrentQuestion(q); 199 } 200 catch (Interview.Fault e) { 201 } 202 return; 203 } 204 } 205 getToolkit().beep(); 206 return; 207 } 208 } 209 } 210 } 211 212 private boolean matches(Question q, String answer, boolean considerCase, boolean word) { 213 String text = textField.getText(); 214 String where = (String)(whereChoice.getSelectedItem()); 215 if (where.equals(TITLE)) 216 return match(text, q.getSummary(), considerCase, word); 217 else if (where.equals(QUESTION)) 218 return match(text, q.getText(), considerCase, word); 219 else if (where.equals(ANSWER)) 220 return (answer != null && match(text, answer, considerCase, word)); 221 else 222 return ( match(text, q.getSummary(), considerCase, word) || 223 match(text, q.getText(), considerCase, word) || 224 (answer != null && match(text, answer, considerCase, word)) ); 225 } 226 227 private static boolean match(String s1, String s2, boolean considerCase, boolean word) { 228 int s1len = s1.length(); 229 int s2len = s2.length(); 230 for (int i = 0; i <= s2len - s1len; i++) { 231 if (s1.regionMatches(!considerCase, 0, s2, i, s1len)) { 232 if (word) 233 return ( (i == 0 || isBoundaryCh(s2.charAt(i-1))) 234 && (i+s1len == s2.length() || isBoundaryCh(s2.charAt(i+s1len))) ); 235 else 236 return true; 237 } 238 } 239 return false; 240 } 241 242 private static boolean isBoundaryCh(char c) { 243 return !(Character.isUnicodeIdentifierStart(c) 244 || Character.isUnicodeIdentifierPart(c)); 245 } 246 247 private JButton createButton(String uiKey, String actionCommand, ActionListener l) { 248 JButton b = new JButton(i18n.getString(uiKey + ".btn")); 249 b.setName(uiKey); 250 b.setMnemonic(getMnemonic(uiKey)); 251 b.setActionCommand(actionCommand); 252 b.addActionListener(l); 253 setToolTipText(b, uiKey); 254 //b.registerKeyboardAction(listener, actionCommand, enterKey, JComponent.WHEN_FOCUSED); 255 return b; 256 } 257 258 private JCheckBox createCheckBox(String uiKey) { 259 JCheckBox b = new JCheckBox(i18n.getString(uiKey + ".ckb")); 260 b.setName(uiKey); 261 b.setMnemonic(getMnemonic(uiKey)); 262 setToolTipText(b, uiKey); 263 return b; 264 } 265 266 private JComboBox<String> createChoice(final String uiKey, final String[] choiceKeys) { 267 // create a cache of the presentation string, for use when 268 // rendering, but otherwise, let the JComboBox work in terms of the 269 // choiceKeys 270 final String[] choices = new String[choiceKeys.length]; 271 for (int i = 0; i < choices.length; i++) 272 choices[i] = i18n.getString(uiKey + "." + choiceKeys[i] + ".chc"); 273 274 JComboBox<String> choice = new JComboBox<>(choiceKeys); 275 choice.setName(uiKey); 276 AccessibleContext ac = choice.getAccessibleContext(); 277 ac.setAccessibleName(i18n.getString(uiKey + ".tip")); 278 279 choice.setRenderer(new DefaultListCellRenderer() { 280 public Component getListCellRendererComponent(JList<?> list, Object o, int index, boolean isSelected, boolean cellHasFocus) { 281 Object c = o; 282 for (int i = 0; i < choiceKeys.length; i++) { 283 if (choiceKeys[i] == o) { 284 c = choices[i]; 285 break; 286 } 287 } 288 return super.getListCellRendererComponent(list, c, index, isSelected, cellHasFocus); 289 } 290 }); 291 292 setToolTipText(choice, uiKey); 293 ac.setAccessibleDescription(choice.getToolTipText()); 294 return choice; 295 } 296 297 private JLabel createLabel(String uiKey, boolean needMnemonic) { 298 JLabel l = new JLabel(i18n.getString(uiKey + ".lbl")); 299 l.setName(uiKey); 300 if (needMnemonic) 301 l.setDisplayedMnemonic(getMnemonic(uiKey)); 302 setToolTipText(l, uiKey); 303 return l; 304 } 305 306 private char getMnemonic(String uiKey) { 307 return i18n.getString(uiKey + ".mne").charAt(0); 308 } 309 310 private void setToolTipText(JComponent c, String uiKey) { 311 c.setToolTipText(i18n.getString(uiKey + ".tip")); 312 } 313 314 private ActionListener listener = new ActionListener() { 315 public void actionPerformed(ActionEvent e) { 316 String cmd = e.getActionCommand(); 317 if (cmd.equals(FIND)) 318 find(); 319 else if (cmd.equals(CLOSE)) 320 setVisible(false); 321 else if (cmd.equals(HELP)) { 322 helpBroker.displayCurrentID(helpPrefix + "search.csh"); 323 } 324 } 325 }; 326 327 private Interview interview; 328 private Question currentQuestion; 329 private HelpBroker helpBroker; 330 private String helpPrefix; 331 private JTextField textField; 332 private JComboBox<String> whereChoice; 333 private JCheckBox caseChk; 334 private JCheckBox wordChk; 335 336 private static final String ANSWER = "answer"; 337 private static final String ANYWHERE = "anywhere"; 338 private static final String CLOSE = "close"; 339 private static final String FIND = "find"; 340 private static final String HELP = "help"; 341 private static final String QUESTION = "question"; 342 private static final String TITLE = "title"; 343 private static final KeyStroke escapeKey = KeyStroke.getKeyStroke("ESCAPE"); 344 345 private static final I18NResourceBundle i18n = I18NResourceBundle.getDefaultBundle(); 346 }