1 /* 2 * $Id$ 3 * 4 * Copyright (c) 2002, 2013, 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.javatest.tool; 28 29 import java.awt.Component; 30 import java.awt.Dimension; 31 import java.awt.event.ActionEvent; 32 import java.awt.event.ActionListener; 33 import java.text.DateFormat; 34 import java.util.*; 35 36 import javax.swing.JButton; 37 import javax.swing.JComponent; 38 import javax.swing.JDialog; 39 import javax.swing.JMenu; 40 import javax.swing.JMenuItem; 41 import javax.swing.JOptionPane; 42 import javax.swing.JPopupMenu; 43 import javax.swing.JPopupMenu.Separator; 44 import javax.swing.ScrollPaneConstants; 45 import javax.swing.JTextArea; 46 import javax.swing.JTextField; 47 import javax.swing.event.MenuEvent; 48 import javax.swing.event.MenuListener; 49 50 import com.sun.interview.Help; 51 import com.sun.javatest.Harness; 52 import com.sun.javatest.ProductInfo; 53 import com.sun.javatest.TestSuite; 54 import com.sun.javatest.tool.jthelp.HelpBroker; 55 import com.sun.javatest.tool.jthelp.HelpSet; 56 import com.sun.javatest.tool.jthelp.JTHelpBroker; 57 58 59 class HelpMenu extends JMenu 60 { 61 HelpMenu(Component parent, Desktop desktop, UIFactory uif) { 62 this.parent = parent; 63 this.desktop = desktop; 64 this.uif = uif; 65 66 listener = new Listener(); 67 68 String[] items = { 69 HELP, 70 null, 71 // test suite items will be dynamically added here 72 // (after the last separator) 73 ABOUT_JAVATEST, 74 ABOUT_JAVA 75 }; 76 uif.initMenu(this, "hm", items, listener); 77 addMenuListener(listener); 78 } 79 80 private void addTestSuiteItems() { 81 Tool[] tools = desktop.getTools(); 82 if (tools == null || tools.length == 0) { 83 return; 84 } 85 86 // first, collect the set of active test suites 87 Set<TestSuite> loadedTestSuites = new TreeSet<>(new Comparator<TestSuite>() { 88 @Override 89 public int compare(TestSuite o1, TestSuite o2) { 90 TestSuite ts1 = o1; 91 TestSuite ts2 = o2; 92 return ts1.getName().compareTo(ts2.getName()); 93 } 94 }); 95 Tool selTool = desktop.getSelectedTool(); 96 if (selTool != null) { 97 TestSuite[] tss = selTool.getLoadedTestSuites(); 98 if (tss != null){ 99 loadedTestSuites.addAll(Arrays.asList(tss)); 100 } 101 } 102 else { 103 for (int i = 0; i < tools.length; i++) { 104 TestSuite[] tss = tools[i].getLoadedTestSuites(); 105 if (tss != null) { 106 loadedTestSuites.addAll(Arrays.asList(tss)); 107 } 108 } 109 } 110 111 112 // locate insert point after last separator 113 int insertPoint = getItemCount() - 1; 114 while (insertPoint > 0 && (getItem(insertPoint - 1) != null)) { 115 insertPoint--; 116 } 117 118 // for the active test suites, add any available help sets to the menu 119 // e.g. those specified in the testsuite.jtt 120 int count = 0; 121 for (Iterator iter = loadedTestSuites.iterator(); iter.hasNext(); ) { 122 TestSuite ts = (TestSuite) (iter.next()); 123 JMenuItem[] menuItems = getMenuItems(ts, count); 124 if (menuItems != null && menuItems.length > 0) { 125 for (int i = 0; i < menuItems.length; i++) { 126 JMenuItem mi = menuItems[i]; 127 // mark the entry as a dynamic entry 128 mi.putClientProperty(getClass(), this); 129 insert(mi, insertPoint++); 130 } 131 132 Separator sep = new Separator(); 133 sep.putClientProperty(getClass(), this); 134 JPopupMenu p = getPopupMenu(); 135 p.insert(sep, insertPoint++); 136 count += menuItems.length + 1; 137 } 138 } 139 140 // add custom menus (as GUI components) 141 // e.g. those that come from exec tool 142 // this is suboptimal/wrong if the test suite uses both 143 // custom GUI menus and help from the testsuite.jtt 144 ToolManager[] mgrs = desktop.getToolManagers(); 145 for (int i = 0; i < mgrs.length; i++) { 146 JMenuItem[] jmi = mgrs[i].getHelpPrimaryMenus(); 147 if (jmi != null) { 148 for (int j = 0; j < jmi.length; j++) { 149 jmi[j].putClientProperty(getClass(), this); 150 insert(jmi[j], insertPoint++); 151 } // inner for 152 } 153 } // for 154 155 // add secondary test suite help items 156 for (int i = 0; i < mgrs.length; i++) { 157 JMenuItem[] jmi = mgrs[i].getHelpTestSuiteMenus(); 158 if (jmi != null) { 159 for (int j = 0; j < jmi.length; j++) { 160 jmi[j].putClientProperty(getClass(), this); 161 insert(jmi[j], insertPoint++); 162 } // inner for (j) 163 } 164 } // for 165 166 // add test suite specified About items 167 for (int i = 0; i < mgrs.length; i++) { 168 JMenuItem[] jmi = mgrs[i].getHelpAboutMenus(); 169 if (jmi != null) { 170 for (int j = 0; j < jmi.length; j++) { 171 jmi[j].putClientProperty(getClass(), this); 172 add(jmi[j]); 173 } // inner for (j) 174 } 175 } // for 176 } 177 178 private void removeTestSuiteItems() { 179 for (Component c : getMenuComponents()) { 180 if (c instanceof JComponent) { 181 JComponent comp = (JComponent) c; 182 if (comp.getClientProperty(getClass()) == this) { 183 remove(comp); 184 } 185 } 186 } 187 } 188 189 /** 190 * Display a multi-line string in a dialog window, in response 191 * to a Help>About.... menu item. 192 * @param contKey i18n bundle key for getting accessibility name and desc 193 * for the container 194 * @param filedKey i18n bundle key for getting accessibility name and desc 195 * for each of the fields holding the "about" text 196 */ 197 private void showAbout(String title, String s, String contKey, String fieldKey) { 198 List<String> v = new ArrayList<>(); 199 int start = 0; 200 int end = 0; 201 202 while ((end = s.indexOf('\n', start)) != -1) { 203 v.add(s.substring(start, end)); 204 start = end+1; 205 } 206 v.add(s.substring(start)); 207 208 //JTextField[] tfs = new JTextField[v.size()]; 209 ArrayList<JComponent> tfs = new ArrayList<>(); 210 for (int i = 0; i < v.size(); i++) { 211 JTextField tf = new JTextField(v.get(i)); 212 tf.setBorder(null); 213 tf.setHorizontalAlignment(JTextField.CENTER); 214 tf.setOpaque(false); 215 tf.setBackground(UIFactory.Colors.TRANSPARENT.getValue()); 216 tf.setEditable(false); 217 uif.setAccessibleInfo(tf, fieldKey); 218 tfs.add(tf); 219 } 220 221 JTextArea ta = uif.createMessageArea("hm.aboutJavaTest.copy"); 222 ta.setRows(15); 223 tfs.add(uif.createScrollPane(ta, 224 ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, 225 ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED)); 226 Object[] fields = tfs.toArray(); 227 228 /* 229 JOptionPane.showMessageDialog(parent, 230 tfs, 231 title, 232 JOptionPane.INFORMATION_MESSAGE, 233 desktop.getLogo()); 234 */ 235 JOptionPane pane = new JOptionPane(fields, JOptionPane.INFORMATION_MESSAGE); 236 pane.setIcon(desktop.getLogo()); 237 pane.setOptionType(JOptionPane.OK_OPTION); 238 uif.setAccessibleInfo(pane, contKey); 239 JButton okBtn = uif.createCloseButton("hm.about.ok", false); 240 pane.setOptions(new Object[] { okBtn }); 241 JDialog d = pane.createDialog(parent, title); 242 d.getRootPane().setDefaultButton(okBtn); 243 d.setVisible(true); 244 } 245 246 private void showHelpSet(HelpSet hs) { 247 HelpBroker hb = getHelpBroker(hs); 248 if (hb != null) { 249 //hb.setDisplayed(true); 250 //if (hb instanceof DefaultHelpBroker) 251 // ((DefaultHelpBroker) hb).getWindowPresentation().getHelpWindow().toFront(); 252 } 253 else { 254 // could internationalize this, but the error isn't that helpful because a 255 // end-user probably can't fix the problem 256 System.err.println("Unable to display help, the help set isn't available."); 257 } 258 } 259 260 private HelpBroker getHelpBroker(HelpSet hs) { 261 HelpBroker hb = helpBrokerTable.get(hs); 262 if (hb == null) { 263 //hb = hs.createHelpBroker(); // pres. attributes work with this on JH 2.0_02 264 hb = new JTHelpBroker(); 265 helpBrokerTable.put(hs, hb); 266 } 267 return hb; 268 } 269 270 private JMenuItem[] getMenuItems(TestSuite ts, int count) { 271 HelpSet[] docs = docTable.get(ts); 272 if (docs == null) { 273 try { 274 docs = Help.getAdditionalDocs(ts); 275 } 276 catch (Help.Fault e) { 277 String msg = uif.getI18NString("hm.cantLoadDocs", 278 new Object[] { ts.getName(), e.getMessage() }); 279 System.err.println(msg); 280 } 281 if (docs == null) 282 docs = new HelpSet[0]; 283 docTable.put(ts, docs); 284 } 285 286 if (docs.length == 0) { 287 return null; 288 } 289 290 ArrayList<JMenuItem> v = new ArrayList<>(); 291 for (int i = 0; i < docs.length; i++) { 292 final HelpSet doc = docs[i]; 293 294 JMenuItem mi; 295 if (count + i < 10) { 296 mi = new JMenuItem((count + i) + " " + doc.getTitle()); 297 mi.setMnemonic('0' + count + i); 298 } 299 else { 300 mi = new JMenuItem(" " + doc.getTitle()); 301 } 302 303 mi.addActionListener(new ActionListener() { 304 @Override 305 public void actionPerformed(ActionEvent e) { 306 showHelpSet(doc); 307 } 308 }); 309 310 v.add(mi); 311 } 312 313 JMenuItem[]items = new JMenuItem[v.size()]; 314 v.toArray(items); 315 return items; 316 } 317 318 private Component parent; 319 private Desktop desktop; 320 private UIFactory uif; 321 322 private Listener listener; 323 324 private static Map<TestSuite, HelpSet[]> docTable = new WeakHashMap<>(); // gives HelpSet[] for TestSuite 325 private static Map<HelpSet, HelpBroker> helpBrokerTable = new WeakHashMap<>(); // gives HelpBroker for HelpSet 326 327 private static final String HELP = "help"; 328 private static final String ABOUT_JAVA = "aboutJava"; 329 private static final String ABOUT_JAVATEST = "aboutJavaTest"; 330 331 private class Listener 332 implements MenuListener, ActionListener 333 { 334 @Override 335 public void menuSelected(MenuEvent e) { 336 // remove any prior items 337 removeTestSuiteItems(); 338 // add current ones 339 addTestSuiteItems(); 340 } 341 342 @Override 343 public void menuDeselected(MenuEvent e) { 344 } 345 346 @Override 347 public void menuCanceled(MenuEvent e) { 348 } 349 350 @Override 351 public void actionPerformed(ActionEvent e) { 352 String cmd = e.getActionCommand(); 353 if (cmd.equals(ABOUT_JAVATEST)) { 354 JMenuItem src = (JMenuItem)(e.getSource()); 355 356 // read en_US date, and prepare to emit it using the 357 // current locale 358 DateFormat df = DateFormat.getDateInstance(DateFormat.LONG); 359 String date = null; 360 Date dt = ProductInfo.getBuildDate(); 361 if (dt != null) { 362 date = df.format(dt); 363 } 364 else { 365 date = uif.getI18NString("hm.aboutBadDate"); 366 } 367 368 String aboutJavaTest = 369 uif.getI18NString("hm.aboutJavaTest", new Object[] { 370 ProductInfo.getName(), 371 ProductInfo.getVersion(), 372 ProductInfo.getMilestone(), 373 ProductInfo.getBuildNumber(), 374 Harness.getClassDir().getPath(), 375 ProductInfo.getBuildJavaVersion(), 376 date 377 }); 378 showAbout(src.getText(), aboutJavaTest, "hm.aboutJavaTest", 379 "hm.aboutJavaTest.text"); 380 } 381 else if (cmd.equals(ABOUT_JAVA)) { 382 JMenuItem src = (JMenuItem)(e.getSource()); 383 String aboutJava = 384 uif.getI18NString("hm.aboutJava", new Object[] { 385 System.getProperty("java.version"), 386 System.getProperty("java.vendor"), 387 System.getProperty("java.home"), 388 System.getProperty("java.vendor.url") 389 }); 390 showAbout(src.getText(), aboutJava, "hm.aboutJava", "hm.aboutJava.text"); 391 } 392 else if (cmd.equals(HELP)) { 393 HelpBroker helpBroker = desktop.getHelpBroker(); 394 if (helpBroker != null) { 395 helpBroker.displayCurrentID("jthelp.csh"); 396 } 397 else { 398 // could internationalize this, but the error isn't that helpful because a 399 // end-user probably can't fix the problem 400 System.err.println("Unable to display help, the help system isn't available."); 401 } 402 } 403 } 404 405 } 406 }