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