/** Cache the values entered by the user in VEPs dynamically-displayed on VM start. */ void cacheArgumentValues() { // Collect the value entry panels which correspond to target arguments in the TableTop List<ValueEditor> argPanels = getArgumentPanels(); List<Gem.PartInput> argParts = targetDisplayedGem.getTargetArguments(); int numArgs = argParts.size(); // sanity check if (numArgs != argPanels.size()) { throw new IllegalStateException( "Programming Error: matching " + numArgs + " arguments and " + argPanels.size() + " argument panels."); } for (int i = 0; i < numArgs; i++) { Gem.PartInput argPart = argParts.get(i); ValueEditor argPanel = argPanels.get(i); ValueNode argNode = argPanel.getValueNode(); gemCutter.getTableTop().cacheArgValue(argPart, argNode); } }
private TypeExpr[] getArgTypes() { List<ValueEditor> argPanelList = getArgumentPanels(); TypeExpr[] argTypes = new TypeExpr[argPanelList.size()]; for (int i = 0, nArgs = argPanelList.size(); i < nArgs; i++) { ValueEditor argPanel = argPanelList.get(i); argTypes[i] = argPanel.getValueNode().getTypeExpr(); } return argTypes; }
private InputPolicy[] getInputPolicies() { List<ValueEditor> argPanelList = getArgumentPanels(); InputPolicy[] ips = new InputPolicy[argPanelList.size()]; for (int i = 0, nArgs = argPanelList.size(); i < nArgs; i++) { ValueEditor argPanel = argPanelList.get(i); ips[i] = argPanel.getValueNode().getInputPolicy(); } return ips; }
/** {@inheritDoc} */ @Override public void valueCommitted(ValueEditorEvent evt) { ValueEditor committedEditor = (ValueEditor) evt.getSource(); ValueNode oldValue = evt.getOldValue(); ValueNode newValue = committedEditor.getValueNode(); if (!oldValue.sameValue(newValue)) { switchValueNodeTypeExpr(oldValue, newValue); committedEditor.setSize(committedEditor.getPreferredSize()); } }
private Object[] getRuntimeArgumentValues() { List<ValueEditor> argPanelList = getArgumentPanels(); ArrayList<Object> inputJavaValues = new ArrayList<Object>(); for (int i = 0, nArgs = argPanelList.size(); i < nArgs; i++) { ValueEditor argPanel = argPanelList.get(i); Object[] values = argPanel.getValueNode().getInputJavaValues(); for (final Object value : values) { inputJavaValues.add(value); } } return inputJavaValues.toArray(); }
/** Clears the data types and values of the arguments of the running gem */ void resetArgumentValues() { // Loop thru the ValueEditors and reset their ValueNodes. for (final ValueEditor editor : valueEditorHierarchyManager.getTopValueEditors()) { // build the new ValueNode and give it to the argument panel TypeExpr leastConstrainedType = editor.getContext().getLeastConstrainedTypeExpr(); ValueNode newNode = valueEditorHierarchyManager .getValueEditorManager() .getValueNodeBuilderHelper() .getValueNodeForTypeExpr(leastConstrainedType); editor.changeOwnerValue(newNode); } }
/** This method is called when the runtime is about to start evaluating. */ @Override public void enterRunningState() { List<ValueEditor> argPanelList = getArgumentPanels(); // If there are argument panels, we use these to specialize the target // type. int nPanels = argPanelList.size(); TypeExpr[] argPanelTypes = new TypeExpr[nPanels]; for (int i = 0; i < nPanels; i++) { ValueEditor argPanel = argPanelList.get(i); argPanelTypes[i] = argPanel.getValueNode().getTypeExpr(); } gemCutter.getStatusMessageDisplayer().clearMessage(this); gemCutter.setTargetRunningButtons(true); // System.out.println ("DisplayedGemRunner.run()"); }
/** * Positions the given value editor next to the connection point for the given input. * * @param editor the editor to position * @param inputPart the input part to position it next to */ private void positionEditor(ValueEditor editor, Gem.PartInput inputPart) { // Determine position of the panel and make sure it will be within the parent Point xy = gemCutter.getTableTop().getDisplayedPartConnectable(inputPart).getConnectionPoint(); editor.setSize(editor.getPreferredSize()); // Make sure this is OK xy.x -= editor.getWidth(); xy.y -= editor.getHeight() / 2; if (xy.x <= 0) { xy.x = 0; } if (xy.y <= 0) { xy.y = 0; } editor.setLocation(xy); }
/** * This is used for switching the type of a ValueNode within a given context. Basically, a * switch is made between valueNode and newValueNode, but their types are different. * Consequently, other valueNodes may be modified. * * <p>For example: * * <p>Let's say you have "add 1 2", where 1, 2 are of type Integer and are represented by * ValueNodes, then to switch '1' to '1.0' (a Double), you must switch '2' to '2.0' to avoid * type clashes. * * <p>This method will handle the switching of the associated types within a type context, so it * should so if you pass 1, 1.0 it'll convert 2 to 2.0 . * * <p>Note that you are able to pass in '5.0' as the new value if you'd like. * * @param oldValueNode your original ValueNode * @param newValueNode the valueNode that you want to arrive at */ private void switchValueNodeTypeExpr(ValueNode oldValueNode, ValueNode newValueNode) { // Create the map from input to value node Map<PartInput, ValueNode> inputToValueNodeMap = new HashMap<PartInput, ValueNode>(); for (final PartInput input : inputToEditorMap.keySet()) { ValueEditor editor = inputToEditorMap.get(input); inputToValueNodeMap.put(input, editor.getOwnerValueNode()); } // Create the type switcher InputValueTypeSwitchHelper switcher = new InputValueTypeSwitchHelper(valueEditorManager.getValueNodeCommitHelper()); // Get the switched values Map<PartInput, ValueNode> inputNewValueMap = switcher.getInputSwitchValues(oldValueNode, newValueNode, inputToValueNodeMap); // Now update with the switched values. for (final Map.Entry<PartInput, ValueNode> mapEntry : inputNewValueMap.entrySet()) { Gem.PartInput input = mapEntry.getKey(); ValueNode newInputValue = mapEntry.getValue(); ValueEditor editor = inputToEditorMap.get(input); editor.changeOwnerValue(newInputValue); editor.setSize(editor.getPreferredSize()); } }
/** * Display value entry controls for all unbound arguments. Precondition: the target must be set. */ private void displayArgumentControls() { TableTopPanel tableTopPanel = getTableTopPanel(); // Build the list of value entry panels and place them onto the TableTop // Get the list of unbound arguments List<Gem.PartInput> argParts = targetDisplayedGem.getTargetArguments(); // see if it's ok to use the cached argument values boolean canUseCachedArgs = canUseCachedArguments(); // Figure out the types of the argument panels. Note that we must account for cached values int numArgs = argParts.size(); // make copies of the input types. TypeExpr[] inputTypes = new TypeExpr[numArgs]; for (int i = 0; i < numArgs; i++) { // Get this input, and its type Gem.PartInput inputPart = argParts.get(i); inputTypes[i] = inputPart.getType(); } TypeExpr[] specializedInputTypes; if (canUseCachedArgs) { // this is the array of types cached for each argument. If there is no cached type, we just // use the argument type. TypeExpr[] cachedTypes = new TypeExpr[numArgs]; for (int i = 0; i < numArgs; ++i) { // What we do next depends on whether we use cached sink values Gem.PartInput inputPart = argParts.get(i); ValueNode cachedVN = gemCutter.getTableTop().getCachedValue(inputPart); if (cachedVN != null) { cachedTypes[i] = cachedVN.getTypeExpr(); } } try { ModuleTypeInfo contextModuleTypeInfo = gemCutter.getPerspective().getWorkingModuleTypeInfo(); specializedInputTypes = TypeExpr.patternMatchPieces(cachedTypes, inputTypes, contextModuleTypeInfo); } catch (TypeException te) { throw new IllegalStateException("Error reusing cached args."); } } else { specializedInputTypes = TypeExpr.copyTypeExprs(inputTypes); } ValueEditorManager valueEditorManager = gemCutter.getValueEditorManager(); ValueEditorDirector valueEditorDirector = valueEditorManager.getValueEditorDirector(); Map<PartInput, ValueEditor> inputToEditorMap = new LinkedHashMap<PartInput, ValueEditor>(); // Step through args, create a new value input panel for each, with the correct value type for (int i = 0; i < numArgs; i++) { // Get the gem and input final Gem.PartInput inputPart = argParts.get(i); final Gem inputGem = inputPart.getGem(); int argumentNumber = inputPart.getInputNum(); QualifiedName scName = null; if (inputGem instanceof FunctionalAgentGem) { scName = ((FunctionalAgentGem) inputGem).getName(); } // What we do next depends on whether we use cached sink values ValueNode cachedVN; final ValueEditor editor; if (canUseCachedArgs && (cachedVN = gemCutter.getTableTop().getCachedValue(inputPart)) != null) { // use cached sink value to generate the VEP // get a copy of the cached VN but with the new type expr ValueNode newVN = cachedVN.copyValueNode(); // instantiate the VEP with the new VN (which has the old cached value) editor = valueEditorDirector.getRootValueEditor( valueEditorHierarchyManager, newVN, scName, argumentNumber, new GemCutterMetadataRunner(gemCutter, inputGem)); } else { // don't use cached sink value. Generate the default VEP for this sink. TypeExpr inputType = specializedInputTypes[i]; editor = valueEditorDirector.getRootValueEditor( valueEditorHierarchyManager, inputType, scName, argumentNumber, new GemCutterMetadataRunner(gemCutter, inputGem)); } // If this is a value entry panel then set the name of the input for use in tooltips if (editor instanceof ValueEntryPanel) { ((ValueEntryPanel) editor) .setArgumentName(inputPart.getArgumentName().getCompositeName()); } // Position the editor next to the connection point. positionEditor(editor, inputPart); // Now add the editor to the table top. tableTopPanel.add(editor, 0); // Add to the list of active entry panels valueEditorHierarchyManager.addTopValueEditor(editor); // Update the context and editor map editor.setContext( new ValueEditorContext() { public TypeExpr getLeastConstrainedTypeExpr() { return inputPart.getType(); } }); inputToEditorMap.put(inputPart, editor); // If the editor resizes because it's value changes, make sure it stays aligned to the // connection editor.addComponentListener( new ComponentAdapter() { @Override public void componentResized(ComponentEvent e) { positionEditor((ValueEditor) e.getComponent(), inputPart); } }); } // Must prevent ValueGems from being editable. tableTopPanel.setValueGemsEnabled(false); // Need to activate the value editor hierarchy to ensure correct highlighting. valueEditorHierarchyManager.activateCurrentEditor(); // Set the context and type switch listener for each new editor. ArgumentValueCommitter argumentValueCommitter = new ArgumentValueCommitter(valueEditorManager, inputToEditorMap); for (final ValueEditor argumentEditor : getArgumentPanels()) { argumentEditor.addValueEditorListener(argumentValueCommitter); } // May need to show argument controls. if (numArgs > 0) { gemCutter.showArgumentControls(inputToEditorMap); gemCutter.getResetAction().setEnabled(true); } else { gemCutter.getResetAction().setEnabled(false); } }