First pass at using export settings.

This commit is contained in:
a2geek committed 2026-10-03 17:17:49 -05:00
1 parent 64324a7616
commit b64d24a7b7
6 files changed
+103 -19

No files matched your search

@@ -5,6 +5,7 @@ module org.applecommander.javafx {
requires javafx.controls;
requires javafx.graphics;
requires org.applecommander.api;
requires org.applecommander.applesingle;
opens org.applecommander.javafx to javafx.graphics;
opens org.applecommander.javafx.settings to javafx.graphics;
@@ -39,6 +39,8 @@ import org.applecommander.capability.Capability;
import org.applecommander.filestore.Directory;
import org.applecommander.filestore.DisplayColumn;
import org.applecommander.filestore.FileEntry;
import org.applecommander.javafx.settings.ExportOption;
import org.applecommander.javafx.settings.Settings;
import org.applecommander.source.Source;
import org.applecommander.source.Sources;
@@ -47,7 +49,6 @@ import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@@ -123,16 +124,17 @@ public class FileView extends BorderPane {
fileTable.setOnDragDetected(event -> {
if (!fileTable.getSelectionModel().getSelectedItems().isEmpty()) {
try {
ExportOption exportOption = Settings.getExportOption();
Path tempDir = Files.createTempDirectory("AppleCommander-drag-");
tempDir.toFile().deleteOnExit();
List<File> files = new ArrayList<>();
// TODO this should be configured by a setting
for (FileEntry fileEntry : fileTable.getSelectionModel().getSelectedItems()) {
Path path = Path.of(TEMP_DIRECTORY, fileEntry.getName());
Files.write(path, fileEntry.getDataFork().asBytes(), StandardOpenOption.CREATE);
File file = path.toFile();
file.deleteOnExit();
files.add(file);
// We may write two files, so copyToPath gives us ALL the names we care about
for (Path path : exportOption.copyToPath(fileEntry, Path.of(TEMP_DIRECTORY, fileEntry.getName()))) {
File file = path.toFile();
file.deleteOnExit();
files.add(file);
}
}
ClipboardContent content = new ClipboardContent();
content.putFiles(files);
@@ -19,18 +19,103 @@
*/
package org.applecommander.javafx.settings;
import org.applecommander.applesingle.AppleSingle;
import org.applecommander.filestore.FileEntry;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.BiFunction;
public enum ExportOption {
RAW_BINARY("Raw Binary (filename)"),
APPLE_SINGLE("AppleSingle (filename.as)"),
ATTRIBUTE_PRESERVATION("ProDOS Attribute Preservation (filename#TTAAAA.ext)");
RAW_BINARY("Raw Binary (filename)", ExportOption::copyToRawBinary),
APPLE_SINGLE("AppleSingle (filename.as)", ExportOption::copyToAppleSingle),
ATTRIBUTE_PRESERVATION("ProDOS Attribute Preservation (filename#TTAAAA.ext)", ExportOption::copyWithAttributePreservation);
private final String description;
private final BiFunction<FileEntry,Path,List<Path>> copyFn;
ExportOption(String description) {
ExportOption(String description, BiFunction<FileEntry,Path,List<Path>> copyFn) {
Objects.requireNonNull(description, "description cannot be null");
Objects.requireNonNull(copyFn, "copyFn cannot be null");
this.description = description;
this.copyFn = copyFn;
}
public String getDescription() {
return description;
}
public List<Path> copyToPath(FileEntry fileEntry, Path destination) {
return copyFn.apply(fileEntry, destination);
}
public static Path addToFilename(Path path, String suffix) {
String name = path.getFileName().toString();
int idx = name.lastIndexOf('.');
if (idx == -1) {
return path.resolveSibling(name.concat(suffix));
}
name = name.substring(0, idx).concat(suffix).concat(name.substring(idx + 1));
return path.resolve(name);
}
public static List<Path> copyToRawBinary(FileEntry fileEntry, Path destination) {
try {
List<Path> paths = new ArrayList<>();
paths.add(destination);
Files.write(destination, fileEntry.getDataFork().asBytes(), StandardOpenOption.CREATE);
if (fileEntry.getResourceFork().isPresent()) {
Files.write(addToFilename(destination, "-rsrc"), fileEntry.getResourceFork().get().asBytes(),
StandardOpenOption.CREATE);
}
return paths;
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
}
public static List<Path> copyToAppleSingle(FileEntry fileEntry, Path destination) {
try {
List<Path> paths = new ArrayList<>();
destination = destination.resolveSibling(destination.getFileName() + ".as");
paths.add(destination);
// TODO need to get ProDOS-ified file type + some mechanism for access bits + dates. Maybe it fits in FileStore??
AppleSingle.Builder builder = AppleSingle.builder()
.realName(fileEntry.getName())
.dataFork(fileEntry.getDataFork().asBytes());
fileEntry.getResourceFork().ifPresent(resourceFork -> builder.resourceFork(resourceFork.asBytes()));
builder.build().save(destination);
return paths;
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
}
public static List<Path> copyWithAttributePreservation(FileEntry fileEntry, Path destination) {
try {
List<Path> paths = new ArrayList<>();
String name = fileEntry.getName();
String ext = fileEntry.getFiletype();
int idx = name.lastIndexOf('.');
if (idx > -1) {
ext = name.substring(idx + 1);
name = name.substring(0, idx);
}
Path dataForkPath = destination.resolveSibling(String.format("%s#TTAAAA.%s", name, ext));
Files.write(dataForkPath, fileEntry.getDataFork().asBytes(), StandardOpenOption.CREATE);
if (fileEntry.getResourceFork().isPresent()) {
Path resourceForkPath = destination.resolve(String.format("%s#TTAAAA_rsrc_.%s", name, ext));
Files.write(resourceForkPath, fileEntry.getResourceFork().get().asBytes(), StandardOpenOption.CREATE);
}
return paths;
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
}
}
@@ -60,13 +60,13 @@ public abstract class Settings {
prefs.put(THEME_SELECTION, themeSelection.name());
}
public static Optional<ExportOption> getExportOption() {
public static ExportOption getExportOption() {
Preferences prefs = Preferences.userNodeForPackage(AppleCommanderFX.class);
String exportName = prefs.get(EXPORT_OPTION, null);
if (exportName == null || exportName.isBlank()) {
return Optional.of(ExportOption.RAW_BINARY);
return ExportOption.RAW_BINARY;
}
return Optional.of(ExportOption.valueOf(exportName));
return ExportOption.valueOf(exportName);
}
public static void setExportOption(ExportOption exportOption) {
@@ -74,7 +74,7 @@ public class SettingsDialog {
Objects.requireNonNull(parent);
Settings.getThemeSelection().ifPresent(themeSelection::set);
Settings.getExportOption().ifPresent(exportOption::set);
exportOption.set(Settings.getExportOption());
Window window = dialog.getDialogPane().getScene().getWindow();
@@ -222,10 +222,6 @@ public class DiskFileStoreAdapter implements FileStore {
return DataBuffer.wrap(fileEntry.getFileData());
}
@Override
public Optional<DataBuffer> getResourceFork() {
throw new RuntimeException("Not supported by the legacy AppleCommander.");
}
@Override
public void setDataFork(DataBuffer fileData) {
try {
fileEntry.setFileData(fileData.asBytes());