diff --git a/CHANGELOG.md b/CHANGELOG.md
index dccad437a..e06d8ab23 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -22,6 +22,7 @@ All notable changes to this project will be documented in this file.
- Option to enter custom zoom level by clicking on zoom percentage label
- Show in Simple editor context menu item for timelined items (sprites, buttons, swfs)
- Simple editor - change background color
+- Simple editor - filters (read only yet)
### Fixed
- [#2424] DefineEditText handling of letterSpacing, font size on incorrect values
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/BEVELFILTER.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/BEVELFILTER.java
index 4751a36f1..51053fc96 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/BEVELFILTER.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/BEVELFILTER.java
@@ -22,6 +22,7 @@ import com.jpexs.decompiler.flash.types.RGBA;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.helpers.SerializableImage;
import java.awt.Color;
+import java.util.Objects;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@@ -253,4 +254,72 @@ public class BEVELFILTER extends FILTER {
}
return result;
}
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 47 * hash + Objects.hashCode(this.shadowColor);
+ hash = 47 * hash + Objects.hashCode(this.highlightColor);
+ hash = 47 * hash + (int) (Double.doubleToLongBits(this.blurX) ^ (Double.doubleToLongBits(this.blurX) >>> 32));
+ hash = 47 * hash + (int) (Double.doubleToLongBits(this.blurY) ^ (Double.doubleToLongBits(this.blurY) >>> 32));
+ hash = 47 * hash + (int) (Double.doubleToLongBits(this.angle) ^ (Double.doubleToLongBits(this.angle) >>> 32));
+ hash = 47 * hash + (int) (Double.doubleToLongBits(this.distance) ^ (Double.doubleToLongBits(this.distance) >>> 32));
+ hash = 47 * hash + Float.floatToIntBits(this.strength);
+ hash = 47 * hash + (this.innerShadow ? 1 : 0);
+ hash = 47 * hash + (this.knockout ? 1 : 0);
+ hash = 47 * hash + (this.compositeSource ? 1 : 0);
+ hash = 47 * hash + (this.onTop ? 1 : 0);
+ hash = 47 * hash + this.passes;
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final BEVELFILTER other = (BEVELFILTER) obj;
+ if (Double.doubleToLongBits(this.blurX) != Double.doubleToLongBits(other.blurX)) {
+ return false;
+ }
+ if (Double.doubleToLongBits(this.blurY) != Double.doubleToLongBits(other.blurY)) {
+ return false;
+ }
+ if (Double.doubleToLongBits(this.angle) != Double.doubleToLongBits(other.angle)) {
+ return false;
+ }
+ if (Double.doubleToLongBits(this.distance) != Double.doubleToLongBits(other.distance)) {
+ return false;
+ }
+ if (Float.floatToIntBits(this.strength) != Float.floatToIntBits(other.strength)) {
+ return false;
+ }
+ if (this.innerShadow != other.innerShadow) {
+ return false;
+ }
+ if (this.knockout != other.knockout) {
+ return false;
+ }
+ if (this.compositeSource != other.compositeSource) {
+ return false;
+ }
+ if (this.onTop != other.onTop) {
+ return false;
+ }
+ if (this.passes != other.passes) {
+ return false;
+ }
+ if (!Objects.equals(this.shadowColor, other.shadowColor)) {
+ return false;
+ }
+ return Objects.equals(this.highlightColor, other.highlightColor);
+ }
+
+
}
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/BLURFILTER.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/BLURFILTER.java
index 76844450a..a946c812c 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/BLURFILTER.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/BLURFILTER.java
@@ -82,4 +82,40 @@ public class BLURFILTER extends FILTER {
public String toSvg(Document document, Element filtersElement, SVGExporter exporter, String in) {
return blurSvg(blurX, blurY, passes, document, filtersElement, exporter, in);
}
+
+ @Override
+ public int hashCode() {
+ int hash = 3;
+ hash = 37 * hash + (int) (Double.doubleToLongBits(this.blurX) ^ (Double.doubleToLongBits(this.blurX) >>> 32));
+ hash = 37 * hash + (int) (Double.doubleToLongBits(this.blurY) ^ (Double.doubleToLongBits(this.blurY) >>> 32));
+ hash = 37 * hash + this.passes;
+ hash = 37 * hash + this.reserved;
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final BLURFILTER other = (BLURFILTER) obj;
+ if (Double.doubleToLongBits(this.blurX) != Double.doubleToLongBits(other.blurX)) {
+ return false;
+ }
+ if (Double.doubleToLongBits(this.blurY) != Double.doubleToLongBits(other.blurY)) {
+ return false;
+ }
+ if (this.passes != other.passes) {
+ return false;
+ }
+ return this.reserved == other.reserved;
+ }
+
+
}
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/COLORMATRIXFILTER.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/COLORMATRIXFILTER.java
index 339932815..2a000d826 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/COLORMATRIXFILTER.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/COLORMATRIXFILTER.java
@@ -22,6 +22,7 @@ import com.jpexs.decompiler.flash.types.annotations.SWFArray;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.helpers.SerializableImage;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@@ -96,4 +97,27 @@ public class COLORMATRIXFILTER extends FILTER {
return result;
}
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 67 * hash + Arrays.hashCode(this.matrix);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final COLORMATRIXFILTER other = (COLORMATRIXFILTER) obj;
+ return Arrays.equals(this.matrix, other.matrix);
+ }
+
+
}
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/CONVOLUTIONFILTER.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/CONVOLUTIONFILTER.java
index 5b50a43ec..52ed841fc 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/CONVOLUTIONFILTER.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/CONVOLUTIONFILTER.java
@@ -23,7 +23,9 @@ import com.jpexs.decompiler.flash.types.annotations.Reserved;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.helpers.SerializableImage;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@@ -138,4 +140,60 @@ public class CONVOLUTIONFILTER extends FILTER {
return result;
}
+
+ @Override
+ public int hashCode() {
+ int hash = 3;
+ hash = 53 * hash + this.matrixX;
+ hash = 53 * hash + this.matrixY;
+ hash = 53 * hash + Float.floatToIntBits(this.divisor);
+ hash = 53 * hash + Float.floatToIntBits(this.bias);
+ hash = 53 * hash + Arrays.hashCode(this.matrix);
+ hash = 53 * hash + Objects.hashCode(this.defaultColor);
+ hash = 53 * hash + this.reserved;
+ hash = 53 * hash + (this.clamp ? 1 : 0);
+ hash = 53 * hash + (this.preserveAlpha ? 1 : 0);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final CONVOLUTIONFILTER other = (CONVOLUTIONFILTER) obj;
+ if (this.matrixX != other.matrixX) {
+ return false;
+ }
+ if (this.matrixY != other.matrixY) {
+ return false;
+ }
+ if (Float.floatToIntBits(this.divisor) != Float.floatToIntBits(other.divisor)) {
+ return false;
+ }
+ if (Float.floatToIntBits(this.bias) != Float.floatToIntBits(other.bias)) {
+ return false;
+ }
+ if (this.reserved != other.reserved) {
+ return false;
+ }
+ if (this.clamp != other.clamp) {
+ return false;
+ }
+ if (this.preserveAlpha != other.preserveAlpha) {
+ return false;
+ }
+ if (!Arrays.equals(this.matrix, other.matrix)) {
+ return false;
+ }
+ return Objects.equals(this.defaultColor, other.defaultColor);
+ }
+
+
}
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/DROPSHADOWFILTER.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/DROPSHADOWFILTER.java
index b4951e890..a58ed13e9 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/DROPSHADOWFILTER.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/DROPSHADOWFILTER.java
@@ -22,6 +22,7 @@ import com.jpexs.decompiler.flash.types.RGBA;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.helpers.SerializableImage;
import java.awt.Color;
+import java.util.Objects;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@@ -114,4 +115,64 @@ public class DROPSHADOWFILTER extends FILTER {
public String toSvg(Document document, Element filtersElement, SVGExporter exporter, String in) {
return dropShadowSvg(distance, angle, dropShadowColor, innerShadow, knockout, compositeSource, blurX, blurY, strength, passes, document, filtersElement, exporter, in);
}
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 97 * hash + Objects.hashCode(this.dropShadowColor);
+ hash = 97 * hash + (int) (Double.doubleToLongBits(this.blurX) ^ (Double.doubleToLongBits(this.blurX) >>> 32));
+ hash = 97 * hash + (int) (Double.doubleToLongBits(this.blurY) ^ (Double.doubleToLongBits(this.blurY) >>> 32));
+ hash = 97 * hash + (int) (Double.doubleToLongBits(this.angle) ^ (Double.doubleToLongBits(this.angle) >>> 32));
+ hash = 97 * hash + (int) (Double.doubleToLongBits(this.distance) ^ (Double.doubleToLongBits(this.distance) >>> 32));
+ hash = 97 * hash + Float.floatToIntBits(this.strength);
+ hash = 97 * hash + (this.innerShadow ? 1 : 0);
+ hash = 97 * hash + (this.knockout ? 1 : 0);
+ hash = 97 * hash + (this.compositeSource ? 1 : 0);
+ hash = 97 * hash + this.passes;
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final DROPSHADOWFILTER other = (DROPSHADOWFILTER) obj;
+ if (Double.doubleToLongBits(this.blurX) != Double.doubleToLongBits(other.blurX)) {
+ return false;
+ }
+ if (Double.doubleToLongBits(this.blurY) != Double.doubleToLongBits(other.blurY)) {
+ return false;
+ }
+ if (Double.doubleToLongBits(this.angle) != Double.doubleToLongBits(other.angle)) {
+ return false;
+ }
+ if (Double.doubleToLongBits(this.distance) != Double.doubleToLongBits(other.distance)) {
+ return false;
+ }
+ if (Float.floatToIntBits(this.strength) != Float.floatToIntBits(other.strength)) {
+ return false;
+ }
+ if (this.innerShadow != other.innerShadow) {
+ return false;
+ }
+ if (this.knockout != other.knockout) {
+ return false;
+ }
+ if (this.compositeSource != other.compositeSource) {
+ return false;
+ }
+ if (this.passes != other.passes) {
+ return false;
+ }
+ return Objects.equals(this.dropShadowColor, other.dropShadowColor);
+ }
+
+
}
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/GLOWFILTER.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/GLOWFILTER.java
index ef7d88147..93210e6d1 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/GLOWFILTER.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/GLOWFILTER.java
@@ -22,6 +22,7 @@ import com.jpexs.decompiler.flash.types.RGBA;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.helpers.SerializableImage;
import java.awt.Color;
+import java.util.Objects;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@@ -196,4 +197,56 @@ public class GLOWFILTER extends FILTER {
return feCompositeResult;
}
}
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 89 * hash + Objects.hashCode(this.glowColor);
+ hash = 89 * hash + (int) (Double.doubleToLongBits(this.blurX) ^ (Double.doubleToLongBits(this.blurX) >>> 32));
+ hash = 89 * hash + (int) (Double.doubleToLongBits(this.blurY) ^ (Double.doubleToLongBits(this.blurY) >>> 32));
+ hash = 89 * hash + Float.floatToIntBits(this.strength);
+ hash = 89 * hash + (this.innerGlow ? 1 : 0);
+ hash = 89 * hash + (this.knockout ? 1 : 0);
+ hash = 89 * hash + (this.compositeSource ? 1 : 0);
+ hash = 89 * hash + this.passes;
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final GLOWFILTER other = (GLOWFILTER) obj;
+ if (Double.doubleToLongBits(this.blurX) != Double.doubleToLongBits(other.blurX)) {
+ return false;
+ }
+ if (Double.doubleToLongBits(this.blurY) != Double.doubleToLongBits(other.blurY)) {
+ return false;
+ }
+ if (Float.floatToIntBits(this.strength) != Float.floatToIntBits(other.strength)) {
+ return false;
+ }
+ if (this.innerGlow != other.innerGlow) {
+ return false;
+ }
+ if (this.knockout != other.knockout) {
+ return false;
+ }
+ if (this.compositeSource != other.compositeSource) {
+ return false;
+ }
+ if (this.passes != other.passes) {
+ return false;
+ }
+ return Objects.equals(this.glowColor, other.glowColor);
+ }
+
+
}
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/GRADIENTBEVELFILTER.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/GRADIENTBEVELFILTER.java
index 33c510238..7a969f71d 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/GRADIENTBEVELFILTER.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/GRADIENTBEVELFILTER.java
@@ -24,6 +24,7 @@ import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.helpers.SerializableImage;
import java.awt.Color;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@@ -155,4 +156,72 @@ public class GRADIENTBEVELFILTER extends FILTER {
public String toSvg(Document document, Element filtersElement, SVGExporter exporter, String in) {
return null; //NOT SUPPORTED
}
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 37 * hash + Arrays.deepHashCode(this.gradientColors);
+ hash = 37 * hash + Arrays.hashCode(this.gradientRatio);
+ hash = 37 * hash + (int) (Double.doubleToLongBits(this.blurX) ^ (Double.doubleToLongBits(this.blurX) >>> 32));
+ hash = 37 * hash + (int) (Double.doubleToLongBits(this.blurY) ^ (Double.doubleToLongBits(this.blurY) >>> 32));
+ hash = 37 * hash + (int) (Double.doubleToLongBits(this.angle) ^ (Double.doubleToLongBits(this.angle) >>> 32));
+ hash = 37 * hash + (int) (Double.doubleToLongBits(this.distance) ^ (Double.doubleToLongBits(this.distance) >>> 32));
+ hash = 37 * hash + Float.floatToIntBits(this.strength);
+ hash = 37 * hash + (this.innerShadow ? 1 : 0);
+ hash = 37 * hash + (this.knockout ? 1 : 0);
+ hash = 37 * hash + (this.compositeSource ? 1 : 0);
+ hash = 37 * hash + (this.onTop ? 1 : 0);
+ hash = 37 * hash + this.passes;
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final GRADIENTBEVELFILTER other = (GRADIENTBEVELFILTER) obj;
+ if (Double.doubleToLongBits(this.blurX) != Double.doubleToLongBits(other.blurX)) {
+ return false;
+ }
+ if (Double.doubleToLongBits(this.blurY) != Double.doubleToLongBits(other.blurY)) {
+ return false;
+ }
+ if (Double.doubleToLongBits(this.angle) != Double.doubleToLongBits(other.angle)) {
+ return false;
+ }
+ if (Double.doubleToLongBits(this.distance) != Double.doubleToLongBits(other.distance)) {
+ return false;
+ }
+ if (Float.floatToIntBits(this.strength) != Float.floatToIntBits(other.strength)) {
+ return false;
+ }
+ if (this.innerShadow != other.innerShadow) {
+ return false;
+ }
+ if (this.knockout != other.knockout) {
+ return false;
+ }
+ if (this.compositeSource != other.compositeSource) {
+ return false;
+ }
+ if (this.onTop != other.onTop) {
+ return false;
+ }
+ if (this.passes != other.passes) {
+ return false;
+ }
+ if (!Arrays.deepEquals(this.gradientColors, other.gradientColors)) {
+ return false;
+ }
+ return Arrays.equals(this.gradientRatio, other.gradientRatio);
+ }
+
+
}
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/GRADIENTGLOWFILTER.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/GRADIENTGLOWFILTER.java
index b3d867939..a8e60d103 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/GRADIENTGLOWFILTER.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/GRADIENTGLOWFILTER.java
@@ -24,6 +24,7 @@ import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.helpers.SerializableImage;
import java.awt.Color;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@@ -155,4 +156,72 @@ public class GRADIENTGLOWFILTER extends FILTER {
public String toSvg(Document document, Element filtersElement, SVGExporter exporter, String in) {
return null; //NOT SUPPORTED
}
+
+ @Override
+ public int hashCode() {
+ int hash = 5;
+ hash = 67 * hash + Arrays.deepHashCode(this.gradientColors);
+ hash = 67 * hash + Arrays.hashCode(this.gradientRatio);
+ hash = 67 * hash + (int) (Double.doubleToLongBits(this.blurX) ^ (Double.doubleToLongBits(this.blurX) >>> 32));
+ hash = 67 * hash + (int) (Double.doubleToLongBits(this.blurY) ^ (Double.doubleToLongBits(this.blurY) >>> 32));
+ hash = 67 * hash + (int) (Double.doubleToLongBits(this.angle) ^ (Double.doubleToLongBits(this.angle) >>> 32));
+ hash = 67 * hash + (int) (Double.doubleToLongBits(this.distance) ^ (Double.doubleToLongBits(this.distance) >>> 32));
+ hash = 67 * hash + Float.floatToIntBits(this.strength);
+ hash = 67 * hash + (this.innerShadow ? 1 : 0);
+ hash = 67 * hash + (this.knockout ? 1 : 0);
+ hash = 67 * hash + (this.compositeSource ? 1 : 0);
+ hash = 67 * hash + (this.onTop ? 1 : 0);
+ hash = 67 * hash + this.passes;
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final GRADIENTGLOWFILTER other = (GRADIENTGLOWFILTER) obj;
+ if (Double.doubleToLongBits(this.blurX) != Double.doubleToLongBits(other.blurX)) {
+ return false;
+ }
+ if (Double.doubleToLongBits(this.blurY) != Double.doubleToLongBits(other.blurY)) {
+ return false;
+ }
+ if (Double.doubleToLongBits(this.angle) != Double.doubleToLongBits(other.angle)) {
+ return false;
+ }
+ if (Double.doubleToLongBits(this.distance) != Double.doubleToLongBits(other.distance)) {
+ return false;
+ }
+ if (Float.floatToIntBits(this.strength) != Float.floatToIntBits(other.strength)) {
+ return false;
+ }
+ if (this.innerShadow != other.innerShadow) {
+ return false;
+ }
+ if (this.knockout != other.knockout) {
+ return false;
+ }
+ if (this.compositeSource != other.compositeSource) {
+ return false;
+ }
+ if (this.onTop != other.onTop) {
+ return false;
+ }
+ if (this.passes != other.passes) {
+ return false;
+ }
+ if (!Arrays.deepEquals(this.gradientColors, other.gradientColors)) {
+ return false;
+ }
+ return Arrays.equals(this.gradientRatio, other.gradientRatio);
+ }
+
+
}
diff --git a/src/com/jpexs/decompiler/flash/easygui/FiltersTreeTable.java b/src/com/jpexs/decompiler/flash/easygui/FiltersTreeTable.java
new file mode 100644
index 000000000..4e6648069
--- /dev/null
+++ b/src/com/jpexs/decompiler/flash/easygui/FiltersTreeTable.java
@@ -0,0 +1,376 @@
+/*
+ * Copyright (C) 2024 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.easygui;
+
+import com.jpexs.decompiler.flash.ecma.EcmaNumberToString;
+import com.jpexs.decompiler.flash.gui.View;
+import com.jpexs.decompiler.flash.types.RGB;
+import com.jpexs.decompiler.flash.types.RGBA;
+import com.jpexs.decompiler.flash.types.filters.FILTER;
+import de.javagl.treetable.JTreeTable;
+import de.javagl.treetable.TreeTableModel;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.util.List;
+import javax.swing.JLabel;
+import javax.swing.JTable;
+import javax.swing.JTree;
+import javax.swing.ListSelectionModel;
+import javax.swing.SwingUtilities;
+import javax.swing.event.TreeModelListener;
+import javax.swing.plaf.basic.BasicTableUI;
+import javax.swing.table.TableColumn;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeCellRenderer;
+import javax.swing.tree.TreePath;
+
+/**
+ *
+ * @author JPEXS
+ */
+public class FiltersTreeTable extends JTreeTable {
+
+ public FiltersTreeTable() {
+ super(new FiltersTreeTableModel(null));
+ getTree().setCellRenderer(new FiltersTreeCellRenderer());
+ getTree().setRootVisible(false);
+ getTree().setShowsRootHandles(true);
+ addKeyListener(new KeyAdapter() {
+ @Override
+ public void keyPressed(KeyEvent e) {
+ int selectedRow = getSelectedRow();
+ JTree tree = getTree();
+
+ if (e.getKeyCode() == KeyEvent.VK_LEFT) {
+ TreePath path = tree.getPathForRow(selectedRow);
+ if (path != null && tree.isExpanded(path)) {
+ tree.collapsePath(path);
+
+ int parentRow = tree.getRowForPath(path);
+ changeSelection(parentRow, 0, false, false);
+ } else if (path != null) {
+ TreePath parentPath = path.getParentPath();
+ if (parentPath != null) {
+ int parentRow = tree.getRowForPath(parentPath);
+ changeSelection(parentRow, 0, false, false);
+ }
+ }
+ e.consume();
+ }
+
+ if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
+ TreePath path = tree.getPathForRow(selectedRow);
+ if (path != null && !tree.isExpanded(path)) {
+ tree.expandPath(path);
+ int parentRow = tree.getRowForPath(path);
+ changeSelection(parentRow, 0, false, false);
+ } else {
+ TreePath childPath = tree.getPathForRow(selectedRow + 1);
+ if (childPath != null) {
+ int childRow = tree.getRowForPath(childPath);
+ changeSelection(childRow, 0, false, false);
+ }
+ }
+ e.consume();
+ }
+ }
+ });
+ setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ setUI(new BasicTableUI());
+
+ setRowHeight(18);
+ getTree().setRowHeight(18);
+
+ if (View.isOceanic()) {
+ setBackground(Color.WHITE);
+ getTree().setBackground(Color.WHITE);
+ }
+
+ addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() == 2) {
+ int selectedRow = getSelectedRow();
+ if (selectedRow == -1) {
+ return;
+ }
+ DefaultMutableTreeNode node = (DefaultMutableTreeNode) getValueAt(selectedRow, 0);
+ Object obj = node.getUserObject();
+
+ }
+ }
+ });
+
+ getTableHeader().setReorderingAllowed(false);
+ }
+
+ public void setFilters(List filters) {
+ setTreeTableModel(new FiltersTreeTableModel(filters));
+
+ getColumnModel().getColumn(0).setMinWidth(200);
+ getColumnModel().getColumn(0).setWidth(200);
+ getColumnModel().getColumn(0).setPreferredWidth(200);
+ getColumnModel().getColumn(1).setPreferredWidth(Integer.MAX_VALUE);
+ }
+
+ private static class FiltersTreeCellRenderer extends DefaultTreeCellRenderer {
+
+ @Override
+ public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
+ JLabel label = (JLabel) super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
+ if (value instanceof DefaultMutableTreeNode) {
+ DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
+ Object object = node.getUserObject();
+ label.setText(object.toString());
+ }
+ if (View.isOceanic()) {
+ if (selected) {
+ label.setBackground(getBackgroundSelectionColor());
+ } else {
+ label.setBackground(Color.white);
+ }
+ label.setOpaque(true);
+ }
+ return label;
+ }
+ }
+
+ private static class LibraryFolder {
+
+ private String name;
+
+ public LibraryFolder(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String toString() {
+ return EasyStrings.translate("library.folder." + name);
+ }
+
+ public String getName() {
+ return name;
+ }
+ }
+
+ private static class FilterField {
+
+ private final FILTER filter;
+ private final Field field;
+
+ public FilterField(FILTER filter, Field property) {
+ this.filter = filter;
+ this.field = property;
+ }
+
+ public FILTER getFilter() {
+ return filter;
+ }
+
+ public Field getField() {
+ return field;
+ }
+
+ public Object getValue() {
+ try {
+ return field.get(filter);
+ } catch (IllegalArgumentException | IllegalAccessException ex) {
+ return null;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return field.getName();
+ }
+
+ }
+
+ private static class FiltersTreeTableModel implements TreeTableModel {
+
+ private final DefaultMutableTreeNode root;
+
+ public FiltersTreeTableModel(List filters) {
+ root = new DefaultMutableTreeNode("root");
+
+ if (filters == null) {
+ DefaultMutableTreeNode indeterminate = new DefaultMutableTreeNode(EasyStrings.translate("properties.instance.filters.indeterminate"));
+ root.add(indeterminate);
+ return;
+ }
+
+ for (FILTER filter : filters) {
+ DefaultMutableTreeNode filterNode = new DefaultMutableTreeNode(filter.getClass().getSimpleName());
+ root.add(filterNode);
+ Field[] fields = filter.getClass().getFields();
+ for (Field field : fields) {
+ if ("id".equals(field.getName())) {
+ continue;
+ }
+ FilterField filterField = new FilterField(filter, field);
+ DefaultMutableTreeNode fieldNode = new DefaultMutableTreeNode(filterField);
+ filterNode.add(fieldNode);
+ }
+ }
+ }
+
+ @Override
+ public int getColumnCount() {
+ return 2;
+ }
+
+ @Override
+ public String getColumnName(int column) {
+ switch (column) {
+ case 0:
+ return EasyStrings.translate("properties.instance.filters.header.property");
+ case 1:
+ return EasyStrings.translate("properties.instance.filters.header.value");
+ default:
+ return null;
+ }
+ }
+
+ @Override
+ public Class> getColumnClass(int column) {
+ switch (column) {
+ case 0:
+ return TreeTableModel.class;
+ default:
+ return String.class;
+ }
+
+ }
+
+ private String valueToString(String fieldName, Object value) {
+ if (value == null) {
+ return "null";
+ }
+
+ if (value.getClass().isArray()) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("[");
+ int length = Array.getLength(value);
+ for (int i = 0; i < length; i++) {
+ Object element = Array.get(value, i);
+ sb.append(valueToString(fieldName, element));
+ if (i < length - 1) {
+ sb.append(", ");
+ }
+ }
+ sb.append("]");
+ return sb.toString();
+ }
+ if (value.getClass() == RGBA.class) {
+ RGBA rgb = (RGBA) value;
+ return rgb.toHexARGB();
+ }
+ if (value.getClass() == RGB.class) {
+ RGB rgb = (RGB) value;
+ return rgb.toHexRGB();
+ }
+
+ if (fieldName.equals("angle")) {
+ return "" + EcmaNumberToString.stringFor(Math.round(Math.toDegrees((double) value) * 100) / 100.0);
+ }
+ if (value.getClass() == Double.class) {
+ return EcmaNumberToString.stringFor((Double) value);
+ }
+ if (value.getClass() == Float.class) {
+ return EcmaNumberToString.stringFor((Float) value);
+ }
+ return "" + value;
+ }
+
+ @Override
+ public Object getValueAt(Object node, int column) {
+ DefaultMutableTreeNode n = (DefaultMutableTreeNode) node;
+ Object o = n.getUserObject();
+ switch (column) {
+ case 0:
+ return node;
+ case 1:
+ if (o instanceof FilterField) {
+ FilterField filterField = (FilterField) o;
+ return valueToString(filterField.field.getName(), filterField.getValue());
+ } else {
+ return "";
+ }
+ default:
+ return null;
+ }
+ }
+
+ @Override
+ public boolean isCellEditable(Object node, int column) {
+ if (column == 0) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void setValueAt(Object value, Object node, int column) {
+
+ }
+
+ @Override
+ public Object getRoot() {
+ return root;
+ }
+
+ @Override
+ public Object getChild(Object parent, int index) {
+ return ((DefaultMutableTreeNode) parent).getChildAt(index);
+ }
+
+ @Override
+ public int getChildCount(Object parent) {
+ return ((DefaultMutableTreeNode) parent).getChildCount();
+ }
+
+ @Override
+ public boolean isLeaf(Object node) {
+ return ((DefaultMutableTreeNode) node).isLeaf();
+ }
+
+ @Override
+ public void valueForPathChanged(TreePath path, Object newValue) {
+
+ }
+
+ @Override
+ public int getIndexOfChild(Object parent, Object child) {
+ return ((DefaultMutableTreeNode) parent).getIndex((DefaultMutableTreeNode) child);
+ }
+
+ @Override
+ public void addTreeModelListener(TreeModelListener l) {
+ }
+
+ @Override
+ public void removeTreeModelListener(TreeModelListener l) {
+ }
+
+ }
+}
diff --git a/src/com/jpexs/decompiler/flash/easygui/properties/panels/AbstractPropertiesPanel.java b/src/com/jpexs/decompiler/flash/easygui/properties/panels/AbstractPropertiesPanel.java
index 4b097c985..52c66dcf8 100644
--- a/src/com/jpexs/decompiler/flash/easygui/properties/panels/AbstractPropertiesPanel.java
+++ b/src/com/jpexs/decompiler/flash/easygui/properties/panels/AbstractPropertiesPanel.java
@@ -19,6 +19,7 @@ package com.jpexs.decompiler.flash.easygui.properties.panels;
import com.jpexs.decompiler.flash.easygui.EasyStrings;
import com.jpexs.decompiler.flash.gui.View;
import java.awt.BorderLayout;
+import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
@@ -30,7 +31,6 @@ import java.awt.event.MouseEvent;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.swing.BorderFactory;
-import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
@@ -49,6 +49,8 @@ public abstract class AbstractPropertiesPanel extends JPanel {
private static final char PLUS_CHAR = '\u2BC8';
private static final char MINUS_CHAR = '\u2BC6';
+
+ private JPanel verticalFiller = new JPanel();
public AbstractPropertiesPanel(String titleIdentifier) {
this.titleIdentifier = titleIdentifier;
@@ -59,8 +61,8 @@ public abstract class AbstractPropertiesPanel extends JPanel {
return EasyStrings.translate("property.label").replace("%item%", item);
}
- protected JPanel makeCard(String id, String icon, JPanel contents) {
- JPanel cardPanel = new JPanel();
+ protected void addCard(JPanel cardPanel, String id, String icon, JPanel contents, GridBagConstraints gbc, boolean last) {
+ //JPanel cardPanel = new JPanel();
JPanel headerPanel = new JPanel(new BorderLayout());
JLabel label = new JLabel(EasyStrings.translate("properties." + titleIdentifier + ".header." + id));
@@ -76,31 +78,54 @@ public abstract class AbstractPropertiesPanel extends JPanel {
headerPanel.add(plusMinusLabel, BorderLayout.WEST);
headerPanel.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
headerPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 30));
- headerPanel.setMinimumSize(new Dimension(0, 30));
+ headerPanel.setMinimumSize(new Dimension(0, 30));
headerPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
- cardPanel.setLayout(new BoxLayout(cardPanel, BoxLayout.Y_AXIS));
+ //cardPanel.setLayout(new BoxLayout(cardPanel, BoxLayout.Y_AXIS));
headerPanel.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
- setCardOpened(id, !isCardOpened(id));
+ boolean newOpened = !isCardOpened(id);
+ if (last) {
+ verticalFiller.setVisible(!newOpened);
+ }
+ setCardOpened(id, newOpened);
cardPanel.revalidate();
cardPanel.repaint();
}
}
});
- contents.setAlignmentX(Component.LEFT_ALIGNMENT);
- contents.setVisible(false);
- cardPanel.add(headerPanel);
- cardPanel.add(contents);
+ //contents.setAlignmentX(Component.LEFT_ALIGNMENT);
+ contents.setVisible(false);
+ gbc.gridx = 0;
+ gbc.gridy++;
+ gbc.anchor = GridBagConstraints.FIRST_LINE_START;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ gbc.weightx = 1;
+ cardPanel.add(headerPanel, gbc);
+ gbc.gridx = 0;
+ gbc.gridy++;
+ gbc.fill = GridBagConstraints.BOTH;
+ gbc.weighty = last ? 1 : 0;
+ cardPanel.add(contents, gbc);
contents.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+ //contents.setBorder(BorderFactory.createLineBorder(Color.green, 5));
//contents.setMaximumSize(new Dimension(getPreferredSize().width, contents.getPreferredSize().height + 10));
- cardPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
- cardPanel.setAlignmentY(Component.TOP_ALIGNMENT);
+ //cardPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
+ //cardPanel.setAlignmentY(Component.TOP_ALIGNMENT);
cardContents.put(id, contents);
cardPlusMinusLabels.put(id, plusMinusLabel);
- return cardPanel;
+
+ if (last) {
+ gbc.gridy++;
+ gbc.weighty = 1;
+ gbc.fill = GridBagConstraints.BOTH;
+ cardPanel.add(verticalFiller, gbc);
+ }
+
+ //cardPanel.setBorder(BorderFactory.createLineBorder(Color.red, 2));
+ //return cardPanel;
}
private boolean isCardOpened(String id) {
diff --git a/src/com/jpexs/decompiler/flash/easygui/properties/panels/InstancePropertiesPanel.java b/src/com/jpexs/decompiler/flash/easygui/properties/panels/InstancePropertiesPanel.java
index 3f47ce176..daf3a8350 100644
--- a/src/com/jpexs/decompiler/flash/easygui/properties/panels/InstancePropertiesPanel.java
+++ b/src/com/jpexs/decompiler/flash/easygui/properties/panels/InstancePropertiesPanel.java
@@ -19,6 +19,7 @@ package com.jpexs.decompiler.flash.easygui.properties.panels;
import com.jpexs.decompiler.flash.easygui.EasyStrings;
import com.jpexs.decompiler.flash.easygui.EasySwfPanel;
import com.jpexs.decompiler.flash.easygui.EasyTagNameResolver;
+import com.jpexs.decompiler.flash.easygui.FiltersTreeTable;
import com.jpexs.decompiler.flash.easygui.UndoManager;
import com.jpexs.decompiler.flash.easygui.properties.FloatPropertyField;
import com.jpexs.decompiler.flash.easygui.properties.IntegerPropertyField;
@@ -36,9 +37,11 @@ import com.jpexs.decompiler.flash.timeline.Timelined;
import com.jpexs.decompiler.flash.types.CXFORMWITHALPHA;
import com.jpexs.decompiler.flash.types.ColorTransform;
import com.jpexs.decompiler.flash.types.RGBA;
+import com.jpexs.decompiler.flash.types.filters.FILTER;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
+import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
@@ -55,9 +58,11 @@ import java.util.Set;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.DefaultComboBoxModel;
+import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
+import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.border.BevelBorder;
import javax.swing.event.ChangeEvent;
@@ -97,6 +102,8 @@ public class InstancePropertiesPanel extends AbstractPropertiesPanel {
private final JPanel backgroundColorPanel = new JPanel();
private final JLabel backgroundColorLabel = new JLabel();
+ private final FiltersTreeTable filtersTable;
+
private boolean updating = false;
public InstancePropertiesPanel(EasySwfPanel swfPanel, UndoManager undoManager) {
@@ -325,17 +332,44 @@ public class InstancePropertiesPanel extends AbstractPropertiesPanel {
gbc.fill = GridBagConstraints.HORIZONTAL;
displayPanel.add(new JPanel(), gbc);
- propertiesPanel = new JPanel();
- propertiesPanel.setLayout(new BoxLayout(propertiesPanel, BoxLayout.Y_AXIS));
+ JPanel filtersPanel = new JPanel(new BorderLayout());
+ filtersTable = new FiltersTreeTable();
+ JScrollPane sp = new JScrollPane(filtersTable);
+ filtersPanel.add(sp, BorderLayout.CENTER);
+ sp.getViewport().setBackground(filtersTable.getBackground());
+ //filtersPanel.setBorder(BorderFactory.createLineBorder(Color.red, 5));
+ //sp.setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE));
- propertiesPanel.add(makeCard("positionSize", null, positionSizePanel));
+ propertiesPanel = new JPanel();
+ //propertiesPanel.setLayout(new BoxLayout(propertiesPanel, BoxLayout.Y_AXIS));
+ //propertiesPanel.setBorder(BorderFactory.createLineBorder(Color.GREEN, 5));
+ propertiesPanel.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
+ propertiesPanel.setLayout(new GridBagLayout());
+
+ gbc = new GridBagConstraints();
+ gbc.gridx = 0;
+ gbc.gridy = -1;
+ /*gbc.anchor = GridBagConstraints.FIRST_LINE_START;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ gbc.gridx = 0;
+ gbc.gridy = 0;
+ gbcc.weightx = 1;*/
+
+ addCard(propertiesPanel, "positionSize", null, positionSizePanel, gbc, false);
+
+ //gbc.gridy++;
+ addCard(propertiesPanel, "colorEffect", null, colorEffectPanel, gbc, false);
+
+ //gbc.gridy++;
+ addCard(propertiesPanel, "display", null, displayPanel, gbc, false);
+
+ //gbc.gridy++;
+ //gbc.fill = GridBagConstraints.BOTH; //GridBagConstraints.BOTH;
+ //gbc.weighty = 1;
+ addCard(propertiesPanel, "filters", null, filtersPanel, gbc, true);
setCardOpened("positionSize", true);
- propertiesPanel.add(makeCard("colorEffect", null, colorEffectPanel));
-
- propertiesPanel.add(makeCard("display", null, displayPanel));
-
this.swfPanel = swfPanel;
alphaPercentPropertyField.addChangeListener(new ChangeListener() {
@@ -675,6 +709,7 @@ public class InstancePropertiesPanel extends AbstractPropertiesPanel {
Set blendMode = new HashSet<>();
Set cacheAsBitmap = new HashSet<>();
Set backgroundColor = new HashSet<>();
+ Set> filters = new HashSet<>();
for (DepthState ds : dss) {
if (ds == null) {
@@ -708,6 +743,7 @@ public class InstancePropertiesPanel extends AbstractPropertiesPanel {
blendMode.add(bm);
cacheAsBitmap.add(ds.cacheAsBitmap);
backgroundColor.add(ds.backGroundColor);
+ filters.add(ds.filters);
}
if (visible.size() == 0) {
@@ -789,6 +825,18 @@ public class InstancePropertiesPanel extends AbstractPropertiesPanel {
}
}
+ if (filters.size() == 1) {
+ List oneFilters = filters.iterator().next();
+ if (oneFilters == null) {
+ filtersTable.setFilters(new ArrayList<>());
+ } else {
+ filtersTable.setFilters(oneFilters);
+ }
+ } else if (filters.isEmpty()) {
+ filtersTable.setFilters(new ArrayList<>());
+ } else {
+ filtersTable.setFilters(null);
+ }
updating = false;
revalidate();
}
diff --git a/src/com/jpexs/decompiler/flash/gui/locales/EasyPanel.properties b/src/com/jpexs/decompiler/flash/gui/locales/EasyPanel.properties
index da24f4395..aadb65db9 100644
--- a/src/com/jpexs/decompiler/flash/gui/locales/EasyPanel.properties
+++ b/src/com/jpexs/decompiler/flash/gui/locales/EasyPanel.properties
@@ -117,4 +117,11 @@ property.instance.display.cacheAsBitmap.transparent = Transparent
property.instance.display.cacheAsBitmap.opaque = Opaque
#after 22.0.2
-property.document.backgroundColor = Background color
\ No newline at end of file
+property.document.backgroundColor = Background color
+
+properties.instance.header.filters = Filters
+
+properties.instance.filters.header.property = Property
+properties.instance.filters.header.value = Value
+
+properties.instance.filters.indeterminate = Indeterminate
\ No newline at end of file