1 /* 2 * $Id$ 3 * 4 * Copyright (c) 2006, 2012, 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.mrep; 28 29 import com.sun.javatest.CompositeFilter; 30 import com.sun.javatest.InterviewParameters; 31 import com.sun.javatest.TestFilter; 32 import java.awt.BorderLayout; 33 import java.awt.CardLayout; 34 import java.awt.Color; 35 import java.awt.Component; 36 import java.awt.Container; 37 import java.awt.GridBagConstraints; 38 import java.awt.GridBagLayout; 39 import java.awt.GridLayout; 40 import java.awt.Insets; 41 import java.awt.Toolkit; 42 import java.awt.event.ActionListener; 43 import java.awt.event.KeyEvent; 44 import java.awt.event.KeyListener; 45 import java.awt.event.MouseEvent; 46 import java.beans.PropertyChangeEvent; 47 import java.beans.PropertyChangeListener; 48 import java.util.*; 49 50 import javax.swing.BorderFactory; 51 import javax.swing.DefaultListModel; 52 import javax.swing.JButton; 53 import javax.swing.JCheckBox; 54 import javax.swing.JComponent; 55 import javax.swing.JLabel; 56 import javax.swing.JList; 57 import javax.swing.JPanel; 58 import javax.swing.JTabbedPane; 59 import javax.swing.JTextArea; 60 import javax.swing.ListCellRenderer; 61 import javax.swing.ListModel; 62 import javax.swing.ListSelectionModel; 63 import javax.swing.event.ListSelectionEvent; 64 import javax.swing.event.ListSelectionListener; 65 import javax.swing.event.MouseInputAdapter; 66 67 import com.sun.javatest.exec.ContextManager; 68 import com.sun.javatest.exec.ExecTool; 69 import com.sun.javatest.report.CustomReport; 70 import com.sun.javatest.report.CustomReport.ReportConfigPanel; 71 import com.sun.javatest.report.Report; 72 import com.sun.javatest.report.ReportSettings; 73 import com.sun.javatest.tool.Desktop; 74 import com.sun.javatest.tool.Tool; 75 import com.sun.javatest.tool.UIFactory; 76 import java.awt.Font; 77 78 class OptionsPane extends JPanel { 79 80 OptionsPane(UIFactory uif, Desktop desktop, ActionListener chTabListener, 81 ActionListener okListener) { 82 this.uif = uif; 83 this.desktop = desktop; 84 this.chTabListener = chTabListener; 85 this.okListener = okListener; 86 initGUI(); 87 } 88 89 boolean resolveByRecent() { 90 return resolveAsRecentBox.isSelected(); 91 } 92 93 boolean isXmlReport() { 94 return cbXml.isSelected(); 95 } 96 97 CustomReport[] getCustomSelected() { 98 return getActiveCustomReports().toArray(new CustomReport[0]); 99 } 100 protected void initGUI() { 101 setName("opts"); 102 setFocusable(false); 103 setLayout(new GridBagLayout()); 104 setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); 105 106 JLabel title = uif.createLabel("opts.title"); 107 GridBagConstraints lc = new GridBagConstraints(); 108 lc.gridwidth = GridBagConstraints.REMAINDER; 109 lc.anchor = GridBagConstraints.WEST; 110 lc.insets = new Insets(5,5,15,5); 111 lc.fill = GridBagConstraints.HORIZONTAL; 112 lc.weightx = 1.0; 113 this.add(title, lc); 114 115 lc = new GridBagConstraints(); 116 lc.anchor = GridBagConstraints.NORTHEAST; 117 lc.gridheight = 2; 118 lc.insets.right = 10; 119 JLabel conflictLabel = uif.createLabel("opts.conflict", true); 120 this.add(conflictLabel, lc); 121 122 handleConfilctsBox = uif.createCheckBox("opts.handleconflict", true); 123 lc = new GridBagConstraints(); 124 lc.anchor = GridBagConstraints.NORTHEAST; 125 lc.fill = GridBagConstraints.HORIZONTAL; 126 lc.gridwidth = GridBagConstraints.REMAINDER; 127 handleConfilctsBox.setEnabled(false); 128 this.add(handleConfilctsBox, lc); 129 130 resolveAsRecentBox = uif.createCheckBox("opts.resolverecent", true); 131 lc = new GridBagConstraints(); 132 lc.anchor = GridBagConstraints.NORTHEAST; 133 lc.fill = GridBagConstraints.HORIZONTAL; 134 this.add(resolveAsRecentBox, lc); 135 136 // -------------------------------------------------------------------------------- 137 JPanel bottom = uif.createPanel("opts.bottom", false); 138 bottom.setLayout(new BorderLayout()); 139 bottom.setBorder(BorderFactory.createCompoundBorder( 140 uif.createTitledBorder("opts.bottom"), 141 BorderFactory.createEmptyBorder(12,12,12,12))); 142 143 144 listModel = new DefaultListModel<>(); 145 146 // populate list and card panel 147 final CardLayout cards = new CardLayout(); 148 final JPanel p = uif.createPanel("opts.typecards", cards, false); 149 150 // standard report 151 cbXml = uif.createCheckBox("opts.type.xml", false); 152 listModel.addElement(cbXml); 153 p.add("opts.type.xml", uif.createPanel("opts.blank", false)); 154 155 // custom entries 156 getCustomReports(p); 157 158 list = uif.createList("opts.typel", listModel); 159 list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 160 SelectListener sl = new SelectListener(list, p, cards); 161 list.addMouseListener(sl); 162 list.addKeyListener(sl); 163 list.addListSelectionListener(sl); 164 list.setCellRenderer(new CheckBoxListCellRenderer()); 165 list.setBorder(BorderFactory.createCompoundBorder( 166 BorderFactory.createEtchedBorder(), 167 BorderFactory.createEmptyBorder(0,3,0,3))); 168 169 170 171 descriptionArea = uif.createMessageArea("opts.type.desc"); 172 descriptionArea.setRows(3); 173 Font f = descriptionArea.getFont(); 174 f = f.deriveFont(Font.PLAIN, f.getSize2D()-1); 175 descriptionArea.setFont(f); 176 177 178 if (customBoxes != null && list != null) { 179 CustomReport val = customBoxes.get(list.getSelectedValue()); 180 if (val != null) 181 descriptionArea.setText(val.getDescription()); 182 } 183 184 JPanel rightCenter = uif.createPanel("opts.blank", false); 185 rightCenter.setLayout(new BorderLayout()); 186 //rightCenter.setBackground(Color.magenta); 187 rightCenter.add(descriptionArea, BorderLayout.PAGE_START); 188 rightCenter.add(p, BorderLayout.CENTER); 189 bottom.add(rightCenter, BorderLayout.CENTER); 190 191 bottom.add(list, BorderLayout.WEST); 192 193 lc.insets.left = 0; 194 lc.gridwidth = 1; 195 lc.gridy = 3; 196 lc.anchor = GridBagConstraints.NORTHWEST; 197 lc.gridwidth = GridBagConstraints.REMAINDER; 198 lc.fill = GridBagConstraints.BOTH; 199 lc.weighty = 1.0; 200 201 add(bottom, lc); 202 203 //--------------------------------------------------------------------------------- 204 205 okBtn = uif.createButton("opts.ok", okListener); 206 cancelBtn = uif.createCancelButton("opts.cancel"); 207 backBtn = uif.createButton("opts.back", chTabListener); 208 helpBtn = uif.createHelpButton("opts.help", 209 "mergeReports.window.csh"); 210 JButton[] buttons = new JButton[] { okBtn, cancelBtn, helpBtn }; 211 212 JPanel buttonsPanel = uif.createPanel("opts.but"); 213 GridBagConstraints co = new GridBagConstraints(); 214 co.anchor = GridBagConstraints.EAST; 215 co.weightx = 1; 216 co.gridwidth = 3; 217 co.insets = new Insets(10,0,0,0); 218 219 GridBagConstraints bb = new GridBagConstraints(); 220 bb.anchor = GridBagConstraints.WEST; 221 bb.insets = new Insets(10,0,0,0); 222 this.add(backBtn, bb); 223 224 this.add(buttonsPanel, co); 225 buttonsPanel.setLayout(new GridLayout(1, 3, 5, 5)); 226 227 GridBagConstraints b = new GridBagConstraints(); 228 b.anchor = GridBagConstraints.EAST; 229 co.insets = new Insets(10,0,0,0); 230 for (int i = 0; i < buttons.length; i++) { 231 buttonsPanel.add(buttons[i]); 232 233 } 234 235 list.setSelectedIndex(0); 236 } 237 238 /** 239 * @return number of custom reports added 240 */ 241 private int getCustomReports(JPanel p) { 242 int result = 0; 243 Tool[] tools = desktop.getTools(); 244 List<CustomReport> customReportsList = new ArrayList<>(); 245 for (int i = 0; i < tools.length; i++) { 246 if (tools[i] instanceof ExecTool) { 247 // should not be using report types from ExecTool 248 // should have a separate list available for this tool 249 ExecTool tool = (ExecTool) tools[i]; 250 InterviewParameters ip = tool.getInterviewParameters(); 251 TestFilter tf = new CompositeFilter(ip.getFilters()); 252 ReportSettings rs = new ReportSettings(ip); 253 rs.setFilter(tf); 254 ContextManager cm = tool.getContextManager(); 255 if (cm != null && cm.getCustomReports() != null) { 256 for (CustomReport cr : cm.getCustomReports()) { 257 cr.setEnviroment(rs); 258 customReportsList.add(cr); 259 } 260 } 261 } 262 } // for 263 264 customReports = customReportsList 265 .toArray(new CustomReport[0]); 266 if (customReports == null || customReports.length == 0) { 267 customReports = null; 268 return 0; 269 } 270 271 customBoxes = new HashMap<>(); 272 273 for (int i = 0; i < customReports.length; i++) { 274 JCheckBox cb = new JCheckBox(customReports[i].getName()); 275 cb.setName(customReports[i].getReportId()); 276 listModel.addElement(cb); 277 customBoxes.put(cb, customReports[i]); 278 279 ReportConfigPanel[] ops = customReports[i].getOptionPanes(); 280 if (ops == null || ops.length == 0) { 281 // no config panels, use blank 282 p.add(customReports[i].getReportId(), uif.createPanel( 283 "opts.blank", false)); 284 } else { 285 // tabbed pane for all supplied panels 286 JTabbedPane tp = uif.createTabbedPane("opts.custom.tabs"); 287 for (int j = 0; j < ops.length; j++) 288 tp.addTab(ops[j].getPanelName(), ops[j]); 289 290 p.add(customReports[i].getReportId(), tp); 291 } 292 result++; 293 } // for 294 295 return result; 296 } 297 298 private ArrayList<CustomReport> getActiveCustomReports() { 299 300 ArrayList<CustomReport> customReps = new ArrayList<>(); 301 if (customBoxes != null && customBoxes.size() > 0) { 302 Iterator<JCheckBox> it = customBoxes.keySet().iterator(); 303 while (it.hasNext()) { 304 JCheckBox box = it.next(); 305 if (box.isSelected()) { 306 customReps.add(customBoxes.get(box)); 307 } 308 } 309 } 310 return customReps; 311 } 312 313 314 /** 315 * This listener changes options state against checkboxes 316 */ 317 private class SelectListener extends MouseInputAdapter implements 318 KeyListener, ListSelectionListener { 319 320 /** 321 * @param lst JList of checkboxes 322 * @param p parent Panel 323 * @param cardLayout The CardLayout for options 324 */ 325 SelectListener(JList lst, JPanel p, CardLayout cardLayout) { 326 list = lst; 327 listModel = list.getModel(); 328 lastSelected = listModel.getElementAt(0); 329 panel = p; 330 cards = cardLayout; 331 } 332 333 public void keyTyped(KeyEvent e) { 334 if (e.getKeyChar() == ' ') { 335 process(list.getSelectedIndex()); 336 } 337 } 338 339 public void mouseClicked(MouseEvent e) { 340 if (e.getPoint().getX() <= emptyCBW) { 341 process(list.locationToIndex(e.getPoint())); 342 } 343 } 344 345 public void valueChanged(ListSelectionEvent e) { 346 int index = list.getSelectedIndex(); 347 JCheckBox box = (JCheckBox) (listModel.getElementAt(index)); 348 349 if (lastSelected != box) { 350 cards.show(panel, box.getName()); 351 lastSelected = box; 352 } 353 enablePanel(box); 354 } 355 356 private void enablePanel(final JCheckBox box) { 357 for (int i = 0; i < panel.getComponentCount(); i++) { 358 JComponent tab = (JComponent) panel.getComponent(i); 359 tab.setEnabled(box.isSelected()); 360 } 361 362 if (box == cbXml) { 363 descriptionArea.setText(uif.getI18NString("opts.xmlDesc.txt")); 364 return; 365 } 366 367 if (customBoxes != null) { 368 CustomReport rep = customBoxes.get(box); 369 if(rep != null) { 370 if (rep.getOptionPanes() != null) { 371 for (int i = 0; i < rep.getOptionPanes().length; i++) { 372 rep.getOptionPanes()[i].setEnabled(box.isSelected()); 373 } // for 374 } 375 376 descriptionArea.setText(rep.getDescription()); 377 } 378 } 379 } 380 381 private void process(final int index) { 382 JCheckBox box = (JCheckBox) (listModel.getElementAt(index)); 383 384 if (lastSelected == box) { 385 box.doClick(); 386 list.repaint(); // important! 387 enablePanel(box); 388 } 389 lastSelected = box; 390 } 391 392 public void keyReleased(KeyEvent e) { 393 } 394 395 public void keyPressed(KeyEvent e) { 396 } 397 398 Object lastSelected; 399 JList list; 400 ListModel listModel; 401 JPanel panel; 402 CardLayout cards; 403 double emptyCBW = new JCheckBox("").getPreferredSize().getWidth() + 2; 404 } 405 406 /* 407 * PropertyChangeListener for enabling/disabling container's content 408 */ 409 private class PanelEnableListener implements PropertyChangeListener { 410 /** 411 * @param container Container for controlling 412 */ 413 PanelEnableListener(Container container) { 414 theContainer = container; 415 } 416 417 /** 418 * Catches changes of "enabled" property 419 * and changes enabled status for all child components 420 */ 421 public void propertyChange(PropertyChangeEvent evt) { 422 if ("enabled".equals(evt.getPropertyName())) { 423 boolean oldV = ((Boolean) evt.getOldValue()).booleanValue(); 424 boolean newV = ((Boolean) evt.getNewValue()).booleanValue(); 425 if (oldV && !newV) { 426 // disable 427 Iterator<Component> chIt = collectChildren(theContainer, 428 new ArrayList<Component>()).iterator(); 429 enabledComp = new HashSet<>(); 430 while (chIt.hasNext()) { 431 Component c = chIt.next(); 432 if (c.isEnabled()) { 433 enabledComp.add(c); 434 c.setEnabled(false); 435 } 436 } 437 438 } else if (!oldV && newV && enabledComp != null) { 439 // enable 440 Iterator<Component> chIt = collectChildren(theContainer, 441 new ArrayList<Component>()).iterator(); 442 while (chIt.hasNext()) { 443 Component c = chIt.next(); 444 if (enabledComp.contains(c)) { 445 c.setEnabled(true); 446 } 447 } 448 } 449 } 450 } 451 452 /** 453 * Recursively gathers all children components 454 */ 455 private Collection<Component> collectChildren(Container comp, Collection<Component> c) { 456 Component[] ch = comp.getComponents(); 457 for (int i = 0; i < ch.length; i++) { 458 c.add(ch[i]); 459 if (ch[i] instanceof Container) { 460 collectChildren((Container) ch[i], c); 461 } 462 } 463 return c; 464 } 465 466 private Container theContainer; 467 468 private Set<Component> enabledComp; 469 } 470 471 private class CheckBoxListCellRenderer implements ListCellRenderer<JCheckBox> { 472 public Component getListCellRendererComponent(JList list, JCheckBox comp, 473 int index, boolean isSelected, boolean cellHasFocus) { 474 // assert: value is a JCheckBox 475 if (isSelected) { 476 comp.setOpaque(true); 477 comp.setBackground(UIFactory.Colors.TEXT_HIGHLIGHT_COLOR.getValue()); 478 } else { 479 comp.setOpaque(false); 480 comp.setForeground(Color.black); 481 } 482 483 return comp; 484 } 485 } 486 487 JButton[] getButtons() { 488 return new JButton[] { backBtn, okBtn, cancelBtn, helpBtn }; 489 } 490 491 private DefaultListModel<JCheckBox> listModel; 492 private JList<JCheckBox> list; 493 private CustomReport[] customReports; 494 private JTextArea descriptionArea; 495 private Map<JCheckBox, CustomReport> customBoxes; 496 private JCheckBox cbXml; 497 private JButton backBtn; 498 private JButton okBtn; 499 private JButton cancelBtn; 500 private JCheckBox handleConfilctsBox; 501 private JCheckBox resolveAsRecentBox; 502 private ActionListener chTabListener; 503 private ActionListener okListener; 504 private JButton helpBtn; 505 506 private Desktop desktop; 507 private UIFactory uif; 508 private static final int DOTS_PER_INCH = Toolkit.getDefaultToolkit().getScreenResolution(); 509 }