001/* A pane to configure an execution choice actor.
002 * 
003 * Copyright (c) 2012 The Regents of the University of California.
004 * All rights reserved.
005 *
006 * '$Author: crawl $'
007 * '$Date: 2013-07-19 00:06:40 +0000 (Fri, 19 Jul 2013) $' 
008 * '$Revision: 32229 $'
009 * 
010 * Permission is hereby granted, without written agreement and without
011 * license or royalty fees, to use, copy, modify, and distribute this
012 * software and its documentation for any purpose, provided that the above
013 * copyright notice and the following two paragraphs appear in all copies
014 * of this software.
015 *
016 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
017 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
018 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
019 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
020 * SUCH DAMAGE.
021 *
022 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
023 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
024 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
025 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
026 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
027 * ENHANCEMENTS, OR MODIFICATIONS.
028 *
029 */
030package org.kepler.ddp.gui;
031
032import java.awt.Color;
033import java.awt.Component;
034import java.util.ArrayList;
035import java.util.Arrays;
036import java.util.Hashtable;
037import java.util.List;
038
039import javax.swing.JPanel;
040import javax.swing.JTabbedPane;
041import javax.swing.SwingConstants;
042
043import org.kepler.ddp.actor.ExecutionChoice;
044
045import ptolemy.actor.gui.EditorPaneFactory;
046import ptolemy.actor.gui.PtolemyQuery;
047import ptolemy.actor.lib.hoc.Refinement;
048import ptolemy.data.expr.Parameter;
049import ptolemy.data.expr.StringParameter;
050import ptolemy.gui.Query;
051import ptolemy.kernel.util.Attribute;
052import ptolemy.kernel.util.IllegalActionException;
053import ptolemy.kernel.util.NameDuplicationException;
054import ptolemy.kernel.util.NamedObj;
055import ptolemy.kernel.util.Settable;
056import ptolemy.util.MessageHandler;
057import ptolemy.vergil.basic.KeplerDocumentationAttribute;
058
059/** A pane to configure an execution choice actor.
060 * 
061 *  @author Daniel Crawl
062 *  @version $Id: ExecutionChoiceEditorPane.java 32229 2013-07-19 00:06:40Z crawl $
063 */
064public class ExecutionChoiceEditorPane extends JPanel {
065
066    public ExecutionChoiceEditorPane(ExecutionChoice choice) {
067        
068        try {
069            
070                KeplerDocumentationAttribute docAttribute = null;
071                List<KeplerDocumentationAttribute> docList = choice.attributeList(KeplerDocumentationAttribute.class);
072                if(!docList.isEmpty()) {
073                        docAttribute = docList.get(0);
074                        // see if docAttribute has been initialized
075                        Hashtable<?,?> hashTable = docAttribute.getPortHash();
076                        if(hashTable.isEmpty()) {
077                                docAttribute.createInstanceFromExisting(docAttribute);
078                        }
079                }
080                
081            PtolemyQuery query = new PtolemyQuery(choice);
082            
083            // add program and arguments
084            query.addSeparator();
085            query.addStyledEntry(choice.program);
086    
087            // add inputs
088            query.addSeparator();
089            query.addText("Input File Parameters", Color.BLACK, SwingConstants.LEFT);
090            List<String> names = choice.getInputNames(false);
091            if(names.isEmpty()) {
092                query.addText("None", Color.BLACK, SwingConstants.LEFT);
093            } else {
094                for(String name : names) {
095                        
096                        _addDocumentation(name, query, docAttribute);
097                        
098                    StringParameter parameter = (StringParameter) choice.getAttribute(name);
099                    String argument = choice.getArgument(name);
100                    if(argument != null && !argument.trim().isEmpty()) {
101                        query.addTextArea(name,
102                                name + " (" + argument + ")",
103                                parameter.getExpression(),
104                                PtolemyQuery.preferredBackgroundColor(parameter),
105                                PtolemyQuery.preferredForegroundColor(parameter),
106                                1, Query.DEFAULT_ENTRY_WIDTH);
107                        query.attachParameter(parameter, name);
108                    } else {
109                        query.addStyledEntry(parameter);
110                    }
111                    
112                }
113            }
114    
115            // add outputs
116            query.addSeparator();
117            query.addText("Output File Parameters", Color.BLACK, SwingConstants.LEFT);
118            query.addStyledEntry(choice.checkOutputTimestamp);
119            names = choice.getOutputNames(false);
120            if(names.isEmpty()) {
121                query.addText("None", Color.BLACK, SwingConstants.LEFT);
122            } else {
123                for(String name : names) {
124
125                        boolean addedDocs = _addDocumentation(name, query, docAttribute);
126
127                    StringParameter parameter = (StringParameter) choice.getAttribute(name);
128                    String argument = choice.getArgument(name);
129                    if(argument != null && !argument.trim().isEmpty()) {
130                        query.addTextArea(name,
131                                name + " (" + argument + ")",
132                                parameter.getExpression(),
133                                PtolemyQuery.preferredBackgroundColor(parameter),
134                                PtolemyQuery.preferredForegroundColor(parameter),
135                                1, Query.DEFAULT_ENTRY_WIDTH);
136                        query.attachParameter(parameter, name);
137                    } else {
138                        query.addStyledEntry(parameter);
139                    }
140                    
141                    if(addedDocs) {
142                        //query.addText("", Color.BLACK, SwingConstants.LEFT);
143                        //query.addText("", Color.BLACK, SwingConstants.LEFT);
144                    }
145                }
146            }
147            
148            // add additional parameters
149            query.addSeparator();
150            query.addText("Parameters", Color.BLACK, SwingConstants.LEFT);
151    
152            // add additional parameters
153            query.addStyledEntry(choice.additionalOptions);
154            
155            final List<String> parameterNames = choice.getParameterNames();        
156            final String[] namesArray = parameterNames.toArray(new String[parameterNames.size()]);
157            Arrays.sort(namesArray);
158            for(String name : namesArray) {
159                
160                _addDocumentation(name, query, docAttribute);
161
162                Parameter parameter = (Parameter) choice.getAttribute(name);
163                String argument = choice.getArgument(name);
164                if(argument != null && !argument.trim().isEmpty()) {
165                    query.addTextArea(name,
166                            name + " (" + argument + ")",
167                            parameter.getExpression(),
168                            PtolemyQuery.preferredBackgroundColor(parameter),
169                            PtolemyQuery.preferredForegroundColor(parameter),
170                            1, Query.DEFAULT_ENTRY_WIDTH);
171                    query.attachParameter(parameter, name);
172                } else {
173                    query.addStyledEntry(parameter);
174                }
175            }
176                    
177            // add execution choice combo box
178            query.addSeparator();
179            
180            // make sure at least one choice has been loaded
181            /*
182            if(choice.entityList(Refinement.class).isEmpty()) {
183                try {
184                    choice.newExecutionChoice(ExecutionChoice.DEFAULT_TEMPLATE_NAME,
185                        ExecutionChoice.DEFAULT_TEMPLATE_NAME);
186                } catch (IllegalActionException e) {
187                    MessageHandler.error("Error adding default execution choice.", e);
188                }
189            }
190            */
191            
192            choice.updateExecutionChoices();
193            _addDocumentation(choice.control.getName(), query, docAttribute);
194            query.addStyledEntry(choice.control);
195    
196                    
197            JTabbedPane tabbedPane = new JTabbedPane();        
198            tabbedPane.addTab("Shared Options", query);
199            
200            _addTabsForRefinements(tabbedPane, choice);
201            
202            add(tabbedPane);
203            
204        } catch(IllegalActionException e) {
205            MessageHandler.error("Error creating pane.", e);
206        }
207    }
208    
209    /** Add documentation to the configuration dialog for a specific field. 
210     *  @param name the name of the field
211     *  @param query the configuration dialog
212     *  @param docAttribute the attribute containing the port and parameter documentation 
213     *  @return True if the documentation for the field is found and non-empty, otherwise false.
214     */
215    private boolean _addDocumentation(String name, Query query, KeplerDocumentationAttribute docAttribute) {
216        boolean retval = false;
217        
218        /* turned off until can do better alignment
219        if(docAttribute != null) {
220                String docText = docAttribute.getProperty(name);
221                if(docText != null && !docText.trim().isEmpty()) {
222                        query.addText(docText, Color.BLACK, SwingConstants.LEFT);
223                        //query.addTextArea(name + "docs", docText, "", Color.BLACK, Color.BLACK, -1, -1);
224                        
225                        //query.addText("", Color.BLACK, SwingConstants.LEFT);
226                        //query.addText("", Color.BLACK, SwingConstants.LEFT);
227                        retval = true;
228                }
229        }
230        */
231        
232        return retval;
233        }
234
235        /** Add a tab for each refinement. */
236    private void _addTabsForRefinements(JTabbedPane tabbedPane, ExecutionChoice choice) {
237        
238        for(String refinementName : choice.getExecutionChoiceNames()) {
239            
240            Refinement refinement = (Refinement) choice.getEntity(refinementName);
241            final PtolemyQuery query = new PtolemyQuery(refinement);
242            
243            // get all the parameter names in this refinement
244            final ArrayList<String> names = new ArrayList<String>();
245            for(Parameter parameter : refinement.attributeList(Parameter.class)) {
246                final String parameterName = parameter.getName();
247                if(!parameterName.startsWith("_")) {
248                    names.add(parameterName);
249                    Attribute attribute = parameter.getAttribute("class");
250                    if(attribute != null && (attribute instanceof Settable)) {
251                        ((Settable)attribute).setVisibility(Settable.NONE);
252                    }
253                }
254            }
255            
256            // see if there are any parameters
257            if(names.isEmpty()) {
258                query.addText("No Parameters", Color.BLACK, SwingConstants.LEFT);
259            } else {
260                // sort names alphabetically and add to query
261                final String[] namesArray = names.toArray(new String[names.size()]);
262                Arrays.sort(namesArray);
263                for(String parameterName : namesArray) {
264                    
265                    try {
266                        Settable parameter = (Settable) refinement.getAttribute(parameterName);
267                        String argument = choice.getArgument(refinement, parameterName);
268                        if(argument != null) {
269                            query.addTextArea(parameterName,
270                                    parameterName + " (" + argument + ")",
271                                    parameter.getExpression(),
272                                    PtolemyQuery.preferredBackgroundColor(parameter),
273                                    PtolemyQuery.preferredForegroundColor(parameter),
274                                    1, Query.DEFAULT_ENTRY_WIDTH);
275                            query.attachParameter(parameter, parameterName);
276                        } else {
277                            query.addStyledEntry(parameter);
278                        }
279                    } catch(IllegalActionException e) {
280                        MessageHandler.error("Error accessing argument for " +
281                                parameterName + " in " + refinementName, e);
282                    }
283                }
284            }
285                        
286            // add query to tab
287            tabbedPane.addTab(refinement.getDisplayName(), query);
288        }
289    }
290    
291    /** An editor pane factory for execution choice. */
292    public static class Factory extends EditorPaneFactory {
293
294        public Factory(NamedObj container, String name)
295                throws IllegalActionException, NameDuplicationException {
296            super(container, name);
297            if(container instanceof ExecutionChoice) {
298                _target = (ExecutionChoice)container;
299            }
300        }
301        
302        @Override
303        public Component createEditorPane() {
304            if(_target!= null) {
305                return new ExecutionChoiceEditorPane(_target);
306            }
307            return null;
308        }
309        
310        private ExecutionChoice _target;
311    }
312}