1 /*
   2  * $Id$
   3  *
   4  * Copyright (c) 2003, 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.javatest.tool;
  28 
  29 import java.awt.Color;
  30 import java.awt.Component;
  31 import java.awt.Container;
  32 import java.awt.FocusTraversalPolicy;
  33 import java.awt.Frame;
  34 import java.awt.GridBagConstraints;
  35 import java.awt.GridBagLayout;
  36 import java.awt.KeyboardFocusManager;
  37 import java.awt.Window;
  38 import java.awt.event.ActionEvent;
  39 import java.awt.event.WindowAdapter;
  40 import java.awt.event.WindowEvent;
  41 import java.beans.PropertyChangeEvent;
  42 import java.beans.PropertyChangeListener;
  43 import java.io.*;
  44 import java.nio.charset.StandardCharsets;
  45 import java.util.Iterator;
  46 import java.util.Set;
  47 import java.util.Vector;
  48 import java.beans.PropertyChangeListener;
  49 import javax.accessibility.AccessibleContext;
  50 import javax.swing.AbstractAction;
  51 import javax.swing.Action;
  52 import javax.swing.ActionMap;
  53 import javax.swing.BorderFactory;
  54 import javax.swing.InputMap;
  55 import javax.swing.JButton;
  56 import javax.swing.JCheckBoxMenuItem;
  57 import javax.swing.JComponent;
  58 import javax.swing.JDialog;
  59 import javax.swing.JEditorPane;
  60 import javax.swing.JFrame;
  61 import javax.swing.JLabel;
  62 import javax.swing.JList;
  63 import javax.swing.JMenu;
  64 import javax.swing.JMenuBar;
  65 import javax.swing.JPanel;
  66 import javax.swing.JRootPane;
  67 import javax.swing.JScrollBar;
  68 import javax.swing.JTextField;
  69 import javax.swing.JTree;
  70 import javax.swing.KeyStroke;
  71 import javax.swing.SwingUtilities;
  72 import javax.swing.event.ChangeEvent;
  73 import javax.swing.event.ChangeListener;
  74 import javax.swing.event.MenuEvent;
  75 import javax.swing.event.MenuListener;
  76 import javax.swing.text.Document;
  77 import javax.swing.text.JTextComponent;
  78 import com.sun.javatest.tool.jthelp.JHelpContentViewer;
  79 
  80 class FocusMonitor
  81 {
  82     public static FocusMonitor access() {
  83         if (focusMonitor == null)
  84             focusMonitor = new FocusMonitor();
  85 
  86         return focusMonitor;
  87     }
  88 
  89     public void setOptions(String[] opts) {
  90         for (int i = 0; i < opts.length; i++) {
  91             if (opts[i].equals("-open"))
  92                 setVisible(true);
  93             else if (opts[i].equals("-bg"))
  94                 setHighlightEnabled(true);
  95             else
  96                 System.err.println("Warning: bad option for FocusMonitor: " + opts[i]);
  97         }
  98     }
  99 
 100     public void setActivateKey(String key) {
 101         activateKey = KeyStroke.getKeyStroke(key);
 102     }
 103 
 104     public void setReportKey(String key) {
 105         reportKey = KeyStroke.getKeyStroke(key);
 106     }
 107 
 108     public void setReportFile(String file) {
 109         reportFile = file;
 110     }
 111 
 112     public void monitor(Component c) {
 113         if (c == null
 114             || (frame != null && (frame == c || frame.isAncestorOf(c))))
 115             return;
 116 
 117         if (activateKey != null || reportKey != null) {
 118             Window w = (Window) (c instanceof Window ? c
 119                                  : SwingUtilities.getAncestorOfClass(Window.class, c));
 120             if (w == null)
 121                 return;
 122 
 123             JRootPane root;
 124             if (w instanceof JFrame)
 125                 root = ((JFrame) w).getRootPane();
 126             else if (w instanceof JDialog)
 127                 root = ((JDialog) w).getRootPane();
 128             else
 129                 return;
 130 
 131             if (root == null)
 132                 return;
 133 
 134             InputMap inputMap =  root.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
 135             inputMap.put(activateKey, "focusMonitor.activate");
 136             inputMap.put(reportKey, "focusMonitor.report");
 137 
 138             ActionMap actionMap =  root.getActionMap();
 139             actionMap.put("focusMonitor.activate", activateAction);
 140             actionMap.put("focusMonitor.report", reportAction);
 141         }
 142     }
 143 
 144     public void report() {
 145         try {
 146             Writer out;
 147             if (reportFile == null) {
 148                 out = new OutputStreamWriter(System.out) {
 149                         public void close() throws IOException {
 150                             flush();  // don't close System.out
 151                         }
 152                     };
 153             }
 154             else
 155                 out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(reportFile, true), StandardCharsets.UTF_8));
 156 
 157             out.write("---------------------------------------");
 158             out.write(NEWLINE);
 159             report(out);
 160             out.close();
 161         }
 162         catch (IOException e) {
 163             System.err.println(e);
 164         }
 165     }
 166 
 167     public void setVisible(boolean b) {
 168         if (b) {
 169             if (frame == null)
 170                 initGUI();
 171             KeyboardFocusManager fm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
 172             focusMonitor.monitor(fm.getFocusOwner());
 173             frame.setVisible(true);
 174             focusMonitor.update();
 175         }
 176         else if (frame != null)
 177             frame.setVisible(false);
 178     }
 179 
 180     private FocusMonitor() {
 181         KeyboardFocusManager fm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
 182         fm.addPropertyChangeListener(new PropertyChangeListener() {
 183                 public void propertyChange(PropertyChangeEvent e) {
 184                     if (e.getPropertyName().equals("focusOwner"))
 185                         update();
 186                 }
 187             });
 188     }
 189 
 190     private void deactivate() {
 191         frame.setVisible(false);
 192         frame.dispose();
 193         frame = null;
 194     }
 195 
 196     private void update() {
 197         if (frame == null || !frame.isVisible())
 198             return;
 199 
 200         KeyboardFocusManager fm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
 201         Component c = fm.getFocusOwner();
 202 
 203         if (c == null || frame == c || frame.isAncestorOf(c)) {
 204             prevFocusPanel.setEnabled(false);
 205             currFocusPanel.setEnabled(false);
 206             nextFocusPanel.setEnabled(false);
 207         }
 208         else {
 209             if (highlighting) {
 210                 setHighlight(currentComponent, false);
 211                 setHighlight(c, true);
 212             }
 213 
 214             currentComponent = c;
 215 
 216             prevFocusPanel.setComponent(getPreviousFocus(c));
 217             currFocusPanel.setComponent(c);
 218             nextFocusPanel.setComponent(getNextFocus(c));
 219 
 220             Window w = fm.getFocusedWindow();
 221             while (w != null && !(w instanceof Frame))
 222                 w = w.getOwner();
 223 
 224             String title = "Focus Monitor";
 225             if (w instanceof Frame)
 226                 title += " - " + ((Frame)w).getTitle();
 227             frame.setTitle(title);
 228         }
 229     }
 230 
 231     private void setHighlightEnabled(boolean b) {
 232         if (b != highlighting) {
 233             highlighting = b;
 234             KeyboardFocusManager fm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
 235             Component c = fm.getFocusOwner();
 236             if (frame == null || !frame.isAncestorOf(c))
 237                 setHighlight(c, highlighting);
 238         }
 239     }
 240 
 241     private void setHighlight(Component c, boolean b) {
 242         if (c == null)
 243             return;
 244         if (b) {
 245             savedOpaque = c.isOpaque();
 246             savedBackground = c.getBackground();
 247             if (c instanceof JComponent)
 248                 ((JComponent) c).setOpaque(true);
 249             c.setBackground(HILITE_COLOR);
 250         }
 251         else {
 252             if (c instanceof JComponent)
 253                 ((JComponent) c).setOpaque(savedOpaque);
 254             c.setBackground(savedBackground);
 255         }
 256     }
 257 
 258     private void report(Writer out) throws IOException {
 259         if (currFocusPanel == null) {
 260             System.err.println("focus monitor not open: no component selected");
 261             return;
 262         }
 263 
 264         currFocusPanel.write(out);
 265     }
 266 
 267     private void initGUI() {
 268         JMenuBar menuBar = new JMenuBar();
 269         JMenu viewMenu = new JMenu("View");
 270         final JCheckBoxMenuItem showBackgroundMenuItem = new JCheckBoxMenuItem("background");
 271         viewMenu.addMenuListener(new MenuListener() {
 272                 public void menuSelected(MenuEvent e) {
 273                     showBackgroundMenuItem.setSelected(highlighting);
 274                 }
 275                 public void menuDeselected(MenuEvent e) { }
 276                 public void menuCanceled(MenuEvent e) { }
 277             });
 278         showBackgroundMenuItem.addChangeListener(new ChangeListener() {
 279                 public void stateChanged(ChangeEvent e) {
 280                     setHighlightEnabled(showBackgroundMenuItem.isSelected());
 281                 }
 282             });
 283         viewMenu.add(showBackgroundMenuItem);
 284         menuBar.add(viewMenu);
 285 
 286         prevFocusPanel = new SummaryPanel();
 287         prevFocusPanel.setBorder(BorderFactory.createTitledBorder("previous focus"));
 288 
 289         currFocusPanel = new DetailPanel();
 290         currFocusPanel.setBorder(BorderFactory.createTitledBorder("current focus"));
 291 
 292         nextFocusPanel = new SummaryPanel();
 293         nextFocusPanel.setBorder(BorderFactory.createTitledBorder("next focus"));
 294 
 295         JPanel main = new JPanel(new GridBagLayout());
 296         GridBagConstraints c = new GridBagConstraints();
 297         c.fill = GridBagConstraints.BOTH;
 298         c.gridwidth = GridBagConstraints.REMAINDER;
 299         c.weightx = 1;
 300         main.add(prevFocusPanel, c);
 301         c.insets.top = 10;
 302         main.add(currFocusPanel, c);
 303         main.add(nextFocusPanel, c);
 304 
 305         JFrame f = new JFrame("Focus Monitor");
 306         f.setJMenuBar(menuBar);
 307         f.setContentPane(main);
 308         f.pack();
 309         f.addWindowListener(new WindowAdapter() {
 310                 public void windowClosed(WindowEvent e) {
 311                     deactivate();
 312                 }
 313             });
 314 
 315         frame = f;
 316     }
 317 
 318     private Component getNextFocus(Component c) {
 319         if (c == null)
 320             return null;
 321 
 322         Container rootAncestor = c.getFocusCycleRootAncestor();
 323         Component comp = c;
 324         while (rootAncestor != null &&
 325                !(rootAncestor.isShowing() &&
 326                  rootAncestor.isFocusable() &&
 327                  rootAncestor.isEnabled()))
 328         {
 329             comp = rootAncestor;
 330             rootAncestor = comp.getFocusCycleRootAncestor();
 331         }
 332 
 333         if (rootAncestor == null)
 334             return null;
 335 
 336         FocusTraversalPolicy policy = rootAncestor.getFocusTraversalPolicy();
 337         Component toFocus = policy.getComponentAfter(rootAncestor, comp);
 338         if (toFocus == null)
 339             toFocus = policy.getDefaultComponent(rootAncestor);
 340 
 341         return toFocus;
 342     }
 343 
 344     private Component getPreviousFocus(Component c) {
 345         if (c == null)
 346             return null;
 347 
 348         Container rootAncestor = c.getFocusCycleRootAncestor();
 349         Component comp = c;
 350         while (rootAncestor != null &&
 351                !(rootAncestor.isShowing() &&
 352                  rootAncestor.isFocusable() &&
 353                  rootAncestor.isEnabled()))
 354         {
 355             comp = rootAncestor;
 356             rootAncestor = comp.getFocusCycleRootAncestor();
 357         }
 358 
 359         if (rootAncestor == null)
 360             return null;
 361 
 362         FocusTraversalPolicy policy = rootAncestor.getFocusTraversalPolicy();
 363         Component toFocus = policy.getComponentBefore(rootAncestor, comp);
 364         if (toFocus == null)
 365             toFocus = policy.getDefaultComponent(rootAncestor);
 366 
 367         return toFocus;
 368     }
 369 
 370     private Component getUpFocus(Component c) {
 371         if (c == null)
 372             return null;
 373 
 374         Container rootAncestor;
 375         for (rootAncestor = c.getFocusCycleRootAncestor();
 376              rootAncestor != null && !(rootAncestor.isShowing() &&
 377                                        rootAncestor.isFocusable() &&
 378                                        rootAncestor.isEnabled());
 379              rootAncestor = rootAncestor.getFocusCycleRootAncestor()) {
 380         }
 381 
 382         if (rootAncestor != null)
 383             return rootAncestor;
 384 
 385         Container window =
 386             (c instanceof Container) ? ((Container)c) : c.getParent();
 387         while (window != null && !(window instanceof Window)) {
 388             window = window.getParent();
 389         }
 390         if (window == null)
 391             return null;
 392 
 393         Component toFocus = window.getFocusTraversalPolicy().getDefaultComponent(window);
 394         return toFocus;
 395     }
 396 
 397     private static String getKeysString(Component c, int mode) {
 398         if (c == null)
 399             return null;
 400 
 401         Set s = c.getFocusTraversalKeys(mode);
 402         StringBuffer sb = new StringBuffer();
 403         for (Iterator iter = s.iterator(); iter.hasNext(); ) {
 404             if (sb.length() > 0)
 405                 sb.append(", ");
 406             sb.append(iter.next());
 407         }
 408         if (!c.areFocusTraversalKeysSet(mode))
 409             sb.append(" (inherited)");
 410         return sb.toString();
 411     }
 412 
 413     private static String getPath(Component c) {
 414         StringBuffer sb = new StringBuffer();
 415         appendPath(sb, c);
 416         return sb.toString();
 417     }
 418 
 419     private static void appendPath(StringBuffer sb, Component c) {
 420         Container p = c.getParent();
 421         if (p != null)
 422             appendPath(sb, p);
 423         sb.append('/');
 424         String name = c.getName();
 425         if (name == null || name.length() == 0) {
 426             if (p == null)  // special case, root component, no name
 427                 sb.append("(Root component)" );
 428             else
 429                 for (int i = 0; i < p.getComponentCount(); i++) {
 430                     if (p.getComponent(i) == c) {
 431                         sb.append(i);
 432                         break;
 433                     }
 434                 }   // for
 435         }
 436         else
 437             sb.append(name);
 438     }
 439 
 440     private Action activateAction = new AbstractAction() {
 441             public void actionPerformed(ActionEvent e) {
 442                 setVisible(true);
 443             }
 444         };
 445 
 446     private Action reportAction = new AbstractAction() {
 447             public void actionPerformed(ActionEvent e) {
 448                 report();
 449             }
 450         };
 451 
 452 
 453     private KeyStroke activateKey;
 454     private KeyStroke reportKey;
 455     private String reportFile;
 456     private JFrame frame;
 457     private SummaryPanel prevFocusPanel;
 458     private DetailPanel currFocusPanel;
 459     private SummaryPanel nextFocusPanel;
 460 
 461     private Component currentComponent;
 462     private boolean highlighting;
 463     private boolean savedOpaque;
 464     private Color savedBackground;
 465 
 466     private static FocusMonitor focusMonitor;
 467 
 468     private static final Color STD_COLOR = Color.black;
 469     private static final Color ERR_COLOR = Color.red;
 470     private static final Color WARN_COLOR = Color.yellow;
 471     private static final Color HILITE_COLOR = new Color(255, 255, 200);
 472     private static final String NEWLINE = System.getProperty("line.separator");
 473 
 474     private class Entry {
 475         Entry(String name) {
 476             label = new JLabel(name + ": ");
 477             label.setName(name);
 478             field = new JTextField(60);
 479             field.setName(name + ".value");
 480             field.setEditable(false);
 481             label.setLabelFor(field);
 482         }
 483 
 484         void setParentEnabled(boolean parentEnabled) {
 485             label.setEnabled(parentEnabled && enabled);
 486             field.setEnabled(parentEnabled && enabled);
 487         }
 488 
 489         void setEnabled(boolean enabled) {
 490             this.enabled = enabled;
 491             label.setEnabled(enabled);
 492             field.setEnabled(enabled);
 493             field.setText("");
 494         }
 495 
 496         void setText(String s) {
 497             setEnabled(true);
 498             field.setText(s);
 499             field.setForeground(STD_COLOR);
 500         }
 501 
 502         void setText(String s, boolean ok) {
 503             setText(s, ok, STD_COLOR, ERR_COLOR);
 504         }
 505 
 506         void setText(String s, boolean ok, Color okColor, Color notOKColor) {
 507             setEnabled(true);
 508             field.setText(s);
 509             field.setForeground(ok ? okColor : notOKColor);
 510         }
 511 
 512         void setText(String s, String err) {
 513             if (s == null || s.length() == 0)
 514                 setText(err, false);
 515             else
 516                 setText(s, true);
 517         }
 518 
 519         void setText(String s, String err, Color okColor, Color notOKColor) {
 520             if (s == null || s.length() == 0)
 521                 setText(err, false, okColor, notOKColor);
 522             else
 523                 setText(s, true, okColor, notOKColor);
 524         }
 525 
 526         void write(Writer out) throws IOException {
 527             if (field.isEnabled()) {
 528                 out.write(field.getForeground() == ERR_COLOR ? "** " : "   ");
 529                 out.write(label.getText());
 530                 out.write(field.getText());
 531                 out.write(NEWLINE);
 532             }
 533         }
 534 
 535         JLabel label;
 536         JTextField field;
 537         boolean enabled;
 538     }
 539 
 540     private class SummaryPanel extends JPanel {
 541         SummaryPanel() {
 542             setName("summary");
 543             setLayout(new GridBagLayout());
 544             add(type = new Entry("type"));
 545             add(name = new Entry("name"));
 546             add(path = new Entry("path"));
 547         }
 548 
 549         void setComponent(Component c) {
 550             if (c == null) {
 551                 setEnabled(false);
 552                 type.setEnabled(false);
 553                 name.setEnabled(false);
 554                 path.setEnabled(false);
 555             }
 556             else {
 557                 setEnabled(true);
 558                 type.setText(c.getClass().getName());
 559                 name.setText(c.getName(), "no name", STD_COLOR, WARN_COLOR);
 560                 path.setText(getPath(c));
 561             }
 562         }
 563 
 564         void write(Writer out) throws IOException {
 565             for (int i = 0; i <entries.size(); i++) {
 566                 Entry e = entries.elementAt(i);
 567                 e.write(out);
 568             }
 569         }
 570 
 571         public void setEnabled(boolean enabled) {
 572             super.setEnabled(enabled);
 573             for (int i = 0; i <entries.size(); i++) {
 574                 Entry e = entries.elementAt(i);
 575                 e.setParentEnabled(enabled);
 576             }
 577         }
 578 
 579         protected void add(Entry entry) {
 580             GridBagConstraints lc = new GridBagConstraints();
 581             add(entry.label, lc);
 582 
 583             GridBagConstraints fc = new GridBagConstraints();
 584             fc.fill = GridBagConstraints.HORIZONTAL;
 585             fc.gridwidth = GridBagConstraints.REMAINDER;
 586             fc.weightx = 1;
 587             add(entry.field, fc);
 588 
 589             entries.add(entry);
 590         }
 591 
 592         private Vector<Entry> entries = new Vector<>();
 593         private Entry name;
 594         private Entry path;
 595         private Entry type;
 596     }
 597 
 598     private class DetailPanel extends SummaryPanel {
 599         DetailPanel() {
 600             // is accessible
 601             add(accName = new Entry("acc. name"));
 602             add(accDesc = new Entry("acc. desc"));
 603             add(toolTip = new Entry("tooltip"));
 604             add(text = new Entry("text"));
 605             // labelled by
 606             add(labelFor = new Entry("label for"));
 607             add(mnemonic = new Entry("mnemonic"));
 608             add(fwdKeys = new Entry("> keys"));
 609             add(bwdKeys = new Entry("< keys"));
 610             add(upKeys = new Entry("^ keys"));
 611             add(downKeys = new Entry("v keys"));
 612         }
 613 
 614         void setComponent(Component c) {
 615             // summary info (type, name)
 616             super.setComponent(c);
 617 
 618             // accessible info (name, description)
 619             AccessibleContext ac = (c == null ? null : c.getAccessibleContext());
 620             if (ac == null) {
 621                 accName.setText(null, "not accessible");
 622                 accDesc.setText(null, "not accessible");
 623             }
 624             else {
 625                 boolean sb = (c instanceof JScrollBar);
 626                 String an = ac.getAccessibleName();
 627                 accName.setText((an != null ? an : "no accessible name"), (an != null || sb));
 628                 String ad = ac.getAccessibleDescription();
 629                 accDesc.setText((ad != null ? ad : "no accessible description"), (ad != null || sb));
 630             }
 631 
 632             if (c != null && c instanceof JComponent) {
 633                 String ttText = ((JComponent)c).getToolTipText();
 634                 boolean ttEmpty = (ttText == null || ttText.length() == 0);
 635                 boolean toolTipOK = !ttEmpty
 636                     || c instanceof JTree
 637                     || c instanceof JEditorPane
 638                     || c instanceof JHelpContentViewer
 639                     || c instanceof JList
 640                     || c instanceof JRootPane
 641                     || c instanceof JScrollBar
 642                     || (c instanceof JTextComponent && !((JTextComponent) c).isEditable());
 643                 toolTip.setText((ttEmpty ? "no tooltip" : ttText), toolTipOK);
 644             }
 645             else
 646                 toolTip.setEnabled(false);
 647 
 648             // what the text content might be
 649             if (c instanceof JButton)
 650                 text.setText(((JButton) c).getText());
 651             else if (c instanceof JLabel)
 652                 text.setText(((JLabel) c).getText());
 653             else if (c instanceof JTextComponent) {
 654                 JTextComponent tc = (JTextComponent) c;
 655                 Document d = tc.getDocument();
 656                 try {
 657                     text.setText(d.getText(0, Math.min(80, d.getLength())));
 658                 }
 659                 catch (Exception e) {
 660                     text.setText(null, e.toString());
 661                 }
 662             }
 663             else
 664                 text.setEnabled(false);
 665 
 666             // what it might be a label for
 667             if (c != null && c instanceof JLabel)
 668                 labelFor.setText(c.getClass().getName() + " " + c.getName());
 669             else
 670                 labelFor.setEnabled(false);
 671 
 672             // what the mnemonic might be
 673             if (c instanceof JLabel) {
 674                 JLabel l = (JLabel) c;
 675                 int mne = l.getDisplayedMnemonic();
 676                 boolean mnemonicOK = (mne != 0
 677                                       || l.getLabelFor() == null);
 678                 mnemonic.setText((mne == 0 ? "no mnemonic" : String.valueOf((char)mne)), mnemonicOK);
 679             }
 680             else if (c instanceof JButton) {
 681                 JButton b = (JButton) c;
 682                 int mne = b.getMnemonic();
 683                 String cmd = b.getActionCommand();
 684                 boolean mnemonicOK = (mne != 0
 685                                      || (cmd != null && cmd.equals(UIFactory.CANCEL)));
 686                 mnemonic.setText(mne == 0 ? "no mnemonic" : String.valueOf((char)mne), mnemonicOK);
 687             }
 688             else
 689                 mnemonic.setEnabled(false);
 690 
 691             // what the traversal keys are
 692             fwdKeys.setText(getKeysString(c, KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS));
 693             bwdKeys.setText(getKeysString(c, KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS));
 694             upKeys.setText(getKeysString(c, KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS));
 695             downKeys.setText(getKeysString(c, KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS));
 696         }
 697 
 698         private Entry accName;
 699         private Entry accDesc;
 700         private Entry toolTip;
 701         private Entry text;
 702         private Entry labelFor;
 703         private Entry mnemonic;
 704         private Entry fwdKeys;
 705         private Entry bwdKeys;
 706         private Entry upKeys;
 707         private Entry downKeys;
 708 
 709     }
 710 }