private void removeItem(Object obj, Field field, int index) { final JScrollBar sb = genericTagPropertiesEditPanelScrollPanel.getVerticalScrollBar(); final int val = sb.getValue(); // save scroll top SWFType swfType = field.getAnnotation(SWFType.class); if (swfType != null && !swfType .countField() .isEmpty()) { // Fields with same countField must be removed from too Field[] fields = obj.getClass().getDeclaredFields(); for (int f = 0; f < fields.length; f++) { SWFType fieldSwfType = fields[f].getAnnotation(SWFType.class); if (fieldSwfType != null && fieldSwfType.countField().equals(swfType.countField())) { ReflectionTools.removeFromField(obj, fields[f], index); } } try { // If countField exists, decrement, otherwise do nothing Field countField = obj.getClass().getDeclaredField(swfType.countField()); int cnt = countField.getInt(obj); cnt--; countField.setInt(obj, cnt); } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) { // ignored } } else { ReflectionTools.removeFromField(obj, field, index); } generateEditControls(editedTag, false); // Restore scroll top after some time. TODO: Handle this better. I don't know how :-(. new Thread() { @Override public void run() { try { Thread.sleep(500); } catch (InterruptedException ex) { logger.log(Level.SEVERE, null, ex); } View.execInEventDispatch( () -> { genericTagPropertiesEditPanelScrollPanel.getVerticalScrollBar().setValue(val); }); } }.start(); revalidate(); repaint(); }
public BinaryDataEditor( MainPanel mainPanel, String fieldName, Object obj, Field field, int index, Class<?> type) { super(); this.mainPanel = mainPanel; this.obj = obj; this.field = field; this.index = index; this.type = type; this.fieldName = fieldName; setText(AppStrings.translate("button.replace")); addActionListener(this::buttonActionPerformed); try { Object val = ReflectionTools.getValue(obj, field, index); if (val instanceof byte[]) { byte[] ba = (byte[]) val; setToolTipText(ba.length + " bytes"); } else if (val instanceof ByteArrayRange) { ByteArrayRange bar = (ByteArrayRange) val; setToolTipText(bar.getLength() + " bytes"); } value = val; } catch (IllegalArgumentException | IllegalAccessException ex) { // ignore } }
@Override public void save() { try { ReflectionTools.setValue(obj, field, index, value); } catch (IllegalArgumentException | IllegalAccessException ex) { // ignore } }
@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; }
private int generateEditControlsRecursive( final Object obj, String parent, List<Field> parentFields, List<Integer> parentIndices, boolean readonly) { if (obj == null) { return 0; } Field[] fields = obj.getClass().getDeclaredFields(); int propCount = 0; for (final Field field : fields) { try { if (Modifier.isStatic(field.getModifiers())) { continue; } field.setAccessible(true); String name = parent + field.getName(); final Object value = field.get(obj); if (List.class.isAssignableFrom(field.getType())) { if (value != null) { int i = 0; for (Object obj1 : (Iterable) value) { final String subname = name + "[" + i + "]"; propCount += addEditor( subname, obj, field, i, obj1.getClass(), obj1, parentFields, parentIndices, readonly); final int fi = i; i++; JButton removeButton = new JButton(View.getIcon("close16")); removeButton.addActionListener( new ActionListener() { @Override public void actionPerformed(ActionEvent e) { removeItem(obj, field, fi); } }); removeButtons.put(subname, removeButton); } } } else if (field.getType().isArray()) { if (value != null) { for (int i = 0; i < Array.getLength(value); i++) { Object item = Array.get(value, i); String subname = name + "[" + i + "]"; propCount += addEditor( subname, obj, field, i, item.getClass(), item, parentFields, parentIndices, readonly); final int fi = i; JButton removeButton = new JButton(View.getIcon("close16")); removeButton.addActionListener( new ActionListener() { @Override public void actionPerformed(ActionEvent e) { removeItem(obj, field, fi); } }); removeButtons.put(subname, removeButton); } } } else { propCount += addEditor( name, obj, field, 0, field.getType(), value, parentFields, parentIndices, readonly); } if (ReflectionTools.needsIndex(field) && !readonly && !field.getName().equals("clipActionRecords")) { // No clip actions, sorry JButton addButton = new JButton(View.getIcon("add16")); addButton.addActionListener( new ActionListener() { @Override public void actionPerformed(ActionEvent e) { addItem(obj, field); } }); name += "[]"; List<Field> parList = new ArrayList<>(parentFields); parList.add(field); fieldPaths.put(name, parList); List<Integer> parIndices = new ArrayList<>(parentIndices); parIndices.add(0); fieldIndices.put(name, parIndices); addRow(name, addButton, field); addKeys.add(name); addButtons.put(name, addButton); } } catch (IllegalArgumentException | IllegalAccessException ex) { logger.log(Level.SEVERE, null, ex); } } return propCount; }