/**
     * 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());
      }
    }
    /** {@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());
      }
    }
    /**
     * 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);
    }