001/* An editor factory for execution choice. 002 * 003 * Copyright (c) 2012 The Regents of the University of California. 004 * All rights reserved. 005 * 006 * '$Author: crawl $' 007 * '$Date: 2015-09-04 20:53:26 +0000 (Fri, 04 Sep 2015) $' 008 * '$Revision: 33870 $' 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.Frame; 034import java.awt.GridBagConstraints; 035import java.awt.GridBagLayout; 036import java.awt.event.ActionEvent; 037import java.awt.event.ActionListener; 038import java.io.File; 039import java.util.Arrays; 040import java.util.HashMap; 041import java.util.HashSet; 042import java.util.LinkedList; 043import java.util.List; 044import java.util.Map; 045import java.util.Set; 046 047import javax.swing.ButtonGroup; 048import javax.swing.JComboBox; 049import javax.swing.JFileChooser; 050import javax.swing.JLabel; 051import javax.swing.JPanel; 052import javax.swing.JRadioButton; 053import javax.swing.JTabbedPane; 054import javax.swing.JTextField; 055import javax.swing.SwingConstants; 056 057import org.apache.commons.io.FilenameUtils; 058import org.kepler.ddp.actor.ExecutionChoice; 059import org.kepler.gui.KeplerGraphFrame; 060import org.kepler.gui.ModelToFrameManager; 061import org.kepler.gui.frame.TabbedKeplerGraphFrame; 062 063import ptolemy.actor.TypedIOPort; 064import ptolemy.actor.gui.Configurer; 065import ptolemy.actor.gui.EditorFactory; 066import ptolemy.actor.lib.hoc.Refinement; 067import ptolemy.data.expr.Parameter; 068import ptolemy.gui.ComponentDialog; 069import ptolemy.gui.ExtensionFilenameFilter; 070import ptolemy.gui.JFileChooserBugFix; 071import ptolemy.gui.PtFileChooser; 072import ptolemy.gui.PtGUIUtilities; 073import ptolemy.gui.Query; 074import ptolemy.kernel.ComponentEntity; 075import ptolemy.kernel.CompositeEntity; 076import ptolemy.kernel.Port; 077import ptolemy.kernel.util.Attribute; 078import ptolemy.kernel.util.IllegalActionException; 079import ptolemy.kernel.util.NameDuplicationException; 080import ptolemy.kernel.util.NamedObj; 081import ptolemy.moml.MoMLChangeRequest; 082import ptolemy.util.MessageHandler; 083 084/** An editor factory to create an editor for ExecutionChoice. An 085 * ExecutioChoiceEditorPane is used to configure the actor. This 086 * class handles button presses and can display panes for adding, 087 * removing, and renaming components, and exporting the execution 088 * choices. 089 * 090 * @author Daniel Crawl 091 * @version $Id: ExecutionChoiceEditorFactory.java 33870 2015-09-04 20:53:26Z crawl $ 092 */ 093public class ExecutionChoiceEditorFactory extends EditorFactory { 094 095 public ExecutionChoiceEditorFactory(NamedObj container, String name) 096 throws IllegalActionException, NameDuplicationException { 097 super(container, name); 098 } 099 100 @Override 101 public void createEditor(NamedObj object, Frame parent) { 102 103 if(!(object instanceof ExecutionChoice)) { 104 MessageHandler.error("Object to edit must be ExecutionChoice."); 105 return; 106 } 107 108 ExecutionChoice choice = (ExecutionChoice)object; 109 110 try { 111 choice.addDefaults(); 112 } catch (Exception e) { 113 MessageHandler.error("Error adding default input/outputs.", e); 114 } 115 116 boolean done = false; 117 118 Set<String> addedInputs = new HashSet<String>(); 119 Set<String> addedOutputs = new HashSet<String>(); 120 Set<String> addedParameters = new HashSet<String>(); 121 Set<String> addedChoices = new HashSet<String>(); 122 123 // a set of Configure objects for the execution choice actor and 124 // each sub-workflow. if the user hits Cancel, escape, or the 125 // close window button (top-left or top-right of dialog), the 126 // Configure objects are used to restore the parameter values in 127 // the actor and for each sub-workflow. 128 Set<Configurer> configurers = new HashSet<Configurer>(); 129 130 while(!done) { 131 final Configurer actorConfigurer = new Configurer(object); 132 133 configurers.clear(); 134 configurers.add(actorConfigurer); 135 136 for(Refinement refinement : choice.entityList(Refinement.class)) { 137 configurers.add(new Configurer(refinement)); 138 } 139 140 final ComponentDialog dialog = new ComponentDialog(parent, 141 object.getFullName(), 142 actorConfigurer, 143 new String[] {"Commit", "Types", "Rename", "Remove", 144 "Import", "Export", "Arguments", "Add", "Cancel"}); 145 final String buttonPressed = dialog.buttonPressed(); 146 147 // if user pushed escape button, buttonPressed is empty. 148 if(buttonPressed.equals("Commit")) { 149 done = true; 150 } else if(buttonPressed.equals("Cancel") || buttonPressed.isEmpty()) { 151 152 // NOTE: Cancel only restores parameter values. 153 154 for(Configurer configurer : configurers) { 155 configurer.restore(); 156 } 157 158 // remove all added items 159 /* 160 for(String addedInput : addedInputs) { 161 try { 162 choice.removeInput(addedInput); 163 } catch (Exception e) { 164 MessageHandler.error("Error removing input " + addedInput, e); 165 } 166 } 167 for(String addedOutput : addedOutputs) { 168 try { 169 choice.removeOutput(addedOutput); 170 } catch (Exception e) { 171 MessageHandler.error("Error removing output " + addedOutput, e); 172 } 173 } 174 for(String addedParameter : addedParameters) { 175 try { 176 // FIXME parameter may have been added to refinement 177 choice.removeParameter(addedParameter); 178 } catch (Exception e) { 179 MessageHandler.error("Error removing parameter " + addedParameter, e); 180 } 181 } 182 for(String addedChoice : addedChoices) { 183 try { 184 choice.removeExecutionChoice(addedChoice); 185 } catch (Exception e) { 186 MessageHandler.error("Error removing execution choice " + addedChoice, e); 187 } 188 } 189 */ 190 191 // TODO restore all removed items 192 193 // TODO restore all renamed items 194 195 // TODO restore all argument changes 196 197 // TODO remove parameters add to refinements 198 199 // TODO restore parameters removed from refinements 200 201 // TODO restore parameters renamed in refinements 202 203 // repaint canvas to remove any added ports 204 //_repaintCanvas(choice); 205 206 done = true; 207 208 } else if(buttonPressed.equals("Add")) { 209 boolean doneAdding = false; 210 String addStr = null; 211 String newName = null; 212 String typeStr = null; 213 String argumentStr = null; 214 String choiceStr = null; 215 while(!doneAdding) { 216 final AddPane addPane = new AddPane(choice); 217 addPane.setAdd(addStr); 218 addPane.setTextName(newName); 219 addPane.setType(typeStr); 220 addPane.setArgument(argumentStr); 221 addPane.setChoice(choiceStr); 222 final ComponentDialog addDialog = new ComponentDialog(parent, 223 buttonPressed, addPane, 224 new String[] {"Add", "Add & Continue", "Cancel"}); 225 String pressed = addDialog.buttonPressed(); 226 if(pressed.equals("Add") || pressed.equals("Add & Continue")) { 227 try { 228 addStr = addPane.getAdd(); 229 newName = addPane.getTextName(); 230 typeStr = addPane.getType(); 231 argumentStr = addPane.getArgument(); 232 choiceStr = addPane.getChoice(); 233 234 boolean chooseNewName = false; 235 236 if(newName.isEmpty()) { 237 MessageHandler.error("Please specify a name."); 238 } else { 239 if(addStr.equals("Input")) { 240 if(choice.getInputNames(true).contains(newName)) { 241 chooseNewName = true; 242 } else { 243 choice.newInput(newName, 244 ExecutionChoice.IOType.valueOf(typeStr), 245 argumentStr); 246 addedInputs.add(newName); 247 } 248 } else if(addStr.equals("Output")) { 249 if(choice.getOutputNames(true).contains(newName)) { 250 chooseNewName = true; 251 } else { 252 choice.newOutput(newName, 253 ExecutionChoice.IOType.valueOf(typeStr), 254 argumentStr); 255 addedOutputs.add(newName); 256 } 257 } else if(addStr.equals("Parameter")) { 258 // use getAttribute() instead of getParameterNames() 259 // since the latter does not include all the parameters 260 if(choice.getAttribute(newName) != null) { 261 chooseNewName = true; 262 } else { 263 choice.newParameter(newName, argumentStr, null, choiceStr, 264 ExecutionChoice.ParameterType.valueOf(typeStr)); 265 addedParameters.add(newName); 266 } 267 } else if(addStr.equals("Execution Choice")) { 268 if(choice.getEntity(newName) != null) { 269 chooseNewName = true; 270 } else { 271 choice.newExecutionChoice(typeStr, newName); 272 addedChoices.add(newName); 273 274 // if the choices are open in a frame, add a new tab for the new choice 275 KeplerGraphFrame frame = ModelToFrameManager.getInstance().getFrame(choice); 276 if(frame != null && (frame instanceof TabbedKeplerGraphFrame)) { 277 ((TabbedKeplerGraphFrame)frame). 278 addSubComposite((CompositeEntity)choice.getEntity(newName)); 279 } 280 } 281 } 282 283 if(chooseNewName) { 284 MessageHandler.error(addStr + " " + newName + 285 " is already used. Please choose a different name."); 286 } else { 287 // execute an empty change request so that the new port 288 // appears (if we added a new port) 289 _repaintCanvas(choice); 290 291 if(pressed.equals("Add")) { 292 doneAdding = true; 293 } 294 } 295 } 296 } catch(IllegalActionException e) { 297 MessageHandler.error("Error", e); 298 } catch(NameDuplicationException e) { 299 MessageHandler.error(addPane.getTextName() + 300 " already exists. Please choose a different name.", e); 301 } 302 } else if(addDialog.buttonPressed().equals("Cancel") || 303 addDialog.buttonPressed().isEmpty()) { 304 doneAdding = true; 305 } 306 } 307 } else if(buttonPressed.equals("Rename")) { 308 try { 309 boolean doneRenaming = false; 310 while(!doneRenaming) { 311 RenamePane renamePane; 312 try { 313 renamePane = new RenamePane(choice); 314 } catch (IllegalActionException e) { 315 MessageHandler.error("Error creating Rename dialog.", e); 316 break; 317 } 318 final ComponentDialog renameDialog = new ComponentDialog(parent, 319 buttonPressed, renamePane); 320 if(renameDialog.buttonPressed().equals("OK")) { 321 Set<RenameInfo> renames = renamePane.getRenames(); 322 323 // first check all the renames to make sure that 324 // there are no name conflicts. 325 String newName = null; 326 String type = null; 327 NamedObj container = null; 328 boolean chooseNewName = false; 329 for(RenameInfo rename : renames) { 330 type = rename._type; 331 newName = rename._newName; 332 container = rename._container; 333 if(type.equals("Execution Choice")) { 334 if(choice.getEntity(newName) != null) { 335 chooseNewName = true; 336 break; 337 } 338 } else if(type.equals("Input")) { 339 // TODO what if output name exists? 340 if(choice.getInputNames(true).contains(newName)) { 341 chooseNewName = true; 342 break; 343 } 344 } else if(type.equals("Output")) { 345 if(choice.getOutputNames(true).contains(newName)) { 346 chooseNewName = true; 347 break; 348 } 349 } else if(type.equals("Parameter")) { 350 if(container.getAttribute(newName) != null) { 351 chooseNewName = true; 352 break; 353 } 354 } 355 } 356 357 if(chooseNewName) { 358 MessageHandler.error(type + " " + newName + 359 " is already used. Please choose a different name."); 360 } else { 361 362 // perform each rename 363 for(RenameInfo renameInfo : renamePane.getRenames()) { 364 //try { 365 if(renameInfo._type.equals("Execution Choice")) { 366 choice.renameExecutionChoice(renameInfo._oldName, 367 renameInfo._newName); 368 369 // if the choices are open in a frame, remove the tab for the choice 370 // that was removed. 371 KeplerGraphFrame frame = ModelToFrameManager.getInstance().getFrame(choice); 372 if(frame != null && (frame instanceof TabbedKeplerGraphFrame)) { 373 ((TabbedKeplerGraphFrame)frame).updateTabsForComposite(choice); 374 } 375 376 } else if(renameInfo._type.equals("Input")) { 377 choice.renameInput(renameInfo._oldName, 378 renameInfo._newName); 379 } else if(renameInfo._type.equals("Output")) { 380 choice.renameOutput(renameInfo._oldName, 381 renameInfo._newName); 382 } else if(renameInfo._type.equals("Parameter")) { 383 choice.renameParameter(renameInfo._oldName, 384 renameInfo._newName, renameInfo._container); 385 } 386 //} catch(IllegalActionException e) { 387 //MessageHandler.error("Error renaming " + renameInfo._oldName, e); 388 //} 389 } 390 // execute an empty change request so that the new port 391 // names appear (if we changed any port names) 392 _repaintCanvas(choice); 393 doneRenaming = true; 394 } 395 } else if(renameDialog.buttonPressed().equals("Cancel") || 396 renameDialog.buttonPressed().isEmpty()) { 397 doneRenaming = true; 398 } 399 } 400 401 } catch(Exception e) { 402 MessageHandler.error("Error renaming.", e); 403 } 404 } else if(buttonPressed.equals("Remove")) { 405 boolean doneRemoving = false; 406 while(!doneRemoving) { 407 RemovePane removePane = null; 408 try { 409 removePane = new RemovePane(choice); 410 } catch (IllegalActionException e) { 411 MessageHandler.error("Error creating Remove dialog.", e); 412 } 413 414 if(removePane != null) { 415 final ComponentDialog removeDialog = new ComponentDialog(parent, 416 buttonPressed, removePane, 417 new String[] {"Remove", "Remove & Continue", "Cancel"}); 418 String pressed = removeDialog.buttonPressed(); 419 420 doneRemoving = true; 421 if(pressed.equals("Remove & Continue")) { 422 doneRemoving = false; 423 } 424 425 if(pressed.equals("Remove") || pressed.equals("Remove & Continue")) { 426 String removeStr = removePane.getRemove(); 427 String name = removePane.getTextName(); 428 if(name != null) { 429 boolean removed = false; 430 try { 431 if(removeStr.equals("Input")) { 432 if(MessageHandler.yesNoQuestion("Remove input " + name + "?")) { 433 choice.removeInput(name); 434 removed = true; 435 addedInputs.remove(name); 436 } 437 } else if(removeStr.equals("Output")) { 438 if(MessageHandler.yesNoQuestion("Remove output " + name + "?")) { 439 choice.removeOutput(name); 440 removed = true; 441 addedOutputs.remove(name); 442 } 443 } else if(removeStr.equals("Parameter")) { 444 if(MessageHandler.yesNoQuestion("Remove parameter " + name + "?")) { 445 final NamedObj container = removePane.getRemoveContainer(); 446 if(container == choice) { 447 choice.removeParameter(name); 448 removed = true; 449 addedParameters.remove(name); 450 } else { 451 Attribute parameter = container.getAttribute(name); 452 parameter.setContainer(null); 453 removed = true; 454 // TODO undo stuff 455 } 456 457 } 458 } else if(removeStr.equals("Execution Choice")) { 459 if(MessageHandler.yesNoQuestion("Remove execution choice " + 460 name + " and all of its components?")) { 461 choice.removeExecutionChoice(name); 462 removed = true; 463 addedChoices.remove(name); 464 465 // if the choices are open in a frame, remove the tab for the choice 466 // that was removed. 467 KeplerGraphFrame frame = ModelToFrameManager.getInstance().getFrame(choice); 468 if(frame != null && (frame instanceof TabbedKeplerGraphFrame)) { 469 ((TabbedKeplerGraphFrame)frame).updateTabsForComposite(choice); 470 } 471 } 472 } 473 474 if(removed) { 475 // execute an empty change request so that removed port 476 // no longer shows on the canvas 477 _repaintCanvas(choice); 478 } 479 } catch(Exception e) { 480 MessageHandler.error("Error removing " + name, e); 481 } 482 } 483 } 484 } 485 } 486 } else if(buttonPressed.equals("Export")) { 487 final ExportPane exportPane = new ExportPane(choice); 488 final ComponentDialog exportDialog = new ComponentDialog(parent, 489 buttonPressed, exportPane); 490 if(exportDialog.buttonPressed().equals("OK")) { 491 String name = exportPane.getChoiceName(); 492 if(name != null) { 493 494 // Avoid white boxes in file chooser, see 495 // http://bugzilla.ecoinformatics.org/show_bug.cgi?id=3801 496 JFileChooserBugFix jFileChooserBugFix = new JFileChooserBugFix(); 497 Color background = null; 498 PtFileChooser chooser = null; 499 500 try { 501 background = jFileChooserBugFix.saveBackground(); 502 chooser = new PtFileChooser(parent, "Export", 503 JFileChooser.SAVE_DIALOG); 504 505 String defaultFileName = name.replaceAll("\\s+", "") + ".xml"; 506 chooser.setSelectedFile(new File(defaultFileName)); 507 508 int returnVal = chooser.showDialog(parent, "Export"); 509 if (returnVal == JFileChooser.APPROVE_OPTION) { 510 // process the given file 511 File saveFile = chooser.getSelectedFile(); 512 513 if(saveFile.exists() && !PtGUIUtilities.useFileDialog()) { 514 if (!MessageHandler.yesNoQuestion("Overwrite \"" 515 + saveFile.getName() + "\"?")) { 516 saveFile = null; 517 } 518 } 519 520 try { 521 choice.exportExecutionChoice(saveFile, name); 522 } catch (Exception e) { 523 MessageHandler.error("Error exporting execution choice.", e); 524 } 525 526 } 527 528 } finally { 529 jFileChooserBugFix.restoreBackground(background); 530 } 531 532 } 533 } 534 } else if(buttonPressed.equals("Import")) { 535 536 // Avoid white boxes in file chooser, see 537 // http://bugzilla.ecoinformatics.org/show_bug.cgi?id=3801 538 JFileChooserBugFix jFileChooserBugFix = new JFileChooserBugFix(); 539 Color background = null; 540 PtFileChooser chooser = null; 541 542 try { 543 background = jFileChooserBugFix.saveBackground(); 544 chooser = new PtFileChooser(parent, "Import", 545 JFileChooser.OPEN_DIALOG); 546 chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); 547 chooser.addChoosableFileFilter(new ExtensionFilenameFilter("xml")); 548 549 550 int returnVal = chooser.showDialog(parent, "Import"); 551 if(returnVal == JFileChooser.APPROVE_OPTION) { 552 553 // load the file as a new execution choice 554 File loadFile = chooser.getSelectedFile(); 555 556 // ask the user for the name of the new execution choice 557 558 String refinementName = null; 559 boolean doneAskingName = false; 560 561 while(!doneAskingName) { 562 563 // set the default name to be the file name 564 final ImportPane importPane = 565 new ImportPane(FilenameUtils.removeExtension(loadFile.getName())); 566 final ComponentDialog importDialog = new ComponentDialog(parent, 567 buttonPressed, importPane); 568 if(importDialog.buttonPressed().equals("OK")) { 569 570 // see if the name has already been chosen 571 refinementName = importPane.getChoiceName(); 572 if(choice.getEntity(refinementName) != null) { 573 MessageHandler.error("The name " + refinementName + 574 " is already used. Please choose a different name."); 575 } else { 576 doneAskingName = true; 577 } 578 579 } else if(importDialog.buttonPressed().equals("Cancel")) { 580 refinementName = null; 581 doneAskingName = true; 582 } 583 } 584 585 // load the execution choice if a unique name was selected. 586 if(refinementName != null) { 587 try { 588 choice.newExecutionChoice(loadFile, refinementName); 589 } catch(IllegalActionException e) { 590 MessageHandler.error("Error importing execution choice.", e); 591 } 592 } 593 594 } 595 596 } finally { 597 jFileChooserBugFix.restoreBackground(background); 598 } 599 600 } else if(buttonPressed.equals("Arguments")) { 601 ArgumentsPane argumentsPane = null; 602 try { 603 argumentsPane = new ArgumentsPane(choice); 604 } catch (IllegalActionException e) { 605 MessageHandler.error("Error creating Arguments dialog.", e); 606 } 607 608 if(argumentsPane != null) { 609 final ComponentDialog argumentsDialog = new ComponentDialog(parent, 610 buttonPressed, argumentsPane); 611 if(argumentsDialog.buttonPressed().equals("OK")) { 612 try { 613 argumentsPane.applyChanges(); 614 } catch(Exception e) { 615 MessageHandler.error("Error changing arguments.", e); 616 } 617 } 618 } 619 } else if(buttonPressed.equals("Types")) { 620 TypesPane typesPane = null; 621 try { 622 typesPane = new TypesPane(choice); 623 } catch (IllegalActionException e) { 624 MessageHandler.error("Error creating Types dialog.", e); 625 } 626 627 if(typesPane != null) { 628 final ComponentDialog typesDialog = new ComponentDialog(parent, 629 buttonPressed, typesPane); 630 if(typesDialog.buttonPressed().equals("OK")) { 631 try { 632 typesPane.applyChanges(); 633 } catch(Exception e) { 634 MessageHandler.error("Error changing types.", e); 635 } 636 } 637 } 638 } 639 } 640 } 641 642 /** Repaint the canvas by executing an empty change request. */ 643 private void _repaintCanvas(ExecutionChoice choice) { 644 MoMLChangeRequest change = 645 new MoMLChangeRequest(this, this, "<group></group>"); 646 change.setPersistent(false); 647 choice.requestChange(change); 648 } 649 650 /** A utility pane for adding/removing. */ 651 private static abstract class UtilPane extends JPanel implements ActionListener { 652 653 public UtilPane(ExecutionChoice choice) { 654 _choice = choice; 655 } 656 657 /** Get the type of the component added, e.g., if the component is 658 * an execution choice, the type is the name of one of the templates. 659 */ 660 public String getType() { 661 Object item = _typeComboBox.getSelectedItem(); 662 if(item == null) { 663 return ""; 664 } 665 // return toString() since item may not be a String, 666 // e.g., it could be an ExecutionChoice.IOType 667 return item.toString(); 668 } 669 670 /** Set the type of the component to be added. */ 671 public void setType(String typeStr) { 672 if(typeStr != null) { 673 _typeComboBox.setSelectedItem(typeStr); 674 } 675 } 676 677 /** Get the selected action component type, 678 * e.g, input, output, parameter, execution choice. 679 */ 680 protected String _getActionButtonSelected() { 681 for(JRadioButton button : _buttonMap.values()) { 682 if(button.isSelected()) { 683 return button.getText(); 684 } 685 } 686 return null; 687 } 688 689 /** Set the selected action component. */ 690 public void setActionButtonSelected(String buttonText) { 691 if(buttonText != null) { 692 for(JRadioButton button : _buttonMap.values()) { 693 if(button.getText().equals(buttonText)) { 694 button.setSelected(true); 695 } else { 696 button.setSelected(false); 697 } 698 } 699 } 700 } 701 702 /** Layout the top part of the pane with the radio buttons. */ 703 protected void _doTopLayout(String actionStr, GridBagConstraints c) { 704 705 c.fill = GridBagConstraints.HORIZONTAL; 706 c.anchor = GridBagConstraints.LINE_START; 707 708 c.gridx = 0; 709 c.gridy = 0; 710 add(new JLabel(actionStr + ":"), c); 711 712 final ButtonGroup buttonGroup = new ButtonGroup(); 713 JRadioButton inputButton = new JRadioButton("Input"); 714 inputButton.setSelected(true); 715 inputButton.addActionListener(this); 716 buttonGroup.add(inputButton); 717 _buttonMap.put("Input", inputButton); 718 c.gridx = 1; 719 c.gridy++; 720 add(inputButton, c); 721 722 JRadioButton outputButton = new JRadioButton("Output"); 723 outputButton.addActionListener(this); 724 buttonGroup.add(outputButton); 725 _buttonMap.put("Output", outputButton); 726 c.gridy++; 727 add(outputButton, c); 728 729 JRadioButton parameterButton = new JRadioButton("Parameter"); 730 parameterButton.addActionListener(this); 731 buttonGroup.add(parameterButton); 732 _buttonMap.put("Parameter", parameterButton); 733 c.gridy++; 734 add(parameterButton, c); 735 736 JRadioButton choiceButton = new JRadioButton("Execution Choice"); 737 choiceButton.addActionListener(this); 738 buttonGroup.add(choiceButton); 739 _buttonMap.put("Execution Choice", choiceButton); 740 c.gridy++; 741 add(choiceButton, c); 742 743 c.gridx = 0; 744 c.gridy++; 745 add(new JLabel("Name:"), c); 746 } 747 748 protected Map<String,JRadioButton> _buttonMap = new HashMap<String,JRadioButton>(); 749 protected JComboBox<Object> _typeComboBox; 750 protected ExecutionChoice _choice; 751 752 /** The label for choice entry. */ 753 protected JLabel _choiceLabel; 754 755 /** The label for the type combobox. */ 756 protected JLabel _typeLabel; 757 758 /** The combobox to hold the names of execution choices. */ 759 protected JComboBox<String> _choiceComboBox; 760 761 } 762 763 /** A pane to add an input, output, or execution choice. */ 764 private static class AddPane extends UtilPane { 765 766 public AddPane(ExecutionChoice choice) { 767 768 super(choice); 769 770 GridBagLayout layout = new GridBagLayout(); 771 setLayout(layout); 772 773 GridBagConstraints c = new GridBagConstraints(); 774 775 _doTopLayout("Add", c); 776 777 _nameTextField = new JTextField("", 20); 778 c.gridx = 1; 779 add(_nameTextField, c); 780 781 c.gridx = 0; 782 c.gridy++; 783 _argumentLabel = new JLabel(ExecutionChoice.ARGUMENT_NAME + ":"); 784 add(_argumentLabel, c); 785 786 _argumentTextField = new JTextField("", 20); 787 c.gridx = 1; 788 add(_argumentTextField, c); 789 790 c.gridx = 0; 791 c.gridy++; 792 _typeLabel = new JLabel("Type:"); 793 add(_typeLabel, c); 794 795 _typeComboBox = new JComboBox<Object>(ExecutionChoice.IOType.values()); 796 _typeComboBox.addActionListener(this); 797 c.gridx = 1; 798 add(_typeComboBox, c); 799 800 c.gridx = 0; 801 c.gridy++; 802 _choiceLabel = new JLabel("Choice:"); 803 add(_choiceLabel, c); 804 _choiceLabel.setEnabled(false); 805 806 _choiceComboBox = new JComboBox<String>(); 807 _choiceComboBox.addItem(ExecutionChoice.ALL_CHOICES_NAME); 808 for(String name : _choice.getExecutionChoiceNames()) { 809 _choiceComboBox.addItem(name); 810 } 811 _choiceComboBox.addActionListener(this); 812 c.gridx = 1; 813 add(_choiceComboBox, c); 814 _choiceComboBox.setEnabled(false); 815 } 816 817 @Override 818 public void actionPerformed(ActionEvent event) { 819 820 Object source = event.getSource(); 821 // see if the type of component to add was changed 822 if(source instanceof JRadioButton) { 823 final String buttonText = (String) ((JRadioButton)source).getText(); 824 _updateTypeComboBox(buttonText); 825 } 826 827 _updateEnabledFields(); 828 } 829 830 /** Get the component added, i.e., input, output, execution choice. */ 831 public String getAdd() { 832 return _getActionButtonSelected(); 833 } 834 835 /** Set the component to be added. */ 836 public void setAdd(String addStr) { 837 if(addStr != null) { 838 setActionButtonSelected(addStr); 839 _updateTypeComboBox(addStr); 840 _updateEnabledFields(); 841 } 842 } 843 844 /** Get the argument value. */ 845 public String getArgument() { 846 return _argumentTextField.getText(); 847 } 848 849 /** Set the argument. */ 850 public void setArgument(String argumentStr) { 851 if(argumentStr != null) { 852 _argumentTextField.setText(argumentStr); 853 } 854 } 855 856 /** Get the name of the selected execution choice. */ 857 public String getChoice() { 858 return (String) _choiceComboBox.getSelectedItem(); 859 } 860 861 /** Set the name of the seleced execution choice. */ 862 public void setChoice(String choiceStr) { 863 if(choiceStr != null) { 864 _choiceComboBox.setSelectedItem(choiceStr); 865 } 866 } 867 868 /** Get the user-specified name of the component added. */ 869 public String getTextName() { 870 return _nameTextField.getText(); 871 } 872 873 /** Set the name of the component to be added. */ 874 public void setTextName(String newName) { 875 if(newName != null) { 876 _nameTextField.setText(newName); 877 } 878 } 879 880 /** Refill the type combo box based on the add type. */ 881 protected void _updateTypeComboBox(String addStr) { 882 // remove all the types 883 _typeComboBox.removeAllItems(); 884 // see if the add was set to input or output 885 if(addStr.equals("Input") || addStr.equals("Output")) { 886 for(ExecutionChoice.IOType type : ExecutionChoice.IOType.values()) { 887 _typeComboBox.addItem(type); 888 } 889 } else if(addStr.equals("Parameter")) { 890 for(ExecutionChoice.ParameterType type : ExecutionChoice.ParameterType.values()) { 891 _typeComboBox.addItem(type); 892 } 893 } else { 894 // add was set to execution choice, so load the template 895 // names in the type combobox 896 try { 897 for(String name : _choice.getTemplateNames()) { 898 _typeComboBox.addItem(name); 899 } 900 } catch(IllegalActionException e) { 901 MessageHandler.error("Error loading template names.", e); 902 } 903 } 904 } 905 906 /** Enable or disable fields based on the selected radio button. */ 907 private void _updateEnabledFields() { 908 909 // get the type of component to add 910 String buttonText = _getActionButtonSelected(); 911 912 if(buttonText.equals("Execution Choice") || getType().equals("Data")) { 913 _argumentLabel.setEnabled(false); 914 _argumentTextField.setEnabled(false); 915 } else { 916 _argumentLabel.setEnabled(true); 917 _argumentTextField.setEnabled(true); 918 } 919 920 // the choice combobox selects which choice to add the parameter to 921 if(buttonText.equals("Parameter")) { 922 _choiceLabel.setEnabled(true); 923 _choiceComboBox.setEnabled(true); 924 } else { 925 _choiceLabel.setEnabled(false); 926 _choiceComboBox.setEnabled(false); 927 } 928 } 929 930 /** The name of the component. */ 931 private JTextField _nameTextField; 932 933 /** The (optional) argument used with the component. */ 934 private JTextField _argumentTextField; 935 936 /** The label for argument entry. */ 937 private JLabel _argumentLabel; 938 939 } 940 941 /** A pane to remove an input, output, or execution choice. */ 942 private static class RemovePane extends UtilPane { 943 944 public RemovePane(ExecutionChoice choice) throws IllegalActionException { 945 946 super(choice); 947 948 GridBagLayout layout = new GridBagLayout(); 949 setLayout(layout); 950 951 GridBagConstraints c = new GridBagConstraints(); 952 953 _doTopLayout("Remove", c); 954 955 _nameComboBox = new JComboBox<String>(); 956 List<String> inputNames = _choice.getInputNames(true); 957 for(String inputName : inputNames) { 958 _nameComboBox.addItem(inputName); 959 } 960 if(_nameComboBox.getItemCount() == 0) { 961 _nameComboBox.addItem(NONE_TO_REMOVE); 962 _nameComboBox.setEnabled(false); 963 } 964 c.gridx = 1; 965 add(_nameComboBox, c); 966 967 c.gridx = 0; 968 c.gridy++; 969 _choiceLabel = new JLabel("Choice:"); 970 add(_choiceLabel, c); 971 _choiceLabel.setEnabled(false); 972 973 _choiceComboBox = new JComboBox<String>(); 974 _choiceComboBox.addItem(ExecutionChoice.ALL_CHOICES_NAME); 975 for(String name : choice.getExecutionChoiceNames()) { 976 _choiceComboBox.addItem(name); 977 } 978 _choiceComboBox.addActionListener(this); 979 c.gridx = 1; 980 add(_choiceComboBox, c); 981 _choiceComboBox.setEnabled(false); 982 } 983 984 @Override 985 public void actionPerformed(ActionEvent event) { 986 987 Object source = event.getSource(); 988 989 try { 990 991 // see if the add combobox was changed 992 if(source instanceof JRadioButton) { 993 _nameComboBox.removeAllItems(); 994 String typeStr = (String) ((JRadioButton)source).getText(); 995 if(typeStr.equals("Input")) { 996 for(String name : _choice.getInputNames(true)) { 997 _nameComboBox.addItem(name); 998 } 999 } else if(typeStr.equals("Output")) { 1000 for(String name : _choice.getOutputNames(true)) { 1001 _nameComboBox.addItem(name); 1002 } 1003 } else if(typeStr.equals("Parameter")) { 1004 for(String name : _choice.getParameterNames()) { 1005 _nameComboBox.addItem(name); 1006 } 1007 } else { 1008 // add was set to execution choice, so load the template 1009 // names in the type combobox 1010 for(Refinement refinement : _choice.entityList(Refinement.class)) { 1011 _nameComboBox.addItem(refinement.getDisplayName()); 1012 } 1013 } 1014 1015 // the choice combobox denotes which execution choice 1016 // contains the parameter to remove. 1017 if(typeStr.equals("Parameter")) { 1018 _choiceLabel.setEnabled(true); 1019 _choiceComboBox.setEnabled(true); 1020 } else { 1021 _choiceLabel.setEnabled(false); 1022 _choiceComboBox.setEnabled(false); 1023 } 1024 1025 } else if(source == _choiceComboBox) { 1026 1027 _nameComboBox.removeAllItems(); 1028 String refinementName = (String) _choiceComboBox.getSelectedItem(); 1029 if(refinementName.equals(ExecutionChoice.ALL_CHOICES_NAME)) { 1030 for(String name : _choice.getParameterNames()) { 1031 _nameComboBox.addItem(name); 1032 } 1033 } else { 1034 ComponentEntity<?> refinement = _choice.getEntity(refinementName); 1035 for(Parameter parameter : refinement.attributeList(Parameter.class)) { 1036 String name = parameter.getName(); 1037 // can't delete the commandLine parameter 1038 if(!name.equals(ExecutionChoice.COMMAND_LINE_NAME) && 1039 !name.startsWith("_")) { 1040 _nameComboBox.addItem(name); 1041 } 1042 } 1043 } 1044 } 1045 1046 if(_nameComboBox.getItemCount() == 0) { 1047 _nameComboBox.addItem(NONE_TO_REMOVE); 1048 _nameComboBox.setEnabled(false); 1049 } else { 1050 _nameComboBox.setEnabled(true); 1051 } 1052 } catch(IllegalActionException e) { 1053 MessageHandler.error("Error performing action.", e); 1054 } 1055 } 1056 1057 /** Get the container of the parameter to remove. */ 1058 public NamedObj getRemoveContainer() { 1059 String refinementName = (String) _choiceComboBox.getSelectedItem(); 1060 if(refinementName.equals(ExecutionChoice.ALL_CHOICES_NAME)) { 1061 return _choice; 1062 } else { 1063 return _choice.getEntity(refinementName); 1064 } 1065 } 1066 1067 /** Get the user-specified name of the component removed. */ 1068 public String getTextName() { 1069 String name = (String) _nameComboBox.getSelectedItem(); 1070 if(!name.equals(NONE_TO_REMOVE)) { 1071 return name; 1072 } 1073 return null; 1074 } 1075 1076 /** Get the type of component to be removed, 1077 * e.g., input, output, parameter, execution choice. 1078 */ 1079 public String getRemove() { 1080 return _getActionButtonSelected(); 1081 } 1082 1083 private JComboBox<String> _nameComboBox; 1084 1085 private static final String NONE_TO_REMOVE = "None to remove."; 1086 } 1087 1088 /** A utility class to hold rename information. */ 1089 private static class RenameInfo { 1090 1091 public RenameInfo(String newName, String oldName, String type, NamedObj container) { 1092 _newName = newName; 1093 _oldName = oldName; 1094 _type = type; 1095 _container = container; 1096 } 1097 1098 private String _oldName; 1099 private String _newName; 1100 private String _type; 1101 private NamedObj _container; 1102 } 1103 1104 /** A pane to rename inputs, outputs, or execution choices. */ 1105 private static class RenamePane extends FieldsPane { 1106 1107 public RenamePane(ExecutionChoice choice) throws IllegalActionException { 1108 super(choice, true, true); 1109 } 1110 1111 /** Get rename information. */ 1112 public Set<RenameInfo> getRenames() throws IllegalActionException { 1113 1114 final Set<RenameInfo> renames = new HashSet<RenameInfo>(); 1115 1116 Query query = _queries.get(_choice); 1117 1118 for(String name : _choice.getInputNames(true)) { 1119 String newName = query.getStringValue(name); 1120 if(!name.equals(newName)) { 1121 renames.add(new RenameInfo(newName, name, "Input", _choice)); 1122 } 1123 } 1124 1125 for(String name : _choice.getOutputNames(true)) { 1126 String newName = query.getStringValue(name); 1127 if(!name.equals(newName)) { 1128 renames.add(new RenameInfo(newName, name, "Output", _choice)); 1129 } 1130 } 1131 1132 for(String name : _choice.getParameterNames()) { 1133 String newName = query.getStringValue(name); 1134 if(!name.equals(newName)) { 1135 renames.add(new RenameInfo(newName, name, "Parameter", _choice)); 1136 } 1137 } 1138 1139 for(String name : _choice.getExecutionChoiceNames()) { 1140 String newName = query.getStringValue(name); 1141 if(!name.equals(newName)) { 1142 renames.add(new RenameInfo(newName, name, "Execution Choice", _choice)); 1143 } 1144 } 1145 1146 // get the renames for parameters in refinements 1147 for(String executionName : _choice.getExecutionChoiceNames()) { 1148 ComponentEntity<?> container = _choice.getEntity(executionName); 1149 query = _queries.get(container); 1150 1151 for(Parameter parameter : container.attributeList(Parameter.class)) { 1152 String name = parameter.getName(); 1153 if(!name.equals(ExecutionChoice.COMMAND_LINE_NAME) && 1154 !name.startsWith("_")) { 1155 String newName = query.getStringValue(name); 1156 if(!name.equals(newName)) { 1157 renames.add(new RenameInfo(newName, name, "Parameter", container)); 1158 } 1159 } 1160 } 1161 } 1162 1163 return renames; 1164 } 1165 1166 /** Add a set of renames to a query. 1167 * @param names the list of field names 1168 * @param choice the ExecutionChoice actor 1169 * @param container the container of the fields. this may be the same as choice. 1170 * @param query the query dialog to add the gui widgets to 1171 * @param noneMessage the text to display in the query if no fields are added. 1172 */ 1173 @Override 1174 protected void _addFields(List<String> names, ExecutionChoice choice, 1175 NamedObj container, Query query, String noneMessage) { 1176 1177 if(!names.isEmpty()) { 1178 String[] namesArray = names.toArray(new String[names.size()]); 1179 Arrays.sort(namesArray); 1180 for(String name : names) { 1181 query.addTextArea(name, name, name, _STRING_MODE_BACKGROUND_COLOR, 1182 Color.BLACK, 1, Query.DEFAULT_ENTRY_WIDTH); 1183 } 1184 } else { 1185 query.addText(noneMessage, Color.BLACK, SwingConstants.LEFT); 1186 } 1187 } 1188 1189 } 1190 1191 /** A pane to enter the name of an execution choice. */ 1192 private static class ImportPane extends JPanel { 1193 1194 /** Create a new ImportPane with the default name for the 1195 * imported execution choice. 1196 */ 1197 public ImportPane(String defaultName) { 1198 1199 add(new JLabel("Execution Choice Name:")); 1200 1201 _nameTextField = new JTextField(defaultName); 1202 add(_nameTextField); 1203 } 1204 1205 /** Get the name of the execution choice. */ 1206 public String getChoiceName() { 1207 return _nameTextField.getText(); 1208 } 1209 1210 /** A text field to enter the name. */ 1211 private JTextField _nameTextField; 1212 1213 } 1214 1215 /** A pane to export an execution choice. */ 1216 private static class ExportPane extends JPanel { 1217 1218 public ExportPane(ExecutionChoice choice) { 1219 1220 add(new JLabel("Execution Choice:")); 1221 1222 _choiceComboBox = new JComboBox<String>(choice.getExecutionChoiceNames().toArray(new String[0])); 1223 add(_choiceComboBox); 1224 } 1225 1226 /** Get the name of the selected execution choice. */ 1227 public String getChoiceName() { 1228 return (String) _choiceComboBox.getSelectedItem(); 1229 } 1230 1231 private JComboBox<String> _choiceComboBox; 1232 } 1233 1234 private static class ArgumentsPane extends FieldsPane { 1235 1236 public ArgumentsPane(ExecutionChoice choice) throws IllegalActionException { 1237 super(choice, false, false); 1238 } 1239 1240 /** Update the argument parameters with new values from the dialog. */ 1241 public void applyChanges() throws IllegalActionException, NameDuplicationException { 1242 1243 for(Map.Entry<NamedObj, Query> entry : _queries.entrySet()) { 1244 final NamedObj container = entry.getKey(); 1245 final Query query = entry.getValue(); 1246 1247 Set<String> names = new HashSet<String>(); 1248 if(container == _choice) { 1249 // add inputs for file types 1250 for(String inputName : _choice.getInputNames(false)) { 1251 if(ExecutionChoice.getPortIOType(_choice.getPort(inputName)) 1252 == ExecutionChoice.IOType.File) { 1253 names.add(inputName); 1254 } 1255 } 1256 1257 // add output for file types 1258 for(String outputName : _choice.getOutputNames(false)) { 1259 if(ExecutionChoice.getPortIOType(_choice.getPort(outputName)) 1260 == ExecutionChoice.IOType.File) { 1261 names.add(outputName); 1262 } 1263 } 1264 1265 // add parameters 1266 names.addAll(_choice.getParameterNames()); 1267 } else { 1268 // add the parameter names in the refinement 1269 List<Parameter> parameters = container.attributeList(Parameter.class); 1270 for(Parameter parameter : parameters) { 1271 String name = parameter.getName(); 1272 if(!name.equals(ExecutionChoice.COMMAND_LINE_NAME) && 1273 !name.startsWith("_")) { 1274 names.add(name); 1275 } 1276 } 1277 } 1278 1279 // see if any values in the query were changed 1280 for(String name : names) { 1281 String argument = ExecutionChoice.getArgument(container, name); 1282 String newArgument = query.getStringValue(name); 1283 if((argument == null && !newArgument.trim().isEmpty()) || 1284 (argument != null && !argument.equals(newArgument))) { 1285 Parameter parameter = (Parameter) container.getAttribute(name); 1286 ExecutionChoice.setArgument(parameter, newArgument); 1287 //System.out.println(name + " changed " + argument + " to " + newArgument); 1288 } 1289 } 1290 } 1291 } 1292 1293 /** Add a set of arguments to a query. 1294 * @param names the names of the components containing the arguments 1295 * @param choice the ExecutionChoice containing the components with arguments. 1296 * @param query the query in which to add the fields 1297 * @param noneMessage the text to add to the query if names is empty. 1298 * 1299 */ 1300 @Override 1301 protected void _addFields(List<String> names, ExecutionChoice choice, 1302 NamedObj container, Query query, String noneMessage) throws IllegalActionException { 1303 1304 if(!names.isEmpty()) { 1305 String[] namesArray = names.toArray(new String[names.size()]); 1306 Arrays.sort(namesArray); 1307 for(String name : names) { 1308 String argument = ExecutionChoice.getArgument(container, name); 1309 query.addTextArea(name, 1310 name, 1311 argument, 1312 _STRING_MODE_BACKGROUND_COLOR, 1313 Color.black, 1314 1, 1315 Query.DEFAULT_ENTRY_WIDTH); 1316 } 1317 } else { 1318 query.addText(noneMessage, Color.BLACK, SwingConstants.LEFT); 1319 } 1320 } 1321 1322 } 1323 1324 /** A dialog for changing the types of inputs, outputs, and parameters. */ 1325 private static class TypesPane extends FieldsPane { 1326 1327 public TypesPane(ExecutionChoice choice) throws IllegalActionException { 1328 super(choice, false, true); 1329 } 1330 1331 /** Change the types. */ 1332 public void applyChanges() throws IllegalActionException, NameDuplicationException { 1333 1334 Query query = _queries.get(_choice); 1335 1336 List<Port> ports = new LinkedList<Port>(_choice.portList()); 1337 1338 for(Port port : ports) { 1339 if(port != _choice.control.getPort()) { 1340 String newTypeStr = query.getStringValue(port.getName()); 1341 ExecutionChoice.IOType newType = ExecutionChoice.IOType.valueOf(newTypeStr); 1342 // see if the types are different 1343 if(ExecutionChoice.getPortIOType(port) != newType) { 1344 _choice.setPortIOType((TypedIOPort)port, newType); 1345 } 1346 } 1347 } 1348 1349 for(String name : _choice.getParameterNames()) { 1350 String newTypeStr = query.getStringValue(name); 1351 ExecutionChoice.ParameterType newType = ExecutionChoice.ParameterType.valueOf(newTypeStr); 1352 // see if the types are different 1353 if(_choice.getParameterType(name) != newType) { 1354 _choice.setParameterType(name, newType); 1355 } 1356 } 1357 1358 // get the type changes for parameters in refinements 1359 for(String executionName : _choice.getExecutionChoiceNames()) { 1360 ComponentEntity<?> container = _choice.getEntity(executionName); 1361 query = _queries.get(container); 1362 1363 for(Parameter parameter : container.attributeList(Parameter.class)) { 1364 String name = parameter.getName(); 1365 if(!name.equals(ExecutionChoice.COMMAND_LINE_NAME) && 1366 !name.startsWith("_")) { 1367 String newTypeStr = query.getStringValue(name); 1368 ExecutionChoice.ParameterType newType = ExecutionChoice.ParameterType.valueOf(newTypeStr); 1369 // see if the types are different 1370 if(ExecutionChoice.getParameterType(container, name) != newType) { 1371 ExecutionChoice.setParameterType(container, name, newType); 1372 } 1373 } 1374 } 1375 } 1376 } 1377 1378 /** Add a set of fields and their types to a query. 1379 * @param names the names of the fields 1380 * @param choice the ExecutionChoice containing the fields. 1381 * @param container the container of the fields. this may be the same as choice. 1382 * @param query the query in which to add the fields 1383 * @param noneMessage the text to add to the query if names is empty. 1384 */ 1385 @Override 1386 protected void _addFields(List<String> names, ExecutionChoice choice, 1387 NamedObj container, Query query, String noneMessage) throws IllegalActionException { 1388 1389 if(!names.isEmpty()) { 1390 String[] namesArray = names.toArray(new String[names.size()]); 1391 Arrays.sort(namesArray); 1392 for(String name : names) { 1393 1394 boolean added = false; 1395 if(container == choice) { 1396 Port port = choice.getPort(name); 1397 // see if the name belongs to a port or a parameter. 1398 if(port != null) { 1399 ExecutionChoice.IOType type = ExecutionChoice.getPortIOType(port); 1400 query.addChoice(name, name, ExecutionChoice.IOType.values(), type); 1401 added = true; 1402 } 1403 } 1404 1405 if(!added) { 1406 ExecutionChoice.ParameterType type = ExecutionChoice.getParameterType(container, name); 1407 query.addChoice(name, name, ExecutionChoice.ParameterType.values(), type); 1408 } 1409 } 1410 } else { 1411 query.addText(noneMessage, Color.BLACK, SwingConstants.LEFT); 1412 } 1413 } 1414 } 1415 1416 /** A base class to display a pane for the inputs, outputs, parameters, 1417 * and sub-workflows. 1418 */ 1419 private static abstract class FieldsPane extends JPanel { 1420 1421 /** Create a new pane listing the fields for an ExecutionChoice actor. 1422 * @param choice the ExecutionChoice actor 1423 * @param includeChoices if true, include the list of refinements 1424 * @param includeDataPorts if true, the list of inputs and outputs 1425 * are the data and file ports. otherwise, the list is the file ports. 1426 */ 1427 private FieldsPane(ExecutionChoice choice, boolean includeChoices, boolean includeDataPorts) 1428 throws IllegalActionException { 1429 1430 _choice = choice; 1431 1432 Query query = new Query(); 1433 _queries.put(choice, query); 1434 1435 // NOTE: use empty spaces here to make the dialog wider otherwise the tabs 1436 // for refinements are stacked (linux) or do not appear (mac). 1437 1438 // add inputs 1439 query.addText("File Input Parameters ", 1440 Color.BLACK, SwingConstants.LEFT); 1441 _addFields(choice.getInputNames(includeDataPorts), choice, choice, query, "None"); 1442 1443 // add outputs 1444 query.addSeparator(); 1445 query.addText("File Output Parameters ", 1446 Color.BLACK, SwingConstants.LEFT); 1447 _addFields(choice.getOutputNames(includeDataPorts), choice, choice, query, "None"); 1448 1449 // add parameters 1450 query.addSeparator(); 1451 query.addText("Additional Parameters ", 1452 Color.BLACK, SwingConstants.LEFT); 1453 _addFields(choice.getParameterNames(), choice, choice, query, "None"); 1454 1455 // add execution choices 1456 if(includeChoices) { 1457 query.addSeparator(); 1458 query.addText("Execution Choices", Color.BLACK, SwingConstants.LEFT); 1459 _addFields(choice.getExecutionChoiceNames(), choice, choice, query, "None"); 1460 } 1461 1462 JTabbedPane tabbedPane = new JTabbedPane(); 1463 tabbedPane.addTab("Shared Options", query); 1464 1465 // add a tab for each refinement 1466 1467 for(String executionName : choice.getExecutionChoiceNames()) { 1468 query = new Query(); 1469 final ComponentEntity<?> container = choice.getEntity(executionName); 1470 _queries.put(container, query); 1471 1472 // get the names and sort them 1473 final List<String> names = new LinkedList<String>(); 1474 final List<Parameter> parameters = container.attributeList(Parameter.class); 1475 for(Parameter parameter : parameters) { 1476 String name = parameter.getName(); 1477 if(!name.equals(ExecutionChoice.COMMAND_LINE_NAME) && 1478 !name.startsWith("_")) { 1479 names.add(parameter.getName()); 1480 } 1481 } 1482 _addFields(names, choice, container, query, "No parameters."); 1483 1484 tabbedPane.addTab(executionName, query); 1485 } 1486 1487 add(tabbedPane); 1488 1489 } 1490 1491 /** Add the fields for a set of names. 1492 * @param names the list of field names 1493 * @param choice the ExecutionChoice actor 1494 * @param container the container of the fields. this may be the same as choice. 1495 * @param query the query dialog to add the gui widgets to 1496 * @param noneMessage the text to display in the query if no fields are added. 1497 */ 1498 protected abstract void _addFields(List<String> names, ExecutionChoice choice, 1499 NamedObj container, Query query, String noneMessage) throws IllegalActionException; 1500 1501 protected ExecutionChoice _choice; 1502 protected Map<NamedObj,Query> _queries = new HashMap<NamedObj,Query>(); 1503 1504 } 1505 1506 /** Background color for string mode edit boxes. */ 1507 // FIXME copied from PtolemyQuery since private 1508 private static Color _STRING_MODE_BACKGROUND_COLOR = new Color(230, 255, 1509 255, 255); 1510 1511}