コード例 #1
0
    /**
     * 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);
      }
    }