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 }