1 /*
   2  * $Id$
   3  *
   4  * Copyright (c) 2002, 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.exec;
  28 
  29 import java.awt.Color;
  30 import java.awt.Dimension;
  31 import java.awt.Font;
  32 import java.awt.GridBagConstraints;
  33 import java.awt.GridBagLayout;
  34 import java.awt.event.ComponentAdapter;
  35 import java.awt.event.ComponentEvent;
  36 import java.awt.event.MouseAdapter;
  37 import java.awt.event.MouseEvent;
  38 import java.util.Arrays;
  39 import java.util.Collection;
  40 import java.util.Comparator;
  41 import javax.swing.BorderFactory;
  42 import javax.swing.JButton;
  43 import javax.swing.JComponent;
  44 import javax.swing.JLabel;
  45 import javax.swing.JPanel;
  46 import javax.swing.JScrollPane;
  47 import javax.swing.JTable;
  48 import javax.swing.JTextArea;
  49 import javax.swing.ListSelectionModel;
  50 import javax.swing.event.ListSelectionEvent;
  51 import javax.swing.event.ListSelectionListener;
  52 import javax.swing.table.AbstractTableModel;
  53 import javax.swing.table.JTableHeader;
  54 
  55 import com.sun.interview.Interview;
  56 import com.sun.interview.Question;
  57 import com.sun.javatest.TestEnvironment;
  58 import com.sun.javatest.InterviewParameters;
  59 import com.sun.javatest.tool.ToolDialog;
  60 import com.sun.javatest.tool.UIFactory;
  61 
  62 class EnvironmentBrowser extends ToolDialog
  63 {
  64 
  65     EnvironmentBrowser(JComponent parent, UIFactory uif) {
  66         super(parent, uif, "env");
  67 
  68         listener = new Listener();
  69 
  70         envTableModel = new ElementsTableModel();
  71     }
  72 
  73     public void show(InterviewParameters params) {
  74         this.params = params;
  75         setVisible(true);
  76     }
  77 
  78     private void setEnv(TestEnvironment env) {
  79         this.env = env;
  80 
  81         if (env == null || env.getName().trim().length() == 0)
  82             setI18NTitle("env.title.unset");
  83         else
  84             setI18NTitle("env.title.name", env.getName());
  85 
  86         envTableModel.setEnvironment(env);
  87     }
  88 
  89     protected void initGUI() {
  90         setHelp("env.window.csh");
  91 
  92         JPanel body = uif.createPanel("env.body", false);
  93         body.setLayout(new GridBagLayout());
  94         body.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
  95 
  96 
  97         table = uif.createTable("env.data", envTableModel);
  98         // make default size small to reduce change of ToolSubPanel scrollbars
  99         table.setPreferredScrollableViewportSize(new Dimension(100, 100));
 100         table.setCellSelectionEnabled(true);
 101         table.getTableHeader().addMouseListener(new MouseAdapter() {
 102             public void mouseClicked(MouseEvent e) {
 103                 Object src = e.getSource();
 104                 if (src instanceof JTableHeader) {
 105                     JTableHeader th = (JTableHeader)src;
 106                     int col = th.columnAtPoint(e.getPoint());
 107                     envTableModel.sort(col);
 108                 }
 109             }
 110         });
 111         table.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
 112         table.getSelectionModel().addListSelectionListener(listener);
 113         table.getColumnModel().getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
 114         table.getColumnModel().getSelectionModel().addListSelectionListener(listener);
 115 
 116         JScrollPane table_sp = uif.createScrollPane(table);
 117         int dpi = uif.getDotsPerInch();
 118         table_sp.setPreferredSize(new Dimension(6 * dpi, 3 * dpi));
 119 
 120         GridBagConstraints c = new GridBagConstraints();
 121         c.gridwidth = GridBagConstraints.REMAINDER;
 122         c.fill = GridBagConstraints.BOTH;
 123         c.insets.bottom = 10;
 124         c.weightx = 1;
 125         c.weighty = 1;
 126         body.add(table_sp, c);
 127 
 128         JLabel lbl = uif.createLabel("env.value", true);
 129         c.insets.bottom = 0;
 130         c.weighty = 0;
 131         body.add(lbl, c);
 132 
 133         text = uif.createTextArea("env.value", lbl);
 134         text.setRows(5);
 135         text.setLineWrap(true);
 136         text.setEditable(false);
 137 
 138         c.weighty = 0.5;
 139         body.add(new JScrollPane(text), c);
 140 
 141         setBody(body);
 142 
 143         JButton helpBtn = uif.createHelpButton("env.help", "env.window.csh");
 144         JButton closeBtn = uif.createCloseButton("env.close");
 145         setButtons(new JButton[] { helpBtn, closeBtn }, closeBtn);
 146 
 147         setComponentListener(listener);
 148     }
 149 
 150     private InterviewParameters params;
 151     private Listener listener;
 152     private TestEnvironment env;
 153     private ElementsTableModel envTableModel;
 154     private JTable table;
 155     private JTextArea text;
 156     static private String[] headings;
 157 
 158     private static final int KEY = 0;
 159     private static final int VALUE = 1;
 160     private static final int DEFINED_IN_FILE = 2;
 161     private static final int DEFINED_IN_ENV = 3;
 162 
 163     private class Listener
 164         extends ComponentAdapter
 165         implements ListSelectionListener, Interview.Observer
 166     {
 167         // ComponentListener
 168         public void componentShown(ComponentEvent e) {
 169             params.addObserver(listener);
 170             updateContent();
 171         }
 172 
 173         public void componentHidden(ComponentEvent e) {
 174             params.removeObserver(listener);
 175         }
 176 
 177         // ListSelectionListener
 178         public void valueChanged(ListSelectionEvent e) {
 179             //System.err.println(e);
 180             int r = table.getSelectedRow();
 181             int c = table.getSelectedColumn();
 182             if (r == -1 || c == -1)
 183                 text.setText("");
 184             else {
 185                 Object o = table.getModel().getValueAt(r, c);
 186                 if (o == null) {
 187                     text.setFont(text.getFont().deriveFont(Font.ITALIC));
 188                     text.setForeground(Color.gray);
 189                     text.setText(uif.getI18NString("env.unset"));
 190                 }
 191                 else {
 192                     text.setFont(text.getFont().deriveFont(Font.PLAIN));
 193                     text.setForeground(table.getForeground());
 194                     text.setText(String.valueOf(o));
 195                 }
 196             }
 197         }
 198 
 199         // Interview.Observer
 200         public void currentQuestionChanged(Question q) {
 201         }
 202 
 203         public void pathUpdated() {
 204             updateContent();
 205         }
 206 
 207         private void updateContent() {
 208             setEnv(params.getEnv());
 209         }
 210     };
 211 
 212     private class EnvEntryComparator implements Comparator<TestEnvironment.Element> {
 213         EnvEntryComparator(int sortMode, String[] inherits) {
 214             this.sortMode = sortMode;
 215             this.inherits = inherits;
 216         }
 217 
 218         public int compare(TestEnvironment.Element e1, TestEnvironment.Element e2) {
 219             // the following should be a switch statement, but JDK
 220             // 1.1.7 can't compile it: doesn't recognize KEY etc as
 221             // constants.
 222             if (sortMode == KEY)
 223                 // key should always be unique, so should be enough to sort on that
 224                 return (e1.getKey().compareTo(e2.getKey()));
 225             else if (sortMode == VALUE) {
 226                 // value probably unique, but if not, sort on key as well
 227                 int c = (e1.getValue().compareTo(e2.getValue()));
 228                 return (c != 0 ? c : e1.getKey().compareTo(e2.getKey()));
 229             }
 230             else if (sortMode == DEFINED_IN_ENV) {
 231                 // defined_in probably not unique, so sort on key as well
 232                 int i1 = getInheritsIndex(e1.getDefinedInEnv());
 233                 int i2 = getInheritsIndex(e2.getDefinedInEnv());
 234                 return (i1 < i2 ? -1 :
 235                         i1 > i2 ? +1 : e1.getKey().compareTo(e2.getKey()));
 236             }
 237             else if (sortMode == DEFINED_IN_FILE) {
 238                 // defined_in probably not unique, so sort on key as well
 239                 int c = (e1.getDefinedInFile().compareTo(e2.getDefinedInFile()));
 240                 return (c != 0 ? c : e1.getKey().compareTo(e2.getKey()));
 241             }
 242             else {
 243                 return 0;
 244             }
 245         }
 246 
 247         private int getInheritsIndex(String s) {
 248             for (int i = 0; i < inherits.length; i++) {
 249                 if (inherits[i].equals(s))
 250                     return i;
 251             }
 252             return inherits.length;
 253         }
 254 
 255         private int sortMode;
 256         private String[] inherits;
 257     }
 258 
 259     private class ElementsTableModel extends AbstractTableModel {
 260         ElementsTableModel() {
 261             if (headings == null) {
 262                 headings = new String[4];
 263                 headings[KEY] = uif.getI18NString("env.head.key");
 264                 headings[VALUE] = uif.getI18NString("env.head.value");
 265                 headings[DEFINED_IN_FILE] = uif.getI18NString("env.head.defInFile");
 266                 headings[DEFINED_IN_ENV] = uif.getI18NString("env.head.defInEnv");
 267             }
 268         }
 269 
 270         public synchronized void setEnvironment(TestEnvironment env) {
 271             int oldRowCount = getRowCount();
 272             currEnv = env;
 273 
 274             if (currEnv == null)
 275                 elems = null;
 276             else {
 277                 Collection<TestEnvironment.Element> e = currEnv.elements();
 278                 elems = e.toArray(new TestEnvironment.Element[e.size()]);
 279                 Arrays.sort(elems, new EnvEntryComparator(KEY, currEnv.getInherits()));
 280             }
 281             int newRowCount = getRowCount();
 282 
 283             int commonRowCount = Math.min(oldRowCount, newRowCount);
 284 
 285             if (commonRowCount > 0) {
 286                 // the rows in common have changed
 287                 fireTableRowsUpdated(0, commonRowCount - 1);
 288             }
 289 
 290             if (newRowCount > oldRowCount) {
 291                 // the new table is bigger: so rows have been added
 292                 fireTableRowsInserted(commonRowCount, newRowCount - 1);
 293             }
 294             else if (newRowCount < oldRowCount) {
 295                 // the new table is smaller, so rows have been removed
 296                 fireTableRowsDeleted(commonRowCount, oldRowCount - 1);
 297             }
 298         }
 299 
 300         public void sort(int columnIndex) {
 301             if (elems != null) {
 302                 Arrays.sort(elems, new EnvEntryComparator(columnIndex, currEnv.getInherits()));
 303                 fireTableRowsUpdated(0, elems.length - 1);
 304             }
 305         }
 306 
 307         private void update() {
 308         }
 309 
 310         public synchronized int getRowCount() {
 311             return (elems == null ? 0 : elems.length);
 312         }
 313 
 314         public int getColumnCount() {
 315             // might be nice to make this more dynamic ...
 316             // have "defined in env" and "defined in file" be dynamic, specified on View menu
 317             return 4; // key, value, defined_in_env, defined_in_file
 318         }
 319 
 320         public String getColumnName(int columnIndex) {
 321             return headings[columnIndex];
 322         }
 323 
 324         public Class<?> getColumnClass(int columnIndex) {
 325             return String.class;
 326         }
 327 
 328         public synchronized Object getValueAt(int rowIndex, int columnIndex) {
 329             if (rowIndex < 0 || rowIndex >= getRowCount()
 330                 || columnIndex < 0 || columnIndex >= getColumnCount())
 331                 throw new IllegalArgumentException();
 332 
 333             TestEnvironment.Element e = elems[rowIndex];
 334             switch (columnIndex) {
 335             case KEY:
 336                 return e.getKey();
 337             case DEFINED_IN_ENV:
 338                 return e.getDefinedInEnv();
 339             case DEFINED_IN_FILE:
 340                 return e.getDefinedInFile();
 341             case VALUE:
 342                 return e.getValue();
 343             default:
 344                 throw new Error();
 345             }
 346         }
 347 
 348         private TestEnvironment.Element[] elems;
 349         private TestEnvironment currEnv;
 350     }
 351 }