001/* A top-level dialog window for displaying the state of an instance. 002 003 Copyright (c) 2006-2014 The Regents of the University of California. 004 All rights reserved. 005 Permission is hereby granted, without written agreement and without 006 license or royalty fees, to use, copy, modify, and distribute this 007 software and its documentation for any purpose, provided that the above 008 copyright notice and the following two paragraphs appear in all copies 009 of this software. 010 011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 015 SUCH DAMAGE. 016 017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 022 ENHANCEMENTS, OR MODIFICATIONS. 023 024 PT_COPYRIGHT_VERSION_2 025 COPYRIGHTENDKEY 026 */ 027package ptolemy.actor.gui; 028 029import java.awt.Color; 030import java.awt.Component; 031import java.awt.Dimension; 032import java.awt.Frame; 033import java.awt.event.KeyAdapter; 034import java.awt.event.KeyEvent; 035import java.net.URL; 036import java.util.ArrayList; 037import java.util.Arrays; 038import java.util.List; 039 040import javax.swing.JLabel; 041import javax.swing.JPanel; 042import javax.swing.JTable; 043import javax.swing.table.AbstractTableModel; 044import javax.swing.table.TableCellRenderer; 045import javax.swing.table.TableColumn; 046 047import ptolemy.kernel.Entity; 048import ptolemy.kernel.util.ChangeListener; 049import ptolemy.kernel.util.ChangeRequest; 050import ptolemy.kernel.util.NamedObj; 051import ptolemy.kernel.util.Settable; 052 053/////////////////////////////////////////////////////////////////// 054//// OpenInstanceDialog 055 056/** 057 This class is a non-modal dialog that displays the current state of 058 parameters of an instance. 059 060 @author Edward A. Lee 061 @version $Id$ 062 @since Ptolemy II 5.2 063 @Pt.ProposedRating Yellow (eal) 064 @Pt.AcceptedRating Red (eal) 065 */ 066@SuppressWarnings("serial") 067public class OpenInstanceDialog extends PtolemyDialog 068 implements ChangeListener { 069 070 /** Construct a dialog that presents the parameters as a table. Each row of the 071 * table corresponds to one parameter. The table shows the expression and its 072 * current evaluated value. 073 * @param tableau The DialogTableau. 074 * @param owner The object that, per the user, appears to be generating the 075 * dialog. 076 * @param target The object whose ports are being configured. 077 * @param configuration The configuration to use to open the help screen 078 * (or null if help is not supported). 079 */ 080 public OpenInstanceDialog(DialogTableau tableau, Frame owner, Entity target, 081 Configuration configuration) { 082 super("Instance: " + target.getFullName(), tableau, owner, target, 083 configuration); 084 085 // Listen for changes that may need to be reflected in the table. 086 // FIXME: Should we just selectively listen to each parameter? 087 getTarget().addChangeListener(this); 088 089 _parameterTable = new JTable(); 090 091 // Initialize which columns will be visible for this target. 092 _initColumnNames(); 093 094 // Create the TableModel and set certain cell editors and renderers 095 _setupTableModel(); 096 097 // The height of the window depends on the number of columns. 098 // FIXME: How to know the height of each row? 16 is a guess. 099 int height = _parameterTableModel.getRowCount() * 16; 100 if (height < 64) { 101 height = 64; 102 } else if (height > 256) { 103 height = 256; 104 } 105 _parameterTable 106 .setPreferredScrollableViewportSize(new Dimension(600, height)); 107 108 // Initialize the displayed column widths. 109 _initColumnSizes(); 110 111 // Make the contents of the table scrollable 112 setScrollableContents(_parameterTable); 113 114 _parameterTable.addKeyListener(new KeyAdapter() { 115 @Override 116 public void keyReleased(KeyEvent event) { 117 int code = event.getKeyCode(); 118 if (code == KeyEvent.VK_ENTER || code == KeyEvent.VK_ESCAPE) { 119 _cancel(); 120 } 121 } 122 }); 123 124 pack(); 125 setVisible(true); 126 } 127 128 /////////////////////////////////////////////////////////////////// 129 //// public methods //// 130 131 /** Update the table. 132 * This is called when a change has been successfully executed. 133 * @param change The change that has been executed. 134 */ 135 @Override 136 public void changeExecuted(ChangeRequest change) { 137 // The ports of the _target may have changed. 138 _setupTableModel(); 139 140 // Given a new renderer, need to do this as well. 141 _initColumnSizes(); 142 } 143 144 /** Do nothing. 145 * This is called when a change has resulted in an exception. 146 * @param change The change that was attempted. 147 * @param exception The exception that resulted. 148 */ 149 @Override 150 public void changeFailed(ChangeRequest change, Exception exception) { 151 } 152 153 /////////////////////////////////////////////////////////////////// 154 //// protected methods //// 155 156 /** Do nothing. This dialog doesn't need additional buttons. 157 */ 158 @Override 159 protected void _createExtendedButtons(JPanel _buttons) { 160 } 161 162 /** Return a URL that points to the help page, which for this 163 * dialog is the expressions documentation. 164 * @return A URL that points to the help page 165 */ 166 @Override 167 protected URL _getHelpURL() { 168 URL doc = getClass().getClassLoader() 169 .getResource("doc/openInstanceHelp.htm"); 170 return doc; 171 } 172 173 /////////////////////////////////////////////////////////////////// 174 //// private methods //// 175 176 /** Initialize which columns will be visible for this target. 177 */ 178 private void _initColumnNames() { 179 String[] temp = { ColumnNames.COL_NAME, ColumnNames.COL_EXPRESSION, 180 ColumnNames.COL_VALUE }; 181 // Store the column names as an ArrayList. 182 List columnList = Arrays.asList(temp); 183 _columnNames = new ArrayList(columnList); 184 } 185 186 /** Initialize the displayed column widths. 187 */ 188 private void _initColumnSizes() { 189 TableColumn column = null; 190 column = _parameterTable.getColumnModel().getColumn(0); 191 column.setPreferredWidth(150); 192 // column.setMaxWidth(300); 193 column = _parameterTable.getColumnModel().getColumn(1); 194 column.setPreferredWidth(300); 195 column = _parameterTable.getColumnModel().getColumn(2); 196 column.setPreferredWidth(300); 197 } 198 199 /** Creates and sets the TableModel. Also arranges for some columns 200 * to have their particular renderers and/or editors. This method 201 * will be invoked when the dialog is created, and every time a 202 * change request from above causes the table to change. 203 */ 204 private void _setupTableModel() { 205 _parameterTableModel = new ParametersTableModel(getTarget()); 206 _parameterTable.setModel(_parameterTableModel); 207 _parameterTable.setDefaultRenderer(String.class, 208 new StringCellRenderer()); 209 } 210 211 /////////////////////////////////////////////////////////////////// 212 //// private variables //// 213 214 /** List of names of columns that will be used for this target. */ 215 private ArrayList _columnNames; 216 217 /** The background color for expert parameters. */ 218 private static Color _EXPERT_COLOR = new Color(1.0f, 0.9f, 0.9f); 219 220 /** The background color for invisible parameters. */ 221 private static Color _INVISIBLE_COLOR = new Color(0.9f, 0.9f, 0.9f); 222 223 /** The target parameter list. */ 224 private List _parameters; 225 226 /** Table of parameters. */ 227 JTable _parameterTable; 228 229 /** The table model. */ 230 ParametersTableModel _parameterTableModel = null; 231 232 /** Strings that are available for the column names. */ 233 private static class ColumnNames { 234 public final static String COL_NAME = "Name"; 235 236 public final static String COL_EXPRESSION = "Expression"; 237 238 public final static String COL_VALUE = "Value"; 239 } 240 241 /////////////////////////////////////////////////////////////////// 242 //// inner classes //// 243 244 /** The table model. 245 */ 246 private class ParametersTableModel extends AbstractTableModel { 247 248 /** Create a table model for the specified target. 249 * @param target The target. 250 */ 251 public ParametersTableModel(NamedObj target) { 252 _parameters = target.attributeList(Settable.class); 253 } 254 255 /** Return the number of columns. 256 * @see javax.swing.table.TableModel#getColumnCount() 257 */ 258 @Override 259 public int getColumnCount() { 260 return _columnNames.size(); 261 } 262 263 /** Return the number of rows. 264 * @see javax.swing.table.TableModel#getRowCount() 265 */ 266 @Override 267 public int getRowCount() { 268 return _parameters.size(); 269 } 270 271 /** Return the column header name. 272 * @see javax.swing.table.TableModel#getColumnName(int) 273 */ 274 @Override 275 public String getColumnName(int col) { 276 return (String) _columnNames.get(col); 277 } 278 279 /** Return the value at a particular row and column. 280 * @param row The row number. 281 * @param col The column number. 282 * @see javax.swing.table.TableModel#getValueAt(int, int) 283 */ 284 @Override 285 public Object getValueAt(int row, int col) { 286 Settable parameter = (Settable) _parameters.get(row); 287 if (ColumnNames.COL_NAME.equals(getColumnName(col))) { 288 return parameter.getDisplayName(); 289 } else if (ColumnNames.COL_EXPRESSION.equals(getColumnName(col))) { 290 return parameter.getExpression(); 291 } else { 292 return parameter.getValueAsString(); 293 } 294 } 295 296 /** Set the value at a particular row and column, which does nothing 297 * because this table is not editable. 298 * @param value The new value. 299 * @param row The row number. 300 * @param col The column number. 301 * @see javax.swing.table.TableModel#setValueAt(Object, int, int) 302 */ 303 @Override 304 public void setValueAt(Object value, int row, int col) { 305 } 306 307 /** Get the Java Class associated with a column param column. 308 * @param col The column number. 309 * @return String.class. 310 * @see javax.swing.table.TableModel#getColumnClass(int) 311 */ 312 @Override 313 public Class getColumnClass(int col) { 314 return String.class; 315 } 316 317 /** Return false. This table is not editable. 318 * @param row The row number. 319 * @param col The column number. 320 * @return False. 321 * @see javax.swing.table.TableModel#isCellEditable(int, int) 322 */ 323 @Override 324 public boolean isCellEditable(int row, int col) { 325 return false; 326 } 327 } 328 329 /** Default renderer for table cells. 330 */ 331 private class StringCellRenderer extends JLabel 332 implements TableCellRenderer { 333 public StringCellRenderer() { 334 super(); 335 } 336 337 @Override 338 public Component getTableCellRendererComponent(JTable table, 339 Object value, boolean isSelected, boolean hasFocus, int row, 340 int col) { 341 setOpaque(true); 342 setText((String) value); 343 // The color depends on the properties of the parameter. 344 Settable parameter = (Settable) _parameters.get(row); 345 if (parameter.getVisibility() == Settable.EXPERT) { 346 setBackground(_EXPERT_COLOR); 347 } else if (parameter.getVisibility() == Settable.NONE) { 348 setBackground(_INVISIBLE_COLOR); 349 } else { 350 setBackground(Color.WHITE); 351 } 352 return this; 353 } 354 } 355}