diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 64c1e10..7e2b137 --- a/README.md +++ b/README.md @@ -2,10 +2,5 @@ ![GitHub all releases](https://img.shields.io/github/downloads/Enaium/JavaOctetEditor/total?style=flat-square) ![GitHub release (latest by date)](https://img.shields.io/github/v/release/Enaium/JavaOctetEditor?style=flat-square) -![GitHub](https://img.shields.io/github/license/Enaium/JavaOctetEditor?style=flat-square) - -![](https://user-images.githubusercontent.com/32991121/190947407-bbc6642e-2c9d-46f3-921c-6558c74272cf.png) -![](https://user-images.githubusercontent.com/32991121/190947409-9df48d03-e1b7-4c0a-ae1d-08e1ca2bc9aa.png) -![](https://user-images.githubusercontent.com/32991121/190947408-df6c6818-ea79-4a42-8b90-101b6daa3099.png) -![](https://user-images.githubusercontent.com/32991121/190947401-fc08fc4f-3714-49ca-a064-913e7312b191.png) -![](https://user-images.githubusercontent.com/32991121/190947410-4b8f224a-c589-4998-950a-e19618ce5734.png) +![GitHub release (latest SemVer including pre-releases)](https://img.shields.io/github/v/release/Enaium/JavaOctetEditor?include_prereleases&style=flat-square) +![GitHub](https://img.shields.io/github/license/Enaium/JavaOctetEditor?style=flat-square) \ No newline at end of file diff --git a/build.gradle b/build.gradle old mode 100644 new mode 100755 index 294cd99..d274de3 --- a/build.gradle +++ b/build.gradle @@ -1,82 +1,30 @@ -import java.text.SimpleDateFormat -import org.gradle.internal.jvm.Jvm - plugins { id 'java' - id 'com.github.johnrengelman.shadow' version '7.1.2' id 'idea' } -group 'cn.enaium' -version '1.3.0' - -sourceCompatibility = targetCompatibility = JavaVersion.VERSION_1_8 - -jar { - manifest.attributes( - 'Manifest-Version': 1.0, - 'Main-Class': 'cn.enaium.joe.Main', - "Implementation-Title": "${project.name}", - "Implementation-Version": "${project.version}", - "Implementation-Vendor": "${project.group}", - "Implementation-Timestamp": new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()), - "Premain-Class": "cn.enaium.joe.Agent", - "Agent-Class": "cn.enaium.joe.Agent", - "Can-Redefine-Classes": true, - "Can-Retransform-Classes": true - ) -} - -new File(System.getProperty("user.dir"), "run").mkdir() - -repositories { - mavenCentral() - maven { url 'https://jitpack.io' } - maven { url 'https://maven.quiltmc.org/repository/release' } +allprojects { + group 'cn.enaium' + version '2.0.0' } -dependencies { - testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.0' - testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.0' +subprojects { + apply plugin: 'java' + apply plugin: 'jacoco' + apply plugin: 'checkstyle' - implementation 'com.formdev:flatlaf:2.4' - implementation 'com.formdev:flatlaf-extras:2.4' - //noinspection GradlePackageUpdate - implementation 'com.miglayout:miglayout-swing:5.3' - implementation 'com.github.bobbylight:RSyntaxTextArea:3.2.0' - implementation 'org.ow2.asm:asm-tree:9.3' - implementation 'org.ow2.asm:asm-util:9.3' - implementation 'org.ow2.asm:asm-commons:9.3' - implementation 'org.benf:cfr:0.152' - implementation 'com.github.mstrobel.procyon:procyon-decompiler:v0.6.0' - implementation 'org.quiltmc:quiltflower:1.8.1' - implementation 'org.javassist:javassist:3.29.1-GA' - implementation 'com.google.code.gson:gson:2.9.0' - implementation 'org.tinylog:tinylog:1.3.6' - implementation 'com.github.FabricMC:mapping-io:597f0722d6' - compileOnly files(Jvm.current().getToolsJar())//Must use jdk8 -} - -test { - useJUnitPlatform() -} - -shadowJar { - dependencies { - include(dependency('com.formdev:.*')) - include(dependency('com.miglayout:.*')) - include(dependency('com.github.bobbylight:RSyntaxTextArea')) - include(dependency('org.ow2.asm:.*')) - include(dependency('org.benf:cfr')) - include(dependency('com.github.mstrobel.procyon:procyon-decompiler')) - include(dependency('org.javassist:javassist')) - include(dependency('com.google.code.gson:gson')) - include(dependency('org.tinylog:.*')) - include(dependency('org.quiltmc:quiltflower')) - include(dependency('com.github.FabricMC:mapping-io')) + //If you want to use your JDK, just takes to change the JDK version and vendor, otherwise Gradle will be download default JDK + java { + toolchain { + languageVersion = JavaLanguageVersion.of(17) + vendor = JvmVendorSpec.BELLSOFT + } } - archiveClassifier.set('') -} -build.dependsOn shadowJar \ No newline at end of file + repositories { + mavenCentral() + maven { url 'https://maven.quiltmc.org/repository/release' } + maven { url 'https://jitpack.io' } + } +} \ No newline at end of file diff --git a/core/build.gradle b/core/build.gradle new file mode 100755 index 0000000..153f7e0 --- /dev/null +++ b/core/build.gradle @@ -0,0 +1,19 @@ +plugins { + id 'java-library' +} + +dependencies { + api 'org.ow2.asm:asm-tree:9.4' + api 'org.ow2.asm:asm-util:9.4' + api 'org.ow2.asm:asm-commons:9.4' + api 'org.benf:cfr:0.152' + api 'com.github.mstrobel.procyon:procyon-decompiler:v0.6.0' + api 'org.quiltmc:quiltflower:1.8.1' + api 'com.google.code.gson:gson:2.10' + api 'org.tinylog:tinylog:1.3.6' + api 'com.github.FabricMC:mapping-io:597f0722d6' +} + +test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/src/main/java/cn/enaium/joe/annotation/Indeterminate.java b/core/src/main/java/cn/enaium/joe/core/annotation/Indeterminate.java similarity index 94% rename from src/main/java/cn/enaium/joe/annotation/Indeterminate.java rename to core/src/main/java/cn/enaium/joe/core/annotation/Indeterminate.java index 2ef3f7c..5f252c2 100644 --- a/src/main/java/cn/enaium/joe/annotation/Indeterminate.java +++ b/core/src/main/java/cn/enaium/joe/core/annotation/Indeterminate.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.enaium.joe.annotation; +package cn.enaium.joe.core.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -23,7 +23,7 @@ /** * @author Enaium - * @since 0.9.0 + * @since 2.0.0 */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) diff --git a/src/main/java/cn/enaium/joe/annotation/Repeatable.java b/core/src/main/java/cn/enaium/joe/core/annotation/Repeatable.java old mode 100644 new mode 100755 similarity index 94% rename from src/main/java/cn/enaium/joe/annotation/Repeatable.java rename to core/src/main/java/cn/enaium/joe/core/annotation/Repeatable.java index d994120..2833057 --- a/src/main/java/cn/enaium/joe/annotation/Repeatable.java +++ b/core/src/main/java/cn/enaium/joe/core/annotation/Repeatable.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.enaium.joe.annotation; +package cn.enaium.joe.core.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -23,7 +23,7 @@ /** * @author Enaium - * @since 0.9.0 + * @since 2.0.0 */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) diff --git a/core/src/main/java/cn/enaium/joe/core/compiler/Compiler.java b/core/src/main/java/cn/enaium/joe/core/compiler/Compiler.java new file mode 100755 index 0000000..b79408c --- /dev/null +++ b/core/src/main/java/cn/enaium/joe/core/compiler/Compiler.java @@ -0,0 +1,77 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.core.compiler; + +import javax.tools.*; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author Enaium + * @since 2.0.0 + */ +public class Compiler { + private final Map javaFileObjectMap = new HashMap<>(); + + private DiagnosticListener listener; + + public void addSource(String name, String content) { + javaFileObjectMap.put(name, new VirtualJavaFileObject(name, content)); + } + + public Map getClasses() { + return javaFileObjectMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, v -> v.getValue().getBytecode())); + } + + @SuppressWarnings("unchecked") + public boolean compile() { + var compiler = ToolProvider.getSystemJavaCompiler(); + var fileManager = new VirtualFileManager(compiler.getStandardFileManager(null, null, StandardCharsets.UTF_8)); + try { + var task = compiler.getTask(null, fileManager, ((DiagnosticListener) (Object) listener), null, null, javaFileObjectMap.values()); + Boolean b = task.call(); + return b != null && b; + } catch (Exception e) { + return false; + } + } + + public void setListener(DiagnosticListener listener) { + this.listener = listener; + } + + private final class VirtualFileManager extends ForwardingJavaFileManager { + public VirtualFileManager(JavaFileManager fileManager) { + super(fileManager); + } + + @Override + public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException { + if (JavaFileObject.Kind.CLASS == kind) { + VirtualJavaFileObject virtualJavaFileObject = new VirtualJavaFileObject(className, null); + javaFileObjectMap.put(className, virtualJavaFileObject); + return virtualJavaFileObject; + } else { + return super.getJavaFileForOutput(location, className, kind, sibling); + } + } + } +} diff --git a/core/src/main/java/cn/enaium/joe/core/compiler/VirtualJavaFileObject.java b/core/src/main/java/cn/enaium/joe/core/compiler/VirtualJavaFileObject.java new file mode 100755 index 0000000..1a5a6a1 --- /dev/null +++ b/core/src/main/java/cn/enaium/joe/core/compiler/VirtualJavaFileObject.java @@ -0,0 +1,52 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.core.compiler; + +import javax.tools.SimpleJavaFileObject; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.net.URI; + +/** + * @author Enaium + * @since 2.0.0 + */ +public class VirtualJavaFileObject extends SimpleJavaFileObject { + + private final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + + private final String content; + + protected VirtualJavaFileObject(String className, String content) { + super(URI.create("string:///" + className.replace(".", "/") + Kind.SOURCE.extension), Kind.SOURCE); + this.content = content; + } + + public byte[] getBytecode() { + return outputStream.toByteArray(); + } + + @Override + public ByteArrayOutputStream openOutputStream() { + return outputStream; + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { + return content; + } +} diff --git a/src/main/java/cn/enaium/joe/config/Config.java b/core/src/main/java/cn/enaium/joe/core/config/Config.java old mode 100644 new mode 100755 similarity index 93% rename from src/main/java/cn/enaium/joe/config/Config.java rename to core/src/main/java/cn/enaium/joe/core/config/Config.java index 15f8bbd..96054a8 --- a/src/main/java/cn/enaium/joe/config/Config.java +++ b/core/src/main/java/cn/enaium/joe/core/config/Config.java @@ -14,15 +14,14 @@ * limitations under the License. */ -package cn.enaium.joe.config; +package cn.enaium.joe.core.config; /** * @author Enaium - * @since 0.7.0 + * @since 2.0.0 */ public class Config { private final String name; - public Config(String name) { this.name = name; } diff --git a/core/src/main/java/cn/enaium/joe/core/config/ConfigManager.java b/core/src/main/java/cn/enaium/joe/core/config/ConfigManager.java new file mode 100755 index 0000000..7920c09 --- /dev/null +++ b/core/src/main/java/cn/enaium/joe/core/config/ConfigManager.java @@ -0,0 +1,128 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.core.config; + +import cn.enaium.joe.core.config.extend.ApplicationConfig; +import cn.enaium.joe.core.config.extend.CFRConfig; +import cn.enaium.joe.core.config.extend.FernFlowerConfig; +import cn.enaium.joe.core.config.extend.ProcyonConfig; +import cn.enaium.joe.core.config.value.Value; +import com.google.gson.*; +import javafx.scene.input.KeyCodeCombination; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.nio.file.Files; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * @author Enaium + * @since 2.0.0 + */ +public class ConfigManager { + private final Map, Config> configMap = new LinkedHashMap<>(); + + public ConfigManager() { + setByClass(new ApplicationConfig()); + setByClass(new CFRConfig()); + setByClass(new FernFlowerConfig()); + setByClass(new ProcyonConfig()); + } + + @SuppressWarnings("unchecked") + public T getByClass(Class klass) { + if (configMap.containsKey(klass)) { + return (T) configMap.get(klass); + } else { + throw new RuntimeException("Not found " + klass); + } + } + + public void setByClass(Config config) { + configMap.put(config.getClass(), config); + } + + public Map, Config> getConfig() { + return configMap; + } + + public Map getConfigMap(Class config) { + Map map = new HashMap<>(); + for (Field declaredField : config.getDeclaredFields()) { + declaredField.setAccessible(true); + try { + Object o = declaredField.get(getByClass(config)); + if (o instanceof Value) { + Object value = ((Value) o).getValue(); + if (value != null) { + map.put(declaredField.getName(), value.toString()); + } + } + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + return map; + } + + private GsonBuilder gson() { + return new GsonBuilder().setPrettyPrinting().disableHtmlEscaping(); + } + + public void load() throws IOException, IllegalAccessException { + for (Map.Entry, Config> classConfigEntry : configMap.entrySet()) { + + Class klass = classConfigEntry.getKey(); + Config config = classConfigEntry.getValue(); + File file = new File(System.getProperty("."), config.getName() + ".json"); + if (file.exists()) { + JsonObject jsonObject = gson().create().fromJson(Files.readString(file.toPath()), JsonObject.class); + + for (Field configField : klass.getDeclaredFields()) { + configField.setAccessible(true); + if (!jsonObject.has(configField.getName())) { + continue; + } + + if (!jsonObject.has(configField.getName())) { + continue; + } + + if (!jsonObject.get(configField.getName()).getAsJsonObject().has("value")) { + continue; + } + + JsonElement valueJsonElement = jsonObject.get(configField.getName()).getAsJsonObject().get("value"); + + Object valueObject = configField.get(config); + if (valueObject instanceof Value value) { + value.serialize(valueJsonElement); + } + } + } + } + } + + public void save() throws IOException { + for (Config value : configMap.values()) { + Files.writeString(new File(System.getProperty("."), value.getName() + ".json").toPath(), gson().registerTypeAdapter(KeyCodeCombination.class, (JsonSerializer) (src, typeOfSrc, context) -> new JsonPrimitive(src.toString())).create().toJson(value)); + } + } +} diff --git a/src/main/java/cn/enaium/joe/config/extend/ApplicationConfig.java b/core/src/main/java/cn/enaium/joe/core/config/extend/ApplicationConfig.java old mode 100644 new mode 100755 similarity index 76% rename from src/main/java/cn/enaium/joe/config/extend/ApplicationConfig.java rename to core/src/main/java/cn/enaium/joe/core/config/extend/ApplicationConfig.java index 0539e4e..47e5ee7 --- a/src/main/java/cn/enaium/joe/config/extend/ApplicationConfig.java +++ b/core/src/main/java/cn/enaium/joe/core/config/extend/ApplicationConfig.java @@ -14,29 +14,27 @@ * limitations under the License. */ -package cn.enaium.joe.config.extend; +package cn.enaium.joe.core.config.extend; -import cn.enaium.joe.annotation.NoUI; -import cn.enaium.joe.config.Config; -import cn.enaium.joe.config.value.EnableValue; -import cn.enaium.joe.config.value.ModeValue; -import cn.enaium.joe.config.value.StringSetValue; +import cn.enaium.joe.core.config.Config; +import cn.enaium.joe.core.config.value.EnableValue; +import cn.enaium.joe.core.config.value.IntegerValue; +import cn.enaium.joe.core.config.value.ModeValue; +import cn.enaium.joe.core.config.value.StringSetValue; -import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; /** * @author Enaium - * @since 0.7.0 + * @since 2.0.0 */ public class ApplicationConfig extends Config { public ModeValue decompilerMode = new ModeValue("Decompiler", "CFR", "Java Decompiler", Arrays.asList("CFR", "Procyon", "FernFlower")); public ModeValue language = new ModeValue("Language", "System", "UI language", Arrays.asList("System", "zh_CN", "en_US")); public ModeValue packagePresentation = new ModeValue("Package Presentation", "Hierarchical", "Package Mode", Arrays.asList("Flat", "Hierarchical")); public EnableValue compactMiddlePackage = new EnableValue("Compact Middle Package", true, "Only Hierarchical Mode"); - @NoUI - public final StringSetValue loadRecent = new StringSetValue("Load Recent", new HashSet<>(), ""); + public StringSetValue loadRecent = new StringSetValue("Load Recent", new HashSet<>(), ""); public ApplicationConfig() { super("Application"); diff --git a/src/main/java/cn/enaium/joe/config/extend/CFRConfig.java b/core/src/main/java/cn/enaium/joe/core/config/extend/CFRConfig.java old mode 100644 new mode 100755 similarity index 98% rename from src/main/java/cn/enaium/joe/config/extend/CFRConfig.java rename to core/src/main/java/cn/enaium/joe/core/config/extend/CFRConfig.java index 31980f3..c86ab74 --- a/src/main/java/cn/enaium/joe/config/extend/CFRConfig.java +++ b/core/src/main/java/cn/enaium/joe/core/config/extend/CFRConfig.java @@ -14,18 +14,17 @@ * limitations under the License. */ -package cn.enaium.joe.config.extend; +package cn.enaium.joe.core.config.extend; -import cn.enaium.joe.config.Config; -import cn.enaium.joe.config.value.EnableValue; -import cn.enaium.joe.config.value.IntegerValue; -import cn.enaium.joe.config.value.ModeValue; -import cn.enaium.joe.config.value.StringValue; +import cn.enaium.joe.core.config.Config; +import cn.enaium.joe.core.config.value.EnableValue; +import cn.enaium.joe.core.config.value.IntegerValue; +import cn.enaium.joe.core.config.value.StringValue; import org.benf.cfr.reader.state.OsInfo; /** * @author Enaium - * @since 0.7.0 + * @since 2.0.0 */ @SuppressWarnings("unused") public class CFRConfig extends Config { diff --git a/src/main/java/cn/enaium/joe/config/extend/FernFlowerConfig.java b/core/src/main/java/cn/enaium/joe/core/config/extend/FernFlowerConfig.java old mode 100644 new mode 100755 similarity index 96% rename from src/main/java/cn/enaium/joe/config/extend/FernFlowerConfig.java rename to core/src/main/java/cn/enaium/joe/core/config/extend/FernFlowerConfig.java index 6254bf1..48ec235 --- a/src/main/java/cn/enaium/joe/config/extend/FernFlowerConfig.java +++ b/core/src/main/java/cn/enaium/joe/core/config/extend/FernFlowerConfig.java @@ -14,19 +14,19 @@ * limitations under the License. */ -package cn.enaium.joe.config.extend; +package cn.enaium.joe.core.config.extend; -import cn.enaium.joe.config.Config; -import cn.enaium.joe.config.value.EnableValue; -import cn.enaium.joe.config.value.IntegerValue; -import cn.enaium.joe.config.value.ModeValue; -import cn.enaium.joe.config.value.StringValue; +import cn.enaium.joe.core.config.Config; +import cn.enaium.joe.core.config.value.EnableValue; +import cn.enaium.joe.core.config.value.IntegerValue; +import cn.enaium.joe.core.config.value.ModeValue; +import cn.enaium.joe.core.config.value.StringValue; import java.util.Arrays; /** * @author Enaium - * @since 1.1.0 + * @since 2.0.0 */ @SuppressWarnings("unused") public class FernFlowerConfig extends Config { diff --git a/src/main/java/cn/enaium/joe/config/extend/ProcyonConfig.java b/core/src/main/java/cn/enaium/joe/core/config/extend/ProcyonConfig.java old mode 100644 new mode 100755 similarity index 98% rename from src/main/java/cn/enaium/joe/config/extend/ProcyonConfig.java rename to core/src/main/java/cn/enaium/joe/core/config/extend/ProcyonConfig.java index 8cbdf74..e1ebe30 --- a/src/main/java/cn/enaium/joe/config/extend/ProcyonConfig.java +++ b/core/src/main/java/cn/enaium/joe/core/config/extend/ProcyonConfig.java @@ -14,14 +14,14 @@ * limitations under the License. */ -package cn.enaium.joe.config.extend; +package cn.enaium.joe.core.config.extend; -import cn.enaium.joe.config.Config; -import cn.enaium.joe.config.value.EnableValue; -import cn.enaium.joe.config.value.IntegerValue; -import cn.enaium.joe.config.value.ModeValue; -import cn.enaium.joe.config.value.Value; -import cn.enaium.joe.util.ReflectUtil; +import cn.enaium.joe.core.config.Config; +import cn.enaium.joe.core.util.ReflectUtil; +import cn.enaium.joe.core.config.value.EnableValue; +import cn.enaium.joe.core.config.value.IntegerValue; +import cn.enaium.joe.core.config.value.ModeValue; +import cn.enaium.joe.core.config.value.Value; import com.strobel.decompiler.languages.java.JavaFormattingOptions; import org.pmw.tinylog.Logger; @@ -30,7 +30,7 @@ /** * @author Enaium - * @since 1.1.0 + * @since 2.0.0 */ public class ProcyonConfig extends Config { public EnableValue IndentNamespaceBody = new EnableValue("IndentNamespaceBody", true, "IndentNamespaceBody"); diff --git a/src/main/java/cn/enaium/joe/config/value/EnableValue.java b/core/src/main/java/cn/enaium/joe/core/config/value/EnableValue.java old mode 100644 new mode 100755 similarity index 79% rename from src/main/java/cn/enaium/joe/config/value/EnableValue.java rename to core/src/main/java/cn/enaium/joe/core/config/value/EnableValue.java index 05300a9..4ada38a --- a/src/main/java/cn/enaium/joe/config/value/EnableValue.java +++ b/core/src/main/java/cn/enaium/joe/core/config/value/EnableValue.java @@ -14,14 +14,21 @@ * limitations under the License. */ -package cn.enaium.joe.config.value; +package cn.enaium.joe.core.config.value; + +import com.google.gson.JsonElement; /** * @author Enaium - * @since 0.7.0 + * @since 2.0.0 */ public class EnableValue extends Value { public EnableValue(String name, Boolean value, String description) { super(name, value, description); } + + @Override + public void serialize(JsonElement element) { + setValue(element.getAsBoolean()); + } } diff --git a/src/main/java/cn/enaium/joe/config/value/IntegerValue.java b/core/src/main/java/cn/enaium/joe/core/config/value/IntegerValue.java old mode 100644 new mode 100755 similarity index 79% rename from src/main/java/cn/enaium/joe/config/value/IntegerValue.java rename to core/src/main/java/cn/enaium/joe/core/config/value/IntegerValue.java index fa3a550..0d64424 --- a/src/main/java/cn/enaium/joe/config/value/IntegerValue.java +++ b/core/src/main/java/cn/enaium/joe/core/config/value/IntegerValue.java @@ -14,14 +14,21 @@ * limitations under the License. */ -package cn.enaium.joe.config.value; +package cn.enaium.joe.core.config.value; + +import com.google.gson.JsonElement; /** * @author Enaium - * @since 0.7.0 + * @since 2.0.0 */ public class IntegerValue extends Value { public IntegerValue(String name, Integer value, String description) { super(name, value, description); } + + @Override + public void serialize(JsonElement element) { + setValue(element.getAsInt()); + } } diff --git a/src/main/java/cn/enaium/joe/config/value/ModeValue.java b/core/src/main/java/cn/enaium/joe/core/config/value/ModeValue.java old mode 100644 new mode 100755 similarity index 77% rename from src/main/java/cn/enaium/joe/config/value/ModeValue.java rename to core/src/main/java/cn/enaium/joe/core/config/value/ModeValue.java index a57cdc3..40b839e --- a/src/main/java/cn/enaium/joe/config/value/ModeValue.java +++ b/core/src/main/java/cn/enaium/joe/core/config/value/ModeValue.java @@ -14,15 +14,16 @@ * limitations under the License. */ -package cn.enaium.joe.config.value; +package cn.enaium.joe.core.config.value; +import com.google.gson.JsonElement; import com.google.gson.annotations.Expose; import java.util.List; /** * @author Enaium - * @since 0.7.0 + * @since 2.0.0 */ public class ModeValue extends Value { @@ -41,4 +42,13 @@ public List getMode() { public void setMode(List mode) { this.mode = mode; } + + @Override + public void serialize(JsonElement element) { + if (mode.contains(element.getAsString())) { + setValue(element.getAsString()); + } else { + setValue(mode.get(0)); + } + } } diff --git a/src/main/java/cn/enaium/joe/gui/panel/file/tree/node/DefaultTreeNode.java b/core/src/main/java/cn/enaium/joe/core/config/value/StringSetValue.java old mode 100644 new mode 100755 similarity index 52% rename from src/main/java/cn/enaium/joe/gui/panel/file/tree/node/DefaultTreeNode.java rename to core/src/main/java/cn/enaium/joe/core/config/value/StringSetValue.java index c168478..e731aea --- a/src/main/java/cn/enaium/joe/gui/panel/file/tree/node/DefaultTreeNode.java +++ b/core/src/main/java/cn/enaium/joe/core/config/value/StringSetValue.java @@ -14,28 +14,28 @@ * limitations under the License. */ -package cn.enaium.joe.gui.panel.file.tree.node; +package cn.enaium.joe.core.config.value; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.MutableTreeNode; -import javax.swing.tree.TreeNode; -import java.util.Vector; -import java.util.concurrent.CopyOnWriteArrayList; +import com.google.gson.JsonElement; + +import java.util.HashSet; +import java.util.Set; /** * @author Enaium + * @since 2.0.0 */ -public class DefaultTreeNode extends DefaultMutableTreeNode { - public DefaultTreeNode(Object userObject) { - super(userObject); +public class StringSetValue extends Value>{ + public StringSetValue(String name, Set value, String description) { + super(name, value, description); } - - @SuppressWarnings("unchecked") - public Vector getChildren() { - if (children == null) { - return new Vector<>(); + @Override + public void serialize(JsonElement element) { + Set strings = new HashSet<>(); + for (JsonElement jsonElement : element.getAsJsonArray()) { + strings.add(jsonElement.getAsString()); } - return children; + setValue(strings); } } diff --git a/src/main/java/cn/enaium/joe/config/value/StringValue.java b/core/src/main/java/cn/enaium/joe/core/config/value/StringValue.java old mode 100644 new mode 100755 similarity index 79% rename from src/main/java/cn/enaium/joe/config/value/StringValue.java rename to core/src/main/java/cn/enaium/joe/core/config/value/StringValue.java index 65d2910..028a797 --- a/src/main/java/cn/enaium/joe/config/value/StringValue.java +++ b/core/src/main/java/cn/enaium/joe/core/config/value/StringValue.java @@ -14,14 +14,21 @@ * limitations under the License. */ -package cn.enaium.joe.config.value; +package cn.enaium.joe.core.config.value; + +import com.google.gson.JsonElement; /** * @author Enaium - * @since 0.7.0 + * @since 2.0.0 */ public class StringValue extends Value { public StringValue(String name, String value, String description) { super(name, value, description); } + + @Override + public void serialize(JsonElement element) { + setValue(element.getAsString()); + } } diff --git a/src/main/java/cn/enaium/joe/config/value/Value.java b/core/src/main/java/cn/enaium/joe/core/config/value/Value.java old mode 100644 new mode 100755 similarity index 80% rename from src/main/java/cn/enaium/joe/config/value/Value.java rename to core/src/main/java/cn/enaium/joe/core/config/value/Value.java index d27d490..aaecc22 --- a/src/main/java/cn/enaium/joe/config/value/Value.java +++ b/core/src/main/java/cn/enaium/joe/core/config/value/Value.java @@ -14,16 +14,18 @@ * limitations under the License. */ -package cn.enaium.joe.config.value; +package cn.enaium.joe.core.config.value; + +import com.google.gson.JsonElement; /** * @author Enaium - * @since 0.7.0 + * @since 2.0.0 */ -public class Value { - private String name; +public abstract class Value { + private final String name; private T value; - private String description; + private final String description; public Value(String name, T value, String description) { this.name = name; @@ -46,4 +48,6 @@ public T getValue() { public void setValue(T value) { this.value = value; } + + public abstract void serialize(JsonElement element); } diff --git a/src/main/java/cn/enaium/joe/gui/panel/file/tree/node/MethodTreeNode.java b/core/src/main/java/cn/enaium/joe/core/decompiler/AbstractDecompiler.java similarity index 57% rename from src/main/java/cn/enaium/joe/gui/panel/file/tree/node/MethodTreeNode.java rename to core/src/main/java/cn/enaium/joe/core/decompiler/AbstractDecompiler.java index fd92275..ecca0ff 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/file/tree/node/MethodTreeNode.java +++ b/core/src/main/java/cn/enaium/joe/core/decompiler/AbstractDecompiler.java @@ -14,21 +14,26 @@ * limitations under the License. */ -package cn.enaium.joe.gui.panel.file.tree.node; +package cn.enaium.joe.core.decompiler; + +import cn.enaium.joe.core.config.ConfigManager; +import cn.enaium.joe.core.model.JarModel; import org.objectweb.asm.tree.ClassNode; -import org.objectweb.asm.tree.MethodNode; -/** - * @author Enaium - */ -public class MethodTreeNode extends PackageTreeNode { - public ClassNode classNode; - public MethodNode methodNode; +import java.util.Map; + +public abstract class AbstractDecompiler { - public MethodTreeNode(ClassNode classNode, MethodNode methodNode) { - super(classNode.name + "." + methodNode.name + methodNode.desc); + public final JarModel jar; + public final ConfigManager config; + public final ClassNode classNode; + + public AbstractDecompiler(JarModel jar, ConfigManager config, ClassNode classNode) { + this.jar = jar; + this.config = config; this.classNode = classNode; - this.methodNode = methodNode; } -} \ No newline at end of file + + abstract String decompile() throws Exception; +} diff --git a/core/src/main/java/cn/enaium/joe/core/decompiler/CFRDecompiler.java b/core/src/main/java/cn/enaium/joe/core/decompiler/CFRDecompiler.java new file mode 100644 index 0000000..2bdf34f --- /dev/null +++ b/core/src/main/java/cn/enaium/joe/core/decompiler/CFRDecompiler.java @@ -0,0 +1,112 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.core.decompiler; + +import cn.enaium.joe.core.config.ConfigManager; +import cn.enaium.joe.core.config.extend.CFRConfig; +import cn.enaium.joe.core.model.JarModel; + +import org.benf.cfr.reader.api.CfrDriver; +import org.benf.cfr.reader.api.ClassFileSource; +import org.benf.cfr.reader.api.OutputSinkFactory; +import org.benf.cfr.reader.bytecode.analysis.parse.utils.Pair; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.tree.ClassNode; + +import java.io.IOException; +import java.util.*; + +/** + * @author Enaium + * @since 2.0.0 + */ +public class CFRDecompiler extends AbstractDecompiler { + public CFRDecompiler(JarModel jar, ConfigManager config, ClassNode classNode) { + super(jar, config, classNode); + } + + @Override + public String decompile() { + ClassFileSource cfs = new ClassFileSource() { + @Override + public void informAnalysisRelativePathDetail(String a, String b) { + } + + @Override + public String getPossiblyRenamedPath(String path) { + return path; + } + + @Override + public Pair getClassFileContent(String path) throws IOException { + String name = path.substring(0, path.length() - 6); + if (name.equals(classNode.name)) { + ClassWriter classWriter = new ClassWriter(0); + classNode.accept(classWriter); + return Pair.make(classWriter.toByteArray(), name); + } else { + ClassNode cn = jar.classes.get(path); + if (cn != null) { + ClassWriter classWriter = new ClassWriter(0); + cn.accept(classWriter); + return Pair.make(classWriter.toByteArray(), name); + } + } + return null; + } + + @Override + public Collection addJar(String arg0) { + return Collections.emptySet(); + } + }; + + OutputSinkFactory outputSinkFactory = new OutputSinkFactory() { + String content; + + @Override + public List getSupportedSinks(SinkType sinkType, Collection available) { + return Arrays.asList(SinkClass.values()); + } + + @Override + public Sink getSink(SinkType sinkType, SinkClass sinkClass) { + + if (sinkType == SinkType.JAVA) { + return this::setContent; + } + + return t -> { + + }; + } + + private void setContent(T content) { + this.content = content.toString(); + } + + @Override + public String toString() { + return content; + } + }; + CfrDriver driver = new CfrDriver.Builder().withClassFileSource(cfs).withOptions(config.getConfigMap(CFRConfig.class)).withOutputSink(outputSinkFactory).build(); + + driver.analyse(Collections.singletonList(classNode.name)); + return outputSinkFactory.toString(); + } +} diff --git a/src/main/java/cn/enaium/joe/service/decompiler/FernFlowerDecompiler.java b/core/src/main/java/cn/enaium/joe/core/decompiler/FernFlowerDecompiler.java similarity index 69% rename from src/main/java/cn/enaium/joe/service/decompiler/FernFlowerDecompiler.java rename to core/src/main/java/cn/enaium/joe/core/decompiler/FernFlowerDecompiler.java index 13270e0..84dcc35 100644 --- a/src/main/java/cn/enaium/joe/service/decompiler/FernFlowerDecompiler.java +++ b/core/src/main/java/cn/enaium/joe/core/decompiler/FernFlowerDecompiler.java @@ -14,12 +14,13 @@ * limitations under the License. */ -package cn.enaium.joe.service.decompiler; +package cn.enaium.joe.core.decompiler; -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.config.extend.FernFlowerConfig; -import cn.enaium.joe.util.MessageUtil; -import cn.enaium.joe.util.ReflectUtil; +import cn.enaium.joe.core.config.ConfigManager; +import cn.enaium.joe.core.config.extend.FernFlowerConfig; + +import cn.enaium.joe.core.model.JarModel; +import cn.enaium.joe.core.util.ReflectUtil; import org.jetbrains.java.decompiler.main.Fernflower; import org.jetbrains.java.decompiler.main.extern.IBytecodeProvider; import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; @@ -35,25 +36,31 @@ import java.io.File; import java.io.IOException; import java.util.HashMap; +import java.util.Map; import java.util.jar.Manifest; /** * @author Enaium - * @since 1.0.0 + * @since 2.0.0 */ -public class FernFlowerDecompiler implements IDecompiler, IBytecodeProvider, IResultSaver { +public class FernFlowerDecompiler extends AbstractDecompiler implements IBytecodeProvider, IResultSaver { private byte[] bytes; private String returned; + public FernFlowerDecompiler(JarModel jar, ConfigManager config, ClassNode classNode) { + super(jar, config, classNode); + } + + @Override - public String decompile(ClassNode classNode) { - ClassWriter classWriter = new ClassWriter(0); + public String decompile() throws IOException, NoSuchFieldException, IllegalAccessException { + var classWriter = new ClassWriter(0); classNode.accept(classWriter); bytes = classWriter.toByteArray(); Fernflower fernflower = new Fernflower(this, this, new HashMap() {{ - JavaOctetEditor.getInstance().config.getConfigMap(FernFlowerConfig.class).forEach((k, v) -> { + config.getConfigMap(FernFlowerConfig.class).forEach((k, v) -> { if (v.equals("true")) { v = "1"; } else if (v.equals("false")) { @@ -69,24 +76,20 @@ public void writeMessage(String message, Severity severity) { @Override public void writeMessage(String message, Severity severity, Throwable t) { - MessageUtil.error(t); + } }); - try { - File file = new File("class.class"); - fernflower.addSource(file); - StructContext structContext = ReflectUtil.getFieldValue(fernflower, "structContext"); - LazyLoader loader = ReflectUtil.getFieldValue(structContext, "loader"); - loader.addClassLink(file.getName(), new LazyLoader.Link(file.getName(), null)); - - StructClass structClass = StructClass.create(new DataInputFullStream(bytes), true, loader); - ContextUnit contextUnit = new ContextUnit(ContextUnit.TYPE_FOLDER, null, file.getName(), true, this, fernflower); - contextUnit.addClass(structClass, file.getName()); - fernflower.decompileContext(); - } catch (NoSuchFieldException | IllegalAccessException | IOException e) { - MessageUtil.error(e); - } + File file = new File("class.class"); + fernflower.addSource(file); + StructContext structContext = ReflectUtil.getFieldValue(fernflower, "structContext"); + LazyLoader loader = ReflectUtil.getFieldValue(structContext, "loader"); + loader.addClassLink(file.getName(), new LazyLoader.Link(file.getName(), null)); + + StructClass structClass = StructClass.create(new DataInputFullStream(bytes), true, loader); + ContextUnit contextUnit = new ContextUnit(ContextUnit.TYPE_FOLDER, null, file.getName(), true, this, fernflower); + contextUnit.addClass(structClass, file.getName()); + fernflower.decompileContext(); return returned; } diff --git a/src/main/java/cn/enaium/joe/service/decompiler/ProcyonDecompiler.java b/core/src/main/java/cn/enaium/joe/core/decompiler/ProcyonDecompiler.java similarity index 81% rename from src/main/java/cn/enaium/joe/service/decompiler/ProcyonDecompiler.java rename to core/src/main/java/cn/enaium/joe/core/decompiler/ProcyonDecompiler.java index df4e35d..c7ee2f7 100644 --- a/src/main/java/cn/enaium/joe/service/decompiler/ProcyonDecompiler.java +++ b/core/src/main/java/cn/enaium/joe/core/decompiler/ProcyonDecompiler.java @@ -14,10 +14,12 @@ * limitations under the License. */ -package cn.enaium.joe.service.decompiler; +package cn.enaium.joe.core.decompiler; + +import cn.enaium.joe.core.config.ConfigManager; +import cn.enaium.joe.core.config.extend.ProcyonConfig; +import cn.enaium.joe.core.model.JarModel; -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.config.extend.ProcyonConfig; import com.strobel.assembler.InputTypeLoader; import com.strobel.assembler.metadata.Buffer; import com.strobel.assembler.metadata.ITypeLoader; @@ -29,14 +31,19 @@ import org.objectweb.asm.tree.ClassNode; import java.io.StringWriter; +import java.util.Map; /** * @author Enaium - * @since 0.7.0 + * @since 2.0.0 */ -public class ProcyonDecompiler implements IDecompiler { +public class ProcyonDecompiler extends AbstractDecompiler { + public ProcyonDecompiler(JarModel jar, ConfigManager config, ClassNode classNode) { + super(jar, config, classNode); + } + @Override - public String decompile(ClassNode classNode) { + public String decompile() { DecompilerSettings decompilerSettings = new DecompilerSettings(); MetadataSystem metadataSystem = new MetadataSystem(new ITypeLoader() { private final InputTypeLoader backLoader = new InputTypeLoader(); @@ -59,7 +66,7 @@ public boolean tryLoadType(String s, Buffer buffer) { decompilerSettings.getLanguage().decompileType(metadataSystem.lookupType(classNode.name).resolve(), new PlainTextOutput(stringwriter), new DecompilationOptions(){{ setFullDecompilation(true); DecompilerSettings settings = DecompilerSettings.javaDefaults(); - settings.setJavaFormattingOptions(JavaOctetEditor.getInstance().config.getByClass(ProcyonConfig.class).get()); + settings.setJavaFormattingOptions(config.getByClass(ProcyonConfig.class).get()); setSettings(settings); }}); return stringwriter.toString(); diff --git a/src/main/java/cn/enaium/joe/mapping/Mapping.java b/core/src/main/java/cn/enaium/joe/core/mapping/Mapping.java similarity index 94% rename from src/main/java/cn/enaium/joe/mapping/Mapping.java rename to core/src/main/java/cn/enaium/joe/core/mapping/Mapping.java index 7f909ea..ec6e858 100644 --- a/src/main/java/cn/enaium/joe/mapping/Mapping.java +++ b/core/src/main/java/cn/enaium/joe/core/mapping/Mapping.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.enaium.joe.mapping; +package cn.enaium.joe.core.mapping; import net.fabricmc.mappingio.MappedElementKind; import net.fabricmc.mappingio.MappingVisitor; @@ -26,7 +26,7 @@ /** * @author Enaium - * @since 1.0.0 + * @since 2.0.0 */ public class Mapping { public final Map MAP = new HashMap<>(); diff --git a/src/main/java/cn/enaium/joe/mapping/MappingParser.java b/core/src/main/java/cn/enaium/joe/core/mapping/MappingParser.java similarity index 96% rename from src/main/java/cn/enaium/joe/mapping/MappingParser.java rename to core/src/main/java/cn/enaium/joe/core/mapping/MappingParser.java index cb103ec..964e290 100644 --- a/src/main/java/cn/enaium/joe/mapping/MappingParser.java +++ b/core/src/main/java/cn/enaium/joe/core/mapping/MappingParser.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package cn.enaium.joe.mapping; +package cn.enaium.joe.core.mapping; -import cn.enaium.joe.util.Pair; +import cn.enaium.joe.core.util.Pair; import net.fabricmc.mappingio.MappedElementKind; import net.fabricmc.mappingio.MappingReader; import net.fabricmc.mappingio.MappingVisitor; @@ -29,7 +29,7 @@ /** * @author Enaium - * @since 1.0.0 + * @since 2.0.0 */ public class MappingParser { @@ -129,21 +129,21 @@ public boolean visitMethodVar(int lvtRowIndex, int lvIndex, int startOpIdx, Stri @Override public void visitDstName(MappedElementKind targetKind, int namespace, String name) throws IOException { switch (targetKind) { - case CLASS: + case CLASS -> { if (isProGuard(mappingFormat)) { mapping.MAP.put(name, klass); } else { mapping.MAP.put(klass, name); } - break; - case FIELD: + } + case FIELD -> { if (isProGuard(mappingFormat)) { mapping.MAP.put(String.format("%s.%s", mapping.CLEAN.getOrDefault(klass, klass), name), field); } else { mapping.MAP.put(String.format("%s.%s", mapping.CLEAN.getOrDefault(klass, klass), field), name); } - break; - case METHOD: + } + case METHOD -> { String cleanName = method.getKey(); String cleanArgument = method.getValue(); StringBuilder argumentBuilder = new StringBuilder(); @@ -157,18 +157,16 @@ public void visitDstName(MappedElementKind targetKind, int namespace, String nam argumentBuilder.append(argument); } argumentBuilder.append(")"); - String ret = methodType.getReturnType().getDescriptor(); if (mapping.CLEAN.containsKey(methodType.getReturnType().getInternalName())) { ret = Type.getObjectType(mapping.CLEAN.get(methodType.getReturnType().getInternalName())).getDescriptor(); } - if (isProGuard(mappingFormat)) { mapping.MAP.put(String.format("%s.%s%s%s", mapping.CLEAN.getOrDefault(klass, klass), name, argumentBuilder, ret), cleanName); } else { mapping.MAP.put(String.format("%s.%s%s%s", mapping.CLEAN.getOrDefault(klass, klass), cleanName, argumentBuilder, ret), name); } - break; + } } } diff --git a/src/main/java/cn/enaium/joe/gui/panel/file/tree/node/ClassTreeNode.java b/core/src/main/java/cn/enaium/joe/core/model/JarModel.java old mode 100644 new mode 100755 similarity index 68% rename from src/main/java/cn/enaium/joe/gui/panel/file/tree/node/ClassTreeNode.java rename to core/src/main/java/cn/enaium/joe/core/model/JarModel.java index 48424c6..fe2412b --- a/src/main/java/cn/enaium/joe/gui/panel/file/tree/node/ClassTreeNode.java +++ b/core/src/main/java/cn/enaium/joe/core/model/JarModel.java @@ -14,18 +14,18 @@ * limitations under the License. */ -package cn.enaium.joe.gui.panel.file.tree.node; +package cn.enaium.joe.core.model; import org.objectweb.asm.tree.ClassNode; +import java.util.LinkedHashMap; +import java.util.Map; + /** * @author Enaium + * @since 2.0.0 */ -public class ClassTreeNode extends PackageTreeNode { - public ClassNode classNode; - - public ClassTreeNode(ClassNode classNode) { - super(classNode.name.substring(classNode.name.lastIndexOf("/") + 1)); - this.classNode = classNode; - } +public class JarModel { + public Map classes = new LinkedHashMap<>(); + public Map resources = new LinkedHashMap<>(); } diff --git a/src/main/java/cn/enaium/joe/service/decompiler/IDecompiler.java b/core/src/main/java/cn/enaium/joe/core/model/SearchResultModel.java similarity index 83% rename from src/main/java/cn/enaium/joe/service/decompiler/IDecompiler.java rename to core/src/main/java/cn/enaium/joe/core/model/SearchResultModel.java index 319daad..cf1a52d 100644 --- a/src/main/java/cn/enaium/joe/service/decompiler/IDecompiler.java +++ b/core/src/main/java/cn/enaium/joe/core/model/SearchResultModel.java @@ -14,14 +14,14 @@ * limitations under the License. */ -package cn.enaium.joe.service.decompiler; +package cn.enaium.joe.core.model; import org.objectweb.asm.tree.ClassNode; /** * @author Enaium - * @since 0.7.0 + * @since 2.0.0 */ -public interface IDecompiler { - String decompile(ClassNode classNode); -} +public record SearchResultModel(ClassNode classNode, Object result) { + +} \ No newline at end of file diff --git a/src/main/java/cn/enaium/joe/task/AbstractTask.java b/core/src/main/java/cn/enaium/joe/core/task/AbstractTask.java old mode 100644 new mode 100755 similarity index 95% rename from src/main/java/cn/enaium/joe/task/AbstractTask.java rename to core/src/main/java/cn/enaium/joe/core/task/AbstractTask.java index 601a5e5..b14b6cd --- a/src/main/java/cn/enaium/joe/task/AbstractTask.java +++ b/core/src/main/java/cn/enaium/joe/core/task/AbstractTask.java @@ -14,14 +14,14 @@ * limitations under the License. */ -package cn.enaium.joe.task; +package cn.enaium.joe.core.task; import java.util.concurrent.Callable; import java.util.function.Supplier; /** * @author Enaium - * @since 0.10.0 + * @since 2.0.0 */ public abstract class AbstractTask implements Supplier { private final String name; diff --git a/src/main/java/cn/enaium/joe/task/DecompileTask.java b/core/src/main/java/cn/enaium/joe/core/task/DecompileTask.java similarity index 54% rename from src/main/java/cn/enaium/joe/task/DecompileTask.java rename to core/src/main/java/cn/enaium/joe/core/task/DecompileTask.java index 47c78fb..da75e7d 100644 --- a/src/main/java/cn/enaium/joe/task/DecompileTask.java +++ b/core/src/main/java/cn/enaium/joe/core/task/DecompileTask.java @@ -14,30 +14,45 @@ * limitations under the License. */ -package cn.enaium.joe.task; +package cn.enaium.joe.core.task; -import cn.enaium.joe.annotation.Repeatable; -import cn.enaium.joe.service.DecompileService; +import cn.enaium.joe.core.annotation.Repeatable; +import cn.enaium.joe.core.config.ConfigManager; +import cn.enaium.joe.core.config.extend.ApplicationConfig; +import cn.enaium.joe.core.decompiler.CFRDecompiler; +import cn.enaium.joe.core.decompiler.FernFlowerDecompiler; +import cn.enaium.joe.core.decompiler.ProcyonDecompiler; +import cn.enaium.joe.core.model.JarModel; + +import cn.enaium.joe.core.util.DecompileUtil; import org.objectweb.asm.tree.ClassNode; import org.pmw.tinylog.Logger; +import java.io.IOException; +import java.io.StringWriter; +import java.util.Map; + /** * @author Enaium - * @since 0.10.0 + * @since 2.0.0 */ @Repeatable public class DecompileTask extends AbstractTask { + private final JarModel jar; + private final ConfigManager config; private final ClassNode classNode; - public DecompileTask(ClassNode classNode) { + public DecompileTask(JarModel jar, ConfigManager config, ClassNode classNode) { super("Decompile"); + this.jar = jar; + this.config = config; this.classNode = classNode; } @Override public String get() { Logger.info("DECOMPILE:{}", classNode.name); - return DecompileService.getService().decompile(classNode); + return DecompileUtil.get(jar, config, classNode); } } diff --git a/src/main/java/cn/enaium/joe/task/InputJarTask.java b/core/src/main/java/cn/enaium/joe/core/task/InputJarTask.java old mode 100644 new mode 100755 similarity index 50% rename from src/main/java/cn/enaium/joe/task/InputJarTask.java rename to core/src/main/java/cn/enaium/joe/core/task/InputJarTask.java index c31eaf6..ffd300a --- a/src/main/java/cn/enaium/joe/task/InputJarTask.java +++ b/core/src/main/java/cn/enaium/joe/core/task/InputJarTask.java @@ -14,57 +14,52 @@ * limitations under the License. */ -package cn.enaium.joe.task; +package cn.enaium.joe.core.task; -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.config.extend.ApplicationConfig; -import cn.enaium.joe.jar.Jar; -import cn.enaium.joe.util.ASMUtil; -import cn.enaium.joe.util.IOUtil; -import cn.enaium.joe.util.MessageUtil; -import cn.enaium.joe.util.Util; +import cn.enaium.joe.core.model.JarModel; +import cn.enaium.joe.core.util.ASMUtil; +import cn.enaium.joe.core.util.ZipUtil; import org.objectweb.asm.ClassReader; -import org.objectweb.asm.tree.ClassNode; -import org.pmw.tinylog.Logger; -import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; -import java.io.InputStream; import java.util.Enumeration; import java.util.jar.JarEntry; import java.util.jar.JarFile; /** + * Input jar task + * * @author Enaium - * @since 0.10.0 + * @since 2.0.0 */ -public class InputJarTask extends AbstractTask { +public class InputJarTask extends AbstractTask { + private final File file; public InputJarTask(File file) { - super("InputJar"); + super("Input Jar"); this.file = file; } @Override - public Jar get() { - Logger.info("LOAD:{}", file.getAbsolutePath()); - Jar jar = new Jar(); + public JarModel get() { + var jarModel = new JarModel(); + try { - JarFile jarFile = new JarFile(file); + var jarFile = new JarFile(file); float loaded = 0; - float files = Util.countFiles(jarFile); + float files = ZipUtil.countFiles(jarFile); Enumeration entries = jarFile.entries(); while (entries.hasMoreElements()) { JarEntry jarEntry = entries.nextElement(); if (jarEntry.getName().endsWith(".class")) { - ClassReader classReader = new ClassReader(IOUtil.getBytes(jarFile.getInputStream(new JarEntry(jarEntry.getName())))); - jar.classes.put(jarEntry.getName(), ASMUtil.acceptClassNode(classReader)); + ClassReader classReader = new ClassReader(jarFile.getInputStream(new JarEntry(jarEntry.getName()))); + jarModel.classes.put(jarEntry.getName(), ASMUtil.acceptClassNode(classReader)); } else if (!jarEntry.isDirectory()) { - jar.resources.put(jarEntry.getName(), IOUtil.getBytes(jarFile.getInputStream(new JarEntry(jarEntry.getName())))); + jarModel.resources.put(jarEntry.getName(), jarFile.getInputStream(new JarEntry(jarEntry.getName())).readAllBytes()); } setProgress((int) ((loaded++ / files) * 100f)); } @@ -73,9 +68,6 @@ public Jar get() { throw new RuntimeException(e); } - JavaOctetEditor.getInstance().config.getByClass(ApplicationConfig.class).loadRecent.getValue().add(file.getAbsolutePath()); - JavaOctetEditor.getInstance().setJar(jar); - JavaOctetEditor.getInstance().window.setTitle(JavaOctetEditor.TITLE + "-" + file.getName()); - return jar; + return jarModel; } } diff --git a/src/main/java/cn/enaium/joe/task/OutputJarTask.java b/core/src/main/java/cn/enaium/joe/core/task/OutputJarTask.java similarity index 88% rename from src/main/java/cn/enaium/joe/task/OutputJarTask.java rename to core/src/main/java/cn/enaium/joe/core/task/OutputJarTask.java index 6177624..77812bd 100644 --- a/src/main/java/cn/enaium/joe/task/OutputJarTask.java +++ b/core/src/main/java/cn/enaium/joe/core/task/OutputJarTask.java @@ -14,11 +14,9 @@ * limitations under the License. */ -package cn.enaium.joe.task; +package cn.enaium.joe.core.task; -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.jar.Jar; -import cn.enaium.joe.util.MessageUtil; +import cn.enaium.joe.core.model.JarModel; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.tree.ClassNode; @@ -31,13 +29,13 @@ /** * @author Enaium - * @since 0.10.0 + * @since 2.0.0 */ public class OutputJarTask extends AbstractTask { - private final Jar jar; + private final JarModel jar; private final File out; - public OutputJarTask(Jar jar, File out) { + public OutputJarTask(JarModel jar, File out) { super("OutputJar"); this.jar = jar; this.out = out; @@ -66,8 +64,7 @@ public Boolean get() { zipOutputStream.closeEntry(); zipOutputStream.close(); } catch (IOException ex) { - MessageUtil.error(ex); - return false; + throw new RuntimeException(ex); } return true; } diff --git a/src/main/java/cn/enaium/joe/task/RemappingTask.java b/core/src/main/java/cn/enaium/joe/core/task/RemappingTask.java similarity index 84% rename from src/main/java/cn/enaium/joe/task/RemappingTask.java rename to core/src/main/java/cn/enaium/joe/core/task/RemappingTask.java index adba0c7..ad96b9c 100644 --- a/src/main/java/cn/enaium/joe/task/RemappingTask.java +++ b/core/src/main/java/cn/enaium/joe/core/task/RemappingTask.java @@ -14,14 +14,12 @@ * limitations under the License. */ -package cn.enaium.joe.task; - -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.annotation.Indeterminate; -import cn.enaium.joe.jar.Jar; -import cn.enaium.joe.mapping.Mapping; -import cn.enaium.joe.mapping.MappingParser; -import cn.enaium.joe.util.MessageUtil; +package cn.enaium.joe.core.task; + +import cn.enaium.joe.core.annotation.Indeterminate; +import cn.enaium.joe.core.mapping.Mapping; +import cn.enaium.joe.core.mapping.MappingParser; +import cn.enaium.joe.core.model.JarModel; import net.fabricmc.mappingio.format.MappingFormat; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.Opcodes; @@ -35,41 +33,40 @@ /** * @author Enaium - * @since 1.0.0 + * @since 2.0.0 */ @Indeterminate -public class RemappingTask extends AbstractTask { - - +public class RemappingTask extends AbstractTask { public final Map> superHashMap = new HashMap<>(); + private final JarModel jar; private final File mapping; private final MappingFormat mappingFormat; - public RemappingTask(File mapping, MappingFormat mappingFormat) { + public RemappingTask(JarModel jar, File mapping, MappingFormat mappingFormat) { super("Remapping"); + this.jar = jar; this.mapping = mapping; this.mappingFormat = mappingFormat; } @Override - public Boolean get() { + public JarModel get() { if (mappingFormat == MappingFormat.ENIGMA) { if (!mapping.getName().endsWith(".mapping")) { - MessageUtil.warning("File suffix must be mapping"); + throw new RuntimeException("File suffix must be mapping"); } } try { Mapping read = MappingParser.read(mapping.toPath(), mappingFormat); - Jar oldJar = JavaOctetEditor.getInstance().getJar(); - Jar jar = new Jar(); - jar.resources.putAll(oldJar.resources); + JarModel newJar = new JarModel(); + newJar.resources.putAll(jar.resources); - oldJar.classes.values().forEach(this::analyze); + jar.classes.values().forEach(this::analyze); - for (Map.Entry stringClassNodeEntry : oldJar.classes.entrySet()) { + for (Map.Entry stringClassNodeEntry : jar.classes.entrySet()) { ClassNode classNode = new ClassNode(); ClassRemapper classRemapper = new ClassRemapper(new ClassVisitor(Opcodes.ASM9, classNode) { }, new SimpleRemapper(read.MAP) { @@ -107,13 +104,12 @@ public String mapMethodName(String owner, String name, String descriptor) { } }); stringClassNodeEntry.getValue().accept(classRemapper); - jar.classes.put(stringClassNodeEntry.getKey(), classNode); + newJar.classes.put(stringClassNodeEntry.getKey(), classNode); } - JavaOctetEditor.getInstance().setJar(jar); + return newJar; } catch (IOException ex) { throw new RuntimeException(ex); } - return true; } public void analyze(ClassNode classNode) { diff --git a/src/main/java/cn/enaium/joe/task/SaveAllSourceTask.java b/core/src/main/java/cn/enaium/joe/core/task/SaveAllSourceTask.java similarity index 75% rename from src/main/java/cn/enaium/joe/task/SaveAllSourceTask.java rename to core/src/main/java/cn/enaium/joe/core/task/SaveAllSourceTask.java index c1a716a..fe9373d 100644 --- a/src/main/java/cn/enaium/joe/task/SaveAllSourceTask.java +++ b/core/src/main/java/cn/enaium/joe/core/task/SaveAllSourceTask.java @@ -14,13 +14,11 @@ * limitations under the License. */ -package cn.enaium.joe.task; +package cn.enaium.joe.core.task; -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.jar.Jar; -import cn.enaium.joe.service.DecompileService; -import cn.enaium.joe.service.decompiler.ProcyonDecompiler; -import cn.enaium.joe.util.MessageUtil; +import cn.enaium.joe.core.config.ConfigManager; +import cn.enaium.joe.core.model.JarModel; +import cn.enaium.joe.core.util.DecompileUtil; import org.objectweb.asm.tree.ClassNode; import java.io.File; @@ -34,16 +32,18 @@ /** * @author Enaium - * @since 0.10.0 + * @since 2.0.0 */ public class SaveAllSourceTask extends AbstractTask { - private final Jar jar; + private final JarModel jar; private final File out; + private final ConfigManager config; - public SaveAllSourceTask(Jar jar, File out) { + public SaveAllSourceTask(JarModel jar, File out, ConfigManager config) { super("SaveAllSource"); this.jar = jar; this.out = out; + this.config = config; } @Override @@ -53,11 +53,11 @@ public Boolean get() { try { ZipOutputStream zipOutputStream = new ZipOutputStream(Files.newOutputStream(out.toPath())); - for (ClassNode value : jar.classes.values()) { - String name = value.name + ".java"; + for (ClassNode classNode : jar.classes.values()) { + String name = classNode.name + ".java"; name = "src/main/java/" + name; zipOutputStream.putNextEntry(new ZipEntry(name)); - zipOutputStream.write(DecompileService.getService().decompile(value).getBytes(StandardCharsets.UTF_8)); + zipOutputStream.write(DecompileUtil.get(jar, config, classNode).getBytes(StandardCharsets.UTF_8)); setProgress((int) ((loaded++ / files) * 100f)); } @@ -70,10 +70,9 @@ public Boolean get() { } zipOutputStream.closeEntry(); zipOutputStream.close(); + return true; } catch (IOException ex) { - MessageUtil.error(ex); - return false; + throw new RuntimeException(ex); } - return true; } } diff --git a/src/main/java/cn/enaium/joe/task/SearchFieldTask.java b/core/src/main/java/cn/enaium/joe/core/task/SearchFieldTask.java similarity index 55% rename from src/main/java/cn/enaium/joe/task/SearchFieldTask.java rename to core/src/main/java/cn/enaium/joe/core/task/SearchFieldTask.java index 84fe2b5..7d16998 100644 --- a/src/main/java/cn/enaium/joe/task/SearchFieldTask.java +++ b/core/src/main/java/cn/enaium/joe/core/task/SearchFieldTask.java @@ -14,31 +14,27 @@ * limitations under the License. */ -package cn.enaium.joe.task; +package cn.enaium.joe.core.task; -import cn.enaium.joe.gui.panel.search.ResultNode; -import cn.enaium.joe.jar.Jar; -import cn.enaium.joe.util.ColorUtil; -import cn.enaium.joe.util.HtmlUtil; -import cn.enaium.joe.util.StringUtil; +import cn.enaium.joe.core.model.JarModel; +import cn.enaium.joe.core.model.SearchResultModel; import org.objectweb.asm.tree.FieldInsnNode; -import java.awt.*; import java.util.ArrayList; import java.util.List; /** * @author Enaium - * @since 0.10.0 + * @since 2.0.0 */ -public class SearchFieldTask extends SearchInstructionTask> { +public class SearchFieldTask extends SearchInstructionTask> { private final String owner; private final String name; private final String description; - public SearchFieldTask(Jar jar, String owner, String name, String description) { + public SearchFieldTask(JarModel jar, String owner, String name, String description) { super("SearchField", jar); this.owner = owner; this.name = name; @@ -46,16 +42,15 @@ public SearchFieldTask(Jar jar, String owner, String name, String description) { } @Override - public List get() { - List resultNodes = new ArrayList<>(); + public List get() { + var resultNodes = new ArrayList(); searchInstruction((classNode, instruction) -> { - if (instruction instanceof FieldInsnNode) { - FieldInsnNode fieldInsnNode = (FieldInsnNode) instruction; - if ((fieldInsnNode.owner.contains(owner) || StringUtil.isBlank(owner)) && - (fieldInsnNode.name.contains(name) || StringUtil.isBlank(name)) && - (fieldInsnNode.desc.contains(description) || StringUtil.isBlank(description)) + if (instruction instanceof FieldInsnNode fieldInsnNode) { + if ((fieldInsnNode.owner.contains(owner) || owner.isBlank()) && + (fieldInsnNode.name.contains(name) || name.isBlank()) && + (fieldInsnNode.desc.contains(description) || description.isBlank()) ) { - resultNodes.add(new ResultNode(classNode, HtmlUtil.setColor(fieldInsnNode.name, ColorUtil.name) + HtmlUtil.setColor(":", ColorUtil.opcode) + HtmlUtil.setColor(fieldInsnNode.desc, ColorUtil.desc))); + resultNodes.add(new SearchResultModel(classNode, instruction)); } } }); diff --git a/src/main/java/cn/enaium/joe/task/SearchInstructionTask.java b/core/src/main/java/cn/enaium/joe/core/task/SearchInstructionTask.java similarity index 90% rename from src/main/java/cn/enaium/joe/task/SearchInstructionTask.java rename to core/src/main/java/cn/enaium/joe/core/task/SearchInstructionTask.java index 2c2534a..09fb169 100644 --- a/src/main/java/cn/enaium/joe/task/SearchInstructionTask.java +++ b/core/src/main/java/cn/enaium/joe/core/task/SearchInstructionTask.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package cn.enaium.joe.task; +package cn.enaium.joe.core.task; -import cn.enaium.joe.jar.Jar; +import cn.enaium.joe.core.model.JarModel; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.MethodNode; @@ -26,13 +26,13 @@ /** * @author Enaium - * @since 0.10.0 + * @since 2.0.0 */ public abstract class SearchInstructionTask extends AbstractTask { - private final Jar jar; + private final JarModel jar; - public SearchInstructionTask(String name, Jar jar) { + public SearchInstructionTask(String name, JarModel jar) { super(name); this.jar = jar; } diff --git a/src/main/java/cn/enaium/joe/task/SearchLdcTask.java b/core/src/main/java/cn/enaium/joe/core/task/SearchLdcTask.java similarity index 60% rename from src/main/java/cn/enaium/joe/task/SearchLdcTask.java rename to core/src/main/java/cn/enaium/joe/core/task/SearchLdcTask.java index 5c4b1f1..bf3679f 100644 --- a/src/main/java/cn/enaium/joe/task/SearchLdcTask.java +++ b/core/src/main/java/cn/enaium/joe/core/task/SearchLdcTask.java @@ -14,39 +14,36 @@ * limitations under the License. */ -package cn.enaium.joe.task; +package cn.enaium.joe.core.task; -import cn.enaium.joe.gui.panel.search.ResultNode; -import cn.enaium.joe.jar.Jar; -import cn.enaium.joe.util.ColorUtil; -import cn.enaium.joe.util.HtmlUtil; +import cn.enaium.joe.core.model.JarModel; +import cn.enaium.joe.core.model.SearchResultModel; import org.objectweb.asm.tree.LdcInsnNode; -import javax.swing.*; import java.util.ArrayList; import java.util.List; /** * @author Enaium - * @since 0.10.0 + * @since 2.0.0 */ -public class SearchLdcTask extends SearchInstructionTask> { +public class SearchLdcTask extends SearchInstructionTask> { private final Object ldc; - public SearchLdcTask(Jar jar, Object ldc) { + public SearchLdcTask(JarModel jar, Object ldc) { super("SearchLdc", jar); this.ldc = ldc; } @Override - public List get() { - List resultNodes = new ArrayList<>(); + public List get() { + var resultNodes = new ArrayList(); searchInstruction((classNode, instruction) -> { - if (instruction instanceof LdcInsnNode) { - String ldc = ((LdcInsnNode) instruction).cst.toString(); + if (instruction instanceof LdcInsnNode ldcInsnNode) { + String ldc = ldcInsnNode.cst.toString(); if (ldc.contains(this.ldc.toString())) { - resultNodes.add(new ResultNode(classNode, HtmlUtil.setColor(ldc, ColorUtil.string))); + resultNodes.add(new SearchResultModel(classNode, instruction)); } } }); diff --git a/src/main/java/cn/enaium/joe/task/SearchMethodTask.java b/core/src/main/java/cn/enaium/joe/core/task/SearchMethodTask.java similarity index 51% rename from src/main/java/cn/enaium/joe/task/SearchMethodTask.java rename to core/src/main/java/cn/enaium/joe/core/task/SearchMethodTask.java index 77e19f3..760a693 100644 --- a/src/main/java/cn/enaium/joe/task/SearchMethodTask.java +++ b/core/src/main/java/cn/enaium/joe/core/task/SearchMethodTask.java @@ -14,14 +14,10 @@ * limitations under the License. */ -package cn.enaium.joe.task; +package cn.enaium.joe.core.task; -import cn.enaium.joe.gui.panel.search.ResultNode; -import cn.enaium.joe.jar.Jar; -import cn.enaium.joe.util.ColorUtil; -import cn.enaium.joe.util.HtmlUtil; -import cn.enaium.joe.util.StringUtil; -import org.objectweb.asm.tree.FieldInsnNode; +import cn.enaium.joe.core.model.JarModel; +import cn.enaium.joe.core.model.SearchResultModel; import org.objectweb.asm.tree.MethodInsnNode; import java.util.ArrayList; @@ -29,9 +25,9 @@ /** * @author Enaium - * @since 0.10.0 + * @since 2.0.0 */ -public class SearchMethodTask extends SearchInstructionTask> { +public class SearchMethodTask extends SearchInstructionTask> { private final String owner; private final String name; @@ -40,8 +36,8 @@ public class SearchMethodTask extends SearchInstructionTask> { private final boolean itf; - public SearchMethodTask(Jar jar, String owner, String name, String description, boolean itf) { - super("SearchField", jar); + public SearchMethodTask(JarModel jar, String owner, String name, String description, boolean itf) { + super("SearchMethod", jar); this.owner = owner; this.name = name; this.description = description; @@ -49,20 +45,16 @@ public SearchMethodTask(Jar jar, String owner, String name, String description, } @Override - public List get() { - List resultNodes = new ArrayList<>(); + public List get() { + var resultNodes = new ArrayList(); searchInstruction((classNode, instruction) -> { - if (instruction instanceof MethodInsnNode) { - MethodInsnNode methodInsnNode = (MethodInsnNode) instruction; - if ((methodInsnNode.owner.contains(owner) || StringUtil.isBlank(owner)) && - (methodInsnNode.name.contains(name) || StringUtil.isBlank(name)) && - (methodInsnNode.desc.contains(description) || StringUtil.isBlank(description)) && + if (instruction instanceof MethodInsnNode methodInsnNode) { + if ((methodInsnNode.owner.contains(owner) || owner.isBlank()) && + (methodInsnNode.name.contains(name) || name.isBlank()) && + (methodInsnNode.desc.contains(description) || description.isBlank()) && (methodInsnNode.itf || !itf) ) { - resultNodes.add(new ResultNode(classNode, HtmlUtil.setColor(methodInsnNode.name, ColorUtil.name) - + HtmlUtil.setColor(":", ColorUtil.opcode) - + HtmlUtil.setColor(methodInsnNode.desc, ColorUtil.desc) - + HtmlUtil.setColor(String.valueOf(methodInsnNode.itf), ColorUtil.bool))); + resultNodes.add(new SearchResultModel(classNode, instruction)); } } }); diff --git a/core/src/main/java/cn/enaium/joe/core/task/SearchOpcodeTask.java b/core/src/main/java/cn/enaium/joe/core/task/SearchOpcodeTask.java new file mode 100644 index 0000000..ba2c0a9 --- /dev/null +++ b/core/src/main/java/cn/enaium/joe/core/task/SearchOpcodeTask.java @@ -0,0 +1,48 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.core.task; + +import cn.enaium.joe.core.model.JarModel; +import cn.enaium.joe.core.model.SearchResultModel; +import cn.enaium.joe.core.util.OpcodeUtil; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Enaium + */ +public class SearchOpcodeTask extends SearchInstructionTask> { + + private final String opcode; + + public SearchOpcodeTask(JarModel jar, String opcode) { + super("SearchOpcode", jar); + this.opcode = opcode; + } + + @Override + public List get() { + var resultNodes = new ArrayList(); + searchInstruction((classNode, instruction) -> { + if (String.valueOf(instruction.getOpcode()).equals(opcode) || opcode.equals(OpcodeUtil.OPCODE.get(instruction.getOpcode()))) { + resultNodes.add(new SearchResultModel(classNode, instruction)); + } + }); + return resultNodes; + } +} diff --git a/src/main/java/cn/enaium/joe/task/TaskManager.java b/core/src/main/java/cn/enaium/joe/core/task/TaskManager.java old mode 100644 new mode 100755 similarity index 81% rename from src/main/java/cn/enaium/joe/task/TaskManager.java rename to core/src/main/java/cn/enaium/joe/core/task/TaskManager.java index 6b64368..378b0dd --- a/src/main/java/cn/enaium/joe/task/TaskManager.java +++ b/core/src/main/java/cn/enaium/joe/core/task/TaskManager.java @@ -14,33 +14,28 @@ * limitations under the License. */ -package cn.enaium.joe.task; +package cn.enaium.joe.core.task; -import cn.enaium.joe.annotation.Repeatable; -import cn.enaium.joe.util.MessageUtil; -import cn.enaium.joe.util.Pair; +import cn.enaium.joe.core.annotation.Repeatable; +import cn.enaium.joe.core.util.Pair; -import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import java.util.logging.Logger; /** * @author Enaium - * @since 0.10.0 + * @since 2.0.0 */ public class TaskManager { private final ExecutorService executorService = Executors.newCachedThreadPool(); - private final List, CompletableFuture>> task = new ArrayList<>(); + private final List, CompletableFuture>> task = new CopyOnWriteArrayList<>(); public CompletableFuture submit(AbstractTask abstractTask) { for (Pair, CompletableFuture> classCompletableFuturePair : task) { if (classCompletableFuturePair.getKey().getClass().equals(abstractTask.getClass()) && !classCompletableFuturePair.getKey().getClass().isAnnotationPresent(Repeatable.class)) { - MessageUtil.warning("task already exists"); throw new RuntimeException("task already exists"); } } @@ -48,7 +43,7 @@ public CompletableFuture submit(AbstractTask abstractTask) { completableFuture.whenComplete((t, throwable) -> { task.removeIf(it -> it.getValue().isDone()); if (throwable != null) { - MessageUtil.error(throwable); + throw new RuntimeException(throwable); } }); @@ -56,7 +51,7 @@ public CompletableFuture submit(AbstractTask abstractTask) { return completableFuture; } - public List, CompletableFuture>> getTask() { + public List, CompletableFuture>> getAll() { return task; } } diff --git a/src/main/java/cn/enaium/joe/util/ASMUtil.java b/core/src/main/java/cn/enaium/joe/core/util/ASMUtil.java old mode 100644 new mode 100755 similarity index 71% rename from src/main/java/cn/enaium/joe/util/ASMUtil.java rename to core/src/main/java/cn/enaium/joe/core/util/ASMUtil.java index 8033fc1..394e27e --- a/src/main/java/cn/enaium/joe/util/ASMUtil.java +++ b/core/src/main/java/cn/enaium/joe/core/util/ASMUtil.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.enaium.joe.util; +package cn.enaium.joe.core.util; import org.objectweb.asm.ClassReader; import org.objectweb.asm.Type; @@ -27,10 +27,18 @@ /** * @author Enaium - * @since 1.2.0 + * @since 2.0.0 */ public class ASMUtil { - public static Object toType(Class type, String text) { + /** + * converts a string value to a value of that type + * + * @param type value type + * @param text value text + * @param value type + * @return value of type + */ + public static Object valueOf(Class type, String text) { try { Method valueOf = type.getMethod("valueOf", String.class); return valueOf.invoke(null, text); @@ -43,6 +51,13 @@ public static Object toType(Class type, String text) { } } + + /** + * accept as class node + * + * @param classReader class reader + * @return class node + */ public static ClassNode acceptClassNode(ClassReader classReader) { ClassNode classNode = new ClassNode(); try { @@ -57,6 +72,12 @@ public static ClassNode acceptClassNode(ClassReader classReader) { return classNode; } + /** + * get all parents, include interfaces + * + * @param classNode class node + * @return all interfaces and superclasses + */ public static Set getParentClass(ClassNode classNode) { Set parent = new HashSet<>(); if (classNode.superName != null && !classNode.superName.equals(Object.class.getName().replace(".", "/"))) { @@ -65,4 +86,14 @@ public static Set getParentClass(ClassNode classNode) { parent.addAll(classNode.interfaces); return parent; } + + /** + * replace all `/` to `.` + * + * @param classNode class node + * @return reference name + */ + public static String getReferenceName(ClassNode classNode) { + return classNode.name.replace("/", "."); + } } diff --git a/core/src/main/java/cn/enaium/joe/core/util/DecompileUtil.java b/core/src/main/java/cn/enaium/joe/core/util/DecompileUtil.java new file mode 100644 index 0000000..175a3a3 --- /dev/null +++ b/core/src/main/java/cn/enaium/joe/core/util/DecompileUtil.java @@ -0,0 +1,52 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.core.util; + +import cn.enaium.joe.core.config.ConfigManager; +import cn.enaium.joe.core.config.extend.ApplicationConfig; +import cn.enaium.joe.core.decompiler.CFRDecompiler; +import cn.enaium.joe.core.decompiler.FernFlowerDecompiler; +import cn.enaium.joe.core.decompiler.ProcyonDecompiler; +import cn.enaium.joe.core.model.JarModel; +import org.objectweb.asm.tree.ClassNode; + +import java.io.IOException; + +/** + * @author Enaium + * @since 2.0.0 + */ +public class DecompileUtil { + public static String get(JarModel jar, ConfigManager config, ClassNode classNode) { + switch (config.getByClass(ApplicationConfig.class).decompilerMode.getValue()) { + case "CFR" -> { + return new CFRDecompiler(jar, config, classNode).decompile(); + } + case "Procyon" -> { + return new ProcyonDecompiler(jar, config, classNode).decompile(); + } + case "FernFlower" -> { + try { + return new FernFlowerDecompiler(jar, config, classNode).decompile(); + } catch (IOException | NoSuchFieldException | IllegalAccessException e) { + return e.getMessage(); + } + } + } + return "NULL"; + } +} diff --git a/src/main/java/cn/enaium/joe/util/ListUtil.java b/core/src/main/java/cn/enaium/joe/core/util/ListUtil.java similarity index 93% rename from src/main/java/cn/enaium/joe/util/ListUtil.java rename to core/src/main/java/cn/enaium/joe/core/util/ListUtil.java index bb42281..7ac44e1 100644 --- a/src/main/java/cn/enaium/joe/util/ListUtil.java +++ b/core/src/main/java/cn/enaium/joe/core/util/ListUtil.java @@ -14,13 +14,13 @@ * limitations under the License. */ -package cn.enaium.joe.util; +package cn.enaium.joe.core.util; import java.util.List; /** * @author Enaium - * @since 1.2.0 + * @since 2.0.0 */ public class ListUtil { public static Class getType(List list) { diff --git a/src/main/java/cn/enaium/joe/util/OpcodeUtil.java b/core/src/main/java/cn/enaium/joe/core/util/OpcodeUtil.java similarity index 99% rename from src/main/java/cn/enaium/joe/util/OpcodeUtil.java rename to core/src/main/java/cn/enaium/joe/core/util/OpcodeUtil.java index 5965fc5..080be89 100644 --- a/src/main/java/cn/enaium/joe/util/OpcodeUtil.java +++ b/core/src/main/java/cn/enaium/joe/core/util/OpcodeUtil.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.enaium.joe.util; +package cn.enaium.joe.core.util; import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.AbstractInsnNode; @@ -28,7 +28,7 @@ /** * @author Enaium - * @since 0.8.0 + * @since 2.0.0 */ public class OpcodeUtil { public static final Map API = new HashMap() {{ diff --git a/src/main/java/cn/enaium/joe/util/Pair.java b/core/src/main/java/cn/enaium/joe/core/util/Pair.java old mode 100644 new mode 100755 similarity index 97% rename from src/main/java/cn/enaium/joe/util/Pair.java rename to core/src/main/java/cn/enaium/joe/core/util/Pair.java index 13e23c2..eb8be44 --- a/src/main/java/cn/enaium/joe/util/Pair.java +++ b/core/src/main/java/cn/enaium/joe/core/util/Pair.java @@ -14,13 +14,13 @@ * limitations under the License. */ -package cn.enaium.joe.util; +package cn.enaium.joe.core.util; import java.util.Objects; /** * @author Enaium - * @since 1.0.0 + * @since 2.0.0 */ public class Pair { private K key; diff --git a/src/main/java/cn/enaium/joe/util/ReflectUtil.java b/core/src/main/java/cn/enaium/joe/core/util/ReflectUtil.java old mode 100644 new mode 100755 similarity index 70% rename from src/main/java/cn/enaium/joe/util/ReflectUtil.java rename to core/src/main/java/cn/enaium/joe/core/util/ReflectUtil.java index 65cde6a..5d2f669 --- a/src/main/java/cn/enaium/joe/util/ReflectUtil.java +++ b/core/src/main/java/cn/enaium/joe/core/util/ReflectUtil.java @@ -14,21 +14,30 @@ * limitations under the License. */ -package cn.enaium.joe.util; +package cn.enaium.joe.core.util; import java.lang.reflect.Field; import java.lang.reflect.Method; /** * @author Enaium - * @since 1.0.0 + * @since 2.0.0 */ public class ReflectUtil { - public static void setAll(T old, T t) throws NoSuchFieldException, IllegalAccessException { - for (Field oldField : old.getClass().getDeclaredFields()) { + /** + * copy all class member from the old class object to the new class object + * + * @param oldObject old object + * @param newObject new object + * @param type of two classes + * @throws NoSuchFieldException e + * @throws IllegalAccessException e + */ + public static void copyAllMember(T oldObject, T newObject) throws NoSuchFieldException, IllegalAccessException { + for (Field oldField : oldObject.getClass().getDeclaredFields()) { oldField.setAccessible(true); - Field declaredField = t.getClass().getDeclaredField(oldField.getName()); - oldField.set(old, declaredField.get(t)); + Field declaredField = newObject.getClass().getDeclaredField(oldField.getName()); + oldField.set(oldObject, declaredField.get(newObject)); } } diff --git a/src/main/java/cn/enaium/joe/util/Util.java b/core/src/main/java/cn/enaium/joe/core/util/ZipUtil.java old mode 100644 new mode 100755 similarity index 59% rename from src/main/java/cn/enaium/joe/util/Util.java rename to core/src/main/java/cn/enaium/joe/core/util/ZipUtil.java index 7358e50..7b3bb73 --- a/src/main/java/cn/enaium/joe/util/Util.java +++ b/core/src/main/java/cn/enaium/joe/core/util/ZipUtil.java @@ -14,18 +14,19 @@ * limitations under the License. */ -package cn.enaium.joe.util; +package cn.enaium.joe.core.util; import java.util.Enumeration; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; /** * @author Enaium + * @since 2.0.0 */ -public class Util { - public static int countFiles(JarFile zipFile) { - final Enumeration entries = zipFile.entries(); +public class ZipUtil { + public static int countFiles(ZipFile zipFile) { + final Enumeration entries = zipFile.entries(); int c = 0; while (entries.hasMoreElements()) { entries.nextElement(); @@ -33,17 +34,4 @@ public static int countFiles(JarFile zipFile) { } return c; } - - public static boolean isText(byte[] bytes) { - int total = bytes.length; - if (total >= 8000) { - total = 8000; - } - for (int i = 0; i < total; i++) { - if (((char) bytes[i]) == '\0') { - return false; - } - } - return true; - } } diff --git a/src/main/java/cn/enaium/joe/wrapper/LabelNodeWrapper.java b/core/src/main/java/cn/enaium/joe/core/wrapper/LabelNodeWrapper.java similarity index 90% rename from src/main/java/cn/enaium/joe/wrapper/LabelNodeWrapper.java rename to core/src/main/java/cn/enaium/joe/core/wrapper/LabelNodeWrapper.java index 355a05a..1d275ac 100644 --- a/src/main/java/cn/enaium/joe/wrapper/LabelNodeWrapper.java +++ b/core/src/main/java/cn/enaium/joe/core/wrapper/LabelNodeWrapper.java @@ -14,14 +14,14 @@ * limitations under the License. */ -package cn.enaium.joe.wrapper; +package cn.enaium.joe.core.wrapper; -import cn.enaium.joe.util.OpcodeUtil; +import cn.enaium.joe.core.util.OpcodeUtil; import org.objectweb.asm.tree.LabelNode; /** * @author Enaium - * @since 0.8.0 + * @since 2.0.0 */ public class LabelNodeWrapper extends Wrapper { public LabelNodeWrapper(LabelNode wrapper) { diff --git a/src/main/java/cn/enaium/joe/wrapper/ObjectWrapper.java b/core/src/main/java/cn/enaium/joe/core/wrapper/ObjectWrapper.java similarity index 96% rename from src/main/java/cn/enaium/joe/wrapper/ObjectWrapper.java rename to core/src/main/java/cn/enaium/joe/core/wrapper/ObjectWrapper.java index 6f92611..c8d20a0 100644 --- a/src/main/java/cn/enaium/joe/wrapper/ObjectWrapper.java +++ b/core/src/main/java/cn/enaium/joe/core/wrapper/ObjectWrapper.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.enaium.joe.wrapper; +package cn.enaium.joe.core.wrapper; import org.objectweb.asm.Type; import org.objectweb.asm.tree.AnnotationNode; @@ -25,7 +25,7 @@ /** * @author Enaium - * @since 1.2.0 + * @since 2.0.0 */ public class ObjectWrapper extends Wrapper { public ObjectWrapper(Object wrapper) { diff --git a/src/main/java/cn/enaium/joe/wrapper/Wrapper.java b/core/src/main/java/cn/enaium/joe/core/wrapper/Wrapper.java similarity index 94% rename from src/main/java/cn/enaium/joe/wrapper/Wrapper.java rename to core/src/main/java/cn/enaium/joe/core/wrapper/Wrapper.java index 2e59d42..5de4d05 100644 --- a/src/main/java/cn/enaium/joe/wrapper/Wrapper.java +++ b/core/src/main/java/cn/enaium/joe/core/wrapper/Wrapper.java @@ -14,11 +14,11 @@ * limitations under the License. */ -package cn.enaium.joe.wrapper; +package cn.enaium.joe.core.wrapper; /** * @author Enaium - * @since 0.8.0 + * @since 2.0.0 */ public class Wrapper { diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar old mode 100644 new mode 100755 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties old mode 100644 new mode 100755 diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 diff --git a/gradlew.bat b/gradlew.bat old mode 100644 new mode 100755 diff --git a/settings.gradle b/settings.gradle old mode 100644 new mode 100755 index 0627ce9..6200c84 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1,4 @@ rootProject.name = 'JavaOctetEditor' +include 'core' +include 'ui' diff --git a/src/main/java/cn/enaium/joe/Agent.java b/src/main/java/cn/enaium/joe/Agent.java deleted file mode 100644 index 3a5a6a6..0000000 --- a/src/main/java/cn/enaium/joe/Agent.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe; - -import cn.enaium.joe.jar.Jar; -import cn.enaium.joe.util.ReflectUtil; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.tree.ClassNode; - -import java.io.IOException; -import java.lang.instrument.Instrumentation; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.URL; -import java.net.URLClassLoader; - -/** - * @author Enaium - * @since 1.1.0 - */ -public class Agent { - public static void premain(String agentArgs, Instrumentation inst) throws Exception { - agent(agentArgs, inst); - } - - public static void agentmain(String agentArgs, Instrumentation inst) throws Exception { - agent(agentArgs, inst); - } - - private static void agent(String agentArgs, Instrumentation inst) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { - URLClassLoader loader = new URLClassLoader(new URL[]{Agent.class.getProtectionDomain().getCodeSource().getLocation()}, ClassLoader.getSystemClassLoader().getParent()); - Class main = loader.loadClass("cn.enaium.joe.Main"); - Method agent = ReflectUtil.getMethod(main, "agent", Instrumentation.class); - agent.invoke(null, inst); - } -} diff --git a/src/main/java/cn/enaium/joe/JavaOctetEditor.java b/src/main/java/cn/enaium/joe/JavaOctetEditor.java deleted file mode 100644 index f3ba9c1..0000000 --- a/src/main/java/cn/enaium/joe/JavaOctetEditor.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe; - -import cn.enaium.joe.config.ConfigManager; -import cn.enaium.joe.event.EventManager; -import cn.enaium.joe.gui.panel.BottomPanel; -import cn.enaium.joe.gui.panel.file.tree.CenterPanel; -import cn.enaium.joe.gui.panel.file.tabbed.FileTabbedPanel; -import cn.enaium.joe.gui.component.FileTree; -import cn.enaium.joe.gui.panel.menu.*; -import cn.enaium.joe.jar.Jar; -import cn.enaium.joe.task.TaskManager; -import cn.enaium.joe.util.BytecodeTokenMaker; -import cn.enaium.joe.util.LangUtil; -import cn.enaium.joe.util.MessageUtil; -import cn.enaium.joe.util.ReflectUtil; -import com.formdev.flatlaf.extras.FlatSVGIcon; -import org.fife.ui.rsyntaxtextarea.AbstractTokenMakerFactory; -import org.fife.ui.rsyntaxtextarea.TokenMakerFactory; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.*; - -/** - * @author Enaium - */ -public class JavaOctetEditor { - private static JavaOctetEditor instance; - - public static final String TITLE = "JavaOctetEditor"; - - public JFrame window = new JFrame(TITLE); - - private Jar jar; - - public FileTabbedPanel fileTabbedPanel; - - public FileTree fileTree; - - public BottomPanel bottomPanel; - - public EventManager event; - - public ConfigManager config; - - public TaskManager task; - - - public JavaOctetEditor() { - instance = this; - event = new EventManager(); - config = new ConfigManager(); - config.load(); - task = new TaskManager(); - Runtime.getRuntime().addShutdownHook(new Thread(config::save)); - fileTabbedPanel = new FileTabbedPanel(); - fileTree = new FileTree(); - bottomPanel = new BottomPanel(); - } - - public void run() { - - ToolTipManager.sharedInstance().setInitialDelay(0); - - AbstractTokenMakerFactory abstractTokenMakerFactory = (AbstractTokenMakerFactory) TokenMakerFactory.getDefaultInstance(); - abstractTokenMakerFactory.putMapping("text/custom", BytecodeTokenMaker.class.getName()); - - window.setIconImage(new FlatSVGIcon("icons/logo.svg").getImage()); - - window.setJMenuBar(new JMenuBar() {{ - add(new FileMenu()); - add(new SearchMenu()); - - AttachMenu attachMenu = new AttachMenu() {{ - if (!ReflectUtil.classHas("com.sun.tools.attach.VirtualMachine")) { - setEnabled(false); - } - }}; - add(attachMenu); - add(new MappingMenu()); - add(new ConfigMenu()); - add(new HelpMenu()); - }}); - - window.setContentPane(new JPanel(new BorderLayout()) {{ - add(new CenterPanel(), BorderLayout.CENTER); - add(bottomPanel, BorderLayout.SOUTH); - }}); - - - window.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); - window.addWindowListener(new WindowAdapter() { - @Override - public void windowClosing(WindowEvent e) { - MessageUtil.confirm(LangUtil.i18n("dialog.wantCloseWindow"), LangUtil.i18n("warning"), () -> { - window.dispose(); - System.exit(0); - }, () -> { - }); - } - }); - window.setSize(1000, 600); - window.setLocationRelativeTo(null); - window.setVisible(true); - } - - public Jar getJar() { - return jar; - } - - public void setJar(Jar jar) { - this.jar = jar; - fileTree.refresh(jar); - } - - public static JavaOctetEditor getInstance() { - return instance; - } -} diff --git a/src/main/java/cn/enaium/joe/Main.java b/src/main/java/cn/enaium/joe/Main.java deleted file mode 100644 index b08c32f..0000000 --- a/src/main/java/cn/enaium/joe/Main.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe; - -import cn.enaium.joe.jar.Jar; -import cn.enaium.joe.util.IOUtil; -import cn.enaium.joe.util.MessageUtil; -import cn.enaium.joe.util.ReflectUtil; -import cn.enaium.joe.util.TinyLogPrintStream; -import com.formdev.flatlaf.FlatDarkLaf; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.tree.ClassNode; -import org.pmw.tinylog.Configurator; -import org.pmw.tinylog.Logger; -import org.pmw.tinylog.writers.ConsoleWriter; -import org.pmw.tinylog.writers.FileWriter; - -import javax.swing.*; -import java.io.IOException; -import java.lang.instrument.Instrumentation; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLClassLoader; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Objects; - -import static cn.enaium.joe.util.TinyLogPrintStream.Type.STDERR; -import static cn.enaium.joe.util.TinyLogPrintStream.Type.STDOUT; - -/** - * @author Enaium - */ -public final class Main { - public static void main(String[] args) { - loadTools(); - launch(); - } - - - private static void agent(Instrumentation inst) throws IOException { - launch(); - Jar jar = new Jar(); - for (Class allLoadedClass : inst.getAllLoadedClasses()) { - String name = allLoadedClass.getName().replace('.', '/'); - if (name.contains("$$") || name.contains("[") || !inst.isModifiableClass(allLoadedClass) - || allLoadedClass.getClassLoader() == Main.class.getClassLoader() - || name.matches("(java|sun|javax|com.sun|jdk|javafx).+")) { - continue; - } - - ClassNode classNode = new ClassNode(); - ClassReader classReader = new ClassReader(IOUtil.getBytes(Objects.requireNonNull(ClassLoader.getSystemClassLoader().getResourceAsStream(name + ".class")))); - classReader.accept(classNode, 0); - jar.classes.put(allLoadedClass.getName(), classNode); - } - JavaOctetEditor.getInstance().setJar(jar); - } - - private static void launch() { - Configurator.currentConfig().writer(new ConsoleWriter(), "[{date: HH:mm:ss.SSS}] {level} > {message}").addWriter(new FileWriter("latest.log"), "[{date: HH:mm:ss.SSS}] {level} > {message}").activate(); - System.setOut(new TinyLogPrintStream(System.out, STDOUT)); - System.setErr(new TinyLogPrintStream(System.err, STDERR)); - - Logger.info("DIR:{}", System.getProperty("user.dir")); - FlatDarkLaf.setup(); - UIManager.put("Tree.paintLines", true); - new JavaOctetEditor().run(); - } - - private static void loadTools() { - if (!ReflectUtil.classHas("com.sun.tools.attach.VirtualMachine")) { - Path toolsPath = Paths.get("lib", "tools.jar"); - Path jrePath = Paths.get(System.getProperty("java.home")); - Path tool = jrePath.getParent().resolve(toolsPath); - if (Files.notExists(tool)) { - Logger.warn("Please use jdk to run"); - return; - } - try { - Method addURL = URLClassLoader.class.getDeclaredMethod("addURL", URL.class); - addURL.setAccessible(true); - addURL.invoke(Main.class.getClassLoader(), tool.toUri().toURL()); - } catch (NoSuchMethodException | MalformedURLException | InvocationTargetException | - IllegalAccessException e) { - MessageUtil.error(e); - } - } - } -} diff --git a/src/main/java/cn/enaium/joe/config/ConfigManager.java b/src/main/java/cn/enaium/joe/config/ConfigManager.java deleted file mode 100644 index 33e9ae6..0000000 --- a/src/main/java/cn/enaium/joe/config/ConfigManager.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.config; - -import cn.enaium.joe.config.extend.ApplicationConfig; -import cn.enaium.joe.config.extend.CFRConfig; -import cn.enaium.joe.config.extend.FernFlowerConfig; -import cn.enaium.joe.config.extend.ProcyonConfig; -import cn.enaium.joe.config.value.*; -import cn.enaium.joe.util.MessageUtil; -import cn.enaium.joe.util.ReflectUtil; -import com.google.gson.*; -import com.google.gson.annotations.Expose; - -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Field; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.util.*; - -/** - * @author Enaium - * @since 0.7.0 - */ -public class ConfigManager { - private final Map, Config> configMap = new LinkedHashMap<>(); - - public ConfigManager() { - setByClass(new ApplicationConfig()); - setByClass(new CFRConfig()); - setByClass(new FernFlowerConfig()); - setByClass(new ProcyonConfig()); - } - - @SuppressWarnings("unchecked") - public T getByClass(Class klass) { - if (configMap.containsKey(klass)) { - return (T) configMap.get(klass); - } else { - throw new RuntimeException("Not found " + klass); - } - } - - public void setByClass(Config config) { - configMap.put(config.getClass(), config); - } - - public Map, Config> getConfig() { - return configMap; - } - - public Map getConfigMap(Class config) { - Map map = new HashMap<>(); - for (Field declaredField : config.getDeclaredFields()) { - declaredField.setAccessible(true); - try { - Object o = declaredField.get(getByClass(config)); - if (o instanceof Value) { - Object value = ((Value) o).getValue(); - if (value != null) { - map.put(declaredField.getName(), value.toString()); - } - } - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - } - return map; - } - - private Gson gson() { - return new GsonBuilder().setPrettyPrinting().create(); - } - - public void load() { - for (Map.Entry, Config> classConfigEntry : configMap.entrySet()) { - - Class klass = classConfigEntry.getKey(); - Config config = classConfigEntry.getValue(); - try { - File file = new File(System.getProperty("."), config.getName() + ".json"); - if (file.exists()) { - JsonObject jsonObject = gson().fromJson(new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8), JsonObject.class); - - for (Field configField : klass.getDeclaredFields()) { - configField.setAccessible(true); - if (!jsonObject.has(configField.getName())) { - continue; - } - - if (!jsonObject.has(configField.getName())) { - continue; - } - - if (!jsonObject.get(configField.getName()).getAsJsonObject().has("value")) { - continue; - } - - JsonElement valueJsonElement = jsonObject.get(configField.getName()).getAsJsonObject().get("value"); - - Object valueObject = configField.get(config); - if (valueObject instanceof Value) { - Value value = (Value) valueObject; - if (value instanceof EnableValue) { - ((EnableValue) value).setValue(valueJsonElement.getAsBoolean()); - } else if (value instanceof IntegerValue) { - ((IntegerValue) value).setValue(valueJsonElement.getAsInt()); - } else if (value instanceof ModeValue) { - ModeValue modeValue = (ModeValue) value; - if (modeValue.getMode().contains(valueJsonElement.getAsString())) { - modeValue.setValue(valueJsonElement.getAsString()); - } else { - modeValue.setValue(modeValue.getMode().get(0)); - } - } else if (value instanceof StringSetValue) { - Set strings = new HashSet<>(); - for (JsonElement jsonElement : valueJsonElement.getAsJsonArray()) { - strings.add(jsonElement.getAsString()); - } - ((StringSetValue) value).setValue(strings); - } else if (value instanceof StringValue) { - ((StringValue) value).setValue(valueJsonElement.getAsString()); - } - } - } - } - } catch (Throwable e) { - MessageUtil.error(e); - } - } - } - - public void save() { - for (Config value : configMap.values()) { - try { - Files.write(new File(System.getProperty("."), value.getName() + ".json").toPath(), gson().toJson(value).getBytes(StandardCharsets.UTF_8)); - } catch (IOException e) { - MessageUtil.error(e); - } - } - } -} diff --git a/src/main/java/cn/enaium/joe/dialog/AboutDialog.java b/src/main/java/cn/enaium/joe/dialog/AboutDialog.java deleted file mode 100644 index 76d1687..0000000 --- a/src/main/java/cn/enaium/joe/dialog/AboutDialog.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.dialog; - -import cn.enaium.joe.util.LangUtil; -import cn.enaium.joe.util.ReflectUtil; -import net.miginfocom.swing.MigLayout; - -import javax.swing.*; -import javax.swing.border.EmptyBorder; -import javax.tools.ToolProvider; - -/** - * @author Enaium - */ -public class AboutDialog extends Dialog { - public AboutDialog() { - super(LangUtil.i18n("menu.help.about")); - setContentPane(new JPanel(new MigLayout("fillx", "[fill][fill]")) {{ - setBorder(new EmptyBorder(10, 10, 10, 10)); - add(new JLabel(LangUtil.i18n("about.system")), "wrap"); - add(new JLabel(LangUtil.i18n("about.system.description")), "wrap"); - - add(new JLabel(LangUtil.i18n("about.system.name"))); - add(new JLabel(System.getProperty("os.name")), "wrap"); - add(new JLabel(LangUtil.i18n("about.system.architecture"))); - add(new JLabel(System.getProperty("os.arch")), "wrap"); - - add(new JSeparator(), "span 2"); - add(new JLabel(), "wrap"); - - add(new JLabel(LangUtil.i18n("about.java")), "wrap"); - add(new JLabel(LangUtil.i18n("about.java.description")), "wrap"); - - - add(new JLabel(LangUtil.i18n("about.java.version"))); - add(new JLabel(System.getProperty("java.version")), "wrap"); - add(new JLabel(LangUtil.i18n("about.java.vm.name"))); - add(new JLabel(System.getProperty("java.vm.name")), "wrap"); - add(new JLabel(LangUtil.i18n("about.java.vm.vendor"))); - add(new JLabel(System.getProperty("java.vm.vendor")), "wrap"); - add(new JLabel(LangUtil.i18n("about.java.home"))); - add(new JLabel(System.getProperty("java.home")), "wrap"); - add(new JLabel(LangUtil.i18n("about.java.supportCompiler"))); - add(new JLabel(String.valueOf(ToolProvider.getSystemJavaCompiler() != null)), "wrap"); - add(new JLabel(LangUtil.i18n("about.java.supportAttach"))); - add(new JLabel(String.valueOf(ReflectUtil.classHas("com.sun.tools.attach.VirtualMachine"))), "wrap"); - }}); - setResizable(false); - pack(); - } -} diff --git a/src/main/java/cn/enaium/joe/dialog/AnnotationListDialog.java b/src/main/java/cn/enaium/joe/dialog/AnnotationListDialog.java deleted file mode 100644 index 6818b37..0000000 --- a/src/main/java/cn/enaium/joe/dialog/AnnotationListDialog.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.dialog; - -import cn.enaium.joe.util.JMenuUtil; -import cn.enaium.joe.util.LangUtil; -import cn.enaium.joe.wrapper.ObjectWrapper; -import org.objectweb.asm.tree.AnnotationNode; - -import javax.swing.*; -import javax.swing.table.DefaultTableModel; -import java.awt.*; -import java.util.List; - -/** - * @author Enaium - * @since 1.2.0 - */ -public class AnnotationListDialog extends Dialog { - public AnnotationListDialog(List annotationNodes) { - super("Annotation"); - setLayout(new BorderLayout()); - DefaultTableModel dm = new DefaultTableModel(new Object[][]{}, new String[]{"Description", "Has Value"}); - for (AnnotationNode annotationNode : annotationNodes) { - dm.addRow(new Object[]{new ObjectWrapper(annotationNode), annotationNode.values != null}); - } - JTable jTable = new JTable(dm) { - public boolean isCellEditable(int row, int column) { - return false; - } - }; - jTable.getTableHeader().setReorderingAllowed(false); - jTable.getTableHeader().setResizingAllowed(false); - add(new JScrollPane(jTable), BorderLayout.CENTER); - JMenuUtil.addPopupMenu(jTable, () -> new JPopupMenu() {{ - add(new JMenuItem(LangUtil.i18n("button.edit")) {{ - addActionListener(e -> { - new AnnotationValueDialog(((AnnotationNode) ((ObjectWrapper) dm.getValueAt(jTable.getSelectedRow(), 0)).getWrapper()).values).setVisible(true); - }); - }}); - }}, () -> jTable.getSelectedRow() != -1 && Boolean.parseBoolean(dm.getValueAt(jTable.getSelectedRow(), 1).toString())); - } -} diff --git a/src/main/java/cn/enaium/joe/dialog/AnnotationValueDialog.java b/src/main/java/cn/enaium/joe/dialog/AnnotationValueDialog.java deleted file mode 100644 index c679a29..0000000 --- a/src/main/java/cn/enaium/joe/dialog/AnnotationValueDialog.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.dialog; - -import cn.enaium.joe.gui.panel.confirm.ListValueEditPanel; -import cn.enaium.joe.gui.panel.confirm.ValueEditPanel; -import cn.enaium.joe.util.JMenuUtil; -import cn.enaium.joe.util.LangUtil; -import cn.enaium.joe.util.ListUtil; -import cn.enaium.joe.util.MessageUtil; -import cn.enaium.joe.wrapper.ObjectWrapper; -import org.objectweb.asm.tree.AnnotationNode; - -import javax.swing.*; -import javax.swing.table.DefaultTableModel; -import java.awt.*; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -/** - * @author Enaium - * @since 1.2.0 - */ -public class AnnotationValueDialog extends Dialog { - public AnnotationValueDialog(List objects) { - super("Annotation Value"); - DefaultTableModel dm = new DefaultTableModel(new Object[][]{}, new String[]{"Description", "Value"}); - - for (Object object : objects) { - int index = objects.indexOf(object); - if (index % 2 == 1) { - dm.addRow(new Object[]{objects.get(index - 1), new ObjectWrapper(object)}); - } - } - JTable jTable = new JTable(dm) { - public boolean isCellEditable(int row, int column) { - return false; - } - }; - jTable.getTableHeader().setReorderingAllowed(false); - jTable.getTableHeader().setResizingAllowed(false); - add(new JScrollPane(jTable), BorderLayout.CENTER); - JMenuUtil.addPopupMenu(jTable, () -> new JPopupMenu() {{ - add(new JMenuItem(LangUtil.i18n("button.edit")) {{ - addActionListener(e -> { - ObjectWrapper valueAt = (ObjectWrapper) dm.getValueAt(jTable.getSelectedRow(), 1); - if (valueAt.getWrapper() instanceof ArrayList) { - @SuppressWarnings("unchecked") List wrapper = (List) valueAt.getWrapper(); - if (ListUtil.getType(wrapper) == AnnotationNode.class) { - new AnnotationListDialog(wrapper.stream().map(it -> ((AnnotationNode) it)).collect(Collectors.toList())).setVisible(true); - } else { - MessageUtil.confirm(new ListValueEditPanel(wrapper), "List"); - } - } else { - int index = (jTable.getSelectedRow() + 1) * 2 - 1; - if (valueAt.getWrapper().getClass().isArray()) { - ArrayList newList = new ArrayList<>(Arrays.asList(((Object[]) valueAt.getWrapper()))); - MessageUtil.confirm(new ListValueEditPanel(newList), "List", () -> { - String[] strings = newList.stream().map(Object::toString).toArray(String[]::new); - valueAt.setWrapper(strings); - objects.set(index, strings); - }); - } else { - ObjectWrapper objectWrapper = new ObjectWrapper(valueAt.getWrapper()); - ValueEditPanel confirmPanel = new ValueEditPanel(objectWrapper); - MessageUtil.confirm(confirmPanel, LangUtil.i18n("button.edit"), () -> { - valueAt.setWrapper(objectWrapper.getWrapper()); - objects.set(index, objectWrapper.getWrapper()); - }); - } - } - }); - }}); - }}, () -> jTable.getSelectedRow() != -1); - } -} diff --git a/src/main/java/cn/enaium/joe/dialog/CallTreeDialog.java b/src/main/java/cn/enaium/joe/dialog/CallTreeDialog.java deleted file mode 100644 index d19a53a..0000000 --- a/src/main/java/cn/enaium/joe/dialog/CallTreeDialog.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.dialog; - -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.gui.panel.BorderPanel; -import cn.enaium.joe.gui.panel.MemberListPanel; -import cn.enaium.joe.gui.panel.file.tree.node.MethodTreeNode; -import cn.enaium.joe.util.JMenuUtil; -import cn.enaium.joe.util.LangUtil; -import cn.enaium.joe.util.Pair; -import com.formdev.flatlaf.extras.FlatSVGIcon; -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.ClassNode; -import org.objectweb.asm.tree.MethodInsnNode; -import org.objectweb.asm.tree.MethodNode; - -import javax.swing.*; -import javax.swing.tree.DefaultTreeCellRenderer; -import javax.swing.tree.DefaultTreeModel; -import java.awt.*; -import java.util.*; - -/** - * @author Enaium - * @since 1.3.0 - */ -public class CallTreeDialog extends Dialog { - public CallTreeDialog(ClassNode classNode, MethodNode methodNode) { - super(LangUtil.i18n("popup.member.callTree")); - setContentPane(new BorderPanel() {{ - JTree call = new JTree() {{ - setModel(new DefaultTreeModel(new MethodTreeNode(classNode, methodNode) {{ - recursion(this); - }})); - - setCellRenderer(new DefaultTreeCellRenderer() { - @Override - public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { - setIcon(new FlatSVGIcon("icons/method.svg")); - setText(value.toString()); - return this; - } - }); - }}; - JMenuUtil.addPopupMenu(call, () -> { - MethodTreeNode lastPathComponent = (MethodTreeNode) Objects.requireNonNull(call.getSelectionPath()).getLastPathComponent(); - return MemberListPanel.getPopupMenu(new Pair<>(lastPathComponent.classNode, lastPathComponent.methodNode)); - }, () -> call.getSelectionPath() != null); - setCenter(new JScrollPane(call)); - }}); - } - - private final Set set = new HashSet<>(); - - private void recursion(MethodTreeNode methodTreeNode) { - MethodNode methodNode = methodTreeNode.methodNode; - Map> map = new HashMap<>(); - - for (AbstractInsnNode instruction : methodNode.instructions) { - if (instruction instanceof MethodInsnNode) { - MethodInsnNode methodInsnNode = (MethodInsnNode) instruction; - if (!(methodTreeNode.classNode.name + "." + methodNode.name + methodNode.desc).equals(methodInsnNode.owner + "." + methodInsnNode.name + methodInsnNode.desc)) { - Map classes = JavaOctetEditor.getInstance().getJar().classes; - String key = methodInsnNode.owner + ".class"; - if (classes.containsKey(key)) { - ClassNode classNode = classes.get(key); - //Find target method - for (MethodNode method : classNode.methods) { - if ((classNode.name + "." + method.name + method.desc).equals(methodInsnNode.owner + "." + methodInsnNode.name + methodInsnNode.desc)) { - //Deduplication - map.put(classNode.name + "." + method.name + method.desc, new Pair<>(classNode, method)); - break; - } - } - } - } - } - } - - for (Pair value : map.values()) { - MethodTreeNode newChild = new MethodTreeNode(value.getKey(), value.getValue()); - methodTreeNode.add(newChild); - if (!set.contains(value.getValue())) { - set.add(value.getValue()); - recursion(newChild); - } - } - } -} diff --git a/src/main/java/cn/enaium/joe/dialog/ConfigDialog.java b/src/main/java/cn/enaium/joe/dialog/ConfigDialog.java deleted file mode 100644 index 36b348a..0000000 --- a/src/main/java/cn/enaium/joe/dialog/ConfigDialog.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.dialog; - -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.annotation.NoUI; -import cn.enaium.joe.config.Config; -import cn.enaium.joe.config.value.*; -import cn.enaium.joe.util.LangUtil; -import cn.enaium.joe.util.MessageUtil; -import net.miginfocom.swing.MigLayout; - -import javax.swing.*; -import javax.swing.border.EmptyBorder; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; -import java.awt.*; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.lang.reflect.Field; - -/** - * @author Enaium - * @since 0.7.0 - */ -public class ConfigDialog extends Dialog { - public ConfigDialog(Config config) { - super(LangUtil.i18n("menu.config")); - - setContentPane(new JScrollPane(new JPanel(new MigLayout("fillx", "[fill][fill]")) {{ - try { - for (Field declaredField : config.getClass().getDeclaredFields()) { - declaredField.setAccessible(true); - - if (declaredField.isAnnotationPresent(NoUI.class)) { - continue; - } - - Object o = declaredField.get(config); - - if (o instanceof Value) { - Value value = (Value) o; - - add(new JLabel(value.getName()) {{ - setToolTipText(value.getDescription()); - }}); - } - - if (o instanceof StringValue) { - StringValue stringValue = (StringValue) o; - add(new JTextField(25) {{ - JTextField jTextField = this; - jTextField.setText(stringValue.getValue()); - getDocument().addDocumentListener(new DocumentListener() { - @Override - public void insertUpdate(DocumentEvent e) { - stringValue.setValue(jTextField.getText()); - } - - @Override - public void removeUpdate(DocumentEvent e) { - stringValue.setValue(jTextField.getText()); - } - - @Override - public void changedUpdate(DocumentEvent e) { - stringValue.setValue(jTextField.getText()); - } - }); - }}, "wrap"); - } else if (o instanceof IntegerValue) { - IntegerValue integerValue = (IntegerValue) o; - add(new JSpinner() {{ - addChangeListener(e -> integerValue.setValue(Integer.parseInt(getValue().toString()))); - }}, "wrap"); - } else if (o instanceof EnableValue) { - EnableValue enableValue = (EnableValue) o; - add(new JCheckBox() {{ - JCheckBox jCheckBox = this; - setHorizontalAlignment(JCheckBox.RIGHT); - setSelected(enableValue.getValue()); - addActionListener(e -> { - enableValue.setValue(jCheckBox.isSelected()); - }); - }}, "wrap"); - } else if (o instanceof ModeValue) { - add(new JComboBox(new DefaultComboBoxModel<>()) {{ - JComboBox jComboBox = this; - ModeValue modeValue = (ModeValue) o; - for (String s : modeValue.getMode()) { - DefaultComboBoxModel model = (DefaultComboBoxModel) getModel(); - model.addElement(s); - model.setSelectedItem(modeValue.getValue()); - jComboBox.addActionListener(e -> { - modeValue.setValue(model.getSelectedItem().toString()); - }); - } - }}, "wrap"); - } - } - } catch (IllegalAccessException e) { - MessageUtil.error(e); - } - }})); - addWindowListener(new WindowAdapter() { - @Override - public void windowClosing(WindowEvent e) { - JavaOctetEditor.getInstance().config.save(); - } - }); - } -} diff --git a/src/main/java/cn/enaium/joe/dialog/ContactDialog.java b/src/main/java/cn/enaium/joe/dialog/ContactDialog.java deleted file mode 100644 index e779b35..0000000 --- a/src/main/java/cn/enaium/joe/dialog/ContactDialog.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.dialog; - -import cn.enaium.joe.util.LangUtil; -import com.formdev.flatlaf.extras.FlatSVGIcon; -import net.miginfocom.swing.MigLayout; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Locale; - -/** - * @author Enaium - */ -public class ContactDialog extends Dialog { - public ContactDialog() { - super(LangUtil.i18n("menu.help.contact")); - setSize(290, 150); - setContentPane(new JPanel(new MigLayout()) {{ - addLink(this, "Github", new FlatSVGIcon("icons/github.svg"), "https://github.com/Enaium/JavaOctetEditor"); - if (Locale.getDefault().getLanguage().equals("zh")) { - addLink(this, "BiliBili", new FlatSVGIcon("icons/biliBili.svg"), "https://space.bilibili.com/44537204"); - addLink(this, "KOOK", new FlatSVGIcon("icons/kook.svg"), "https://kook.top/YaP12f"); - } - }}); - setResizable(false); - pack(); - } - - public void addLink(JPanel panel, String name, Icon icon, String link) { - panel.add(new JLabel(icon)); - panel.add(new JLabel(name)); - panel.add(new JLabel("" + link + "") {{ - addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - try { - Desktop.getDesktop().browse(new URI(link)); - } catch (IOException | URISyntaxException ex) { - throw new RuntimeException(ex); - } - } - }); - }}, "wrap"); - } -} diff --git a/src/main/java/cn/enaium/joe/dialog/ProcessListDialog.java b/src/main/java/cn/enaium/joe/dialog/ProcessListDialog.java deleted file mode 100644 index edb668d..0000000 --- a/src/main/java/cn/enaium/joe/dialog/ProcessListDialog.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.dialog; - -import cn.enaium.joe.Main; -import cn.enaium.joe.util.JFileChooserUtil; -import cn.enaium.joe.util.JMenuUtil; -import cn.enaium.joe.util.LangUtil; -import cn.enaium.joe.util.MessageUtil; -import com.formdev.flatlaf.extras.FlatSVGIcon; -import com.sun.tools.attach.*; -import com.sun.tools.attach.spi.AttachProvider; - -import javax.swing.*; -import javax.swing.border.EmptyBorder; -import javax.swing.table.DefaultTableModel; -import java.awt.*; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.io.File; -import java.io.IOException; -import java.util.List; -import java.util.Map; - -/** - * @author Enaium - * @since 1.1.0 - */ -public class ProcessListDialog extends Dialog { - public ProcessListDialog() { - super("ProcessList"); - setLayout(new BorderLayout()); - DefaultListModel virtualMachineDescriptorDefaultListModel = new DefaultListModel<>(); - JList jList = new JList<>(virtualMachineDescriptorDefaultListModel); - jList.setCellRenderer((list, value, index, isSelected, cellHasFocus) -> new JPanel(new BorderLayout()) {{ - setBorder(new EmptyBorder(5, 5, 5, 5)); - if (isSelected) { - setBackground(list.getSelectionBackground()); - } else { - setBackground(list.getBackground()); - } - try { - add(new JPanel(new BorderLayout()) {{ - add(new JLabel() {{ - setVerticalAlignment(JLabel.CENTER); - setIcon(new FlatSVGIcon("icons/openjdk.svg")); - }}, BorderLayout.CENTER); - }}, BorderLayout.WEST); - add(new JPanel(new BorderLayout()) {{ - add(new JLabel(String.format("%s - %s", value.getVirtualMachineDescriptor().id(), value.getVirtualMachineDescriptor().displayName())), BorderLayout.NORTH); - add(new JLabel("VM:" + value.getVirtualMachine().getSystemProperties().getProperty("java.vm.name")), BorderLayout.CENTER); - add(new JLabel("Version:" + value.getVirtualMachine().getSystemProperties().getProperty("java.version")), BorderLayout.SOUTH); - }}, BorderLayout.CENTER); - } catch (IOException ignore) { - - } - }}); - List list = VirtualMachine.list(); - for (VirtualMachineDescriptor virtualMachineDescriptor : list) { - try { - AttachProvider attachProvider = virtualMachineDescriptor.provider(); - VirtualMachine virtualMachine = attachProvider.attachVirtualMachine(virtualMachineDescriptor); - virtualMachineDescriptorDefaultListModel.addElement(new Process(virtualMachineDescriptor, virtualMachine)); - } catch (AttachNotSupportedException e) { - MessageUtil.error(e); - } catch (IOException ignore) { - - } - } - - JPopupMenu jPopupMenu = new JPopupMenu(); - jPopupMenu.add(new JMenuItem(LangUtil.i18n("popup.attach.properties")) {{ - addActionListener(e -> { - try { - new Dialog(jList.getSelectedValue().getVirtualMachineDescriptor().displayName()) {{ - setLayout(new BorderLayout()); - DefaultTableModel defaultTableModel = new DefaultTableModel(new Object[][]{}, new String[]{"Key", "Value"}); - add(new JScrollPane(new JTable(defaultTableModel)), BorderLayout.CENTER); - for (Map.Entry objectObjectEntry : jList.getSelectedValue().getVirtualMachine().getSystemProperties().entrySet()) { - defaultTableModel.addRow(new Object[]{objectObjectEntry.getKey(), objectObjectEntry.getValue()}); - } - }}.setVisible(true); - } catch (IOException ignore) { - - } - }); - }}); - jPopupMenu.add(new JMenuItem(LangUtil.i18n("menu.attach")) {{ - addActionListener(e -> { - MessageUtil.confirm("", LangUtil.i18n("menu.attach"), () -> { - try { - VirtualMachine virtualMachine = jList.getSelectedValue().getVirtualMachine(); - virtualMachine.loadAgent(new File(Main.class.getProtectionDomain().getCodeSource().getLocation().getFile()).getAbsolutePath()); - virtualMachine.detach(); - } catch (AgentLoadException | AgentInitializationException | IOException exception) { - MessageUtil.error(exception); - } - System.exit(0); - }); - }); - }}); - jPopupMenu.add(new JMenuItem(LangUtil.i18n("popup.attach.external")) {{ - addActionListener(e -> { - File show = JFileChooserUtil.show(JFileChooserUtil.Type.OPEN); - if (show != null) { - try { - VirtualMachine virtualMachine = jList.getSelectedValue().getVirtualMachine(); - virtualMachine.loadAgent(show.getAbsolutePath()); - virtualMachine.detach(); - } catch (AgentLoadException | AgentInitializationException | - IOException exception) { - MessageUtil.error(exception); - } - System.exit(0); - } - }); - }}); - JMenuUtil.addPopupMenu(jList, () -> jPopupMenu, () -> jList.getSelectedValue() != null); - - add(new JScrollPane(jList), BorderLayout.CENTER); - } - - private static class Process { - private final VirtualMachineDescriptor virtualMachineDescriptor; - private final VirtualMachine virtualMachine; - - public Process(VirtualMachineDescriptor virtualMachineDescriptor, VirtualMachine virtualMachine) { - this.virtualMachineDescriptor = virtualMachineDescriptor; - this.virtualMachine = virtualMachine; - } - - public VirtualMachineDescriptor getVirtualMachineDescriptor() { - return virtualMachineDescriptor; - } - - public VirtualMachine getVirtualMachine() { - return virtualMachine; - } - } -} diff --git a/src/main/java/cn/enaium/joe/dialog/SearchDialog.java b/src/main/java/cn/enaium/joe/dialog/SearchDialog.java deleted file mode 100644 index 453b70b..0000000 --- a/src/main/java/cn/enaium/joe/dialog/SearchDialog.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.dialog; - -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.gui.component.ResultList; -import cn.enaium.joe.jar.Jar; -import cn.enaium.joe.util.LangUtil; -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.ClassNode; -import org.objectweb.asm.tree.MethodNode; - -import javax.swing.*; -import java.awt.*; -import java.util.Map; -import java.util.function.BiConsumer; - -/** - * @author Enaium - */ -public class SearchDialog extends Dialog { - public ResultList resultList = new ResultList(); - - public SearchDialog() { - super(LangUtil.i18n("menu.search")); - setLayout(new BorderLayout()); - setSize(700, 400); - add(new JScrollPane(resultList), BorderLayout.CENTER); - } -} diff --git a/src/main/java/cn/enaium/joe/dialog/search/SearchFieldDialog.java b/src/main/java/cn/enaium/joe/dialog/search/SearchFieldDialog.java deleted file mode 100644 index c995728..0000000 --- a/src/main/java/cn/enaium/joe/dialog/search/SearchFieldDialog.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.dialog.search; - -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.dialog.SearchDialog; -import cn.enaium.joe.gui.panel.search.ResultNode; -import cn.enaium.joe.task.SearchFieldTask; -import cn.enaium.joe.util.LangUtil; -import cn.enaium.joe.util.MessageUtil; -import cn.enaium.joe.util.StringUtil; - -import javax.swing.*; -import java.awt.*; - -/** - * @author Enaium - * @since 0.5.0 - */ -public class SearchFieldDialog extends SearchDialog { - public SearchFieldDialog() { - setTitle(LangUtil.i18n("search.field.title")); - add(new JPanel(new FlowLayout()) {{ - add(new JLabel(LangUtil.i18n("search.owner"))); - JTextField owner = new JTextField(); - add(owner); - add(new JLabel(LangUtil.i18n("search.name"))); - JTextField name = new JTextField(); - add(name); - add(new JLabel(LangUtil.i18n("search.description"))); - JTextField description = new JTextField(); - add(description); - add(new JButton(LangUtil.i18n("button.search")) {{ - addActionListener(e -> { - - if (StringUtil.isBlank(owner.getText()) && StringUtil.isBlank(name.getText()) && StringUtil.isBlank(description.getText())) { - MessageUtil.warning("Please input"); - return; - } - - ((DefaultListModel) resultList.getModel()).clear(); - - JavaOctetEditor.getInstance().task - .submit(new SearchFieldTask(JavaOctetEditor.getInstance().getJar(), owner.getText(), name.getText(), description.getText())) - .thenAccept(it -> { - for (ResultNode resultNode : it) { - ((DefaultListModel) resultList.getModel()).addElement(resultNode); - } - }); - }); - }}); - }}, BorderLayout.SOUTH); - } -} diff --git a/src/main/java/cn/enaium/joe/dialog/search/SearchLdcDialog.java b/src/main/java/cn/enaium/joe/dialog/search/SearchLdcDialog.java deleted file mode 100644 index 1630128..0000000 --- a/src/main/java/cn/enaium/joe/dialog/search/SearchLdcDialog.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.dialog.search; - -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.dialog.SearchDialog; -import cn.enaium.joe.gui.panel.search.ResultNode; -import cn.enaium.joe.task.SearchFieldTask; -import cn.enaium.joe.task.SearchLdcTask; -import cn.enaium.joe.util.ASyncUtil; -import cn.enaium.joe.util.LangUtil; -import org.objectweb.asm.tree.LdcInsnNode; - -import javax.swing.*; -import java.awt.*; - -/** - * @author Enaium - */ -public class SearchLdcDialog extends SearchDialog { - public SearchLdcDialog() { - setTitle(LangUtil.i18n("search.ldc.title")); - add(new JPanel(new FlowLayout()) {{ - JTextField text = new JTextField(15); - add(text); - add(new JButton(LangUtil.i18n("button.search")) {{ - addActionListener(e -> { - if (!text.getText().isEmpty()) { - ((DefaultListModel) resultList.getModel()).clear(); - JavaOctetEditor.getInstance().task - .submit(new SearchLdcTask(JavaOctetEditor.getInstance().getJar(), text.getText())) - .thenAccept(it -> { - ((DefaultListModel) resultList.getModel()).clear(); - for (ResultNode resultNode : it) { - ((DefaultListModel) resultList.getModel()).addElement(resultNode); - } - }); - } - }); - }}); - }}, BorderLayout.SOUTH); - } -} diff --git a/src/main/java/cn/enaium/joe/dialog/search/SearchMethodDialog.java b/src/main/java/cn/enaium/joe/dialog/search/SearchMethodDialog.java deleted file mode 100644 index 08e9ac4..0000000 --- a/src/main/java/cn/enaium/joe/dialog/search/SearchMethodDialog.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.dialog.search; - -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.dialog.SearchDialog; -import cn.enaium.joe.gui.panel.search.ResultNode; -import cn.enaium.joe.task.SearchFieldTask; -import cn.enaium.joe.task.SearchMethodTask; -import cn.enaium.joe.util.ASyncUtil; -import cn.enaium.joe.util.LangUtil; -import cn.enaium.joe.util.MessageUtil; -import cn.enaium.joe.util.StringUtil; -import org.objectweb.asm.tree.*; - -import javax.swing.*; -import java.awt.*; - -/** - * @author Enaium - * @since 0.5.0 - */ -public class SearchMethodDialog extends SearchDialog { - public SearchMethodDialog() { - setTitle(LangUtil.i18n("search.method.title")); - add(new JPanel(new FlowLayout()) {{ - add(new JLabel(LangUtil.i18n("search.owner"))); - JTextField owner = new JTextField(); - add(owner); - add(new JLabel(LangUtil.i18n("search.name"))); - JTextField name = new JTextField(); - add(name); - add(new JLabel(LangUtil.i18n("search.description"))); - JTextField description = new JTextField(); - add(description); - JCheckBox anInterface = new JCheckBox(LangUtil.i18n("search.interface")); - add(anInterface); - add(new JButton(LangUtil.i18n("button.search")) {{ - addActionListener(e -> { - - - if (StringUtil.isBlank(owner.getText()) && StringUtil.isBlank(name.getText()) && StringUtil.isBlank(description.getText()) && !anInterface.isSelected()) { - MessageUtil.warning("Please input"); - return; - } - - - JavaOctetEditor.getInstance().task - .submit(new SearchMethodTask(JavaOctetEditor.getInstance().getJar(), owner.getText(), name.getText(), description.getText(), anInterface.isSelected())) - .thenAccept(it -> { - ((DefaultListModel) resultList.getModel()).clear(); - for (ResultNode resultNode : it) { - ((DefaultListModel) resultList.getModel()).addElement(resultNode); - } - }); - }); - }}); - }}, BorderLayout.SOUTH); - } -} diff --git a/src/main/java/cn/enaium/joe/event/EventManager.java b/src/main/java/cn/enaium/joe/event/EventManager.java deleted file mode 100644 index 452930f..0000000 --- a/src/main/java/cn/enaium/joe/event/EventManager.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.event; - -import cn.enaium.joe.util.Pair; - -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.function.Consumer; - -/** - * @author Enaium - * @since 1.2.0 - */ -public class EventManager { - List, Consumer>> listeners = new CopyOnWriteArrayList<>(); - - @SuppressWarnings("unchecked") - public void register(Class listener, Consumer consumer) { - listeners.add(new Pair<>(listener, ((Consumer) consumer))); - } - - public void call(Event event) { - listeners.stream().filter(it -> it.getKey() == event.getClass()).forEach(it -> it.getValue().accept(event)); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/component/FileTree.java b/src/main/java/cn/enaium/joe/gui/component/FileTree.java deleted file mode 100644 index fc35fa0..0000000 --- a/src/main/java/cn/enaium/joe/gui/component/FileTree.java +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.component; - -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.config.extend.ApplicationConfig; -import cn.enaium.joe.gui.panel.file.FileDropTarget; -import cn.enaium.joe.gui.panel.file.tabbed.tab.classes.ClassTabPanel; -import cn.enaium.joe.gui.panel.file.tabbed.tab.resources.FileTablePane; -import cn.enaium.joe.gui.panel.file.tree.FileTreeCellRenderer; -import cn.enaium.joe.gui.panel.file.tree.node.*; -import cn.enaium.joe.jar.Jar; -import cn.enaium.joe.task.InputJarTask; -import cn.enaium.joe.util.JMenuUtil; -import cn.enaium.joe.util.JTreeUtil; -import cn.enaium.joe.util.LangUtil; -import org.objectweb.asm.tree.ClassNode; - -import javax.swing.*; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.DefaultTreeModel; -import javax.swing.tree.MutableTreeNode; -import javax.swing.tree.TreeNode; -import java.awt.dnd.DnDConstants; -import java.awt.dnd.DropTarget; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.*; -import java.util.concurrent.CopyOnWriteArrayList; - -/** - * @author Enaium - */ -public class FileTree extends JTree { - - public static final DefaultTreeNode classesRoot = new DefaultTreeNode("classes"); - public static final DefaultTreeNode resourceRoot = new DefaultTreeNode("resources"); - - public FileTree() { - super(new DefaultTreeNode("") {{ - add(classesRoot); - add(resourceRoot); - }}); - - setRootVisible(false); - setShowsRootHandles(true); - setCellRenderer(new FileTreeCellRenderer()); - addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - if (e.getClickCount() == 2) { - addTab(); - } - } - }); - - new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, new FileDropTarget(".jar", files -> { - if (!files.isEmpty()) { - JavaOctetEditor.getInstance().task.submit(new InputJarTask(files.get(0))); - } - }), true); - - JPopupMenu jPopupMenu = new JPopupMenu(); - - - jPopupMenu.add(new JMenuItem(LangUtil.i18n("popup.fileTree.expandAll")) {{ - addActionListener(e -> { - JTreeUtil.setNodeExpandedState(FileTree.this, ((DefaultMutableTreeNode) Objects.requireNonNull(getSelectionPath()).getLastPathComponent()), true); - }); - }}); - JMenuUtil.addPopupMenu(this, () -> jPopupMenu, () -> getSelectionPath() != null); - } - - public void addTab() { - if (getSelectionPath() == null) { - return; - } - Object lastPathComponent = getSelectionPath().getLastPathComponent(); - SwingUtilities.invokeLater(() -> { - if (lastPathComponent instanceof PackageTreeNode) { - PackageTreeNode packageTreeNode = (PackageTreeNode) lastPathComponent; - if (packageTreeNode instanceof ClassTreeNode) { - ClassNode classNode = ((ClassTreeNode) packageTreeNode).classNode; - JavaOctetEditor.getInstance().fileTabbedPanel.addTab(classNode.name.substring(classNode.name.lastIndexOf("/") + 1), new ClassTabPanel(classNode)); - } - } else if (lastPathComponent instanceof FolderTreeNode) { - FolderTreeNode folderTreeNode = (FolderTreeNode) lastPathComponent; - if (folderTreeNode instanceof FileTreeNode) { - FileTreeNode fileTreeNode = (FileTreeNode) folderTreeNode; - JavaOctetEditor.getInstance().fileTabbedPanel.addTab(fileTreeNode.toString().substring(fileTreeNode.toString().lastIndexOf("/") + 1), new FileTablePane(fileTreeNode)); - } - } - JavaOctetEditor.getInstance().fileTabbedPanel.setSelectedIndex(JavaOctetEditor.getInstance().fileTabbedPanel.getTabCount() - 1); - }); - } - - public void refresh(Jar jar) { - DefaultTreeModel model = (DefaultTreeModel) getModel(); - model.reload(); - classesRoot.removeAllChildren(); - resourceRoot.removeAllChildren(); - - ApplicationConfig config = JavaOctetEditor.getInstance().config.getByClass(ApplicationConfig.class); - - - String packagePresentationValue = config.packagePresentation.getValue(); - - if (packagePresentationValue.equals("Hierarchical")) { - Map hasMap = new HashMap<>(); - - for (ClassNode classNode : jar.classes.values()) { - String[] split = classNode.name.split("/"); - DefaultTreeNode prev = null; - StringBuilder stringBuilder = new StringBuilder(); - int i = 0; - for (String s : split) { - stringBuilder.append(s); - PackageTreeNode packageTreeNode = new PackageTreeNode(s); - - if (split.length == i + 1) { - packageTreeNode = new ClassTreeNode(classNode); - } - - if (prev == null) { - if (!hasMap.containsKey(stringBuilder.toString())) { - classesRoot.add(packageTreeNode); - hasMap.put(stringBuilder.toString(), packageTreeNode); - prev = packageTreeNode; - } else { - prev = hasMap.get(stringBuilder.toString()); - } - } else { - if (!hasMap.containsKey(stringBuilder.toString())) { - prev.add(packageTreeNode); - hasMap.put(stringBuilder.toString(), packageTreeNode); - prev = packageTreeNode; - } else { - prev = hasMap.get(stringBuilder.toString()); - } - } - i++; - } - } - compact(model, classesRoot); - sort(model, classesRoot); - - hasMap.clear(); - - for (Map.Entry stringEntry : jar.resources.entrySet()) { - String[] split = stringEntry.getKey().split("/"); - DefaultTreeNode prev = null; - StringBuilder stringBuilder = new StringBuilder(); - int i = 0; - for (String s : split) { - stringBuilder.append(s); - FolderTreeNode folderTreeNode = new FolderTreeNode(s); - - if (split.length == i + 1) { - folderTreeNode = new FileTreeNode(s, stringEntry.getValue()); - } - - if (prev == null) { - if (!hasMap.containsKey(stringBuilder.toString())) { - resourceRoot.add(folderTreeNode); - hasMap.put(stringBuilder.toString(), folderTreeNode); - prev = folderTreeNode; - } else { - prev = hasMap.get(stringBuilder.toString()); - } - } else { - if (!hasMap.containsKey(stringBuilder.toString())) { - prev.add(folderTreeNode); - hasMap.put(stringBuilder.toString(), folderTreeNode); - prev = folderTreeNode; - } else { - prev = hasMap.get(stringBuilder.toString()); - } - } - i++; - } - } - compact(model, classesRoot); - sort(model, resourceRoot); - } else if (packagePresentationValue.equals("Flat")) { - Map hasMap = new HashMap<>(); - for (ClassNode value : jar.classes.values()) { - String packageName = ""; - if (value.name.contains("/")) { - packageName = value.name.substring(0, value.name.lastIndexOf("/")).replace("/", "."); - } - - ClassTreeNode classTreeNode = new ClassTreeNode(value); - - if (packageName.isEmpty()) { - classesRoot.add(classTreeNode); - } else { - DefaultTreeNode defaultTreeNode; - if (hasMap.containsKey(packageName)) { - defaultTreeNode = hasMap.get(packageName); - } else { - defaultTreeNode = new PackageTreeNode(packageName); - hasMap.put(packageName, defaultTreeNode); - } - defaultTreeNode.add(classTreeNode); - classesRoot.add(defaultTreeNode); - } - } - hasMap.clear(); - - for (Map.Entry stringEntry : jar.resources.entrySet()) { - String folderName = ""; - String name = stringEntry.getKey(); - if (stringEntry.getKey().contains("/")) { - folderName = stringEntry.getKey().substring(0, stringEntry.getKey().lastIndexOf("/")).replace("/", "."); - name = name.substring(name.lastIndexOf("/") + 1); - } - - FileTreeNode classTreeNode = new FileTreeNode(name, stringEntry.getValue()); - - if (folderName.isEmpty()) { - resourceRoot.add(classTreeNode); - } else { - DefaultTreeNode defaultTreeNode; - if (hasMap.containsKey(folderName)) { - defaultTreeNode = hasMap.get(folderName); - } else { - defaultTreeNode = new FolderTreeNode(folderName); - hasMap.put(folderName, defaultTreeNode); - } - defaultTreeNode.add(classTreeNode); - resourceRoot.add(defaultTreeNode); - } - } - sort(model, resourceRoot); - } - - JavaOctetEditor.getInstance().fileTabbedPanel.removeAll(); - - repaint(); - } - - public void compact(DefaultTreeModel defaultTreeModel, DefaultTreeNode defaultTreeNode) { - - if (!JavaOctetEditor.getInstance().config.getByClass(ApplicationConfig.class).compactMiddlePackage.getValue()) { - return; - } - - if (!defaultTreeNode.isLeaf()) { - DefaultTreeNode parent = (DefaultTreeNode) defaultTreeNode.getParent(); - if (parent.getChildren().size() == 1 && !(parent.equals(classesRoot) || parent.equals(resourceRoot))) { - parent.setUserObject(parent.getUserObject() + "." + defaultTreeNode.getUserObject()); - parent.getChildren().clear(); - for (DefaultTreeNode child : defaultTreeNode.getChildren()) { - child.setParent(parent); - parent.getChildren().add(child); - } - } - - - for (int i = 0; i < defaultTreeModel.getChildCount(defaultTreeNode); i++) { - DefaultTreeNode child = ((DefaultTreeNode) defaultTreeModel.getChild(defaultTreeNode, i)); - compact(defaultTreeModel, child); - } - } - } - - - public void sort(DefaultTreeModel defaultTreeModel, DefaultTreeNode defaultTreeNode) { - if (!defaultTreeNode.isLeaf()) { - defaultTreeNode.getChildren().sort((o1, o2) -> { - boolean class1 = o1 instanceof ClassTreeNode; - boolean class2 = o2 instanceof ClassTreeNode; - - boolean file1 = o1 instanceof FileTreeNode; - boolean file2 = o2 instanceof FileTreeNode; - - if (class1 && !class2) { - return 1; - } - if (!class1 && class2) { - return -1; - } - - if (file1 && !file2) { - return 1; - } - if (!file1 && file2) { - return -1; - } - return o1.toString().compareTo(o2.toString()); - }); - for (int i = 0; i < defaultTreeModel.getChildCount(defaultTreeNode); i++) { - DefaultTreeNode child = ((DefaultTreeNode) defaultTreeModel.getChild(defaultTreeNode, i)); - sort(defaultTreeModel, child); - } - } - } -} diff --git a/src/main/java/cn/enaium/joe/gui/component/LabelNodeComboBox.java b/src/main/java/cn/enaium/joe/gui/component/LabelNodeComboBox.java deleted file mode 100644 index 47d853d..0000000 --- a/src/main/java/cn/enaium/joe/gui/component/LabelNodeComboBox.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.component; - -import cn.enaium.joe.util.OpcodeUtil; -import cn.enaium.joe.wrapper.LabelNodeWrapper; -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.LabelNode; - -import javax.swing.*; - -/** - * @author Enaium - * @since 0.8.0 - */ -public class LabelNodeComboBox extends JComboBox { - public LabelNodeComboBox(AbstractInsnNode instruction, LabelNode select) { - super(new DefaultComboBoxModel<>()); - LabelNodeWrapper selected = null; - for (AbstractInsnNode abstractInsnNode : OpcodeUtil.getInstructionList(select)) { - if (abstractInsnNode instanceof LabelNode) { - LabelNodeWrapper anObject = new LabelNodeWrapper(((LabelNode) abstractInsnNode)); - if (abstractInsnNode.equals(select)) { - selected = anObject; - } - ((DefaultComboBoxModel) getModel()).addElement(anObject); - } - } - getModel().setSelectedItem(selected); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/component/ResultList.java b/src/main/java/cn/enaium/joe/gui/component/ResultList.java deleted file mode 100644 index 46ba2d5..0000000 --- a/src/main/java/cn/enaium/joe/gui/component/ResultList.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.component; - -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.gui.panel.file.tree.node.*; -import cn.enaium.joe.gui.panel.search.ResultNode; -import cn.enaium.joe.util.ASyncUtil; -import cn.enaium.joe.util.JMenuUtil; -import org.objectweb.asm.tree.ClassNode; - -import javax.swing.*; -import javax.swing.tree.DefaultTreeModel; -import javax.swing.tree.TreePath; -import java.awt.*; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; - -/** - * @author Enaium - */ -public class ResultList extends JList { - - public ResultList() { - super(new DefaultListModel<>()); - //avoid repeat updateFixedCellSize - setPrototypeCellValue(new ResultNode()); - //fix auto wrap - setCellRenderer((list, value, index, isSelected, cellHasFocus) -> new JPanel(new BorderLayout()) {{ - if (isSelected) { - setBackground(list.getSelectionBackground()); - } else { - setBackground(list.getBackground()); - } - JLabel comp = new JLabel(value.toString()); - add(comp, BorderLayout.CENTER); - }}); - JPopupMenu jPopupMenu = new JPopupMenu(); - JMenuItem jMenuItem = new JMenuItem("Jump to Node"); - jMenuItem.addActionListener(e -> { - if (getSelectedValue() != null) { - SwingUtilities.invokeLater(() -> { - FileTree fileTree = JavaOctetEditor.getInstance().fileTree; - DefaultTreeModel model = (DefaultTreeModel) fileTree.getModel(); - if (selectEntry(fileTree, getSelectedValue().getClassNode(), model, FileTree.classesRoot)) { - fileTree.addTab(); - fileTree.repaint(); - } - }); - } - }); - jPopupMenu.add(jMenuItem); - JMenuUtil.addPopupMenu(this, () -> jPopupMenu, () -> this.getSelectedValue() != null); - } - - public boolean selectEntry(JTree jTree, ClassNode classNode, DefaultTreeModel defaultTreeModel, DefaultTreeNode defaultTreeNode) { - for (int i = 0; i < defaultTreeModel.getChildCount(defaultTreeNode); i++) { - DefaultTreeNode child = ((DefaultTreeNode) defaultTreeModel.getChild(defaultTreeNode, i)); - if (child instanceof PackageTreeNode) { - PackageTreeNode packageTreeNode = (PackageTreeNode) child; - if (packageTreeNode instanceof ClassTreeNode) { - ClassTreeNode classTreeNode = (ClassTreeNode) packageTreeNode; - if (classNode.equals(classTreeNode.classNode)) { - TreePath treePath = new TreePath(defaultTreeModel.getPathToRoot(classTreeNode)); - jTree.setSelectionPath(treePath); - jTree.scrollPathToVisible(treePath); - return true; - } - } - } - if (!defaultTreeNode.isLeaf()) { - if (selectEntry(jTree, classNode, defaultTreeModel, child)) { - return true; - } - } - } - return false; - } -} diff --git a/src/main/java/cn/enaium/joe/gui/component/RightTabBar.java b/src/main/java/cn/enaium/joe/gui/component/RightTabBar.java deleted file mode 100644 index 16d2fd4..0000000 --- a/src/main/java/cn/enaium/joe/gui/component/RightTabBar.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.component; - -import cn.enaium.joe.gui.panel.InheritPanel; -import cn.enaium.joe.gui.panel.MemberListPanel; -import cn.enaium.joe.util.LangUtil; -import com.formdev.flatlaf.extras.FlatSVGIcon; - -import javax.swing.*; - -/** - * @author Enaium - * @since 1.3.0 - */ -public class RightTabBar extends TabPane { - public RightTabBar() { - super(TabPane.RIGHT); - addTab(LangUtil.i18n("sideTab.member"), new FlatSVGIcon("icons/structure.svg"), new MemberListPanel()); - addTab(LangUtil.i18n("sideTab.inherit"), new FlatSVGIcon("icons/inherit.svg"), new InheritPanel()); - cancelSelect(); - setVerticalLabel(); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/component/TabPane.java b/src/main/java/cn/enaium/joe/gui/component/TabPane.java deleted file mode 100644 index 61ed17f..0000000 --- a/src/main/java/cn/enaium/joe/gui/component/TabPane.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.component; - -import cn.enaium.joe.gui.ui.VerticalLabelUI; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.*; - -/** - * @author Enaium - * @since 1.2.0 - */ -public class TabPane extends JTabbedPane { - private final Map componentMap = new HashMap<>(); - private final Set selected = new HashSet() {{ - add(0); - }}; - - public TabPane(int tabPlacement) { - super(tabPlacement); - addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - if (selected.contains(getSelectedIndex())) { - cancelSelect(); - } else { - selected.add(getSelectedIndex()); - } - } - }); - } - - @Override - public void addTab(String title, Component component) { - addTab(title, null, component); - } - - public void addTab(String title, Icon icon, Component component) { - componentMap.put(componentMap.size(), component); - super.addTab(title, icon, null); - } - - @Override - public Component getSelectedComponent() { - return componentMap.get(getSelectedIndex()); - } - - public void cancelSelect() { - selected.clear(); - setSelectedIndex(-1); - } - - public void setVerticalLabel() { - for (int i = 0; i < getTabCount(); i++) { - int finalI = i; - setTabComponentAt(i, new JLabel(getTitleAt(i)) {{ - setIcon(getIconAt(finalI)); - setUI(new VerticalLabelUI(getTabPlacement() == RIGHT)); - }}); - } - } -} diff --git a/src/main/java/cn/enaium/joe/gui/layout/AbstractLayout.java b/src/main/java/cn/enaium/joe/gui/layout/AbstractLayout.java deleted file mode 100644 index 00a70cc..0000000 --- a/src/main/java/cn/enaium/joe/gui/layout/AbstractLayout.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.layout; - -import java.awt.*; - -/** - * @author Enaium - * @since 1.2.0 - */ -public abstract class AbstractLayout implements LayoutManager2 { - - @Override - public Dimension maximumLayoutSize(Container target) { - return null; - } - - @Override - public float getLayoutAlignmentX(Container target) { - return 0; - } - - @Override - public float getLayoutAlignmentY(Container target) { - return 0; - } - - @Override - public void invalidateLayout(Container target) { - - } - - @Override - public void addLayoutComponent(String name, Component comp) { - - } - - @Override - public void removeLayoutComponent(Component comp) { - - } -} diff --git a/src/main/java/cn/enaium/joe/gui/layout/HalfLayout.java b/src/main/java/cn/enaium/joe/gui/layout/HalfLayout.java deleted file mode 100644 index aba454e..0000000 --- a/src/main/java/cn/enaium/joe/gui/layout/HalfLayout.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.layout; - -import java.awt.*; -import java.util.HashMap; -import java.util.Map; - -/** - * @author Enaium - * @since 1.2.0 - */ -public class HalfLayout extends AbstractLayout { - private final Map componentMap = new HashMap<>(); - - private int minWidth = 0, minHeight = 0; - private int preferredWidth = 0, preferredHeight = 0; - - public static final String LEFT = "LEFT"; - public static final String RIGHT = "RIGHT"; - public static final String TOP = "TOP"; - public static final String BOTTOM = "BOTTOM"; - public static final int LEFT_AND_RIGHT = 0; - public static final int TOP_AND_BOTTOM = 1; - - private final int side; - - public HalfLayout() { - this(LEFT_AND_RIGHT); - } - - public HalfLayout(int side) { - this.side = side; - } - - private void setSizes(Container parent) { - int nComps = parent.getComponentCount(); - Dimension d; - - preferredWidth = 0; - preferredHeight = 0; - minWidth = 0; - minHeight = 0; - - for (int i = 0; i < nComps; i++) { - Component c = parent.getComponent(i); - d = c.getPreferredSize(); - - if (i > 0) { - preferredWidth += d.width / 2; - preferredHeight += 5; - } else { - preferredWidth = d.width; - if (side == LEFT_AND_RIGHT) { - preferredHeight += d.height; - } - } - - if (side == TOP_AND_BOTTOM) { - preferredHeight += d.height; - } - - minWidth = Math.max(c.getMinimumSize().width, minWidth); - minHeight = preferredHeight; - } - } - - @Override - public Dimension preferredLayoutSize(Container parent) { - Dimension dim = new Dimension(0, 0); - - setSizes(parent); - - Insets insets = parent.getInsets(); - dim.width = preferredWidth + insets.left + insets.right; - dim.height = preferredHeight + insets.top + insets.bottom; - return dim; - } - - @Override - public Dimension minimumLayoutSize(Container parent) { - Dimension dim = new Dimension(0, 0); - - Insets insets = parent.getInsets(); - dim.width = minWidth + insets.left + insets.right; - dim.height = minHeight + insets.top + insets.bottom; - - return dim; - } - - @Override - public void layoutContainer(Container parent) { - Component left = componentMap.get(LEFT); - Component right = componentMap.get(RIGHT); - - if (left == null) { - left = componentMap.get(TOP); - } - - if (right == null) { - right = componentMap.get(BOTTOM); - } - - - if (side == LEFT_AND_RIGHT) { - left.setBounds(0, 0, right.isVisible() ? parent.getWidth() / 2 : parent.getWidth(), parent.getHeight()); - right.setBounds(left.isVisible() ? parent.getWidth() / 2 : 0, 0, left.isVisible() ? parent.getWidth() / 2 : parent.getWidth(), parent.getHeight()); - } else if (side == TOP_AND_BOTTOM) { - left.setBounds(0, 0, parent.getWidth(), right.isVisible() ? parent.getHeight() / 2 : parent.getHeight()); - right.setBounds(0, left.isVisible() ? left.getHeight() : 0, parent.getWidth(), left.isVisible() ? parent.getHeight() / 2 : parent.getHeight()); - } - } - - @Override - public void addLayoutComponent(Component comp, Object constraints) { - componentMap.put(constraints.toString(), comp); - } - - public boolean isAllHide() { - boolean hide = true; - for (Map.Entry stringComponentEntry : componentMap.entrySet()) { - if (stringComponentEntry.getValue().isVisible()) { - hide = false; - break; - } - } - return hide; - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/BorderPanel.java b/src/main/java/cn/enaium/joe/gui/panel/BorderPanel.java deleted file mode 100644 index b807615..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/BorderPanel.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel; - -import javax.swing.*; -import java.awt.*; - -/** - * @author Enaium - * @since 1.3.0 - */ -public class BorderPanel extends JPanel { - public BorderPanel() { - super(new BorderLayout()); - } - - public void setCenter(Component component) { - add(component, BorderLayout.CENTER); - } - - public void setTop(Component component) { - add(component, BorderLayout.NORTH); - } - - public void setBottom(Component component) { - add(component, BorderLayout.SOUTH); - } - - public void setLeft(Component component) { - add(component, BorderLayout.WEST); - } - - public void setRight(Component component) { - add(component, BorderLayout.EAST); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/BottomPanel.java b/src/main/java/cn/enaium/joe/gui/panel/BottomPanel.java deleted file mode 100644 index 8e7a1bb..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/BottomPanel.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel; - -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.annotation.Indeterminate; -import cn.enaium.joe.gui.panel.popup.TaskListPopup; -import cn.enaium.joe.task.AbstractTask; -import cn.enaium.joe.util.Pair; - -import javax.swing.*; -import javax.swing.border.EmptyBorder; -import java.awt.*; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -/** - * @author Enaium - */ -public class BottomPanel extends JPanel { - - public BottomPanel() { - super(new GridLayout(1, 2)); - this.setBorder(new EmptyBorder(5, 5, 5, 5)); - add(new JLabel("\u00A9 Enaium 2022")); - TaskListPopup taskListPopup = new TaskListPopup(); - JProgressBar jProgressBar = new JProgressBar() {{ - - JProgressBar self = this; - addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - Point locationOnScreen = self.getLocationOnScreen(); - taskListPopup.place(locationOnScreen.x, locationOnScreen.y - taskListPopup.getPreferredSize().height); - } - }); - }}; - - add(jProgressBar); - - ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1); - scheduledExecutorService.scheduleAtFixedRate(() -> { - List, CompletableFuture>> task = JavaOctetEditor.getInstance().task.getTask(); - if (task.isEmpty()) { - SwingUtilities.invokeLater(() -> { - jProgressBar.setValue(0); - jProgressBar.setStringPainted(true); - jProgressBar.setIndeterminate(false); - jProgressBar.setString(""); - jProgressBar.repaint(); - }); - } else { - Pair, CompletableFuture> classCompletableFuturePair = task.get(task.size() - 1); - SwingUtilities.invokeLater(() -> { - int progress = classCompletableFuturePair.getKey().getProgress(); - if (!classCompletableFuturePair.getKey().getClass().isAnnotationPresent(Indeterminate.class)) { - jProgressBar.setValue(progress); - jProgressBar.setStringPainted(true); - jProgressBar.setIndeterminate(false); - jProgressBar.setString(String.format("%s:%s", classCompletableFuturePair.getKey().getName(), progress) + "%"); - } else { - jProgressBar.setString(classCompletableFuturePair.getKey().getName()); - jProgressBar.setIndeterminate(true); - } - jProgressBar.repaint(); - }); - } - }, 1, 1, TimeUnit.MILLISECONDS); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/CodeAreaPanel.java b/src/main/java/cn/enaium/joe/gui/panel/CodeAreaPanel.java deleted file mode 100644 index 877c2fe..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/CodeAreaPanel.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel; - -import cn.enaium.joe.util.KeyStrokeUtil; -import cn.enaium.joe.util.LangUtil; -import cn.enaium.joe.util.StringUtil; -import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; -import org.fife.ui.rsyntaxtextarea.Theme; -import org.fife.ui.rtextarea.RTextScrollPane; -import org.fife.ui.rtextarea.SearchContext; -import org.fife.ui.rtextarea.SearchEngine; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; -import java.io.IOException; - -/** - * @author Enaium - */ -public class CodeAreaPanel extends BorderPanel implements ActionListener { - - private final RSyntaxTextArea textArea; - private final JTextField searchField; - private final JCheckBox regexCB; - private final JCheckBox matchCaseCB; - - public CodeAreaPanel() { - textArea = new RSyntaxTextArea(); - textArea.setCodeFoldingEnabled(true); - textArea.setEditable(false); - Theme theme; - try { - theme = Theme.load(getClass().getResourceAsStream("/org/fife/ui/rsyntaxtextarea/themes/monokai.xml")); - } catch (IOException e) { - throw new RuntimeException(e); - } - theme.apply(textArea); - - JToolBar toolBar = new JToolBar(); - searchField = new JTextField(30); - toolBar.add(searchField); - final JButton nextButton = new JButton(LangUtil.i18n("button.findNext")); - nextButton.setActionCommand("FindNext"); - nextButton.addActionListener(this); - toolBar.add(nextButton); - searchField.addActionListener(e -> nextButton.doClick(0)); - JButton prevButton = new JButton(LangUtil.i18n("button.findPrevious")); - prevButton.setActionCommand("FindPrev"); - prevButton.addActionListener(this); - toolBar.add(prevButton); - regexCB = new JCheckBox("Regex"); - toolBar.add(regexCB); - matchCaseCB = new JCheckBox("Match Case"); - toolBar.add(matchCaseCB); - toolBar.setVisible(false); - setTop(toolBar); - setCenter(new RTextScrollPane(textArea) {{ - KeyStrokeUtil.register(textArea, KeyStroke.getKeyStroke(KeyEvent.VK_F, InputEvent.CTRL_DOWN_MASK), () -> { - if (!StringUtil.isBlank(textArea.getSelectedText())) { - searchField.setText(textArea.getSelectedText()); - searchField.setFocusable(true); - } - toolBar.setVisible(true); - searchField.requestFocus(); - }); - KeyStrokeUtil.register(textArea, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), () -> { - toolBar.setVisible(false); - }); - }}); - } - - @Override - public void actionPerformed(ActionEvent e) { - - // "FindNext" => search forward, "FindPrev" => search backward - String command = e.getActionCommand(); - boolean forward = "FindNext".equals(command); - - // Create an object defining our search parameters. - SearchContext context = new SearchContext(); - String text = searchField.getText(); - if (text.length() == 0) { - return; - } - context.setSearchFor(text); - context.setMatchCase(matchCaseCB.isSelected()); - context.setRegularExpression(regexCB.isSelected()); - context.setSearchForward(forward); - context.setWholeWord(false); - - SearchEngine.find(textArea, context); - } - - public RSyntaxTextArea getTextArea() { - return textArea; - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/FieldInfoPanel.java b/src/main/java/cn/enaium/joe/gui/panel/FieldInfoPanel.java deleted file mode 100644 index 1175d29..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/FieldInfoPanel.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel; - -import cn.enaium.joe.dialog.AnnotationListDialog; -import cn.enaium.joe.util.LangUtil; -import cn.enaium.joe.util.StringUtil; -import net.miginfocom.swing.MigLayout; -import org.objectweb.asm.tree.FieldNode; - -import javax.swing.*; -import java.awt.*; - -/** - * @author Enaium - * @since 0.6.0 - */ -public class FieldInfoPanel extends JPanel { - public FieldInfoPanel(FieldNode fieldNode) { - setLayout(new MigLayout("fillx", "[fill][fill]")); - add(new JLabel(LangUtil.i18n("class.info.name"))); - JTextField name = new JTextField(fieldNode.name); - add(name, "wrap"); - add(new JLabel(LangUtil.i18n("class.info.description"))); - JTextField description = new JTextField(fieldNode.desc); - add(description, "wrap"); - add(new JLabel(LangUtil.i18n("class.info.access"))); - JTextField access = new JTextField(String.valueOf(fieldNode.access)); - add(access, "wrap"); - add(new JLabel(LangUtil.i18n("class.info.signature"))); - JTextField signature = new JTextField(fieldNode.signature); - add(signature, "wrap"); - add(new JLabel("Visible Annotation:")); - add(new JButton(LangUtil.i18n("button.edit")) {{ - addActionListener(e -> { - if (fieldNode.visibleAnnotations != null) { - new AnnotationListDialog(fieldNode.visibleAnnotations).setVisible(true); - } - }); - }}, "wrap"); - add(new JLabel("Invisible Annotation:")); - add(new JButton(LangUtil.i18n("button.edit")) {{ - addActionListener(e -> { - if (fieldNode.invisibleAnnotations != null) { - new AnnotationListDialog(fieldNode.invisibleAnnotations).setVisible(true); - } - }); - }}, "wrap"); - add(new JButton(LangUtil.i18n("button.save")) {{ - addActionListener(e -> { - - if (!StringUtil.isBlank(name.getText())) { - fieldNode.name = name.getText(); - } - - - if (!StringUtil.isBlank(description.getText())) { - fieldNode.desc = description.getText(); - } else { - fieldNode.desc = null; - } - - if (!StringUtil.isBlank(access.getText())) { - fieldNode.access = Integer.parseInt(access.getText()); - } - - if (!StringUtil.isBlank(signature.getText())) { - fieldNode.signature = signature.getName(); - } else { - fieldNode.signature = null; - } - - JOptionPane.showMessageDialog(FieldInfoPanel.this, LangUtil.i18n("success")); - }); - }}, "span 2"); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/InheritPanel.java b/src/main/java/cn/enaium/joe/gui/panel/InheritPanel.java deleted file mode 100644 index d217bea..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/InheritPanel.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel; - -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.event.events.FileTabbedSelectEvent; -import cn.enaium.joe.gui.panel.file.tabbed.tab.classes.ClassTabPanel; -import cn.enaium.joe.gui.panel.file.tree.FileTreeCellRenderer; -import cn.enaium.joe.gui.panel.file.tree.node.ClassTreeNode; -import cn.enaium.joe.jar.Jar; -import cn.enaium.joe.util.ASMUtil; -import cn.enaium.joe.util.JTreeUtil; -import cn.enaium.joe.util.ReflectUtil; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.tree.ClassNode; - -import javax.swing.*; -import javax.swing.tree.DefaultTreeModel; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.IOException; -import java.util.Map; -import java.util.Set; -import java.util.function.Consumer; - -/** - * @author Enaium - * @since 1.3.0 - */ -public class InheritPanel extends BorderPanel { - - private ClassNode current; - - public InheritPanel() { - JTree inheritance = new JTree() {{ - setModel(new DefaultTreeModel(null)); - setCellRenderer(new FileTreeCellRenderer()); - }}; - JavaOctetEditor.getInstance().event.register(FileTabbedSelectEvent.class, (Consumer) event -> { - if (event.getSelect() instanceof ClassTabPanel) { - current = ((ClassTabPanel) event.getSelect()).classNode; - setModel(inheritance, true); - } else { - current = null; - inheritance.setModel(new DefaultTreeModel(null)); - } - repaint(); - }); - setCenter(new JScrollPane(inheritance)); - - setBottom(new JToggleButton("Parent", true) {{ - addActionListener(e -> InheritPanel.this.setModel(inheritance, isSelected())); - }}); - } - - private void setModel(JTree jTree, boolean p) { - if (current != null) { - jTree.setModel(new DefaultTreeModel(new ClassTreeNode(current) {{ - recursion(this, p); - }})); - JTreeUtil.setTreeExpandedState(jTree, true); - } - } - - private void recursion(ClassTreeNode classTreeNode, boolean parent) { - ClassNode classNode = classTreeNode.classNode; - Jar jar = JavaOctetEditor.getInstance().getJar(); - if (parent) { - for (String s : ASMUtil.getParentClass(classNode)) { - Map classes = jar.classes; - ClassTreeNode newChild = null; - if (classes.containsKey(s + ".class")) { - newChild = new ClassTreeNode(classes.get(s + ".class")); - } else if (ReflectUtil.classHas(s.replace("/", "."))) { - try { - newChild = new ClassTreeNode(ASMUtil.acceptClassNode(new ClassReader(s))); - } catch (IOException ignored) { - - } - } - if (newChild != null) { - classTreeNode.add(newChild); - recursion(newChild, true); - } - } - } else { - for (ClassNode value : jar.classes.values()) { - Set parentClass = ASMUtil.getParentClass(value); - if (parentClass.contains(classNode.name)) { - ClassTreeNode newChild = new ClassTreeNode(value); - classTreeNode.add(newChild); - recursion(newChild, false); - } - } - } - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/LeftPanel.java b/src/main/java/cn/enaium/joe/gui/panel/LeftPanel.java deleted file mode 100644 index 80db474..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/LeftPanel.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel; - -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.jar.Jar; -import cn.enaium.joe.util.JTreeUtil; -import cn.enaium.joe.util.LangUtil; - -import javax.swing.*; -import javax.swing.border.EmptyBorder; -import java.awt.*; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.util.Locale; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * @author Enaium - */ -public class LeftPanel extends BorderPanel { - public LeftPanel() { - setCenter(new JScrollPane(JavaOctetEditor.getInstance().fileTree)); - setBottom(new BorderPanel() {{ - setBorder(new EmptyBorder(5, 0, 0, 0)); - setCenter(new JTextField() {{ - putClientProperty("JTextField.placeholderText", LangUtil.i18n("menu.search")); - JTextField jTextField = this; - addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_ENTER) { - Jar jar = JavaOctetEditor.getInstance().getJar(); - if (jar != null) { - if (!jTextField.getText().replace(" ", "").isEmpty()) { - Jar searchedJar = jar.copy(); - - searchedJar.classes = searchedJar.classes.entrySet().stream().filter(stringClassNodeEntry -> { - String key = stringClassNodeEntry.getKey(); - - if (!key.contains("/")) { - key = key.substring(key.lastIndexOf("/") + 1); - } - - return key.toLowerCase(Locale.ROOT).contains(jTextField.getText().toLowerCase(Locale.ROOT)); - }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - searchedJar.resources = searchedJar.resources.entrySet().stream().filter(stringEntry -> { - String key = stringEntry.getKey(); - if (!key.contains("/")) { - key = key.substring(key.lastIndexOf("/") + 1); - } - return key.toLowerCase(Locale.ROOT).contains(jTextField.getText().toLowerCase(Locale.ROOT)); - }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - - JavaOctetEditor.getInstance().fileTree.refresh(searchedJar); - JTreeUtil.setTreeExpandedState(JavaOctetEditor.getInstance().fileTree, true); - } else { - JavaOctetEditor.getInstance().fileTree.refresh(jar); - } - } - } - } - }); - }}); - }}); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/MemberListPanel.java b/src/main/java/cn/enaium/joe/gui/panel/MemberListPanel.java deleted file mode 100644 index eec90c8..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/MemberListPanel.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel; - -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.dialog.CallTreeDialog; -import cn.enaium.joe.dialog.FieldDialog; -import cn.enaium.joe.dialog.MethodDialog; -import cn.enaium.joe.event.events.FileTabbedSelectEvent; -import cn.enaium.joe.gui.panel.file.tabbed.tab.classes.ClassTabPanel; -import cn.enaium.joe.util.JMenuUtil; -import cn.enaium.joe.util.LangUtil; -import cn.enaium.joe.util.OpcodeUtil; -import cn.enaium.joe.util.Pair; -import com.formdev.flatlaf.extras.FlatSVGIcon; -import org.objectweb.asm.tree.ClassNode; -import org.objectweb.asm.tree.FieldNode; -import org.objectweb.asm.tree.MethodNode; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.function.Consumer; - -/** - * @author Enaium - * @since 1.2.0 - */ -public class MemberListPanel extends BorderPanel { - public MemberListPanel() { - - JList> memberList = new JList<>(new DefaultListModel<>()); - - memberList.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - if (e.getClickCount() == 2 && memberList.getSelectedIndex() != -1) { - edit(memberList.getSelectedValue()); - } - } - }); - - JMenuUtil.addPopupMenu(memberList, () -> getPopupMenu(memberList.getSelectedValue()), () -> memberList.getSelectedIndex() != -1); - - memberList.setCellRenderer((list, value, index, isSelected, cellHasFocus) -> new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0)) {{ - if (isSelected) { - setBackground(list.getSelectionBackground()); - } else { - setBackground(list.getBackground()); - } - String name = null; - Icon icon = null; - int access = 0; - if (value.getValue() instanceof FieldNode) { - name = ((FieldNode) value.getValue()).name; - icon = new FlatSVGIcon("icons/field.svg"); - access = ((FieldNode) value.getValue()).access; - } else if (value.getValue() instanceof MethodNode) { - name = ((MethodNode) value.getValue()).name; - icon = new FlatSVGIcon("icons/method.svg"); - access = ((MethodNode) value.getValue()).access; - } - Icon accessIcon = null; - if (OpcodeUtil.isPublic(access)) { - accessIcon = new FlatSVGIcon("icons/public.svg"); - } else if (OpcodeUtil.isPrivate(access)) { - accessIcon = new FlatSVGIcon("icons/private.svg"); - } else if (OpcodeUtil.isProtected(access)) { - accessIcon = new FlatSVGIcon("icons/protected.svg"); - } else if (OpcodeUtil.isStatic(access) && "".equals(name)) { - accessIcon = new FlatSVGIcon("icons/static.svg"); - } else { - accessIcon = new FlatSVGIcon("icons/cyan_dot.svg"); - } - - add(new JLabel(icon)); - add(new JLabel(accessIcon)); - add(new JLabel(name)); - }}); - - JavaOctetEditor.getInstance().event.register(FileTabbedSelectEvent.class, (Consumer) event -> { - if (event.getSelect() instanceof ClassTabPanel) { - ClassTabPanel select = (ClassTabPanel) event.getSelect(); - ClassNode classNode = select.classNode; - memberList.setModel(new DefaultListModel>() {{ - for (FieldNode field : classNode.fields) { - addElement(new Pair<>(classNode, field)); - } - - for (MethodNode method : classNode.methods) { - addElement(new Pair<>(classNode, method)); - } - }}); - } else { - ((DefaultListModel>) memberList.getModel()).clear(); - } - memberList.repaint(); - }); - setCenter(new JScrollPane(memberList)); - } - - public static JPopupMenu getPopupMenu(Pair selectedValue) { - return new JPopupMenu() {{ - add(new JMenuItem(LangUtil.i18n("button.edit")) {{ - addActionListener(e -> edit(selectedValue)); - }}); - add(new JMenuItem(LangUtil.i18n("popup.member.callTree")) {{ - addActionListener(e -> { - if (selectedValue.getValue() instanceof MethodNode) { - new CallTreeDialog(selectedValue.getKey(), (MethodNode) selectedValue.getValue()).setVisible(true); - } - }); - }}); - }}; - } - - private static void edit(Pair value) { - if (value.getValue() instanceof MethodNode) { - new MethodDialog(value.getKey(), ((MethodNode) value.getValue())).setVisible(true); - } else if (value.getValue() instanceof FieldNode) { - new FieldDialog(value.getKey(), ((FieldNode) value.getValue())).setVisible(true); - } - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/confirm/BootstrapMethodArgumentEditPanel.java b/src/main/java/cn/enaium/joe/gui/panel/confirm/BootstrapMethodArgumentEditPanel.java deleted file mode 100644 index 3234825..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/confirm/BootstrapMethodArgumentEditPanel.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.confirm; - -import cn.enaium.joe.util.LangUtil; -import cn.enaium.joe.util.MessageUtil; -import cn.enaium.joe.wrapper.Wrapper; -import org.objectweb.asm.Handle; -import org.objectweb.asm.Type; - -import javax.swing.*; -import java.awt.*; -import java.util.ArrayList; -import java.util.List; - -/** - * @author Enaium - * @since 0.8.0 - */ -public class BootstrapMethodArgumentEditPanel extends ConfirmPanel { - public BootstrapMethodArgumentEditPanel(Wrapper wrapper) { - setLayout(new BorderLayout()); - DefaultListModel objectDefaultListModel = new DefaultListModel<>(); - JList objectJList = new JList<>(objectDefaultListModel); - for (Object bsmArg : wrapper.getWrapper()) { - objectDefaultListModel.addElement(bsmArg); - } - add(new JScrollPane(objectJList), BorderLayout.CENTER); - add(new JPanel() {{ - add(new JButton(LangUtil.i18n("button.add")) {{ - addActionListener(e -> { - MessageUtil.confirm(new ConfirmPanel() {{ - setLayout(new BorderLayout()); - JPanel left = new JPanel(new GridLayout(0, 1)); - JPanel right = new JPanel(new GridLayout(0, 1)); - add(left, BorderLayout.WEST); - add(right, BorderLayout.CENTER); - JComboBox jComboBox = new JComboBox<>(new String[]{"String", "float", "double", "int", "long", "Class"}); - left.add(new JLabel(LangUtil.i18n("instruction.type"))); - right.add(jComboBox); - left.add(new JLabel(LangUtil.i18n("instruction.var"))); - JTextField ldc = new JTextField(); - right.add(ldc); - setConfirm(() -> { - Object value; - if (jComboBox.getSelectedItem() != null) { - switch (jComboBox.getSelectedItem().toString()) { - case "float": - value = Float.parseFloat(ldc.getText()); - break; - case "double": - value = Double.parseDouble(ldc.getText()); - break; - case "int": - value = Integer.parseInt(ldc.getText()); - break; - case "long": - value = Long.parseLong(ldc.getText()); - break; - case "Class": - value = Type.getType(ldc.getText()); - break; - default: - value = ldc.getText(); - } - objectDefaultListModel.addElement(value); - } - }); - }}, LangUtil.i18n("button.add")); - }); - }}); - add(new JButton("Add Handle") {{ - addActionListener(e -> { - Wrapper handleWrapper = new Wrapper<>(new Handle(1, "", "", "", false)); - HandleEditPanel confirmPanel = new HandleEditPanel(handleWrapper); - MessageUtil.confirm(confirmPanel, "Add Handle", () -> { - confirmPanel.getConfirm().run(); - objectDefaultListModel.addElement(handleWrapper.getWrapper()); - }, () -> { - }); - }); - }}); - add(new JButton(LangUtil.i18n("button.remove")) {{ - addActionListener(e -> { - if (objectJList.getSelectedIndex() != -1) { - objectDefaultListModel.remove(objectJList.getSelectedIndex()); - } - }); - }}); - }}, BorderLayout.SOUTH); - setConfirm(() -> { - List objects = new ArrayList<>(); - for (int i = 0; i < objectDefaultListModel.size(); i++) { - objects.add(objectDefaultListModel.get(i)); - } - wrapper.setWrapper(objects.toArray(new Object[0])); - }); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/confirm/FrameListEditPanel.java b/src/main/java/cn/enaium/joe/gui/panel/confirm/FrameListEditPanel.java deleted file mode 100644 index 4b34629..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/confirm/FrameListEditPanel.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.confirm; - -import cn.enaium.joe.util.LangUtil; -import cn.enaium.joe.util.MessageUtil; -import cn.enaium.joe.util.OpcodeUtil; -import cn.enaium.joe.util.StringUtil; -import org.objectweb.asm.tree.FrameNode; - -import javax.swing.*; -import javax.swing.border.EmptyBorder; -import java.awt.*; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * @author Enaium - * @since 0.8.0 - */ -public class FrameListEditPanel extends ConfirmPanel { - - public FrameListEditPanel(FrameNode frameNode) { - setLayout(new BorderLayout(10, 10)); - JPanel left = new JPanel(new BorderLayout()); - JPanel right = new JPanel(new BorderLayout()); - left.add(new JLabel("Local", JLabel.CENTER), BorderLayout.NORTH); - ObjectList localObjectList = new ObjectList(frameNode.local); - left.add(localObjectList, BorderLayout.CENTER); - right.add(new JLabel("Stack", JLabel.CENTER), BorderLayout.NORTH); - ObjectList stackObjectList = new ObjectList(frameNode.stack); - right.add(stackObjectList, BorderLayout.CENTER); - add(left, BorderLayout.WEST); - add(new JSeparator(JSeparator.VERTICAL), BorderLayout.CENTER); - add(right, BorderLayout.EAST); - setConfirm(() -> { - frameNode.local = localObjectList.getList().stream().map(it -> { - Map reverse = OpcodeUtil.reverse(OpcodeUtil.FRAME_ELEMENT); - if (reverse.containsKey(it.toString())) { - return reverse.get(it.toString()); - } else { - return it; - } - }).collect(Collectors.toList()); - - frameNode.stack = stackObjectList.getList().stream().map(it -> { - Map reverse = OpcodeUtil.reverse(OpcodeUtil.FRAME_ELEMENT); - if (reverse.containsKey(it.toString())) { - return reverse.get(it.toString()); - } else { - return it; - } - }).collect(Collectors.toList()); - }); - } - - private static class ObjectList extends JPanel { - DefaultListModel stringDefaultListModel = new DefaultListModel<>(); - - public ObjectList(List list) { - setLayout(new BorderLayout()); - setBorder(new EmptyBorder(5, 5, 5, 5)); - JList jList = new JList<>(stringDefaultListModel); - for (Object o : list) { - if (o instanceof String) { - stringDefaultListModel.addElement(o.toString()); - } else if (o instanceof Integer) { - stringDefaultListModel.addElement(OpcodeUtil.FRAME_ELEMENT.get(Integer.parseInt(o.toString()))); - } - } - add(new JScrollPane(jList), BorderLayout.CENTER); - add(new JPanel(new GridLayout(1, 3)) {{ - add(new JButton("Add String") {{ - addActionListener(e -> { - String s = JOptionPane.showInputDialog(ObjectList.this, "Input:"); - if (s != null && !StringUtil.isBlank(s)) { - stringDefaultListModel.addElement(s); - } - }); - }}); - add(new JButton("Add Type") {{ - addActionListener(e -> { - JComboBox message = new JComboBox<>(OpcodeUtil.FRAME_ELEMENT.values().toArray(new String[0])); - MessageUtil.confirm(message, "Type", () -> { - Object selectedItem = message.getSelectedItem(); - if (selectedItem != null) { - stringDefaultListModel.addElement(selectedItem.toString()); - } - }, () -> { - - }); - }); - }}); - add(new JButton(LangUtil.i18n("button.remove")) {{ - addActionListener(e -> { - if (jList.getSelectedIndex() != -1) { - stringDefaultListModel.remove(jList.getSelectedIndex()); - } - }); - }}); - }}, BorderLayout.SOUTH); - } - - public List getList() { - return Arrays.asList(stringDefaultListModel.toArray()); - } - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/confirm/HandleEditPanel.java b/src/main/java/cn/enaium/joe/gui/panel/confirm/HandleEditPanel.java deleted file mode 100644 index 2a70181..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/confirm/HandleEditPanel.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.confirm; - -import cn.enaium.joe.util.OpcodeUtil; -import cn.enaium.joe.wrapper.Wrapper; -import org.objectweb.asm.Handle; - -import javax.swing.*; -import java.awt.*; - -/** - * @author Enaium - * @since 0.8.0 - */ -public class HandleEditPanel extends ConfirmPanel { - public HandleEditPanel(Wrapper wrapper) { - Handle handle = wrapper.getWrapper(); - setLayout(new BorderLayout()); - JPanel left = new JPanel(new GridLayout(0, 1)); - JPanel right = new JPanel(new GridLayout(0, 1)); - add(left, BorderLayout.WEST); - add(right, BorderLayout.CENTER); - left.add(new JLabel("Tag:")); - JComboBox tag = new JComboBox<>(OpcodeUtil.HANDLE.values().toArray(new String[0])); - tag.setSelectedItem(OpcodeUtil.HANDLE.get(handle.getTag())); - right.add(tag); - left.add(new JLabel("Owner:")); - JTextField owner = new JTextField(handle.getOwner()); - right.add(owner); - left.add(new JLabel("Name:")); - JTextField name = new JTextField(handle.getName()); - right.add(name); - left.add(new JLabel("Description:")); - JTextField description = new JTextField(handle.getDesc()); - right.add(description); - left.add(new JLabel("Interface:")); - JCheckBox isInterface = new JCheckBox() {{ - setSelected(handle.isInterface()); - setHorizontalAlignment(JCheckBox.RIGHT); - }}; - right.add(isInterface); - setConfirm(() -> { - if (tag.getSelectedItem() != null) { - wrapper.setWrapper(new Handle(OpcodeUtil.reverse(OpcodeUtil.HANDLE).get(tag.getSelectedItem().toString()), owner.getText(), name.getText(), description.getText(), isInterface.isSelected())); - } - }); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/confirm/InstructionEditPanel.java b/src/main/java/cn/enaium/joe/gui/panel/confirm/InstructionEditPanel.java deleted file mode 100644 index 283167d..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/confirm/InstructionEditPanel.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.confirm; - -import cn.enaium.joe.gui.panel.instruction.*; -import cn.enaium.joe.util.LangUtil; -import cn.enaium.joe.util.MessageUtil; -import cn.enaium.joe.util.OpcodeUtil; -import org.objectweb.asm.tree.*; - -import java.awt.*; - -/** - * @author Enaium - * @since 0.8.0 - */ -public class InstructionEditPanel extends ConfirmPanel { - public InstructionEditPanel(AbstractInsnNode instruction) { - setLayout(new BorderLayout()); - AbstractInstructionPanel abstractInstructionPanel = null; - - switch (instruction.getType()) { - case AbstractInsnNode.INSN: - abstractInstructionPanel = new InstructionPanel((InsnNode) instruction); - break; - case AbstractInsnNode.INT_INSN: - abstractInstructionPanel = new IntInstructionPanel((IntInsnNode) instruction); - break; - case AbstractInsnNode.VAR_INSN: - abstractInstructionPanel = new VarInstructionPanel((VarInsnNode) instruction); - break; - case AbstractInsnNode.TYPE_INSN: - abstractInstructionPanel = new TypeInstructionPanel((TypeInsnNode) instruction); - break; - case AbstractInsnNode.FIELD_INSN: - abstractInstructionPanel = new FieldInstructionPanel((FieldInsnNode) instruction); - break; - case AbstractInsnNode.METHOD_INSN: - abstractInstructionPanel = new MethodInstructionPanel((MethodInsnNode) instruction); - break; - case AbstractInsnNode.INVOKE_DYNAMIC_INSN: - abstractInstructionPanel = new InvokeDynamicInstructionPanel(((InvokeDynamicInsnNode) instruction)); - break; - case AbstractInsnNode.JUMP_INSN: - abstractInstructionPanel = new JumpInstructionPanel(((JumpInsnNode) instruction)); - break; - case AbstractInsnNode.LABEL: - break; - case AbstractInsnNode.LDC_INSN: - abstractInstructionPanel = new LdcInstructionPanel(((LdcInsnNode) instruction)); - break; - case AbstractInsnNode.IINC_INSN: - abstractInstructionPanel = new IncrInstructionPanel((IincInsnNode) instruction); - break; - case AbstractInsnNode.TABLESWITCH_INSN: - abstractInstructionPanel = new TableSwitchInstructionPanel(((TableSwitchInsnNode) instruction)); - break; - case AbstractInsnNode.LOOKUPSWITCH_INSN: - abstractInstructionPanel = new LookupSwitchInstructionPanel(((LookupSwitchInsnNode) instruction)); - break; - case AbstractInsnNode.MULTIANEWARRAY_INSN: - abstractInstructionPanel = new MultiANewArrayInstructionPanel(((MultiANewArrayInsnNode) instruction)); - break; - case AbstractInsnNode.FRAME: - abstractInstructionPanel = new FrameInstructionPanel(((FrameNode) instruction)); - break; - case AbstractInsnNode.LINE: - abstractInstructionPanel = new LineInstructionPanel(((LineNumberNode) instruction)); - break; - } - if (abstractInstructionPanel != null) { - AbstractInstructionPanel finalAbstractInstructionPanel = abstractInstructionPanel; - add(abstractInstructionPanel, BorderLayout.CENTER); - setConfirm(() -> { - try { - if (!finalAbstractInstructionPanel.getConfirm().call()) { - MessageUtil.info(LangUtil.i18n("fail")); - } - } catch (Exception ex) { - MessageUtil.error(ex); - } - }); - } - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/confirm/LabelListEditPanel.java b/src/main/java/cn/enaium/joe/gui/panel/confirm/LabelListEditPanel.java deleted file mode 100644 index 15869ad..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/confirm/LabelListEditPanel.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.confirm; - -import cn.enaium.joe.util.LangUtil; -import cn.enaium.joe.util.MessageUtil; -import cn.enaium.joe.wrapper.LabelNodeWrapper; -import cn.enaium.joe.wrapper.Wrapper; -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.InsnList; -import org.objectweb.asm.tree.LabelNode; - -import javax.swing.*; -import java.awt.*; -import java.util.List; - -/** - * @author Enaium - * @since 0.8.0 - */ -public class LabelListEditPanel extends ConfirmPanel { - public LabelListEditPanel(List labelNodes, InsnList instructions) { - setLayout(new BorderLayout()); - DefaultListModel labelNodeWrapperDefaultListModel = new DefaultListModel<>(); - JList labelNodeWrapperJList = new JList<>(labelNodeWrapperDefaultListModel); - for (LabelNode labelNode : labelNodes) { - labelNodeWrapperDefaultListModel.addElement(new LabelNodeWrapper(labelNode)); - } - add(new JScrollPane(labelNodeWrapperJList), BorderLayout.CENTER); - add(new JPanel() {{ - add(new JButton(LangUtil.i18n("button.add")) {{ - addActionListener(e -> { - DefaultComboBoxModel labelNodeWrapperDefaultComboBoxModel = new DefaultComboBoxModel<>(); - JComboBox labelNodeWrapperJComboBox = new JComboBox<>(labelNodeWrapperDefaultComboBoxModel); - for (AbstractInsnNode instruction : instructions) { - if (instruction instanceof LabelNode) { - labelNodeWrapperDefaultComboBoxModel.addElement(new LabelNodeWrapper((LabelNode) instruction)); - } - } - MessageUtil.confirm(labelNodeWrapperJComboBox, "Label", () -> { - if (labelNodeWrapperJComboBox.getSelectedItem() != null) { - labelNodeWrapperDefaultListModel.addElement(((LabelNodeWrapper) labelNodeWrapperJComboBox.getSelectedItem())); - } - }, () -> { - }); - }); - }}); - add(new JButton(LangUtil.i18n("button.remove")) {{ - addActionListener(e -> { - if (labelNodeWrapperJList.getSelectedIndex() != -1) { - labelNodeWrapperDefaultListModel.remove(labelNodeWrapperJList.getSelectedIndex()); - } - }); - }}); - }}, BorderLayout.SOUTH); - setConfirm(() -> { - labelNodes.clear(); - for (int i = 0; i < labelNodeWrapperDefaultListModel.size(); i++) { - labelNodes.add(labelNodeWrapperDefaultListModel.get(i).getWrapper()); - } - }); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/confirm/ListValueEditPanel.java b/src/main/java/cn/enaium/joe/gui/panel/confirm/ListValueEditPanel.java deleted file mode 100644 index 9742da3..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/confirm/ListValueEditPanel.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.confirm; - -import cn.enaium.joe.util.ASMUtil; -import cn.enaium.joe.util.ListUtil; - -import javax.swing.*; -import java.awt.*; -import java.util.List; - -/** - * @author Enaium - * @since 1.2.0 - */ -public class ListValueEditPanel extends ConfirmPanel { - public ListValueEditPanel(List objects) { - setLayout(new BorderLayout()); - - Class type = ListUtil.getType(objects); - - JTextArea jTextArea = new JTextArea(); - int index = 0; - for (Object object : objects) { - jTextArea.append(object.toString()); - - if (index != objects.size() - 1) { - jTextArea.append("\n"); - } - } - add(new JScrollPane(jTextArea), BorderLayout.CENTER); - setConfirm(() -> { - objects.clear(); - for (String s : jTextArea.getText().replaceAll("^\\s+", "").split("\n")) { - objects.add(ASMUtil.toType(type, s)); - } - }); - } -} - - diff --git a/src/main/java/cn/enaium/joe/gui/panel/confirm/LookupSwitchEditPanel.java b/src/main/java/cn/enaium/joe/gui/panel/confirm/LookupSwitchEditPanel.java deleted file mode 100644 index 298f320..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/confirm/LookupSwitchEditPanel.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.confirm; - -import cn.enaium.joe.gui.component.LabelNodeComboBox; -import cn.enaium.joe.util.LangUtil; -import cn.enaium.joe.util.MessageUtil; -import cn.enaium.joe.wrapper.LabelNodeWrapper; -import org.objectweb.asm.tree.LabelNode; - -import javax.swing.*; -import javax.swing.table.DefaultTableModel; -import java.awt.*; -import java.util.List; - -/** - * @author Enaium - * @since 0.8.0 - */ -public class LookupSwitchEditPanel extends ConfirmPanel { - public LookupSwitchEditPanel(List keys, List labels) { - setLayout(new BorderLayout()); - DefaultTableModel dm = new DefaultTableModel(new Object[][]{}, new String[]{"Key", "Label"}); - JTable jTable = new JTable(dm) { - public boolean isCellEditable(int row, int column) { - return false; - } - }; - jTable.getTableHeader().setReorderingAllowed(false); - jTable.getTableHeader().setResizingAllowed(false); - for (int i = 0; i < keys.size(); i++) { - dm.addRow(new Object[]{keys.get(i), new LabelNodeWrapper(labels.get(i))}); - } - add(new JScrollPane(jTable), BorderLayout.CENTER); - add(new JPanel() {{ - add(new JButton(LangUtil.i18n("button.add")) {{ - addActionListener(e -> { - MessageUtil.confirm(new ConfirmPanel() {{ - JSpinner key = new JSpinner(); - add(key); - LabelNodeComboBox value = new LabelNodeComboBox(labels.get(0), null); - add(value); - setConfirm(() -> { - Object selectedItem = value.getSelectedItem(); - if (selectedItem != null) { - dm.addRow(new Object[]{key.getValue(), selectedItem}); - } - }); - }}, "Add"); - }); - }}); - add(new JButton(LangUtil.i18n("button.remove")) {{ - addActionListener(e -> { - if (jTable.getSelectedRow() != -1) { - dm.removeRow(jTable.getSelectedRow()); - } - }); - }}); - }}, BorderLayout.SOUTH); - setConfirm(() -> { - keys.clear(); - labels.clear(); - for (int i = 0; i < jTable.getRowCount(); i++) { - keys.add(Integer.parseInt(jTable.getValueAt(i, 0).toString())); - labels.add(((LabelNodeWrapper) jTable.getValueAt(i, 1)).getWrapper()); - } - }); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/confirm/ValueEditPanel.java b/src/main/java/cn/enaium/joe/gui/panel/confirm/ValueEditPanel.java deleted file mode 100644 index d605a05..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/confirm/ValueEditPanel.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.confirm; - -import cn.enaium.joe.util.ASMUtil; -import cn.enaium.joe.wrapper.ObjectWrapper; - -import javax.swing.*; -import java.awt.*; - -/** - * @author Enaium - * @since 1.2.0 - */ -public class ValueEditPanel extends ConfirmPanel { - public ValueEditPanel(ObjectWrapper objectWrapper) { - setLayout(new BorderLayout()); - JTextField jTextField = new JTextField(objectWrapper.getWrapper().toString()); - add(jTextField, BorderLayout.CENTER); - setConfirm(() -> { - objectWrapper.setWrapper(ASMUtil.toType(objectWrapper.getWrapper().getClass(), jTextField.getText())); - }); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/file/FileDropTarget.java b/src/main/java/cn/enaium/joe/gui/panel/file/FileDropTarget.java deleted file mode 100644 index 72d4505..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/file/FileDropTarget.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.file; - -import java.awt.datatransfer.DataFlavor; -import java.awt.datatransfer.Transferable; -import java.awt.datatransfer.UnsupportedFlavorException; -import java.awt.dnd.*; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; - -/** - * @author Enaium - */ -public class FileDropTarget implements DropTargetListener { - - private boolean drop = false; - private final List files = new ArrayList<>(); - - private final String suffix; - private final Consumer> consumer; - - public FileDropTarget(String suffix, Consumer> consumer) { - this.suffix = suffix; - this.consumer = consumer; - } - - @Override - public void dragEnter(DropTargetDragEvent dtde) { - drop = false; - files.clear(); - Transferable t = dtde.getTransferable(); - if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) { - try { - Object td = t.getTransferData(DataFlavor.javaFileListFlavor); - if (td instanceof List) { - drop = true; - for (Object value : ((List) td)) { - if (value instanceof File) { - File file = (File) value; - String name = file.getName().toLowerCase(); - if (!name.endsWith(suffix)) { - drop = false; - break; - } else { - files.add(file); - } - } - } - } - } catch (UnsupportedFlavorException | IOException ex) { - ex.printStackTrace(); - } - } - if (drop) { - dtde.acceptDrag(DnDConstants.ACTION_COPY); - } else { - dtde.rejectDrag(); - } - } - - @Override - public void dragOver(DropTargetDragEvent dtde) { - - } - - @Override - public void dropActionChanged(DropTargetDragEvent dtde) { - - } - - @Override - public void dragExit(DropTargetEvent dte) { - drop = false; - files.clear(); - } - - @Override - public void drop(DropTargetDropEvent dtde) { - consumer.accept(files); - drop = false; - files.clear(); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/FileTabbedPanel.java b/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/FileTabbedPanel.java deleted file mode 100644 index aa1c590..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/FileTabbedPanel.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.file.tabbed; - -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.event.events.FileTabbedSelectEvent; -import cn.enaium.joe.util.JMenuUtil; -import cn.enaium.joe.util.LangUtil; - -import javax.swing.*; -import java.awt.*; -import java.util.function.BiConsumer; - -/** - * @author Enaium - */ -public class FileTabbedPanel extends JTabbedPane { - public FileTabbedPanel() { - setTabLayoutPolicy(SCROLL_TAB_LAYOUT); - putClientProperty("JTabbedPane.tabClosable", true); - putClientProperty("JTabbedPane.tabCloseCallback", (BiConsumer) JTabbedPane::remove); - addChangeListener(e -> { - Component selectedComponent = ((FileTabbedPanel) e.getSource()).getSelectedComponent(); - JavaOctetEditor.getInstance().event.call(new FileTabbedSelectEvent(selectedComponent)); - }); - JMenuUtil.addPopupMenu(this, () -> new JPopupMenu() {{ - add(new JMenuItem(LangUtil.i18n("popup.tabbed.closeAll")) {{ - addActionListener(e -> { - FileTabbedPanel.this.removeAll(); - }); - }}); - add(new JMenuItem(LangUtil.i18n("popup.tabbed.closeOther")) {{ - addActionListener(e -> { - int tabCount = getTabCount(); - while (tabCount-- > 0) { - if (tabCount != getSelectedIndex()) { - removeTabAt(tabCount); - } - } - }); - }}); - add(new JMenuItem(LangUtil.i18n("popup.tabbed.closeAllLeft")) {{ - addActionListener(e -> { - int tabCount = getTabCount(); - while (tabCount-- > 0) { - if (tabCount < getSelectedIndex()) { - removeTabAt(tabCount); - } - } - }); - }}); - add(new JMenuItem(LangUtil.i18n("popup.tabbed.closeAllRight")) {{ - addActionListener(e -> { - int tabCount = getTabCount(); - while (tabCount-- > 0) { - if (tabCount > getSelectedIndex()) { - removeTabAt(tabCount); - } - } - }); - }}); - }}, () -> getSelectedComponent() != null); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/ASMifierTablePanel.java b/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/ASMifierTablePanel.java deleted file mode 100644 index be1e5cb..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/ASMifierTablePanel.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.file.tabbed.tab.classes; - -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.gui.panel.CodeAreaPanel; -import cn.enaium.joe.util.*; -import javassist.ClassPool; -import javassist.CtClass; -import javassist.CtMethod; -import javassist.Loader; -import org.fife.ui.rsyntaxtextarea.SyntaxConstants; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.tree.ClassNode; -import org.objectweb.asm.util.ASMifier; -import org.objectweb.asm.util.TraceClassVisitor; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.InputEvent; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.io.PrintWriter; -import java.io.StringWriter; - -/** - * @author Enaium - */ -public class ASMifierTablePanel extends ClassNodeTabPanel { - public ASMifierTablePanel(ClassNode classNode) { - super(classNode); - setLayout(new BorderLayout()); - CodeAreaPanel codeAreaPanel = new CodeAreaPanel() {{ - KeyStrokeUtil.register(getTextArea(), KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK), () -> { - try { - StringWriter stringWriter = new StringWriter(); - ClassReader classReader = new ClassReader(this.getClass().getName()); - classReader.accept(new TraceClassVisitor(null, new ASMifier(), new PrintWriter(stringWriter)), 0); - ClassPool classPool = new ClassPool(); - classPool.appendSystemPath(); - classPool.importPackage("org.objectweb.asm.AnnotationVisitor"); - classPool.importPackage("org.objectweb.asm.Attribute"); - classPool.importPackage("org.objectweb.asm.ClassReader"); - classPool.importPackage("org.objectweb.asm.ClassWriter"); - classPool.importPackage("org.objectweb.asm.ConstantDynamic"); - classPool.importPackage("org.objectweb.asm.FieldVisitor"); - classPool.importPackage("org.objectweb.asm.Handle"); - classPool.importPackage("org.objectweb.asm.Label"); - classPool.importPackage("org.objectweb.asm.MethodVisitor"); - classPool.importPackage("org.objectweb.asm.Opcodes"); - classPool.importPackage("org.objectweb.asm.RecordComponentVisitor"); - classPool.importPackage("org.objectweb.asm.Type"); - classPool.importPackage("org.objectweb.asm.TypePath"); - CtClass ctClass = classPool.makeClass(ASMifier.class.getSimpleName()); - ctClass.addInterface(classPool.get("org.objectweb.asm.Opcodes")); - ctClass.addMethod(CtMethod.make("public static byte[] dump() throws Exception {" + getTextArea().getText() + "return classWriter.toByteArray();}", ctClass)); - byte[] dumps = (byte[]) new Loader(classPool).loadClass(ASMifier.class.getSimpleName()).getMethod("dump").invoke(null); - ClassNode newClassNode = new ClassNode(); - new ClassReader(dumps).accept(newClassNode, ClassReader.EXPAND_FRAMES); - ReflectUtil.setAll(classNode, newClassNode); - JOptionPane.showMessageDialog(null, LangUtil.i18n("success")); - } catch (Throwable e) { - MessageUtil.error(e); - } - }); - }}; - codeAreaPanel.getTextArea().setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA); - codeAreaPanel.getTextArea().setEditable(true); - StringWriter stringWriter = new StringWriter(); - - ASyncUtil.execute(() -> { - classNode.accept(new TraceClassVisitor(null, new ASMifier(), new PrintWriter(stringWriter))); - }, () -> { - String trim = getMiddle(getMiddle(stringWriter.toString())).trim(); - codeAreaPanel.getTextArea().setText(trim.substring(0, trim.lastIndexOf("\n"))); - codeAreaPanel.getTextArea().setCaretPosition(0); - }); - add(codeAreaPanel); - } - - public String getMiddle(String s) { - return s.substring(s.indexOf("{") + 1, s.lastIndexOf("}")); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/ClassInfoTabPanel.java b/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/ClassInfoTabPanel.java deleted file mode 100644 index 7f9b1e8..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/ClassInfoTabPanel.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.file.tabbed.tab.classes; - - -import cn.enaium.joe.dialog.AnnotationListDialog; -import cn.enaium.joe.util.LangUtil; -import cn.enaium.joe.util.StringUtil; -import net.miginfocom.swing.MigLayout; -import org.benf.cfr.reader.util.StringUtils; -import org.objectweb.asm.tree.ClassNode; - -import javax.swing.*; -import java.awt.*; -import java.util.ArrayList; -import java.util.Arrays; - -/** - * @author Enaium - * @since 0.6.0 - */ -public class ClassInfoTabPanel extends ClassNodeTabPanel { - public ClassInfoTabPanel(ClassNode classNode) { - super(classNode); - setLayout(new MigLayout("fillx", "[fill][fill]")); - add(new JLabel(LangUtil.i18n("class.info.name"))); - JTextField name = new JTextField(classNode.name); - add(name, "wrap"); - add(new JLabel(LangUtil.i18n("class.info.sourceFile"))); - JTextField sourceFile = new JTextField(classNode.sourceFile); - add(sourceFile, "wrap"); - add(new JLabel(LangUtil.i18n("class.info.debugFile"))); - JTextField sourceDebug = new JTextField(classNode.sourceDebug); - add(sourceDebug, "wrap"); - add(new JLabel(LangUtil.i18n("class.info.access"))); - JTextField access = new JTextField(String.valueOf(classNode.access)); - add(access, "wrap"); - add(new JLabel(LangUtil.i18n("class.info.version"))); - JTextField version = new JTextField(String.valueOf(classNode.version)); - add(version, "wrap"); - add(new JLabel(LangUtil.i18n("class.info.signature"))); - JTextField signature = new JTextField(classNode.signature); - add(signature, "wrap"); - add(new JLabel(LangUtil.i18n("class.info.superName"))); - JTextField superName = new JTextField(classNode.superName); - add(superName, "wrap"); - add(new JLabel(LangUtil.i18n("class.info.interfaces"))); - JTextField interfaces = new JTextField(StringUtils.join(classNode.interfaces, ";")); - add(interfaces, "wrap"); - add(new JLabel(LangUtil.i18n("class.info.outerClass"))); - JTextField outerClass = new JTextField(classNode.outerClass); - add(outerClass, "wrap"); - add(new JLabel(LangUtil.i18n("class.info.outerMethod"))); - JTextField outerMethod = new JTextField(classNode.outerMethod); - add(outerMethod, "wrap"); - add(new JLabel(LangUtil.i18n("class.info.outerMethodDescription"))); - JTextField outerMethodDesc = new JTextField(classNode.outerMethodDesc); - add(outerMethodDesc, "wrap"); - add(new JLabel("Visible Annotation:")); - add(new JButton(LangUtil.i18n("button.edit")) {{ - addActionListener(e -> { - if (classNode.visibleAnnotations != null) { - new AnnotationListDialog(classNode.visibleAnnotations).setVisible(true); - } - }); - }}, "wrap"); - add(new JLabel("Invisible Annotation:")); - add(new JButton(LangUtil.i18n("button.edit")) {{ - addActionListener(e -> { - if (classNode.invisibleAnnotations != null) { - new AnnotationListDialog(classNode.invisibleAnnotations).setVisible(true); - } - }); - }}, "wrap"); - add(new JButton(LangUtil.i18n("button.save")) {{ - addActionListener(e -> { - - if (!StringUtil.isBlank(name.getText())) { - classNode.name = name.getText(); - } - - if (!StringUtil.isBlank(sourceFile.getText())) { - classNode.sourceFile = sourceFile.getText(); - } else { - classNode.sourceFile = null; - } - - if (!StringUtil.isBlank(sourceDebug.getText())) { - classNode.sourceDebug = sourceDebug.getText(); - } else { - classNode.sourceDebug = null; - } - - if (!StringUtil.isBlank(access.getText())) { - classNode.access = Integer.parseInt(access.getText()); - } - - if (!StringUtil.isBlank(version.getText())) { - classNode.version = Integer.parseInt(version.getText()); - } - - if (!StringUtil.isBlank(signature.getText())) { - classNode.signature = signature.getText(); - } else { - classNode.signature = null; - } - - if (!StringUtil.isBlank(interfaces.getText())) { - classNode.interfaces = Arrays.asList(superName.getText().split(";")); - } else { - classNode.interfaces = new ArrayList<>(); - } - - if (!StringUtil.isBlank(outerClass.getText())) { - classNode.outerClass = outerClass.getText(); - } else { - classNode.outerClass = null; - } - - if (!StringUtil.isBlank(outerMethod.getText())) { - classNode.outerMethod = outerMethod.getText(); - } else { - classNode.outerClass = null; - } - - if (!StringUtil.isBlank(outerMethodDesc.getText())) { - classNode.outerMethodDesc = outerMethodDesc.getText(); - } else { - classNode.outerClass = null; - } - - JOptionPane.showMessageDialog(ClassInfoTabPanel.this, LangUtil.i18n("success")); - }); - }}, "span 2"); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/ClassTabPanel.java b/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/ClassTabPanel.java deleted file mode 100644 index 6519e52..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/ClassTabPanel.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.file.tabbed.tab.classes; - -import cn.enaium.joe.util.LangUtil; -import org.objectweb.asm.tree.ClassNode; - -import javax.swing.*; -import java.awt.*; - -/** - * @author Enaium - */ -public class ClassTabPanel extends JPanel { - - public final ClassNode classNode; - - public ClassTabPanel(ClassNode classNode) { - super(new BorderLayout()); - this.classNode = classNode; - JTabbedPane jTabbedPane = new JTabbedPane(); - jTabbedPane.setTabPlacement(JTabbedPane.BOTTOM); - jTabbedPane.addTab(LangUtil.i18n("class.tab.bytecodeView"), new TraceBytecodeTabPanel(classNode)); - jTabbedPane.addTab(LangUtil.i18n("class.tab.decompileView"), new DecompileTabPanel(classNode)); - jTabbedPane.addTab(LangUtil.i18n("class.tab.visitorEdit"), new ASMifierTablePanel(classNode)); - jTabbedPane.addTab(LangUtil.i18n("class.tab.infoEdit"), new ClassInfoTabPanel(classNode)); - add(jTabbedPane); - } -} \ No newline at end of file diff --git a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/DecompileTabPanel.java b/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/DecompileTabPanel.java deleted file mode 100644 index fa97d17..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/DecompileTabPanel.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.file.tabbed.tab.classes; - -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.service.DecompileService; -import cn.enaium.joe.gui.panel.CodeAreaPanel; -import cn.enaium.joe.task.DecompileTask; -import cn.enaium.joe.util.ASyncUtil; -import org.objectweb.asm.tree.ClassNode; - -import java.awt.*; - -/** - * @author Enaium - */ -public class DecompileTabPanel extends ClassNodeTabPanel { - public DecompileTabPanel(ClassNode classNode) { - super(classNode); - setLayout(new BorderLayout()); - CodeAreaPanel codeAreaPanel = new CodeAreaPanel(); - codeAreaPanel.getTextArea().setSyntaxEditingStyle("text/java"); - JavaOctetEditor.getInstance().task.submit(new DecompileTask(classNode)).thenAccept(it -> { - codeAreaPanel.getTextArea().setText(it); - }); - codeAreaPanel.getTextArea().setCaretPosition(0); - add(codeAreaPanel); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/TraceBytecodeTabPanel.java b/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/TraceBytecodeTabPanel.java deleted file mode 100644 index c22b910..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/TraceBytecodeTabPanel.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.file.tabbed.tab.classes; - -import cn.enaium.joe.gui.panel.CodeAreaPanel; -import cn.enaium.joe.util.ASyncUtil; -import org.objectweb.asm.tree.ClassNode; -import org.objectweb.asm.util.TraceClassVisitor; - -import java.awt.*; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.nio.charset.StandardCharsets; - -/** - * @author Enaium - */ -public class TraceBytecodeTabPanel extends ClassNodeTabPanel { - public TraceBytecodeTabPanel(ClassNode classNode) { - super(classNode); - setLayout(new BorderLayout()); - CodeAreaPanel codeAreaPanel = new CodeAreaPanel(); - codeAreaPanel.getTextArea().setSyntaxEditingStyle("text/custom"); - final StringWriter stringWriter = new StringWriter(); - ASyncUtil.execute(() -> { - classNode.accept(new TraceClassVisitor(new PrintWriter(stringWriter))); - }, () -> { - codeAreaPanel.getTextArea().setText(new String(stringWriter.toString().getBytes(StandardCharsets.UTF_8))); - codeAreaPanel.getTextArea().setCaretPosition(0); - }); - add(codeAreaPanel); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/resources/FileTablePane.java b/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/resources/FileTablePane.java deleted file mode 100644 index 8e96df7..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/resources/FileTablePane.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.file.tabbed.tab.resources; - -import cn.enaium.joe.gui.panel.file.tree.node.FileTreeNode; -import cn.enaium.joe.util.IOUtil; -import cn.enaium.joe.util.StringUtil; -import cn.enaium.joe.util.Util; - -import javax.swing.*; -import java.awt.*; - -/** - * @author Enaium - * @since 1.2.0 - */ -public class FileTablePane extends JPanel { - public FileTablePane(FileTreeNode fileTreeNode) { - super(new BorderLayout()); - if (Util.isText(fileTreeNode.getData())) { - add(new TextTablePanel(fileTreeNode)); - } else if (IOUtil.isImage(fileTreeNode.getData())) { - add(new ImageTablePanel(fileTreeNode)); - } else { - add(new HexTablePanel(fileTreeNode)); - } - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/resources/HexTablePanel.java b/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/resources/HexTablePanel.java deleted file mode 100644 index 70fab2f..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/resources/HexTablePanel.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.file.tabbed.tab.resources; - -import cn.enaium.joe.gui.panel.file.tree.node.FileTreeNode; -import cn.enaium.joe.util.ASyncUtil; - -import javax.swing.*; -import javax.swing.table.DefaultTableModel; -import java.awt.*; - -/** - * @author Enaium - * @since 0.7.0 - */ -public class HexTablePanel extends JPanel { - public HexTablePanel(FileTreeNode fileTreeNode) { - super(new BorderLayout()); - DefaultTableModel defaultTableModel = new DefaultTableModel(new Object[][]{}, new String[]{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"}); - JTable jTable = new JTable(defaultTableModel) { - @Override - public boolean isCellEditable(int row, int column) { - return false; - } - }; - jTable.getTableHeader().setReorderingAllowed(false); - add(new JScrollPane(jTable), BorderLayout.CENTER); - - ASyncUtil.execute(() -> { - int row = 0; - Object[] array = new Object[16]; - byte[] data = fileTreeNode.getData(); - for (int i = 0; i < data.length; i++) { - byte b = data[i]; - array[row] = String.format("%02X", b); - if (row == 15 || i == fileTreeNode.getData().length - 1) { - defaultTableModel.addRow(array); - row = 0; - array = new Object[16]; - continue; - } - row++; - } - }); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/resources/ImageTablePanel.java b/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/resources/ImageTablePanel.java deleted file mode 100644 index 0f829a7..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/resources/ImageTablePanel.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.file.tabbed.tab.resources; - -import cn.enaium.joe.gui.panel.file.tree.node.FileTreeNode; -import cn.enaium.joe.util.IOUtil; -import cn.enaium.joe.util.MessageUtil; - -import javax.swing.*; -import java.awt.*; -import java.io.IOException; - -/** - * @author Enaium - * @since 1.2.0 - */ -public class ImageTablePanel extends JPanel { - public ImageTablePanel(FileTreeNode fileTreeNode) { - setLayout(new BorderLayout()); - add(new JScrollPane(new JLabel() {{ - try { - setHorizontalAlignment(SwingUtilities.CENTER); - setIcon(IOUtil.getIcon(fileTreeNode.getData())); - } catch (IOException e) { - MessageUtil.error(e); - } - }})); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/resources/TextTablePanel.java b/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/resources/TextTablePanel.java deleted file mode 100644 index e82a802..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/resources/TextTablePanel.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.file.tabbed.tab.resources; - -import cn.enaium.joe.gui.panel.BorderPanel; -import cn.enaium.joe.gui.panel.CodeAreaPanel; -import cn.enaium.joe.gui.panel.file.tree.node.FileTreeNode; -import org.fife.ui.rsyntaxtextarea.FileTypeUtil; -import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; -import org.fife.ui.rsyntaxtextarea.SyntaxConstants; - -import javax.swing.*; -import java.awt.*; -import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.Map; - -/** - * @author Enaium - * @since 1.2.0 - */ -public class TextTablePanel extends BorderPanel { - public TextTablePanel(FileTreeNode fileTreeNode) { - setCenter(new CodeAreaPanel() {{ - String name = fileTreeNode.toString(); - String syntax = SyntaxConstants.SYNTAX_STYLE_NONE; - for (Map.Entry> stringListEntry : FileTypeUtil.get().getDefaultContentTypeToFilterMap().entrySet()) { - for (String s : stringListEntry.getValue()) { - if (name.matches("." + s)) { - syntax = stringListEntry.getKey(); - break; - } - } - } - getTextArea().setSyntaxEditingStyle(syntax); - getTextArea().setText(new String(fileTreeNode.getData(), StandardCharsets.UTF_8)); - }}); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/file/tree/CenterPanel.java b/src/main/java/cn/enaium/joe/gui/panel/file/tree/CenterPanel.java deleted file mode 100644 index a754811..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/file/tree/CenterPanel.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.file.tree; - -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.gui.component.RightTabBar; -import cn.enaium.joe.gui.panel.BorderPanel; -import cn.enaium.joe.gui.panel.LeftPanel; - -import javax.swing.*; -import java.awt.*; - -/** - * @author Enaium - * @since 1.2.0 - */ -public class CenterPanel extends BorderPanel { - public CenterPanel() { - setCenter(new JSplitPane() {{ - setLeftComponent(new LeftPanel()); - setRightComponent(JavaOctetEditor.getInstance().fileTabbedPanel); - setDividerLocation(200); - }}); - setRight(new BorderPanel() {{ - JViewport jViewport = new JViewport(); - setCenter(jViewport); - setRight(new RightTabBar() {{ - addChangeListener(e -> { - jViewport.setView(getSelectedComponent()); - }); - }}); - - }}); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/file/tree/FileTreeCellRenderer.java b/src/main/java/cn/enaium/joe/gui/panel/file/tree/FileTreeCellRenderer.java deleted file mode 100644 index d9f0ca0..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/file/tree/FileTreeCellRenderer.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.file.tree; - -import cn.enaium.joe.gui.panel.file.tree.node.*; -import com.formdev.flatlaf.extras.FlatSVGIcon; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.tree.ClassNode; - -import javax.swing.*; -import javax.swing.tree.DefaultTreeCellRenderer; -import java.awt.*; - -/** - * @author Enaium - */ -public class FileTreeCellRenderer extends DefaultTreeCellRenderer { - @Override - public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { - FileTreeCellRenderer self = this; - super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); - final DefaultTreeNode defaultTreeNode = (DefaultTreeNode) value; - - if (defaultTreeNode.toString().equals("classes")) { - setIcon(new FlatSVGIcon("icons/classesRoot.svg")); - } else if (defaultTreeNode.toString().equals("resources")) { - setIcon(new FlatSVGIcon("icons/resourceRoot.svg")); - } else if (defaultTreeNode instanceof PackageTreeNode) { - setIcon(new FlatSVGIcon("icons/package.svg")); - PackageTreeNode packageTreeNode = (PackageTreeNode) defaultTreeNode; - if (packageTreeNode instanceof ClassTreeNode) { - ClassNode classNode = ((ClassTreeNode) packageTreeNode).classNode; - if (classNode.access == (Opcodes.ACC_PUBLIC | Opcodes.ACC_ANNOTATION | Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE)) { - setIcon(new FlatSVGIcon("icons/annotation.svg")); - } else if (classNode.access == (Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE)) { - setIcon(new FlatSVGIcon("icons/interface.svg")); - } else if (classNode.access == (Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER | Opcodes.ACC_ABSTRACT)) { - setIcon(new FlatSVGIcon("icons/abstractClass.svg")); - } else if (classNode.access == (Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_SUPER | Opcodes.ACC_ENUM)) { - setIcon(new FlatSVGIcon("icons/enum.svg")); - } else if (classNode.access == (Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_SUPER)) { - setIcon(new FlatSVGIcon("icons/finalClass.svg")); - } else { - setIcon(new FlatSVGIcon("icons/class.svg")); - } - } - } else if (defaultTreeNode instanceof FolderTreeNode) { - setIcon(new FlatSVGIcon("icons/folder.svg")); - - FolderTreeNode folderTreeNode = (FolderTreeNode) defaultTreeNode; - if (folderTreeNode instanceof FileTreeNode) { - setIcon(new FlatSVGIcon("icons/file.svg")); - } - } - return new JPanel(new BorderLayout()) {{ - if (sel) { - setBackground(self.getBackgroundSelectionColor()); - } else { - setBackground(self.getBackground()); - } - add(new JLabel(value.toString()) {{ - setIcon(self.getIcon()); - }}, BorderLayout.CENTER); - }}; - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/instruction/AbstractInstructionPanel.java b/src/main/java/cn/enaium/joe/gui/panel/instruction/AbstractInstructionPanel.java deleted file mode 100644 index fd1805d..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/instruction/AbstractInstructionPanel.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.instruction; - -import cn.enaium.joe.util.LangUtil; -import cn.enaium.joe.util.OpcodeUtil; -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.InsnList; - -import javax.swing.*; -import javax.swing.border.EmptyBorder; -import java.awt.*; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Callable; - -/** - * @author Enaium - * @since 0.8.0 - */ -public abstract class AbstractInstructionPanel extends JPanel { - private final JComboBox opcode = new JComboBox<>(new DefaultComboBoxModel<>()); - - private final JPanel names = new JPanel(new GridLayout(0, 1)); - private final JPanel components = new JPanel(new GridLayout(0, 1)); - - private Callable confirm = () -> false; - - public AbstractInstructionPanel(AbstractInsnNode instruction) { - setLayout(new BorderLayout()); - if (instruction.getOpcode() != -1) { - DefaultComboBoxModel model = (DefaultComboBoxModel) opcode.getModel(); - getOpcodes().forEach(model::addElement); - model.setSelectedItem(OpcodeUtil.OPCODE.get(instruction.getOpcode())); - addComponent(new JLabel(LangUtil.i18n("instruction.opcode")), opcode); - } - - add(names, BorderLayout.WEST); - add(components, BorderLayout.CENTER); - } - - public void addComponent(JComponent name, JComponent component) { - names.add(new JPanel(new BorderLayout()) {{ - setBorder(new EmptyBorder(10, 10, 10, 10)); - add(name, BorderLayout.CENTER); - }}); - components.add(new JPanel(new BorderLayout()) {{ - setBorder(new EmptyBorder(10, 10, 10, 10)); - add(component, BorderLayout.CENTER); - }}); - } - - public void setConfirm(Callable callable) { - confirm = callable; - } - - public Callable getConfirm() { - return confirm; - } - - public Integer getOpcode() { - if (opcode.getSelectedItem() == null) { - throw new NullPointerException("unselected opcode"); - } - return OpcodeUtil.reverse(OpcodeUtil.OPCODE).get(opcode.getSelectedItem().toString()); - } - - public abstract List getOpcodes(); -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/instruction/FieldInstructionPanel.java b/src/main/java/cn/enaium/joe/gui/panel/instruction/FieldInstructionPanel.java deleted file mode 100644 index f986ec1..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/instruction/FieldInstructionPanel.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.instruction; - -import cn.enaium.joe.util.LangUtil; -import org.objectweb.asm.tree.FieldInsnNode; -import org.objectweb.asm.tree.InsnList; -import org.objectweb.asm.tree.TypeInsnNode; - -import javax.swing.*; -import java.util.ArrayList; -import java.util.List; - -/** - * @author Enaium - * @since 0.8.0 - */ -public class FieldInstructionPanel extends AbstractInstructionPanel { - public FieldInstructionPanel(FieldInsnNode instruction) { - super(instruction); - JTextField owner = new JTextField(instruction.owner); - JTextField name = new JTextField(instruction.name); - JTextField description = new JTextField(instruction.desc); - addComponent(new JLabel(LangUtil.i18n("instruction.owner")), owner); - addComponent(new JLabel(LangUtil.i18n("instruction.name")), name); - addComponent(new JLabel(LangUtil.i18n("instruction.description")), description); - setConfirm(() -> { - instruction.setOpcode(getOpcode()); - instruction.owner = owner.getText(); - instruction.name = owner.getText(); - instruction.desc = description.getText(); - return true; - }); - } - - @Override - public List getOpcodes() { - return new ArrayList() {{ - add("GETSTATIC"); - add("PUTSTATIC"); - add("GETFIELD"); - add("PUTFIELD"); - }}; - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/instruction/FrameInstructionPanel.java b/src/main/java/cn/enaium/joe/gui/panel/instruction/FrameInstructionPanel.java deleted file mode 100644 index 6c02c23..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/instruction/FrameInstructionPanel.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.instruction; - -import cn.enaium.joe.gui.panel.confirm.FrameListEditPanel; -import cn.enaium.joe.util.LangUtil; -import cn.enaium.joe.util.MessageUtil; -import cn.enaium.joe.util.OpcodeUtil; -import org.objectweb.asm.tree.FrameNode; -import org.objectweb.asm.tree.InsnList; - -import javax.swing.*; -import java.util.List; - -/** - * @author Enaium - * @since 0.8.0 - */ -public class FrameInstructionPanel extends AbstractInstructionPanel { - public FrameInstructionPanel(FrameNode instruction) { - super(instruction); - JComboBox component = new JComboBox<>(OpcodeUtil.FRAME.values().toArray(new String[0])); - component.setSelectedItem(OpcodeUtil.FRAME.get(instruction.type)); - addComponent(new JLabel(LangUtil.i18n("instruction.type")), component); - addComponent(new JLabel(LangUtil.i18n("instruction.localOrStack")), new JButton(LangUtil.i18n("button.edit")) {{ - addActionListener(e -> { - FrameListEditPanel frameListEditPanel = new FrameListEditPanel(instruction); - MessageUtil.confirm(frameListEditPanel, "Frame Edit", () -> { - frameListEditPanel.getConfirm().run(); - }, () -> { - frameListEditPanel.getCancel().run(); - }); - }); - }}); - setConfirm(() -> { - if (component.getSelectedItem() != null) { - instruction.type = OpcodeUtil.reverse(OpcodeUtil.FRAME).get(component.getSelectedItem().toString()); - return true; - } else { - return false; - } - }); - } - - @Override - public List getOpcodes() { - return null; - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/instruction/IncrInstructionPanel.java b/src/main/java/cn/enaium/joe/gui/panel/instruction/IncrInstructionPanel.java deleted file mode 100644 index 33410a4..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/instruction/IncrInstructionPanel.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.instruction; - -import cn.enaium.joe.util.LangUtil; -import org.objectweb.asm.tree.IincInsnNode; -import org.objectweb.asm.tree.InsnList; - -import javax.swing.*; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * @author Enaium - * @since 0.8.0 - */ -public class IncrInstructionPanel extends AbstractInstructionPanel { - public IncrInstructionPanel(IincInsnNode instruction) { - super(instruction); - JSpinner varIndex = new JSpinner(); - varIndex.setValue(instruction.var); - addComponent(new JLabel(LangUtil.i18n("instruction.varIndex")), varIndex); - JSpinner incr = new JSpinner(); - incr.setValue(instruction.incr); - addComponent(new JLabel(LangUtil.i18n("instruction.incr")), incr); - setConfirm(() -> { - instruction.var = Integer.parseInt(varIndex.getValue().toString()); - instruction.incr = Integer.parseInt(incr.getValue().toString()); - return true; - }); - } - - @Override - public List getOpcodes() { - return Collections.singletonList("IINC"); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/instruction/InstructionPanel.java b/src/main/java/cn/enaium/joe/gui/panel/instruction/InstructionPanel.java deleted file mode 100644 index ccaf23a..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/instruction/InstructionPanel.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.instruction; - -import cn.enaium.joe.util.OpcodeUtil; -import org.objectweb.asm.tree.InsnList; -import org.objectweb.asm.tree.InsnNode; - -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.List; - -/** - * @author Enaium - * @since 0.8.0 - */ -public class InstructionPanel extends AbstractInstructionPanel { - public InstructionPanel(InsnNode instruction) { - super(instruction); - setConfirm(() -> { - Field opcode = instruction.getClass().getSuperclass().getDeclaredField("opcode"); - opcode.setAccessible(true); - opcode.set(instruction, getOpcode()); - return true; - }); - } - - @Override - public List getOpcodes() { - return new ArrayList() {{ - add("NOP"); - add("ACONST_NULL"); - add("ICONST_M1"); - add("ICONST_0"); - add("ICONST_1"); - add("ICONST_2"); - add("ICONST_3"); - add("ICONST_4"); - add("ICONST_5"); - add("LCONST_0"); - add("LCONST_1"); - add("FCONST_0"); - add("FCONST_1"); - add("FCONST_2"); - add("DCONST_0"); - add("DCONST_1"); - add("IALOAD"); - add("LALOAD"); - add("FALOAD"); - add("DALOAD"); - add("AALOAD"); - add("BALOAD"); - add("CALOAD"); - add("SALOAD"); - add("IASTORE"); - add("LASTORE"); - add("FASTORE"); - add("DASTORE"); - add("AASTORE"); - add("BASTORE"); - add("CASTORE"); - add("SASTORE"); - add("POP"); - add("POP2"); - add("DUP"); - add("DUP_X1"); - add("DUP_X2"); - add("DUP2"); - add("DUP2_X1"); - add("DUP2_X2"); - add("SWAP"); - add("IADD"); - add("LADD"); - add("FADD"); - add("DADD"); - add("ISUB"); - add("LSUB"); - add("FSUB"); - add("DSUB"); - add("IMUL"); - add("LMUL"); - add("FMUL"); - add("DMUL"); - add("IDIV"); - add("LDIV"); - add("FDIV"); - add("DDIV"); - add("IREM"); - add("LREM"); - add("FREM"); - add("DREM"); - add("INEG"); - add("LNEG"); - add("FNEG"); - add("DNEG"); - add("ISHL"); - add("LSHL"); - add("ISHR"); - add("LSHR"); - add("IUSHR"); - add("LUSHR"); - add("IAND"); - add("LAND"); - add("IOR"); - add("LOR"); - add("IXOR"); - add("LXOR"); - add("I2L"); - add("I2F"); - add("I2D"); - add("L2I"); - add("L2F"); - add("L2D"); - add("F2I"); - add("F2L"); - add("F2D"); - add("D2I"); - add("D2L"); - add("D2F"); - add("I2B"); - add("I2C"); - add("I2S"); - add("LCMP"); - add("FCMPL"); - add("FCMPG"); - add("DCMPL"); - add("DCMPG"); - add("IRETURN"); - add("LRETURN"); - add("FRETURN"); - add("DRETURN"); - add("ARETURN"); - add("RETURN"); - add("ARRAYLENGTH"); - add("ATHROW"); - add("MONITORENTER"); - add("MONITOREXIT"); - }}; - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/instruction/IntInstructionPanel.java b/src/main/java/cn/enaium/joe/gui/panel/instruction/IntInstructionPanel.java deleted file mode 100644 index 38ed1e1..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/instruction/IntInstructionPanel.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.instruction; - -import cn.enaium.joe.util.LangUtil; -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.InsnList; -import org.objectweb.asm.tree.InsnNode; -import org.objectweb.asm.tree.IntInsnNode; - -import javax.swing.*; -import java.util.ArrayList; -import java.util.List; - -/** - * @author Enaium - * @since 0.8.0 - */ -public class IntInstructionPanel extends AbstractInstructionPanel { - public IntInstructionPanel(IntInsnNode instruction) { - super(instruction); - JSpinner operand = new JSpinner(); - operand.setValue(instruction.operand); - addComponent(new JLabel(LangUtil.i18n("instruction.operand")), operand); - setConfirm(() -> { - instruction.setOpcode(getOpcode()); - instruction.operand = Integer.parseInt(operand.getValue().toString()); - return true; - }); - } - - @Override - public List getOpcodes() { - return new ArrayList() {{ - add("BIPUSH"); - add("SIPUSH"); - add("NEWARRAY"); - }}; - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/instruction/InvokeDynamicInstructionPanel.java b/src/main/java/cn/enaium/joe/gui/panel/instruction/InvokeDynamicInstructionPanel.java deleted file mode 100644 index 47de3a7..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/instruction/InvokeDynamicInstructionPanel.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.instruction; - -import cn.enaium.joe.gui.panel.confirm.BootstrapMethodArgumentEditPanel; -import cn.enaium.joe.gui.panel.confirm.HandleEditPanel; -import cn.enaium.joe.util.LangUtil; -import cn.enaium.joe.util.MessageUtil; -import cn.enaium.joe.wrapper.Wrapper; -import org.objectweb.asm.Handle; -import org.objectweb.asm.tree.InvokeDynamicInsnNode; - -import javax.swing.*; -import java.util.Collections; -import java.util.List; - -/** - * @author Enaium - * @since 0.8.0 - */ -public class InvokeDynamicInstructionPanel extends AbstractInstructionPanel { - public InvokeDynamicInstructionPanel(InvokeDynamicInsnNode instruction) { - super(instruction); - JTextField name = new JTextField(instruction.name); - JTextField description = new JTextField(instruction.desc); - addComponent(new JLabel(LangUtil.i18n("instruction.name")), name); - addComponent(new JLabel(LangUtil.i18n("instruction.description")), description); - addComponent(new JLabel(LangUtil.i18n("instruction.bootstrapMethod")), new JButton(LangUtil.i18n("button.edit")) {{ - addActionListener(e -> { - Wrapper wrapper = new Wrapper<>(instruction.bsm); - HandleEditPanel handleEditPanel = new HandleEditPanel(wrapper); - MessageUtil.confirm(handleEditPanel, "Handle Edit", () -> { - handleEditPanel.getConfirm().run(); - instruction.bsm = wrapper.getWrapper(); - }, () -> { - - }); - }); - }}); - addComponent(new JLabel(LangUtil.i18n("instruction.bootstrapMethodArgument")), new JButton(LangUtil.i18n("button.edit")) {{ - addActionListener(e -> { - Wrapper bsmArgs = new Wrapper<>(instruction.bsmArgs); - BootstrapMethodArgumentEditPanel confirmPanel = new BootstrapMethodArgumentEditPanel(bsmArgs); - MessageUtil.confirm(confirmPanel, LangUtil.i18n("instruction.bootstrapMethodArgument"), () -> { - confirmPanel.getConfirm().run(); - instruction.bsmArgs = bsmArgs.getWrapper(); - }, () -> { - }); - }); - }}); - setConfirm(() -> { - instruction.name = name.getText(); - instruction.desc = description.getText(); - return true; - }); - } - - @Override - public List getOpcodes() { - return Collections.singletonList("INVOKEDYNAMIC"); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/instruction/JumpInstructionPanel.java b/src/main/java/cn/enaium/joe/gui/panel/instruction/JumpInstructionPanel.java deleted file mode 100644 index d94dafa..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/instruction/JumpInstructionPanel.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.instruction; - -import cn.enaium.joe.gui.component.LabelNodeComboBox; -import cn.enaium.joe.util.LangUtil; -import cn.enaium.joe.util.OpcodeUtil; -import cn.enaium.joe.wrapper.LabelNodeWrapper; -import org.objectweb.asm.tree.*; - -import javax.swing.*; -import java.util.ArrayList; -import java.util.List; - -/** - * @author Enaium - * @since 0.8.0 - */ -public class JumpInstructionPanel extends AbstractInstructionPanel { - public JumpInstructionPanel(JumpInsnNode instruction) { - super(instruction); - LabelNodeComboBox component = new LabelNodeComboBox(instruction, instruction.label); - addComponent(new JLabel(LangUtil.i18n("instruction.label")), component); - setConfirm(() -> { - Object selectedItem = component.getSelectedItem(); - if (selectedItem != null) { - instruction.setOpcode(getOpcode()); - instruction.label = ((LabelNodeWrapper) selectedItem).getWrapper(); - return true; - } - return false; - }); - } - - @Override - public List getOpcodes() { - return new ArrayList() {{ - add("IFEQ"); - add("IFNE"); - add("IFLT"); - add("IFGE"); - add("IFGT"); - add("IFLE"); - add("IF_ICMPEQ"); - add("IF_ICMPNE"); - add("IF_ICMPLT"); - add("IF_ICMPGE"); - add("IF_ICMPGT"); - add("IF_ICMPLE"); - add("IF_ACMPEQ"); - add("IF_ACMPNE"); - add("GOTO"); - add("JSR"); - add("IFNULL"); - add("IFNONNULL"); - }}; - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/instruction/LdcInstructionPanel.java b/src/main/java/cn/enaium/joe/gui/panel/instruction/LdcInstructionPanel.java deleted file mode 100644 index 90bc430..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/instruction/LdcInstructionPanel.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.instruction; - -import cn.enaium.joe.gui.panel.confirm.HandleEditPanel; -import cn.enaium.joe.util.LangUtil; -import cn.enaium.joe.util.MessageUtil; -import cn.enaium.joe.wrapper.Wrapper; -import org.objectweb.asm.Handle; -import org.objectweb.asm.Type; -import org.objectweb.asm.tree.InsnList; -import org.objectweb.asm.tree.LdcInsnNode; -import org.objectweb.asm.tree.VarInsnNode; - -import javax.swing.*; -import javax.swing.event.ListDataEvent; -import javax.swing.event.ListDataListener; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Objects; - -/** - * @author Enaium - * @since 0.8.0 - */ -public class LdcInstructionPanel extends AbstractInstructionPanel { - public LdcInstructionPanel(LdcInsnNode instruction) { - super(instruction); - JComboBox jComboBox = new JComboBox<>(new String[]{"String", "float", "double", "int", "long", "Class", "Handle"}); - addComponent(new JLabel("Type:"), jComboBox); - Handle handle = null; - if (instruction.cst instanceof String) { - jComboBox.setSelectedItem("String"); - } else if (instruction.cst instanceof Float) { - jComboBox.setSelectedItem("float"); - } else if (instruction.cst instanceof Double) { - jComboBox.setSelectedItem("double"); - } else if (instruction.cst instanceof Integer) { - jComboBox.setSelectedItem("int"); - } else if (instruction.cst instanceof Long) { - jComboBox.setSelectedItem("long"); - } else if (instruction.cst instanceof Type) { - jComboBox.setSelectedItem("Class"); - } else if (instruction.cst instanceof Handle) { - jComboBox.setSelectedItem("Handle"); - handle = ((Handle) instruction.cst); - } - - JTextField ldc = new JTextField(); - ldc.setText(instruction.cst.toString()); - JLabel verLabel = new JLabel(LangUtil.i18n("instruction.var")); - verLabel.setVisible(!(Objects.equals(jComboBox.getSelectedItem(), "Handle"))); - ldc.setVisible(!(Objects.equals(jComboBox.getSelectedItem(), "Handle"))); - addComponent(verLabel, ldc); - setConfirm(() -> { - Object value; - if (jComboBox.getSelectedItem() != null) { - switch (jComboBox.getSelectedItem().toString()) { - case "String": - value = ldc.getText(); - break; - case "float": - value = Float.parseFloat(ldc.getText()); - break; - case "double": - value = Double.parseDouble(ldc.getText()); - break; - case "int": - value = Integer.parseInt(ldc.getText()); - break; - case "long": - value = Long.parseLong(ldc.getText()); - break; - case "Class": - value = Type.getType(ldc.getText()); - break; - default: - return true; - } - instruction.cst = value; - } - return true; - }); - Handle finalHandle = handle; - - JLabel handleLabel = new JLabel(LangUtil.i18n("instruction.handle")); - handleLabel.setVisible(Objects.equals(jComboBox.getSelectedItem(), "Handle")); - JButton handleButton = new JButton(LangUtil.i18n("button.edit")) {{ - setVisible(Objects.equals(jComboBox.getSelectedItem(), "Handle")); - addActionListener(e -> { - Wrapper wrapper = new Wrapper<>(finalHandle); - HandleEditPanel message = new HandleEditPanel(wrapper); - MessageUtil.confirm(message, LangUtil.i18n("instruction.handle"), () -> { - message.getConfirm().run(); - instruction.cst = wrapper.getWrapper(); - }, () -> { - }); - }); - }}; - addComponent(handleLabel, handleButton); - jComboBox.getModel().addListDataListener(new ListDataListener() { - @Override - public void intervalAdded(ListDataEvent e) { - - } - - @Override - public void intervalRemoved(ListDataEvent e) { - - } - - @Override - public void contentsChanged(ListDataEvent e) { - handleLabel.setVisible(Objects.equals(jComboBox.getSelectedItem(), "Handle")); - handleButton.setVisible(Objects.equals(jComboBox.getSelectedItem(), "Handle")); - verLabel.setVisible(!Objects.equals(jComboBox.getSelectedItem(), "Handle")); - ldc.setVisible(!Objects.equals(jComboBox.getSelectedItem(), "Handle")); - } - }); - - } - - @Override - public List getOpcodes() { - return Collections.singletonList("LDC"); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/instruction/LineInstructionPanel.java b/src/main/java/cn/enaium/joe/gui/panel/instruction/LineInstructionPanel.java deleted file mode 100644 index 7e69321..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/instruction/LineInstructionPanel.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.instruction; - -import cn.enaium.joe.gui.component.LabelNodeComboBox; -import cn.enaium.joe.util.LangUtil; -import cn.enaium.joe.util.OpcodeUtil; -import cn.enaium.joe.wrapper.LabelNodeWrapper; -import org.objectweb.asm.tree.*; - -import javax.swing.*; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * @author Enaium - * @since 0.8.0 - */ -public class LineInstructionPanel extends AbstractInstructionPanel { - public LineInstructionPanel(LineNumberNode instruction) { - super(instruction); - JSpinner spinner = new JSpinner(); - spinner.setValue(instruction.line); - addComponent(new JLabel(LangUtil.i18n("instruction.line")), spinner); - LabelNodeComboBox component = new LabelNodeComboBox(instruction, instruction.start); - addComponent(new JLabel(LangUtil.i18n("instruction.start")), component); - - setConfirm(() -> { - Object selectedItem = component.getSelectedItem(); - if (selectedItem != null) { - instruction.line = Integer.parseInt(spinner.getValue().toString()); - instruction.start = ((LabelNodeWrapper) selectedItem).getWrapper(); - return true; - } - return false; - }); - } - - @Override - public List getOpcodes() { - return null; - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/instruction/LookupSwitchInstructionPanel.java b/src/main/java/cn/enaium/joe/gui/panel/instruction/LookupSwitchInstructionPanel.java deleted file mode 100644 index fbeb873..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/instruction/LookupSwitchInstructionPanel.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.instruction; - -import cn.enaium.joe.gui.component.LabelNodeComboBox; -import cn.enaium.joe.gui.panel.confirm.LookupSwitchEditPanel; -import cn.enaium.joe.util.LangUtil; -import cn.enaium.joe.util.MessageUtil; -import cn.enaium.joe.util.OpcodeUtil; -import cn.enaium.joe.wrapper.LabelNodeWrapper; -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.InsnList; -import org.objectweb.asm.tree.LabelNode; -import org.objectweb.asm.tree.LookupSwitchInsnNode; - -import javax.swing.*; -import java.util.Collections; -import java.util.List; - -/** - * @author Enaium - * @since 0.8.0 - */ -public class LookupSwitchInstructionPanel extends AbstractInstructionPanel { - public LookupSwitchInstructionPanel(LookupSwitchInsnNode instruction) { - super(instruction); - LabelNodeComboBox component = new LabelNodeComboBox(instruction, instruction.dflt); - addComponent(new JLabel(LangUtil.i18n("instruction.default")), component); - addComponent(new JLabel(LangUtil.i18n("instruction.keyOrLabel")), new JButton(LangUtil.i18n("button.edit")) {{ - addActionListener(e -> { - MessageUtil.confirm(new LookupSwitchEditPanel(instruction.keys, instruction.labels), LangUtil.i18n("instruction.keyOrLabel")); - }); - }}); - setConfirm(() -> { - Object selectedItem = component.getSelectedItem(); - if (selectedItem != null) { - instruction.dflt = ((LabelNodeWrapper) selectedItem).getWrapper(); - return true; - } - return false; - }); - } - - @Override - public List getOpcodes() { - return Collections.singletonList("LOOKUPSWITCH"); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/instruction/MethodInstructionPanel.java b/src/main/java/cn/enaium/joe/gui/panel/instruction/MethodInstructionPanel.java deleted file mode 100644 index f872973..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/instruction/MethodInstructionPanel.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.instruction; - -import cn.enaium.joe.util.LangUtil; -import org.objectweb.asm.tree.FieldInsnNode; -import org.objectweb.asm.tree.InsnList; -import org.objectweb.asm.tree.MethodInsnNode; - -import javax.swing.*; -import java.util.ArrayList; -import java.util.List; - -/** - * @author Enaium - * @since 0.8.0 - */ -public class MethodInstructionPanel extends AbstractInstructionPanel { - public MethodInstructionPanel(MethodInsnNode instruction) { - super(instruction); - JTextField owner = new JTextField(instruction.owner); - JTextField name = new JTextField(instruction.name); - JTextField description = new JTextField(instruction.desc); - JCheckBox isInterface = new JCheckBox() {{ - setHorizontalAlignment(JCheckBox.RIGHT); - }}; - addComponent(new JLabel(LangUtil.i18n("instruction.owner")), owner); - addComponent(new JLabel(LangUtil.i18n("instruction.name")), name); - addComponent(new JLabel(LangUtil.i18n("instruction.description")), description); - addComponent(new JLabel(LangUtil.i18n("instruction.interface")), isInterface); - setConfirm(() -> { - instruction.setOpcode(getOpcode()); - instruction.owner = owner.getText(); - instruction.name = name.getText(); - instruction.desc = description.getText(); - instruction.itf = isInterface.isSelected(); - return true; - }); - } - - @Override - public List getOpcodes() { - return new ArrayList() {{ - add("INVOKEVIRTUAL"); - add("INVOKESPECIAL"); - add("INVOKESTATIC"); - add("INVOKEINTERFACE"); - }}; - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/instruction/MultiANewArrayInstructionPanel.java b/src/main/java/cn/enaium/joe/gui/panel/instruction/MultiANewArrayInstructionPanel.java deleted file mode 100644 index 317eeb0..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/instruction/MultiANewArrayInstructionPanel.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.instruction; - -import cn.enaium.joe.util.LangUtil; -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.InsnList; -import org.objectweb.asm.tree.MultiANewArrayInsnNode; - -import javax.swing.*; -import java.util.Collections; -import java.util.List; - -/** - * @author Enaium - * @since 0.8.0 - */ -public class MultiANewArrayInstructionPanel extends AbstractInstructionPanel { - public MultiANewArrayInstructionPanel(MultiANewArrayInsnNode instruction) { - super(instruction); - JTextField description = new JTextField(); - description.setText(instruction.desc); - addComponent(new JLabel(LangUtil.i18n("instruction.description")), description); - JSpinner dimension = new JSpinner(); - dimension.setValue(instruction.dims); - addComponent(new JLabel(LangUtil.i18n("instruction.dimension")), dimension); - setConfirm(() -> { - instruction.desc = description.getText(); - instruction.dims = Integer.parseInt(dimension.getValue().toString()); - return true; - }); - } - - @Override - public List getOpcodes() { - return Collections.singletonList("MULTIANEWARRAY"); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/instruction/TableSwitchInstructionPanel.java b/src/main/java/cn/enaium/joe/gui/panel/instruction/TableSwitchInstructionPanel.java deleted file mode 100644 index f74a1d9..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/instruction/TableSwitchInstructionPanel.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.instruction; - -import cn.enaium.joe.gui.component.LabelNodeComboBox; -import cn.enaium.joe.gui.panel.confirm.LabelListEditPanel; -import cn.enaium.joe.util.LangUtil; -import cn.enaium.joe.util.MessageUtil; -import cn.enaium.joe.util.OpcodeUtil; -import cn.enaium.joe.wrapper.LabelNodeWrapper; -import org.benf.cfr.reader.util.StringUtils; -import org.objectweb.asm.tree.*; - -import javax.swing.*; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; - -/** - * @author Enaium - * @since 0.8.0 - */ -public class TableSwitchInstructionPanel extends AbstractInstructionPanel { - public TableSwitchInstructionPanel(TableSwitchInsnNode instruction) { - super(instruction); - JSpinner min = new JSpinner(); - min.setValue(instruction.min); - addComponent(new JLabel(LangUtil.i18n("instruction.min")), min); - JSpinner max = new JSpinner(); - max.setValue(instruction.max); - addComponent(new JLabel(LangUtil.i18n("instruction.max")), max); - LabelNodeComboBox component = new LabelNodeComboBox(instruction, instruction.dflt); - addComponent(new JLabel(LangUtil.i18n("instruction.default")), component); - addComponent(new JLabel(LangUtil.i18n("instruction.labels")), new JButton(LangUtil.i18n("button.edit")) {{ - addActionListener(e -> { - MessageUtil.confirm(new LabelListEditPanel(instruction.labels, OpcodeUtil.getInstructionList(instruction)), "Labels Edit"); - }); - }}); - - setConfirm(() -> { - Object selectedItem = component.getSelectedItem(); - if (selectedItem != null) { - instruction.min = Integer.parseInt(min.getValue().toString()); - instruction.max = Integer.parseInt(max.getValue().toString()); - instruction.dflt = ((LabelNodeWrapper) selectedItem).getWrapper(); - return true; - } - return false; - }); - } - - @Override - public List getOpcodes() { - return Collections.singletonList("TABLESWITCH"); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/instruction/TypeInstructionPanel.java b/src/main/java/cn/enaium/joe/gui/panel/instruction/TypeInstructionPanel.java deleted file mode 100644 index eedcc90..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/instruction/TypeInstructionPanel.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.instruction; - -import cn.enaium.joe.util.LangUtil; -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.InsnList; -import org.objectweb.asm.tree.TypeInsnNode; - -import javax.swing.*; -import java.util.ArrayList; -import java.util.List; - -/** - * @author Enaium - * @since 0.8.0 - */ -public class TypeInstructionPanel extends AbstractInstructionPanel { - public TypeInstructionPanel(TypeInsnNode instruction) { - super(instruction); - JTextField description = new JTextField(instruction.desc); - addComponent(new JLabel(LangUtil.i18n("instruction.description")), description); - setConfirm(() -> { - instruction.setOpcode(getOpcode()); - instruction.desc = description.getText(); - return true; - }); - } - - @Override - public List getOpcodes() { - return new ArrayList() {{ - add("NEW"); - add("ANEWARRAY"); - add("CHECKCAST"); - add("INSTANCEOF"); - }}; - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/instruction/VarInstructionPanel.java b/src/main/java/cn/enaium/joe/gui/panel/instruction/VarInstructionPanel.java deleted file mode 100644 index f6ada76..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/instruction/VarInstructionPanel.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.instruction; - -import cn.enaium.joe.util.LangUtil; -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.InsnList; -import org.objectweb.asm.tree.IntInsnNode; -import org.objectweb.asm.tree.VarInsnNode; - -import javax.swing.*; -import java.util.ArrayList; -import java.util.List; - -/** - * @author Enaium - * @since 0.8.0 - */ -public class VarInstructionPanel extends AbstractInstructionPanel { - public VarInstructionPanel(VarInsnNode instruction) { - super(instruction); - JSpinner spinner = new JSpinner(); - spinner.setValue(instruction.var); - addComponent(new JLabel(LangUtil.i18n("instruction.var")), spinner); - setConfirm(() -> { - instruction.setOpcode(getOpcode()); - instruction.var = Integer.parseInt(spinner.getValue().toString()); - return true; - }); - } - - @Override - public List getOpcodes() { - return new ArrayList() {{ - add("ILOAD"); - add("LLOAD"); - add("FLOAD"); - add("DLOAD"); - add("ALOAD"); - add("ISTORE"); - add("LSTORE"); - add("FSTORE"); - add("DSTORE"); - add("ASTORE"); - add("RET"); - }}; - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/menu/ConfigMenu.java b/src/main/java/cn/enaium/joe/gui/panel/menu/ConfigMenu.java deleted file mode 100644 index 1ca86e8..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/menu/ConfigMenu.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.menu; - -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.config.Config; -import cn.enaium.joe.dialog.ConfigDialog; -import cn.enaium.joe.util.LangUtil; - -import javax.swing.*; - -/** - * @author Enaium - * @since 0.7.0 - */ -public class ConfigMenu extends JMenu { - public ConfigMenu() { - super(LangUtil.i18n("menu.config")); - for (Config value : JavaOctetEditor.getInstance().config.getConfig().values()) { - add(new JMenuItem(value.getName()) {{ - addActionListener(e -> { - new ConfigDialog(value).setVisible(true); - }); - }}); - } - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/menu/FileMenu.java b/src/main/java/cn/enaium/joe/gui/panel/menu/FileMenu.java deleted file mode 100644 index d48bdbf..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/menu/FileMenu.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.menu; - -import cn.enaium.joe.gui.panel.menu.file.LoadMenuItem; -import cn.enaium.joe.gui.panel.menu.file.LoadRecentMenu; -import cn.enaium.joe.gui.panel.menu.file.SaveAllSourceMenuItem; -import cn.enaium.joe.gui.panel.menu.file.SaveMenuItem; -import cn.enaium.joe.util.LangUtil; - -import javax.swing.*; - -/** - * @author Enaium - */ -public class FileMenu extends JMenu { - public FileMenu() { - super(LangUtil.i18n("menu.file")); - add(new LoadMenuItem()); - add(new LoadRecentMenu()); - add(new SaveMenuItem()); - add(new JSeparator()); - add(new SaveAllSourceMenuItem()); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/menu/HelpMenu.java b/src/main/java/cn/enaium/joe/gui/panel/menu/HelpMenu.java deleted file mode 100644 index e2dd75f..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/menu/HelpMenu.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.menu; - -import cn.enaium.joe.gui.panel.menu.help.AboutMenuItem; -import cn.enaium.joe.gui.panel.menu.help.ContactMenuItem; -import cn.enaium.joe.util.LangUtil; - -import javax.swing.*; - -/** - * @author Enaium - */ -public class HelpMenu extends JMenu { - public HelpMenu() { - super(LangUtil.i18n("menu.help")); - add(new AboutMenuItem()); - add(new ContactMenuItem()); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/menu/MappingMenu.java b/src/main/java/cn/enaium/joe/gui/panel/menu/MappingMenu.java deleted file mode 100644 index d64e640..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/menu/MappingMenu.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.menu; - -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.task.RemappingTask; -import cn.enaium.joe.util.JFileChooserUtil; -import cn.enaium.joe.util.LangUtil; -import net.fabricmc.mappingio.format.MappingFormat; - -import javax.swing.*; -import javax.swing.filechooser.FileFilter; -import java.io.File; - -/** - * @author Enaium - * @since 1.0.0 - */ -public class MappingMenu extends JMenu { - public MappingMenu() { - super(LangUtil.i18n("menu.mapping")); - for (MappingFormat value : MappingFormat.values()) { - add(new JMenuItem(value.name) {{ - addActionListener(e -> { - File show = JFileChooserUtil.show(JFileChooserUtil.Type.OPEN, new FileFilter() { - @Override - public boolean accept(File f) { - return f.getName().matches(".+(txt|map|mapping|pro|srg|tsrg|tiny|tiyv2)") || f.isDirectory(); - } - - @Override - public String getDescription() { - return "Mapping file(*.txt,*.map,*.mapping,*.pro,*.srg)"; - } - }); - if (JavaOctetEditor.getInstance().getJar() != null && show != null) { - JavaOctetEditor.getInstance().task.submit(new RemappingTask(show, value)); - } - }); - }}); - } - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/menu/SearchMenu.java b/src/main/java/cn/enaium/joe/gui/panel/menu/SearchMenu.java deleted file mode 100644 index 50197c7..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/menu/SearchMenu.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.menu; - -import cn.enaium.joe.gui.panel.menu.search.FieldMenuItem; -import cn.enaium.joe.gui.panel.menu.search.LdcMenuItem; -import cn.enaium.joe.gui.panel.menu.search.MethodMenuItem; -import cn.enaium.joe.util.LangUtil; - -import javax.swing.*; - -/** - * @author Enaium - */ -public class SearchMenu extends JMenu { - public SearchMenu() { - super(LangUtil.i18n("menu.search")); - add(new LdcMenuItem()); - add(new FieldMenuItem()); - add(new MethodMenuItem()); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/menu/file/LoadRecentMenu.java b/src/main/java/cn/enaium/joe/gui/panel/menu/file/LoadRecentMenu.java deleted file mode 100644 index bab92aa..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/menu/file/LoadRecentMenu.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.menu.file; - -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.config.extend.ApplicationConfig; -import cn.enaium.joe.task.InputJarTask; -import cn.enaium.joe.util.LangUtil; -import com.formdev.flatlaf.extras.FlatSVGIcon; - -import javax.swing.*; -import javax.swing.event.MenuEvent; -import javax.swing.event.MenuListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.io.File; -import java.util.Set; - -/** - * @author Enaium - * @since 0.9.0 - */ -public class LoadRecentMenu extends JMenu { - public LoadRecentMenu() { - super(LangUtil.i18n("menu.file.loadRecent")); - addMenuListener(new MenuListener() { - @Override - public void menuSelected(MenuEvent e) { - removeAll(); - Set loadRecent = JavaOctetEditor.getInstance().config.getByClass(ApplicationConfig.class).loadRecent.getValue(); - for (String s : loadRecent) { - add(new JMenuItem(s) {{ - setIcon(new FlatSVGIcon("icons/jar.svg")); - addActionListener(e -> { - File file = new File(s); - if (file.exists()) { - JavaOctetEditor.getInstance().task.submit(new InputJarTask(file)); - } else { - loadRecent.remove(s); - } - }); - }}); - } - } - - @Override - public void menuDeselected(MenuEvent e) { - - } - - @Override - public void menuCanceled(MenuEvent e) { - - } - }); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/menu/file/SaveAllSourceMenuItem.java b/src/main/java/cn/enaium/joe/gui/panel/menu/file/SaveAllSourceMenuItem.java deleted file mode 100644 index 0a292de..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/menu/file/SaveAllSourceMenuItem.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.menu.file; - -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.service.decompiler.ProcyonDecompiler; -import cn.enaium.joe.jar.Jar; -import cn.enaium.joe.task.OutputJarTask; -import cn.enaium.joe.task.SaveAllSourceTask; -import cn.enaium.joe.util.ASyncUtil; -import cn.enaium.joe.util.JFileChooserUtil; -import cn.enaium.joe.util.LangUtil; -import org.objectweb.asm.tree.ClassNode; - -import javax.swing.*; -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.util.Map; -import java.util.jar.JarEntry; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - -/** - * @author Enaium - */ -public class SaveAllSourceMenuItem extends JMenuItem { - public SaveAllSourceMenuItem() { - super(LangUtil.i18n("menu.file.saveAllSource")); - addActionListener(e -> { - Jar jar = JavaOctetEditor.getInstance().getJar(); - if (jar == null) { - return; - } - - File show = JFileChooserUtil.show(JFileChooserUtil.Type.SAVE); - if (show != null) { - JavaOctetEditor.getInstance().task.submit(new SaveAllSourceTask(jar, show)); - } - }); - } -} \ No newline at end of file diff --git a/src/main/java/cn/enaium/joe/gui/panel/menu/file/SaveMenuItem.java b/src/main/java/cn/enaium/joe/gui/panel/menu/file/SaveMenuItem.java deleted file mode 100644 index 61662f0..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/menu/file/SaveMenuItem.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.menu.file; - -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.jar.Jar; -import cn.enaium.joe.task.OutputJarTask; -import cn.enaium.joe.util.ASyncUtil; -import cn.enaium.joe.util.JFileChooserUtil; -import cn.enaium.joe.util.LangUtil; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.tree.ClassNode; - -import javax.swing.*; -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.util.Map; -import java.util.jar.JarEntry; -import java.util.zip.ZipOutputStream; - -/** - * @author Enaium - */ -public class SaveMenuItem extends JMenuItem { - public SaveMenuItem() { - super(LangUtil.i18n("menu.file.save")); - addActionListener(e -> { - Jar jar = JavaOctetEditor.getInstance().getJar(); - if (jar == null) { - return; - } - File show = JFileChooserUtil.show(JFileChooserUtil.Type.SAVE); - if (show != null) { - JavaOctetEditor.getInstance().task.submit(new OutputJarTask(jar, show)); - } - }); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/menu/help/AboutMenuItem.java b/src/main/java/cn/enaium/joe/gui/panel/menu/help/AboutMenuItem.java deleted file mode 100644 index d678c65..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/menu/help/AboutMenuItem.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.menu.help; - -import cn.enaium.joe.dialog.AboutDialog; -import cn.enaium.joe.util.LangUtil; - -import javax.swing.*; - -/** - * @author Enaium - */ -public class AboutMenuItem extends JMenuItem { - public AboutMenuItem() { - super(LangUtil.i18n("menu.help.about")); - addActionListener(e -> new AboutDialog().setVisible(true)); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/menu/help/ContactMenuItem.java b/src/main/java/cn/enaium/joe/gui/panel/menu/help/ContactMenuItem.java deleted file mode 100644 index 2df40db..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/menu/help/ContactMenuItem.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.menu.help; - -import cn.enaium.joe.dialog.ContactDialog; -import cn.enaium.joe.util.LangUtil; - -import javax.swing.*; - -/** - * @author Enaium - */ -public class ContactMenuItem extends JMenuItem { - public ContactMenuItem() { - super(LangUtil.i18n("menu.help.contact")); - addActionListener(e -> { - new ContactDialog().setVisible(true); - }); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/menu/search/FieldMenuItem.java b/src/main/java/cn/enaium/joe/gui/panel/menu/search/FieldMenuItem.java deleted file mode 100644 index d1a8f17..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/menu/search/FieldMenuItem.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.menu.search; - -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.dialog.search.SearchFieldDialog; -import cn.enaium.joe.jar.Jar; -import cn.enaium.joe.util.LangUtil; - -import javax.swing.*; - -/** - * @author Enaium - * @since 0.5.0 - */ -public class FieldMenuItem extends JMenuItem { - public FieldMenuItem() { - super(LangUtil.i18n("menu.search.field")); - addActionListener(e -> { - Jar jar = JavaOctetEditor.getInstance().getJar(); - if (jar == null) { - return; - } - new SearchFieldDialog().setVisible(true); - }); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/menu/search/MethodMenuItem.java b/src/main/java/cn/enaium/joe/gui/panel/menu/search/MethodMenuItem.java deleted file mode 100644 index b77f9df..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/menu/search/MethodMenuItem.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.menu.search; - -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.dialog.search.SearchFieldDialog; -import cn.enaium.joe.dialog.search.SearchMethodDialog; -import cn.enaium.joe.jar.Jar; -import cn.enaium.joe.util.LangUtil; - -import javax.swing.*; - -/** - * @author Enaium - * @since 0.5.0 - */ -public class MethodMenuItem extends JMenuItem { - public MethodMenuItem() { - super(LangUtil.i18n("menu.search.method")); - addActionListener(e -> { - Jar jar = JavaOctetEditor.getInstance().getJar(); - if (jar == null) { - return; - } - new SearchMethodDialog().setVisible(true); - }); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/method/MethodInfoTabPanel.java b/src/main/java/cn/enaium/joe/gui/panel/method/MethodInfoTabPanel.java deleted file mode 100644 index 3b8c311..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/method/MethodInfoTabPanel.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.method; - -import cn.enaium.joe.dialog.AnnotationListDialog; -import cn.enaium.joe.util.LangUtil; -import cn.enaium.joe.util.StringUtil; -import net.miginfocom.swing.MigLayout; -import org.benf.cfr.reader.util.StringUtils; -import org.objectweb.asm.tree.MethodNode; - -import javax.swing.*; -import java.awt.*; -import java.util.ArrayList; -import java.util.Arrays; - -/** - * @author Enaium - * @since 0.6.0 - */ -public class MethodInfoTabPanel extends JPanel { - public MethodInfoTabPanel(MethodNode methodNode) { - setLayout(new MigLayout("fillx", "[fill][fill]")); - add(new JLabel(LangUtil.i18n("class.info.name"))); - JTextField name = new JTextField(methodNode.name); - add(name, "wrap"); - add(new JLabel(LangUtil.i18n("class.info.description"))); - JTextField description = new JTextField(methodNode.desc); - add(description, "wrap"); - add(new JLabel(LangUtil.i18n("class.info.access"))); - JTextField access = new JTextField(String.valueOf(methodNode.access)); - add(access, "wrap"); - add(new JLabel(LangUtil.i18n("class.info.signature"))); - JTextField signature = new JTextField(methodNode.signature); - add(signature, "wrap"); - add(new JLabel(LangUtil.i18n("class.info.exceptions"))); - JTextField exceptions = new JTextField(StringUtils.join(methodNode.exceptions, ";")); - add(exceptions, "wrap"); - - add(new JLabel("Visible Annotation:")); - add(new JButton(LangUtil.i18n("button.edit")) {{ - addActionListener(e -> { - if (methodNode.visibleAnnotations != null) { - new AnnotationListDialog(methodNode.visibleAnnotations).setVisible(true); - } - }); - }}, "wrap"); - add(new JLabel("Invisible Annotation:")); - add(new JButton(LangUtil.i18n("button.edit")) {{ - addActionListener(e -> { - if (methodNode.invisibleAnnotations != null) { - new AnnotationListDialog(methodNode.invisibleAnnotations).setVisible(true); - } - }); - }}, "wrap"); - add(new JButton(LangUtil.i18n("button.save")) {{ - addActionListener(e -> { - - if (!StringUtil.isBlank(name.getText())) { - methodNode.name = name.getText(); - } - - if (!StringUtil.isBlank(description.getText())) { - methodNode.desc = description.getText(); - } else { - methodNode.desc = null; - } - - if (!StringUtil.isBlank(access.getText())) { - methodNode.access = Integer.parseInt(access.getText()); - } - - if (!StringUtil.isBlank(signature.getText())) { - methodNode.signature = signature.getName(); - } else { - methodNode.signature = null; - } - - if (!StringUtil.isBlank(signature.getText())) { - methodNode.exceptions = Arrays.asList(signature.getText().split(";")); - } else { - methodNode.exceptions = new ArrayList<>(); - } - - JOptionPane.showMessageDialog(MethodInfoTabPanel.this, LangUtil.i18n("success")); - }); - }}, "span 2"); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/method/MethodInstructionPanel.java b/src/main/java/cn/enaium/joe/gui/panel/method/MethodInstructionPanel.java deleted file mode 100644 index dd25d31..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/method/MethodInstructionPanel.java +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.method; - -import cn.enaium.joe.gui.component.InstructionComboBox; -import cn.enaium.joe.gui.panel.confirm.InstructionEditPanel; -import cn.enaium.joe.util.*; -import cn.enaium.joe.wrapper.InstructionWrapper; -import org.objectweb.asm.Handle; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.tree.*; - -import javax.swing.*; -import java.awt.*; -import java.awt.datatransfer.StringSelection; -import java.awt.event.KeyEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.ArrayList; -import java.util.HashMap; - -/** - * @author Enaium - * @since 0.8.0 - */ -public class MethodInstructionPanel extends JPanel { - public MethodInstructionPanel(MethodNode methodNode) { - super(new BorderLayout()); - DefaultListModel instructionDefaultListModel = new DefaultListModel<>(); - JList instructionJList = new JList<>(instructionDefaultListModel); - instructionJList.setPrototypeCellValue(new InstructionWrapper(null)); - instructionJList.setCellRenderer((list, value, index, isSelected, cellHasFocus) -> new JPanel(new BorderLayout()) {{ - if (isSelected) { - setBackground(list.getSelectionBackground()); - } else { - setBackground(list.getBackground()); - } - add(new JLabel(String.format("%04d ", index)), BorderLayout.WEST); - add(new JLabel(value.toString()), BorderLayout.CENTER); - }}); - for (AbstractInsnNode instruction : methodNode.instructions) { - instructionDefaultListModel.addElement(new InstructionWrapper(instruction)); - } - - JPopupMenu jPopupMenu = new JPopupMenu(); - jPopupMenu.add(new JMenuItem(LangUtil.i18n("popup.instruction.edit")) {{ - addActionListener(e -> { - InstructionWrapper selectedValue = instructionJList.getSelectedValue(); - if (selectedValue != null && !(selectedValue.getWrapper() instanceof LabelNode)) { - MessageUtil.confirm(new InstructionEditPanel(selectedValue.getWrapper()), LangUtil.i18n("popup.instruction.edit")); - } - }); - }}); - - jPopupMenu.add(new JMenuItem(LangUtil.i18n("popup.instruction.clone")) {{ - addActionListener(e -> { - InstructionWrapper selectedValue = instructionJList.getSelectedValue(); - if (instructionJList.getSelectedIndex() != -1 || selectedValue != null) { - AbstractInsnNode clone; - if (selectedValue.getWrapper() instanceof LabelNode) { - clone = new LabelNode(); - } else { - clone = selectedValue.getWrapper().clone(new HashMap<>()); - } - - instructionDefaultListModel.add(instructionJList.getSelectedIndex() + 1, new InstructionWrapper(clone)); - methodNode.instructions.insert(selectedValue.getWrapper(), clone); - } - }); - }}); - - jPopupMenu.add(new JMenuItem(LangUtil.i18n("popup.instructions.remove")) {{ - addActionListener(e -> { - InstructionWrapper selectedValue = instructionJList.getSelectedValue(); - if (instructionJList.getSelectedIndex() != -1 || selectedValue != null) { - MessageUtil.confirm(LangUtil.i18n("dialog.wantRemove"), LangUtil.i18n("button.remove"), () -> { - instructionDefaultListModel.remove(instructionJList.getSelectedIndex()); - methodNode.instructions.remove(selectedValue.getWrapper()); - }); - } - }); - }}); - - jPopupMenu.add(new JMenuItem(LangUtil.i18n("popup.instructions.copyText")) {{ - addActionListener(e -> { - InstructionWrapper selectedValue = instructionJList.getSelectedValue(); - if (instructionJList.getSelectedIndex() != -1 || selectedValue != null) { - Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(HtmlUtil.remove(selectedValue.toString())), null); - } - }); - }}); - - jPopupMenu.add(new JMenuItem(LangUtil.i18n("popup.instructions.insertBefore")) {{ - addActionListener(e -> { - insert(methodNode, instructionJList, true); - }); - }}); - - jPopupMenu.add(new JMenuItem(LangUtil.i18n("popup.instructions.insertAfter")) {{ - addActionListener(e -> { - insert(methodNode, instructionJList, false); - }); - }}); - - jPopupMenu.add(new JMenuItem(LangUtil.i18n("popup.instructions.moveUp")) {{ - addActionListener(e -> { - moveInstruction(instructionJList, methodNode, true); - }); - }}); - - jPopupMenu.add(new JMenuItem(LangUtil.i18n("popup.instructions.moveDown")) {{ - addActionListener(e -> { - moveInstruction(instructionJList, methodNode, false); - }); - }}); - - JMenuUtil.addPopupMenu(instructionJList, () -> jPopupMenu, () -> instructionJList.getSelectedValue() != null); - add(new JScrollPane(instructionJList), BorderLayout.CENTER); - } - - private static void moveInstruction(JList instructionJList, MethodNode methodNode, boolean up) { - DefaultListModel instructionDefaultListModel = ((DefaultListModel) instructionJList.getModel()); - InstructionWrapper selectedValue = instructionJList.getSelectedValue(); - if (instructionJList.getSelectedIndex() != -1 || selectedValue != null) { - AbstractInsnNode node = up ? selectedValue.getWrapper().getPrevious() : selectedValue.getWrapper().getNext(); - if (node != null) { - try { - InstructionWrapper instructionWrapper = instructionDefaultListModel.get(instructionJList.getSelectedIndex() + (up ? -1 : 1)); - instructionDefaultListModel.removeElement(instructionWrapper); - instructionDefaultListModel.add(instructionJList.getSelectedIndex() + (up ? 1 : 0), instructionWrapper); - } catch (Exception ignore) { - - } - methodNode.instructions.remove(node); - if (up) { - methodNode.instructions.insert(selectedValue.getWrapper(), node); - } else { - methodNode.instructions.insertBefore(selectedValue.getWrapper(), node); - } - } - } - } - - private static void insert(MethodNode methodNode, JList instructionJList, boolean before) { - if (instructionJList.getSelectedIndex() == -1 || instructionJList.getSelectedValue() == null) { - return; - } - DefaultListModel instructionDefaultListModel = ((DefaultListModel) instructionJList.getModel()); - InstructionComboBox instructionComboBox = new InstructionComboBox(); - MessageUtil.confirm(instructionComboBox, "select insert instruction", () -> { - AbstractInsnNode abstractInsnNode; - int selectedIndex = instructionComboBox.getSelectedIndex(); - switch (selectedIndex) { - case AbstractInsnNode.INSN: - abstractInsnNode = new InsnNode(Opcodes.NOP); - break; - case AbstractInsnNode.INT_INSN: - abstractInsnNode = new IntInsnNode(Opcodes.BIPUSH, 0); - break; - case AbstractInsnNode.VAR_INSN: - abstractInsnNode = new VarInsnNode(Opcodes.ILOAD, 0); - break; - case AbstractInsnNode.TYPE_INSN: - abstractInsnNode = new TypeInsnNode(Opcodes.ILOAD, ""); - break; - case AbstractInsnNode.FIELD_INSN: - abstractInsnNode = new FieldInsnNode(Opcodes.GETSTATIC, "", "", ""); - break; - case AbstractInsnNode.METHOD_INSN: - abstractInsnNode = new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "", "", "", false); - break; - case AbstractInsnNode.INVOKE_DYNAMIC_INSN: - abstractInsnNode = new InvokeDynamicInsnNode("", "", new Handle(Opcodes.H_GETFIELD, "", "", "", false)); - break; - case AbstractInsnNode.JUMP_INSN: - abstractInsnNode = new JumpInsnNode(Opcodes.IFEQ, OpcodeUtil.getFirstLabel(methodNode.instructions)); - break; - case AbstractInsnNode.LABEL: - abstractInsnNode = new LabelNode(); - break; - case AbstractInsnNode.LDC_INSN: - abstractInsnNode = new LdcInsnNode(""); - break; - case AbstractInsnNode.IINC_INSN: - abstractInsnNode = new IntInsnNode(Opcodes.IINC, 0); - break; - case AbstractInsnNode.TABLESWITCH_INSN: - abstractInsnNode = new TableSwitchInsnNode(0, 0, OpcodeUtil.getFirstLabel(methodNode.instructions)); - break; - case AbstractInsnNode.LOOKUPSWITCH_INSN: - abstractInsnNode = new LookupSwitchInsnNode(OpcodeUtil.getFirstLabel(methodNode.instructions), new int[]{}, new LabelNode[]{}); - break; - case AbstractInsnNode.MULTIANEWARRAY_INSN: - abstractInsnNode = new MultiANewArrayInsnNode("", 0); - break; - case AbstractInsnNode.FRAME: - abstractInsnNode = new FrameNode(Opcodes.F_NEW, 0, new Object[]{}, 0, new Object[]{}); - break; - case AbstractInsnNode.LINE: - abstractInsnNode = new LineNumberNode(0, OpcodeUtil.getFirstLabel(methodNode.instructions)); - break; - default: - throw new RuntimeException(); - } - - MessageUtil.confirm(new InstructionEditPanel(abstractInsnNode), LangUtil.i18n("popup.instruction.edit"), () -> { - if (before) { - methodNode.instructions.insertBefore(instructionJList.getSelectedValue().getWrapper(), abstractInsnNode); - } else { - methodNode.instructions.insert(instructionJList.getSelectedValue().getWrapper(), abstractInsnNode); - } - instructionDefaultListModel.add(instructionJList.getSelectedIndex() + (before ? 0 : 1), new InstructionWrapper(abstractInsnNode)); - }); - }); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/method/MethodTabPanel.java b/src/main/java/cn/enaium/joe/gui/panel/method/MethodTabPanel.java deleted file mode 100644 index 7b5d4f2..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/method/MethodTabPanel.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.method; - -import org.objectweb.asm.tree.MethodNode; - -import javax.swing.*; -import java.awt.*; - -/** - * @author Enaium - * @since 0.8.0 - */ -public class MethodTabPanel extends JPanel { - public MethodTabPanel(MethodNode methodNode) { - super(new BorderLayout()); - JTabbedPane jTabbedPane = new JTabbedPane(); - jTabbedPane.setTabPlacement(JTabbedPane.BOTTOM); - jTabbedPane.addTab("InstructionEdit", new MethodInstructionPanel(methodNode)); - jTabbedPane.addTab("InfoEdit", new MethodInfoTabPanel(methodNode)); - add(jTabbedPane); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/popup/AbstractPopup.java b/src/main/java/cn/enaium/joe/gui/panel/popup/AbstractPopup.java deleted file mode 100644 index bab4ef0..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/popup/AbstractPopup.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.popup; - -import cn.enaium.joe.JavaOctetEditor; -import com.formdev.flatlaf.extras.FlatSVGIcon; - -import javax.swing.*; -import javax.swing.border.EmptyBorder; -import java.awt.*; -import java.awt.event.FocusEvent; -import java.awt.event.FocusListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; - -/** - * @author Enaium - * @since 1.2.0 - */ -public abstract class AbstractPopup extends JPanel { - private Popup popup; - - protected AbstractPopup(String name) { - super(new BorderLayout()); - add(new JPanel(new BorderLayout()) {{ - setBorder(new EmptyBorder(5, 5, 5, 5)); - setBackground(new JButton().getBackground()); - add(new JLabel(name), BorderLayout.CENTER); - add(new JLabel(new FlatSVGIcon("icons/minimize.svg") {{ - addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - destroy(); - } - }); - }}), BorderLayout.EAST); - - }}, BorderLayout.NORTH); - } - - public void place(int x, int y) { - if (popup == null) { - popup = PopupFactory.getSharedInstance().getPopup(JavaOctetEditor.getInstance().window, this, x, y); - popup.show(); - } - } - - public void destroy() { - if (popup != null) { - popup.hide(); - popup = null; - } - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/popup/TaskListPopup.java b/src/main/java/cn/enaium/joe/gui/panel/popup/TaskListPopup.java deleted file mode 100644 index 0076019..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/popup/TaskListPopup.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.popup; - -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.task.AbstractTask; -import cn.enaium.joe.util.Pair; - -import javax.swing.*; -import java.awt.*; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -/** - * @author Enaium - * @since 1.2.0 - */ -public class TaskListPopup extends AbstractPopup { - public TaskListPopup() { - super("TaskList"); - JList> comp = new JList<>(); - comp.setCellRenderer((list, value, index, isSelected, cellHasFocus) -> new JProgressBar() {{ - setValue(value.getProgress()); - setStringPainted(true); - setString(String.format("%s:%s", value.getName(), value.getProgress()) + "%"); - }}); - add(new JScrollPane(comp), BorderLayout.CENTER); - ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1); - scheduledExecutorService.scheduleAtFixedRate(() -> { - SwingUtilities.invokeLater(() -> { - DefaultListModel> abstractTaskDefaultListModel = new DefaultListModel<>(); - for (Pair, CompletableFuture> abstractTaskCompletableFuturePair : JavaOctetEditor.getInstance().task.getTask()) { - abstractTaskDefaultListModel.addElement(abstractTaskCompletableFuturePair.getKey()); - } - comp.setModel(abstractTaskDefaultListModel); - }); - }, 1, 1, TimeUnit.MILLISECONDS); - } -} diff --git a/src/main/java/cn/enaium/joe/gui/panel/search/ResultNode.java b/src/main/java/cn/enaium/joe/gui/panel/search/ResultNode.java deleted file mode 100644 index 22123ae..0000000 --- a/src/main/java/cn/enaium/joe/gui/panel/search/ResultNode.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.panel.search; - -import cn.enaium.joe.util.ColorUtil; -import cn.enaium.joe.util.HtmlUtil; -import org.objectweb.asm.tree.ClassNode; - -import java.awt.*; - -/** - * @author Enaium - */ -public class ResultNode { - private ClassNode classNode; - - private final String text; - - public ResultNode() { - text = " "; - } - - public ResultNode(ClassNode classNode, String result) { - this.classNode = classNode; - text = HtmlUtil.toHtml(HtmlUtil.setColor(classNode.name, Color.WHITE) + "#" + result); - } - - public ClassNode getClassNode() { - return classNode; - } - - @Override - public String toString() { - return text; - } -} diff --git a/src/main/java/cn/enaium/joe/gui/ui/VerticalLabelUI.java b/src/main/java/cn/enaium/joe/gui/ui/VerticalLabelUI.java deleted file mode 100644 index aa6f61d..0000000 --- a/src/main/java/cn/enaium/joe/gui/ui/VerticalLabelUI.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.gui.ui; - -import javax.swing.*; -import javax.swing.plaf.basic.BasicLabelUI; -import java.awt.*; -import java.awt.geom.AffineTransform; - -public class VerticalLabelUI extends BasicLabelUI { - static { - labelUI = new VerticalLabelUI(false); - } - - protected boolean clockwise; - - public VerticalLabelUI(boolean clockwise) { - this.clockwise = clockwise; - } - - public Dimension getPreferredSize(JComponent c) { - Dimension dim = super.getPreferredSize(c); - return new Dimension(dim.height, dim.width); - } - - private static final Rectangle paintIconR = new Rectangle(); - private static final Rectangle paintTextR = new Rectangle(); - private static final Rectangle paintViewR = new Rectangle(); - private static Insets paintViewInsets = new Insets(0, 0, 0, 0); - - public void paint(Graphics g, JComponent c) { - - JLabel label = (JLabel) c; - String text = label.getText(); - Icon icon = (label.isEnabled()) ? label.getIcon() : label.getDisabledIcon(); - - if ((icon == null) && (text == null)) { - return; - } - - FontMetrics fm = g.getFontMetrics(); - paintViewInsets = c.getInsets(paintViewInsets); - - paintViewR.x = paintViewInsets.left; - paintViewR.y = paintViewInsets.top; - - // Use inverted height & width - paintViewR.height = c.getWidth() - (paintViewInsets.left + paintViewInsets.right); - paintViewR.width = c.getHeight() - (paintViewInsets.top + paintViewInsets.bottom); - - paintIconR.x = paintIconR.y = paintIconR.width = paintIconR.height = 0; - paintTextR.x = paintTextR.y = paintTextR.width = paintTextR.height = 0; - - String clippedText = layoutCL(label, fm, text, icon, paintViewR, paintIconR, paintTextR); - - Graphics2D g2 = (Graphics2D) g; - AffineTransform tr = g2.getTransform(); - - if (icon != null) { - icon.paintIcon(c, g, paintIconR.x, paintIconR.y); - } - - if (clockwise) { - g2.rotate(Math.PI / 2); - g2.translate(0, -c.getWidth()); - } else { - g2.rotate(-Math.PI / 2); - g2.translate(-c.getHeight(), 0); - } - - if (text != null) { - int textX = paintTextR.x; - int textY = paintTextR.y + fm.getAscent(); - - if (label.isEnabled()) { - paintEnabledText(label, g, clippedText, textX, textY); - } else { - paintDisabledText(label, g, clippedText, textX, textY); - } - } - - g2.setTransform(tr); - } -} - diff --git a/src/main/java/cn/enaium/joe/jar/Jar.java b/src/main/java/cn/enaium/joe/jar/Jar.java deleted file mode 100644 index 88e9503..0000000 --- a/src/main/java/cn/enaium/joe/jar/Jar.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.jar; - -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.config.extend.ApplicationConfig; -import cn.enaium.joe.util.Util; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.tree.ClassNode; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.Enumeration; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; - -/** - * @author Enaium - */ -public class Jar { - public Map classes = new LinkedHashMap<>(); - public Map resources = new LinkedHashMap<>(); - - public Jar copy() { - Jar jar = new Jar(); - jar.classes.putAll(classes); - jar.resources.putAll(resources); - return jar; - } -} diff --git a/src/main/java/cn/enaium/joe/service/DecompileService.java b/src/main/java/cn/enaium/joe/service/DecompileService.java deleted file mode 100644 index 061451e..0000000 --- a/src/main/java/cn/enaium/joe/service/DecompileService.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.service; - -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.config.extend.ApplicationConfig; -import cn.enaium.joe.config.value.ModeValue; -import cn.enaium.joe.service.decompiler.*; - -/** - * @author Enaium - * @since 0.7.0 - */ -public class DecompileService { - public static IDecompiler getService() { - ModeValue decompilerMode = JavaOctetEditor.getInstance().config.getByClass(ApplicationConfig.class).decompilerMode; - switch (decompilerMode.getValue()) { - case "CFR": return new CFRDecompiler(); - case "Procyon": return new ProcyonDecompiler(); - case "FernFlower": return new FernFlowerDecompiler(); - } - throw new NullPointerException("Not found decompiler"); - } -} diff --git a/src/main/java/cn/enaium/joe/service/decompiler/CFRDecompiler.java b/src/main/java/cn/enaium/joe/service/decompiler/CFRDecompiler.java deleted file mode 100644 index 03c8269..0000000 --- a/src/main/java/cn/enaium/joe/service/decompiler/CFRDecompiler.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.service.decompiler; - -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.config.extend.CFRConfig; -import org.benf.cfr.reader.PluginRunner; -import org.benf.cfr.reader.api.ClassFileSource; -import org.benf.cfr.reader.bytecode.analysis.parse.utils.Pair; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.tree.ClassNode; - -import java.io.IOException; -import java.util.Collection; - -/** - * @author Enaium - * @since 0.7.0 - */ -public class CFRDecompiler implements IDecompiler { - @Override - public String decompile(ClassNode classNode) { - ClassFileSource cfs = new ClassFileSource() { - @Override - public void informAnalysisRelativePathDetail(String a, String b) { - } - - @Override - public String getPossiblyRenamedPath(String path) { - return path; - } - - @Override - public Pair getClassFileContent(String path) throws IOException { - String name = path.substring(0, path.length() - 6); - if (name.equals(classNode.name)) { - ClassWriter classWriter = new ClassWriter(0); - classNode.accept(classWriter); - return Pair.make(classWriter.toByteArray(), name); - } - return null; - } - - @Override - public Collection addJar(String arg0) { - throw new RuntimeException(); - } - }; - return new PluginRunner(JavaOctetEditor.getInstance().config.getConfigMap(CFRConfig.class), cfs).getDecompilationFor(classNode.name); - } -} diff --git a/src/main/java/cn/enaium/joe/util/BytecodeTokenMaker.java b/src/main/java/cn/enaium/joe/util/BytecodeTokenMaker.java deleted file mode 100644 index e884ab0..0000000 --- a/src/main/java/cn/enaium/joe/util/BytecodeTokenMaker.java +++ /dev/null @@ -1,442 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.util; - -import org.fife.ui.rsyntaxtextarea.*; - -import javax.swing.*; -import javax.swing.text.Segment; - -/** - * @author Enaium - */ -public class BytecodeTokenMaker extends AbstractTokenMaker { - @Override - public TokenMap getWordsToHighlight() { - TokenMap tokenMap = new TokenMap(); - tokenMap.put("NOP", Token.RESERVED_WORD); - tokenMap.put("ACONST_NULL", Token.RESERVED_WORD); - tokenMap.put("ICONST_M1", Token.RESERVED_WORD); - tokenMap.put("ICONST_0", Token.RESERVED_WORD); - tokenMap.put("ICONST_1", Token.RESERVED_WORD); - tokenMap.put("ICONST_2", Token.RESERVED_WORD); - tokenMap.put("ICONST_3", Token.RESERVED_WORD); - tokenMap.put("ICONST_4", Token.RESERVED_WORD); - tokenMap.put("ICONST_5", Token.RESERVED_WORD); - tokenMap.put("LCONST_0", Token.RESERVED_WORD); - tokenMap.put("LCONST_1", Token.RESERVED_WORD); - tokenMap.put("FCONST_0", Token.RESERVED_WORD); - tokenMap.put("FCONST_1", Token.RESERVED_WORD); - tokenMap.put("FCONST_2", Token.RESERVED_WORD); - tokenMap.put("DCONST_0", Token.RESERVED_WORD); - tokenMap.put("DCONST_1", Token.RESERVED_WORD); - tokenMap.put("BIPUSH", Token.RESERVED_WORD); - tokenMap.put("SIPUSH", Token.RESERVED_WORD); - tokenMap.put("LDC", Token.RESERVED_WORD); - tokenMap.put("ILOAD", Token.RESERVED_WORD); - tokenMap.put("LLOAD", Token.RESERVED_WORD); - tokenMap.put("FLOAD", Token.RESERVED_WORD); - tokenMap.put("DLOAD", Token.RESERVED_WORD); - tokenMap.put("ALOAD", Token.RESERVED_WORD); - tokenMap.put("IALOAD", Token.RESERVED_WORD); - tokenMap.put("LALOAD", Token.RESERVED_WORD); - tokenMap.put("FALOAD", Token.RESERVED_WORD); - tokenMap.put("DALOAD", Token.RESERVED_WORD); - tokenMap.put("AALOAD", Token.RESERVED_WORD); - tokenMap.put("BALOAD", Token.RESERVED_WORD); - tokenMap.put("CALOAD", Token.RESERVED_WORD); - tokenMap.put("SALOAD", Token.RESERVED_WORD); - tokenMap.put("ISTORE", Token.RESERVED_WORD); - tokenMap.put("LSTORE", Token.RESERVED_WORD); - tokenMap.put("FSTORE", Token.RESERVED_WORD); - tokenMap.put("DSTORE", Token.RESERVED_WORD); - tokenMap.put("ASTORE", Token.RESERVED_WORD); - tokenMap.put("IASTORE", Token.RESERVED_WORD); - tokenMap.put("LASTORE", Token.RESERVED_WORD); - tokenMap.put("FASTORE", Token.RESERVED_WORD); - tokenMap.put("DASTORE", Token.RESERVED_WORD); - tokenMap.put("AASTORE", Token.RESERVED_WORD); - tokenMap.put("BASTORE", Token.RESERVED_WORD); - tokenMap.put("CASTORE", Token.RESERVED_WORD); - tokenMap.put("SASTORE", Token.RESERVED_WORD); - tokenMap.put("POP", Token.RESERVED_WORD); - tokenMap.put("POP2", Token.RESERVED_WORD); - tokenMap.put("DUP", Token.RESERVED_WORD); - tokenMap.put("DUP_X1", Token.RESERVED_WORD); - tokenMap.put("DUP_X2", Token.RESERVED_WORD); - tokenMap.put("DUP2", Token.RESERVED_WORD); - tokenMap.put("DUP2_X1", Token.RESERVED_WORD); - tokenMap.put("DUP2_X2", Token.RESERVED_WORD); - tokenMap.put("SWAP", Token.RESERVED_WORD); - tokenMap.put("IADD", Token.RESERVED_WORD); - tokenMap.put("LADD", Token.RESERVED_WORD); - tokenMap.put("FADD", Token.RESERVED_WORD); - tokenMap.put("DADD", Token.RESERVED_WORD); - tokenMap.put("ISUB", Token.RESERVED_WORD); - tokenMap.put("LSUB", Token.RESERVED_WORD); - tokenMap.put("FSUB", Token.RESERVED_WORD); - tokenMap.put("DSUB", Token.RESERVED_WORD); - tokenMap.put("IMUL", Token.RESERVED_WORD); - tokenMap.put("LMUL", Token.RESERVED_WORD); - tokenMap.put("FMUL", Token.RESERVED_WORD); - tokenMap.put("DMUL", Token.RESERVED_WORD); - tokenMap.put("IDIV", Token.RESERVED_WORD); - tokenMap.put("LDIV", Token.RESERVED_WORD); - tokenMap.put("FDIV", Token.RESERVED_WORD); - tokenMap.put("DDIV", Token.RESERVED_WORD); - tokenMap.put("IREM", Token.RESERVED_WORD); - tokenMap.put("LREM", Token.RESERVED_WORD); - tokenMap.put("FREM", Token.RESERVED_WORD); - tokenMap.put("DREM", Token.RESERVED_WORD); - tokenMap.put("INEG", Token.RESERVED_WORD); - tokenMap.put("LNEG", Token.RESERVED_WORD); - tokenMap.put("FNEG", Token.RESERVED_WORD); - tokenMap.put("DNEG", Token.RESERVED_WORD); - tokenMap.put("ISHL", Token.RESERVED_WORD); - tokenMap.put("LSHL", Token.RESERVED_WORD); - tokenMap.put("ISHR", Token.RESERVED_WORD); - tokenMap.put("LSHR", Token.RESERVED_WORD); - tokenMap.put("IUSHR", Token.RESERVED_WORD); - tokenMap.put("LUSHR", Token.RESERVED_WORD); - tokenMap.put("IAND", Token.RESERVED_WORD); - tokenMap.put("LAND", Token.RESERVED_WORD); - tokenMap.put("IOR", Token.RESERVED_WORD); - tokenMap.put("LOR", Token.RESERVED_WORD); - tokenMap.put("IXOR", Token.RESERVED_WORD); - tokenMap.put("LXOR", Token.RESERVED_WORD); - tokenMap.put("IINC", Token.RESERVED_WORD); - tokenMap.put("I2L", Token.RESERVED_WORD); - tokenMap.put("I2F", Token.RESERVED_WORD); - tokenMap.put("I2D", Token.RESERVED_WORD); - tokenMap.put("L2I", Token.RESERVED_WORD); - tokenMap.put("L2F", Token.RESERVED_WORD); - tokenMap.put("L2D", Token.RESERVED_WORD); - tokenMap.put("F2I", Token.RESERVED_WORD); - tokenMap.put("F2L", Token.RESERVED_WORD); - tokenMap.put("F2D", Token.RESERVED_WORD); - tokenMap.put("D2I", Token.RESERVED_WORD); - tokenMap.put("D2L", Token.RESERVED_WORD); - tokenMap.put("D2F", Token.RESERVED_WORD); - tokenMap.put("I2B", Token.RESERVED_WORD); - tokenMap.put("I2C", Token.RESERVED_WORD); - tokenMap.put("I2S", Token.RESERVED_WORD); - tokenMap.put("LCMP", Token.RESERVED_WORD); - tokenMap.put("FCMPL", Token.RESERVED_WORD); - tokenMap.put("FCMPG", Token.RESERVED_WORD); - tokenMap.put("DCMPL", Token.RESERVED_WORD); - tokenMap.put("DCMPG", Token.RESERVED_WORD); - tokenMap.put("IFEQ", Token.RESERVED_WORD); - tokenMap.put("IFNE", Token.RESERVED_WORD); - tokenMap.put("IFLT", Token.RESERVED_WORD); - tokenMap.put("IFGE", Token.RESERVED_WORD); - tokenMap.put("IFGT", Token.RESERVED_WORD); - tokenMap.put("IFLE", Token.RESERVED_WORD); - tokenMap.put("IF_ICMPEQ", Token.RESERVED_WORD); - tokenMap.put("IF_ICMPNE", Token.RESERVED_WORD); - tokenMap.put("IF_ICMPLT", Token.RESERVED_WORD); - tokenMap.put("IF_ICMPGE", Token.RESERVED_WORD); - tokenMap.put("IF_ICMPGT", Token.RESERVED_WORD); - tokenMap.put("IF_ICMPLE", Token.RESERVED_WORD); - tokenMap.put("IF_ACMPEQ", Token.RESERVED_WORD); - tokenMap.put("IF_ACMPNE", Token.RESERVED_WORD); - tokenMap.put("GOTO", Token.RESERVED_WORD); - tokenMap.put("JSR", Token.RESERVED_WORD); - tokenMap.put("RET", Token.RESERVED_WORD); - tokenMap.put("TABLESWITCH", Token.RESERVED_WORD); - tokenMap.put("LOOKUPSWITCH", Token.RESERVED_WORD); - tokenMap.put("IRETURN", Token.RESERVED_WORD); - tokenMap.put("LRETURN", Token.RESERVED_WORD); - tokenMap.put("FRETURN", Token.RESERVED_WORD); - tokenMap.put("DRETURN", Token.RESERVED_WORD); - tokenMap.put("ARETURN", Token.RESERVED_WORD); - tokenMap.put("RETURN", Token.RESERVED_WORD); - tokenMap.put("GETSTATIC", Token.RESERVED_WORD); - tokenMap.put("PUTSTATIC", Token.RESERVED_WORD); - tokenMap.put("GETFIELD", Token.RESERVED_WORD); - tokenMap.put("PUTFIELD", Token.RESERVED_WORD); - tokenMap.put("INVOKEVIRTUAL", Token.RESERVED_WORD); - tokenMap.put("INVOKESPECIAL", Token.RESERVED_WORD); - tokenMap.put("INVOKESTATIC", Token.RESERVED_WORD); - tokenMap.put("INVOKEINTERFACE", Token.RESERVED_WORD); - tokenMap.put("INVOKEDYNAMIC", Token.RESERVED_WORD); - tokenMap.put("NEW", Token.RESERVED_WORD); - tokenMap.put("NEWARRAY", Token.RESERVED_WORD); - tokenMap.put("ANEWARRAY", Token.RESERVED_WORD); - tokenMap.put("ARRAYLENGTH", Token.RESERVED_WORD); - tokenMap.put("ATHROW", Token.RESERVED_WORD); - tokenMap.put("CHECKCAST", Token.RESERVED_WORD); - tokenMap.put("INSTANCEOF", Token.RESERVED_WORD); - tokenMap.put("MONITORENTER", Token.RESERVED_WORD); - tokenMap.put("MONITOREXIT", Token.RESERVED_WORD); - tokenMap.put("MULTIANEWARRAY", Token.RESERVED_WORD); - tokenMap.put("IFNULL", Token.RESERVED_WORD); - tokenMap.put("IFNONNULL", Token.RESERVED_WORD); - - - tokenMap.put("LDC", Token.RESERVED_WORD); - tokenMap.put("NEW", Token.RESERVED_WORD); - tokenMap.put("LINENUMBER", Token.RESERVED_WORD); - tokenMap.put("DEFINE", Token.RESERVED_WORD); - tokenMap.put("FIELD", Token.RESERVED_WORD); - tokenMap.put("METHOD", Token.RESERVED_WORD); - tokenMap.put("METHOD_START", Token.RESERVED_WORD); - tokenMap.put("METHOD_END", Token.RESERVED_WORD); - tokenMap.put("LABEL", Token.RESERVED_WORD); - tokenMap.put("JUMP", Token.RESERVED_WORD); - tokenMap.put("OPCODE", Token.RESERVED_WORD); - tokenMap.put("VER", Token.RESERVED_WORD); - tokenMap.put("TYPE", Token.RESERVED_WORD); - tokenMap.put("INT", Token.RESERVED_WORD); - tokenMap.put("VER", Token.RESERVED_WORD); - - - tokenMap.put("public", Token.RESERVED_WORD); - tokenMap.put("private", Token.RESERVED_WORD); - tokenMap.put("static", Token.RESERVED_WORD); - tokenMap.put("final", Token.RESERVED_WORD); - tokenMap.put("interface", Token.RESERVED_WORD); - tokenMap.put("class", Token.RESERVED_WORD); - tokenMap.put("abstract", Token.RESERVED_WORD); - tokenMap.put("LOCALVARIABLE", Token.RESERVED_WORD); - tokenMap.put("MAXSTACK", Token.RESERVED_WORD); - tokenMap.put("MAXLOCALS", Token.RESERVED_WORD); - tokenMap.put("FRAME", Token.RESERVED_WORD); - return tokenMap; - } - - @Override - public void addToken(Segment segment, int start, int end, int tokenType, int startOffset) { - // This assumes all keywords, etc. were parsed as "identifiers." - if (tokenType == Token.IDENTIFIER) { - int value = wordsToHighlight.get(segment, start, end); - if (value != -1) { - tokenType = value; - } - } - super.addToken(segment, start, end, tokenType, startOffset); - } - - /** - * Returns a list of tokens representing the given text. - * - * @param text The text to break into tokens. - * @param startTokenType The token with which to start tokenizing. - * @param startOffset The offset at which the line of tokens begins. - * @return A linked list of tokens representing text. - */ - public Token getTokenList(Segment text, int startTokenType, int startOffset) { - - resetTokenList(); - - char[] array = text.array; - int offset = text.offset; - int count = text.count; - int end = offset + count; - - // Token starting offsets are always of the form: - // 'startOffset + (currentTokenStart-offset)', but since startOffset and - // offset are constant, tokens' starting positions become: - // 'newStartOffset+currentTokenStart'. - int newStartOffset = startOffset - offset; - - int currentTokenStart = offset; - int currentTokenType = startTokenType; - - for (int i = offset; i < end; i++) { - - char c = array[i]; - - switch (currentTokenType) { - - case Token.NULL: - - currentTokenStart = i; // Starting a new token here. - - switch (c) { - - case ' ': - case '\t': - currentTokenType = Token.WHITESPACE; - break; - - case '"': - currentTokenType = Token.LITERAL_STRING_DOUBLE_QUOTE; - break; - - case '#': - currentTokenType = Token.COMMENT_EOL; - break; - - default: - if (RSyntaxUtilities.isDigit(c)) { - currentTokenType = Token.LITERAL_NUMBER_DECIMAL_INT; - break; - } else if (RSyntaxUtilities.isLetter(c) || c == '/' || c == '_') { - currentTokenType = Token.IDENTIFIER; - break; - } - - // Anything not currently handled - mark as an identifier - currentTokenType = Token.IDENTIFIER; - break; - - } // End of switch (c). - - break; - - case Token.WHITESPACE: - - switch (c) { - - case ' ': - case '\t': - break; // Still whitespace. - - case '"': - addToken(text, currentTokenStart, i - 1, Token.WHITESPACE, newStartOffset + currentTokenStart); - currentTokenStart = i; - currentTokenType = Token.LITERAL_STRING_DOUBLE_QUOTE; - break; - - case '#': - addToken(text, currentTokenStart, i - 1, Token.WHITESPACE, newStartOffset + currentTokenStart); - currentTokenStart = i; - currentTokenType = Token.COMMENT_EOL; - break; - - default: // Add the whitespace token and start anew. - - addToken(text, currentTokenStart, i - 1, Token.WHITESPACE, newStartOffset + currentTokenStart); - currentTokenStart = i; - - if (RSyntaxUtilities.isDigit(c)) { - currentTokenType = Token.LITERAL_NUMBER_DECIMAL_INT; - break; - } else if (RSyntaxUtilities.isLetter(c) || c == '/' || c == '_') { - currentTokenType = Token.IDENTIFIER; - break; - } - - // Anything not currently handled - mark as identifier - currentTokenType = Token.IDENTIFIER; - - } // End of switch (c). - - break; - - default: // Should never happen - case Token.IDENTIFIER: - - switch (c) { - - case ' ': - case '\t': - addToken(text, currentTokenStart, i - 1, Token.IDENTIFIER, newStartOffset + currentTokenStart); - currentTokenStart = i; - currentTokenType = Token.WHITESPACE; - break; - - case '"': - addToken(text, currentTokenStart, i - 1, Token.IDENTIFIER, newStartOffset + currentTokenStart); - currentTokenStart = i; - currentTokenType = Token.LITERAL_STRING_DOUBLE_QUOTE; - break; - - default: - if (RSyntaxUtilities.isLetterOrDigit(c) || c == '/' || c == '_') { - break; // Still an identifier of some type. - } - // Otherwise, we're still an identifier (?). - - } // End of switch (c). - - break; - - case Token.LITERAL_NUMBER_DECIMAL_INT: - - switch (c) { - - case ' ': - case '\t': - addToken(text, currentTokenStart, i - 1, Token.LITERAL_NUMBER_DECIMAL_INT, newStartOffset + currentTokenStart); - currentTokenStart = i; - currentTokenType = Token.WHITESPACE; - break; - - case '"': - addToken(text, currentTokenStart, i - 1, Token.LITERAL_NUMBER_DECIMAL_INT, newStartOffset + currentTokenStart); - currentTokenStart = i; - currentTokenType = Token.LITERAL_STRING_DOUBLE_QUOTE; - break; - - default: - - if (RSyntaxUtilities.isDigit(c)) { - break; // Still a literal number. - } - - // Otherwise, remember this was a number and start over. - addToken(text, currentTokenStart, i - 1, Token.LITERAL_NUMBER_DECIMAL_INT, newStartOffset + currentTokenStart); - i--; - currentTokenType = Token.NULL; - - } // End of switch (c). - - break; - - case Token.COMMENT_EOL: - i = end - 1; - addToken(text, currentTokenStart, i, currentTokenType, newStartOffset + currentTokenStart); - // We need to set token type to null so at the bottom we don't add one more token. - currentTokenType = Token.NULL; - break; - - case Token.LITERAL_STRING_DOUBLE_QUOTE: - if (c == '"') { - addToken(text, currentTokenStart, i, Token.LITERAL_STRING_DOUBLE_QUOTE, newStartOffset + currentTokenStart); - currentTokenType = Token.NULL; - } - break; - - } // End of switch (currentTokenType). - - } // End of for (int i=offset; i%s", text); - } - - public static String setColor(String text, Color color) { - return String.format("%s", color.getRed(), color.getGreen(), color.getBlue(), text); - } - - public static String remove(String text) { - return text.replaceAll("<[^>]+>",""); - } -} diff --git a/src/main/java/cn/enaium/joe/util/IOUtil.java b/src/main/java/cn/enaium/joe/util/IOUtil.java deleted file mode 100644 index e90a875..0000000 --- a/src/main/java/cn/enaium/joe/util/IOUtil.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.util; - -import javax.imageio.ImageIO; -import javax.swing.*; -import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; - -/** - * @author Enaium - * @since 0.9.0 - */ -public class IOUtil { - public static String getString(InputStream inputStream) throws IOException { - return new String(getBytes(inputStream), StandardCharsets.UTF_8); - } - - public static byte[] getBytes(InputStream inputStream) throws IOException { - ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream(); - byte[] buffer = new byte[1024 * 4]; - int n; - while (-1 != (n = inputStream.read(buffer))) { - byteOutputStream.write(buffer, 0, n); - } - inputStream.close(); - return byteOutputStream.toByteArray(); - } - - public static Icon getIcon(byte[] data) throws IOException { - return new ImageIcon(ImageIO.read(new ByteArrayInputStream(data))); - } - - public static boolean isImage(byte[] data) { - ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(data); - try { - BufferedImage read = ImageIO.read(byteArrayInputStream); - return read != null; - } catch (Throwable ignore) { - return false; - } finally { - try { - byteArrayInputStream.close(); - } catch (IOException e) { - MessageUtil.error(e); - } - } - } -} diff --git a/src/main/java/cn/enaium/joe/util/JFileChooserUtil.java b/src/main/java/cn/enaium/joe/util/JFileChooserUtil.java deleted file mode 100644 index 14e9495..0000000 --- a/src/main/java/cn/enaium/joe/util/JFileChooserUtil.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.util; - -import cn.enaium.joe.JavaOctetEditor; - -import javax.swing.*; -import javax.swing.filechooser.FileFilter; -import javax.swing.filechooser.FileSystemView; -import java.io.File; - -/** - * @author Enaium - */ -public class JFileChooserUtil { - - private JFileChooserUtil() { - throw new IllegalAccessError("Utility"); - } - - public static File show(Type type) { - return show(type, new FileFilter() { - @Override - public boolean accept(File file) { - return file.getName().endsWith(".zip") || file.getName().endsWith(".jar") || file.isDirectory(); - } - - @Override - public String getDescription() { - return "Zip File(*.zip,*.jar)"; - } - }); - } - - public static File show(Type type, FileFilter fileFilter) { - return show(type, fileFilter, JFileChooser.FILES_ONLY); - } - - public static File show(Type type, FileFilter fileFilter, int mode) { - JFileChooser jFileChooser = new JFileChooser(); - jFileChooser.setCurrentDirectory(FileSystemView.getFileSystemView().getHomeDirectory()); - jFileChooser.setFileSelectionMode(mode); - jFileChooser.removeChoosableFileFilter(jFileChooser.getAcceptAllFileFilter()); - jFileChooser.addChoosableFileFilter(fileFilter); - - if (type.equals(Type.OPEN)) { - jFileChooser.showOpenDialog(JavaOctetEditor.getInstance().window); - } else if (type.equals(Type.SAVE)) { - jFileChooser.showSaveDialog(JavaOctetEditor.getInstance().window); - } - - return jFileChooser.getSelectedFile(); - } - - public enum Type { - OPEN, - SAVE - } -} diff --git a/src/main/java/cn/enaium/joe/util/JMenuUtil.java b/src/main/java/cn/enaium/joe/util/JMenuUtil.java deleted file mode 100644 index ebe58e3..0000000 --- a/src/main/java/cn/enaium/joe/util/JMenuUtil.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.util; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.function.Supplier; - -/** - * @author Enaium - * @since 1.2.0 - */ -public class JMenuUtil { - public static void addPopupMenu(Component component, Supplier popupMenu, Supplier show) { - component.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - if (SwingUtilities.isRightMouseButton(e) && show.get()) { - popupMenu.get().show(component, e.getX(), e.getY()); - } - } - }); - } -} diff --git a/src/main/java/cn/enaium/joe/util/JTreeUtil.java b/src/main/java/cn/enaium/joe/util/JTreeUtil.java deleted file mode 100644 index 96aa70b..0000000 --- a/src/main/java/cn/enaium/joe/util/JTreeUtil.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.util; - -import cn.enaium.joe.gui.panel.file.tree.node.ClassTreeNode; -import cn.enaium.joe.gui.panel.file.tree.node.PackageTreeNode; - -import javax.swing.*; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.TreeNode; -import javax.swing.tree.TreePath; -import java.util.Enumeration; - -public class JTreeUtil { - public static void setTreeExpandedState(JTree tree, boolean expanded) { - DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getModel().getRoot(); - setNodeExpandedState(tree, node, expanded); - } - - public static void setNodeExpandedState(JTree tree, DefaultMutableTreeNode node, boolean expanded) { - Enumeration children = node.children(); - while (children.hasMoreElements()) { - setNodeExpandedState(tree, (DefaultMutableTreeNode) children.nextElement(), expanded); - } - - if (!expanded && node.isRoot()) { - return; - } - TreePath path = new TreePath(node.getPath()); - if (expanded) { - tree.expandPath(path); - } else { - tree.collapsePath(path); - } - } -} \ No newline at end of file diff --git a/src/main/java/cn/enaium/joe/util/KeyStrokeUtil.java b/src/main/java/cn/enaium/joe/util/KeyStrokeUtil.java deleted file mode 100644 index d9a15e5..0000000 --- a/src/main/java/cn/enaium/joe/util/KeyStrokeUtil.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.util; - -import javax.swing.*; -import java.awt.event.ActionEvent; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * @author Enaium - * @since 1.0.0 - */ -public class KeyStrokeUtil { - - private static final AtomicInteger ATOMIC_INTEGER = new AtomicInteger(0); - - public static void register(JComponent component, KeyStroke keyStroke, Runnable action) { - String key = String.valueOf(ATOMIC_INTEGER.incrementAndGet()); - InputMap inputMap = component.getInputMap(JComponent.WHEN_FOCUSED); - inputMap.put(keyStroke, key); - ActionMap actionMap = component.getActionMap(); - actionMap.put(key, new AbstractAction() { - @Override - public void actionPerformed(ActionEvent e) { - action.run(); - } - }); - } -} diff --git a/src/main/java/cn/enaium/joe/util/LangUtil.java b/src/main/java/cn/enaium/joe/util/LangUtil.java deleted file mode 100644 index 874b1d4..0000000 --- a/src/main/java/cn/enaium/joe/util/LangUtil.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.util; - -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.config.extend.ApplicationConfig; -import cn.enaium.joe.config.value.ModeValue; -import com.google.gson.Gson; -import com.google.gson.JsonObject; -import org.pmw.tinylog.Logger; - -import java.io.IOException; -import java.net.URL; -import java.util.Locale; - -public class LangUtil { - - public static String i18n(String key, Object... args) { - Locale locale = Locale.getDefault(); - String lang = locale.getLanguage() + "_" + locale.getCountry(); - ModeValue language = JavaOctetEditor.getInstance().config.getByClass(ApplicationConfig.class).language; - if (!language.getValue().equals("System")) { - lang = language.getValue(); - } - try { - - String en = IOUtil.getString(LangUtil.class.getResourceAsStream("/lang/en_US.json")); - - URL url = LangUtil.class.getResource("/lang/" + lang + ".json"); - - if (url == null) { - RuntimeException runtimeException = new RuntimeException(String.format("lang ' %s ' not Found!", lang)); - MessageUtil.error(runtimeException); - throw runtimeException; - } - - JsonObject jsonObject = new Gson().fromJson(IOUtil.getString(url.openStream()), JsonObject.class); - try { - return String.format(jsonObject.get(key).getAsString(), args); - } catch (NullPointerException e) { - Logger.warn(String.format("Lang not found \" %s \" ", key)); - try { - return String.format(new Gson().fromJson(en, JsonObject.class).get(key).getAsString(), args); - } catch (NullPointerException ex) { - MessageUtil.error(new NullPointerException(String.format("not found key ' %s ' in en_us", key))); - } - } - } catch (IOException e) { - MessageUtil.error(e); - } - return key; - } -} \ No newline at end of file diff --git a/src/main/java/cn/enaium/joe/util/MessageUtil.java b/src/main/java/cn/enaium/joe/util/MessageUtil.java deleted file mode 100644 index f3947bb..0000000 --- a/src/main/java/cn/enaium/joe/util/MessageUtil.java +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Copyright 2022 Enaium - *

- * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.util; - -import cn.enaium.joe.gui.panel.confirm.ConfirmPanel; -import org.pmw.tinylog.Logger; - -import javax.swing.*; - -/** - * @author Enaium - * @since 0.7.0 - */ -public class MessageUtil { - - public static void error(Throwable e) { - Logger.error(e); - JOptionPane.showMessageDialog(null, e.toString(), LangUtil.i18n("error"), JOptionPane.ERROR_MESSAGE); - } - - public static void confirm(Object message, String title, Runnable yes, Runnable no) { - int i = JOptionPane.showConfirmDialog(null, message, title, JOptionPane.OK_CANCEL_OPTION); - if (i == JOptionPane.YES_OPTION) { - if (yes != null) { - yes.run(); - } - } else { - if (no != null) { - no.run(); - } - } - } - - public static void confirm(ConfirmPanel confirmPanel, String title) { - confirm(confirmPanel, title, () -> { - confirmPanel.getConfirm().run(); - }, () -> { - confirmPanel.getCancel().run(); - }); - } - - public static void confirm(ConfirmPanel confirmPanel, String title, Runnable yes) { - confirm(confirmPanel, title, () -> { - confirmPanel.getConfirm().run(); - yes.run(); - }, null); - } - - public static void confirm(Object message, String title, Runnable yes) { - confirm(message, title, yes, null); - } - - - public static void info(String message) { - JOptionPane.showMessageDialog(null, message, LangUtil.i18n("info"), JOptionPane.INFORMATION_MESSAGE); - Logger.info(message); - } - - public static void warning(String message) { - JOptionPane.showMessageDialog(null, message, LangUtil.i18n("warning"), JOptionPane.WARNING_MESSAGE); - Logger.warn(message); - } -} diff --git a/src/main/java/cn/enaium/joe/util/TinyLogPrintStream.java b/src/main/java/cn/enaium/joe/util/TinyLogPrintStream.java deleted file mode 100644 index 04fe521..0000000 --- a/src/main/java/cn/enaium/joe/util/TinyLogPrintStream.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.util; - -import org.pmw.tinylog.Logger; - -import java.io.OutputStream; -import java.io.PrintStream; - -/** - * @author Enaium - * @since 1.3.0 - */ -public class TinyLogPrintStream extends PrintStream { - - private final Type type; - - public TinyLogPrintStream(OutputStream out, Type type) { - super(out); - this.type = type; - } - - @Override - public void println(String x) { - log(x); - } - - @Override - public void println(Object x) { - log(String.valueOf(x)); - } - - private void log(String log) { - if (type == Type.STDOUT) { - Logger.info(log); - } else if (type == Type.STDERR) { - Logger.error(log); - } - } - - public enum Type { - STDOUT, STDERR - } -} diff --git a/src/main/java/cn/enaium/joe/wrapper/InstructionWrapper.java b/src/main/java/cn/enaium/joe/wrapper/InstructionWrapper.java deleted file mode 100644 index 18414ec..0000000 --- a/src/main/java/cn/enaium/joe/wrapper/InstructionWrapper.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.wrapper; - -import cn.enaium.joe.util.ColorUtil; -import cn.enaium.joe.util.HtmlUtil; -import cn.enaium.joe.util.OpcodeUtil; -import org.objectweb.asm.Handle; -import org.objectweb.asm.tree.*; - -import java.awt.*; -import java.util.Arrays; - -/** - * @author Enaium - * @since 0.8.0 - */ -public class InstructionWrapper extends Wrapper { - - - public InstructionWrapper(AbstractInsnNode wrapper) { - super(wrapper); - } - - @Override - public String toString() { - - - if (getWrapper() == null) { - return " "; - } - - - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append(""); - - if (getWrapper().getOpcode() != -1) { - stringBuilder.append(HtmlUtil.setColor(OpcodeUtil.OPCODE.get(getWrapper().getOpcode()), ColorUtil.opcode)); - } - - switch (getWrapper().getType()) { - case AbstractInsnNode.INSN: - //Opcode - break; - case AbstractInsnNode.INT_INSN: - IntInsnNode intInsnNode = (IntInsnNode) getWrapper(); - append(stringBuilder, HtmlUtil.setColor(String.valueOf(intInsnNode.operand), ColorUtil.base)); - break; - case AbstractInsnNode.VAR_INSN: - append(stringBuilder, HtmlUtil.setColor(String.valueOf(((VarInsnNode) getWrapper()).var), ColorUtil.base)); - break; - case AbstractInsnNode.TYPE_INSN: - append(stringBuilder, HtmlUtil.setColor(((TypeInsnNode) getWrapper()).desc, ColorUtil.desc)); - break; - case AbstractInsnNode.FIELD_INSN: - FieldInsnNode fieldInsnNode = (FieldInsnNode) getWrapper(); - append(stringBuilder, HtmlUtil.setColor(fieldInsnNode.name, ColorUtil.name)); - append(stringBuilder, HtmlUtil.setColor(fieldInsnNode.desc, ColorUtil.desc)); - break; - case AbstractInsnNode.METHOD_INSN: - MethodInsnNode methodInsnNode = (MethodInsnNode) getWrapper(); - append(stringBuilder, HtmlUtil.setColor(methodInsnNode.name, ColorUtil.name)); - append(stringBuilder, HtmlUtil.setColor(methodInsnNode.desc, ColorUtil.desc)); - append(stringBuilder, HtmlUtil.setColor(String.valueOf(methodInsnNode.itf), ColorUtil.bool)); - break; - case AbstractInsnNode.INVOKE_DYNAMIC_INSN: - InvokeDynamicInsnNode invokeDynamicInsnNode = (InvokeDynamicInsnNode) getWrapper(); - append(stringBuilder, HtmlUtil.setColor(invokeDynamicInsnNode.name, ColorUtil.name)); - append(stringBuilder, HtmlUtil.setColor(invokeDynamicInsnNode.desc, ColorUtil.desc)); - append(stringBuilder, "\n"); - append(stringBuilder, handle(invokeDynamicInsnNode.bsm)); - String[] strings = Arrays.stream(invokeDynamicInsnNode.bsmArgs).map(it -> { - if (it instanceof Handle) { - return handle(((Handle) it)); - } else { - return it.toString(); - } - }).toArray(String[]::new); - append(stringBuilder, HtmlUtil.setColor(Arrays.toString(strings), ColorUtil.desc)); - break; - case AbstractInsnNode.JUMP_INSN: - append(stringBuilder, HtmlUtil.setColor("L" + OpcodeUtil.getLabelIndex(((JumpInsnNode) getWrapper()).label), ColorUtil.base)); - break; - case AbstractInsnNode.LABEL: - append(stringBuilder, HtmlUtil.setColor("L", ColorUtil.opcode)); - append(stringBuilder, HtmlUtil.setColor(String.valueOf(OpcodeUtil.getLabelIndex(getWrapper())), ColorUtil.base)); - break; - case AbstractInsnNode.LDC_INSN: - LdcInsnNode ldcInsnNode = (LdcInsnNode) getWrapper(); - if (ldcInsnNode.cst instanceof String) { - append(stringBuilder, HtmlUtil.setColor("\"" + ldcInsnNode.cst + "\"", ColorUtil.string)); - } else if (ldcInsnNode.cst instanceof Boolean) { - append(stringBuilder, HtmlUtil.setColor(ldcInsnNode.cst.toString(), ColorUtil.bool)); - } else { - append(stringBuilder, HtmlUtil.setColor(ldcInsnNode.cst.toString(), ColorUtil.base)); - } - break; - case AbstractInsnNode.IINC_INSN: - IincInsnNode iincInsnNode = (IincInsnNode) getWrapper(); - append(stringBuilder, HtmlUtil.setColor(String.valueOf(iincInsnNode.var), ColorUtil.base)); - append(stringBuilder, HtmlUtil.setColor(String.valueOf(iincInsnNode.incr), ColorUtil.base)); - break; - case AbstractInsnNode.TABLESWITCH_INSN: - TableSwitchInsnNode tableSwitchInsnNode = (TableSwitchInsnNode) getWrapper(); - append(stringBuilder, HtmlUtil.setColor(String.format("range[%s:%s]", tableSwitchInsnNode.min, tableSwitchInsnNode.max), ColorUtil.desc)); - tableSwitchInsnNode.labels.stream().map(OpcodeUtil::getLabelIndex).forEach(it -> append(stringBuilder, HtmlUtil.setColor("L" + it, ColorUtil.base))); - if (tableSwitchInsnNode.dflt != null) { - append(stringBuilder, HtmlUtil.setColor("default", ColorUtil.other) + ":" + HtmlUtil.setColor("L" + OpcodeUtil.getLabelIndex(tableSwitchInsnNode.dflt), ColorUtil.base)); - } - break; - case AbstractInsnNode.LOOKUPSWITCH_INSN: - LookupSwitchInsnNode lookupSwitchInsnNode = (LookupSwitchInsnNode) getWrapper(); - for (int i = 0; i < lookupSwitchInsnNode.keys.size(); i++) { - append(stringBuilder, HtmlUtil.setColor(String.valueOf(lookupSwitchInsnNode.keys.get(i)), ColorUtil.base) + ":" + HtmlUtil.setColor("L" + OpcodeUtil.getLabelIndex(lookupSwitchInsnNode.labels.get(i)), ColorUtil.base)); - } - if (lookupSwitchInsnNode.dflt != null) { - append(stringBuilder, HtmlUtil.setColor("default", ColorUtil.other) + ":" + HtmlUtil.setColor("L" + OpcodeUtil.getLabelIndex(lookupSwitchInsnNode.dflt), ColorUtil.base)); - } - break; - case AbstractInsnNode.MULTIANEWARRAY_INSN: - MultiANewArrayInsnNode multiANewArrayInsnNode = (MultiANewArrayInsnNode) getWrapper(); - append(stringBuilder, HtmlUtil.setColor(multiANewArrayInsnNode.desc, ColorUtil.desc)); - append(stringBuilder, HtmlUtil.setColor(String.valueOf(multiANewArrayInsnNode.dims), ColorUtil.base)); - break; - case AbstractInsnNode.FRAME: - FrameNode frameNode = (FrameNode) getWrapper(); - append(stringBuilder, HtmlUtil.setColor(OpcodeUtil.FRAME.get(frameNode.type), ColorUtil.opcode)); - append(stringBuilder, HtmlUtil.setColor(String.valueOf(frameNode.local), ColorUtil.desc)); - append(stringBuilder, HtmlUtil.setColor(String.valueOf(frameNode.stack), ColorUtil.desc)); - break; - case AbstractInsnNode.LINE: - LineNumberNode lineNumberNode = (LineNumberNode) getWrapper(); - append(stringBuilder, HtmlUtil.setColor("LINE", ColorUtil.opcode)); - append(stringBuilder, HtmlUtil.setColor(String.valueOf(lineNumberNode.line), ColorUtil.base)); - append(stringBuilder, HtmlUtil.setColor("L" + OpcodeUtil.getLabelIndex(lineNumberNode.start), ColorUtil.base)); - break; - } - - stringBuilder.append(""); - return stringBuilder.toString(); - } - - private void append(StringBuilder stringBuilder, String str) { - stringBuilder.append(" ").append(str); - } - - private String handle(Handle handle) { - return HtmlUtil.setColor("handle[", ColorUtil.other) + - HtmlUtil.setColor(OpcodeUtil.HANDLE.get(handle.getTag()), ColorUtil.opcode) + ":" + - HtmlUtil.setColor(handle.getOwner(), ColorUtil.desc) + "." + - HtmlUtil.setColor(handle.getName(), ColorUtil.name) + - HtmlUtil.setColor(handle.getDesc(), ColorUtil.desc) + - HtmlUtil.setColor(String.valueOf(handle.isInterface()), ColorUtil.bool) + - HtmlUtil.setColor("]", ColorUtil.other); - } -} diff --git a/src/main/resources/icons/logo.svg b/src/main/resources/icons/logo.svg deleted file mode 100644 index 8d6fdc8..0000000 --- a/src/main/resources/icons/logo.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/src/test/java/cn/enaium/joe/asm/GenerateDecompilerConfigTest.java b/src/test/java/cn/enaium/joe/asm/GenerateDecompilerConfigTest.java deleted file mode 100644 index 75901b7..0000000 --- a/src/test/java/cn/enaium/joe/asm/GenerateDecompilerConfigTest.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.asm; - -import com.strobel.decompiler.languages.java.JavaFormattingOptions; -import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; -import org.junit.jupiter.api.Test; - -import java.lang.reflect.Field; -import java.util.Arrays; -import java.util.Map; - -/** - * @author Enaium - * @since 1.1.0 - */ -public class GenerateDecompilerConfigTest { - @Test - public void fernFlower() throws IllegalAccessException { - Map defaults = IFernflowerPreferences.getDefaults(); - for (Field field : IFernflowerPreferences.class.getFields()) { - if (field.isAnnotationPresent(IFernflowerPreferences.Name.class) && field.isAnnotationPresent(IFernflowerPreferences.Description.class)) { - String f = field.getName(); - String name = field.getAnnotation(IFernflowerPreferences.Name.class).value(); - String description = field.getAnnotation(IFernflowerPreferences.Description.class).value(); - Object value = field.get(null); - Object o = defaults.get(value); - - if (o != null) { - if (o.equals("1")) { - o = true; - } else if (o.equals("0")) { - o = false; - } else if (o instanceof String) { - o = "\"" + o + "\""; - } - } else { - System.out.println("NULL:" + f); - } - - - System.out.printf("public EnableValue %s = new EnableValue(\"%s\", %s,\"%s\");%n", value, name, o, description); - } - } - } - - @Test - public void procyon() throws IllegalAccessException { - JavaFormattingOptions aDefault = JavaFormattingOptions.createDefault(); - for (Field field : JavaFormattingOptions.class.getFields()) { - String type = null; - Object value = field.get(aDefault); - if (value instanceof Boolean) { - type = "EnableValue"; - } else if (value instanceof Enum) { - type = "ModeValue"; - } else if (value instanceof Integer) { - type = "IntegerValue"; - } - - StringBuilder stringBuilder = new StringBuilder(); - - stringBuilder.append("public"); - stringBuilder.append(" "); - stringBuilder.append(type); - stringBuilder.append(" "); - stringBuilder.append(field.getName()); - stringBuilder.append("="); - stringBuilder.append("new"); - stringBuilder.append(" "); - stringBuilder.append(type); - stringBuilder.append("("); - stringBuilder.append("\"").append(field.getName()).append("\"").append(","); - if (value instanceof Enum) { - stringBuilder.append("\"").append(value).append("\"").append(","); - } else { - stringBuilder.append(value).append(","); - } - stringBuilder.append("\"").append(field.getName()).append("\""); - if (value instanceof Enum) { - stringBuilder.append(","); - stringBuilder.append("Arrays.asList").append("("); - int index = 0; - Field[] eFields = ((Enum) value).getDeclaringClass().getFields(); - for (Field e : eFields) { - stringBuilder.append("\"").append(e.getName()).append("\""); - - if (index != eFields.length - 1) { - stringBuilder.append(","); - } - - index++; - } - stringBuilder.append(")"); - } - stringBuilder.append(");"); - System.out.println(stringBuilder); - } - } -} diff --git a/src/test/java/cn/enaium/joe/asm/VisitorTest.java b/src/test/java/cn/enaium/joe/asm/VisitorTest.java deleted file mode 100644 index 977a771..0000000 --- a/src/test/java/cn/enaium/joe/asm/VisitorTest.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.enaium.joe.asm; - -import javassist.*; -import org.junit.jupiter.api.Test; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.util.ASMifier; -import org.objectweb.asm.util.TraceClassVisitor; - -import java.io.*; -import java.lang.reflect.InvocationTargetException; - -/** - * @author Enaium - */ -class VisitorTest { - @Test - public void test() throws IOException, CannotCompileException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, NotFoundException { - StringWriter stringWriter = new StringWriter(); - ClassReader classReader = new ClassReader(this.getClass().getName()); - classReader.accept(new TraceClassVisitor(null, new ASMifier(), new PrintWriter(stringWriter)), 0); - ClassPool classPool = ClassPool.getDefault(); - classPool.importPackage("org.objectweb.asm.AnnotationVisitor"); - classPool.importPackage("org.objectweb.asm.Attribute"); - classPool.importPackage("org.objectweb.asm.ClassReader"); - classPool.importPackage("org.objectweb.asm.ClassWriter"); - classPool.importPackage("org.objectweb.asm.ConstantDynamic"); - classPool.importPackage("org.objectweb.asm.FieldVisitor"); - classPool.importPackage("org.objectweb.asm.Handle"); - classPool.importPackage("org.objectweb.asm.Label"); - classPool.importPackage("org.objectweb.asm.MethodVisitor"); - classPool.importPackage("org.objectweb.asm.Opcodes"); - classPool.importPackage("org.objectweb.asm.RecordComponentVisitor"); - classPool.importPackage("org.objectweb.asm.Type"); - classPool.importPackage("org.objectweb.asm.TypePath"); - CtClass ctClass = classPool.makeClass(ASMifier.class.getSimpleName()); - ctClass.addInterface(classPool.get("org.objectweb.asm.Opcodes")); - String substring = stringWriter.toString().substring(stringWriter.toString().indexOf("{") + 1, stringWriter.toString().lastIndexOf("}")); - ctClass.addMethod(CtMethod.make(substring, ctClass)); - System.out.println(ctClass.toClass().getMethod("dump").invoke(null)); - } -} \ No newline at end of file diff --git a/ui/build.gradle b/ui/build.gradle new file mode 100755 index 0000000..468a355 --- /dev/null +++ b/ui/build.gradle @@ -0,0 +1,59 @@ +import java.text.SimpleDateFormat + +plugins { + id 'java' + id 'org.openjfx.javafxplugin' version '0.0.13' + id 'org.jetbrains.kotlin.jvm' version '1.7.21' + id 'com.github.johnrengelman.shadow' version '7.1.2' +} + +dependencies { + implementation project(':core') + implementation 'com.miglayout:miglayout-javafx:11.0' + implementation 'com.github.hervegirod:fxsvgimage:1.0b2' + implementation 'org.fxmisc.richtext:richtextfx:0.11.0' +} + +new File(System.getProperty("user.dir"), "run").mkdir() + +javafx { + version = '17.0.2' +} + +jar { + manifest.attributes( + 'Manifest-Version': 1.0, + 'Main-Class': 'cn.enaium.joe.ui.MainKt', + "Implementation-Title": "${project.name}", + "Implementation-Version": "${project.version}", + "Implementation-Vendor": "${project.group}", + "Implementation-Timestamp": new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()), + "Premain-Class": "cn.enaium.joe.Agent", + "Agent-Class": "cn.enaium.joe.Agent", + "Can-Redefine-Classes": true, + "Can-Retransform-Classes": true + ) +} + +tasks.withType(JavaCompile) { + options.encoding = 'UTF-8' +} + +[compileKotlin, compileTestKotlin].forEach { + it.kotlinOptions { + jvmTarget = '17' + } +} + +shadowJar { + archiveBaseName.set('JavaOctetEditor') + archiveClassifier.set('') + archiveVersion.set(project.version) + minimize { + dependencies { + exclude(dependency('org.openjfx:.*')) + } + } +} + +build.dependsOn shadowJar \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/Instance.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/Instance.kt new file mode 100644 index 0000000..4dc6ab5 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/Instance.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui + +import cn.enaium.joe.core.model.JarModel +import cn.enaium.joe.ui.JavaOctetEditor.Companion.event +import cn.enaium.joe.ui.event.LoadJar + +/** + * @author Enaium + * @author 2.0.0 + */ +object Instance { + /** + * Don't use const,because need to initialize first + */ + @Suppress("MayBeConstant") + val NAME = "JavaOctetEditor" + var jar: JarModel? = null + + init { + event.register { + jar = it.jar + } + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/JavaOctetEditor.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/JavaOctetEditor.kt new file mode 100755 index 0000000..c2e224f --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/JavaOctetEditor.kt @@ -0,0 +1,88 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package cn.enaium.joe.ui + +import cn.enaium.joe.core.config.ConfigManager +import cn.enaium.joe.core.task.TaskManager +import cn.enaium.joe.ui.config.extend.KeymapConfig +import cn.enaium.joe.ui.dialog.ConfirmDialog +import cn.enaium.joe.ui.event.EventManager +import cn.enaium.joe.ui.pane.MainPane +import cn.enaium.joe.ui.pane.confirm.ConfirmPane +import cn.enaium.joe.ui.util.addStyle +import cn.enaium.joe.ui.util.i18n +import javafx.application.Application +import javafx.scene.Scene +import javafx.scene.control.Label +import javafx.stage.Stage +import org.pmw.tinylog.Configurator +import org.pmw.tinylog.writers.ConsoleWriter +import org.pmw.tinylog.writers.FileWriter +import kotlin.system.exitProcess + + +/** + * @author Enaium + * @since 2.0.0 + */ +class JavaOctetEditor : Application() { + + override fun start(primaryStage: Stage) { + Configurator.currentConfig().writer(ConsoleWriter(), "[{date: HH:mm:ss.SSS}] {level} > {message}") + .addWriter(FileWriter("latest.log"), "[{date: HH:mm:ss.SSS}] {level} > {message}").activate() + + + stage = primaryStage + + config = ConfigManager().apply { + setByClass(KeymapConfig()) + } + config.load() + Runtime.getRuntime().addShutdownHook(Thread(config::save)) + + task = TaskManager() + event = EventManager() + + create(primaryStage) + + primaryStage.setOnCloseRequest { + ConfirmDialog(ConfirmPane().apply { + center = Label(i18n("dialog.wantCloseWindow")) + confirm = { + exitProcess(0) + } + cancel = { + it.consume() + } + }).showAndWait() + } + } + + private fun create(primaryStage: Stage) { + val scene = Scene(MainPane(primaryStage), 1000.0, 600.0) + primaryStage.title = Instance.NAME + primaryStage.scene = scene + primaryStage.show() + } + + + companion object { + lateinit var stage: Stage + lateinit var config: ConfigManager + lateinit var task: TaskManager + lateinit var event: EventManager + } +} \ No newline at end of file diff --git a/src/main/java/cn/enaium/joe/gui/panel/file/tree/node/FolderTreeNode.java b/ui/src/main/kotlin/cn/enaium/joe/ui/Main.kt old mode 100644 new mode 100755 similarity index 76% rename from src/main/java/cn/enaium/joe/gui/panel/file/tree/node/FolderTreeNode.java rename to ui/src/main/kotlin/cn/enaium/joe/ui/Main.kt index a49bae7..9d1a85a --- a/src/main/java/cn/enaium/joe/gui/panel/file/tree/node/FolderTreeNode.java +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/Main.kt @@ -14,13 +14,13 @@ * limitations under the License. */ -package cn.enaium.joe.gui.panel.file.tree.node; +package cn.enaium.joe.ui + +import javafx.application.Application /** * @author Enaium */ -public class FolderTreeNode extends DefaultTreeNode { - public FolderTreeNode(Object userObject) { - super(userObject); - } -} +fun main() { + Application.launch(JavaOctetEditor::class.java) +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/cell/FileTreeCell.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/cell/FileTreeCell.kt new file mode 100755 index 0000000..afc4468 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/cell/FileTreeCell.kt @@ -0,0 +1,79 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.cell + +import cn.enaium.joe.ui.control.tree.ClassTreeItem +import cn.enaium.joe.ui.control.tree.FileTreeItem +import cn.enaium.joe.ui.control.tree.FolderTreeItem +import cn.enaium.joe.ui.control.tree.PackageTreeItem +import cn.enaium.joe.ui.util.loadSVG +import javafx.scene.control.TreeCell +import org.objectweb.asm.Opcodes + +/** + * @author Enaium + * @since 2.0.0 + */ +class FileTreeCell : TreeCell() { + override fun updateItem(item: Any?, empty: Boolean) { + super.updateItem(item, empty) + if (empty) { + graphic = null + text = null + contextMenu = null + } else { + text = item.toString() + if (treeItem is ClassTreeItem) { + graphic = when ((treeItem as ClassTreeItem).classNode.access) { + Opcodes.ACC_PUBLIC or Opcodes.ACC_ANNOTATION or Opcodes.ACC_ABSTRACT or Opcodes.ACC_INTERFACE -> { + loadSVG("icons/annotation.svg") + } + + Opcodes.ACC_PUBLIC or Opcodes.ACC_ABSTRACT or Opcodes.ACC_INTERFACE -> { + loadSVG("icons/interface.svg") + } + + Opcodes.ACC_PUBLIC or Opcodes.ACC_SUPER or Opcodes.ACC_ABSTRACT -> { + loadSVG("icons/abstractClass.svg") + } + + Opcodes.ACC_PUBLIC or Opcodes.ACC_FINAL or Opcodes.ACC_SUPER or Opcodes.ACC_ENUM -> { + loadSVG("icons/enum.svg") + } + + Opcodes.ACC_PUBLIC or Opcodes.ACC_FINAL or Opcodes.ACC_SUPER -> { + loadSVG("icons/finalClass.svg") + } + + else -> { + loadSVG("icons/class.svg") + } + } + } else if (treeItem is PackageTreeItem) { + graphic = loadSVG("icons/package.svg") + } else if (treeItem is FileTreeItem) { + graphic = loadSVG("icons/file.svg") + } else if (treeItem is FolderTreeItem) { + graphic = loadSVG("icons/folder.svg") + } else if (item.toString() == "classes") { + graphic = loadSVG("icons/classesRoot.svg") + } else if (item.toString() == "resources") { + graphic = loadSVG("icons/resourceRoot.svg") + } + } + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/cell/InstructionListCell.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/cell/InstructionListCell.kt new file mode 100644 index 0000000..0569db5 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/cell/InstructionListCell.kt @@ -0,0 +1,260 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.cell + +import cn.enaium.joe.core.util.OpcodeUtil +import cn.enaium.joe.ui.util.ColorUtil +import javafx.scene.Node +import javafx.scene.control.ListCell +import javafx.scene.text.Text +import javafx.scene.text.TextFlow +import org.objectweb.asm.Handle +import org.objectweb.asm.tree.* + +/** + * @author Enaium + * @since 2.0.0 + */ +class InstructionListCell : ListCell() { + override fun updateItem(item: AbstractInsnNode?, empty: Boolean) { + super.updateItem(item, empty) + if (empty) { + graphic = null + text = null + contextMenu = null + } else { + val instruction = item!! + val textFlow = TextFlow() + + fun addText(vararg element: Node) { + textFlow.children.add(Text(" ")) + textFlow.children.addAll(element) + } + + fun handle(handle: Handle): TextFlow { + return TextFlow(Text("handle[").apply { + fill = ColorUtil.other + }, Text(OpcodeUtil.HANDLE[handle.tag]).apply { + fill = ColorUtil.opcode + }, Text(":"), Text(handle.owner).apply { + fill = ColorUtil.desc + }, Text(handle.name).apply { + fill = ColorUtil.name + }, Text(handle.desc).apply { + fill = ColorUtil.desc + }, Text(handle.isInterface.toString()).apply { + fill = ColorUtil.bool + }, Text("]").apply { + fill = ColorUtil.other + }) + } + + if (instruction.opcode != -1) { + addText(Text(OpcodeUtil.OPCODE[instruction.opcode]).apply { + fill = ColorUtil.opcode + }) + } + when (instruction) { + is InsnNode -> { + //Opcode + } + + is IntInsnNode -> { + addText(Text(instruction.operand.toString()).apply { + fill = ColorUtil.base + }) + } + + is VarInsnNode -> { + addText(Text(instruction.`var`.toString()).apply { + fill = ColorUtil.base + }) + } + + is TypeInsnNode -> { + addText(Text(instruction.desc.toString()).apply { + fill = ColorUtil.desc + }) + } + + is FieldInsnNode -> { + addText(Text(instruction.name).apply { + fill = ColorUtil.name + }) + addText(Text(instruction.desc).apply { + fill = ColorUtil.desc + }) + } + + is MethodInsnNode -> { + addText(Text(instruction.name).apply { + fill = ColorUtil.name + }) + addText(Text(instruction.desc).apply { + fill = ColorUtil.desc + }) + addText(Text(instruction.itf.toString()).apply { + fill = ColorUtil.base + }) + } + + is InvokeDynamicInsnNode -> { + addText(Text(instruction.name).apply { + fill = ColorUtil.name + }) + addText(Text(instruction.desc).apply { + fill = ColorUtil.desc + }) + addText(Text("\n")) + addText(handle(instruction.bsm)) + addText(Text(instruction.bsmArgs.map { + if (it is Handle) { + handle(it) + } else { + it.toString() + } + }.toString()).apply { + fill = ColorUtil.desc + }) + } + + is JumpInsnNode -> { + addText(Text(OpcodeUtil.getLabelIndex(instruction.label).toString()).apply { + fill = ColorUtil.base + }) + } + + is LabelNode -> { + addText(Text("L").apply { + fill = ColorUtil.opcode + }) + addText(Text(OpcodeUtil.getLabelIndex(instruction).toString()).apply { + fill = ColorUtil.base + }) + } + + is LdcInsnNode -> { + when (instruction.cst) { + is String -> { + addText(Text("\"${instruction.cst}\"").apply { + fill = ColorUtil.string + }) + } + + is Boolean -> { + addText(Text(instruction.cst.toString()).apply { + fill = ColorUtil.bool + }) + } + + else -> { + addText(Text(instruction.cst.toString()).apply { + fill = ColorUtil.base + }) + } + } + } + + is IincInsnNode -> { + addText(Text(instruction.`var`.toString()).apply { + fill = ColorUtil.base + }) + addText(Text(instruction.incr.toString()).apply { + fill = ColorUtil.base + }) + } + + is TableSwitchInsnNode -> { + addText(Text("range[${instruction.min},${instruction.max}]").apply { + fill = ColorUtil.desc + }) + instruction.labels.map { OpcodeUtil.getLabelIndex(it) }.forEach { + addText(Text("L${it}").apply { + fill = ColorUtil.base + }) + } + if (instruction.dflt != null) { + addText(Text("default").apply { + fill = ColorUtil.other + }, Text(":"), Text("L${OpcodeUtil.getLabelIndex(instruction.dflt)}").apply { + fill = ColorUtil.base + }) + } + } + + is LookupSwitchInsnNode -> { + for (i in 0 until instruction.keys.size) { + addText( + Text(instruction.keys[i].toString()).apply { + fill = ColorUtil.base + }, + Text(":"), + Text( + "L" + OpcodeUtil.getLabelIndex( + instruction.labels[i] + ) + ).apply { + fill = ColorUtil.base + } + ) + } + if (instruction.dflt != null) { + addText( + Text("default").apply { + fill = ColorUtil.other + }, + Text(":"), + Text("L${OpcodeUtil.getLabelIndex(instruction.dflt)}").apply { + fill = ColorUtil.base + } + ) + } + } + + is MultiANewArrayInsnNode -> { + addText(Text(instruction.desc).apply { fill = ColorUtil.desc }) + addText(Text(instruction.dims.toString()).apply { fill = ColorUtil.base }) + } + + is FrameNode -> { + addText(Text(OpcodeUtil.FRAME[instruction.type]).apply { + fill = ColorUtil.opcode + }) + addText(Text(instruction.local.toString()).apply { + fill = ColorUtil.desc + }) + addText(Text(instruction.stack.toString()).apply { + fill = ColorUtil.desc + }) + } + + is LineNumberNode -> { + addText(Text("LINE").apply { + fill = ColorUtil.opcode + }) + addText(Text(instruction.line.toString()).apply { + fill = ColorUtil.base + }) + addText(Text("L${OpcodeUtil.getLabelIndex(instruction.start)}").apply { + fill = ColorUtil.base + }) + } + } + graphic = textFlow + } + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/cell/MemberListCell.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/cell/MemberListCell.kt new file mode 100644 index 0000000..5d0bf3f --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/cell/MemberListCell.kt @@ -0,0 +1,47 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.cell + +import cn.enaium.joe.ui.util.loadSVG +import javafx.scene.control.ListCell +import org.objectweb.asm.tree.ClassNode +import org.objectweb.asm.tree.FieldNode +import org.objectweb.asm.tree.MethodNode + +/** + * @author Enaium + * @since 2.0.0 + */ +class MemberListCell : ListCell>() { + override fun updateItem(item: Pair?, empty: Boolean) { + super.updateItem(item, empty) + if (empty) { + graphic = null + text = null + contextMenu = null + } else { + val second = item!!.second + if (second is FieldNode) { + text = second.name + graphic = loadSVG("icons/field.svg") + } else if (second is MethodNode) { + text = second.name + graphic = loadSVG("icons/method.svg") + } + } + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/cell/SearchResultListCell.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/cell/SearchResultListCell.kt new file mode 100644 index 0000000..bb6ae0b --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/cell/SearchResultListCell.kt @@ -0,0 +1,89 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.cell + +import cn.enaium.joe.core.model.SearchResultModel +import cn.enaium.joe.core.util.OpcodeUtil +import cn.enaium.joe.ui.util.ColorUtil +import javafx.scene.control.ListCell +import javafx.scene.text.Text +import javafx.scene.text.TextFlow +import org.objectweb.asm.tree.AbstractInsnNode +import org.objectweb.asm.tree.FieldInsnNode +import org.objectweb.asm.tree.LdcInsnNode +import org.objectweb.asm.tree.MethodInsnNode + +/** + * @author Enaium + * @since 2.0.0 + */ +class SearchResultListCell : ListCell() { + override fun updateItem(item: SearchResultModel?, empty: Boolean) { + super.updateItem(item, empty) + if (empty) { + graphic = null + text = null + contextMenu = null + } else { + when (val result = item!!.result) { + is FieldInsnNode -> { + graphic = TextFlow(Text(result.name).apply { + fill = ColorUtil.name + }, Text(":").apply { + fill = ColorUtil.opcode + }, Text(result.desc).apply { + fill = ColorUtil.desc + }) + } + + is MethodInsnNode -> { + graphic = TextFlow(Text(result.name).apply { + fill = ColorUtil.name + }, Text(":").apply { + fill = ColorUtil.opcode + }, Text(result.desc).apply { + fill = ColorUtil.desc + }, Text(result.itf.toString()).apply { + fill = ColorUtil.bool + }) + } + + is LdcInsnNode -> { + graphic = Text(result.cst.toString()).apply { + fill = when (result.cst) { + is Boolean -> { + ColorUtil.bool + } + + is String -> { + ColorUtil.string + } + + else -> { + ColorUtil.base + } + } + } + } + + is AbstractInsnNode -> { + text = OpcodeUtil.OPCODE[result.opcode] + } + } + } + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/config/extend/KeymapConfig.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/config/extend/KeymapConfig.kt new file mode 100755 index 0000000..d4fe6ec --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/config/extend/KeymapConfig.kt @@ -0,0 +1,71 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.config.extend + +import cn.enaium.joe.core.config.Config +import cn.enaium.joe.ui.config.value.KeyCodeValue +import javafx.scene.input.KeyCode +import javafx.scene.input.KeyCodeCombination +import javafx.scene.input.KeyCombination +import javax.swing.KeyStroke + + +/** + * @author Enaium + * @since 2.0.0 + */ +class KeymapConfig : Config("Keymap") { + var edit: KeyCodeValue = KeyCodeValue("Edit", KeyCodeCombination(KeyCode.ENTER), "Edit method instruction") + var clone: KeyCodeValue = + KeyCodeValue( + "Clone", + KeyCodeCombination(KeyCode.D, KeyCombination.CONTROL_DOWN), + "Clone method instruction" + ) + var remove: KeyCodeValue = KeyCodeValue( + "Remove", + KeyCodeCombination(KeyCode.Y, KeyCombination.CONTROL_DOWN), + "Remove method instruction" + ) + var copy: KeyCodeValue = KeyCodeValue( + "Copy", + KeyCodeCombination(KeyCode.C, KeyCombination.CONTROL_DOWN), + "Copy method instruction text" + ) + var insertBefore: KeyCodeValue = KeyCodeValue( + "InsertBefore", + KeyCodeCombination(KeyCode.ENTER, KeyCombination.CONTROL_DOWN, KeyCombination.ALT_DOWN), + "Insert method instruction before current" + ) + var insertAfter: KeyCodeValue = KeyCodeValue( + "InsertAfter", + KeyCodeCombination(KeyCode.ENTER, KeyCombination.CONTROL_DOWN), + "Insert method instruction after current" + ) + var moveUp: KeyCodeValue = KeyCodeValue( + "Move Up", + KeyCodeCombination(KeyCode.UP, KeyCombination.CONTROL_DOWN, KeyCombination.SHIFT_DOWN), + "Move method instruction up" + ) + var moveDown: KeyCodeValue = KeyCodeValue( + "Move Up", + KeyCodeCombination(KeyCode.DOWN, KeyCombination.CONTROL_DOWN, KeyCombination.SHIFT_DOWN), + "Move method instruction down" + ) + var save: KeyCodeValue = + KeyCodeValue("Save", KeyCodeCombination(KeyCode.S, KeyCombination.CONTROL_DOWN), "Save something") +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/config/value/KeyCodeValue.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/config/value/KeyCodeValue.kt new file mode 100755 index 0000000..8ad745b --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/config/value/KeyCodeValue.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.config.value + +import cn.enaium.joe.core.config.value.Value +import com.google.gson.JsonElement +import javafx.scene.input.KeyCodeCombination + +/** + * @author Enaium + * @since 2.0.0 + */ +class KeyCodeValue(name: String, value: KeyCodeCombination, description: String) : + Value(name, value, description) { + override fun serialize(element: JsonElement) { + value = KeyCodeCombination.keyCombination(element.asString) as KeyCodeCombination + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/control/CodeEditor.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/control/CodeEditor.kt new file mode 100644 index 0000000..7e42eba --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/control/CodeEditor.kt @@ -0,0 +1,86 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.control + +import cn.enaium.joe.ui.util.addStyle +import cn.enaium.joe.ui.util.runLater +import com.google.gson.Gson +import org.fxmisc.richtext.CodeArea +import org.fxmisc.richtext.LineNumberFactory +import org.fxmisc.richtext.model.StyleSpans +import org.fxmisc.richtext.model.StyleSpansBuilder +import java.io.IOException +import java.util.* +import java.util.regex.Matcher +import java.util.regex.Pattern + + +/** + * @author Enaium + */ +class CodeEditor(type: Language.Type) : CodeArea() { + init { + paragraphGraphicFactory = LineNumberFactory.get(this) + if (type != Language.Type.UNKNOWN) { + richChanges().subscribe { + runLater({ computeHighlighting(type, text) }, { result -> setStyleSpans(0, result) }) + } + addStyle(this, "style/highlight.css") + } + } + + private fun computeHighlighting(type: Language.Type, text: String): StyleSpans> { + val name: String = type.lang + val language = Gson().fromJson(CodeEditor::class.java.classLoader.getResource("language/$name.json")!!.readText(), Language::class.java) + val stringBuilder = StringBuilder() + for (i in language.rules.indices) { + val rule = language.rules[i] + if (i > 0) { + stringBuilder.append("|") + } + stringBuilder.append("(?<%s>%s)".format(rule.name, rule.pattern)) + } + val matcher: Matcher = Pattern.compile(stringBuilder.toString()).matcher(text) + var lastKwEnd = 0 + val spansBuilder = StyleSpansBuilder>() + while (matcher.find()) { + var styleClass: String? = null + for (rule in language.rules) { + if (matcher.group(rule.name) != null) { + styleClass = rule.name; + } + } + if (styleClass != null) { + spansBuilder.add(Collections.emptyList(), matcher.start() - lastKwEnd) + spansBuilder.add(Collections.singleton(styleClass), matcher.end() - matcher.start()) + lastKwEnd = matcher.end() + } + } + spansBuilder.add(Collections.emptyList(), text.length - lastKwEnd) + return spansBuilder.create() + } + + class Language(val name: String, val rules: List) { + class Rule(val name: String, val pattern: String) + + enum class Type(val lang: String) { + UNKNOWN("unknown"), + JAVA("java"), + BYTECODE("bytecode"); + } + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/control/FileTree.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/control/FileTree.kt new file mode 100755 index 0000000..092a0a5 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/control/FileTree.kt @@ -0,0 +1,206 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.control + +import cn.enaium.joe.core.config.extend.ApplicationConfig +import cn.enaium.joe.ui.JavaOctetEditor +import cn.enaium.joe.ui.JavaOctetEditor.Companion.event +import cn.enaium.joe.ui.cell.FileTreeCell +import cn.enaium.joe.ui.control.tree.* +import cn.enaium.joe.ui.event.LoadJar +import cn.enaium.joe.ui.event.ResultJump +import cn.enaium.joe.ui.event.SelectTreeItem +import cn.enaium.joe.ui.util.expandAll +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.ContextMenu +import javafx.scene.control.MenuItem +import javafx.scene.control.TreeItem +import javafx.scene.control.TreeView +import org.objectweb.asm.tree.ClassNode + + +/** + * @author Enaium + */ +class FileTree : TreeView() { + private val classesRoot = AnyTreeItem("classes") + private val resourceRoot = AnyTreeItem("resources") + + init { + setCellFactory { + FileTreeCell() + } + isShowRoot = false + root = TreeItem() + root.children.add(classesRoot) + root.children.add(resourceRoot) + root.isExpanded = true + setOnMouseClicked { + if (it.clickCount == 2) { + selectionModel.selectedItem?.let { select -> + event.call(SelectTreeItem(select as AnyTreeItem)) + } + } + } + + event.register { + selectClassNode(classesRoot, it.classNode) + } + + contextMenu = ContextMenu().apply { + items.add(MenuItem(i18n("context.fileTree.expandAll")).apply { + setOnAction { + selectionModel.selectedItem?.let { + expandAll(selectionModel.selectedItem) + } + } + }) + } + + + event.register { + classesRoot.children.clear() + resourceRoot.children.clear() + + val hasMap: MutableMap = HashMap() + for (classNode in it.jar.classes.values) { + val split = classNode.name.split("/") + var prev: AnyTreeItem? = null + val stringBuilder = StringBuilder() + for ((index, s) in split.withIndex()) { + stringBuilder.append(s) + var packageItem = PackageTreeItem(s) + if (split.size == index + 1) { + packageItem = ClassTreeItem(classNode) + } + if (prev == null) { + if (!hasMap.containsKey(stringBuilder.toString())) { + classesRoot.children.add(packageItem) + hasMap[stringBuilder.toString()] = packageItem + prev = packageItem + } else { + prev = hasMap[stringBuilder.toString()] + } + } else { + if (!hasMap.containsKey(stringBuilder.toString())) { + prev.children.add(packageItem) + hasMap[stringBuilder.toString()] = packageItem + prev = packageItem + } else { + prev = hasMap[stringBuilder.toString()] + } + } + } + } + sort(classesRoot) + compact(classesRoot) + hasMap.clear() + for ((key, value) in it.jar.resources) { + val split = key.split("/") + var prev: AnyTreeItem? = null + val stringBuilder = StringBuilder() + for ((index, s) in split.withIndex()) { + stringBuilder.append(s) + var folderTreeItem = FolderTreeItem(s) + if (split.size == index + 1) { + folderTreeItem = FileTreeItem(s, value) + } + if (prev == null) { + if (!hasMap.containsKey(stringBuilder.toString())) { + resourceRoot.children.add(folderTreeItem) + hasMap[stringBuilder.toString()] = folderTreeItem + prev = folderTreeItem + } else { + prev = hasMap[stringBuilder.toString()] + } + } else { + if (!hasMap.containsKey(stringBuilder.toString())) { + prev.children.add(folderTreeItem) + hasMap[stringBuilder.toString()] = folderTreeItem + prev = folderTreeItem + } else { + prev = hasMap[stringBuilder.toString()] + } + } + } + } + sort(resourceRoot) + compact(resourceRoot) + } + } + + private fun compact(anyTreeItem: TreeItem) { + if (!JavaOctetEditor.config.getByClass(ApplicationConfig::class.java).compactMiddlePackage.value) { + return + } + if (!anyTreeItem.isLeaf) { + val parent = anyTreeItem.parent + if (parent.children.size == 1 && !(parent.equals(classesRoot) || parent.equals(resourceRoot))) { + parent.value = "${parent.value}.${anyTreeItem.value}" + parent.children.clear() + for (child in anyTreeItem.children) { + child.parent.value = parent + parent.children.add(child) + } + } + + for (i in 0 until anyTreeItem.children.size) { + compact(anyTreeItem.children[i]) + } + } + } + + private fun sort(anyTreeItem: TreeItem) { + if (!anyTreeItem.isLeaf) { + anyTreeItem.children.sortWith(Comparator { o1: TreeItem, o2: TreeItem -> + val class1 = o1 is ClassTreeItem + val class2 = o2 is ClassTreeItem + val file1 = o1 is FileTreeItem + val file2 = o2 is FileTreeItem + if (class1 && !class2) { + return@Comparator 1 + } + if (!class1 && class2) { + return@Comparator -1 + } + if (file1 && !file2) { + return@Comparator 1 + } + if (!file1 && file2) { + return@Comparator -1 + } + o1.toString().compareTo(o2.toString()) + }) + for (i in 0 until anyTreeItem.children.size) { + sort(anyTreeItem.children[i]) + } + } + } + + private fun selectClassNode(anyTreeItem: TreeItem, classNode: ClassNode) { + if (anyTreeItem is ClassTreeItem) { + if (anyTreeItem.classNode == classNode) { + selectionModel.select(anyTreeItem) + event.call(SelectTreeItem(anyTreeItem as AnyTreeItem)) + } + } + + anyTreeItem.children.forEach { + selectClassNode(it, classNode) + } + } +} \ No newline at end of file diff --git a/src/main/java/cn/enaium/joe/gui/panel/menu/file/LoadMenuItem.java b/ui/src/main/kotlin/cn/enaium/joe/ui/control/LabelNodeComboBox.kt similarity index 50% rename from src/main/java/cn/enaium/joe/gui/panel/menu/file/LoadMenuItem.java rename to ui/src/main/kotlin/cn/enaium/joe/ui/control/LabelNodeComboBox.kt index 644526f..d548cbf 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/menu/file/LoadMenuItem.java +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/control/LabelNodeComboBox.kt @@ -14,27 +14,33 @@ * limitations under the License. */ -package cn.enaium.joe.gui.panel.menu.file; +package cn.enaium.joe.ui.control -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.task.InputJarTask; -import cn.enaium.joe.util.JFileChooserUtil; -import cn.enaium.joe.util.LangUtil; - -import javax.swing.*; -import java.io.File; +import cn.enaium.joe.core.util.OpcodeUtil +import cn.enaium.joe.core.wrapper.LabelNodeWrapper +import javafx.scene.control.ComboBox +import org.objectweb.asm.tree.LabelNode /** + * all label node + * * @author Enaium + * @since 2.0.0 + * + * @param select selected label */ -public class LoadMenuItem extends JMenuItem { - public LoadMenuItem() { - super(LangUtil.i18n("menu.file.load")); - addActionListener(e -> { - File show = JFileChooserUtil.show(JFileChooserUtil.Type.OPEN); - if (show != null) { - JavaOctetEditor.getInstance().task.submit(new InputJarTask(show)); +class LabelNodeComboBox(select: LabelNode) : ComboBox() { + init { + OpcodeUtil.getInstructionList(select).forEach { + if (it is LabelNode) { + items.add(LabelNodeWrapper(it)) + } + } + + items.forEach { + if (it.wrapper == select) { + selectionModel.select(it) } - }); + } } -} +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/control/MainMenuBar.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/control/MainMenuBar.kt new file mode 100755 index 0000000..20af6a0 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/control/MainMenuBar.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package cn.enaium.joe.ui.control + +import cn.enaium.joe.ui.control.menu.* +import javafx.scene.control.Menu +import javafx.scene.control.MenuBar +import javafx.scene.control.MenuItem + +/** + * @author Enaium + * @since 2.0.0 + */ +class MainMenuBar : MenuBar() { + init { + menus.add(FileMenu()) + menus.add(SearchMenu()) + menus.add(MappingMenu()) + menus.add(ConfigMenu()) + menus.add(AboutMenu()) + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/control/MethodInstructionList.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/control/MethodInstructionList.kt new file mode 100644 index 0000000..2b854d8 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/control/MethodInstructionList.kt @@ -0,0 +1,49 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.control + +import cn.enaium.joe.ui.cell.InstructionListCell +import cn.enaium.joe.ui.dialog.ConfirmDialog +import cn.enaium.joe.ui.pane.confirm.InstructionEditPane +import javafx.scene.control.ListView +import org.objectweb.asm.tree.AbstractInsnNode +import org.objectweb.asm.tree.MethodNode + + +/** + * @author Enaium + * @since 2.0.0 + */ +class MethodInstructionList(methodNode: MethodNode) : ListView() { + init { + setCellFactory { + InstructionListCell() + } + + methodNode.instructions.forEach { + items.add(it) + } + + setOnMouseClicked { + if (it.clickCount == 2) { + selectionModel.selectedItem?.let { + ConfirmDialog(InstructionEditPane(selectionModel.selectedItem)).show() + } + } + } + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/control/SearchResultList.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/control/SearchResultList.kt new file mode 100644 index 0000000..b357a1e --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/control/SearchResultList.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.control + +import cn.enaium.joe.core.model.SearchResultModel +import cn.enaium.joe.ui.JavaOctetEditor.Companion.event +import cn.enaium.joe.ui.cell.SearchResultListCell +import cn.enaium.joe.ui.event.ResultJump +import cn.enaium.joe.ui.util.ColorUtil +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.ContextMenu +import javafx.scene.control.ListCell +import javafx.scene.control.ListView +import javafx.scene.control.MenuItem +import javafx.scene.text.Text +import javafx.scene.text.TextFlow +import org.objectweb.asm.tree.FieldInsnNode +import org.objectweb.asm.tree.LdcInsnNode +import org.objectweb.asm.tree.MethodInsnNode +import java.awt.Color + +/** + * @author Enaium + * @since 2.0.0 + */ +class SearchResultList : ListView() { + init { + setCellFactory { + SearchResultListCell() + } + contextMenu = ContextMenu().apply { + items.add(MenuItem(i18n("context.result.jump")).apply { + setOnAction { + selectionModel.selectedItem?.let { + event.call(ResultJump(selectionModel.selectedItem.classNode)) + } + } + }) + } + } +} \ No newline at end of file diff --git a/src/main/java/cn/enaium/joe/event/events/FileTabbedSelectEvent.java b/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/AboutMenu.kt old mode 100644 new mode 100755 similarity index 64% rename from src/main/java/cn/enaium/joe/event/events/FileTabbedSelectEvent.java rename to ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/AboutMenu.kt index a992fdf..3c5130d --- a/src/main/java/cn/enaium/joe/event/events/FileTabbedSelectEvent.java +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/AboutMenu.kt @@ -14,24 +14,19 @@ * limitations under the License. */ -package cn.enaium.joe.event.events; +package cn.enaium.joe.ui.control.menu -import cn.enaium.joe.event.Event; - -import java.awt.*; +import cn.enaium.joe.ui.control.menu.help.AboutMenuItem +import cn.enaium.joe.ui.control.menu.help.ContactMenuItem +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.Menu /** * @author Enaium - * @since 1.2.0 */ -public class FileTabbedSelectEvent implements Event { - private final Component select; - - public FileTabbedSelectEvent(Component select) { - this.select = select; - } - - public Component getSelect() { - return select; +class AboutMenu : Menu(i18n("menu.help")) { + init { + items.add(AboutMenuItem()) + items.add(ContactMenuItem()) } -} +} \ No newline at end of file diff --git a/src/test/java/cn/enaium/joe/asm/GenerateOpcodeTest.java b/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/ConfigMenu.kt similarity index 53% rename from src/test/java/cn/enaium/joe/asm/GenerateOpcodeTest.java rename to ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/ConfigMenu.kt index 869cb4e..ccc4c3f 100644 --- a/src/test/java/cn/enaium/joe/asm/GenerateOpcodeTest.java +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/ConfigMenu.kt @@ -14,28 +14,26 @@ * limitations under the License. */ -package cn.enaium.joe.asm; +package cn.enaium.joe.ui.control.menu -import org.junit.jupiter.api.Test; -import org.objectweb.asm.Opcodes; - -import java.lang.reflect.Field; +import cn.enaium.joe.ui.JavaOctetEditor.Companion.config +import cn.enaium.joe.ui.dialog.ConfigDialog +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.Menu +import javafx.scene.control.MenuItem /** * @author Enaium + * @since 2.0.0 */ -public class GenerateOpcodeTest { - @Test - public void map() { - for (Field field : Opcodes.class.getFields()) { - System.out.println("put(Opcodes." + field.getName() + "," + "\"" + field.getName() + "\");"); - } - } - - @Test - public void list() { - for (Field field : Opcodes.class.getFields()) { - System.out.println("add(\"" + field.getName() + "\");"); +class ConfigMenu : Menu(i18n("menu.config")) { + init { + config.config.values.forEach { config -> + items.add(MenuItem(config.name).apply { + setOnAction { + ConfigDialog(config).show() + } + }) } } -} +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/FileMenu.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/FileMenu.kt new file mode 100755 index 0000000..402c3a6 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/FileMenu.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.control.menu + +import cn.enaium.joe.ui.control.menu.file.LoadMenuItem +import cn.enaium.joe.ui.control.menu.file.LoadRecentMenuItem +import cn.enaium.joe.ui.control.menu.file.SaveAllSourceMenuItem +import cn.enaium.joe.ui.control.menu.file.SaveMenuItem +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.Menu +import javafx.scene.control.MenuItem + +/** + * @author Enaium + */ +class FileMenu : Menu(i18n("menu.file")) { + init { + items.add(LoadMenuItem()) + items.add(LoadRecentMenuItem()) + items.add(SaveMenuItem()) + items.add(SaveAllSourceMenuItem()) + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/MappingMenu.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/MappingMenu.kt new file mode 100644 index 0000000..8f40bc1 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/MappingMenu.kt @@ -0,0 +1,67 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.control.menu + +import cn.enaium.joe.core.task.RemappingTask +import cn.enaium.joe.ui.Instance.jar +import cn.enaium.joe.ui.JavaOctetEditor +import cn.enaium.joe.ui.JavaOctetEditor.Companion.event +import cn.enaium.joe.ui.JavaOctetEditor.Companion.task +import cn.enaium.joe.ui.event.LoadJar +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.Menu +import javafx.scene.control.MenuItem +import javafx.stage.FileChooser +import net.fabricmc.mappingio.format.MappingFormat +import java.io.File + +/** + * @author Enaium + * @since 2.0.0 + */ +class MappingMenu : Menu(i18n("menu.mapping")) { + init { + MappingFormat.values().forEach { value -> + items.add(MenuItem(value.name).apply { + setOnAction { + val fileChooser = FileChooser() + fileChooser.title = "Open Mapping File" + fileChooser.initialDirectory = File(System.getProperty("user.home")) + fileChooser.extensionFilters.addAll( + FileChooser.ExtensionFilter( + "Mapping file(*.txt,*.map,*.mapping,*.pro,*.srg)", + "*.txt", + "*.map", + "*.mapping", + "*.pro", + "*.srg", + "*.tsrg", + "*.tiny", + "*.tiyv2" + ) + ) + val showOpenDialog = fileChooser.showOpenDialog(JavaOctetEditor.stage) + if (jar != null && showOpenDialog != null) { + task.submit(RemappingTask(jar, showOpenDialog, value)).thenAccept { + event.call(LoadJar(it)) + } + } + } + }) + } + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/SearchMenu.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/SearchMenu.kt new file mode 100644 index 0000000..8eb8a6d --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/SearchMenu.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.control.menu + +import cn.enaium.joe.ui.control.menu.search.FieldMenuItem +import cn.enaium.joe.ui.control.menu.search.InstructionMenuItem +import cn.enaium.joe.ui.control.menu.search.LDCMenuItem +import cn.enaium.joe.ui.control.menu.search.MethodMenuItem +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.Menu + +/** + * @author Enaium + * @since 2.0.0 + */ +class SearchMenu : Menu(i18n("menu.search")) { + init { + items.add(FieldMenuItem()) + items.add(MethodMenuItem()) + items.add(LDCMenuItem()) + items.add(InstructionMenuItem()) + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/file/LoadMenuItem.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/file/LoadMenuItem.kt new file mode 100755 index 0000000..0f5f3d3 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/file/LoadMenuItem.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.control.menu.file + +import cn.enaium.joe.core.config.extend.ApplicationConfig + +import cn.enaium.joe.core.task.InputJarTask +import cn.enaium.joe.ui.JavaOctetEditor +import cn.enaium.joe.ui.JavaOctetEditor.Companion.config +import cn.enaium.joe.ui.JavaOctetEditor.Companion.event +import cn.enaium.joe.ui.JavaOctetEditor.Companion.stage +import cn.enaium.joe.ui.JavaOctetEditor.Companion.task +import cn.enaium.joe.ui.event.LoadJar +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.MenuItem +import javafx.stage.FileChooser +import java.io.File + +/** + * @author Enaium + * @since 2.0.0 + */ +class LoadMenuItem : MenuItem(i18n("menu.file.load")) { + init { + setOnAction { + val fileChooser = FileChooser() + fileChooser.title = "Open Resource File" + fileChooser.initialDirectory = File(System.getProperty("user.home")) + fileChooser.extensionFilters.addAll( + FileChooser.ExtensionFilter("Zip File(*.zip,*.jar)", "*.jar", "*.zip") + ) + val showOpenDialog = fileChooser.showOpenDialog(stage) + if (showOpenDialog != null) { + config.getByClass(ApplicationConfig::class.java).loadRecent.value.add(showOpenDialog.absolutePath) + task.submit(InputJarTask(showOpenDialog.absoluteFile)).thenAccept { + event.call(LoadJar(it)) + } + } + } + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/file/LoadRecentMenuItem.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/file/LoadRecentMenuItem.kt new file mode 100755 index 0000000..caa10ad --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/file/LoadRecentMenuItem.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.control.menu.file + +import cn.enaium.joe.core.config.extend.ApplicationConfig +import cn.enaium.joe.core.task.InputJarTask +import cn.enaium.joe.ui.JavaOctetEditor.Companion.config +import cn.enaium.joe.ui.JavaOctetEditor.Companion.event +import cn.enaium.joe.ui.JavaOctetEditor.Companion.task +import cn.enaium.joe.ui.event.LoadJar +import cn.enaium.joe.ui.util.i18n +import cn.enaium.joe.ui.util.loadSVG +import javafx.scene.control.Menu +import javafx.scene.control.MenuItem +import java.io.File + +/** + * @author Enaium + * @since 2.0.0 + */ +class LoadRecentMenuItem : Menu(i18n("menu.file.loadRecent")) { + init { + setOnAction { + items.clear() + val value = config.getByClass(ApplicationConfig::class.java).loadRecent.value + value.forEach { filePath -> + items.add(MenuItem(filePath, loadSVG("icons/jar.svg")).apply { + setOnAction { + val file = File(filePath) + if (file.exists()) { + task.submit(InputJarTask(file.absoluteFile)).thenAcceptAsync { + event.call(LoadJar(it)) + } + } else { + value.remove(filePath) + } + } + }) + } + } + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/file/SaveAllSourceMenuItem.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/file/SaveAllSourceMenuItem.kt new file mode 100755 index 0000000..2a74e6d --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/file/SaveAllSourceMenuItem.kt @@ -0,0 +1,50 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.control.menu.file + +import cn.enaium.joe.core.task.SaveAllSourceTask +import cn.enaium.joe.ui.Instance.jar +import cn.enaium.joe.ui.JavaOctetEditor.Companion.config +import cn.enaium.joe.ui.JavaOctetEditor.Companion.stage +import cn.enaium.joe.ui.JavaOctetEditor.Companion.task +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.MenuItem +import javafx.stage.FileChooser +import java.io.File + +/** + * @author Enaium + * @since 2.0.0 + */ +class SaveAllSourceMenuItem : MenuItem(i18n("menu.file.saveAllSource")) { + init { + setOnAction { + jar?.let { + val fileChooser = FileChooser() + fileChooser.title = "Open Resource File" + fileChooser.initialDirectory = File(System.getProperty("user.home")) + fileChooser.extensionFilters.addAll( + FileChooser.ExtensionFilter("Zip File(*.zip,*.jar)", "*.jar", "*.zip") + ) + val showSaveDialog = fileChooser.showSaveDialog(stage) + showSaveDialog?.let { + task.submit(SaveAllSourceTask(jar, showSaveDialog, config)) + } + } + } + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/file/SaveMenuItem.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/file/SaveMenuItem.kt new file mode 100755 index 0000000..0b0d0fa --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/file/SaveMenuItem.kt @@ -0,0 +1,49 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.control.menu.file + +import cn.enaium.joe.core.task.OutputJarTask +import cn.enaium.joe.ui.Instance.jar +import cn.enaium.joe.ui.JavaOctetEditor.Companion.stage +import cn.enaium.joe.ui.JavaOctetEditor.Companion.task +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.MenuItem +import javafx.stage.FileChooser +import java.io.File + +/** + * @author Enaium + * @since 2.0.0 + */ +class SaveMenuItem : MenuItem(i18n("menu.file.save")) { + init { + setOnAction { + jar?.let { + val fileChooser = FileChooser() + fileChooser.title = "Open Resource File" + fileChooser.initialDirectory = File(System.getProperty("user.home")) + fileChooser.extensionFilters.addAll( + FileChooser.ExtensionFilter("Zip File(*.zip,*.jar)", "*.jar", "*.zip") + ) + val showSaveDialog = fileChooser.showSaveDialog(stage) + showSaveDialog?.let { + task.submit(OutputJarTask(jar, showSaveDialog)) + } + } + } + } +} \ No newline at end of file diff --git a/src/main/java/cn/enaium/joe/gui/panel/file/tree/node/FileTreeNode.java b/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/help/AboutMenuItem.kt old mode 100644 new mode 100755 similarity index 66% rename from src/main/java/cn/enaium/joe/gui/panel/file/tree/node/FileTreeNode.java rename to ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/help/AboutMenuItem.kt index 1c603f3..161bbfb --- a/src/main/java/cn/enaium/joe/gui/panel/file/tree/node/FileTreeNode.java +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/help/AboutMenuItem.kt @@ -14,21 +14,20 @@ * limitations under the License. */ -package cn.enaium.joe.gui.panel.file.tree.node; +package cn.enaium.joe.ui.control.menu.help + +import cn.enaium.joe.ui.dialog.AboutDialog +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.MenuItem /** * @author Enaium + * @since 2.0.0 */ -public class FileTreeNode extends FolderTreeNode { - - private final byte[] data; - - public FileTreeNode(Object userObject, byte[] data) { - super(userObject); - this.data = data; - } - - public byte[] getData() { - return data; +class AboutMenuItem : MenuItem(i18n("menu.help.about")) { + init { + setOnAction { + AboutDialog().show() + } } -} +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/help/ContactMenuItem.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/help/ContactMenuItem.kt new file mode 100755 index 0000000..5878787 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/help/ContactMenuItem.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.control.menu.help + +import cn.enaium.joe.ui.dialog.ContactDialog +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.MenuItem + +/** + * @author Enaium + * @since 2.0.0 + */ +class ContactMenuItem : MenuItem(i18n("menu.help.contact")) { + init { + setOnAction { + ContactDialog().show() + } + } +} \ No newline at end of file diff --git a/src/main/java/cn/enaium/joe/gui/panel/menu/AttachMenu.java b/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/search/FieldMenuItem.kt similarity index 65% rename from src/main/java/cn/enaium/joe/gui/panel/menu/AttachMenu.java rename to ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/search/FieldMenuItem.kt index efadf69..c37f8b8 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/menu/AttachMenu.java +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/search/FieldMenuItem.kt @@ -14,20 +14,20 @@ * limitations under the License. */ -package cn.enaium.joe.gui.panel.menu; +package cn.enaium.joe.ui.control.menu.search -import cn.enaium.joe.gui.panel.menu.attach.ProcessMenuItem; -import cn.enaium.joe.util.LangUtil; - -import javax.swing.*; +import cn.enaium.joe.ui.dialog.SearchFieldDialog +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.MenuItem /** * @author Enaium - * @since 1.1.0 + * @since 2.0.0 */ -public class AttachMenu extends JMenu { - public AttachMenu() { - super(LangUtil.i18n("menu.attach")); - add(new ProcessMenuItem()); +class FieldMenuItem : MenuItem(i18n("menu.search.field")) { + init { + setOnAction { + SearchFieldDialog().show() + } } -} +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/search/InstructionMenuItem.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/search/InstructionMenuItem.kt new file mode 100644 index 0000000..014a127 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/search/InstructionMenuItem.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.control.menu.search + +import cn.enaium.joe.ui.dialog.SearchOpcodeDialog +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.MenuItem + +/** + * @author Enaium + * @since 2.0.0 + */ +class InstructionMenuItem : MenuItem(i18n("menu.search.opcode")) { + init { + setOnAction { + SearchOpcodeDialog().show() + } + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/search/LDCMenuItem.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/search/LDCMenuItem.kt new file mode 100644 index 0000000..12bd108 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/search/LDCMenuItem.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.control.menu.search + +import cn.enaium.joe.ui.dialog.SearchLDCDialog +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.MenuItem + +/** + * @author Enaium + * @since 2.0.0 + */ +class LDCMenuItem : MenuItem(i18n("menu.search.ldc")) { + init { + setOnAction { + SearchLDCDialog().show() + } + } +} \ No newline at end of file diff --git a/src/main/java/cn/enaium/joe/gui/panel/menu/attach/ProcessMenuItem.java b/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/search/MethodMenuItem.kt similarity index 64% rename from src/main/java/cn/enaium/joe/gui/panel/menu/attach/ProcessMenuItem.java rename to ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/search/MethodMenuItem.kt index 2ab4ba3..eafb654 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/menu/attach/ProcessMenuItem.java +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/control/menu/search/MethodMenuItem.kt @@ -14,22 +14,21 @@ * limitations under the License. */ -package cn.enaium.joe.gui.panel.menu.attach; +package cn.enaium.joe.ui.control.menu.search -import cn.enaium.joe.dialog.ProcessListDialog; -import cn.enaium.joe.util.LangUtil; - -import javax.swing.*; +import cn.enaium.joe.ui.dialog.SearchFieldDialog +import cn.enaium.joe.ui.dialog.SearchMethodDialog +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.MenuItem /** * @author Enaium - * @since 1.1.0 + * @since 2.0.0 */ -public class ProcessMenuItem extends JMenuItem { - public ProcessMenuItem() { - super(LangUtil.i18n("menu.attach.process")); - addActionListener(e -> { - new ProcessListDialog().setVisible(true); - }); +class MethodMenuItem : MenuItem(i18n("menu.search.method")) { + init { + setOnAction { + SearchMethodDialog().show() + } } -} +} \ No newline at end of file diff --git a/src/main/java/cn/enaium/joe/util/StringUtil.java b/ui/src/main/kotlin/cn/enaium/joe/ui/control/tree/AnyTreeItem.kt old mode 100644 new mode 100755 similarity index 71% rename from src/main/java/cn/enaium/joe/util/StringUtil.java rename to ui/src/main/kotlin/cn/enaium/joe/ui/control/tree/AnyTreeItem.kt index 0fdedd9..0f412d2 --- a/src/main/java/cn/enaium/joe/util/StringUtil.java +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/control/tree/AnyTreeItem.kt @@ -14,17 +14,17 @@ * limitations under the License. */ -package cn.enaium.joe.util; +package cn.enaium.joe.ui.control.tree + +import javafx.scene.Node +import javafx.scene.control.TreeItem /** * @author Enaium - * @since 0.5.0 + * @since 2.0.0 */ -public class StringUtil { - public static boolean isBlank(String string) { - if (string == null) { - return true; - } - return string.replace(" ", "").isEmpty(); +open class AnyTreeItem(val any: Any) : TreeItem(any) { + override fun toString(): String { + return any.toString() } -} +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/control/tree/ClassTreeItem.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/control/tree/ClassTreeItem.kt new file mode 100755 index 0000000..e93a596 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/control/tree/ClassTreeItem.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.control.tree + +import cn.enaium.joe.ui.util.loadSVG +import org.objectweb.asm.Opcodes +import org.objectweb.asm.tree.ClassNode + +/** + * @author Enaium + */ +class ClassTreeItem(val classNode: ClassNode) : + PackageTreeItem(classNode.name.substring(classNode.name.lastIndexOf("/") + 1)) \ No newline at end of file diff --git a/src/main/java/cn/enaium/joe/gui/panel/file/tree/node/PackageTreeNode.java b/ui/src/main/kotlin/cn/enaium/joe/ui/control/tree/FileTreeItem.kt old mode 100644 new mode 100755 similarity index 76% rename from src/main/java/cn/enaium/joe/gui/panel/file/tree/node/PackageTreeNode.java rename to ui/src/main/kotlin/cn/enaium/joe/ui/control/tree/FileTreeItem.kt index 9c9c0f0..b4b94c8 --- a/src/main/java/cn/enaium/joe/gui/panel/file/tree/node/PackageTreeNode.java +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/control/tree/FileTreeItem.kt @@ -14,13 +14,11 @@ * limitations under the License. */ -package cn.enaium.joe.gui.panel.file.tree.node; +package cn.enaium.joe.ui.control.tree + +import cn.enaium.joe.ui.util.loadSVG /** * @author Enaium */ -public class PackageTreeNode extends DefaultTreeNode { - public PackageTreeNode(Object userObject) { - super(userObject); - } -} +class FileTreeItem(any: Any, val data: ByteArray) : FolderTreeItem(any) \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/control/tree/FolderTreeItem.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/control/tree/FolderTreeItem.kt new file mode 100755 index 0000000..1a83ecd --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/control/tree/FolderTreeItem.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.control.tree + +import cn.enaium.joe.ui.util.loadSVG + +/** + * @author Enaium + */ +open class FolderTreeItem(any: Any) : AnyTreeItem(any) \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/control/tree/PackageTreeItem.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/control/tree/PackageTreeItem.kt new file mode 100755 index 0000000..a4caf08 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/control/tree/PackageTreeItem.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.control.tree + +import cn.enaium.joe.ui.util.loadSVG + +/** + * @author Enaium + */ +open class PackageTreeItem(any: Any) : AnyTreeItem(any) \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/dialog/AboutDialog.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/dialog/AboutDialog.kt new file mode 100755 index 0000000..340aa7a --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/dialog/AboutDialog.kt @@ -0,0 +1,66 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.dialog + +import cn.enaium.joe.core.util.ReflectUtil +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.Label +import javafx.scene.control.Separator +import net.miginfocom.layout.CC +import org.tbee.javafx.scene.layout.MigPane +import javax.tools.ToolProvider + +/** + * @author Enaium + * @since 2.0.0 + */ +class AboutDialog : Dialog("About") { + init { + content = MigPane("fillx", "[fill][fill]").apply { + add(Label(i18n("about.system")), "wrap") + add(Label(i18n("about.system.description")), "wrap") + add(Label(i18n("about.system.name"))) + add(Label(System.getProperty("os.name")), "wrap") + add(Label(i18n("about.system.architecture"))) + add(Label(System.getProperty("os.arch")), "wrap") + + add(Separator(), CC().span(2).wrap()) + + add(Label(i18n("about.java")), "wrap") + add(Label(i18n("about.java.description")), "wrap") + add(Label(i18n("about.java.version"))) + add(Label(System.getProperty("java.version")), "wrap") + add(Label(i18n("about.java.vm.name"))) + add(Label(System.getProperty("java.vm.name")), "wrap") + add(Label(i18n("about.java.vm.vendor"))) + add(Label(System.getProperty("java.vm.vendor")), "wrap") + add(Label(i18n("about.java.home"))) + add(Label(System.getProperty("java.home")), "wrap") + add(Label(i18n("about.java.supportCompiler"))) + add(Label("${ToolProvider.getSystemJavaCompiler() != null}"), "wrap") + add(Label(i18n("about.java.supportAttach"))) + add(Label("${ReflectUtil.classHas("com.sun.tools.attach.VirtualMachine")}"), "wrap") + + add(Separator(), CC().span(2).wrap()) + + add(Label("JavaFX"), "wrap") + add(Label("Information about the JavaFX UI"), "wrap") + add(Label("Version")) + add(Label(System.getProperty("javafx.version")), "wrap") + } + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/dialog/AnnotationDialog.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/dialog/AnnotationDialog.kt new file mode 100644 index 0000000..e1f545e --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/dialog/AnnotationDialog.kt @@ -0,0 +1,73 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.dialog + +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.ContextMenu +import javafx.scene.control.MenuItem +import javafx.scene.control.TableColumn +import javafx.scene.control.TableView +import javafx.scene.control.cell.PropertyValueFactory +import org.objectweb.asm.tree.AnnotationNode + + +/** + * @author Enaium + * @since 2.0.0 + */ +class AnnotationDialog(annotationList: List) : Dialog(i18n("instruction.annotation.title")) { + init { + content = TableView().apply { + isEditable = false + + val description = TableColumn(i18n("instruction.annotation.description")) + description.isResizable = false + description.cellValueFactory = PropertyValueFactory("description") + description.prefWidthProperty().bind(widthProperty().multiply(.5)) + + val hasValue = TableColumn(i18n("instruction.annotation.hasValue")) + hasValue.isResizable = false + hasValue.cellValueFactory = PropertyValueFactory("hasValue") + hasValue.prefWidthProperty().bind(widthProperty().multiply(.5)) + + annotationList.forEach { + items.add(Item(it)) + } + columns.addAll(description, hasValue) + contextMenu = ContextMenu().apply { + items.add(MenuItem(i18n("button.edit")).apply { + setOnAction { + if (selectionModel.selectedItem != null && selectionModel.selectedItem.hasValue) { + AnnotationValueDialog(selectionModel.selectedItem.annotationNode.values).show() + } + } + }) + } + } + } + + @Suppress("JoinDeclarationAndAssignment") + class Item(val annotationNode: AnnotationNode) { + val description: String + val hasValue: Boolean + + init { + description = annotationNode.desc + hasValue = annotationNode.values != null + } + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/dialog/AnnotationValueDialog.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/dialog/AnnotationValueDialog.kt new file mode 100644 index 0000000..2f557da --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/dialog/AnnotationValueDialog.kt @@ -0,0 +1,97 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.dialog + +import cn.enaium.joe.core.util.ListUtil +import cn.enaium.joe.core.wrapper.Wrapper +import cn.enaium.joe.ui.pane.confirm.ListValueEditPane +import cn.enaium.joe.ui.pane.confirm.ValueEditPane +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.ContextMenu +import javafx.scene.control.MenuItem +import javafx.scene.control.TableColumn +import javafx.scene.control.TableView +import javafx.scene.control.cell.PropertyValueFactory +import org.objectweb.asm.tree.AnnotationNode + + +/** + * @author Enaium + * @since 2.0.0 + */ +@Suppress("UNCHECKED_CAST") +class AnnotationValueDialog(anyList: MutableList) : Dialog(i18n("instruction.annotation.title")) { + init { + content = TableView().apply { + + isEditable = false + + val description = TableColumn(i18n("instruction.annotation.description")) + description.isResizable = false + description.cellValueFactory = PropertyValueFactory("description") + description.prefWidthProperty().bind(widthProperty().multiply(.5)) + + val value = TableColumn(i18n("instruction.annotation.value")) + value.isResizable = false + value.cellValueFactory = PropertyValueFactory("value") + value.prefWidthProperty().bind(widthProperty().multiply(.5)) + columns.addAll(description, value) + anyList.indices.forEach { i -> + if (i % 2 == 1) { + items.add(Item(anyList[i - 1].toString(), anyList[i])) + } + } + + contextMenu = ContextMenu().apply { + items.add(MenuItem(i18n("button.edit")).apply { + setOnAction { + val selectedItem = selectionModel.selectedItem + selectedItem?.let { + if (selectedItem.value is List<*>) { + if (ListUtil.getType(selectedItem.value) == AnnotationNode::class.java) { + AnnotationDialog(selectedItem.value.map { it as AnnotationNode }).show() + } else { + ConfirmDialog(ListValueEditPane(selectedItem.value as MutableList)).show() + } + } else { + val index: Int = (selectionModel.selectedIndex + 1) * 2 - 1 + + if (selectedItem.value.javaClass.isArray) { + val newList = mutableListOf(selectedItem.value) + ConfirmDialog(ListValueEditPane(newList)).apply { + confirm = { + anyList[index] = newList + } + }.show() + } else { + val wrapper = Wrapper(selectedItem.value) + ConfirmDialog(ValueEditPane(wrapper)).apply { + confirm = { + anyList[index] = wrapper.wrapper + } + }.show() + } + } + } + } + }) + } + } + } + + class Item(val description: String, val value: Any) +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/dialog/ConfigDialog.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/dialog/ConfigDialog.kt new file mode 100644 index 0000000..f7e65a4 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/dialog/ConfigDialog.kt @@ -0,0 +1,114 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.dialog + +import cn.enaium.joe.core.config.Config +import cn.enaium.joe.core.config.value.* +import cn.enaium.joe.ui.config.value.KeyCodeValue +import cn.enaium.joe.ui.util.i18n +import javafx.geometry.Pos +import javafx.scene.control.* +import javafx.scene.input.KeyCodeCombination +import javafx.scene.input.KeyCombination +import org.tbee.javafx.scene.layout.MigPane + +/** + * @author Enaium + * @since 2.0.0 + */ +class ConfigDialog(config: Config) : Dialog(i18n("menu.config")) { + init { + content = ScrollPane(MigPane("fillx", "[fill][fill]").apply { + config.javaClass.declaredFields.forEach { field -> + field.isAccessible = true + val o = field.get(config) + if (o is Value<*>) { + add(Label(o.name)) + } + + when (o) { + is StringValue -> { + add(TextField(o.value).apply { + setOnInputMethodTextChanged { + o.value = text + } + }, "wrap") + } + + is IntegerValue -> { + add(Spinner(0, Int.MAX_VALUE, o.value).apply { + setOnInputMethodTextChanged { + o.value = value + } + }, "wrap") + } + + is EnableValue -> { + add(CheckBox().apply { + alignment = Pos.CENTER_RIGHT + isSelected = o.value + setOnAction { + o.value = isSelected + } + }, "wrap") + } + + is ModeValue -> { + add(ComboBox().apply { + value = o.value + o.mode.forEach { + items.add(it) + } + selectionModel.selectedItemProperty() + .addListener { _, _, newValue -> + o.value = newValue + } + }, "wrap") + } + + is KeyCodeValue -> { + add(Button(o.value.name).apply { + setOnKeyPressed { + val modifiers = mutableListOf() + + if (it.isAltDown) { + modifiers.add(KeyCombination.ALT_DOWN) + } + + if (it.isControlDown) { + modifiers.add(KeyCombination.CONTROL_DOWN) + } + + if (it.isShiftDown) { + modifiers.add(KeyCombination.SHIFT_DOWN) + } + + if (!it.code.isModifierKey) { + o.value = KeyCodeCombination(it.code, *modifiers.toTypedArray()) + text = o.value.name + } + } + }, "wrap") + } + } + } + }).apply { + isFitToWidth = true + isFitToHeight = true + } + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/dialog/ConfirmDialog.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/dialog/ConfirmDialog.kt new file mode 100644 index 0000000..d2be140 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/dialog/ConfirmDialog.kt @@ -0,0 +1,58 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.dialog + +import cn.enaium.joe.ui.pane.confirm.ConfirmPane +import javafx.geometry.Pos +import javafx.scene.control.Button +import javafx.scene.layout.BorderPane +import javafx.scene.layout.HBox + +/** + * @author Enaium + * @since 2.0.0 + */ +class ConfirmDialog(confirmPane: ConfirmPane) : Dialog("Confirm") { + var confirm = {} + var cancel = {} + init { + content = BorderPane().apply { + center = confirmPane + bottom = HBox(10.0).apply { + alignment = Pos.CENTER_RIGHT + children.add(Button("OK").apply { + setOnAction { + confirmPane.confirm.invoke() + confirm.invoke() + close() + } + }) + children.add(Button("Cancel").apply { + setOnAction { + confirmPane.cancel.invoke() + cancel.invoke() + close() + } + }) + } + } + setOnCloseRequest { + confirmPane.cancel.invoke() + cancel.invoke() + } + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/dialog/ContactDialog.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/dialog/ContactDialog.kt new file mode 100755 index 0000000..5b148e3 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/dialog/ContactDialog.kt @@ -0,0 +1,49 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.dialog + +import cn.enaium.joe.ui.util.loadSVG +import javafx.scene.Cursor +import javafx.scene.Node +import javafx.scene.control.Label +import org.tbee.javafx.scene.layout.MigPane +import java.awt.Desktop +import java.net.URI + +/** + * @author Enaium + * @since 2.0.0 + */ +class ContactDialog : Dialog("About") { + init { + content = MigPane().apply { + fun add(name: String, icon: Node, link: String) { + add(Label().apply { + graphic = icon + }) + add(Label(name)) + add(Label(link).apply { + cursor = Cursor.HAND + setOnMouseClicked { + Desktop.getDesktop().browse(URI(link)); + } + }) + } + add("GitHub", loadSVG("icons/github.svg"), "https://github.com/Enaium/JavaOctetEditor") + } + } +} \ No newline at end of file diff --git a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/ClassNodeTabPanel.java b/ui/src/main/kotlin/cn/enaium/joe/ui/dialog/Dialog.kt old mode 100644 new mode 100755 similarity index 62% rename from src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/ClassNodeTabPanel.java rename to ui/src/main/kotlin/cn/enaium/joe/ui/dialog/Dialog.kt index 9f970a2..b50bc8d --- a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/ClassNodeTabPanel.java +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/dialog/Dialog.kt @@ -14,23 +14,25 @@ * limitations under the License. */ -package cn.enaium.joe.gui.panel.file.tabbed.tab.classes; +package cn.enaium.joe.ui.dialog -import org.objectweb.asm.tree.ClassNode; - -import javax.swing.*; +import javafx.scene.Node +import javafx.scene.Parent +import javafx.scene.Scene +import javafx.scene.layout.BorderPane +import javafx.stage.Stage /** * @author Enaium + * @since 2.0.0 */ -public class ClassNodeTabPanel extends JPanel { - private final ClassNode classNode; - - public ClassNodeTabPanel(ClassNode classNode) { - this.classNode = classNode; - } +open class Dialog(title: String) : Stage() { + var content: Parent = BorderPane() + set(value) { + scene = Scene(value) + } - public ClassNode getClassNode() { - return classNode; + init { + setTitle(title) } -} +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/dialog/SearchFieldDialog.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/dialog/SearchFieldDialog.kt new file mode 100644 index 0000000..4769dad --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/dialog/SearchFieldDialog.kt @@ -0,0 +1,67 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.dialog + +import cn.enaium.joe.core.task.SearchFieldTask +import cn.enaium.joe.ui.Instance.jar +import cn.enaium.joe.ui.JavaOctetEditor.Companion.task +import cn.enaium.joe.ui.control.SearchResultList +import cn.enaium.joe.ui.util.i18n +import cn.enaium.joe.ui.util.warning +import javafx.scene.control.Button +import javafx.scene.control.Label +import javafx.scene.control.TextField +import javafx.scene.layout.BorderPane +import org.tbee.javafx.scene.layout.MigPane + +/** + * @author Enaium + * @since 2.0.0 + */ +class SearchFieldDialog : Dialog(i18n("search.field.title")) { + init { + content = BorderPane().apply { + val searchResultList = SearchResultList() + top = MigPane("fillx", "[fill][fill]").apply { + add(Label(i18n("search.owner"))) + val owner = TextField() + add(owner, "wrap") + add(Label(i18n("search.name"))) + val name = TextField() + add(name, "wrap") + add(Label(i18n("search.description"))) + val description = TextField() + add(description, "wrap") + add(Button(i18n("menu.search")).apply { + setOnAction { + if (owner.text.isBlank() && name.text.isBlank() && description.text.isBlank()) { + warning("Please input!") + return@setOnAction + } + searchResultList.items.clear() + task.submit(SearchFieldTask(jar, owner.text, name.text, description.text)).thenAccept { + it.forEach { result -> + searchResultList.items.add(result) + } + } + } + }, "span 2") + } + center = searchResultList + } + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/dialog/SearchLDCDialog.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/dialog/SearchLDCDialog.kt new file mode 100644 index 0000000..2475b96 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/dialog/SearchLDCDialog.kt @@ -0,0 +1,61 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.dialog + +import cn.enaium.joe.core.task.SearchLdcTask +import cn.enaium.joe.ui.Instance.jar +import cn.enaium.joe.ui.JavaOctetEditor.Companion.task +import cn.enaium.joe.ui.control.SearchResultList +import cn.enaium.joe.ui.util.i18n +import cn.enaium.joe.ui.util.warning +import javafx.scene.control.Button +import javafx.scene.control.Label +import javafx.scene.control.TextField +import javafx.scene.layout.BorderPane +import org.tbee.javafx.scene.layout.MigPane + +/** + * @author Enaium + * @since 2.0.0 + */ +class SearchLDCDialog : Dialog(i18n("search.ldc.title")) { + init { + content = BorderPane().apply { + val searchResultList = SearchResultList() + top = MigPane("fillx", "[fill][fill]").apply { + add(Label(i18n("menu.search.ldc"))) + val ldc = TextField() + add(ldc, "wrap") + add(Button(i18n("menu.search")).apply { + setOnAction { + if (ldc.text.isBlank()) { + warning("Please input!") + return@setOnAction + } + searchResultList.items.clear() + task.submit(SearchLdcTask(jar, ldc.text)).thenAccept { + it.forEach { result -> + searchResultList.items.add(result) + } + } + } + }, "span 2") + } + center = searchResultList + } + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/dialog/SearchMethodDialog.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/dialog/SearchMethodDialog.kt new file mode 100644 index 0000000..a89e937 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/dialog/SearchMethodDialog.kt @@ -0,0 +1,80 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.dialog + +import cn.enaium.joe.core.task.SearchMethodTask +import cn.enaium.joe.ui.Instance.jar +import cn.enaium.joe.ui.JavaOctetEditor.Companion.task +import cn.enaium.joe.ui.control.SearchResultList +import cn.enaium.joe.ui.util.i18n +import cn.enaium.joe.ui.util.warning +import javafx.scene.control.Button +import javafx.scene.control.CheckBox +import javafx.scene.control.Label +import javafx.scene.control.TextField +import javafx.scene.layout.BorderPane +import org.tbee.javafx.scene.layout.MigPane + +/** + * @author Enaium + * @since 2.0.0 + */ +class SearchMethodDialog : Dialog(i18n("search.method.title")) { + init { + content = BorderPane().apply { + val searchResultList = SearchResultList() + top = MigPane("fillx", "[fill][fill]").apply { + add(Label(i18n("search.owner"))) + val owner = TextField() + add(owner, "wrap") + add(Label(i18n("search.name"))) + val name = TextField() + add(name, "wrap") + add(Label(i18n("search.description"))) + val description = TextField() + add(description, "wrap") + add(Label(i18n("search.interface"))) + val anInterface = CheckBox() + add(anInterface, "wrap") + add(Button(i18n("menu.search")).apply { + setOnAction { + if (owner.text.isBlank() && name.text.isBlank() && description.text.isBlank() && !anInterface.isSelected) { + warning("Please input!") + return@setOnAction + } + searchResultList.items.clear() + task.submit( + SearchMethodTask( + jar, + owner.text, + name.text, + description.text, + anInterface.isSelected + ) + ) + .thenAccept { + it.forEach { result -> + searchResultList.items.add(result) + } + } + } + }, "span 2") + } + center = searchResultList + } + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/dialog/SearchOpcodeDialog.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/dialog/SearchOpcodeDialog.kt new file mode 100644 index 0000000..e440b59 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/dialog/SearchOpcodeDialog.kt @@ -0,0 +1,67 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.dialog + +import cn.enaium.joe.core.task.SearchOpcodeTask +import cn.enaium.joe.core.util.OpcodeUtil +import cn.enaium.joe.ui.Instance.jar +import cn.enaium.joe.ui.JavaOctetEditor.Companion.task +import cn.enaium.joe.ui.control.SearchResultList +import cn.enaium.joe.ui.util.i18n +import cn.enaium.joe.ui.util.warning +import javafx.scene.control.Button +import javafx.scene.control.ComboBox +import javafx.scene.control.Label +import javafx.scene.layout.BorderPane +import org.tbee.javafx.scene.layout.MigPane + +/** + * @author Enaium + * @since 2.0.0 + */ +class SearchOpcodeDialog : Dialog(i18n("search.opcode.title")) { + init { + content = BorderPane().apply { + val searchResultList = SearchResultList() + top = MigPane("fillx", "[fill][fill]").apply { + add(Label(i18n("search.opcode"))) + val opcode = ComboBox().apply { + isEditable = true + OpcodeUtil.OPCODE.forEach { + items.add(it.value) + } + } + add(opcode, "wrap") + add(Button(i18n("menu.search")).apply { + setOnAction { + if (opcode.value.isBlank()) { + warning("Please input!") + return@setOnAction + } + searchResultList.items.clear() + task.submit(SearchOpcodeTask(jar, opcode.value)).thenAccept { + it.forEach { result -> + searchResultList.items.add(result) + } + } + } + }, "span 2") + } + center = searchResultList + } + } +} \ No newline at end of file diff --git a/src/main/java/cn/enaium/joe/event/Event.java b/ui/src/main/kotlin/cn/enaium/joe/ui/event/Event.kt old mode 100644 new mode 100755 similarity index 89% rename from src/main/java/cn/enaium/joe/event/Event.java rename to ui/src/main/kotlin/cn/enaium/joe/ui/event/Event.kt index c262db1..f59b62c --- a/src/main/java/cn/enaium/joe/event/Event.java +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/event/Event.kt @@ -13,12 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -package cn.enaium.joe.event; +package cn.enaium.joe.ui.event /** * @author Enaium - * @since 1.2.0 + * @since 2.0.0 */ -public interface Event { -} +interface Event \ No newline at end of file diff --git a/src/main/java/cn/enaium/joe/gui/panel/confirm/ConfirmPanel.java b/ui/src/main/kotlin/cn/enaium/joe/ui/event/EventManager.kt old mode 100644 new mode 100755 similarity index 53% rename from src/main/java/cn/enaium/joe/gui/panel/confirm/ConfirmPanel.java rename to ui/src/main/kotlin/cn/enaium/joe/ui/event/EventManager.kt index a868706..39a7c2a --- a/src/main/java/cn/enaium/joe/gui/panel/confirm/ConfirmPanel.java +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/event/EventManager.kt @@ -13,36 +13,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package cn.enaium.joe.ui.event -package cn.enaium.joe.gui.panel.confirm; - -import javax.swing.*; -import java.awt.*; +import cn.enaium.joe.core.util.Pair +import java.util.concurrent.CopyOnWriteArrayList +import java.util.function.Consumer /** * @author Enaium - * @since 0.8.0 + * @since 2.0.0 */ -public class ConfirmPanel extends JPanel { - - private Runnable confirm = () -> { - }; - private Runnable cancel = () -> { - }; - - public Runnable getConfirm() { - return confirm; - } - - public void setConfirm(Runnable confirm) { - this.confirm = confirm; - } - - public Runnable getCancel() { - return cancel; +class EventManager { + val listeners: MutableList, Consumer>> = CopyOnWriteArrayList() + inline fun register(consumer: Consumer) { + listeners.add(Pair(T::class.java, consumer as Consumer)) } - public void setCancel(Runnable cancel) { - this.cancel = cancel; + fun call(event: Event) { + listeners.stream().filter { it.key == event.javaClass }.forEach { it.value.accept(event) } } -} +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/event/Events.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/event/Events.kt new file mode 100755 index 0000000..fe8e3b3 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/event/Events.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.event + +import cn.enaium.joe.core.model.JarModel +import cn.enaium.joe.ui.control.tree.AnyTreeItem +import javafx.scene.control.Tab +import org.objectweb.asm.tree.ClassNode + +/** + * @author Enaium + * @since 2.0.0 + */ +class LoadJar(val jar: JarModel) : Event + +class SelectTreeItem(val item: AnyTreeItem) : Event + +class ContentTabChange(val old: Tab?, val new: Tab?) : Event + +class ResultJump(val classNode: ClassNode) : Event \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/CodePane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/CodePane.kt new file mode 100755 index 0000000..c7b96e4 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/CodePane.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane + +import cn.enaium.joe.ui.control.CodeEditor +import javafx.scene.layout.BorderPane +import org.fxmisc.flowless.VirtualizedScrollPane + + +/** + * @author Enaium + */ +class CodePane(type: CodeEditor.Language.Type) : BorderPane() { + val codeEditor = CodeEditor(type) + + init { + center = VirtualizedScrollPane(codeEditor) + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/MainPane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/MainPane.kt new file mode 100755 index 0000000..6b5fc68 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/MainPane.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package cn.enaium.joe.ui.pane + +import cn.enaium.joe.ui.JavaOctetEditor.Companion.event +import cn.enaium.joe.ui.control.MainMenuBar +import cn.enaium.joe.ui.event.LoadJar +import javafx.application.Platform +import javafx.scene.layout.BorderPane +import javafx.stage.Stage + +/** + * @author Enaium + * @since 2.0.0 + */ +class MainPane(primaryStage: Stage) : BorderPane() { + init { + top = MainMenuBar().apply { + isUseSystemMenuBar = true + } + + center = ProjectPane() + } +} \ No newline at end of file diff --git a/src/main/java/cn/enaium/joe/dialog/MethodDialog.java b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/ProjectPane.kt old mode 100644 new mode 100755 similarity index 55% rename from src/main/java/cn/enaium/joe/dialog/MethodDialog.java rename to ui/src/main/kotlin/cn/enaium/joe/ui/pane/ProjectPane.kt index bd2fbfa..ce6dfa4 --- a/src/main/java/cn/enaium/joe/dialog/MethodDialog.java +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/ProjectPane.kt @@ -14,22 +14,26 @@ * limitations under the License. */ -package cn.enaium.joe.dialog; +package cn.enaium.joe.ui.pane -import cn.enaium.joe.gui.panel.method.MethodTabPanel; -import org.objectweb.asm.tree.ClassNode; -import org.objectweb.asm.tree.MethodNode; -import java.awt.*; +import cn.enaium.joe.ui.control.FileTree +import cn.enaium.joe.ui.pane.content.ContentTabPane +import cn.enaium.joe.ui.pane.side.SidePane +import javafx.scene.control.SplitPane +import javafx.scene.layout.BorderPane /** * @author Enaium - * @since 1.2.0 + * @since 2.0.0 */ -public class MethodDialog extends Dialog { - public MethodDialog(ClassNode classNode, MethodNode methodNode) { - super(classNode.name + "#" + methodNode.name); - setLayout(new BorderLayout()); - add(new MethodTabPanel(methodNode), BorderLayout.CENTER); +class ProjectPane : BorderPane() { + init { + center = SplitPane().apply { + items.add(FileTree()) + items.add(ContentTabPane()) + items.add(SidePane()) + setDividerPositions(.2, .9) + } } -} +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/confirm/BootstrapMethodArgumentEditPane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/confirm/BootstrapMethodArgumentEditPane.kt new file mode 100644 index 0000000..a9ab552 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/confirm/BootstrapMethodArgumentEditPane.kt @@ -0,0 +1,109 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.confirm + +import cn.enaium.joe.core.wrapper.Wrapper +import cn.enaium.joe.ui.dialog.ConfirmDialog +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.* +import javafx.scene.layout.HBox +import org.objectweb.asm.Handle +import org.objectweb.asm.Type +import org.tbee.javafx.scene.layout.MigPane + +/** + * @author Enaium + * @since 2.0.0 + */ +class BootstrapMethodArgumentEditPane(anyArrayWrapper: Wrapper>) : ConfirmPane() { + init { + val list = ListView().apply { + anyArrayWrapper.wrapper.forEach { + items.add(it) + } + } + center = list + bottom = HBox().apply { + children.add(Button(i18n("button.add")).apply { + setOnAction { + ConfirmDialog(ConfirmPane().apply { + center = MigPane("fillx", "[fill][fill]").apply { + add(Label(i18n("instruction.type"))) + val type = ComboBox().apply { + items.addAll("String", "float", "double", "int", "long", "Class") + } + add(type, "wrap") + add(Label(i18n("instruction.var"))) + val ldc = TextField() + add(ldc) + confirm = { + type.value?.let { + when (type.value) { + "String" -> { + list.items.add(ldc.text) + } + + "float" -> { + list.items.add(ldc.text.toFloat()) + } + + "double" -> { + list.items.add(ldc.text.toDouble()) + } + + "int" -> { + list.items.add(ldc.text.toInt()) + } + + "long" -> { + list.items.add(ldc.text.toLong()) + } + + "Class" -> { + list.items.add(Type.getType(ldc.text)) + } + } + } + } + } + }).show() + } + }) + children.add(Button(i18n("instruction.addHandle")).apply { + setOnAction { + val handleWrapper = Wrapper(Handle(1, "", "", "", false)) + ConfirmDialog(HandleEditPane(handleWrapper)).apply { + confirm = { + list.items.add(handleWrapper.wrapper) + } + }.show() + } + }) + children.add(Button(i18n("button.remove")).apply { + setOnAction { + list.selectionModel.selectedItem?.let { + list.items.remove(list.selectionModel.selectedItem) + } + } + }) + } + + confirm = { + anyArrayWrapper.wrapper = list.items.toTypedArray() + } + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/confirm/ConfirmPane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/confirm/ConfirmPane.kt new file mode 100644 index 0000000..019bc46 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/confirm/ConfirmPane.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.confirm + +import javafx.scene.layout.BorderPane + +/** + * @author Enaium + * @since 2.0.0 + */ +open class ConfirmPane : BorderPane() { + var confirm = {} + var cancel = {} +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/confirm/FrameListEditPane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/confirm/FrameListEditPane.kt new file mode 100644 index 0000000..b5af1ba --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/confirm/FrameListEditPane.kt @@ -0,0 +1,100 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.confirm + +import cn.enaium.joe.core.util.OpcodeUtil +import cn.enaium.joe.ui.dialog.ConfirmDialog +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.* +import javafx.scene.layout.BorderPane +import javafx.scene.layout.HBox +import org.objectweb.asm.tree.FrameNode + +/** + * @author Enaium + * @since 2.0.0 + */ +class FrameListEditPane(frameNode: FrameNode) : ConfirmPane() { + init { + center = SplitPane().apply { + val tempLocal = frameNode.local.toMutableList() + items.add(BorderPane().apply { + top = Label(i18n("instruction.local")) + center = AnyList(tempLocal) + }) + val tempStack = frameNode.stack.toMutableList() + items.add(BorderPane().apply { + top = Label(i18n("instruction.stack")) + center = AnyList(tempStack) + }) + confirm = { + frameNode.local = tempLocal + frameNode.stack = tempStack + } + } + } + + private class AnyList(anyList: MutableList) : BorderPane() { + init { + val list = ListView().apply { + anyList.forEach { + if (it is String) { + items.add(it) + } else if (it is Int) { + items.add(OpcodeUtil.FRAME_ELEMENT[it]) + } + } + } + center = list + bottom = HBox().apply { + children.add(Button(i18n("instruction.frame.addString")).apply { + setOnAction { + val string = TextInputDialog().showAndWait() + if (string.get().isNotBlank()) { + anyList.add(string.get()) + list.items.add(string.get()) + } + } + }) + children.add(Button(i18n("instruction.frame.addType")).apply { + setOnAction { + ConfirmDialog(ConfirmPane().apply { + val type = ComboBox().apply { + items.addAll(OpcodeUtil.FRAME_ELEMENT.values) + } + center = type + confirm = { + type.selectionModel.selectedItem?.let { + anyList.add(type.selectionModel.selectedItem) + list.items.add(type.selectionModel.selectedItem) + } + } + }).show() + } + }) + children.add(Button(i18n("button.remove")).apply { + setOnAction { + list.selectionModel.selectedItem?.let { + anyList.removeAt(list.selectionModel.selectedIndex) + list.items.removeAt(list.selectionModel.selectedIndex) + } + } + }) + } + } + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/confirm/HandleEditPane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/confirm/HandleEditPane.kt new file mode 100644 index 0000000..c6e1a11 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/confirm/HandleEditPane.kt @@ -0,0 +1,71 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.confirm + +import cn.enaium.joe.core.util.OpcodeUtil +import cn.enaium.joe.core.wrapper.Wrapper +import cn.enaium.joe.ui.util.i18n +import javafx.geometry.Pos +import javafx.scene.control.CheckBox +import javafx.scene.control.ComboBox +import javafx.scene.control.Label +import javafx.scene.control.TextField +import org.objectweb.asm.Handle +import org.tbee.javafx.scene.layout.MigPane + +/** + * @author Enaium + * @since 2.0.0 + */ +class HandleEditPane(handleWrapper: Wrapper) : ConfirmPane() { + init { + center = MigPane("fillx,", "[fill][fill]").apply { + add(Label(i18n("instruction.tag"))) + val tag = ComboBox().apply { + OpcodeUtil.HANDLE.values.forEach { + items.add(it) + } + } + add(tag, "wrap") + add(Label(i18n("instruction.owner"))) + val owner = TextField(handleWrapper.wrapper.owner) + add(owner, "wrap") + add(Label(i18n("instruction.name"))) + val name = TextField(handleWrapper.wrapper.name) + add(name, "wrap") + add(Label(i18n("instruction.description"))) + val description = TextField(handleWrapper.wrapper.desc) + add(description, "wrap") + add(Label(i18n("instruction.interface"))) + val isInterface = CheckBox().apply { + alignment = Pos.CENTER_RIGHT + } + add(isInterface, "wrap") + confirm = { + tag.value?.let { + handleWrapper.wrapper = Handle( + OpcodeUtil.reverse(OpcodeUtil.HANDLE)[tag.selectionModel.selectedItem]!!, + owner.text, + name.text, + description.text, + isInterface.isSelected + ) + } + } + } + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/confirm/InstructionEditPane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/confirm/InstructionEditPane.kt new file mode 100644 index 0000000..6ced33c --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/confirm/InstructionEditPane.kt @@ -0,0 +1,75 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.confirm + +import cn.enaium.joe.ui.pane.instruction.* +import cn.enaium.joe.ui.util.warning +import org.objectweb.asm.tree.AbstractInsnNode +import org.objectweb.asm.tree.FieldInsnNode +import org.objectweb.asm.tree.FrameNode +import org.objectweb.asm.tree.IincInsnNode +import org.objectweb.asm.tree.InsnNode +import org.objectweb.asm.tree.IntInsnNode +import org.objectweb.asm.tree.InvokeDynamicInsnNode +import org.objectweb.asm.tree.JumpInsnNode +import org.objectweb.asm.tree.LabelNode +import org.objectweb.asm.tree.LdcInsnNode +import org.objectweb.asm.tree.LineNumberNode +import org.objectweb.asm.tree.LookupSwitchInsnNode +import org.objectweb.asm.tree.MethodInsnNode +import org.objectweb.asm.tree.MultiANewArrayInsnNode +import org.objectweb.asm.tree.TableSwitchInsnNode +import org.objectweb.asm.tree.TypeInsnNode +import org.objectweb.asm.tree.VarInsnNode + +/** + * @author Enaium + * @since 2.0.0 + */ +class InstructionEditPane(instruction: AbstractInsnNode) : ConfirmPane() { + init { + var abstractInstructionPane: AbstractInstructionPane? = null + + when (instruction) { + is InsnNode -> abstractInstructionPane = InstructionPane(instruction) + is IntInsnNode -> abstractInstructionPane = IntInstructionPane(instruction) + is VarInsnNode -> abstractInstructionPane = VarInstructionPane(instruction) + is TypeInsnNode -> abstractInstructionPane = TypeInstructionPane(instruction) + is FieldInsnNode -> abstractInstructionPane = FieldInstructionPane(instruction) + is MethodInsnNode -> abstractInstructionPane = MethodInstructionPane(instruction) + is InvokeDynamicInsnNode -> abstractInstructionPane = InvokeDynamicInstructionPane(instruction) + is JumpInsnNode -> abstractInstructionPane = JumpInstructionPane(instruction) + is LabelNode -> {} + is LdcInsnNode -> abstractInstructionPane = LDCInstructionPane(instruction) + is IincInsnNode -> abstractInstructionPane = IncrInstructionPane(instruction) + is TableSwitchInsnNode -> abstractInstructionPane = TableSwitchInstructionPane(instruction) + is LookupSwitchInsnNode -> abstractInstructionPane = LookupSwitchInstructionPane(instruction) + is MultiANewArrayInsnNode -> abstractInstructionPane = MultiANewArrayInstructionPane(instruction) + is FrameNode -> abstractInstructionPane = FrameInstructionPane(instruction) + is LineNumberNode -> abstractInstructionPane = LineInstructionPane(instruction) + } + + abstractInstructionPane?.let { + center = abstractInstructionPane + confirm = { + if (!abstractInstructionPane.confirm.invoke()) { + warning("Fail") + } + } + } + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/confirm/LabelListEditPane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/confirm/LabelListEditPane.kt new file mode 100644 index 0000000..f4306e1 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/confirm/LabelListEditPane.kt @@ -0,0 +1,77 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.confirm + +import cn.enaium.joe.core.wrapper.LabelNodeWrapper +import cn.enaium.joe.ui.dialog.ConfirmDialog +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.Button +import javafx.scene.control.ComboBox +import javafx.scene.control.ListView +import javafx.scene.layout.HBox +import org.objectweb.asm.tree.InsnList +import org.objectweb.asm.tree.LabelNode + +/** + * @author Enaium + * @since 2.0.0 + */ +class LabelListEditPane(labelList: MutableList, insnList: InsnList) : ConfirmPane() { + init { + val list = ListView().apply { + labelList.forEach { + items.add(LabelNodeWrapper(it)) + } + } + center = list + bottom = HBox().apply { + children.add(Button(i18n("button.add")).apply { + setOnAction { + val comboBox = ComboBox().apply { + + insnList.forEach { + if (it is LabelNode) { + items.add(LabelNodeWrapper(it)) + } + } + } + ConfirmDialog(ConfirmPane().apply { + center = comboBox + + confirm = { + comboBox.value?.let { + list.items.add(comboBox.value) + } + } + }).show() + } + }) + children.add(Button(i18n("button.remove")).apply { + list.selectionModel.selectedItem?.let { + list.items.removeAt(list.selectionModel.selectedIndex) + } + }) + } + + confirm = { + labelList.clear() + list.items.forEach { + labelList.add(it.wrapper) + } + } + } +} \ No newline at end of file diff --git a/src/main/java/cn/enaium/joe/util/ASyncUtil.java b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/confirm/ListValueEditPane.kt similarity index 53% rename from src/main/java/cn/enaium/joe/util/ASyncUtil.java rename to ui/src/main/kotlin/cn/enaium/joe/ui/pane/confirm/ListValueEditPane.kt index fa2f0e6..671355a 100644 --- a/src/main/java/cn/enaium/joe/util/ASyncUtil.java +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/confirm/ListValueEditPane.kt @@ -14,28 +14,26 @@ * limitations under the License. */ -package cn.enaium.joe.util; +package cn.enaium.joe.ui.pane.confirm -import javax.swing.*; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; +import cn.enaium.joe.core.util.ASMUtil +import cn.enaium.joe.core.util.ListUtil +import javafx.scene.control.TextArea /** * @author Enaium + * @since 2.0.0 */ -public class ASyncUtil { - - public static void execute(Runnable run) { - execute(run, null); - } - - public static void execute(Runnable run, Runnable ui) { - ExecutorService executorService = Executors.newSingleThreadExecutor(); - executorService.execute(() -> { - run.run(); - if (ui != null) { - SwingUtilities.invokeLater(ui); +class ListValueEditPane(anyList: MutableList) : ConfirmPane() { + init { + val type = ListUtil.getType(anyList) + val textArea = TextArea(anyList.joinToString("\n")) + center = textArea + confirm = { + anyList.clear() + textArea.text.split("\n").forEach { + anyList.add(ASMUtil.valueOf(type, it)) } - }); + } } -} +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/confirm/LookupSwitchEditPane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/confirm/LookupSwitchEditPane.kt new file mode 100644 index 0000000..6e58b9b --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/confirm/LookupSwitchEditPane.kt @@ -0,0 +1,92 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.confirm + +import cn.enaium.joe.core.wrapper.LabelNodeWrapper +import cn.enaium.joe.ui.control.LabelNodeComboBox +import cn.enaium.joe.ui.dialog.ConfirmDialog +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.Button +import javafx.scene.control.Spinner +import javafx.scene.control.TableColumn +import javafx.scene.control.TableView +import javafx.scene.control.cell.PropertyValueFactory +import javafx.scene.layout.HBox +import org.objectweb.asm.tree.LabelNode +import org.tbee.javafx.scene.layout.MigPane + +/** + * @author Enaium + */ +class LookupSwitchEditPane(keys: MutableList, labels: MutableList) : ConfirmPane() { + init { + val tableView = TableView().apply { + isEditable = false + val key = TableColumn(i18n("instruction.lookSwitch.keys")) + key.isResizable = false + key.cellValueFactory = PropertyValueFactory("key") + key.prefWidthProperty().bind(widthProperty().multiply(.5)) + + val label = TableColumn(i18n("instruction.lookSwitch.labels")) + label.isResizable = false + label.cellValueFactory = PropertyValueFactory("labelNodeWrapper") + label.prefWidthProperty().bind(widthProperty().multiply(.5)) + + labels.indices.forEach { + items.add(Item(keys[it], LabelNodeWrapper(labels[it]))) + } + columns.addAll(key, label) + } + center = tableView + bottom = HBox().apply { + children.add(Button(i18n("button.add")).apply { + setOnAction { + ConfirmDialog(ConfirmPane().apply { + center = MigPane("fillx", "[fill][fill]").apply { + val key = Spinner() + val label = LabelNodeComboBox(labels[0]) + add(key) + add(label) + confirm = { + label.value?.let { + tableView.items.add(Item(key.value, label.value)) + } + } + } + }).show() + } + }) + children.add(Button(i18n("button.remove")).apply { + setOnAction { + tableView.selectionModel.selectedItem?.let { + tableView.items.removeAt(tableView.selectionModel.selectedIndex) + } + } + }) + } + confirm = { + keys.clear() + labels.clear() + tableView.items.forEach { + keys.add(it.key) + labels.add(it.labelNodeWrapper.wrapper) + } + } + } + + class Item(val key: Int, val labelNodeWrapper: LabelNodeWrapper) +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/confirm/ValueEditPane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/confirm/ValueEditPane.kt new file mode 100644 index 0000000..239018b --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/confirm/ValueEditPane.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.confirm + +import cn.enaium.joe.core.util.ASMUtil +import cn.enaium.joe.core.wrapper.Wrapper +import javafx.scene.control.TextField + +/** + * @author Enaium + * @since 2.0.0 + */ +class ValueEditPane(anyWrapper: Wrapper) : ConfirmPane() { + init { + val textField = TextField(anyWrapper.wrapper.toString()) + center = textField + confirm = { + anyWrapper.wrapper = ASMUtil.valueOf(anyWrapper.wrapper.javaClass, textField.text) + } + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/content/ContentTabPane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/content/ContentTabPane.kt new file mode 100755 index 0000000..05bd76a --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/content/ContentTabPane.kt @@ -0,0 +1,62 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.content + + +import cn.enaium.joe.ui.JavaOctetEditor.Companion.event +import cn.enaium.joe.ui.control.tree.ClassTreeItem +import cn.enaium.joe.ui.control.tree.FileTreeItem +import cn.enaium.joe.ui.event.ContentTabChange +import cn.enaium.joe.ui.event.SelectTreeItem +import cn.enaium.joe.ui.pane.content.classes.ClassTabPane +import cn.enaium.joe.ui.pane.content.resources.ResourceTabPane +import javafx.scene.control.Tab +import javafx.scene.control.TabPane + +/** + * @author Enaium + * @since 2.0.0 + */ +class ContentTabPane : TabPane() { + init { + event.register { + when (it.item) { + is ClassTreeItem -> { + Tab(it.item.toString()).apply { + content = ClassTabPane(it.item) + } + } + + is FileTreeItem -> { + Tab(it.item.toString()).apply { + content = ResourceTabPane(it.item) + } + } + + else -> { + null + } + }?.let { tab -> + tabs.add(tab) + selectionModel.select(tab) + } + } + + selectionModel.selectedItemProperty() + .addListener { _, oldValue, newValue -> event.call(ContentTabChange(oldValue, newValue)) } + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/content/classes/ASMifierPane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/content/classes/ASMifierPane.kt new file mode 100644 index 0000000..0c2244c --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/content/classes/ASMifierPane.kt @@ -0,0 +1,49 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.content.classes + + +import cn.enaium.joe.ui.control.CodeEditor +import cn.enaium.joe.ui.pane.CodePane +import cn.enaium.joe.ui.util.runLater +import javafx.scene.layout.BorderPane +import org.objectweb.asm.tree.ClassNode +import org.objectweb.asm.util.ASMifier +import org.objectweb.asm.util.TraceClassVisitor +import java.io.PrintWriter +import java.io.StringWriter + + +class ASMifierPane(classNode: ClassNode) : BorderPane() { + init { + + center = CodePane(CodeEditor.Language.Type.JAVA).apply { + runLater({ + val stringWriter = StringWriter() + classNode.accept(TraceClassVisitor(null, ASMifier(), PrintWriter(stringWriter))) + stringWriter.toString() + }, { result -> + val trim = getMiddle(getMiddle(result)).trim() + codeEditor.replaceText(trim.substring(0, trim.lastIndexOf("\n"))) + }) + } + } + + private fun getMiddle(s: String): String { + return s.substring(s.indexOf("{") + 1, s.lastIndexOf("}")) + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/content/classes/BytecodePane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/content/classes/BytecodePane.kt new file mode 100755 index 0000000..af5fde8 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/content/classes/BytecodePane.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.content.classes + + +import cn.enaium.joe.ui.control.CodeEditor +import cn.enaium.joe.ui.pane.CodePane +import cn.enaium.joe.ui.util.runLater +import javafx.scene.layout.BorderPane +import org.objectweb.asm.tree.ClassNode +import org.objectweb.asm.util.TraceClassVisitor +import java.io.PrintWriter +import java.io.StringWriter + + +/** + * @author Enaium + * @since 2.0.0 + */ +class BytecodePane(classNode: ClassNode) : BorderPane() { + init { + center = CodePane(CodeEditor.Language.Type.BYTECODE).apply { + runLater({ + val stringWriter = StringWriter() + classNode.accept(TraceClassVisitor(PrintWriter(stringWriter))) + stringWriter.toString() + }) { result -> codeEditor.replaceText(result) } + } + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/content/classes/ClassTabPane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/content/classes/ClassTabPane.kt new file mode 100755 index 0000000..5860ba6 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/content/classes/ClassTabPane.kt @@ -0,0 +1,51 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.content.classes + + +import cn.enaium.joe.ui.control.tree.ClassTreeItem +import cn.enaium.joe.ui.util.i18n +import javafx.geometry.Side +import javafx.scene.control.Tab +import javafx.scene.control.TabPane + +/** + * @author Enaium + */ +class ClassTabPane(val classTreeItem: ClassTreeItem) : TabPane() { + init { + side = Side.BOTTOM + tabs.addAll( + Tab(i18n("class.tab.bytecode")).apply { + isClosable = false + content = BytecodePane(classTreeItem.classNode) + }, + Tab(i18n("class.tab.decompile")).apply { + isClosable = false + content = DecompilePane(classTreeItem.classNode) + }, + Tab(i18n("class.tab.visitor")).apply { + isClosable = false + content = ASMifierPane(classTreeItem.classNode) + }, + Tab(i18n("class.tab.info")).apply { + isClosable = false + content = InfoPane(classTreeItem.classNode) + }, + ) + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/content/classes/DecompilePane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/content/classes/DecompilePane.kt new file mode 100644 index 0000000..419c099 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/content/classes/DecompilePane.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.content.classes + + +import cn.enaium.joe.core.task.DecompileTask +import cn.enaium.joe.ui.Instance +import cn.enaium.joe.ui.JavaOctetEditor.Companion.config +import cn.enaium.joe.ui.JavaOctetEditor.Companion.task +import cn.enaium.joe.ui.control.CodeEditor +import cn.enaium.joe.ui.pane.CodePane +import javafx.application.Platform +import javafx.scene.layout.BorderPane +import org.objectweb.asm.tree.ClassNode + + +class DecompilePane(classNode: ClassNode) : BorderPane() { + init { + center = CodePane(CodeEditor.Language.Type.JAVA).apply { + task.submit(DecompileTask(Instance.jar, config, classNode)).thenAccept { + Platform.runLater { codeEditor.replaceText(it) } + } + } + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/content/classes/InfoPane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/content/classes/InfoPane.kt new file mode 100755 index 0000000..7c307d8 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/content/classes/InfoPane.kt @@ -0,0 +1,139 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.content.classes + + +import cn.enaium.joe.ui.dialog.AnnotationDialog +import cn.enaium.joe.ui.util.i18n +import cn.enaium.joe.ui.util.info +import javafx.scene.control.Button +import javafx.scene.control.Label +import javafx.scene.control.TextField +import org.benf.cfr.reader.util.StringUtils +import org.objectweb.asm.tree.ClassNode +import org.tbee.javafx.scene.layout.MigPane +import java.lang.String +import kotlin.apply + + +/** + * @author Enaium + */ +class InfoPane(classNode: ClassNode) : MigPane("fillx", "[fill][fill]") { + init { + add(Label(i18n("class.info.name"))) + val name = TextField(classNode.name) + add(name, "wrap") + add(Label(i18n("class.info.sourceFile"))) + val sourceFile = TextField(classNode.sourceFile) + add(sourceFile, "wrap") + add(Label(i18n("class.info.debugFile"))) + val sourceDebug = TextField(classNode.sourceDebug) + add(sourceDebug, "wrap") + add(Label(i18n("class.info.access"))) + val access = TextField(String.valueOf(classNode.access)) + add(access, "wrap") + add(Label(i18n("class.info.version"))) + val version = TextField(String.valueOf(classNode.version)) + add(version, "wrap") + add(Label(i18n("class.info.signature"))) + val signature = TextField(classNode.signature) + add(signature, "wrap") + add(Label(i18n("class.info.superName"))) + val superName = TextField(classNode.superName) + add(superName, "wrap") + add(Label(i18n("class.info.interfaces"))) + val interfaces = TextField(classNode.interfaces.joinToString(";")) + add(interfaces, "wrap") + add(Label(i18n("class.info.outerClass"))) + val outerClass = TextField(classNode.outerClass) + add(outerClass, "wrap") + add(Label(i18n("class.info.outerMethod"))) + val outerMethod = TextField(classNode.outerMethod) + add(outerMethod, "wrap") + add(Label(i18n("class.info.outerMethodDescription"))) + val outerMethodDesc = TextField(classNode.outerMethodDesc) + add(outerMethodDesc, "wrap") + add(Label(i18n("class.info.visibleAnnotation"))) + add(Button(i18n("button.edit")).apply { + setOnAction { + classNode.visibleAnnotations?.let { + AnnotationDialog(classNode.visibleAnnotations).show() + } + } + }, "wrap") + add(Label(i18n("class.info.invisibleAnnotation"))) + add(Button(i18n("button.edit")).apply { + setOnAction { + classNode.invisibleAnnotations?.let { + AnnotationDialog(classNode.invisibleAnnotations).show() + } + } + }, "wrap") + add(Button(i18n("button.save")).apply { + setOnAction { + if (name.text?.isNotBlank() == true) { + classNode.name = name.text + } + if (sourceFile.text?.isNotBlank() == true) { + classNode.sourceFile = sourceFile.text + } else { + classNode.sourceFile = null + } + if (sourceDebug.text?.isNotBlank() == true) { + classNode.sourceDebug = sourceDebug.text + } else { + classNode.sourceDebug = null + } + if (access.text?.isNotBlank() == true) { + classNode.access = access.text.toInt() + } + if (version.text?.isNotBlank() == true) { + classNode.version = version.text.toInt() + } + if (signature.text?.isNotBlank() == true) { + classNode.signature = signature.text + } else { + classNode.signature = null + } + if (interfaces.text?.isNotBlank() == true) { + classNode.interfaces = listOf( + *superName.text.split(";".toRegex()).dropLastWhile { it.isEmpty() } + .toTypedArray()) + } else { + classNode.interfaces = emptyList() + } + if (outerClass.text?.isNotBlank() == true) { + classNode.outerClass = outerClass.text + } else { + classNode.outerClass = null + } + if (outerMethod.text?.isNotBlank() == true) { + classNode.outerMethod = outerMethod.text + } else { + classNode.outerClass = null + } + if (outerMethodDesc.text?.isNotBlank() == true) { + classNode.outerMethodDesc = outerMethodDesc.text + } else { + classNode.outerClass = null + } + info(i18n("success")) + } + }, "span 2") + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/content/resources/HexPane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/content/resources/HexPane.kt new file mode 100644 index 0000000..3f4a173 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/content/resources/HexPane.kt @@ -0,0 +1,57 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.content.resources + +import cn.enaium.joe.ui.control.tree.FileTreeItem +import javafx.beans.property.SimpleStringProperty +import javafx.scene.control.TableColumn +import javafx.scene.control.TableView +import javafx.scene.control.cell.PropertyValueFactory +import javafx.scene.layout.BorderPane +import kotlin.math.ceil + +/** + * @author Enaium + * @since 2.0.0 + */ +class HexPane(fileTreeItem: FileTreeItem) : BorderPane() { + init { + val tableView = TableView() + for (i in 0..15) { + val element = TableColumn("%X".format(i)) + element.isReorderable = false + element.setCellValueFactory { cell -> + val x = i + val y = cell.value + try { + SimpleStringProperty("%02X".format(fileTreeItem.data[x + y * 16])) + } catch (_: ArrayIndexOutOfBoundsException) { + SimpleStringProperty("") + } + } + element.prefWidthProperty().bind(widthProperty().multiply(1.0 / 16.0)) + tableView.columns.add(element) + } + + for (i in 0 until ceil(fileTreeItem.data.size / 16.0).toInt()) { + tableView.items.add(i) + } + + + center = tableView + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/content/resources/ImagePane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/content/resources/ImagePane.kt new file mode 100755 index 0000000..e398997 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/content/resources/ImagePane.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.content.resources + +import cn.enaium.joe.ui.control.tree.FileTreeItem +import javafx.scene.image.Image +import javafx.scene.image.ImageView +import javafx.scene.layout.BorderPane +import java.io.ByteArrayInputStream + +/** + * @author Enaium + */ +class ImagePane(fileTreeItem: FileTreeItem) : BorderPane() { + init { + center = ImageView(Image(ByteArrayInputStream(fileTreeItem.data))) + } +} \ No newline at end of file diff --git a/src/main/java/cn/enaium/joe/dialog/FieldDialog.java b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/content/resources/ResourceTabPane.kt old mode 100644 new mode 100755 similarity index 52% rename from src/main/java/cn/enaium/joe/dialog/FieldDialog.java rename to ui/src/main/kotlin/cn/enaium/joe/ui/pane/content/resources/ResourceTabPane.kt index 3ae0bba..7893fdc --- a/src/main/java/cn/enaium/joe/dialog/FieldDialog.java +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/content/resources/ResourceTabPane.kt @@ -1,35 +1,38 @@ -/* - * Copyright 2022 Enaium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.enaium.joe.dialog; - -import cn.enaium.joe.gui.panel.FieldInfoPanel; -import org.objectweb.asm.tree.ClassNode; -import org.objectweb.asm.tree.FieldNode; - -import java.awt.*; - -/** - * @author Enaium - * @since 1.2.0 - */ -public class FieldDialog extends Dialog { - public FieldDialog(ClassNode classNode, FieldNode fieldNode) { - super(classNode.name + "#" + fieldNode.name); - setLayout(new BorderLayout()); - add(new FieldInfoPanel(fieldNode), BorderLayout.CENTER); - } -} +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.content.resources + + +import cn.enaium.joe.ui.control.tree.FileTreeItem +import cn.enaium.joe.ui.util.isImage +import cn.enaium.joe.ui.util.isText +import javafx.scene.layout.BorderPane + +/** + * @author Enaium + */ +class ResourceTabPane(fileTreeItem: FileTreeItem) : BorderPane() { + init { + if (isImage(fileTreeItem.data)) { + center = ImagePane(fileTreeItem) + } else if (isText(fileTreeItem.data)) { + center = TextPane(fileTreeItem) + } else { + center = HexPane(fileTreeItem) + } + } +} \ No newline at end of file diff --git a/src/main/java/cn/enaium/joe/dialog/Dialog.java b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/content/resources/TextPane.kt similarity index 54% rename from src/main/java/cn/enaium/joe/dialog/Dialog.java rename to ui/src/main/kotlin/cn/enaium/joe/ui/pane/content/resources/TextPane.kt index 0561b83..f0181ab 100644 --- a/src/main/java/cn/enaium/joe/dialog/Dialog.java +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/content/resources/TextPane.kt @@ -14,18 +14,18 @@ * limitations under the License. */ -package cn.enaium.joe.dialog; +package cn.enaium.joe.ui.pane.content.resources -import com.formdev.flatlaf.extras.FlatSVGIcon; +import cn.enaium.joe.ui.control.CodeEditor +import cn.enaium.joe.ui.control.tree.FileTreeItem +import cn.enaium.joe.ui.pane.CodePane +import javafx.scene.layout.BorderPane +import java.nio.charset.Charset -import javax.swing.*; - -public class Dialog extends JFrame { - public Dialog(String title) { - super(title); - setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); - setSize(800, 500); - setLocationRelativeTo(getOwner()); - setIconImage(new FlatSVGIcon("icons/logo.svg").getImage()); +class TextPane(fileTreeItem: FileTreeItem) : BorderPane() { + init { + center = CodePane(CodeEditor.Language.Type.UNKNOWN).apply { + codeEditor.replaceText(0, 0, fileTreeItem.data.toString(Charset.forName("utf-8"))) + } } } \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/AbstractInstructionPane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/AbstractInstructionPane.kt new file mode 100644 index 0000000..8e97421 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/AbstractInstructionPane.kt @@ -0,0 +1,58 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.instruction + +import cn.enaium.joe.core.util.OpcodeUtil +import cn.enaium.joe.ui.util.i18n +import javafx.scene.Node +import javafx.scene.control.ComboBox +import javafx.scene.control.Label +import org.objectweb.asm.tree.AbstractInsnNode +import org.tbee.javafx.scene.layout.MigPane +import java.lang.NullPointerException +import java.util.concurrent.Callable + +/** + * @author Enaium + * @since 2.0.0 + */ +abstract class AbstractInstructionPane(instruction: AbstractInsnNode) : MigPane("fillx", "[fill]", "[fill]") { + private val opcode = ComboBox() + var confirm = { false } + + init { + if (instruction.opcode != -1) { + opcode.items.addAll(getOpcodes()) + opcode.selectionModel.select(OpcodeUtil.OPCODE[instruction.opcode]) + add(Label(i18n("instruction.opcode")), opcode) + } + } + + fun add(name: Node, control: Node) { + add(name) + add(control, "wrap") + } + + fun getOpcode(): Int { + if (opcode.selectionModel.selectedItem == null) { + throw NullPointerException("unselect opcode") + } + return OpcodeUtil.reverse(OpcodeUtil.OPCODE)[opcode.selectionModel.selectedItem]!! + } + + abstract fun getOpcodes(): List +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/FieldInstructionPane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/FieldInstructionPane.kt new file mode 100644 index 0000000..d20c452 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/FieldInstructionPane.kt @@ -0,0 +1,57 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.instruction + +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.Label +import javafx.scene.control.TextField +import org.objectweb.asm.tree.FieldInsnNode + +/** + * @author Enaium + * @since 2.0.0 + */ +class FieldInstructionPane(instruction: FieldInsnNode) : AbstractInstructionPane(instruction) { + + init { + val owner = TextField(instruction.owner) + val name = TextField(instruction.name) + val description = TextField(instruction.desc) + + add(Label(i18n("instruction.owner")), owner) + add(Label(i18n("instruction.name")), name) + add(Label(i18n("instruction.description")), description) + + confirm = { + instruction.opcode = getOpcode() + instruction.owner = owner.text + instruction.name = name.text + instruction.desc = description.text + true + } + + } + + override fun getOpcodes(): List { + return listOf( + "GETSTATIC", + "PUTSTATIC", + "GETFIELD", + "PUTFIELD" + ) + } +} diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/FrameInstructionPane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/FrameInstructionPane.kt new file mode 100644 index 0000000..fe57e7a --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/FrameInstructionPane.kt @@ -0,0 +1,58 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.instruction + +import cn.enaium.joe.core.util.OpcodeUtil +import cn.enaium.joe.ui.dialog.ConfirmDialog +import cn.enaium.joe.ui.pane.confirm.ConfirmPane +import cn.enaium.joe.ui.pane.confirm.FrameListEditPane +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.Button +import javafx.scene.control.ComboBox +import javafx.scene.control.Label +import org.objectweb.asm.tree.FrameNode + +/** + * @author Enaium + * @since 2.0.0 + */ +class FrameInstructionPane(instruction: FrameNode) : AbstractInstructionPane(instruction) { + init { + val frame = ComboBox() + frame.selectionModel.select(OpcodeUtil.FRAME[instruction.type]) + frame.items.addAll(OpcodeUtil.FRAME.values) + add(Label(i18n("instruction.type")), frame) + add(Label(i18n("instruction.localOrStack")), Button(i18n("button.edit")).apply { + setOnAction { + ConfirmDialog(FrameListEditPane(instruction)).show() + } + }) + + confirm = { + if (frame.value != null) { + instruction.type = OpcodeUtil.reverse(OpcodeUtil.FRAME)[frame.value]!! + true + } else { + false + } + } + } + + override fun getOpcodes(): List { + return emptyList() + } +} diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/IncrInstructionPane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/IncrInstructionPane.kt new file mode 100644 index 0000000..e31a384 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/IncrInstructionPane.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.instruction + +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.Label +import javafx.scene.control.Spinner +import org.objectweb.asm.tree.IincInsnNode + +/** + * @author Enaium + * @since 2.0.0 + */ +class IncrInstructionPane(instruction: IincInsnNode) : AbstractInstructionPane(instruction) { + init { + val varIndex = Spinner(0, Int.MAX_VALUE, instruction.`var`) + val incr = Spinner(0, Int.MAX_VALUE, instruction.incr) + add(Label(i18n("instruction.varIndex")), varIndex) + add(Label(i18n("instruction.incr")), incr) + confirm = { + instruction.`var` = varIndex.value + instruction.incr = incr.value + true + } + } + + override fun getOpcodes(): List { + return listOf( + "IINC" + ) + } +} diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/InstructionPane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/InstructionPane.kt new file mode 100644 index 0000000..64b2584 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/InstructionPane.kt @@ -0,0 +1,148 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.instruction + +import org.objectweb.asm.tree.AbstractInsnNode + +/** + * @author Enaium + * @since 2.0.0 + */ +class InstructionPane(instruction: AbstractInsnNode) : AbstractInstructionPane(instruction) { + + init { + confirm = { + with(instruction.javaClass.superclass.getDeclaredField("opcode")) { + isAccessible = true + set(instruction, getOpcode()) + } + true + } + } + + override fun getOpcodes(): List { + return listOf( + "NOP", + "ACONST_NULL", + "ICONST_M1", + "ICONST_0", + "ICONST_1", + "ICONST_2", + "ICONST_3", + "ICONST_4", + "ICONST_5", + "LCONST_0", + "LCONST_1", + "FCONST_0", + "FCONST_1", + "FCONST_2", + "DCONST_0", + "DCONST_1", + "IALOAD", + "LALOAD", + "FALOAD", + "DALOAD", + "AALOAD", + "BALOAD", + "CALOAD", + "SALOAD", + "IASTORE", + "LASTORE", + "FASTORE", + "DASTORE", + "AASTORE", + "BASTORE", + "CASTORE", + "SASTORE", + "POP", + "POP2", + "DUP", + "DUP_X1", + "DUP_X2", + "DUP2", + "DUP2_X1", + "DUP2_X2", + "SWAP", + "IADD", + "LADD", + "FADD", + "DADD", + "ISUB", + "LSUB", + "FSUB", + "DSUB", + "IMUL", + "LMUL", + "FMUL", + "DMUL", + "IDIV", + "LDIV", + "FDIV", + "DDIV", + "IREM", + "LREM", + "FREM", + "DREM", + "INEG", + "LNEG", + "FNEG", + "DNEG", + "ISHL", + "LSHL", + "ISHR", + "LSHR", + "IUSHR", + "LUSHR", + "IAND", + "LAND", + "IOR", + "LOR", + "IXOR", + "LXOR", + "I2L", + "I2F", + "I2D", + "L2I", + "L2F", + "L2D", + "F2I", + "F2L", + "F2D", + "D2I", + "D2L", + "D2F", + "I2B", + "I2C", + "I2S", + "LCMP", + "FCMPL", + "FCMPG", + "DCMPL", + "DCMPG", + "IRETURN", + "LRETURN", + "FRETURN", + "DRETURN", + "ARETURN", + "RETURN", + "ARRAYLENGTH", + "ATHROW", + "MONITORENTER", + "MONITOREXIT", + ) + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/IntInstructionPane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/IntInstructionPane.kt new file mode 100644 index 0000000..089b9c2 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/IntInstructionPane.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.instruction + +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.Label +import javafx.scene.control.Spinner +import org.objectweb.asm.tree.IntInsnNode + +/** + * @author Enaium + * @since 2.0.0 + */ +class IntInstructionPane(instruction: IntInsnNode) : AbstractInstructionPane(instruction) { + init { + val operand = Spinner(0, Int.MAX_VALUE, instruction.operand) + add(Label(i18n("instruction.operand")), operand) + confirm = { + instruction.opcode = getOpcode() + instruction.operand = operand.value + true + } + } + + override fun getOpcodes(): List { + return listOf( + "BIPUSH", + "SIPUSH", + "NEWARRAY" + ) + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/InvokeDynamicInstructionPane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/InvokeDynamicInstructionPane.kt new file mode 100644 index 0000000..ebefaee --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/InvokeDynamicInstructionPane.kt @@ -0,0 +1,71 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.instruction + +import cn.enaium.joe.core.wrapper.Wrapper +import cn.enaium.joe.ui.dialog.ConfirmDialog +import cn.enaium.joe.ui.pane.confirm.BootstrapMethodArgumentEditPane +import cn.enaium.joe.ui.pane.confirm.HandleEditPane +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.Button +import javafx.scene.control.Label +import javafx.scene.control.TextField +import org.objectweb.asm.tree.InvokeDynamicInsnNode + +class InvokeDynamicInstructionPane(instruction: InvokeDynamicInsnNode) : AbstractInstructionPane(instruction) { + + init { + val name = TextField(instruction.name) + val description = TextField(instruction.desc) + + add(Label(i18n("instruction.name")), name) + add(Label(i18n("instruction.description")), description) + add(Label(i18n("instruction.bootstrapMethod")), Button(i18n("button.edit")).apply { + setOnAction { + val handleWrapper = Wrapper(instruction.bsm) + ConfirmDialog(HandleEditPane(handleWrapper)).apply { + confirm = { + instruction.bsm = handleWrapper.wrapper + } + }.show() + } + }) + add(Label(i18n("instruction.bootstrapMethodArgument")), Button(i18n("button.edit")).apply { + setOnAction { + val anyArrayWrapper = Wrapper(instruction.bsmArgs) + ConfirmDialog(BootstrapMethodArgumentEditPane(anyArrayWrapper)).apply { + confirm = { + instruction.bsmArgs = anyArrayWrapper.wrapper + } + }.show() + } + }) + + + + + confirm = { + instruction.name = name.text + instruction.desc = description.text + true + } + } + + override fun getOpcodes(): List { + return listOf("INVOKEDYNAMIC") + } +} diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/JumpInstructionPane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/JumpInstructionPane.kt new file mode 100644 index 0000000..a3265f4 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/JumpInstructionPane.kt @@ -0,0 +1,65 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.instruction + +import cn.enaium.joe.ui.control.LabelNodeComboBox +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.Label +import org.objectweb.asm.tree.JumpInsnNode + +/** + * @author Enaium + * @since 2.0.0 + */ +class JumpInstructionPane(instruction: JumpInsnNode) : AbstractInstructionPane(instruction) { + + init { + val labelComboBox = LabelNodeComboBox(instruction.label) + add(Label(i18n("instruction.label")), labelComboBox) + confirm = { + labelComboBox.selectionModel.selectedItem?.let { + instruction.opcode = getOpcode() + instruction.label = labelComboBox.selectionModel.selectedItem.wrapper + true + } + false + } + } + + override fun getOpcodes(): List { + return listOf( + "IFEQ", + "IFNE", + "IFLT", + "IFGE", + "IFGT", + "IFLE", + "IF_ICMPEQ", + "IF_ICMPNE", + "IF_ICMPLT", + "IF_ICMPGE", + "IF_ICMPGT", + "IF_ICMPLE", + "IF_ACMPEQ", + "IF_ACMPNE", + "GOTO", + "JSR", + "IFNULL", + "IFNONNULL" + ) + } +} diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/LDCInstructionPane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/LDCInstructionPane.kt new file mode 100644 index 0000000..6ab3f2b --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/LDCInstructionPane.kt @@ -0,0 +1,123 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.instruction + +import cn.enaium.joe.core.wrapper.Wrapper +import cn.enaium.joe.ui.dialog.ConfirmDialog +import cn.enaium.joe.ui.pane.confirm.HandleEditPane +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.Button +import javafx.scene.control.ComboBox +import javafx.scene.control.Label +import javafx.scene.control.TextField +import org.objectweb.asm.Handle +import org.objectweb.asm.Type +import org.objectweb.asm.tree.LdcInsnNode + +/** + * @author Enaium + * @since 2.0.0 + */ +class LDCInstructionPane(instruction: LdcInsnNode) : AbstractInstructionPane(instruction) { + init { + val type = ComboBox().apply { + items.addAll("String", "float", "double", "int", "long", "Class", "Handle") + } + add(Label(i18n("instruction.type")), type) + var handle: Handle? = null + when (instruction.cst) { + is String -> { + type.selectionModel.select("String") + } + + is Float -> { + type.selectionModel.select("float") + } + + is Double -> { + type.selectionModel.select("double") + } + + is Int -> { + type.selectionModel.select("int") + } + + is Long -> { + type.selectionModel.select("long") + } + + is Type -> { + type.selectionModel.select("Class") + } + + is Handle -> { + type.selectionModel.select("Handle") + handle = instruction.cst as Handle + } + } + + handle?.let { + add(Label(i18n("instruction.handle")), Button(i18n("button.edit")).apply { + setOnAction { + val handleWrapper = Wrapper(handle) + ConfirmDialog(HandleEditPane(handleWrapper)).apply { + confirm = { + instruction.cst = handleWrapper.wrapper + } + }.show() + } + }) + } ?: let { + val ldc = TextField(instruction.cst.toString()) + add(Label(i18n("instruction.var")), ldc) + confirm = { + type.selectionModel.selectedItem?.let { + when (type.selectionModel.selectedItem) { + "String" -> { + instruction.cst = ldc.text + } + + "float" -> { + instruction.cst = ldc.text.toFloat() + } + + "double" -> { + instruction.cst = ldc.text.toDouble() + } + + "int" -> { + instruction.cst = ldc.text.toInt() + } + + "long" -> { + instruction.cst = ldc.text.toLong() + } + + "Class" -> { + instruction.cst = Type.getType(ldc.text) + } + } + } + true + } + } + } + + override fun getOpcodes(): List { + return listOf("LDC") + } +} diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/LineInstructionPane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/LineInstructionPane.kt new file mode 100644 index 0000000..0275fe4 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/LineInstructionPane.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.instruction + +import cn.enaium.joe.ui.control.LabelNodeComboBox +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.Label +import javafx.scene.control.Spinner +import org.objectweb.asm.tree.LineNumberNode + +/** + * @author Enaium + * @since 2.0.0 + */ +class LineInstructionPane(instruction: LineNumberNode) : AbstractInstructionPane(instruction) { + init { + val line = Spinner(0, Int.MAX_VALUE, instruction.line) + val start = LabelNodeComboBox(instruction.start) + add(Label(i18n("instruction.line")), line) + add(Label(i18n("instruction.start")), start) + + confirm = { + instruction.line = line.value + instruction.start = start.selectionModel.selectedItem.wrapper + true + } + } + + override fun getOpcodes(): List { + return emptyList() + } +} diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/LookupSwitchInstructionPane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/LookupSwitchInstructionPane.kt new file mode 100644 index 0000000..341db2b --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/LookupSwitchInstructionPane.kt @@ -0,0 +1,49 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.instruction + +import cn.enaium.joe.ui.control.LabelNodeComboBox +import cn.enaium.joe.ui.dialog.ConfirmDialog +import cn.enaium.joe.ui.pane.confirm.LookupSwitchEditPane +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.Button +import javafx.scene.control.Label +import org.objectweb.asm.tree.LookupSwitchInsnNode + +/** + * @author Enaium + * @since 2.0.0 + */ +class LookupSwitchInstructionPane(instruction: LookupSwitchInsnNode) : AbstractInstructionPane(instruction) { + init { + val dflt = LabelNodeComboBox(instruction.dflt) + add(Label(i18n("instruction.default")), dflt) + add(Label(i18n("instruction.keyOrLabel")), Button(i18n("button.edit")).apply { + setOnAction { + ConfirmDialog(LookupSwitchEditPane(instruction.keys, instruction.labels)).show() + } + }) + confirm = { + instruction.dflt = dflt.selectionModel.selectedItem.wrapper + true + } + } + + override fun getOpcodes(): List { + return listOf("LOOKUPSWITCH") + } +} diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/MethodInstructionPane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/MethodInstructionPane.kt new file mode 100644 index 0000000..4fd1761 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/MethodInstructionPane.kt @@ -0,0 +1,65 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.instruction + +import cn.enaium.joe.ui.util.i18n +import javafx.geometry.Pos +import javafx.scene.control.CheckBox +import javafx.scene.control.Label +import javafx.scene.control.TextField +import org.objectweb.asm.tree.MethodInsnNode + +/** + * @author Enaium + * @since 2.0.0 + */ +class MethodInstructionPane(instruction: MethodInsnNode) : AbstractInstructionPane(instruction) { + + init { + val owner = TextField(instruction.owner) + val name = TextField(instruction.name) + val description = TextField(instruction.desc) + val isInterface = CheckBox().apply { + isSelected = instruction.itf + alignment = Pos.CENTER_RIGHT + } + + add(Label(i18n("instruction.owner")), owner) + add(Label(i18n("instruction.name")), name) + add(Label(i18n("instruction.description")), description) + add(Label(i18n("instruction.interface")), isInterface) + + + confirm = { + instruction.opcode = getOpcode() + instruction.owner = owner.text + instruction.name = name.text + instruction.desc = description.text + instruction.itf = isInterface.isSelected + true + } + } + + override fun getOpcodes(): List { + return listOf( + "GETSTATIC", + "PUTSTATIC", + "GETFIELD", + "PUTFIELD" + ) + } +} diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/MultiANewArrayInstructionPane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/MultiANewArrayInstructionPane.kt new file mode 100644 index 0000000..6eb4e3d --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/MultiANewArrayInstructionPane.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.instruction + +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.Label +import javafx.scene.control.Spinner +import javafx.scene.control.TextField +import org.objectweb.asm.tree.MultiANewArrayInsnNode + +/** + * @author Enaium + * @since 2.0.0 + */ +class MultiANewArrayInstructionPane(instruction: MultiANewArrayInsnNode) : AbstractInstructionPane(instruction) { + init { + val description = TextField(instruction.desc) + add(Label(i18n("instruction.description")), description) + val dims = Spinner(0, Int.MAX_VALUE, instruction.dims) + add(Label(i18n("instruction.dimension")), dims) + confirm = { + instruction.desc = description.text + instruction.dims = dims.value + true + } + } + + override fun getOpcodes(): List { + return listOf("MULTIANEWARRAY") + } +} diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/TableSwitchInstructionPane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/TableSwitchInstructionPane.kt new file mode 100644 index 0000000..5eaef6c --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/TableSwitchInstructionPane.kt @@ -0,0 +1,57 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.instruction + +import cn.enaium.joe.core.util.OpcodeUtil +import cn.enaium.joe.ui.control.LabelNodeComboBox +import cn.enaium.joe.ui.dialog.ConfirmDialog +import cn.enaium.joe.ui.pane.confirm.LabelListEditPane +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.Button +import javafx.scene.control.Label +import javafx.scene.control.Spinner +import org.objectweb.asm.tree.TableSwitchInsnNode + +/** + * @author Enaium + * @since 2.0.0 + */ +class TableSwitchInstructionPane(instruction: TableSwitchInsnNode) : AbstractInstructionPane(instruction) { + init { + val min = Spinner(0, Int.MAX_VALUE, instruction.min) + add(Label(i18n("instruction.min")), min) + val max = Spinner(0, Int.MAX_VALUE, instruction.max) + add(Label(i18n("instruction.max")), max) + val dflt = LabelNodeComboBox(instruction.dflt) + add(Label(i18n("instruction.default")), dflt) + add(Label(i18n("instruction.keyOrLabel")), Button(i18n("button.edit")).apply { + setOnAction { + ConfirmDialog(LabelListEditPane(instruction.labels, OpcodeUtil.getInstructionList(instruction))).show() + } + }) + confirm = { + instruction.min = min.value + instruction.max = max.value + instruction.dflt = dflt.selectionModel.selectedItem.wrapper + true + } + } + + override fun getOpcodes(): List { + return listOf("TABLESWITCH") + } +} diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/TypeInstructionPane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/TypeInstructionPane.kt new file mode 100644 index 0000000..5ad4860 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/TypeInstructionPane.kt @@ -0,0 +1,48 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.instruction + +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.Label +import javafx.scene.control.TextField +import org.objectweb.asm.tree.TypeInsnNode + +/** + * @author Enaium + * @since 2.0.0 + */ +class TypeInstructionPane(instruction: TypeInsnNode) : AbstractInstructionPane(instruction) { + + init { + val description = TextField(instruction.desc) + add(Label(i18n("instruction.description")), description) + confirm = { + instruction.opcode = getOpcode() + instruction.desc = description.text + true + } + } + + override fun getOpcodes(): List { + return listOf( + "NEW", + "ANEWARRAY", + "CHECKCAST", + "INSTANCEOF" + ) + } +} diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/VarInstructionPane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/VarInstructionPane.kt new file mode 100644 index 0000000..05f8d4c --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/instruction/VarInstructionPane.kt @@ -0,0 +1,57 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.instruction + +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.Label +import javafx.scene.control.Spinner +import org.objectweb.asm.tree.AbstractInsnNode +import org.objectweb.asm.tree.VarInsnNode +import java.util.concurrent.Callable + +/** + * @author Enaium + * @since 2.0.0 + */ +class VarInstructionPane(instruction: VarInsnNode) : AbstractInstructionPane(instruction) { + + init { + val spinner = Spinner(0, Int.MAX_VALUE, instruction.`var`) + add(Label(i18n("instruction.var")), spinner) + confirm = { + instruction.opcode = getOpcode() + instruction.`var` = spinner.value + true + } + } + + override fun getOpcodes(): List { + return listOf( + "ILOAD", + "LLOAD", + "FLOAD", + "DLOAD", + "ALOAD", + "ISTORE", + "LSTORE", + "FSTORE", + "DSTORE", + "ASTORE", + "RET" + ) + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/method/InfoPane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/method/InfoPane.kt new file mode 100644 index 0000000..ffda672 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/method/InfoPane.kt @@ -0,0 +1,99 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.method + +import cn.enaium.joe.ui.dialog.AnnotationDialog +import cn.enaium.joe.ui.util.i18n +import javafx.scene.control.Button +import javafx.scene.control.Label +import javafx.scene.control.TextField +import org.objectweb.asm.tree.MethodNode +import org.tbee.javafx.scene.layout.MigPane +import java.lang.String +import java.util.* +import kotlin.Any +import kotlin.apply + + +/** + * @author Enaium + * @since 2.0.0 + */ +class InfoPane(methodNode: MethodNode) : MigPane("fillx", "[fill][fill]") { + init { + add(Label(i18n("class.info.name"))) + val name = TextField(methodNode.name) + add(name, "wrap") + add(Label(i18n("class.info.description"))) + val description = TextField(methodNode.desc) + add(description, "wrap") + add(Label(i18n("class.info.access"))) + val access = TextField(String.valueOf(methodNode.access)) + add(access, "wrap") + add(Label(i18n("class.info.signature"))) + val signature = TextField(methodNode.signature) + add(signature, "wrap") + add(Label(i18n("class.info.exceptions"))) + val exceptions = TextField(methodNode.exceptions.joinToString(";")) + add(exceptions, "wrap") + add(Label(i18n("class.info.visibleAnnotation"))) + add(Button(i18n("button.edit")).apply { + setOnAction { + methodNode.visibleAnnotations?.let { + AnnotationDialog(methodNode.visibleAnnotations).show() + } + } + }, "wrap") + add(Label(i18n("class.info.invisibleAnnotation"))) + add(Button(i18n("button.edit")).apply { + setOnAction { + methodNode.invisibleAnnotations?.let { + AnnotationDialog(methodNode.invisibleAnnotations).show() + } + } + }, "wrap") + add(Button("button.save").apply { + setOnAction { + if (name.text?.isNotBlank() == true) { + methodNode.name = name.text + } + + if (description.text?.isNotBlank() == true) { + methodNode.desc = description.text + } else { + methodNode.desc = null + } + + if (access.text?.isNotBlank() == true) { + methodNode.access = access.text.toInt() + } + + if (signature.text?.isNotBlank() == true) { + methodNode.signature = signature.text + } else { + methodNode.signature = null + } + + if (signature.text?.isNotBlank() == true) { + methodNode.exceptions = signature.text.split(";") + } else { + methodNode.exceptions = emptyList() + } + } + }, "span 2") + } +} \ No newline at end of file diff --git a/src/main/java/cn/enaium/joe/gui/panel/menu/search/LdcMenuItem.java b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/method/MethodTabPane.kt similarity index 52% rename from src/main/java/cn/enaium/joe/gui/panel/menu/search/LdcMenuItem.java rename to ui/src/main/kotlin/cn/enaium/joe/ui/pane/method/MethodTabPane.kt index 7494e01..8a08065 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/menu/search/LdcMenuItem.java +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/method/MethodTabPane.kt @@ -14,28 +14,28 @@ * limitations under the License. */ -package cn.enaium.joe.gui.panel.menu.search; +package cn.enaium.joe.ui.pane.method -import cn.enaium.joe.JavaOctetEditor; -import cn.enaium.joe.dialog.search.SearchLdcDialog; -import cn.enaium.joe.jar.Jar; -import cn.enaium.joe.util.LangUtil; - -import javax.swing.*; +import cn.enaium.joe.ui.control.MethodInstructionList +import javafx.scene.control.Tab +import javafx.scene.control.TabPane +import org.objectweb.asm.tree.MethodNode /** * @author Enaium + * @since 2.0.0 */ -public class LdcMenuItem extends JMenuItem { - public LdcMenuItem() { - super(LangUtil.i18n("menu.search.ldc")); - addActionListener(e -> { - Jar jar = JavaOctetEditor.getInstance().getJar(); - if (jar == null) { - return; +class MethodTabPane(methodNode: MethodNode) : TabPane() { + init { + tabs.addAll( + Tab("Instruction").apply { + isClosable = false + content = MethodInstructionList(methodNode) + }, + Tab("Info").apply { + isClosable = false + content = InfoPane(methodNode) } - - new SearchLdcDialog().setVisible(true); - }); + ) } -} +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/side/InheritSidePane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/side/InheritSidePane.kt new file mode 100644 index 0000000..cd12860 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/side/InheritSidePane.kt @@ -0,0 +1,122 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.side + +import cn.enaium.joe.core.util.ASMUtil +import cn.enaium.joe.core.util.ReflectUtil +import cn.enaium.joe.ui.Instance.jar +import cn.enaium.joe.ui.JavaOctetEditor.Companion.event +import cn.enaium.joe.ui.cell.FileTreeCell +import cn.enaium.joe.ui.control.tree.AnyTreeItem +import cn.enaium.joe.ui.control.tree.ClassTreeItem +import cn.enaium.joe.ui.event.ContentTabChange +import cn.enaium.joe.ui.event.SelectTreeItem +import cn.enaium.joe.ui.pane.content.classes.ClassTabPane +import cn.enaium.joe.ui.util.expandAll +import javafx.scene.control.ToggleButton +import javafx.scene.control.TreeItem +import javafx.scene.control.TreeView +import javafx.scene.layout.BorderPane +import org.objectweb.asm.ClassReader +import org.objectweb.asm.tree.ClassNode + +/** + * @author Enaium + * @since 2.0.0 + */ +class InheritSidePane : BorderPane() { + + var classNode: ClassNode? = null + + init { + val inherit = TreeView() + inherit.isShowRoot = false + + + inherit.setCellFactory { + FileTreeCell() + } + + fun set(parent: Boolean) { + inherit.root = TreeItem() + inherit.root.children.add(ClassTreeItem(classNode!!).apply { + recursion(this, parent) + }) + expandAll(inherit.root) + } + + inherit.setOnMouseClicked { + if (it.clickCount == 2) { + inherit.selectionModel.selectedItem?.let { select -> + event.call(SelectTreeItem(select as AnyTreeItem)) + } + } + } + + event.register { event -> + event.new?.let { + inherit.root = TreeItem() + if (event.new.content is ClassTabPane) { + classNode = (event.new.content as ClassTabPane).classTreeItem.classNode + set(false) + } else { + classNode = null + inherit.root = TreeItem() + } + } + } + center = inherit + bottom = ToggleButton("Parent").apply { + setOnAction { + if (isSelected) { + set(true) + } else { + set(false) + } + } + } + } + + + private fun recursion(classTreeItem: ClassTreeItem, parent: Boolean) { + val classNode = classTreeItem.classNode + if (parent) { + ASMUtil.getParentClass(classNode).forEach { + var newChild: ClassTreeItem? = null + if (jar!!.classes.containsKey("$it.class")) { + newChild = ClassTreeItem(jar!!.classes["$it.class"]!!) + } else if (ReflectUtil.classHas(it.replace("/", "."))) { + newChild = ClassTreeItem(ASMUtil.acceptClassNode(ClassReader(it))) + } + + newChild?.let { + classTreeItem.children.add(newChild) + recursion(newChild, true) + } + } + } else { + jar!!.classes.values.forEach { + val parentClass = ASMUtil.getParentClass(it) + if (parentClass.contains(classNode.name)) { + val newChild = ClassTreeItem(it) + classTreeItem.children.add(newChild) + recursion(newChild, false) + } + } + } + } +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/pane/side/MemberSidePane.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/side/MemberSidePane.kt new file mode 100644 index 0000000..42b9377 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/side/MemberSidePane.kt @@ -0,0 +1,71 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.pane.side + +import cn.enaium.joe.ui.JavaOctetEditor.Companion.event +import cn.enaium.joe.ui.cell.MemberListCell +import cn.enaium.joe.ui.dialog.Dialog +import cn.enaium.joe.ui.event.ContentTabChange +import cn.enaium.joe.ui.pane.content.classes.ClassTabPane +import cn.enaium.joe.ui.pane.method.MethodTabPane +import javafx.scene.control.ListView +import javafx.scene.layout.BorderPane +import org.objectweb.asm.tree.ClassNode +import org.objectweb.asm.tree.MethodNode + +/** + * @author Enaium + * @since 2.0.0 + */ +class MemberSidePane : BorderPane() { + init { + val memberList = ListView>() + + + memberList.setCellFactory { + MemberListCell() + } + + event.register { event -> + event.new?.let { + if (event.new.content is ClassTabPane) { + val classNode = (event.new.content as ClassTabPane).classTreeItem.classNode + memberList.items.clear() + classNode.fields.forEach { field -> + memberList.items.add(Pair(classNode, field)) + } + classNode.methods.forEach { method -> + memberList.items.add(Pair(classNode, method)) + } + } + } + } + + memberList.setOnMouseClicked { + if (it.clickCount == 2) { + val second = memberList.selectionModel.selectedItem.second + if (second is MethodNode) { + Dialog("Method").apply { + content = MethodTabPane(second) + }.show() + } + } + } + + center = memberList + } +} \ No newline at end of file diff --git a/src/test/java/cn/enaium/joe/asm/GenerateInstructionTypeSwitchTest.java b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/side/SidePane.kt similarity index 51% rename from src/test/java/cn/enaium/joe/asm/GenerateInstructionTypeSwitchTest.java rename to ui/src/main/kotlin/cn/enaium/joe/ui/pane/side/SidePane.kt index ead757a..ef2b6f6 100644 --- a/src/test/java/cn/enaium/joe/asm/GenerateInstructionTypeSwitchTest.java +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/pane/side/SidePane.kt @@ -14,25 +14,26 @@ * limitations under the License. */ -package cn.enaium.joe.asm; +package cn.enaium.joe.ui.pane.side -import org.junit.jupiter.api.Test; -import org.objectweb.asm.tree.AbstractInsnNode; - -import java.lang.reflect.Field; +import cn.enaium.joe.ui.util.i18n +import cn.enaium.joe.ui.util.loadSVG +import javafx.scene.control.Accordion +import javafx.scene.control.TitledPane +import javafx.scene.layout.BorderPane /** * @author Enaium */ -class GenerateInstructionTypeSwitchTest { - @Test - public void test() { - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append("switch (i) {").append("\n"); - for (Field field : AbstractInsnNode.class.getFields()) { - stringBuilder.append(String.format("case AbstractInsnNode.%s: break;", field.getName())); +class SidePane : BorderPane() { + init { + center = Accordion().apply { + panes.add(TitledPane(i18n("side.member"), MemberSidePane()).apply { + graphic = loadSVG("icons/structure.svg") + }) + panes.add(TitledPane(i18n("side.inherit"), InheritSidePane()).apply { + graphic = loadSVG("icons/inherit.svg") + }) } - stringBuilder.append("}"); - System.out.println(stringBuilder); } -} +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/util/Async.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/util/Async.kt new file mode 100644 index 0000000..29aaccc --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/util/Async.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.util + +import javafx.application.Platform +import java.util.concurrent.Executors +import java.util.function.Consumer +import java.util.function.Supplier + +/** + * @author Enaium + * @author 2.0.0 + */ +fun runLater(run: Runnable, ui: Runnable) { + val executorService = Executors.newSingleThreadExecutor() + executorService.execute { + run.run() + if (ui != null) { + Platform.runLater(ui) + } + } +} + +fun runLater(supplier: Supplier, ui: Consumer) { + val executorService = Executors.newSingleThreadExecutor() + executorService.execute { + val t: T = supplier.get() + if (ui != null) { + Platform.runLater { ui.accept(t) } + } + } +} \ No newline at end of file diff --git a/src/main/java/cn/enaium/joe/annotation/NoUI.java b/ui/src/main/kotlin/cn/enaium/joe/ui/util/ColorUtil.kt similarity index 61% rename from src/main/java/cn/enaium/joe/annotation/NoUI.java rename to ui/src/main/kotlin/cn/enaium/joe/ui/util/ColorUtil.kt index c899119..45ae70e 100644 --- a/src/main/java/cn/enaium/joe/annotation/NoUI.java +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/util/ColorUtil.kt @@ -13,19 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package cn.enaium.joe.ui.util -package cn.enaium.joe.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; +import javafx.scene.paint.Color /** * @author Enaium - * @since 0.9.0 + * @since 2.0.0 */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.FIELD) -public @interface NoUI { -} +object ColorUtil { + val opcode: Color = Color.DARKVIOLET + val name: Color = Color.INDIANRED + val desc: Color = Color.KHAKI + val base: Color = Color.LEMONCHIFFON + val string: Color = Color.LIGHTGREEN + val bool: Color = Color.MEDIUMORCHID + val other: Color = Color.MEDIUMSLATEBLUE +} \ No newline at end of file diff --git a/src/main/java/cn/enaium/joe/gui/component/InstructionComboBox.java b/ui/src/main/kotlin/cn/enaium/joe/ui/util/HtmlUtil.kt similarity index 60% rename from src/main/java/cn/enaium/joe/gui/component/InstructionComboBox.java rename to ui/src/main/kotlin/cn/enaium/joe/ui/util/HtmlUtil.kt index 2df1d4c..8dedec0 100644 --- a/src/main/java/cn/enaium/joe/gui/component/InstructionComboBox.java +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/util/HtmlUtil.kt @@ -13,19 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package cn.enaium.joe.ui.util -package cn.enaium.joe.gui.component; - -import javax.swing.*; +import java.awt.Color /** * @author Enaium - * @since 0.9.0 + * @since 2.0.0 */ -public class InstructionComboBox extends JComboBox { - public InstructionComboBox() { - super(new String[]{"Opcode", "Int", "Var", "Type", "Field", "Method", "InvokeDynamic", "Jump", "Label", "LDC", "Incr", "TableSwitch", "LookupSwitch", "MultiANewArray", "Frame", "Line"}); - } +fun toHtml(text: String?): String { + return String.format("%s", text) } +fun setColor(text: String?, color: Color): String { + return String.format("%s", color.red, color.green, color.blue, text) +} +fun remove(text: String): String { + return text.replace("<[^>]+>".toRegex(), "") +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/util/IOUtil.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/util/IOUtil.kt new file mode 100755 index 0000000..32abb4d --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/util/IOUtil.kt @@ -0,0 +1,74 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.util + +import java.io.ByteArrayInputStream +import java.io.ByteArrayOutputStream +import java.io.IOException +import java.io.InputStream +import java.nio.charset.StandardCharsets +import javax.imageio.ImageIO + + +/** + * @author Enaium + * @since 2.0.0 + */ + +fun getString(inputStream: InputStream): String { + return String(getBytes(inputStream), StandardCharsets.UTF_8) +} + +fun getBytes(inputStream: InputStream): ByteArray { + val byteOutputStream = ByteArrayOutputStream() + val buffer = ByteArray(1024 * 4) + var n: Int + while (-1 != inputStream.read(buffer).also { n = it }) { + byteOutputStream.write(buffer, 0, n) + } + inputStream.close() + return byteOutputStream.toByteArray() +} + +fun isImage(data: ByteArray): Boolean { + val byteArrayInputStream = ByteArrayInputStream(data) + return try { + val read = ImageIO.read(byteArrayInputStream) + read != null + } catch (ignore: Throwable) { + false + } finally { + try { + byteArrayInputStream.close() + } catch (e: IOException) { + + } + } +} + +fun isText(byteArray: ByteArray): Boolean { + var total: Int = byteArray.size + if (total >= 8000) { + total = 8000 + } + for (i in 0 until total) { + if (byteArray[i].toInt().toChar() == '\u0000') { + return false + } + } + return true +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/util/ImageUtil.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/util/ImageUtil.kt new file mode 100755 index 0000000..f512416 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/util/ImageUtil.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.util + +import javafx.scene.image.ImageView +import org.girod.javafx.svgimage.SVGImage +import org.girod.javafx.svgimage.SVGLoader + +/** + * @author Enaium + * @since 2.0.0 + */ +fun loadSVG(path: String): SVGImage { + return SVGLoader.load(object {}::class.java.classLoader.getResource(path),12.0) +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/util/LangUtil.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/util/LangUtil.kt new file mode 100755 index 0000000..243fe28 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/util/LangUtil.kt @@ -0,0 +1,66 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.util + +import cn.enaium.joe.core.config.extend.ApplicationConfig +import cn.enaium.joe.core.config.value.ModeValue +import cn.enaium.joe.ui.JavaOctetEditor +import com.google.gson.Gson +import com.google.gson.JsonObject +import org.pmw.tinylog.Logger +import java.io.IOException +import java.util.* + +/** + * @author Enaium + * @since 2.0.0 + */ +fun i18n(key: String, vararg arguments: Any): String { + val locale: Locale = Locale.getDefault() + var lang: String = locale.language + "_" + locale.country + val language: ModeValue = JavaOctetEditor.config.getByClass( + ApplicationConfig::class.java).language + if (!language.value.equals("System")) { + lang = language.value + } + try { + val text: String + val url = object {}::class.java.getResource("/i18n/$lang.json") + text = if (url != null) { + getString(url.openStream()) + } else { + getString(object {}::class.java.getResourceAsStream("/i18n/en_US.json")!!) + } + val jsonObject: JsonObject = Gson().fromJson(text, JsonObject::class.java) + try { + return java.lang.String.format(jsonObject.get(key).asString, arguments) + } catch (e: NullPointerException) { + Logger.warn(java.lang.String.format("Lang not found \" %s \" ", key)) + try { + return java.lang.String.format( + Gson().fromJson(text, JsonObject::class.java).get(key).asString, + arguments + ) + } catch (ex: NullPointerException) { + error(NullPointerException(java.lang.String.format("not found key ' %s ' in en_us", key))) + } + } + } catch (e: IOException) { + error(e) + } + return key +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/util/MessageUtil.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/util/MessageUtil.kt new file mode 100755 index 0000000..9b755d3 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/util/MessageUtil.kt @@ -0,0 +1,54 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.util + +import javafx.scene.control.Alert +import javafx.scene.control.TextArea +import java.io.PrintWriter +import java.io.StringWriter + +/** + * @author Enaium + * @author 2.0.0 + */ +fun error(throwable: Throwable) { + throwable.printStackTrace() + val alert = Alert(Alert.AlertType.ERROR) + alert.title = "Error" + alert.contentText = throwable.message + + val out = StringWriter() + throwable.printStackTrace(PrintWriter(out)) + val textArea = TextArea(out.toString()) + textArea.isEditable = false + alert.dialogPane.expandableContent = textArea + alert.show() +} + +fun info(text: String) { + val alert = Alert(Alert.AlertType.INFORMATION) + alert.title = "Info" + alert.contentText = text + alert.show() +} + +fun warning(text: String) { + val alert = Alert(Alert.AlertType.WARNING) + alert.title = "Warning" + alert.contentText = text + alert.show() +} \ No newline at end of file diff --git a/ui/src/main/kotlin/cn/enaium/joe/ui/util/StyleUtil.kt b/ui/src/main/kotlin/cn/enaium/joe/ui/util/StyleUtil.kt new file mode 100644 index 0000000..6b02a58 --- /dev/null +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/util/StyleUtil.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.ui.util + +import javafx.scene.Parent + +/** + * @author Enaium + * @author 2.0.0 + */ +fun addStyle(parent: Parent, path: String) { + parent.stylesheets + .add(object{}::class.java.classLoader.getResource(path)!!.toExternalForm()) +} \ No newline at end of file diff --git a/src/main/java/cn/enaium/joe/config/value/StringSetValue.java b/ui/src/main/kotlin/cn/enaium/joe/ui/util/TreeUtil.kt similarity index 68% rename from src/main/java/cn/enaium/joe/config/value/StringSetValue.java rename to ui/src/main/kotlin/cn/enaium/joe/ui/util/TreeUtil.kt index 0b61c66..32f1329 100644 --- a/src/main/java/cn/enaium/joe/config/value/StringSetValue.java +++ b/ui/src/main/kotlin/cn/enaium/joe/ui/util/TreeUtil.kt @@ -14,17 +14,20 @@ * limitations under the License. */ -package cn.enaium.joe.config.value; +package cn.enaium.joe.ui.util -import java.util.List; -import java.util.Set; +import javafx.scene.control.TreeItem /** * @author Enaium - * @since 0.9.0 + * @since 2.0.0 */ -public class StringSetValue extends Value>{ - public StringSetValue(String name, Set value, String description) { - super(name, value, description); +fun expandAll(treeItem: TreeItem<*>) { + if (!treeItem.isLeaf) { + treeItem.isExpanded = true + treeItem.children.forEach { + it.isExpanded = true + expandAll(it) + } } -} +} \ No newline at end of file diff --git a/src/main/resources/lang/en_US.json b/ui/src/main/resources/i18n/en_US.json old mode 100644 new mode 100755 similarity index 66% rename from src/main/resources/lang/en_US.json rename to ui/src/main/resources/i18n/en_US.json index 3d548e9..4ea8f7a --- a/src/main/resources/lang/en_US.json +++ b/ui/src/main/resources/i18n/en_US.json @@ -2,10 +2,12 @@ "search.ldc.title": "Search LDC", "search.field.title": "Search Field", "search.method.title": "Search Method", + "search.opcode.title": "Search Opcode", "search.owner": "Owner:", "search.name": "Name:", "search.description": "Description:", "search.interface": "Interface:", + "search.opcode": "Opcode:", "about.system": "System", "about.system.description": "Information about the OS", "about.system.name": "Name", @@ -28,34 +30,37 @@ "menu.search.ldc": "LDC", "menu.search.field": "Field", "menu.search.method": "Method", + "menu.search.opcode": "Opcode", "menu.attach": "Attach", "menu.attach.process": "Process", "menu.mapping": "Mapping", "menu.help": "Help", "menu.help.about": "About", "menu.help.contact": "Contact", - "popup.attach.properties": "Properties", - "popup.attach.external": "External", - "popup.instruction.edit": "Edit", - "popup.instruction.clone": "Clone", - "popup.instructions.remove": "Remove", - "popup.instructions.copyText": "Copy Text", - "popup.instructions.insertBefore": "Insert Before", - "popup.instructions.insertAfter": "Insert After", - "popup.instructions.moveUp": "Move Up", - "popup.instructions.moveDown": "Move Down", - "popup.fileTree.expandAll": "Expand All", - "popup.tabbed.closeAll": "Close All", - "popup.tabbed.closeOther": "Close Others", - "popup.tabbed.closeAllLeft": "Close All Left", - "popup.tabbed.closeAllRight": "Close All Right", - "popup.member.callTree": "Call Tree", + "context.attach.properties": "Properties", + "context.attach.external": "External", + "context.instructions.edit": "Edit", + "context.instructions.clone": "Clone", + "context.instructions.remove": "Remove", + "context.instructions.copyText": "Copy Text", + "context.instructions.insertBefore": "Insert Before", + "context.instructions.insertAfter": "Insert After", + "context.instructions.moveUp": "Move Up", + "context.instructions.moveDown": "Move Down", + "context.fileTree.expandAll": "Expand All", + "context.tabbed.closeAll": "Close All", + "context.tabbed.closeOther": "Close Others", + "context.tabbed.closeAllLeft": "Close All Left", + "context.tabbed.closeAllRight": "Close All Right", + "context.result.jump": "Jump to Item", "class.info.name": "Name:", "class.info.sourceFile": "SourceFile:", "class.info.debugFile": "DebugFile:", "class.info.access": "Access:", "class.info.version": "Version:", "class.info.signature": "Signature:", + "class.info.visibleAnnotation": "Visible Annotation:", + "class.info.invisibleAnnotation": "Invisible Annotation:", "class.info.superName": "Super Name:", "class.info.interfaces": "Interfaces:", "class.info.outerClass": "Outer Class:", @@ -63,10 +68,10 @@ "class.info.outerMethodDescription": "Outer Method Description:", "class.info.description": "Description:", "class.info.exceptions": "Exceptions:", - "class.tab.bytecodeView": "BytecodeView", - "class.tab.decompileView": "DecompileView", - "class.tab.visitorEdit": "VisitorEdit", - "class.tab.infoEdit": "InfoEdit", + "class.tab.bytecode": "Bytecode", + "class.tab.decompile": "Decompile", + "class.tab.visitor": "Visitor", + "class.tab.info": "Info", "button.search": "Search", "button.findNext": "Find Next", "button.findPrevious": "Find Previous", @@ -106,6 +111,16 @@ "instruction.min": "Min:", "instruction.max": "Max:", "instruction.labels": "Labels:", - "sideTab.member": "Member", - "sideTab.inherit": "inherit" + "instruction.tag": "Tag:", + "instruction.frame.addString": "Add String", + "instruction.frame.addType": "Add Type", + "instruction.addHandle": "Add Handle", + "instruction.annotation.title": "Annotation", + "instruction.annotation.description": "Description", + "instruction.annotation.hasValue": "Has Value", + "instruction.annotation.value": "Value", + "instruction.lookSwitch.keys": "Keys", + "instruction.lookSwitch.labels": "Labels", + "side.member": "Member", + "side.inherit": "Inherit" } \ No newline at end of file diff --git a/src/main/resources/lang/zh_CN.json b/ui/src/main/resources/i18n/zh_CN.json old mode 100644 new mode 100755 similarity index 78% rename from src/main/resources/lang/zh_CN.json rename to ui/src/main/resources/i18n/zh_CN.json index b449a95..93e5e21 --- a/src/main/resources/lang/zh_CN.json +++ b/ui/src/main/resources/i18n/zh_CN.json @@ -2,10 +2,12 @@ "search.ldc.title": "搜索常量", "search.field.title": "搜索字段", "search.method.title": "搜索方法", + "search.opcode.title": "搜索操作码", "search.owner": "拥有者:", "search.name": "名称:", "search.description": "描述:", "search.interface": "接口:", + "search.opcode": "操作码:", "about.system": "系统", "about.system.description": "有关操作系统的信息", "about.system.name": "名字", @@ -28,6 +30,7 @@ "menu.search.ldc": "常量", "menu.search.field": "字段", "menu.search.method": "方法", + "menu.search.opcode": "操作码", "menu.attach": "附上", "menu.attach.process": "进程", "menu.mapping": "映射", @@ -36,8 +39,8 @@ "menu.help.contact": "联系", "popup.attach.external": "外部", "popup.attach.properties": "属性", - "popup.instruction.edit": "编辑", - "popup.instruction.clone": "克隆", + "popup.instructions.edit": "编辑", + "popup.instructions.clone": "克隆", "popup.instructions.remove": "移除", "popup.instructions.copyText": "复制文本", "popup.instructions.insertBefore": "前插入", @@ -49,13 +52,15 @@ "popup.tabbed.closeOther": "关闭其他", "popup.tabbed.closeAllLeft": "关闭左边所有", "popup.tabbed.closeAllRight": "关闭右边所有", - "popup.member.callTree": "调用树", + "popup.result.jump": "跳转到项目", "class.info.name": "名称:", "class.info.sourceFile": "源文件:", "class.info.debugFile": "调试文件:", "class.info.access": "访问:", "class.info.version": "版本:", "class.info.signature": "签名:", + "class.info.visibleAnnotation": "可见注解:", + "class.info.invisibleAnnotation": "不可见注解:", "class.info.superName": "超类:", "class.info.interfaces": "接口:", "class.info.outerClass": "外部类:", @@ -63,10 +68,10 @@ "class.info.outerMethodDescription": "外部方法描述:", "class.info.description": "描述:", "class.info.exceptions": "异常:", - "class.tab.bytecodeView": "字节码查看", - "class.tab.decompileView": "反编译查看", - "class.tab.visitorEdit": "访问者编辑", - "class.tab.infoEdit": "信息编辑", + "class.tab.bytecode": "字节码查看", + "class.tab.decompile": "反编译编辑", + "class.tab.visitor": "访问者编辑", + "class.tab.info": "信息编辑", "button.search": "搜索", "button.findNext": "查找下一个", "button.findPrevious": "查找上一个", @@ -106,6 +111,16 @@ "instruction.min": "最小:", "instruction.max": "最大:", "instruction.labels": "标签:", - "sideTab.member": "成员", - "sideTab.inherit": "继承" + "instruction.tag": "标记:", + "instruction.addString": "添加字符串", + "instruction.frame.addType": "添加类型", + "instruction.frame.addHandle": "添加句柄", + "instruction.annotation.title": "注解", + "instruction.annotation.description": "描述", + "instruction.annotation.hasValue": "有值", + "instruction.annotation.value": "值", + "instruction.lookSwitch.keys": "键", + "instruction.lookSwitch.labels": "标签", + "side.member": "成员", + "side.inherit": "继承" } \ No newline at end of file diff --git a/src/main/resources/icons/abstractClass.svg b/ui/src/main/resources/icons/abstractClass.svg old mode 100644 new mode 100755 similarity index 100% rename from src/main/resources/icons/abstractClass.svg rename to ui/src/main/resources/icons/abstractClass.svg diff --git a/src/main/resources/icons/annotation.svg b/ui/src/main/resources/icons/annotation.svg old mode 100644 new mode 100755 similarity index 100% rename from src/main/resources/icons/annotation.svg rename to ui/src/main/resources/icons/annotation.svg diff --git a/src/main/resources/icons/biliBili.svg b/ui/src/main/resources/icons/biliBili.svg old mode 100644 new mode 100755 similarity index 100% rename from src/main/resources/icons/biliBili.svg rename to ui/src/main/resources/icons/biliBili.svg diff --git a/src/main/resources/icons/class.svg b/ui/src/main/resources/icons/class.svg old mode 100644 new mode 100755 similarity index 100% rename from src/main/resources/icons/class.svg rename to ui/src/main/resources/icons/class.svg diff --git a/src/main/resources/icons/classesRoot.svg b/ui/src/main/resources/icons/classesRoot.svg old mode 100644 new mode 100755 similarity index 100% rename from src/main/resources/icons/classesRoot.svg rename to ui/src/main/resources/icons/classesRoot.svg diff --git a/src/main/resources/icons/cyan_dot.svg b/ui/src/main/resources/icons/cyan_dot.svg old mode 100644 new mode 100755 similarity index 100% rename from src/main/resources/icons/cyan_dot.svg rename to ui/src/main/resources/icons/cyan_dot.svg diff --git a/src/main/resources/icons/enum.svg b/ui/src/main/resources/icons/enum.svg old mode 100644 new mode 100755 similarity index 100% rename from src/main/resources/icons/enum.svg rename to ui/src/main/resources/icons/enum.svg diff --git a/src/main/resources/icons/field.svg b/ui/src/main/resources/icons/field.svg old mode 100644 new mode 100755 similarity index 100% rename from src/main/resources/icons/field.svg rename to ui/src/main/resources/icons/field.svg diff --git a/src/main/resources/icons/file.svg b/ui/src/main/resources/icons/file.svg old mode 100644 new mode 100755 similarity index 100% rename from src/main/resources/icons/file.svg rename to ui/src/main/resources/icons/file.svg diff --git a/src/main/resources/icons/finalClass.svg b/ui/src/main/resources/icons/finalClass.svg old mode 100644 new mode 100755 similarity index 64% rename from src/main/resources/icons/finalClass.svg rename to ui/src/main/resources/icons/finalClass.svg index 9a9f028..83a1522 --- a/src/main/resources/icons/finalClass.svg +++ b/ui/src/main/resources/icons/finalClass.svg @@ -25,15 +25,11 @@ --> - + - - - - - + d="M21,16.5C21,16.88 20.79,17.21 20.47,17.38L12.57,21.82C12.41,21.94 12.21,22 12,22C11.79,22 11.59,21.94 11.43,21.82L3.53,17.38C3.21,17.21 3,16.88 3,16.5V7.5C3,7.12 3.21,6.79 3.53,6.62L11.43,2.18C11.59,2.06 11.79,2 12,2C12.21,2 12.41,2.06 12.57,2.18L20.47,6.62C20.79,6.79 21,7.12 21,7.5V16.5M12,4.15L6.04,7.5L12,10.85L17.96,7.5L12,4.15Z" + fill="#4FC3F7" /> + diff --git a/src/main/resources/icons/folder.svg b/ui/src/main/resources/icons/folder.svg old mode 100644 new mode 100755 similarity index 100% rename from src/main/resources/icons/folder.svg rename to ui/src/main/resources/icons/folder.svg diff --git a/src/main/resources/icons/github.svg b/ui/src/main/resources/icons/github.svg old mode 100644 new mode 100755 similarity index 100% rename from src/main/resources/icons/github.svg rename to ui/src/main/resources/icons/github.svg diff --git a/src/main/resources/icons/hierarchy.svg b/ui/src/main/resources/icons/hierarchy.svg old mode 100644 new mode 100755 similarity index 100% rename from src/main/resources/icons/hierarchy.svg rename to ui/src/main/resources/icons/hierarchy.svg diff --git a/src/main/resources/icons/inherit.svg b/ui/src/main/resources/icons/inherit.svg old mode 100644 new mode 100755 similarity index 100% rename from src/main/resources/icons/inherit.svg rename to ui/src/main/resources/icons/inherit.svg diff --git a/src/main/resources/icons/interface.svg b/ui/src/main/resources/icons/interface.svg old mode 100644 new mode 100755 similarity index 100% rename from src/main/resources/icons/interface.svg rename to ui/src/main/resources/icons/interface.svg diff --git a/src/main/resources/icons/jar.svg b/ui/src/main/resources/icons/jar.svg old mode 100644 new mode 100755 similarity index 100% rename from src/main/resources/icons/jar.svg rename to ui/src/main/resources/icons/jar.svg diff --git a/src/main/resources/icons/kook.svg b/ui/src/main/resources/icons/kook.svg old mode 100644 new mode 100755 similarity index 100% rename from src/main/resources/icons/kook.svg rename to ui/src/main/resources/icons/kook.svg diff --git a/src/main/resources/icons/method.svg b/ui/src/main/resources/icons/method.svg old mode 100644 new mode 100755 similarity index 100% rename from src/main/resources/icons/method.svg rename to ui/src/main/resources/icons/method.svg diff --git a/src/main/resources/icons/minimize.svg b/ui/src/main/resources/icons/minimize.svg old mode 100644 new mode 100755 similarity index 100% rename from src/main/resources/icons/minimize.svg rename to ui/src/main/resources/icons/minimize.svg diff --git a/src/main/resources/icons/openjdk.svg b/ui/src/main/resources/icons/openjdk.svg old mode 100644 new mode 100755 similarity index 100% rename from src/main/resources/icons/openjdk.svg rename to ui/src/main/resources/icons/openjdk.svg diff --git a/src/main/resources/icons/package.svg b/ui/src/main/resources/icons/package.svg old mode 100644 new mode 100755 similarity index 100% rename from src/main/resources/icons/package.svg rename to ui/src/main/resources/icons/package.svg diff --git a/src/main/resources/icons/private.svg b/ui/src/main/resources/icons/private.svg old mode 100644 new mode 100755 similarity index 100% rename from src/main/resources/icons/private.svg rename to ui/src/main/resources/icons/private.svg diff --git a/src/main/resources/icons/protected.svg b/ui/src/main/resources/icons/protected.svg old mode 100644 new mode 100755 similarity index 100% rename from src/main/resources/icons/protected.svg rename to ui/src/main/resources/icons/protected.svg diff --git a/src/main/resources/icons/public.svg b/ui/src/main/resources/icons/public.svg old mode 100644 new mode 100755 similarity index 100% rename from src/main/resources/icons/public.svg rename to ui/src/main/resources/icons/public.svg diff --git a/src/main/resources/icons/resourceRoot.svg b/ui/src/main/resources/icons/resourceRoot.svg old mode 100644 new mode 100755 similarity index 100% rename from src/main/resources/icons/resourceRoot.svg rename to ui/src/main/resources/icons/resourceRoot.svg diff --git a/src/main/resources/icons/static.svg b/ui/src/main/resources/icons/static.svg old mode 100644 new mode 100755 similarity index 100% rename from src/main/resources/icons/static.svg rename to ui/src/main/resources/icons/static.svg diff --git a/src/main/resources/icons/structure.svg b/ui/src/main/resources/icons/structure.svg old mode 100644 new mode 100755 similarity index 100% rename from src/main/resources/icons/structure.svg rename to ui/src/main/resources/icons/structure.svg diff --git a/ui/src/main/resources/language/bytecode.json b/ui/src/main/resources/language/bytecode.json new file mode 100644 index 0000000..c561802 --- /dev/null +++ b/ui/src/main/resources/language/bytecode.json @@ -0,0 +1,41 @@ +{ + "name": "Java Bytecode", + "rules": [ + { + "name": "keyword", + "pattern": "\\b(NOP|ACONST_NULL|ICONST_M1|ICONST_0|ICONST_1|ICONST_2|ICONST_3|ICONST_4|ICONST_5|LCONST_0|LCONST_1|FCONST_0|FCONST_1|FCONST_2|DCONST_0|DCONST_1|BIPUSH|SIPUSH|LDC|ILOAD|LLOAD|FLOAD|DLOAD|ALOAD|IALOAD|LALOAD|FALOAD|DALOAD|AALOAD|BALOAD|CALOAD|SALOAD|ISTORE|LSTORE|FSTORE|DSTORE|ASTORE|IASTORE|LASTORE|FASTORE|DASTORE|AASTORE|BASTORE|CASTORE|SASTORE|POP|POP2|DUP|DUP_X1|DUP_X2|DUP2|DUP2_X1|DUP2_X2|SWAP|IADD|LADD|FADD|DADD|ISUB|LSUB|FSUB|DSUB|IMUL|LMUL|FMUL|DMUL|IDIV|LDIV|FDIV|DDIV|IREM|LREM|FREM|DREM|INEG|LNEG|FNEG|DNEG|ISHL|LSHL|ISHR|LSHR|IUSHR|LUSHR|IAND|LAND|IOR|LOR|IXOR|LXOR|IINC|I2L|I2F|I2D|L2I|L2F|L2D|F2I|F2L|F2D|D2I|D2L|D2F|I2B|I2C|I2S|LCMP|FCMPL|FCMPG|DCMPL|DCMPG|IFEQ|IFNE|IFLT|IFGE|IFGT|IFLE|IF_ICMPEQ|IF_ICMPNE|IF_ICMPLT|IF_ICMPGE|IF_ICMPGT|IF_ICMPLE|IF_ACMPEQ|IF_ACMPNE|GOTO|JSR|RET|TABLESWITCH|LOOKUPSWITCH|IRETURN|LRETURN|FRETURN|DRETURN|ARETURN|RETURN|GETSTATIC|PUTSTATIC|GETFIELD|PUTFIELD|INVOKEVIRTUAL|INVOKESPECIAL|INVOKESTATIC|INVOKEINTERFACE|INVOKEDYNAMIC|NEW|NEWARRAY|ANEWARRAY|ARRAYLENGTH|ATHROW|CHECKCAST|INSTANCEOF|MONITORENTER|MONITOREXIT|MULTIANEWARRAY|IFNULL|IFNONNULL|LINENUMBER|LOCALVARIABLE|MAXSTACK|MAXLOCALS|INNERCLASS|public|private|class|static|abstract\n)\\b" + }, + { + "name": "comment", + "pattern": "//.+" + }, + { + "name": "annotation", + "pattern": "@(.+?)(?=;)" + }, + { + "name": "string", + "pattern": "\"([^\"\\\\]|\\\\.)*\"" + }, + { + "name": "constant", + "pattern": "\\b0[xX][0-9a-fA-F]+\\b|\\b(?:[\\d_]+\\.\\d+|[\\d_]+)\\b|\\b(?:true|false|null)\\b|'[\\\\]?.'" + }, + { + "name": "paren", + "pattern": "[()]" + }, + { + "name": "brace", + "pattern": "[{}]" + }, + { + "name": "bracket", + "pattern": "[\\[\\]]" + }, + { + "name": "description", + "pattern": "L(.+?)(?=;)" + } + ] +} \ No newline at end of file diff --git a/ui/src/main/resources/language/java.json b/ui/src/main/resources/language/java.json new file mode 100644 index 0000000..192643c --- /dev/null +++ b/ui/src/main/resources/language/java.json @@ -0,0 +1,41 @@ +{ + "name": "java", + "rules": [ + { + "name": "keyword", + "pattern": "\\b(abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|native|new|package|private|protected|public|return|short|static|strictfp|super|switch|synchronized|this|throw|throws|transient|try|void|volatile|while)\\b" + }, + { + "name": "string", + "pattern": "\"([^\"\\\\]|\\\\.)*\"" + }, + { + "name": "constant", + "pattern": "\\b0[xX][0-9a-fA-F]+\\b|\\b(?:[\\d_]+\\.\\d+|[\\d_]+)\\b|\\b(?:true|false|null)\\b|'[\\\\]?.'" + }, + { + "name": "comment", + "pattern": "//[^\n]*|/\\*(.|\\R)*?\\*/" + }, + { + "name": "annotation", + "pattern": "@\\w+|(?<=\\s)@\\w+" + }, + { + "name": "paren", + "pattern": "[()]" + }, + { + "name": "brace", + "pattern": "[{}]" + }, + { + "name": "bracket", + "pattern": "[\\[\\]]" + }, + { + "name": "semicolon", + "pattern": ";" + } + ] +} \ No newline at end of file diff --git a/ui/src/main/resources/style/highlight.css b/ui/src/main/resources/style/highlight.css new file mode 100644 index 0000000..71d88bc --- /dev/null +++ b/ui/src/main/resources/style/highlight.css @@ -0,0 +1,56 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.keyword { + -fx-fill: purple; + -fx-font-weight: bold; +} +.semicolon { + -fx-font-weight: bold; +} +.paren { + -fx-fill: firebrick; + -fx-font-weight: bold; +} +.bracket { + -fx-fill: darkgreen; + -fx-font-weight: bold; +} +.brace { + -fx-fill: teal; + -fx-font-weight: bold; +} +.string { + -fx-fill: blue; +} + +.comment { + -fx-fill: cadetblue; +} + +.constant { + -fx-fill: orange; +} +.annotation { + -fx-fill: purple; +} + +.description { + -fx-fill: rgb(247, 129, 32); +} +.paragraph-box:has-caret { + -fx-background-color: #f2f9fc; +} \ No newline at end of file diff --git a/ui/src/main/resources/style/style.css b/ui/src/main/resources/style/style.css new file mode 100644 index 0000000..e69de29