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 {
 213         EnvEntryComparator(int sortMode, String[] inherits) {
 214             this.sortMode = sortMode;
 215             this.inherits = inherits;
 216         }
 217 
 218         public int compare(Object o1, Object o2) {
 219             TestEnvironment.Element e1 = (TestEnvironment.Element)o1;
 220             TestEnvironment.Element e2 = (TestEnvironment.Element)o2;
 221             // the following should be a switch statement, but JDK
 222             // 1.1.7 can't compile it: doesn't recognize KEY etc as
 223             // constants.
 224             if (sortMode == KEY)
 225                 // key should always be unique, so should be enough to sort on that
 226                 return (e1.getKey().compareTo(e2.getKey()));
 227             else if (sortMode == VALUE) {
 228                 // value probably unique, but if not, sort on key as well
 229                 int c = (e1.getValue().compareTo(e2.getValue()));
 230                 return (c != 0 ? c : e1.getKey().compareTo(e2.getKey()));
 231             }
 232             else if (sortMode == DEFINED_IN_ENV) {
 233                 // defined_in probably not unique, so sort on key as well
 234                 int i1 = getInheritsIndex(e1.getDefinedInEnv());
 235                 int i2 = getInheritsIndex(e2.getDefinedInEnv());
 236                 return (i1 < i2 ? -1 :
 237                         i1 > i2 ? +1 : e1.getKey().compareTo(e2.getKey()));
 238             }
 239             else if (sortMode == DEFINED_IN_FILE) {
 240                 // defined_in probably not unique, so sort on key as well
 241                 int c = (e1.getDefinedInFile().compareTo(e2.getDefinedInFile()));
 242                 return (c != 0 ? c : e1.getKey().compareTo(e2.getKey()));
 243             }
 244             else {
 245                 return 0;
 246             }
 247         }
 248 
 249         private int getInheritsIndex(String s) {
 250             for (int i = 0; i < inherits.length; i++) {
 251                 if (inherits[i].equals(s))
 252                     return i;
 253             }
 254             return inherits.length;
 255         }
 256 
 257         private int sortMode;
 258         private String[] inherits;
 259     }
 260 
 261     private class ElementsTableModel extends AbstractTableModel {
 262         ElementsTableModel() {
 263             if (headings == null) {
 264                 headings = new String[4];
 265                 headings[KEY] = uif.getI18NString("env.head.key");
 266                 headings[VALUE] = uif.getI18NString("env.head.value");
 267                 headings[DEFINED_IN_FILE] = uif.getI18NString("env.head.defInFile");
 268                 headings[DEFINED_IN_ENV] = uif.getI18NString("env.head.defInEnv");
 269             }
 270         }
 271 
 272         public synchronized void setEnvironment(TestEnvironment env) {
 273             int oldRowCount = getRowCount();
 274             currEnv = env;
 275 
 276             if (currEnv == null)
 277                 elems = null;
 278             else {
 279                 Collection e = currEnv.elements();
 280                 elems = (TestEnvironment.Element[]) (e.toArray(new TestEnvironment.Element[e.size()]));
 281                 Arrays.sort(elems, new EnvEntryComparator(KEY, currEnv.getInherits()));
 282             }
 283             int newRowCount = getRowCount();
 284 
 285             int commonRowCount = Math.min(oldRowCount, newRowCount);
 286 
 287             if (commonRowCount > 0) {
 288                 // the rows in common have changed
 289                 fireTableRowsUpdated(0, commonRowCount - 1);
 290             }
 291 
 292             if (newRowCount > oldRowCount) {
 293                 // the new table is bigger: so rows have been added
 294                 fireTableRowsInserted(commonRowCount, newRowCount - 1);
 295             }
 296             else if (newRowCount < oldRowCount) {
 297                 // the new table is smaller, so rows have been removed
 298                 fireTableRowsDeleted(commonRowCount, oldRowCount - 1);
 299             }
 300         }
 301 
 302         public void sort(int columnIndex) {
 303             if (elems != null) {
 304                 Arrays.sort(elems, new EnvEntryComparator(columnIndex, currEnv.getInherits()));
 305                 fireTableRowsUpdated(0, elems.length - 1);
 306             }
 307         }
 308 
 309         private void update() {
 310         }
 311 
 312         public synchronized int getRowCount() {
 313             return (elems == null ? 0 : elems.length);
 314         }
 315 
 316         public int getColumnCount() {
 317             // might be nice to make this more dynamic ...
 318             // have "defined in env" and "defined in file" be dynamic, specified on View menu
 319             return 4; // key, value, defined_in_env, defined_in_file
 320         }
 321 
 322         public String getColumnName(int columnIndex) {
 323             return headings[columnIndex];
 324         }
 325 
 326         public Class getColumnClass(int columnIndex) {
 327             return String.class;
 328         }
 329 
 330         public synchronized Object getValueAt(int rowIndex, int columnIndex) {
 331             if (rowIndex < 0 || rowIndex >= getRowCount()
 332                 || columnIndex < 0 || columnIndex >= getColumnCount())
 333                 throw new IllegalArgumentException();
 334 
 335             TestEnvironment.Element e = elems[rowIndex];
 336             switch (columnIndex) {
 337             case KEY:
 338                 return e.getKey();
 339             case DEFINED_IN_ENV:
 340                 return e.getDefinedInEnv();
 341             case DEFINED_IN_FILE:
 342                 return e.getDefinedInFile();
 343             case VALUE:
 344                 return e.getValue();
 345             default:
 346                 throw new Error();
 347             }
 348         }
 349 
 350         private TestEnvironment.Element[] elems;
 351         private TestEnvironment currEnv;
 352     }
 353 }