001/* 002 * Copyright (c) 2005-2010 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * '$Author: welker $' 006 * '$Date: 2010-05-06 05:21:26 +0000 (Thu, 06 May 2010) $' 007 * '$Revision: 24234 $' 008 * 009 * Permission is hereby granted, without written agreement and without 010 * license or royalty fees, to use, copy, modify, and distribute this 011 * software and its documentation for any purpose, provided that the above 012 * copyright notice and the following two paragraphs appear in all copies 013 * of this software. 014 * 015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 019 * SUCH DAMAGE. 020 * 021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 026 * ENHANCEMENTS, OR MODIFICATIONS. 027 * 028 */ 029 030package org.kepler.sms.gui; 031 032import java.awt.Dimension; 033import java.awt.Frame; 034import java.awt.event.ActionEvent; 035import java.awt.event.ActionListener; 036import java.util.Iterator; 037import java.util.Vector; 038 039import javax.swing.BorderFactory; 040import javax.swing.Box; 041import javax.swing.BoxLayout; 042import javax.swing.JButton; 043import javax.swing.JDialog; 044import javax.swing.JLabel; 045import javax.swing.JPanel; 046import javax.swing.JScrollPane; 047import javax.swing.JTable; 048import javax.swing.JTextField; 049import javax.swing.SwingConstants; 050import javax.swing.event.TableModelEvent; 051import javax.swing.event.TableModelListener; 052import javax.swing.table.AbstractTableModel; 053 054import org.kepler.sms.KeplerCompositeIOPort; 055import org.kepler.sms.KeplerVirtualIOPort; 056import org.kepler.sms.SMSServices; 057 058import ptolemy.actor.IOPort; 059import ptolemy.kernel.Entity; 060 061public class CompositePortDialog extends JDialog { 062 063 private KeplerCompositeIOPort _result = null; 064 065 /** 066 * 067 */ 068 protected KeplerCompositeIOPort getChoice() { 069 // System.out.println(">>> RESULT :="); 070 // System.out.println(_result.exportMoML()); 071 return _result; 072 } 073 074 /** 075 * Note: Only entities may have ports 076 */ 077 public static KeplerCompositeIOPort showDialog(Frame aFrame, Entity entity, 078 int direction) { 079 CompositePortDialog d = new CompositePortDialog(aFrame, entity, 080 direction); 081 return d.getChoice(); 082 } 083 084 /** 085 * 086 */ 087 protected CompositePortDialog(Frame aFrame, Entity entity, int direction) { 088 super(aFrame, true); 089 _direction = direction; 090 091 if (_direction == PortSemanticTypeEditorPane.INPUT) 092 setTitle("Create New Input Composite Port"); 093 else if (_direction == PortSemanticTypeEditorPane.OUTPUT) 094 setTitle("Create New Output Composite Port"); 095 096 _entity = entity; 097 098 JPanel pane = new JPanel(); 099 pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS)); 100 pane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); 101 102 pane.add(_createPortName()); 103 pane.add(Box.createRigidArea(new Dimension(0, 5))); 104 pane.add(_createPortList()); 105 pane.add(Box.createRigidArea(new Dimension(0, 5))); 106 pane.add(_createButtons()); 107 108 _loadPortList(); 109 110 // set up the dialog 111 this.setContentPane(pane); 112 this.setResizable(false); 113 this.setDefaultCloseOperation(DISPOSE_ON_CLOSE); 114 this.pack(); 115 this.show(); 116 } 117 118 /** 119 * 120 */ 121 private JPanel _createPortName() { 122 JPanel pane = new JPanel(); 123 pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS)); 124 125 // name panel 126 JPanel namePane = new JPanel(); 127 namePane.setLayout(new BoxLayout(namePane, BoxLayout.X_AXIS)); 128 pane.add(Box.createRigidArea(new Dimension(10, 0))); 129 if (_direction == PortSemanticTypeEditorPane.INPUT) 130 namePane.add(new JLabel("Composite Input Port Name:", 131 SwingConstants.LEFT)); 132 else if (_direction == PortSemanticTypeEditorPane.OUTPUT) 133 namePane.add(new JLabel("Composite Output Port Name:", 134 SwingConstants.LEFT)); 135 namePane.add(Box.createHorizontalGlue()); 136 pane.add(namePane); 137 138 // add the port name box 139 _txtPortName = new JTextField(); 140 _txtPortName.addActionListener(new ActionListener() { 141 public void actionPerformed(ActionEvent e) { 142 _portNameChanged(); 143 } 144 }); 145 pane.add(_txtPortName); 146 147 return pane; 148 } 149 150 /** 151 * 152 */ 153 private JPanel _createPortList() { 154 JPanel pane = new JPanel(); 155 pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS)); 156 157 // name panel 158 JPanel namePane = new JPanel(); 159 namePane.setLayout(new BoxLayout(namePane, BoxLayout.X_AXIS)); 160 pane.add(Box.createRigidArea(new Dimension(10, 0))); 161 if (_direction == PortSemanticTypeEditorPane.INPUT) 162 namePane.add(new JLabel("Component Input Ports: ", 163 SwingConstants.LEFT)); 164 if (_direction == PortSemanticTypeEditorPane.OUTPUT) 165 namePane.add(new JLabel("Component Output Ports: ", 166 SwingConstants.LEFT)); 167 namePane.add(Box.createHorizontalGlue()); 168 pane.add(namePane); 169 170 // add the port box 171 Vector columns = new Vector(); 172 if (_direction == PortSemanticTypeEditorPane.INPUT) 173 columns.add("Input Port Name"); 174 if (_direction == PortSemanticTypeEditorPane.OUTPUT) 175 columns.add("Output Port Name"); 176 177 columns.add("Include in Composite"); 178 _tblPortList = new JTable(new _PortListTableModel()); 179 _tblPortList.setCellSelectionEnabled(false); 180 _tblPortList.setColumnSelectionAllowed(false); 181 _tblPortList.setRowSelectionAllowed(false); 182 _tblPortList.getModel().addTableModelListener(new TableModelListener() { 183 public void tableChanged(TableModelEvent e) { 184 _portListChanged(); 185 } 186 }); 187 188 JScrollPane scrollPane = new JScrollPane(_tblPortList); 189 scrollPane.setPreferredSize(new Dimension(250, 200)); 190 pane.add(scrollPane); 191 192 return pane; 193 } 194 195 private void _loadPortList() { 196 Vector ports = new Vector(); 197 Iterator iter; 198 if (_direction == PortSemanticTypeEditorPane.INPUT) { 199 // get all the input ports of the entity and a 200 iter = SMSServices.getAllInputPorts(_entity).iterator(); 201 while (iter.hasNext()) 202 ports.add(iter.next()); 203 } else if (_direction == PortSemanticTypeEditorPane.OUTPUT) { 204 iter = SMSServices.getAllOutputPorts(_entity).iterator(); 205 while (iter.hasNext()) 206 ports.add(iter.next()); 207 } 208 iter = ports.iterator(); 209 while (iter.hasNext()) 210 _addRow(iter.next()); 211 212 } 213 214 /** 215 * 216 */ 217 private JPanel _createButtons() { 218 JPanel pane = new JPanel(); 219 pane.setLayout(new BoxLayout(pane, BoxLayout.X_AXIS)); 220 pane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); 221 222 _btnCreate = new JButton("Create"); 223 _btnCancel = new JButton("Cancel"); 224 225 _btnCreate.setEnabled(false); 226 227 pane.add(_btnCreate); 228 pane.add(Box.createRigidArea(new Dimension(15, 0))); 229 pane.add(_btnCancel); 230 231 // add listeners to the buttons 232 _btnCreate.addActionListener(new ActionListener() { 233 public void actionPerformed(ActionEvent ev) { 234 _doCreate(); 235 } 236 }); 237 238 _btnCancel.addActionListener(new ActionListener() { 239 public void actionPerformed(ActionEvent ev) { 240 dispose(); 241 } 242 }); 243 244 return pane; 245 } 246 247 /** 248 * 249 */ 250 private void _portNameChanged() { 251 _checkEnableCreate(); 252 } 253 254 /** 255 * 256 */ 257 private void _portListChanged() { 258 _checkEnableCreate(); 259 } 260 261 /** 262 * 263 */ 264 private void _addRow(Object obj) { 265 _PortListTableModel m = (_PortListTableModel) _tblPortList.getModel(); 266 if (obj instanceof IOPort) { 267 Object[] row = { new _IOPortWrapper((IOPort) obj), Boolean.FALSE }; 268 m.addRow(row); 269 } else { 270 Object[] row = { obj, Boolean.FALSE }; 271 m.addRow(row); 272 } 273 } 274 275 /** 276 * 277 */ 278 private void _clearPortList() { 279 _PortListTableModel m = (_PortListTableModel) _tblPortList.getModel(); 280 m.clearRows(); 281 } 282 283 /** 284 * 285 */ 286 private void _checkEnableCreate() { 287 if (!_validPortName() || !_validSelection()) { 288 _btnCreate.setEnabled(false); 289 return; 290 } 291 _btnCreate.setEnabled(true); 292 } 293 294 /** 295 * 296 */ 297 private boolean _validPortName() { 298 String str = _txtPortName.getText(); 299 if (str == null || str.trim().equals("")) 300 return false; 301 return true; 302 } 303 304 /** 305 * 306 */ 307 private boolean _validSelection() { 308 _PortListTableModel m = (_PortListTableModel) _tblPortList.getModel(); 309 boolean sel = false; 310 for (int i = 0; i < m.getRowCount(); i++) { 311 if (m.rowSelected(i)) 312 sel = true; 313 } 314 if (!sel) 315 return false; 316 return true; 317 } 318 319 /** 320 * 321 */ 322 private void _doCreate() { 323 try { 324 _result = new KeplerCompositeIOPort(_entity, _txtPortName.getText()); 325 _PortListTableModel m = (_PortListTableModel) _tblPortList 326 .getModel(); 327 for (int i = 0; i < m.getRowCount(); i++) { 328 if (m.rowSelected(i)) { 329 Object obj = m.getValueAt(i, 0); 330 if (obj instanceof _IOPortWrapper) { 331 _IOPortWrapper port = (_IOPortWrapper) obj; 332 _result.addEncapsulatedPort(port.getPort()); 333 } else if (obj instanceof KeplerVirtualIOPort) 334 _result.addEncapsulatedPort((KeplerVirtualIOPort) obj); 335 } 336 } 337 dispose(); 338 } catch (Exception e) { 339 e.printStackTrace(); 340 } 341 } 342 343 /** 344 * 345 */ 346 private class _IOPortWrapper { 347 private IOPort _port; 348 349 public _IOPortWrapper(IOPort port) { 350 _port = port; 351 } 352 353 public IOPort getPort() { 354 return _port; 355 } 356 357 public String toString() { 358 if (_port != null) 359 return _port.getName(); 360 else 361 return "''"; 362 } 363 364 }; 365 366 private class _PortListTableModel extends AbstractTableModel { 367 private String[] columnNames = { "Port Name", "Include in Group" }; 368 private Vector data = new Vector(); 369 370 public int getColumnCount() { 371 return columnNames.length; 372 } 373 374 public int getRowCount() { 375 return data.size(); 376 } 377 378 public String getColumnName(int col) { 379 return columnNames[col]; 380 } 381 382 public void addRow(Object[] row) { 383 data.add(row); 384 fireTableRowsInserted(getRowCount(), getRowCount()); 385 } 386 387 public void clearRows() { 388 data = new Vector(); 389 fireTableDataChanged(); 390 } 391 392 public Object getValueAt(int row, int col) { 393 Object[] obj = (Object[]) data.elementAt(row); 394 return obj[col]; 395 } 396 397 /* 398 * JTable uses this method to determine the default renderer/ editor for 399 * each cell. If we didn't implement this method, then the last column 400 * would contain text ("true"/"false"), rather than a check box. 401 */ 402 public Class getColumnClass(int c) { 403 if (getColumnName(c).equals("Port Name")) 404 return Object.class; 405 else if (getColumnName(c).equals("Include in Group")) 406 return Boolean.class; 407 else 408 return Object.class; 409 } 410 411 public void setValueAt(Object value, int row, int col) { 412 Object[] obj = (Object[]) data.elementAt(row); 413 obj[col] = value; 414 fireTableCellUpdated(row, col); 415 } 416 417 public boolean rowSelected(int row) { 418 Object[] obj = (Object[]) data.elementAt(row); 419 Boolean sel = (Boolean) obj[1]; 420 if (sel.equals(Boolean.TRUE)) 421 return true; 422 return false; 423 } 424 425 public boolean isCellEditable(int row, int col) { 426 if (getColumnName(col).equals("Include in Group")) 427 return true; 428 return false; 429 } 430 431 }; 432 433 /** Private members */ 434 private int _direction; // either INPUT or OUTPUT 435 private JTextField _txtPortName; 436 private JTable _tblPortList; 437 private JButton _btnCreate; 438 private JButton _btnCancel; 439 private Entity _entity; 440}