From 19eafbf43ea726e11d31d298e16b8fefae18c972 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sat, 3 Dec 2022 22:22:08 +0100 Subject: [PATCH] Added DebugId tag proper display and editation --- CHANGELOG.md | 1 + .../decompiler/flash/tags/DebugIDTag.java | 2 + .../flash/types/annotations/UUID.java | 29 ++++ .../flash/gui/GenericTagTreePanel.java | 39 ++++- .../gui/generictageditors/UUIDEditor.java | 158 ++++++++++++++++++ 5 files changed, 224 insertions(+), 5 deletions(-) create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/annotations/UUID.java create mode 100644 src/com/jpexs/decompiler/flash/gui/generictageditors/UUIDEditor.java diff --git a/CHANGELOG.md b/CHANGELOG.md index c3c405e09..21c8ea5b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ All notable changes to this project will be documented in this file. - [#1884] Memory search - show size and adress in hex, show only aligned to N bytes - AS3 - "internal" keyword support - ProductInfo tag information display +- DebugId tag proper display and editation ### Fixed - [#1897] Close menu button without selecting specific item diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DebugIDTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DebugIDTag.java index a7bb6c516..c0d49f295 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DebugIDTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DebugIDTag.java @@ -22,6 +22,7 @@ import com.jpexs.decompiler.flash.SWFOutputStream; import com.jpexs.decompiler.flash.types.BasicType; import com.jpexs.decompiler.flash.types.annotations.SWFType; import com.jpexs.decompiler.flash.types.annotations.SWFVersion; +import com.jpexs.decompiler.flash.types.annotations.UUID; import com.jpexs.helpers.ByteArrayRange; import java.io.IOException; import java.util.logging.Level; @@ -39,6 +40,7 @@ public class DebugIDTag extends Tag { public static final String NAME = "DebugID"; @SWFType(value = BasicType.UI8, count = 16) + @UUID public byte[] debugId; /** diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/annotations/UUID.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/annotations/UUID.java new file mode 100644 index 000000000..31af606c2 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/annotations/UUID.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2010-2022 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ + +package com.jpexs.decompiler.flash.types.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface UUID { + +} diff --git a/src/com/jpexs/decompiler/flash/gui/GenericTagTreePanel.java b/src/com/jpexs/decompiler/flash/gui/GenericTagTreePanel.java index 5c8ac00d7..be76cd136 100644 --- a/src/com/jpexs/decompiler/flash/gui/GenericTagTreePanel.java +++ b/src/com/jpexs/decompiler/flash/gui/GenericTagTreePanel.java @@ -27,6 +27,7 @@ import com.jpexs.decompiler.flash.gui.generictageditors.FullSized; import com.jpexs.decompiler.flash.gui.generictageditors.GenericTagEditor; import com.jpexs.decompiler.flash.gui.generictageditors.NumberEditor; import com.jpexs.decompiler.flash.gui.generictageditors.StringEditor; +import com.jpexs.decompiler.flash.gui.generictageditors.UUIDEditor; import com.jpexs.decompiler.flash.gui.tagtree.AbstractTagTree; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.tags.base.ASMSource; @@ -50,6 +51,7 @@ import com.jpexs.decompiler.flash.types.annotations.Multiline; import com.jpexs.decompiler.flash.types.annotations.SWFArray; import com.jpexs.decompiler.flash.types.annotations.SWFType; import com.jpexs.decompiler.flash.types.annotations.Table; +import com.jpexs.decompiler.flash.types.annotations.UUID; import com.jpexs.decompiler.flash.types.annotations.parser.AnnotationParseException; import com.jpexs.decompiler.flash.types.annotations.parser.ConditionEvaluator; import com.jpexs.helpers.ByteArrayRange; @@ -300,9 +302,13 @@ public class GenericTagTreePanel extends GenericTagPanel { swfType = evalSwfType(model, parentPath, swfType); + UUID uuid = field.getAnnotation(UUID.class); + Multiline multiline = field.getAnnotation(Multiline.class); EnumValues enumValues = field.getAnnotation(EnumValues.class); - if (enumValues != null && (type.equals(int.class) || type.equals(Integer.class))) { + if (uuid != null) { + editor = new UUIDEditor(field.getName(), obj, field, index, type); + } else if (enumValues != null && (type.equals(int.class) || type.equals(Integer.class))) { Map values = new HashMap<>(); for (EnumValue enumValue : enumValues.value()) { values.put(enumValue.value(), enumValue.text()); @@ -727,7 +733,7 @@ public class GenericTagTreePanel extends GenericTagPanel { } return ret.toString(); } - + if (fieldSet.size() == 1) { ret.append(toString(0)); } else { @@ -747,7 +753,22 @@ public class GenericTagTreePanel extends GenericTagPanel { public String toString(int fieldIndex) { String valStr = ""; Field field = fieldSet.get(fieldIndex); - if (ReflectionTools.needsIndex(field) && (index == -1)) { + + if (field.getAnnotation(UUID.class) != null) { + StringBuilder sb = new StringBuilder(); + byte[] val = (byte[]) getValue(fieldIndex); + for(int i = 0; i < val.length; i++) { + String h = Integer.toHexString(val[i] & 0xff); + if (h.length() == 1) { + h = "0" + h; + } + sb.append(h); + if (i == 3 || i == 5 || i == 7 || i == 9) { + sb.append("-"); + } + } + valStr += " = " + sb.toString(); + } else if (ReflectionTools.needsIndex(field) && (index == -1)) { valStr += ""; } else if (hasEditor(obj, field, index)) { Object val = getValue(fieldIndex); @@ -787,6 +808,10 @@ public class GenericTagTreePanel extends GenericTagPanel { } public String getType(int fieldIndex) { + UUID uuid = fieldSet.get(fieldIndex).getAnnotation(UUID.class); + if (uuid != null) { + return "UUID"; + } SWFArray swfArray = fieldSet.get(fieldIndex).getAnnotation(SWFArray.class); Class declaredType = fieldSet.get(fieldIndex).getType(); boolean isArray = ReflectionTools.needsIndex(fieldSet.get(fieldIndex)) || swfArray != null; @@ -1214,8 +1239,12 @@ public class GenericTagTreePanel extends GenericTagPanel { type = val.getClass(); } catch (IllegalArgumentException | IllegalAccessException ex) { return false; - } - if (type.equals(int.class) || type.equals(Integer.class) + } + UUID uuid = field.getAnnotation(UUID.class); + + if (uuid != null) { + return true; + } else 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) diff --git a/src/com/jpexs/decompiler/flash/gui/generictageditors/UUIDEditor.java b/src/com/jpexs/decompiler/flash/gui/generictageditors/UUIDEditor.java new file mode 100644 index 000000000..f2e3b7e24 --- /dev/null +++ b/src/com/jpexs/decompiler/flash/gui/generictageditors/UUIDEditor.java @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2010-2022 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.gui.generictageditors; + +import com.jpexs.helpers.Helper; +import com.jpexs.helpers.ReflectionTools; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.lang.reflect.Field; +import javax.swing.JTextArea; +import javax.swing.JTextField; + +/** + * + * @author JPEXS + */ +public class UUIDEditor extends JTextField implements GenericTagEditor { + + private final Object obj; + + private final Field field; + + private final int index; + + private final Class type; + + private String fieldName; + + @Override + public boolean getScrollableTracksViewportWidth() { + return true; + } + + @Override + public Dimension getPreferredSize() { + Dimension ret = super.getPreferredSize(); + ret.width = 300; + return ret; + } + + @Override + public BaselineResizeBehavior getBaselineResizeBehavior() { + return Component.BaselineResizeBehavior.CONSTANT_ASCENT; + } + + @Override + public int getBaseline(int width, int height) { + return 0; + } + + public UUIDEditor(String fieldName, Object obj, Field field, int index, Class type) { + super(32+4); + this.obj = obj; + this.field = field; + this.index = index; + this.type = type; + this.fieldName = fieldName; + reset(); + } + + @Override + public void reset() { + try { + byte[] val = (byte[]) ReflectionTools.getValue(obj, field, index); + StringBuilder sb = new StringBuilder(); + for(int i = 0; i < val.length; i++) { + String h = Integer.toHexString(val[i] & 0xff); + if (h.length() == 1) { + h = "0" + h; + } + sb.append(h); + if (i == 3 || i == 5 || i == 7 || i == 9) { + sb.append("-"); + } + } + setText(sb.toString()); + } catch (IllegalArgumentException | IllegalAccessException ex) { + // ignore + } + } + + @Override + public void save() { + try { + String text = getText(); + text = text.replace("-", "").trim(); + if (!text.matches("[a-fA-F0-9]{32}")) { + return; + } + byte[] val = new byte[16]; + for (int i = 0; i < 16; i++) { + String ch = text.substring(i * 2, i * 2 + 2); + val[i] = (byte) Integer.parseInt(ch, 16); + } + ReflectionTools.setValue(obj, field, index, val); + } catch (IllegalAccessException ex) { + // ignore + } + } + + @Override + public void addChangeListener(final ChangeListener l) { + final GenericTagEditor t = this; + addFocusListener(new FocusAdapter() { + + @Override + public void focusLost(FocusEvent e) { + l.change(t); + } + + }); + } + + @Override + public Object getChangedValue() { + return getText(); + } + + @Override + public String getFieldName() { + return fieldName; + } + + @Override + public Field getField() { + return field; + } + + @Override + public String getReadOnlyValue() { + return Helper.escapeHTML(getChangedValue().toString()); + } + + @Override + public void added() { + + } + + @Override + public void validateValue() { + } +}