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}