1 /* 2 * $Id$ 3 * 4 * Copyright (c) 2001, 2011, 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.exec; 28 29 import java.awt.BorderLayout; 30 import java.awt.Component; 31 import java.awt.CardLayout; 32 import java.awt.Dimension; 33 import java.awt.Frame; 34 import java.awt.GridBagConstraints; 35 import java.awt.GridBagLayout; 36 import java.awt.event.ComponentAdapter; 37 import java.awt.event.ComponentEvent; 38 import java.util.Hashtable; 39 import java.awt.event.ActionEvent; 40 import java.awt.event.ActionListener; 41 42 import javax.swing.BorderFactory; 43 import javax.swing.DefaultListModel; 44 import javax.swing.JButton; 45 import javax.swing.JComponent; 46 import javax.swing.JLabel; 47 import javax.swing.JList; 48 import javax.swing.JPanel; 49 import javax.swing.JSplitPane; 50 import javax.swing.JTextArea; 51 import javax.swing.JTextField; 52 import javax.swing.ListModel; 53 import javax.swing.SwingConstants; 54 import javax.swing.event.ListSelectionEvent; 55 import javax.swing.event.ListSelectionListener; 56 57 import com.sun.javatest.ObservableTestFilter; 58 import com.sun.javatest.TestFilter; 59 import com.sun.javatest.TestSuite; 60 import com.sun.javatest.tool.ToolDialog; 61 import com.sun.javatest.tool.UIFactory; 62 import com.sun.javatest.util.Debug; 63 import com.sun.javatest.util.DynamicArray; 64 65 /** 66 * The primary purpose is to hold the a variety of named filter sets from 67 * which the user will select one (the "active" one). 68 */ 69 public class FilterConfig { 70 /** 71 * Observe changes to the state of the view. The changes to the view state 72 * will generally be the result of user actions. 73 */ 74 public interface Observer { 75 /** 76 * The state of the given filter has changed. 77 */ 78 public void filterUpdated(TestFilter f); 79 80 public void filterAdded(TestFilter f); 81 82 /** 83 * Removing the active filter will result in an exception. 84 */ 85 public void filterRemoved(TestFilter f); 86 } 87 88 public FilterConfig(ExecModel e, JComponent parent, UIFactory uif) { 89 // load default filters here instead of ExecTool to avoid instantiating 90 // them 91 execModel = e; 92 this.parentComponent = parent; 93 this.uif = uif; 94 } 95 96 /** 97 * Add a test filter to the list of possible filters. 98 * Care should be taken not to add a filter more than once. 99 */ 100 synchronized void add(TestFilter f) { 101 if (f == null) 102 return; 103 104 // record this filter officially 105 filters = (TestFilter[])DynamicArray.append(filters, f); 106 107 // register as change observer if possible 108 if (f instanceof ObservableTestFilter) { 109 ((ObservableTestFilter)f).addObserver(listener); 110 } 111 112 if (f instanceof ConfigurableTestFilter && fep != null) { 113 fep.addConfigurableFilter((ConfigurableTestFilter)f); 114 } 115 116 // tell people about the addition 117 // obs should never be null 118 for (int i = 0; i < obs.length; i++) 119 obs[i].filterAdded(f); 120 121 if (fep != null) 122 fep.listModel.addElement(f); 123 } 124 125 /** 126 * Remove a test filter from the list of possible filters. 127 * You cannot remove the active filter. 128 * 129 * @param f Should not be null. Should also be a filter which was previously 130 * added to this object. 131 * @throws FilterInUseFault Thrown if you try to remove the active filter. 132 */ 133 synchronized void remove(TestFilter f) { 134 if (f == null) 135 return; 136 137 // remove this filter officially 138 filters = (TestFilter[])DynamicArray.remove(filters, f); 139 140 if (f instanceof ObservableTestFilter) 141 ((ObservableTestFilter)f).removeObserver(listener); 142 143 if (f instanceof ConfigurableTestFilter && fep != null) { 144 fep.removeConfigurableFilter((ConfigurableTestFilter)f); 145 } 146 147 // tell people about the removal 148 // obs should never be null 149 for (int i = 0; i < obs.length; i++) 150 obs[i].filterRemoved(f); 151 152 if (fep != null) 153 fep.listModel.removeElement(f); 154 } 155 156 synchronized String[] getFilterNames() { 157 int count = filters.length; 158 String[] names = new String[count]; 159 160 for (int i = 0; i < count; i++) 161 names[i] = filters[i].getName(); 162 163 return names; 164 } 165 166 synchronized TestFilter[] getFilters() { 167 int count = filters.length; 168 TestFilter[] copy = new TestFilter[count]; 169 System.arraycopy(filters, 0, copy, 0, count); 170 171 return copy; 172 } 173 174 /** 175 * Get a filter by name. 176 * 177 * @return Null if no match. 178 */ 179 synchronized TestFilter getFilter(String name) { 180 int count = filters.length; 181 182 for (int i = 0; i < count; i++) 183 if (name.equals(filters[i].getName())) 184 return filters[i]; 185 186 // not found 187 return null; 188 } 189 190 /** 191 * Does the view contain the given filter. 192 * Done by reference compare. 193 */ 194 synchronized boolean contains(TestFilter f) { 195 for (int i = 0; i < filters.length; i++) 196 if (filters[i] == f) 197 return true; 198 199 // not found 200 return false; 201 } 202 203 synchronized FilterSelectionHandler createFilterSelectionHandler() { 204 FilterSelectionHandler fsh = new FilterSelectionHandler(this, uif); 205 handlers = (FilterSelectionHandler[])DynamicArray.append(handlers, fsh); 206 207 return fsh; 208 } 209 210 public synchronized void addObserver(Observer o) { 211 if (o == null) 212 return; 213 214 if (obs == null) 215 obs = new Observer[0]; 216 217 obs = (Observer[])DynamicArray.append(obs, o); 218 } 219 220 public synchronized void removeObserver(Observer o) { 221 obs = (Observer[])DynamicArray.remove(obs, o); 222 } 223 224 /** 225 * Notify all observers that a filter has changed state. 226 * This call has no effect if the given filter is not the active 227 * view filter. 228 */ 229 synchronized void notifyUpdated(TestFilter f) { 230 if (obs == null) // this really should not happen 231 return; 232 233 for (int i = 0; i < obs.length; i++) { 234 obs[i].filterUpdated(f); 235 } // for 236 } 237 238 /** 239 * Show the filter editor. 240 */ 241 synchronized void showEditorDialog() { 242 if (fep == null) 243 fep = new FilterEditorPanel(parentComponent, uif); 244 245 fep.setVisible(true); 246 } 247 248 /** 249 * Show the filter editor, with the given filter selected. 250 * @param f the filter to show the user initially 251 */ 252 synchronized void showEditorDialog(TestFilter f) { 253 if (fep == null) 254 fep = new FilterEditorPanel(parentComponent, uif); 255 256 fep.setSelectedFilter(f); 257 fep.setVisible(true); 258 } 259 260 /** 261 * Hide the editor dialog. No effect if the dialog isn't visible or 262 * initialized. 263 */ 264 synchronized void hideEditorDialog(Frame parent) { 265 fep.setVisible(false); 266 } 267 268 private class Listener 269 extends ComponentAdapter 270 implements ObservableTestFilter.Observer 271 { 272 public void filterUpdated(ObservableTestFilter otf) { 273 notifyUpdated(otf); 274 } 275 276 // ComponentListener 277 public void componentHidden(ComponentEvent e) { 278 fep.doReset(); 279 } 280 } 281 282 // too much overhead to impl. all the methods if we use a Vector 283 // we'll accept the hit when we add a new filter, which isn't that 284 // often 285 private TestFilter[] filters = new TestFilter[0]; 286 private UIFactory uif; 287 private ExecModel execModel; 288 private Listener listener = new Listener(); 289 private Observer[] obs = new Observer[0]; 290 private FilterSelectionHandler[] handlers; 291 292 //private JDialog editDialog; 293 private FilterEditorPanel fep; 294 private JComponent parentComponent; 295 296 private static boolean debug = Debug.getBoolean(FilterConfig.class); 297 298 private class FilterEditorPanel 299 extends ToolDialog 300 implements ListSelectionListener, ActionListener 301 { 302 FilterEditorPanel(Component parent, UIFactory uif) { 303 super(parent, uif, "fconfig"); 304 } 305 306 // ActionListener 307 public void actionPerformed(ActionEvent e) { 308 Object source = e.getSource(); 309 String result = null; 310 311 if (source == doneBut) { 312 313 if (mode == EDITABLE) { 314 //Debug.println("FC - in edit mode, attempting to save."); 315 result = doApply(); 316 } 317 else { 318 //Debug.println("FC - not in edit mode, not attempting to save."); 319 } 320 321 if (result == null) 322 //OLD editDialog.hide(); 323 setVisible(false); 324 else { 325 // save failed... 326 } 327 } 328 else if (source == applyBut) { 329 result = doApply(); 330 } 331 else if (source == resetBut) { 332 if (mode == EDITABLE) 333 doReset(); 334 } 335 else if (source == cancelBut) { 336 if (mode == EDITABLE) 337 doReset(); 338 339 //OLD editDialog.hide(); 340 setVisible(false); 341 } 342 /* 343 else if (source == createBut) { 344 Object tf = (TestFilter)(leftList.getSelectedValue()); 345 if (!(tf instanceof ConfigurableTestFilter)) 346 throw new IllegalStateException(""); 347 348 ConfigurableTestFilter ctf = (ConfigurableTestFilter)tf; 349 350 FilterConfig.this.add(ctf.cloneInstance()); 351 } 352 else if (source == deleteBut) { 353 Object tf = (TestFilter)(leftList.getSelectedValue()); 354 if (!(tf instanceof ConfigurableTestFilter)) 355 throw new IllegalStateException(""); 356 357 ConfigurableTestFilter ctf = (ConfigurableTestFilter)tf; 358 359 FilterConfig.this.remove(ctf); 360 } 361 */ 362 363 if (result != null) { // error occurred 364 uif.showError("fconfig.commit", result); 365 } 366 } 367 368 void setSelectedFilter(TestFilter f) { 369 if (listModel != null) { 370 int ind = listModel.indexOf(f); 371 if (ind >= 0) 372 selectIndex(ind); 373 } 374 else { 375 // necessary for correct initialization, since the ToolDialog 376 // does lazy initialization 377 // initGUI() will process this later 378 selectedFilter = f; 379 } 380 } 381 382 // ListSelectionListener 383 public void valueChanged(ListSelectionEvent e) { 384 //int newSelected = e.getLastIndex(); 385 int newSelected = leftList.getSelectedIndex(); 386 // list selection has changed 387 if (newSelected < 0) { 388 selectIndex(0); 389 lastSelected = 0; 390 } 391 else if (newSelected != lastSelected) { 392 selectIndex(newSelected); 393 lastSelected = newSelected; 394 } 395 } 396 397 /** 398 * Process a list selection change. It is assumed that the selection 399 * does not equal the current/last selection. This should always be 400 * called on the event thread. 401 */ 402 private void selectIndex(int index) { 403 leftList.setSelectedIndex(index); 404 405 // update right panel 406 selectedFilter = (TestFilter)(listModel.elementAt(index)); 407 if (selectedFilter instanceof ConfigurableTestFilter) { 408 if (mode == -1 || mode == UNEDITABLE) { 409 nameCards.show(namePanel, NAMING_ACTIVE); 410 //deleteBut.setEnabled(true); 411 //createBut.setEnabled(true); 412 applyBut.setEnabled(true); 413 resetBut.setEnabled(true); 414 mode = EDITABLE; 415 } 416 417 ConfigurableTestFilter ctf = (ConfigurableTestFilter)selectedFilter; 418 namingName.setText(ctf.getName()); 419 420 String cardKey = configPanelHash.get(ctf); 421 configCards.show(configPanel, cardKey); 422 } 423 else if (selectedFilter instanceof TestFilter) { 424 if (mode == -1 || mode == EDITABLE) { 425 nameCards.show(namePanel, NAMING_EMPTY); 426 configCards.show(configPanel, CONFIG_EMPTY); 427 //createBut.setEnabled(false); 428 //deleteBut.setEnabled(false); 429 applyBut.setEnabled(false); 430 resetBut.setEnabled(false); 431 mode = UNEDITABLE; 432 } 433 } 434 else { 435 // hummm 436 } 437 438 fillInfo(selectedFilter); 439 leftList.requestFocus(); 440 } 441 442 protected void initGUI() { 443 setHelp("execFilters.dialog.csh"); 444 445 TestSuite ts = execModel.getTestSuite(); 446 String tsName = ((ts == null ? uif.getI18NString("fconfig.dTitle.unknown") : ts.getName())); 447 setI18NTitle("fconfig.dTitle", tsName); 448 449 JPanel body = uif.createPanel("fe.body", false); 450 body.setLayout(new GridBagLayout()); 451 452 GridBagConstraints gbc = new GridBagConstraints(); 453 gbc.gridx = 0; 454 gbc.gridy = 0; 455 gbc.fill = GridBagConstraints.VERTICAL; 456 gbc.anchor = GridBagConstraints.NORTHWEST; 457 gbc.insets.left = 10; 458 gbc.insets.right = 10; 459 gbc.weighty = 1; 460 gbc.weightx = 0; 461 gbc.gridwidth = 1; 462 gbc.gridheight = 1; 463 464 leftList = uif.createList("fconfig.list"); 465 leftList.setModel(createListModel()); 466 leftList.setCellRenderer(RenderingUtilities.createFilterListRenderer()); 467 leftList.addListSelectionListener(this); 468 leftList.setBorder(BorderFactory.createEtchedBorder()); 469 leftList.getInsets().left = 5; 470 leftList.getInsets().right = 5; 471 uif.setAccessibleInfo(leftList, "fconfig.list"); 472 473 JPanel spacer = new JPanel(); 474 spacer.setBorder(uif.createTitledBorder("fconfig.list")); 475 spacer.setLayout(new BorderLayout()); 476 spacer.add(leftList, BorderLayout.CENTER); 477 478 body.add(spacer, gbc); 479 480 gbc.weightx = 1; 481 gbc.fill = GridBagConstraints.BOTH; 482 gbc.gridx = 1; 483 JComponent rightPanel = createRightPanel(); 484 body.add(rightPanel, gbc); 485 486 int dpi = uif.getDotsPerInch(); 487 body.setPreferredSize(new Dimension(7 * dpi, 5 * dpi)); 488 setBody(body); 489 490 initButtons(); 491 492 setComponentListener(listener); 493 494 //leftList.setNextFocusableComponent(rightPanel.getNextFocusableComponent()); 495 //rightPanel.setNextFocusableComponent(applyBut); 496 //helpBut.setNextFocusableComponent(leftList); 497 498 mode = -1; 499 500 // process any stored state 501 if (selectedFilter != null) 502 setSelectedFilter(selectedFilter); 503 else 504 selectIndex(0); // the default 505 } 506 507 private ListModel<TestFilter> createListModel() { 508 listModel = new DefaultListModel<>(); 509 510 for (int i = 0; i < filters.length; i++) 511 listModel.addElement(filters[i]); 512 513 return listModel; 514 } 515 516 private JComponent createRightPanel() { 517 EMPTY_CONFIG = createEmptyItem("fconfig.empt.conf"); 518 EMPTY_NAMING = createEmptyItem("fconfig.empt.name"); 519 520 EMPTY_CONFIG.setName("config"); 521 EMPTY_NAMING.setName("naming"); 522 523 JPanel pan = new JPanel(new GridBagLayout()); 524 pan.setName("rightFilter"); 525 GridBagConstraints gbc = new GridBagConstraints(); 526 gbc.gridx = 0; 527 gbc.gridy = GridBagConstraints.RELATIVE; 528 gbc.fill = GridBagConstraints.BOTH; 529 gbc.anchor = GridBagConstraints.NORTH; 530 gbc.insets.left = 10; 531 gbc.insets.right = 10; 532 gbc.weighty = 0; 533 gbc.weightx = 1; 534 535 JComponent nextPanel = createInfoPanel(); 536 nextPanel.setBorder(uif.createTitledBorder("fconfig.panel.info")); 537 pan.add(nextPanel, gbc); 538 539 nextPanel = createNamingPanel(); 540 nextPanel.setBorder(uif.createTitledBorder("fconfig.panel.naming")); 541 pan.add(nextPanel, gbc); 542 543 nextPanel = createConfigPanel(); 544 nextPanel.setBorder(uif.createTitledBorder("fconfig.panel.config")); 545 gbc.weighty = 1; 546 pan.add(nextPanel, gbc); 547 548 return pan; 549 } 550 551 /** 552 * ui key should have uikey.txt, uikey.desc, and uikey values in 553 * the bundle. these are for the text itself, a11y description and 554 * a11y name respectively. 555 */ 556 private JComponent createEmptyItem(String uikey) { 557 JTextField item = uif.createHeading(uikey); 558 uif.setAccessibleInfo(item, uikey); 559 item.setHorizontalAlignment(SwingConstants.CENTER); 560 561 return item; 562 } 563 564 private JComponent createInfoPanel() { 565 JPanel pan = new JPanel(new GridBagLayout()); 566 pan.setName("info"); 567 GridBagConstraints gbc = new GridBagConstraints(); 568 gbc.weightx = 5; 569 gbc.gridx = 0; 570 gbc.gridy = 0; 571 gbc.fill = GridBagConstraints.NONE; 572 gbc.anchor = GridBagConstraints.EAST; 573 574 gbc.insets.left = 15; 575 gbc.insets.right = 15; 576 577 JLabel lab = uif.createLabel("fconfig.info.name"); 578 infoName = uif.createOutputField("fconfig.info.name", lab); 579 infoName.setEditable(false); 580 infoName.setBorder(BorderFactory.createEmptyBorder()); 581 lab.setDisplayedMnemonic(uif.getI18NString("fconfig.info.name.mne").charAt(0)); 582 lab.setHorizontalAlignment(SwingConstants.RIGHT); 583 584 // row 1 585 // label in first column 586 pan.add(lab, gbc); 587 588 // add text field in second column 589 gbc.gridx = 1; 590 gbc.fill = GridBagConstraints.HORIZONTAL; 591 gbc.anchor = GridBagConstraints.WEST; 592 pan.add(infoName, gbc); 593 594 lab = uif.createLabel("fconfig.info.desc"); 595 lab.setHorizontalAlignment(SwingConstants.RIGHT); 596 infoDesc = uif.createTextArea("fconfig.info.desc", lab); 597 infoDesc.setRows(3); 598 infoDesc.setEditable(false); 599 infoDesc.setBorder(BorderFactory.createEmptyBorder()); 600 infoDesc.setLineWrap(true); 601 infoDesc.setWrapStyleWord(true); 602 infoDesc.setBackground(UIFactory.Colors.TRANSPARENT.getValue()); 603 infoDesc.setOpaque(false); 604 lab.setDisplayedMnemonic(uif.getI18NString("fconfig.info.desc.mne").charAt(0)); 605 606 // row 2 607 // label in first column 608 gbc.gridx = 0; 609 gbc.gridy = 1; 610 gbc.fill = GridBagConstraints.NONE; 611 gbc.anchor = GridBagConstraints.NORTHEAST; 612 pan.add(lab, gbc); 613 614 // add text area in second column 615 gbc.gridx = 1; 616 gbc.fill = GridBagConstraints.HORIZONTAL; 617 gbc.anchor = GridBagConstraints.WEST; 618 pan.add(infoDesc, gbc); 619 620 /* 621 // NOTE intentional space added below to defeat 622 // i18n check in build while this is commented out 623 lab = uif.createLabel ("fconfig.info.reason"); 624 lab.setHorizontalAlignment(SwingConstants.RIGHT); 625 infoReason = uif.createTextArea("fconfig.info.reason"); 626 infoReason.setRows(2); 627 infoReason.setEditable(false); 628 infoReason.setBorder(BorderFactory.createEmptyBorder()); 629 infoReason.setLineWrap(true); 630 infoReason.setWrapStyleWord(true); 631 infoReason.setOpaque(false); 632 lab.setLabelFor(infoReason); 633 634 // row 3 635 // label in first column 636 gbc.gridx = 0; 637 gbc.gridy = 2; 638 gbc.fill = GridBagConstraints.NONE; 639 gbc.anchor = GridBagConstraints.NORTHEAST; 640 pan.add(lab, gbc); 641 642 // add text area in second column 643 gbc.gridx = 1; 644 gbc.fill = GridBagConstraints.HORIZONTAL; 645 gbc.anchor = GridBagConstraints.WEST; 646 pan.add(infoReason, gbc); 647 */ 648 return pan; 649 } 650 651 private JPanel createNamingPanel() { 652 nameCards = new CardLayout(); 653 namePanel = new JPanel(nameCards); 654 655 JPanel pan = new JPanel(new GridBagLayout()); 656 GridBagConstraints gbc = new GridBagConstraints(); 657 gbc.weightx = 5; 658 gbc.gridx = 0; 659 gbc.gridy = 0; 660 gbc.fill = GridBagConstraints.NONE; 661 gbc.anchor = GridBagConstraints.EAST; 662 663 gbc.insets.left = 15; 664 gbc.insets.right = 15; 665 666 JLabel lab = uif.createLabel("fconfig.naming.name"); 667 namingName = uif.createOutputField("fconfig.naming.name", lab); 668 namingName.setEditable(true); 669 namingName.setEnabled(true); 670 lab.setDisplayedMnemonic(uif.getI18NString("fconfig.naming.name.mne").charAt(0)); 671 lab.setHorizontalAlignment(SwingConstants.RIGHT); 672 673 // row 1 674 // label in first column 675 pan.add(lab, gbc); 676 677 gbc.gridx = 1; 678 gbc.fill = GridBagConstraints.HORIZONTAL; 679 pan.add(namingName, gbc); 680 681 namePanel.add(NAMING_ACTIVE, pan); 682 namePanel.add(NAMING_EMPTY, EMPTY_NAMING); 683 nameCards.show(namePanel, NAMING_EMPTY); 684 685 return namePanel; 686 } 687 688 private JPanel createConfigPanel() { 689 configCards = new CardLayout(); 690 configPanel = new JPanel(configCards); 691 configPanelHash = new Hashtable<>(); 692 693 // insert panels? 694 configPanel.add(CONFIG_EMPTY, EMPTY_CONFIG); 695 696 for (int i = 0; i < listModel.getSize(); i++) { 697 if (listModel.getElementAt(i) instanceof ConfigurableTestFilter) { 698 ConfigurableTestFilter ctf = 699 (ConfigurableTestFilter)listModel.getElementAt(i); 700 addConfigurableFilter(ctf); 701 } 702 } // for 703 704 return configPanel; 705 } 706 707 private void initButtons() { 708 applyBut = uif.createButton("fconfig.edit.apply", this); 709 resetBut = uif.createButton("fconfig.edit.reset", this); 710 cancelBut = uif.createCancelButton("fconfig.edit.cancel", this); 711 doneBut = uif.createButton("fconfig.edit.done", this); 712 helpBut = uif.createHelpButton("fconfig.edit.help", "execFilters.dialog.csh"); 713 setButtons(new JButton[] { applyBut, resetBut, cancelBut, doneBut, helpBut }, 714 doneBut); 715 } 716 717 private void addConfigurableFilter(ConfigurableTestFilter ctf) { 718 JComponent comp = ctf.getEditorPane(); 719 String thisName = "ctf" + ++configCounter; 720 721 if (comp != null) 722 configPanel.add(thisName, comp); 723 else 724 configPanel.add(thisName, EMPTY_CONFIG); 725 726 // to lookup later 727 configPanelHash.put(ctf, thisName); 728 } 729 730 private void removeConfigurableFilter(ConfigurableTestFilter ctf) { 731 configPanelHash.remove(ctf); 732 } 733 734 private void fillInfo(TestFilter f) { 735 if (f == null) 736 return; 737 738 if (f instanceof ConfigurableTestFilter) { 739 infoName.setText(((ConfigurableTestFilter)(f)).getBaseName()); 740 } 741 else 742 infoName.setText(f.getName()); 743 744 infoDesc.setText(f.getDescription()); 745 //infoReason.setText(f.getReason()); 746 } 747 748 private void fillNaming(ConfigurableTestFilter f) { 749 namingName.setText(f.getName()); 750 } 751 752 /** 753 * Attempt the apply operation. 754 * @return Non-null if the apply was successful, null otherwise. If non-null 755 * the value is a localized error message for the user. 756 */ 757 private String doApply() { 758 if (mode == UNEDITABLE) 759 throw new IllegalStateException("filter is uneditable, cannot apply changes"); 760 761 ConfigurableTestFilter ctf = (ConfigurableTestFilter)selectedFilter; 762 763 // should check to see if it's changed 764 String newName = namingName.getText(); 765 if (validateName(newName) != -1) { 766 return uif.getI18NString("fconfig.edit.badName", newName); 767 } 768 else if (newName != null) 769 ctf.setInstanceName(newName); 770 771 String status = ctf.commitEditorSettings(); 772 773 if (handlers != null) 774 for (int i = 0; i < handlers.length; i++) 775 handlers[i].updateFilterMetaInfo(ctf); 776 777 return status; 778 } 779 780 void doReset() { 781 // reset all known configurable filters 782 for (int i = 0; i < listModel.getSize(); i++) { 783 if (listModel.elementAt(i) instanceof 784 ConfigurableTestFilter) { 785 ConfigurableTestFilter ctf = 786 (ConfigurableTestFilter)listModel.elementAt(i); 787 ctf.resetEditorSettings(); 788 } 789 } // for 790 } 791 792 /** 793 * @return The position of the invalid character. 794 */ 795 private int validateName(String text) { 796 for (int i = 0; i < text.length(); i++) { 797 char c = text.charAt(i); 798 if (Character.isLetterOrDigit(c) || 799 c == '-' || 800 c == '_' || 801 c == '.' || 802 c == ' ' || 803 c == ',') 804 continue; 805 else 806 return i; 807 } // for 808 809 return -1; 810 } 811 812 private JSplitPane split; 813 private JList<TestFilter> leftList; 814 private DefaultListModel<TestFilter> listModel; 815 private int lastSelected = -1; 816 private TestFilter selectedFilter; 817 818 // just to help track current state 819 private int mode; 820 //private boolean focusSet; 821 private static final int EDITABLE = 0; 822 private static final int UNEDITABLE = 1; 823 824 // dialog buttons 825 private JButton applyBut; 826 private JButton helpBut; 827 private JButton doneBut; 828 private JButton cancelBut; 829 private JButton createBut; 830 private JButton deleteBut; 831 private JButton resetBut; 832 833 // info panel components 834 private JTextArea infoDesc; 835 private JTextField infoName; 836 //private JTextArea infoReason; 837 838 // naming panel 839 private CardLayout nameCards; 840 private JPanel namePanel; 841 private JTextField namingName; 842 843 // config panel 844 private CardLayout configCards; 845 private JPanel configPanel; 846 private Hashtable<ConfigurableTestFilter, String> configPanelHash; 847 private int configCounter; // to make a unique string 848 849 private JComponent EMPTY_CONFIG; 850 private JComponent EMPTY_NAMING; 851 private JComponent EMPTY_INFO; 852 853 private int NUMBER; 854 855 private static final String CONFIG_ACTIVE = "configa"; 856 private static final String CONFIG_EMPTY = "confige"; 857 private static final String NAMING_ACTIVE = "naminga"; 858 private static final String NAMING_EMPTY = "naminge"; 859 private static final String INFO_ACTIVE = "infoa"; 860 private static final String INFO_EMPTY = "infoe"; 861 } 862 863 }