Skip to content

Commit

Permalink
Added 'Export class' menu to classes
Browse files Browse the repository at this point in the history
  • Loading branch information
jumanji144 committed Mar 1, 2024
1 parent b9bba50 commit b4f0aa4
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,9 @@ private void populateJvmMenu(@Nonnull ContextMenu menu,
refactor.infoItem("menu.refactor.rename", TAG_EDIT, actions::renameClass);
refactor.infoItem("menu.refactor.move", STACKED_MOVE, actions::moveClass);

// Export actions
builder.infoItem("menu.export.class", EXPORT, actions::exportClass);

// TODO: implement operations
// - View
// - Class hierarchy
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import software.coley.recaf.ui.pane.editing.text.TextFilePane;
import software.coley.recaf.util.*;
import software.coley.recaf.util.visitors.*;
import software.coley.recaf.workspace.PathExportingManager;
import software.coley.recaf.workspace.model.Workspace;
import software.coley.recaf.workspace.model.bundle.*;
import software.coley.recaf.workspace.model.resource.WorkspaceResource;
Expand Down Expand Up @@ -78,6 +79,7 @@ public class Actions implements Service {
private final DockingManager dockingManager;
private final TextProviderService textService;
private final IconProviderService iconService;
private final PathExportingManager pathExportingManager;
private final Instance<MappingApplier> applierProvider;
private final Instance<JvmClassPane> jvmPaneProvider;
private final Instance<AndroidClassPane> androidPaneProvider;
Expand All @@ -96,6 +98,7 @@ public Actions(@Nonnull ActionsConfig config,
@Nonnull DockingManager dockingManager,
@Nonnull TextProviderService textService,
@Nonnull IconProviderService iconService,
@Nonnull PathExportingManager pathExportingManager,
@Nonnull Instance<MappingApplier> applierProvider,
@Nonnull Instance<JvmClassPane> jvmPaneProvider,
@Nonnull Instance<AndroidClassPane> androidPaneProvider,
Expand All @@ -111,6 +114,7 @@ public Actions(@Nonnull ActionsConfig config,
this.dockingManager = dockingManager;
this.textService = textService;
this.iconService = iconService;
this.pathExportingManager = pathExportingManager;
this.applierProvider = applierProvider;
this.jvmPaneProvider = jvmPaneProvider;
this.androidPaneProvider = androidPaneProvider;
Expand Down Expand Up @@ -1454,6 +1458,25 @@ else if (path instanceof ClassMemberPathNode classMemberPathNode)
});
}

/**
* Exports a class, prompting the user to select a location to save the class to.
*
* @param workspace
* Containing workspace.
* @param resource
* Containing resource.
* @param bundle
* Containing bundle.
* @param info
* Class to delete.
*/
public void exportClass(@Nonnull Workspace workspace,
@Nonnull WorkspaceResource resource,
@Nonnull JvmClassBundle bundle,
@Nonnull JvmClassInfo info) {
pathExportingManager.export(info);
}

/**
* Prompts the user <i>(if configured, otherwise prompt is skipped)</i> to delete the class.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public class RecentFilesConfig extends BasicConfigContainer {
private final ObservableCollection<WorkspaceModel, List<WorkspaceModel>> recentWorkspaces = new ObservableCollection<>(ArrayList::new);
private final ObservableString lastWorkspaceOpenDirectory = new ObservableString(System.getProperty("user.dir"));
private final ObservableString lastWorkspaceExportDirectory = new ObservableString(System.getProperty("user.dir"));
private final ObservableString lastClassExportDirectory = new ObservableString(System.getProperty("user.dir"));

@Inject
public RecentFilesConfig() {
Expand All @@ -49,6 +50,7 @@ public RecentFilesConfig() {
addValue(new BasicCollectionConfigValue<>("recent-workspaces", List.class, WorkspaceModel.class, recentWorkspaces));
addValue(new BasicConfigValue<>("last-workspace-open-path", String.class, lastWorkspaceOpenDirectory));
addValue(new BasicConfigValue<>("last-workspace-export-path", String.class, lastWorkspaceExportDirectory));
addValue(new BasicConfigValue<>("last-class-export-path", String.class, lastClassExportDirectory));
}

/**
Expand Down Expand Up @@ -126,6 +128,14 @@ public ObservableString getLastWorkspaceExportDirectory() {
return lastWorkspaceExportDirectory;
}

/**
* @return Last path used to export a class to.
*/
@Nonnull
public ObservableString getLastClassExportDirectory() {
return lastClassExportDirectory;
}

/**
* Basic wrapper for workspaces.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.slf4j.Logger;
import software.coley.observables.ObservableString;
import software.coley.recaf.analytics.logging.Logging;
import software.coley.recaf.info.JvmClassInfo;
import software.coley.recaf.services.workspace.WorkspaceManager;
import software.coley.recaf.ui.config.ExportConfig;
import software.coley.recaf.ui.config.RecentFilesConfig;
Expand All @@ -21,6 +22,7 @@

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

/**
Expand Down Expand Up @@ -120,4 +122,39 @@ public void export(Workspace workspace) {
);
}
}

public void export(JvmClassInfo info) {
ObservableString lastClassExportDir = recentFilesConfig.getLastClassExportDirectory();
File lastExportDir = lastClassExportDir.unboxingMap(File::new);

FileChooser chooser = new FileChooser();
chooser.setInitialDirectory(lastExportDir);
chooser.setTitle(Lang.get("dialog.file.export"));
chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("Java Class", "*.class"));

File selectedPath = chooser.showSaveDialog(null);

if (selectedPath == null) {
return;
}

Path exportPath = selectedPath.toPath();
if (!exportPath.endsWith(".class")) {
exportPath = exportPath.resolveSibling(exportPath.getFileName() + ".class");
}

lastClassExportDir.setValue(selectedPath.getParent());

try {
Files.write(exportPath, info.getBytecode());
} catch (IOException ex) {
logger.error("Failed to export class to path '{}'", selectedPath, ex);
ErrorDialogs.show(
Lang.getBinding("dialog.error.exportclass.title"),
Lang.getBinding("dialog.error.exportclass.header"),
Lang.getBinding("dialog.error.exportclass.content"),
ex
);
}
}
}
2 changes: 2 additions & 0 deletions recaf-ui/src/main/resources/translations/en_US.lang
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ menu.edit.noop=Make no-op
menu.edit.changeversion=Change class versions
menu.edit.changeversion.up=Upgrade
menu.edit.changeversion.down=Downgrade
menu.export.class=Export class
menu.help=Help
menu.help.discord=Discord
menu.help.docs=Online user documentation
Expand Down Expand Up @@ -654,6 +655,7 @@ service.io.recent-workspaces-config.last-workspace-export-path=Last workspace ex
service.io.recent-workspaces-config.last-workspace-open-path=Last workspace open path
service.io.recent-workspaces-config.max-recent-workspaces=Maximum record of recent paths
service.io.recent-workspaces-config.recent-workspaces=Recent workspace
service.io.recent-workspaces-config.last-class-export-path=Last class export path
service.io.resource-importer-config=Archive importing
service.io.resource-importer-config.zip-strategy=ZIP parsing strategy
service.io.resource-importer-config.skip-revisited-cen-to-local-links=Skip duplicate CEN-to-LOC entries with JVM strategy
Expand Down

0 comments on commit b4f0aa4

Please sign in to comment.