1 /* 2 * $Id$ 3 * 4 * Copyright (c) 2006, 2016, 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.interview.wizard; 28 29 import java.awt.Component; 30 import java.awt.Dimension; 31 import java.awt.GridBagConstraints; 32 import java.awt.KeyboardFocusManager; 33 import java.awt.event.ActionEvent; 34 import java.awt.event.ActionListener; 35 import java.util.*; 36 37 import javax.accessibility.AccessibleContext; 38 39 import javax.swing.BorderFactory; 40 import javax.swing.Box; 41 import javax.swing.BoxLayout; 42 import javax.swing.JComponent; 43 import javax.swing.JLabel; 44 import javax.swing.JPanel; 45 import javax.swing.JTable; 46 import javax.swing.JTextArea; 47 import javax.swing.table.TableCellRenderer; 48 import javax.swing.table.DefaultTableModel; 49 import javax.swing.table.TableColumn; 50 import javax.swing.table.TableModel; 51 52 import com.sun.interview.PropertiesQuestion; 53 import com.sun.interview.Question; 54 import com.sun.javatest.tool.UIFactory; 55 56 import javax.swing.CellEditor; 57 import javax.swing.event.AncestorEvent; 58 import javax.swing.event.AncestorListener; 59 import javax.swing.table.TableCellEditor; 60 61 62 public class PropertiesQuestionRenderer implements QuestionRenderer { 63 public JComponent getQuestionRendererComponent(Question qq, ActionListener listener) { 64 question = (PropertiesQuestion)qq; 65 66 tables = new HashMap<>(); 67 68 panel = new JPanel(); 69 panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); 70 panel.setName("properties"); 71 panel.setFocusable(false); 72 73 if (question.getValue() == null) { 74 showEmptyQuestion(panel); 75 return panel; 76 } 77 78 // add table(s) 79 addGroup(null, panel, listener); 80 81 // note that empty groups are not returned by the next call 82 String[] groups = question.getGroups(); 83 if (groups != null) 84 for (int i = 0; i < groups.length; i++) { 85 addGroup(groups[i], panel, listener); 86 } // for 87 88 if (panel.getComponentCount() == 0) { 89 showEmptyQuestion(panel); 90 } 91 92 valueSaver = new Runnable() { 93 public void run() { 94 Set<String> keys = tables.keySet(); 95 Iterator<String> iter = keys.iterator(); 96 while(iter.hasNext()) { 97 JTable table = tables.get(iter.next()); 98 CellEditor editor = table.getCellEditor(); 99 if(editor != null) { 100 editor.stopCellEditing(); 101 } 102 } 103 } 104 }; 105 106 panel.putClientProperty(VALUE_SAVER, valueSaver); 107 108 109 // This inserted to handle programmatically fired events 110 // when user click 'X' button in ConfigEditor 111 panel.addAncestorListener(new AncestorListener() { 112 public void ancestorAdded(AncestorEvent e) { 113 114 } 115 public void ancestorMoved(AncestorEvent e) { 116 117 } 118 public void ancestorRemoved(AncestorEvent e) { 119 if (valueSaver != null) { 120 valueSaver.run(); 121 } 122 } 123 }); 124 125 126 return panel; 127 } 128 129 public String getInvalidValueMessage(Question q) { 130 return null; 131 } 132 133 protected void showEmptyQuestion(JPanel panel) { 134 GridBagConstraints gbc = new GridBagConstraints(); 135 gbc.anchor = GridBagConstraints.PAGE_START; 136 gbc.fill = GridBagConstraints.BOTH; 137 gbc.weightx = 2.0; 138 139 // component to hold the message, with lots of 508 adjustments 140 JTextArea txt = new JTextArea(i18n.getString("props.empty.txt")); 141 txt.setOpaque(false); 142 txt.setEditable(false); 143 txt.setLineWrap(true); 144 txt.setWrapStyleWord(true); 145 txt.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, null); 146 txt.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, null); 147 AccessibleContext ac = txt.getAccessibleContext(); 148 ac.setAccessibleName(i18n.getString("props.message.name")); 149 ac.setAccessibleDescription(i18n.getString("props.message.desc")); 150 151 panel.add(txt, gbc); 152 } 153 154 // TABLE BUILDING 155 /** 156 * @param headers Just an optimization right now. 157 */ 158 private void addGroup(String group, JPanel panel, ActionListener listener) { 159 TableModel model = createTableModel(group, listener); 160 // don't show empty tables 161 if (model.getRowCount() == 0) 162 return; 163 164 if (tables.size() == 0) { 165 Component box = Box.createVerticalStrut(20); 166 box.setFocusable(false); 167 panel.add(box); 168 } 169 170 // null group is for ungrouped properties 171 if (group != null) { 172 JLabel label = new JLabel(question.getGroupDisplayName(group)); 173 label.setName(question.getGroupDisplayName(group)); 174 //label.setDisplayedMnemonic(i18n.getString("int.sldr.mne").charAt(0)); 175 //label.setToolTipText(i18n.getString("int.sldr.tip")); 176 panel.add(label); 177 Component box = Box.createVerticalStrut(5); 178 box.setFocusable(false); 179 panel.add(box); 180 } 181 /* 182 else { 183 Component box = Box.createVerticalStrut(1); 184 box.setFocusable(false); 185 panel.add(box, c); 186 } 187 */ 188 189 if (renderer == null || 190 renderer.getQuestion() != question) { 191 renderer = new RenderingUtilities.PropCellRenderer(question); 192 } 193 194 JTable table = createTable(model); 195 table.setBorder(BorderFactory.createEtchedBorder()); 196 table.setRowSelectionAllowed(false); 197 table.setColumnSelectionAllowed(false); 198 table.getTableHeader().setReorderingAllowed(false); 199 table.setBackground(UIFactory.Colors.WINDOW_BACKGROUND.getValue()); 200 201 // setup key column 202 for (int i = 0; i < table.getColumnCount(); i++) { 203 TableColumn tc = table.getColumnModel().getColumn(i); 204 tc.setCellRenderer(getCellRenderer(i)); 205 TableCellEditor editor = getCellEditor(i); 206 if (editor != null) { 207 tc.setCellEditor(editor); 208 } 209 tc.setResizable(true); 210 } 211 212 //panel.add(new JScrollPane(table), c); 213 panel.add(table.getTableHeader()); 214 215 panel.add(table); 216 217 Component box = Box.createVerticalStrut(20); 218 box.setFocusable(false); 219 panel.add(box); 220 221 tables.put(group, table); 222 } 223 224 protected TableCellEditor getCellEditor(int column) { 225 if (column == 1) { 226 return new RenderingUtilities.PCE(question); 227 } 228 else { 229 return null; 230 } 231 } 232 233 protected TableCellRenderer getCellRenderer(int column) { 234 return renderer; 235 } 236 237 protected String[] getTableHeaders() { 238 return new String[] {question.getKeyHeaderName(), 239 question.getValueHeaderName()}; 240 } 241 242 protected TableModel createTableModel(String group, ActionListener l) { 243 return new PropTableModel(getTableHeaders(), group, question, l); 244 } 245 246 protected JTable createTable(TableModel model) { 247 return new PropJTable(model); 248 } 249 250 // UTILITY 251 252 private void fireEditedEvent(Object src, ActionListener l) { 253 ActionEvent e = new ActionEvent(src, 254 ActionEvent.ACTION_PERFORMED, 255 EDITED); 256 l.actionPerformed(e); 257 } 258 259 protected class PropJTable extends JTable { 260 protected PropJTable(TableModel model) { 261 super(model); 262 setIntercellSpacing(new Dimension(4,4)); 263 setRowHeight((int)(getRowHeight() * 1.5)); 264 setFocusable(false); 265 } 266 267 public boolean isCellEditable(int row, int column) { 268 if (column == 0) 269 return false; 270 271 if ( column == 1 && 272 question.isReadOnlyValue(question.getKeyPropertyName((String)getValueAt(row, 0))) ) 273 return false; 274 275 return true; 276 } 277 } 278 279 protected class PropTableModel extends DefaultTableModel { 280 protected PropTableModel(String[] headers, String group, PropertiesQuestion q, 281 ActionListener listener) { 282 super(); 283 this.q = q; 284 editedListener = listener; 285 286 setColumnCount(headers.length); 287 288 String[][] d = q.getGroup(group); 289 290 if (d != null) { 291 ArrayList<String> rm = null; 292 for (int i = 0; i < d.length; i++) { 293 if (!q.isEntryVisible(d[i][0])) { 294 if (rm == null) 295 rm = new ArrayList<>(); 296 else { } 297 rm.add(d[i][0]); 298 } 299 else { 300 // this entry is visible 301 } 302 } // for 303 304 // remove items from d 305 if (rm != null) { 306 String[][] d2 = new String[d.length-rm.size()][2]; 307 int pos = 0; 308 for (int i = 0; i < d.length; i++) { 309 if (rm.contains(d[i][0])) 310 continue; 311 else { 312 d2[pos][0] = d[i][0]; 313 d2[pos][1] = d[i][1]; 314 pos++; 315 } 316 // assert: pos == d2.length 317 } // loop should fill d2.length! 318 319 d = d2; 320 } 321 322 for (int i = 0; i < d.length; i++){ 323 if (q.getPresentationKeys() != null && q.getPresentationKeys().get(d[i][0]) != null){ 324 d[i][0] = q.getPresentationKeys().get(d[i][0]); 325 } 326 } 327 328 setDataVector(d, headers); 329 } 330 331 /* old code which doesn't support invisibility 332 if (d != null) 333 setDataVector(d, headers); 334 */ 335 } 336 337 /* 338 String getColumnName(int column) { 339 if (column > headers.length - 1) 340 return super.getColumnName(); 341 else 342 return headers[column]; 343 } 344 345 String[] headers; 346 */ 347 348 public void setValueAt(Object o, int row, int col) { 349 if (col == 1) { 350 String key = q.getKeyPropertyName((String)(getValueAt(row, 0))); 351 352 q.updateProperty(key, (String)o); 353 fireEditedEvent(this, editedListener); 354 fireTableCellUpdated(row, 0); 355 fireTableCellUpdated(row, 1); 356 o = q.getValue().get(key); 357 } 358 359 super.setValueAt(o, row, col); 360 } 361 362 protected PropertiesQuestion q; 363 protected ActionListener editedListener; 364 } 365 366 protected Runnable valueSaver; 367 protected Map<String, JTable> tables; 368 protected RenderingUtilities.PropCellRenderer renderer; 369 protected PropertiesQuestion question; 370 protected JPanel panel; 371 372 private static final I18NResourceBundle i18n = I18NResourceBundle.getDefaultBundle(); 373 }