private void setTagText(Tag tag) {
   clear();
   generateEditControls(tag, true);
   StringBuilder val = new StringBuilder();
   for (String key : keys) {
     GenericTagEditor ed = editors.get(key);
     if (((Component) ed).isVisible()) {
       val.append(key).append(" : ").append(ed.getReadOnlyValue()).append("<br>");
     }
   }
   // HTML for colors:
   val.insert(0, "<html>").append("</html>");
   genericTagPropertiesEditorPane.setContentType("text/html");
   genericTagPropertiesEditorPane.setText(val.toString());
   genericTagPropertiesEditorPane.setCaretPosition(0);
   hdr.setText(tag.toString());
 }
 public boolean save() {
   for (Object component : genericTagPropertiesEditPanel.getComponents()) {
     if (component instanceof GenericTagEditor) {
       try {
         ((GenericTagEditor) component).validateValue();
         ((GenericTagEditor) component).save();
       } catch (IllegalArgumentException iex) {
         return false;
       }
     }
   }
   SWF swf = tag.getSwf();
   assignTag(tag, editedTag);
   tag.setModified(true);
   tag.setSwf(swf);
   setTagText(tag);
   return true;
 }
  @Override
  public void change(GenericTagEditor ed) {
    for (String key : editors.keySet()) {
      GenericTagEditor dependentEditor = editors.get(key);
      Component dependentLabel = labels.get(key);
      Component dependentTypeLabel = types.get(key);
      List<Field> path = fieldPaths.get(key);
      List<Integer> indices = fieldIndices.get(key);
      String p = "";
      boolean conditionMet = true;
      for (int i = 0; i < path.size(); i++) {
        Field f = path.get(i);
        int index = indices.get(i);
        String par = p;
        if (!p.isEmpty()) {
          p += ".";
        }
        p += f.getName();
        if (ReflectionTools.needsIndex(f)) {
          p += "[" + index + "]";
        }
        Conditional cond = f.getAnnotation(Conditional.class);
        if (cond != null) {
          ConditionEvaluator ev = new ConditionEvaluator(cond);

          try {
            Set<String> fieldNames = ev.getFields();
            Map<String, Boolean> fields = new HashMap<>();
            for (String fld : fieldNames) {
              String ckey = "";
              if (!par.isEmpty()) {
                ckey = par + ".";
              }
              ckey += fld;
              if (editors.containsKey(ckey)) {
                GenericTagEditor editor = editors.get(ckey);
                Object val = editor.getChangedValue();
                fields.put(fld, true);
                if (val instanceof Boolean) {
                  fields.put(fld, (Boolean) val);
                }
              }
            }
            boolean ok = ev.eval(fields);
            if (conditionMet) {
              conditionMet = ok;
            }
            ((Component) dependentEditor).setVisible(conditionMet);
            dependentLabel.setVisible(conditionMet);
            dependentTypeLabel.setVisible(conditionMet);
          } catch (AnnotationParseException ex) {
            logger.log(Level.SEVERE, "Invalid condition", ex);
          }
        }
        if (!conditionMet) {
          break;
        }
      }
    }
    genericTagPropertiesEditPanel.removeAll();
    genericTagPropertiesEditPanel.setSize(0, 0);
    int propCount = 0;
    for (String key : keys) {

      Component dependentEditor;
      if (addKeys.contains(key)) {
        dependentEditor = addButtons.get(key);
      } else if (removeButtons.containsKey(key)) { // It's array/list, add remove button
        JPanel editRemPanel = new JPanel(new BorderLayout());
        editRemPanel.add((Component) editors.get(key), BorderLayout.CENTER);
        editRemPanel.add(removeButtons.get(key), BorderLayout.EAST);
        dependentEditor = editRemPanel;
      } else {
        dependentEditor = (Component) editors.get(key);
      }
      Component dependentLabel = labels.get(key);
      Component dependentTypeLabel = types.get(key);
      if (dependentEditor.isVisible()) {
        genericTagPropertiesEditPanel.add(dependentLabel);
        genericTagPropertiesEditPanel.add(((Component) dependentEditor));
        genericTagPropertiesEditPanel.add(dependentTypeLabel);
        propCount++;
      }
    }
    /*genericTagPropertiesEditPanel.add(new JPanel());
    genericTagPropertiesEditPanel.add(new JPanel());
    genericTagPropertiesEditPanel.add(new JPanel());*/
    relayout(propCount /*+ 1*/);
  }
  private int addEditor(
      String name,
      Object obj,
      Field field,
      int index,
      Class<?> type,
      Object value,
      List<Field> parentList,
      List<Integer> parentIndices,
      boolean readonly)
      throws IllegalArgumentException, IllegalAccessException {
    Calculated calculated = field.getAnnotation(Calculated.class);
    if (calculated != null) {
      return 0;
    }
    List<Field> parList = new ArrayList<>(parentList);
    parList.add(field);

    List<Integer> parIndices = new ArrayList<>(parentIndices);
    parIndices.add(index);
    Internal inter = field.getAnnotation(Internal.class);
    if (inter != null) {
      return 0;
    }
    SWFType swfType = field.getAnnotation(SWFType.class);
    Multiline multiline = field.getAnnotation(Multiline.class);
    Component editor;
    if (type.equals(int.class)
        || type.equals(Integer.class)
        || type.equals(short.class)
        || type.equals(Short.class)
        || type.equals(long.class)
        || type.equals(Long.class)
        || type.equals(double.class)
        || type.equals(Double.class)
        || type.equals(float.class)
        || type.equals(Float.class)) {
      editor = new NumberEditor(name, obj, field, index, type, swfType);
    } else if (type.equals(boolean.class) || type.equals(Boolean.class)) {
      editor = new BooleanEditor(name, obj, field, index, type);
    } else if (type.equals(String.class)) {
      editor = new StringEditor(name, obj, field, index, type, multiline != null);
    } else if (type.equals(RGB.class) || type.equals(RGBA.class) || type.equals(ARGB.class)) {
      editor = new ColorEditor(name, obj, field, index, type);
    } else if (type.equals(ByteArrayRange.class)) {
      editor = new BinaryDataEditor(mainPanel, name, obj, field, index, type);
    } else if (type.equals(Amf3Value.class)) {
      editor = new Amf3ValueEditor(name, obj, field, index, type);
    } else {
      if (value == null) {
        if (readonly) {
          return 0;
        }
        Optional opt = field.getAnnotation(Optional.class);
        if (opt == null) {
          try {
            value = ReflectionTools.newInstanceOf(field.getType());
            field.set(obj, value);
          } catch (InstantiationException | IllegalAccessException ex) {
            logger.log(Level.SEVERE, null, ex);
            return 0;
          }
        } else {
          return 0;
        }
      }
      return generateEditControlsRecursive(value, name + ".", parList, parIndices, readonly);
    }
    if (editor instanceof GenericTagEditor) {
      GenericTagEditor ce = (GenericTagEditor) editor;
      ce.addChangeListener(this);
      editors.put(name, ce);
      fieldPaths.put(name, parList);
      fieldIndices.put(name, parIndices);
      addRow(name, editor, field);

      ce.added();
    }
    return 1;
  }