jdk/test/sanity/client/lib/jemmy/src/org/netbeans/jemmy/explorer/GUIBrowser.java
changeset 36744 a00905527ec2
equal deleted inserted replaced
36743:bdc3f1b79fb7 36744:a00905527ec2
       
     1 /*
       
     2  * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  */
       
    23 package org.netbeans.jemmy.explorer;
       
    24 
       
    25 import java.awt.AWTEvent;
       
    26 import java.awt.AWTException;
       
    27 import java.awt.BorderLayout;
       
    28 import java.awt.Color;
       
    29 import java.awt.Component;
       
    30 import java.awt.Container;
       
    31 import java.awt.Dimension;
       
    32 import java.awt.Frame;
       
    33 import java.awt.Graphics;
       
    34 import java.awt.Rectangle;
       
    35 import java.awt.Robot;
       
    36 import java.awt.Window;
       
    37 import java.awt.event.ActionEvent;
       
    38 import java.awt.event.ActionListener;
       
    39 import java.awt.event.ComponentEvent;
       
    40 import java.awt.event.ComponentListener;
       
    41 import java.awt.event.WindowEvent;
       
    42 import java.awt.event.WindowListener;
       
    43 import java.awt.image.BufferedImage;
       
    44 import java.io.ByteArrayOutputStream;
       
    45 import java.io.File;
       
    46 import java.io.FileInputStream;
       
    47 import java.io.FileOutputStream;
       
    48 import java.io.IOException;
       
    49 import java.io.OutputStream;
       
    50 import java.io.OutputStreamWriter;
       
    51 import java.io.PrintWriter;
       
    52 import java.lang.reflect.Field;
       
    53 import java.lang.reflect.InvocationTargetException;
       
    54 import java.lang.reflect.Method;
       
    55 import java.lang.reflect.Modifier;
       
    56 import java.util.Arrays;
       
    57 import java.util.Collections;
       
    58 import java.util.Comparator;
       
    59 import java.util.Hashtable;
       
    60 import java.util.Properties;
       
    61 import java.util.Vector;
       
    62 
       
    63 import javax.swing.DefaultListModel;
       
    64 import javax.swing.JButton;
       
    65 import javax.swing.JCheckBox;
       
    66 import javax.swing.JComboBox;
       
    67 import javax.swing.JDialog;
       
    68 import javax.swing.JFileChooser;
       
    69 import javax.swing.JFrame;
       
    70 import javax.swing.JLabel;
       
    71 import javax.swing.JList;
       
    72 import javax.swing.JPanel;
       
    73 import javax.swing.JScrollPane;
       
    74 import javax.swing.JSplitPane;
       
    75 import javax.swing.JTabbedPane;
       
    76 import javax.swing.JTable;
       
    77 import javax.swing.JTextArea;
       
    78 import javax.swing.JTextField;
       
    79 import javax.swing.JTree;
       
    80 import javax.swing.ListCellRenderer;
       
    81 import javax.swing.border.BevelBorder;
       
    82 import javax.swing.event.ChangeEvent;
       
    83 import javax.swing.event.ChangeListener;
       
    84 import javax.swing.event.ListSelectionEvent;
       
    85 import javax.swing.event.ListSelectionListener;
       
    86 import javax.swing.event.TreeModelListener;
       
    87 import javax.swing.event.TreeSelectionEvent;
       
    88 import javax.swing.event.TreeSelectionListener;
       
    89 import javax.swing.filechooser.FileFilter;
       
    90 import javax.swing.table.DefaultTableModel;
       
    91 import javax.swing.tree.TreeCellRenderer;
       
    92 import javax.swing.tree.TreeModel;
       
    93 import javax.swing.tree.TreePath;
       
    94 
       
    95 import org.netbeans.jemmy.ClassReference;
       
    96 import org.netbeans.jemmy.QueueTool;
       
    97 import org.netbeans.jemmy.TestOut;
       
    98 import org.netbeans.jemmy.operators.Operator;
       
    99 import org.netbeans.jemmy.util.Dumper;
       
   100 
       
   101 /**
       
   102  * An application allowing to explore a Java GUI application. Could be executed
       
   103  * by command: <br>
       
   104  * <pre>
       
   105  * java "application java options" \
       
   106  *   org.netbeans.jemmy.explorer.GUIBrowser \
       
   107  *   "application main class" \
       
   108  *   "application parameters"
       
   109  * </pre> or from java code by {@code GUIBrowser.showBrowser()} method
       
   110  * using.
       
   111  *
       
   112  * @author Alexandre Iline (alexandre.iline@oracle.com)
       
   113  */
       
   114 public class GUIBrowser extends JFrame {
       
   115 
       
   116     private static String WINDOWS_TAB = "Subwindows";
       
   117     private static String COMPONENTS_TAB = "Hierarchy";
       
   118     private static String PROPERTIES_TAB = "Properties";
       
   119     private static String REFLECTION_TAB = "Reflection";
       
   120     private static String EVENT_TAB = "Events";
       
   121     private static String IMAGE_TAB = "Image";
       
   122 
       
   123     boolean exit;
       
   124     PropertyDialog propDialog;
       
   125     RootNode root;
       
   126     QueueTool qt;
       
   127     JTextField refreshDelay;
       
   128     JTree mainTree;
       
   129     JLabel status;
       
   130     JButton viewButton;
       
   131     JButton expandButton;
       
   132     JSplitPane split;
       
   133     ByteArrayOutputStream dumpData;
       
   134     PrintWriter dumpWriter;
       
   135 
       
   136     private GUIBrowser(boolean exitNecessary) {
       
   137         super("GUI Browser");
       
   138 
       
   139         dumpData = new ByteArrayOutputStream();
       
   140         dumpWriter = new PrintWriter(new OutputStreamWriter(dumpData));
       
   141 
       
   142         exit = exitNecessary;
       
   143         propDialog = new PropertyDialog(this);
       
   144         qt = new QueueTool();
       
   145         qt.setOutput(TestOut.getNullOutput());
       
   146         root = new RootNode();
       
   147 
       
   148         mainTree = new JTree(root.getWindowModel());
       
   149         mainTree.setCellRenderer(new WindowRenderer());
       
   150         mainTree.setEditable(false);
       
   151 
       
   152         refreshDelay = new JTextField(3);
       
   153         refreshDelay.setText("0");
       
   154 
       
   155         viewButton = new JButton("View");
       
   156         viewButton.setEnabled(false);
       
   157         viewButton.addActionListener(new ActionListener() {
       
   158             @Override
       
   159             public void actionPerformed(ActionEvent e) {
       
   160                 new ComponentBrowser(getOwnr(),
       
   161                         (ComponentNode) mainTree.getSelectionPath().
       
   162                         getLastPathComponent()).
       
   163                         setVisible(true);
       
   164             }
       
   165         });
       
   166 
       
   167         expandButton = new JButton("Expand All");
       
   168         expandButton.setEnabled(false);
       
   169         expandButton.addActionListener(new ActionListener() {
       
   170             @Override
       
   171             public void actionPerformed(ActionEvent e) {
       
   172                 expandAll(mainTree,
       
   173                         mainTree.getSelectionPath());
       
   174             }
       
   175         });
       
   176 
       
   177         JButton refreshButton = new JButton("Reload in ...");
       
   178         refreshButton.addActionListener(new ActionListener() {
       
   179             @Override
       
   180             public void actionPerformed(ActionEvent e) {
       
   181                 reload(Integer.parseInt(refreshDelay.getText()));
       
   182             }
       
   183         });
       
   184 
       
   185         JButton dumpButton = new JButton("Dump");
       
   186         dumpButton.addActionListener(new ActionListener() {
       
   187             @Override
       
   188             public void actionPerformed(ActionEvent e) {
       
   189                 JFileChooser chooser
       
   190                         = new JFileChooser(System.getProperty("user.home"));
       
   191                 chooser.addChoosableFileFilter(new FileFilter() {
       
   192                     @Override
       
   193                     public boolean accept(File f) {
       
   194                         return f.getName().endsWith(".xml");
       
   195                     }
       
   196 
       
   197                     @Override
       
   198                     public String getDescription() {
       
   199                         return "xml files";
       
   200                     }
       
   201 
       
   202                     @Override
       
   203                     public String toString() {
       
   204                         return "dumpButton.ActionListener{description = " + getDescription() + '}';
       
   205                     }
       
   206                 });
       
   207                 chooser.showSaveDialog(GUIBrowser.this);
       
   208                 try {
       
   209                     File file = chooser.getSelectedFile();
       
   210                     try (OutputStream output = new FileOutputStream(file)) {
       
   211                         output.write(dumpData.toByteArray());
       
   212                     }
       
   213                 } catch (IOException ee) {
       
   214                     ee.printStackTrace();
       
   215                 }
       
   216             }
       
   217         });
       
   218 
       
   219         JPanel refreshPane = new JPanel();
       
   220         refreshPane.add(viewButton);
       
   221         refreshPane.add(expandButton);
       
   222         refreshPane.add(new JLabel(""));
       
   223         refreshPane.add(new JLabel(""));
       
   224         refreshPane.add(new JLabel(""));
       
   225         refreshPane.add(new JLabel(""));
       
   226         refreshPane.add(new JLabel(""));
       
   227         refreshPane.add(new JLabel(""));
       
   228         refreshPane.add(refreshButton);
       
   229         refreshPane.add(refreshDelay);
       
   230         refreshPane.add(new JLabel("seconds     "));
       
   231         refreshPane.add(dumpButton);
       
   232 
       
   233         split = createUnderPane(mainTree);
       
   234 
       
   235         JPanel nonStatusPane = new JPanel();
       
   236         nonStatusPane.setLayout(new BorderLayout());
       
   237         nonStatusPane.add(refreshPane, BorderLayout.SOUTH);
       
   238         nonStatusPane.add(split, BorderLayout.CENTER);
       
   239 
       
   240         split.setDividerLocation(0.8);
       
   241 
       
   242         status = new JLabel("Reloaded");
       
   243 
       
   244         JPanel statusPane = new JPanel();
       
   245         statusPane.setLayout(new BorderLayout());
       
   246         statusPane.add(status, BorderLayout.CENTER);
       
   247         statusPane.setBorder(new BevelBorder(BevelBorder.LOWERED));
       
   248 
       
   249         JPanel bottomPane = new JPanel();
       
   250         bottomPane.setLayout(new BorderLayout());
       
   251         bottomPane.add(statusPane, BorderLayout.NORTH);
       
   252         bottomPane.add(statusPane, BorderLayout.CENTER);
       
   253 
       
   254         getContentPane().setLayout(new BorderLayout());
       
   255         getContentPane().add(bottomPane, BorderLayout.SOUTH);
       
   256         getContentPane().add(nonStatusPane, BorderLayout.CENTER);
       
   257 
       
   258         Component[] cpss = {viewButton, expandButton};
       
   259         mainTree.addTreeSelectionListener(new SelectionManager(cpss));
       
   260 
       
   261         addWindowListener(new WindowListener() {
       
   262             @Override
       
   263             public void windowActivated(WindowEvent e) {
       
   264             }
       
   265 
       
   266             @Override
       
   267             public void windowClosed(WindowEvent e) {
       
   268                 setVisible(false);
       
   269                 if (exit) {
       
   270                     System.exit(0);
       
   271                 }
       
   272             }
       
   273 
       
   274             @Override
       
   275             public void windowClosing(WindowEvent e) {
       
   276             }
       
   277 
       
   278             @Override
       
   279             public void windowDeactivated(WindowEvent e) {
       
   280             }
       
   281 
       
   282             @Override
       
   283             public void windowDeiconified(WindowEvent e) {
       
   284             }
       
   285 
       
   286             @Override
       
   287             public void windowIconified(WindowEvent e) {
       
   288             }
       
   289 
       
   290             @Override
       
   291             public void windowOpened(WindowEvent e) {
       
   292             }
       
   293         });
       
   294         addComponentListener(new ComponentListener() {
       
   295             @Override
       
   296             public void componentHidden(ComponentEvent e) {
       
   297             }
       
   298 
       
   299             @Override
       
   300             public void componentMoved(ComponentEvent e) {
       
   301             }
       
   302 
       
   303             @Override
       
   304             public void componentResized(ComponentEvent e) {
       
   305                 split.setDividerLocation(0.8);
       
   306             }
       
   307 
       
   308             @Override
       
   309             public void componentShown(ComponentEvent e) {
       
   310             }
       
   311         });
       
   312 
       
   313         setSize(800, 400);
       
   314     }
       
   315 
       
   316     boolean shown = false;
       
   317 
       
   318     @Override
       
   319     @Deprecated
       
   320     public void show() {
       
   321         super.show();
       
   322         viewButton.setEnabled(false);
       
   323         if (!shown) {
       
   324             split.setDividerLocation(0.8);
       
   325             shown = true;
       
   326         }
       
   327     }
       
   328 
       
   329     /**
       
   330      * Specifies a status text.
       
   331      *
       
   332      * @param st a status text.
       
   333      */
       
   334     public void setStatus(String st) {
       
   335         status.setText(st);
       
   336     }
       
   337 
       
   338     /**
       
   339      * Method to invoke GUIBrowser from java code.
       
   340      */
       
   341     public static void showBrowser() {
       
   342         showBrowser(new String[0], false);
       
   343     }
       
   344 
       
   345     /**
       
   346      * Method to invoke GUIBrowser as java application.
       
   347      *
       
   348      * @param argv Argument array. If not empty, first element should be<br>
       
   349      * main class of an aplication to be browsed.<br>
       
   350      * Other elements are application parameters.
       
   351      */
       
   352     public static void main(String[] argv) {
       
   353         showBrowser(argv, true);
       
   354     }
       
   355 
       
   356     private static void showBrowser(String[] argv, boolean exitNecessary) {
       
   357         if (argv.length >= 1) {
       
   358             String[] newArgv = new String[argv.length - 1];
       
   359             System.arraycopy(argv, 1, newArgv, 0, argv.length - 1);
       
   360             try {
       
   361                 new ClassReference(argv[0]).startApplication(newArgv);
       
   362             } catch (ClassNotFoundException
       
   363                     | InvocationTargetException
       
   364                     | NoSuchMethodException e) {
       
   365                 e.printStackTrace();
       
   366                 return;
       
   367             }
       
   368         }
       
   369         new GUIBrowser(exitNecessary).show();
       
   370     }
       
   371 
       
   372     private void reload(final int delay) {
       
   373         viewButton.setEnabled(false);
       
   374         expandButton.setEnabled(false);
       
   375         new Thread(new Runnable() {
       
   376             @Override
       
   377             public void run() {
       
   378                 try {
       
   379                     for (int i = delay - 1; i >= 0; i--) {
       
   380                         setStatus("Reloading after " + Integer.toString(i) + " second");
       
   381                         Thread.sleep(1000);
       
   382                     }
       
   383                     setStatus("Reloading ...");
       
   384                     Dumper.dumpAll(dumpWriter);
       
   385                     //qt.lock();
       
   386                     root = new RootNode();
       
   387                     //qt.unlock();
       
   388                     mainTree.setModel(root.getWindowModel());
       
   389                     setStatus("Reloaded");
       
   390                 } catch (InterruptedException ignored) {
       
   391                 }
       
   392             }
       
   393         }).start();
       
   394     }
       
   395 
       
   396     private JFrame getOwnr() {
       
   397         return this;
       
   398     }
       
   399 
       
   400     private class ClassNode {
       
   401 
       
   402         Class<?> clzz;
       
   403 
       
   404         protected ClassNode() {
       
   405             clzz = null;
       
   406         }
       
   407 
       
   408         public ClassNode(Class<?> clzz) {
       
   409             this.clzz = clzz;
       
   410         }
       
   411 
       
   412         public ClassNode[] getSuperClasses() {
       
   413             int count = 0;
       
   414             Class<?> parent = clzz;
       
   415             while ((parent = parent.getSuperclass()) != null) {
       
   416                 count++;
       
   417             }
       
   418             Class<?>[] interfaces = clzz.getInterfaces();
       
   419             ClassNode[] result = new ClassNode[count + interfaces.length + 1];
       
   420             result[0] = new SuperClassNode(clzz);
       
   421             count = 1;
       
   422             parent = clzz;
       
   423             while ((parent = parent.getSuperclass()) != null) {
       
   424                 result[count] = new SuperClassNode(parent);
       
   425                 count++;
       
   426             }
       
   427             for (int i = count; i < count + interfaces.length; i++) {
       
   428                 result[i] = new InterfaceNode(interfaces[i - count]);
       
   429             }
       
   430             return result;
       
   431         }
       
   432 
       
   433         public String toString() {
       
   434             if (clzz.isArray()) {
       
   435                 return clzz.getComponentType().getName() + "[]";
       
   436             } else {
       
   437                 return clzz.getName();
       
   438             }
       
   439         }
       
   440 
       
   441         public TreeModel getMethodsModel() {
       
   442             return new ClassModel(this);
       
   443         }
       
   444 
       
   445         public ClassNode[] getSubNodes() {
       
   446             Vector<ClassNode> res = new Vector<>();
       
   447             Field[] fields = clzz.getFields();
       
   448             Arrays.sort(fields, new Comparator<Field>() {
       
   449                 @Override
       
   450                 public int compare(Field f1, Field f2) {
       
   451                     return f1.getName().compareTo(f2.getName());
       
   452                 }
       
   453             });
       
   454             Method[] mtds = clzz.getMethods();
       
   455             Arrays.sort(mtds, new Comparator<Method>() {
       
   456                 @Override
       
   457                 public int compare(Method m1, Method m2) {
       
   458                     return m1.getName().compareTo(m2.getName());
       
   459                 }
       
   460             });
       
   461             for (Field field : fields) {
       
   462                 if (field.getDeclaringClass().getName().equals(clzz.getName())) {
       
   463                     res.add(new FieldNode(field));
       
   464                 }
       
   465             }
       
   466             for (Method mtd : mtds) {
       
   467                 if (mtd.getDeclaringClass().getName().equals(clzz.getName())) {
       
   468                     res.add(new MethodNode(mtd));
       
   469                 }
       
   470             }
       
   471             ClassNode[] result = new ClassNode[res.size()];
       
   472             for (int i = 0; i < result.length; i++) {
       
   473                 result[i] = res.get(i);
       
   474             }
       
   475             return result;
       
   476         }
       
   477     }
       
   478 
       
   479     private class SuperClassNode extends ClassNode {
       
   480 
       
   481         public SuperClassNode(Class<?> clzz) {
       
   482             super(clzz);
       
   483         }
       
   484 
       
   485         public String toString() {
       
   486             return "Class: " + super.toString();
       
   487         }
       
   488     }
       
   489 
       
   490     private class InterfaceNode extends ClassNode {
       
   491 
       
   492         public InterfaceNode(Class<?> clzz) {
       
   493             super(clzz);
       
   494         }
       
   495 
       
   496         public String toString() {
       
   497             return "Interfac: " + super.toString();
       
   498         }
       
   499     }
       
   500 
       
   501     private class FieldNode extends ClassNode {
       
   502 
       
   503         Field field;
       
   504 
       
   505         public FieldNode(Field fld) {
       
   506             super(fld.getType());
       
   507             field = fld;
       
   508         }
       
   509 
       
   510         public String toString() {
       
   511             return ("Field: "
       
   512                     + Modifier.toString(field.getModifiers()) + " "
       
   513                     + super.toString() + " "
       
   514                     + field.getName());
       
   515         }
       
   516     }
       
   517 
       
   518     private class MethodNode extends ClassNode {
       
   519 
       
   520         Method method;
       
   521 
       
   522         public MethodNode(Method mtd) {
       
   523             super(mtd.getReturnType());
       
   524             method = mtd;
       
   525         }
       
   526 
       
   527         public String toString() {
       
   528             return ("Method: "
       
   529                     + Modifier.toString(method.getModifiers()) + " "
       
   530                     + super.toString() + " "
       
   531                     + method.getName());
       
   532 
       
   533         }
       
   534 
       
   535         public ClassNode[] getParameters() {
       
   536             Class<?>[] ptps = method.getParameterTypes();
       
   537             ClassNode[] result = new ClassNode[ptps.length];
       
   538             for (int i = 0; i < ptps.length; i++) {
       
   539                 result[i] = new ClassNode(ptps[i]);
       
   540             }
       
   541             return result;
       
   542         }
       
   543     }
       
   544 
       
   545     private class ComponentNode extends ClassNode {
       
   546 
       
   547         protected Hashtable<String, Object> props;
       
   548         protected String clss = "";
       
   549         protected String compToString = "";
       
   550         Component comp;
       
   551         ComponentImageProvider image;
       
   552         protected int x, y, w, h;
       
   553 
       
   554         protected ComponentNode() {
       
   555             props = new Hashtable<>();
       
   556         }
       
   557 
       
   558         public ComponentNode(Component comp) {
       
   559             super(comp.getClass());
       
   560             try {
       
   561                 props = Operator.createOperator(comp).getDump();
       
   562             } catch (Exception e) {
       
   563                 props = new Hashtable<>();
       
   564             }
       
   565             clss = comp.getClass().getName();
       
   566             compToString = comp.toString();
       
   567             this.comp = comp;
       
   568             x = comp.getLocationOnScreen().x;
       
   569             y = comp.getLocationOnScreen().y;
       
   570             w = comp.getWidth();
       
   571             h = comp.getHeight();
       
   572         }
       
   573 
       
   574         public String toString() {
       
   575             return clss;
       
   576         }
       
   577 
       
   578         public Hashtable<String, Object> getProperties() {
       
   579             return props;
       
   580         }
       
   581 
       
   582         public String getToString() {
       
   583             return compToString;
       
   584         }
       
   585 
       
   586         public void setComponentImageProvider(ComponentImageProvider provider) {
       
   587             image = provider;
       
   588         }
       
   589 
       
   590         public BufferedImage getImage() {
       
   591             if (image != null) {
       
   592                 return image.getImage(x, y, w, h);
       
   593             } else {
       
   594                 return null;
       
   595             }
       
   596         }
       
   597     }
       
   598 
       
   599     private class ContainerNode extends ComponentNode {
       
   600 
       
   601         protected ComponentNode[] comps;
       
   602 
       
   603         protected ContainerNode() {
       
   604             super();
       
   605             comps = new ComponentNode[0];
       
   606         }
       
   607 
       
   608         public ContainerNode(Container comp) {
       
   609             super(comp);
       
   610             Component[] cmps = comp.getComponents();
       
   611             Vector<ComponentNode> wwns = new Vector<>();
       
   612             for (Component cmp : cmps) {
       
   613                 if (cmp != null && (propDialog.showAll || cmp.isVisible())) {
       
   614                     if (cmp instanceof Container) {
       
   615                         wwns.add(new ContainerNode((Container) cmp));
       
   616                     } else {
       
   617                         wwns.add(new ComponentNode(cmp));
       
   618                     }
       
   619                 }
       
   620             }
       
   621             comps = new ComponentNode[wwns.size()];
       
   622             for (int i = 0; i < wwns.size(); i++) {
       
   623                 comps[i] = wwns.get(i);
       
   624             }
       
   625         }
       
   626 
       
   627         public ComponentNode[] getComponents() {
       
   628             return comps;
       
   629         }
       
   630 
       
   631         public int getComponentIndex(ComponentNode comp) {
       
   632             for (int i = 0; i < comps.length; i++) {
       
   633                 if (comps[i].equals(comp)) {
       
   634                     return i;
       
   635                 }
       
   636             }
       
   637             return -1;
       
   638         }
       
   639 
       
   640         @Override
       
   641         public void setComponentImageProvider(ComponentImageProvider provider) {
       
   642             super.setComponentImageProvider(provider);
       
   643             for (ComponentNode comp1 : comps) {
       
   644                 comp1.setComponentImageProvider(provider);
       
   645             }
       
   646         }
       
   647 
       
   648         public ComponentModel getComponentModel() {
       
   649             return new ComponentModel(this);
       
   650         }
       
   651     }
       
   652 
       
   653     private class WindowNode extends ContainerNode {
       
   654 
       
   655         protected WindowNode[] wins;
       
   656         String title;
       
   657 
       
   658         protected WindowNode() {
       
   659             super();
       
   660             wins = new WindowNode[0];
       
   661             title = "All Frames";
       
   662             clss = "";
       
   663         }
       
   664 
       
   665         public WindowNode(Window win) {
       
   666             super(win);
       
   667             Window[] wns = win.getOwnedWindows();
       
   668             Vector<WindowNode> wwns = new Vector<>();
       
   669             for (Window wn : wns) {
       
   670                 if (propDialog.showAll || wn.isVisible()) {
       
   671                     wwns.add(new WindowNode(wn));
       
   672                 }
       
   673             }
       
   674             wins = new WindowNode[wwns.size()];
       
   675             for (int i = 0; i < wwns.size(); i++) {
       
   676                 wins[i] = wwns.get(i);
       
   677             }
       
   678             title = win.toString();
       
   679             clss = win.getClass().getName();
       
   680             BufferedImage image = null;
       
   681             try {
       
   682                 image = new Robot().
       
   683                         createScreenCapture(new Rectangle(win.getLocationOnScreen(),
       
   684                                 win.getSize()));
       
   685             } catch (AWTException e) {
       
   686                 e.printStackTrace();
       
   687             }
       
   688             setComponentImageProvider(new ComponentImageProvider(image, x, y));
       
   689         }
       
   690 
       
   691         public WindowNode[] getWindows() {
       
   692             return wins;
       
   693         }
       
   694 
       
   695         public int getWindowIndex(WindowNode node) {
       
   696             for (int i = 0; i < wins.length; i++) {
       
   697                 if (wins[i].equals(node)) {
       
   698                     return i;
       
   699                 }
       
   700             }
       
   701             return -1;
       
   702         }
       
   703 
       
   704         public WindowModel getWindowModel() {
       
   705             return new WindowModel(this);
       
   706         }
       
   707 
       
   708         public String toString() {
       
   709             return clss + " \"" + title + "\"";
       
   710         }
       
   711     }
       
   712 
       
   713     private class RootNode extends WindowNode {
       
   714 
       
   715         public RootNode() {
       
   716             super();
       
   717             Window[] wns = Frame.getFrames();
       
   718             wins = new WindowNode[wns.length];
       
   719             int count = 0;
       
   720             for (Window wn1 : wns) {
       
   721                 if (propDialog.showAll || wn1.isVisible()) {
       
   722                     count++;
       
   723                 }
       
   724             }
       
   725             wins = new WindowNode[count];
       
   726             count = 0;
       
   727             for (Window wn : wns) {
       
   728                 if (propDialog.showAll || wn.isVisible()) {
       
   729                     wins[count] = new WindowNode(wn);
       
   730                     count++;
       
   731                 }
       
   732             }
       
   733         }
       
   734     }
       
   735 
       
   736     private static class ClassModel implements TreeModel {
       
   737 
       
   738         ClassNode clsn;
       
   739 
       
   740         ClassModel(ClassNode clsn) {
       
   741             this.clsn = clsn;
       
   742         }
       
   743 
       
   744         @Override
       
   745         public void addTreeModelListener(TreeModelListener l) {
       
   746         }
       
   747 
       
   748         @Override
       
   749         public Object getChild(Object parent, int index) {
       
   750             if (parent == clsn) {
       
   751                 return clsn.getSuperClasses()[index];
       
   752             } else if (parent instanceof SuperClassNode
       
   753                     || parent instanceof InterfaceNode) {
       
   754                 return ((ClassNode) parent).getSubNodes()[index];
       
   755             } else if (parent instanceof MethodNode) {
       
   756                 return ((MethodNode) parent).getParameters()[index];
       
   757             }
       
   758             return null;
       
   759         }
       
   760 
       
   761         @Override
       
   762         public int getChildCount(Object parent) {
       
   763             if (parent == clsn) {
       
   764                 return clsn.getSuperClasses().length;
       
   765             } else if (parent instanceof SuperClassNode
       
   766                     || parent instanceof InterfaceNode) {
       
   767                 return ((ClassNode) parent).getSubNodes().length;
       
   768             } else if (parent instanceof MethodNode) {
       
   769                 return ((MethodNode) parent).getParameters().length;
       
   770             }
       
   771             return 0;
       
   772         }
       
   773 
       
   774         @Override
       
   775         public int getIndexOfChild(Object parent, Object child) {
       
   776             if (parent == clsn
       
   777                     || parent instanceof MethodNode
       
   778                     || parent instanceof SuperClassNode
       
   779                     || parent instanceof InterfaceNode) {
       
   780                 Object[] children;
       
   781                 if (parent instanceof SuperClassNode
       
   782                         || parent instanceof InterfaceNode) {
       
   783                     children = ((ClassNode) parent).getSuperClasses();
       
   784                 } else if (parent instanceof MethodNode) {
       
   785                     children = ((MethodNode) parent).getParameters();
       
   786                 } else {
       
   787                     children = clsn.getSuperClasses();
       
   788                 }
       
   789                 for (int i = 0; i < children.length; i++) {
       
   790                     if (children.equals(child)) {
       
   791                         return i;
       
   792                     }
       
   793                 }
       
   794             }
       
   795             return 0;
       
   796         }
       
   797 
       
   798         @Override
       
   799         public Object getRoot() {
       
   800             return clsn;
       
   801         }
       
   802 
       
   803         @Override
       
   804         public boolean isLeaf(Object node) {
       
   805             return getChildCount(node) == 0;
       
   806         }
       
   807 
       
   808         @Override
       
   809         public void removeTreeModelListener(TreeModelListener l) {
       
   810         }
       
   811 
       
   812         @Override
       
   813         public void valueForPathChanged(TreePath path, Object newValue) {
       
   814         }
       
   815     }
       
   816 
       
   817     private static class WindowModel implements TreeModel {
       
   818 
       
   819         WindowNode win;
       
   820 
       
   821         WindowModel(WindowNode win) {
       
   822             this.win = win;
       
   823         }
       
   824 
       
   825         @Override
       
   826         public void addTreeModelListener(TreeModelListener l) {
       
   827         }
       
   828 
       
   829         @Override
       
   830         public Object getChild(Object parent, int index) {
       
   831             return ((WindowNode) parent).getWindows()[index];
       
   832         }
       
   833 
       
   834         @Override
       
   835         public int getChildCount(Object parent) {
       
   836             return ((WindowNode) parent).getWindows().length;
       
   837         }
       
   838 
       
   839         @Override
       
   840         public int getIndexOfChild(Object parent, Object child) {
       
   841             return ((WindowNode) parent).getWindowIndex((WindowNode) child);
       
   842         }
       
   843 
       
   844         @Override
       
   845         public Object getRoot() {
       
   846             return win;
       
   847         }
       
   848 
       
   849         @Override
       
   850         public boolean isLeaf(Object node) {
       
   851             return ((WindowNode) node).getWindows().length == 0;
       
   852         }
       
   853 
       
   854         @Override
       
   855         public void removeTreeModelListener(TreeModelListener l) {
       
   856         }
       
   857 
       
   858         @Override
       
   859         public void valueForPathChanged(TreePath path, Object newValue) {
       
   860         }
       
   861     }
       
   862 
       
   863     private static class ComponentModel implements TreeModel {
       
   864 
       
   865         ContainerNode cont;
       
   866 
       
   867         ComponentModel(ContainerNode cont) {
       
   868             this.cont = cont;
       
   869         }
       
   870 
       
   871         @Override
       
   872         public void addTreeModelListener(TreeModelListener l) {
       
   873         }
       
   874 
       
   875         @Override
       
   876         public Object getChild(Object parent, int index) {
       
   877             if (parent instanceof ContainerNode) {
       
   878                 return ((ContainerNode) parent).getComponents()[index];
       
   879             } else {
       
   880                 return "";
       
   881             }
       
   882         }
       
   883 
       
   884         @Override
       
   885         public int getChildCount(Object parent) {
       
   886             if (parent instanceof ContainerNode) {
       
   887                 return ((ContainerNode) parent).getComponents().length;
       
   888             } else {
       
   889                 return 0;
       
   890             }
       
   891         }
       
   892 
       
   893         @Override
       
   894         public int getIndexOfChild(Object parent, Object child) {
       
   895             if (parent instanceof ContainerNode) {
       
   896                 return ((ContainerNode) parent).getComponentIndex((ComponentNode) child);
       
   897             } else {
       
   898                 return -1;
       
   899             }
       
   900         }
       
   901 
       
   902         @Override
       
   903         public Object getRoot() {
       
   904             return cont;
       
   905         }
       
   906 
       
   907         @Override
       
   908         public boolean isLeaf(Object node) {
       
   909             if (node instanceof ContainerNode) {
       
   910                 return ((ContainerNode) node).getComponents().length == 0;
       
   911             } else {
       
   912                 return true;
       
   913             }
       
   914         }
       
   915 
       
   916         @Override
       
   917         public void removeTreeModelListener(TreeModelListener l) {
       
   918         }
       
   919 
       
   920         @Override
       
   921         public void valueForPathChanged(TreePath path, Object newValue) {
       
   922         }
       
   923     }
       
   924 
       
   925     private static class WindowRenderer implements TreeCellRenderer, ListCellRenderer<ClassNode> {
       
   926 
       
   927         public WindowRenderer() {
       
   928         }
       
   929 
       
   930         @Override
       
   931         public Component getTreeCellRendererComponent(JTree tree,
       
   932                 Object value,
       
   933                 boolean selected,
       
   934                 boolean expanded,
       
   935                 boolean leaf,
       
   936                 int row,
       
   937                 boolean hasFocus) {
       
   938             return get((ClassNode) value, selected);
       
   939         }
       
   940 
       
   941         @Override
       
   942         public Component getListCellRendererComponent(JList<? extends ClassNode> list,
       
   943                 ClassNode value,
       
   944                 int index,
       
   945                 boolean isSelected,
       
   946                 boolean cellHasFocus) {
       
   947             return get(value, isSelected);
       
   948         }
       
   949 
       
   950         private Component get(ClassNode value, boolean selected) {
       
   951             Component result = new JLabel(value.toString());
       
   952             if (selected) {
       
   953                 result.setBackground(Color.blue);
       
   954                 result.setForeground(Color.white);
       
   955                 JPanel resPane = new JPanel();
       
   956                 resPane.setLayout(new BorderLayout());
       
   957                 resPane.add(result, BorderLayout.CENTER);
       
   958                 return resPane;
       
   959             } else {
       
   960                 return result;
       
   961             }
       
   962         }
       
   963     }
       
   964 
       
   965     private static class PropertyDialog extends JDialog {
       
   966 
       
   967         public boolean showAll = false;
       
   968         JComboBox<String> visibleCombo;
       
   969         JCheckBox showToString;
       
   970         JCheckBox showReflection;
       
   971         JCheckBox showEvents;
       
   972         DefaultListModel<String> viewTabs;
       
   973         JList<String> orderList;
       
   974         JButton up;
       
   975         JButton down;
       
   976         Properties props;
       
   977         File propFile;
       
   978 
       
   979         public PropertyDialog(JFrame owner) {
       
   980             super(owner, "Properties", true);
       
   981 
       
   982             propFile = new File(System.getProperty("user.home")
       
   983                     + System.getProperty("file.separator")
       
   984                     + ".guibrowser");
       
   985 
       
   986             props = new Properties();
       
   987 
       
   988             String[] cpItems = {"Showing", "All"};
       
   989             visibleCombo = new JComboBox<>(cpItems);
       
   990             visibleCombo.addActionListener(new ActionListener() {
       
   991                 @Override
       
   992                 public void actionPerformed(ActionEvent e) {
       
   993                     showAll = (visibleCombo.getSelectedIndex() == 1);
       
   994                 }
       
   995             });
       
   996 
       
   997             JPanel visiblePane = new JPanel();
       
   998             visiblePane.add(new JLabel("Show "));
       
   999             visiblePane.add(visibleCombo);
       
  1000 
       
  1001             showToString = new JCheckBox("Show toString() method result");
       
  1002             showToString.setSelected(true);
       
  1003 
       
  1004             JPanel compTreePane = new JPanel();
       
  1005             compTreePane.add(visiblePane);
       
  1006 
       
  1007             viewTabs = new DefaultListModel<>();
       
  1008             viewTabs.addElement(WINDOWS_TAB);
       
  1009             viewTabs.addElement(COMPONENTS_TAB);
       
  1010             viewTabs.addElement(PROPERTIES_TAB);
       
  1011             viewTabs.addElement(REFLECTION_TAB);
       
  1012             viewTabs.addElement(IMAGE_TAB);
       
  1013 
       
  1014             orderList = new JList<>(viewTabs);
       
  1015             orderList.addListSelectionListener(new ListSelectionListener() {
       
  1016                 @Override
       
  1017                 public void valueChanged(ListSelectionEvent e) {
       
  1018                     up.setEnabled(orderList.getSelectedIndex() > -1);
       
  1019                     down.setEnabled(orderList.getSelectedIndex() > -1);
       
  1020                 }
       
  1021             });
       
  1022 
       
  1023             showReflection = new JCheckBox("Show reflection tab");
       
  1024             showReflection.setSelected(true);
       
  1025             showReflection.addActionListener(new ActionListener() {
       
  1026                 @Override
       
  1027                 public void actionPerformed(ActionEvent e) {
       
  1028                     if (showReflection.isSelected()) {
       
  1029                         viewTabs.addElement(REFLECTION_TAB);
       
  1030                     } else {
       
  1031                         viewTabs.remove(viewTabs.indexOf(REFLECTION_TAB));
       
  1032                     }
       
  1033                     up.setEnabled(orderList.getSelectedIndex() > -1);
       
  1034                     down.setEnabled(orderList.getSelectedIndex() > -1);
       
  1035                 }
       
  1036             });
       
  1037 
       
  1038             showEvents = new JCheckBox("Show event tab");
       
  1039             showEvents.setSelected(true);
       
  1040             showEvents.addActionListener(new ActionListener() {
       
  1041                 @Override
       
  1042                 public void actionPerformed(ActionEvent e) {
       
  1043                     if (showEvents.isSelected()) {
       
  1044                         viewTabs.addElement(EVENT_TAB);
       
  1045                     } else {
       
  1046                         viewTabs.remove(viewTabs.indexOf(EVENT_TAB));
       
  1047                     }
       
  1048                     up.setEnabled(orderList.getSelectedIndex() > -1);
       
  1049                     down.setEnabled(orderList.getSelectedIndex() > -1);
       
  1050                 }
       
  1051             });
       
  1052 
       
  1053             up = new JButton("Move Up");
       
  1054             up.setEnabled(false);
       
  1055             up.addActionListener(new ActionListener() {
       
  1056                 @Override
       
  1057                 public void actionPerformed(ActionEvent e) {
       
  1058                     int index = orderList.getSelectedIndex();
       
  1059                     if (index > 0) {
       
  1060                         viewTabs.add(index - 1,
       
  1061                                 viewTabs.remove(index));
       
  1062                         orderList.setSelectedIndex(index - 1);
       
  1063                     }
       
  1064                 }
       
  1065             });
       
  1066 
       
  1067             down = new JButton("Move Down");
       
  1068             down.setEnabled(false);
       
  1069             down.addActionListener(new ActionListener() {
       
  1070                 @Override
       
  1071                 public void actionPerformed(ActionEvent e) {
       
  1072                     int index = orderList.getSelectedIndex();
       
  1073                     if (index < viewTabs.size() - 1) {
       
  1074                         viewTabs.add(index + 1,
       
  1075                                 viewTabs.remove(index));
       
  1076                         orderList.setSelectedIndex(index + 1);
       
  1077                     }
       
  1078                 }
       
  1079             });
       
  1080 
       
  1081             JPanel movePane = new JPanel();
       
  1082             movePane.add(showEvents);
       
  1083             movePane.add(showReflection);
       
  1084             movePane.add(up);
       
  1085             movePane.add(down);
       
  1086 
       
  1087             JPanel compViewPane = new JPanel();
       
  1088             compViewPane.setLayout(new BorderLayout());
       
  1089             compViewPane.add(new JLabel("Tab order:"), BorderLayout.NORTH);
       
  1090             compViewPane.add(movePane, BorderLayout.SOUTH);
       
  1091             compViewPane.add(orderList, BorderLayout.CENTER);
       
  1092 
       
  1093             JTabbedPane tbpn = new JTabbedPane();
       
  1094             tbpn.add("Component Tree", compTreePane);
       
  1095             tbpn.add("Component View", compViewPane);
       
  1096 
       
  1097             JButton okBUtton = new JButton("OK");
       
  1098             okBUtton.addActionListener(new ActionListener() {
       
  1099                 @Override
       
  1100                 public void actionPerformed(ActionEvent e) {
       
  1101                     save();
       
  1102                     setVisible(false);
       
  1103                 }
       
  1104             });
       
  1105 
       
  1106             JButton cnBUtton = new JButton("Cancel");
       
  1107             cnBUtton.addActionListener(new ActionListener() {
       
  1108                 @Override
       
  1109                 public void actionPerformed(ActionEvent e) {
       
  1110                     setVisible(false);
       
  1111                     load();
       
  1112                 }
       
  1113             });
       
  1114 
       
  1115             JPanel pn = new JPanel();
       
  1116             pn.add(okBUtton);
       
  1117             pn.add(cnBUtton);
       
  1118 
       
  1119             getContentPane().setLayout(new BorderLayout());
       
  1120             getContentPane().add(pn, BorderLayout.SOUTH);
       
  1121             getContentPane().add(tbpn, BorderLayout.CENTER);
       
  1122 
       
  1123             load();
       
  1124 
       
  1125             setSize(400, 400);
       
  1126         }
       
  1127 
       
  1128         private void save() {
       
  1129             try {
       
  1130                 props.setProperty("guibrowser.showall",
       
  1131                         showAll ? "on" : "off");
       
  1132                 for (int i = 0; i < viewTabs.size(); i++) {
       
  1133                     props.setProperty("guibrowser.viewpage_" + Integer.toString(i),
       
  1134                             viewTabs.elementAt(i));
       
  1135                 }
       
  1136                 try (FileOutputStream fileOutputStream = new FileOutputStream(propFile)) {
       
  1137                     props.store(fileOutputStream,
       
  1138                             "Jemmy GUIBrowser");
       
  1139                 }
       
  1140             } catch (IOException e) {
       
  1141                 e.printStackTrace();
       
  1142             }
       
  1143         }
       
  1144 
       
  1145         private void load() {
       
  1146             if (propFile.exists()) {
       
  1147                 try {
       
  1148                     try (FileInputStream fileInputStream = new FileInputStream(propFile)) {
       
  1149                         props.load(fileInputStream);
       
  1150                     }
       
  1151                     showAll
       
  1152                             = props.getProperty("guibrowser.showall") == null
       
  1153                             || props.getProperty("guibrowser.showall").equals("")
       
  1154                             || props.getProperty("guibrowser.showall").equals("on");
       
  1155                     visibleCombo.setSelectedIndex(showAll ? 1 : 0);
       
  1156                     if (props.getProperty("guibrowser.viewpage_0") != null
       
  1157                             && !props.getProperty("guibrowser.viewpage_0").equals("")) {
       
  1158                         viewTabs.removeAllElements();
       
  1159                         viewTabs.addElement(props.getProperty("guibrowser.viewpage_0"));
       
  1160                         viewTabs.addElement(props.getProperty("guibrowser.viewpage_1"));
       
  1161                         viewTabs.addElement(props.getProperty("guibrowser.viewpage_2"));
       
  1162                         if (props.getProperty("guibrowser.viewpage_3") != null
       
  1163                                 && !props.getProperty("guibrowser.viewpage_3").equals("")) {
       
  1164                             viewTabs.addElement(props.getProperty("guibrowser.viewpage_3"));
       
  1165                         }
       
  1166                         if (props.getProperty("guibrowser.viewpage_4") != null
       
  1167                                 && !props.getProperty("guibrowser.viewpage_4").equals("")) {
       
  1168                             viewTabs.addElement(props.getProperty("guibrowser.viewpage_4"));
       
  1169                         }
       
  1170                     }
       
  1171                 } catch (IOException e) {
       
  1172                     e.printStackTrace();
       
  1173                 }
       
  1174                 showReflection.setSelected(viewTabs.indexOf(REFLECTION_TAB) > -1);
       
  1175                 showEvents.setSelected(viewTabs.indexOf(EVENT_TAB) > -1);
       
  1176             }
       
  1177         }
       
  1178     }
       
  1179 
       
  1180     private class ComponentBrowser extends JFrame {
       
  1181 
       
  1182         JTree winTree;
       
  1183         JTree componentTree;
       
  1184         JTree methodTree;
       
  1185         ClassNode compNode;
       
  1186         JTabbedPane tbd;
       
  1187         JButton viewButton;
       
  1188         JButton expandButton;
       
  1189         JSplitPane winSplit = null;
       
  1190         JSplitPane componentSplit = null;
       
  1191         WindowRenderer renderer;
       
  1192         SelectionManager selManager;
       
  1193         JList<AWTEvent> eventList;
       
  1194         ListListener listListener;
       
  1195         DefaultListModel<AWTEvent> eventModel;
       
  1196         JCheckBox mouseEvents;
       
  1197         JCheckBox mouseMotionEvents;
       
  1198         JCheckBox keyEvents;
       
  1199 
       
  1200         public ComponentBrowser(JFrame owner, ClassNode componentNode) {
       
  1201             super("Component " + componentNode.toString());
       
  1202             fill(componentNode);
       
  1203         }
       
  1204 
       
  1205         private void fill(ClassNode componentNode) {
       
  1206             compNode = componentNode;
       
  1207 
       
  1208             viewButton = new JButton("View");
       
  1209             viewButton.setEnabled(false);
       
  1210             viewButton.addActionListener(new ActionListener() {
       
  1211                 @Override
       
  1212                 public void actionPerformed(ActionEvent e) {
       
  1213                     new ComponentBrowser(getOwnr(),
       
  1214                             getSelectedNode()).
       
  1215                             setVisible(true);
       
  1216                 }
       
  1217             });
       
  1218 
       
  1219             expandButton = new JButton("Expand All");
       
  1220             expandButton.setEnabled(false);
       
  1221             expandButton.addActionListener(new ActionListener() {
       
  1222                 @Override
       
  1223                 public void actionPerformed(ActionEvent e) {
       
  1224                     expandAll(getSelectedTree(),
       
  1225                             getSelectionPath());
       
  1226                 }
       
  1227             });
       
  1228 
       
  1229             JPanel buttonPane = new JPanel();
       
  1230             buttonPane.add(viewButton);
       
  1231             buttonPane.add(expandButton);
       
  1232 
       
  1233             Component[] cpss = {viewButton, expandButton};
       
  1234             selManager = new SelectionManager(cpss);
       
  1235             renderer = new WindowRenderer();
       
  1236 
       
  1237             tbd = new JTabbedPane();
       
  1238 
       
  1239             for (int i = 0; i < propDialog.viewTabs.size(); i++) {
       
  1240                 String next = propDialog.viewTabs.elementAt(i);
       
  1241                 if (next.equals(PROPERTIES_TAB)) {
       
  1242                     addPropertiesTab();
       
  1243                 } else if (next.equals(WINDOWS_TAB)) {
       
  1244                     addWindowTab();
       
  1245                 } else if (next.equals(COMPONENTS_TAB)) {
       
  1246                     addComponentTab();
       
  1247                 } else if (next.equals(REFLECTION_TAB)) {
       
  1248                     addReflectionTab();
       
  1249                 } else if (next.equals(EVENT_TAB)) {
       
  1250                     addEventTab();
       
  1251                 } else if (next.equals(IMAGE_TAB)) {
       
  1252                     addImageTab();
       
  1253                 }
       
  1254             }
       
  1255 
       
  1256             tbd.addChangeListener(new ChangeListener() {
       
  1257                 @Override
       
  1258                 public void stateChanged(ChangeEvent e) {
       
  1259                     viewButton.setEnabled(getSelectedNode() != null);
       
  1260                 }
       
  1261             });
       
  1262 
       
  1263             getContentPane().setLayout(new BorderLayout());
       
  1264             getContentPane().add(buttonPane, BorderLayout.SOUTH);
       
  1265             getContentPane().add(tbd, BorderLayout.CENTER);
       
  1266 
       
  1267             addComponentListener(new ComponentListener() {
       
  1268                 @Override
       
  1269                 public void componentHidden(ComponentEvent e) {
       
  1270                 }
       
  1271 
       
  1272                 @Override
       
  1273                 public void componentMoved(ComponentEvent e) {
       
  1274                 }
       
  1275 
       
  1276                 @Override
       
  1277                 public void componentResized(ComponentEvent e) {
       
  1278                     if (winSplit != null) {
       
  1279                         winSplit.setDividerLocation(0.8);
       
  1280                     }
       
  1281                     if (componentSplit != null) {
       
  1282                         componentSplit.setDividerLocation(0.8);
       
  1283                     }
       
  1284                 }
       
  1285 
       
  1286                 @Override
       
  1287                 public void componentShown(ComponentEvent e) {
       
  1288                 }
       
  1289             });
       
  1290 
       
  1291             setSize(800, 400);
       
  1292         }
       
  1293 
       
  1294         private void addImageTab() {
       
  1295             BufferedImage image = null;
       
  1296             if (compNode instanceof ComponentNode) {
       
  1297                 image = ((ComponentNode) compNode).getImage();
       
  1298             }
       
  1299             if (image != null) {
       
  1300                 JPanel imagePane = new ImagePane(image);
       
  1301                 imagePane.prepareImage(image, imagePane);
       
  1302                 JScrollPane pane = new JScrollPane(imagePane);
       
  1303                 tbd.add(IMAGE_TAB, pane);
       
  1304             }
       
  1305         }
       
  1306 
       
  1307         private void addWindowTab() {
       
  1308             if (compNode instanceof WindowNode
       
  1309                     && ((WindowNode) compNode).getWindows().length > 0) {
       
  1310                 winTree = new JTree(((WindowNode) compNode).getWindowModel());
       
  1311                 winTree.setCellRenderer(renderer);
       
  1312                 winTree.setEditable(false);
       
  1313                 winTree.addTreeSelectionListener(selManager);
       
  1314                 winSplit = createUnderPane(winTree);
       
  1315                 tbd.add(WINDOWS_TAB, winSplit);
       
  1316             }
       
  1317 
       
  1318         }
       
  1319 
       
  1320         private void addComponentTab() {
       
  1321             if (compNode instanceof ContainerNode
       
  1322                     && ((ContainerNode) compNode).getComponents().length > 0) {
       
  1323                 componentTree = new JTree(((ContainerNode) compNode).getComponentModel());
       
  1324                 componentTree.setCellRenderer(renderer);
       
  1325                 componentTree.setEditable(false);
       
  1326                 componentTree.addTreeSelectionListener(selManager);
       
  1327                 componentSplit = createUnderPane(componentTree);
       
  1328                 tbd.add(COMPONENTS_TAB, componentSplit);
       
  1329             }
       
  1330 
       
  1331         }
       
  1332 
       
  1333         private void addReflectionTab() {
       
  1334             methodTree = new JTree(compNode.getMethodsModel());
       
  1335             methodTree.setCellRenderer(renderer);
       
  1336             methodTree.setEditable(false);
       
  1337             methodTree.addTreeSelectionListener(selManager);
       
  1338             tbd.add(REFLECTION_TAB, new JScrollPane(methodTree));
       
  1339         }
       
  1340 
       
  1341         private void addPropertiesTab() {
       
  1342             if (compNode instanceof ComponentNode) {
       
  1343                 Hashtable<String, Object> props = ((ContainerNode) compNode).getProperties();
       
  1344                 if (props.size() > 0) {
       
  1345                     JTable propTable = new JTable(new MyModel(props));
       
  1346                     propTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
       
  1347                     tbd.add(PROPERTIES_TAB, new JScrollPane(propTable));
       
  1348                     /*
       
  1349                     propTable.addMouseListener(new MouseListener() {
       
  1350                         public void mouseClicked(MouseEvent e) {
       
  1351                             new ComponentBrowser(getOwnr(),
       
  1352                                     getSelectedNode()).
       
  1353                                     show();
       
  1354                         }
       
  1355                         public void mouseExited(MouseEvent e) {
       
  1356                         }
       
  1357                         public void mouseEntered(MouseEvent e) {
       
  1358                         }
       
  1359                         public void mousePressed(MouseEvent e) {
       
  1360                         }
       
  1361                         public void mouseReleased(MouseEvent e) {
       
  1362                         }
       
  1363                     });
       
  1364                      */
       
  1365                 }
       
  1366             }
       
  1367         }
       
  1368 
       
  1369         private void addEventTab() {
       
  1370             if (compNode instanceof ComponentNode) {
       
  1371                 eventModel = new DefaultListModel<>();
       
  1372                 eventList = new JList<>(eventModel);
       
  1373                 listListener = new ListListener(eventModel, ((ComponentNode) compNode).comp);
       
  1374                 mouseEvents = new JCheckBox("Mouse events");
       
  1375                 mouseEvents.addActionListener(new ActionListener() {
       
  1376                     @Override
       
  1377                     public void actionPerformed(ActionEvent e) {
       
  1378                         if (mouseEvents.isSelected()) {
       
  1379                             listListener.addMouseListener();
       
  1380                         } else {
       
  1381                             listListener.removeMouseListener();
       
  1382                         }
       
  1383                     }
       
  1384                 });
       
  1385                 mouseMotionEvents = new JCheckBox("Mouse motion events");
       
  1386                 mouseMotionEvents.addActionListener(new ActionListener() {
       
  1387                     @Override
       
  1388                     public void actionPerformed(ActionEvent e) {
       
  1389                         if (mouseMotionEvents.isSelected()) {
       
  1390                             listListener.addMouseMotionListener();
       
  1391                         } else {
       
  1392                             listListener.removeMouseMotionListener();
       
  1393                         }
       
  1394                     }
       
  1395                 });
       
  1396                 keyEvents = new JCheckBox("Key events");
       
  1397                 keyEvents.addActionListener(new ActionListener() {
       
  1398                     @Override
       
  1399                     public void actionPerformed(ActionEvent e) {
       
  1400                         if (keyEvents.isSelected()) {
       
  1401                             listListener.addKeyListener();
       
  1402                         } else {
       
  1403                             listListener.removeKeyListener();
       
  1404                         }
       
  1405                     }
       
  1406                 });
       
  1407                 JButton clear = new JButton("Clear list");
       
  1408                 clear.addActionListener(new ActionListener() {
       
  1409                     @Override
       
  1410                     public void actionPerformed(ActionEvent e) {
       
  1411                         eventModel.removeAllElements();
       
  1412                     }
       
  1413                 });
       
  1414                 JPanel checkPane = new JPanel();
       
  1415                 checkPane.add(mouseEvents);
       
  1416                 checkPane.add(mouseMotionEvents);
       
  1417                 checkPane.add(keyEvents);
       
  1418                 checkPane.add(clear);
       
  1419                 JPanel subPane = new JPanel();
       
  1420                 subPane.setLayout(new BorderLayout());
       
  1421                 subPane.add(checkPane, BorderLayout.SOUTH);
       
  1422                 subPane.add(new JScrollPane(eventList), BorderLayout.CENTER);
       
  1423                 tbd.add(EVENT_TAB, subPane);
       
  1424             }
       
  1425         }
       
  1426 
       
  1427         private JFrame getOwnr() {
       
  1428             return this;
       
  1429         }
       
  1430 
       
  1431         private JTree getSelectedTree() {
       
  1432             String title = tbd.getTitleAt(tbd.getSelectedIndex());
       
  1433             if (title.equals(WINDOWS_TAB)) {
       
  1434                 return winTree;
       
  1435             } else if (title.equals(COMPONENTS_TAB)) {
       
  1436                 return componentTree;
       
  1437             } else if (title.equals(REFLECTION_TAB)) {
       
  1438                 return methodTree;
       
  1439             }
       
  1440             return null;
       
  1441         }
       
  1442 
       
  1443         private TreePath getSelectionPath() {
       
  1444             JTree tree = getSelectedTree();
       
  1445             if (tree != null) {
       
  1446                 return tree.getSelectionPath();
       
  1447             } else {
       
  1448                 return null;
       
  1449             }
       
  1450         }
       
  1451 
       
  1452         private ClassNode getSelectedNode() {
       
  1453             TreePath path = getSelectionPath();
       
  1454             if (path != null) {
       
  1455                 return (ClassNode) path.getLastPathComponent();
       
  1456             } else {
       
  1457                 return null;
       
  1458             }
       
  1459         }
       
  1460 
       
  1461     }
       
  1462 
       
  1463     private static class SelectionManager implements TreeSelectionListener, ListSelectionListener {
       
  1464 
       
  1465         Component[] comps;
       
  1466 
       
  1467         public SelectionManager(Component[] comps) {
       
  1468             this.comps = comps;
       
  1469         }
       
  1470 
       
  1471         @Override
       
  1472         public void valueChanged(TreeSelectionEvent e) {
       
  1473             for (Component comp : comps) {
       
  1474                 comp.setEnabled(e.getPath() != null);
       
  1475             }
       
  1476         }
       
  1477 
       
  1478         @Override
       
  1479         public void valueChanged(ListSelectionEvent e) {
       
  1480             for (Component comp : comps) {
       
  1481                 comp.setEnabled(e.getFirstIndex() != -1);
       
  1482             }
       
  1483         }
       
  1484     }
       
  1485 
       
  1486     private void expandAll(JTree tree, TreePath path) {
       
  1487         tree.expandPath(path);
       
  1488         TreeModel model = tree.getModel();
       
  1489         Object lastComponent = path.getLastPathComponent();
       
  1490         for (int i = 0; i < model.getChildCount(lastComponent); i++) {
       
  1491             expandAll(tree,
       
  1492                     path.pathByAddingChild(model.getChild(lastComponent, i)));
       
  1493         }
       
  1494     }
       
  1495 
       
  1496     private static class ToStringListener implements TreeSelectionListener {
       
  1497 
       
  1498         JTextArea area;
       
  1499 
       
  1500         public ToStringListener(JTextArea area) {
       
  1501             this.area = area;
       
  1502         }
       
  1503 
       
  1504         @Override
       
  1505         public void valueChanged(TreeSelectionEvent e) {
       
  1506             if (e.getPath() != null
       
  1507                     && e.getPath().getLastPathComponent() instanceof ComponentNode) {
       
  1508                 area.setText("toString(): "
       
  1509                         + ((ComponentNode) e.getPath().getLastPathComponent()).
       
  1510                         getToString());
       
  1511             } else {
       
  1512                 area.setText("");
       
  1513             }
       
  1514         }
       
  1515     }
       
  1516 
       
  1517     private JSplitPane createUnderPane(JTree tree) {
       
  1518         JTextArea toStringArea = new JTextArea();
       
  1519         toStringArea.setLineWrap(true);
       
  1520         toStringArea.setEditable(false);
       
  1521         tree.addTreeSelectionListener(new ToStringListener(toStringArea));
       
  1522         JSplitPane result = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
       
  1523                 new JScrollPane(tree),
       
  1524                 new JScrollPane(toStringArea));
       
  1525         result.setOneTouchExpandable(true);
       
  1526         result.setDividerSize(8);
       
  1527         result.setDividerLocation(0.8);
       
  1528         return result;
       
  1529     }
       
  1530 
       
  1531     private static class MyModel extends DefaultTableModel {
       
  1532 
       
  1533         private static final long serialVersionUID = 42L;
       
  1534 
       
  1535         @SuppressWarnings(value = "unchecked")
       
  1536         public MyModel(Hashtable<String, Object> props) {
       
  1537             super();
       
  1538             Object[] keys = props.keySet().toArray();
       
  1539             if (keys.length > 0) {
       
  1540                 addColumn("Name");
       
  1541                 addColumn("Value");
       
  1542                 setNumRows(keys.length);
       
  1543                 for (int i = 0; i < keys.length; i++) {
       
  1544                     setValueAt(keys[i].toString(), i, 0);
       
  1545                     setValueAt(props.get(keys[i]).toString(), i, 1);
       
  1546                 }
       
  1547                 Collections.sort((Vector<Vector<?>>) (Vector<?>) getDataVector(), new Comparator<Vector<?>>() {
       
  1548                     @Override
       
  1549                     public int compare(Vector<?> v1, Vector<?> v2) {
       
  1550                         return v1.get(0).toString().compareTo(v2.get(0).toString());
       
  1551                     }
       
  1552                 });
       
  1553             }
       
  1554         }
       
  1555 
       
  1556         @Override
       
  1557         public boolean isCellEditable(int x, int y) {
       
  1558             return false;
       
  1559         }
       
  1560     }
       
  1561 
       
  1562     private static class ListListener extends TrialListenerManager {
       
  1563 
       
  1564         DefaultListModel<AWTEvent> model;
       
  1565 
       
  1566         public ListListener(DefaultListModel<AWTEvent> m, Component comp) {
       
  1567             super(comp);
       
  1568             model = m;
       
  1569         }
       
  1570 
       
  1571         @Override
       
  1572         void printEvent(AWTEvent e) {
       
  1573             model.addElement(e);
       
  1574         }
       
  1575     }
       
  1576 
       
  1577     private static class ImagePane extends JPanel {
       
  1578 
       
  1579         private static final long serialVersionUID = 42L;
       
  1580         BufferedImage image;
       
  1581 
       
  1582         public ImagePane(BufferedImage image) {
       
  1583             super();
       
  1584             this.image = image;
       
  1585             setPreferredSize(new Dimension(image.getWidth(), image.getHeight()));
       
  1586         }
       
  1587 
       
  1588         @Override
       
  1589         public void paint(Graphics g) {
       
  1590             g.drawImage(image, 0, 0, null);
       
  1591         }
       
  1592     }
       
  1593 
       
  1594     private static class ComponentImageProvider {
       
  1595 
       
  1596         BufferedImage image;
       
  1597         int x;
       
  1598         int y;
       
  1599 
       
  1600         public ComponentImageProvider(BufferedImage image, int x, int y) {
       
  1601             this.image = image;
       
  1602             this.x = x;
       
  1603             this.y = y;
       
  1604         }
       
  1605 
       
  1606         public BufferedImage getImage(int x, int y, int w, int h) {
       
  1607             /*
       
  1608             BufferedImage newImage = image.getSubimage(0, 0, image.getWidth(), image.getHeight());
       
  1609             Graphics g = newImage.getGraphics();
       
  1610             g.setColor(Color.RED);
       
  1611             g.drawRect(x - this.x, y - this.y, w, h);
       
  1612             return newImage;
       
  1613              */
       
  1614             int realW = Math.min(image.getWidth() - x, w);
       
  1615             int realH = Math.min(image.getHeight() - y, h);
       
  1616             return image.getSubimage(x - this.x, y - this.y, realW, realH);
       
  1617         }
       
  1618     }
       
  1619 }