Extracting FilenameFilter to be an entity independent of Disk.

This commit is contained in:
Rob Greene
2025-08-22 14:10:51 -05:00
parent 0a27745030
commit b3bfc9b854
4 changed files with 114 additions and 83 deletions
@@ -25,6 +25,7 @@ import com.google.gson.JsonStreamParser;
import com.webcodepro.applecommander.storage.DirectoryEntry;
import com.webcodepro.applecommander.storage.Disk;
import com.webcodepro.applecommander.storage.FileEntry;
import com.webcodepro.applecommander.storage.FilenameFilter;
import com.webcodepro.applecommander.storage.FormattedDisk;
import com.webcodepro.applecommander.storage.os.cpm.CpmFormatDisk;
import com.webcodepro.applecommander.storage.os.dos33.DosFormatDisk;
@@ -205,7 +206,7 @@ public class ScanCommand extends ReusableCommandOptions {
// Build "glob:**.{do,po,dsk,...}"
StringBuilder globs = new StringBuilder("glob:**.{");
boolean first = true;
for (String ext : Disk.getAllExtensions()) {
for (String ext : FilenameFilter.getAllExtensions()) {
if (!first) globs.append(",");
ext = ext.substring(1); // skip the "." - lots of assumptions here!
// Unix is case-sensitive, so we need to make the pattern case-insensitive (yuck)
@@ -28,7 +28,6 @@ import org.applecommander.util.DataBuffer;
import java.io.*;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.GZIPOutputStream;
@@ -39,29 +38,7 @@ import java.util.zip.GZIPOutputStream;
* @author Rob Greene
*/
public class Disk {
/**
* Specifies a filter to be used in determining filetypes which are supported.
* This works from a file extension, so it may or may not apply to the Macintosh.
*/
public static class FilenameFilter {
private String names;
private String[] extensions;
public FilenameFilter(String names, String... extensions) {
this.names = names;
this.extensions = extensions;
}
public String getExtensions() {
return String.join(";", extensions);
}
public String[] getExtensionList() {
return extensions;
}
public String getNames() {
return names;
}
}
public static final int BLOCK_SIZE = 512;
public static final int BLOCK_SIZE = 512;
public static final int SECTOR_SIZE = 256;
public static final int PRODOS_BLOCKS_ON_140KB_DISK = 280;
public static final int DOS33_SECTORS_ON_140KB_DISK = 560;
@@ -76,44 +53,7 @@ public class Disk {
public static final int APPLE_20MB_HARDDISK = 20971520;
public static final int APPLE_32MB_HARDDISK = 33553920; // short one block!
private static final TextBundle textBundle = StorageBundle.getInstance();
private static final FilenameFilter[] filenameFilters;
private static final List<String> allFileExtensions;
static {
// Build everything dynamically
List<String> templates = List.of(
"140kDosImages:do,dsk",
"140kProdosImages:po",
"140kNibbleImages:nib",
"800kProdosImages:2mg,2img",
"ApplePcImages:hdv",
"WozImages:woz",
"DiskCopyImages:dc");
List<FilenameFilter> filters = new ArrayList<>();
List<String> allImages = new ArrayList<>(List.of("*.shk", "*.sdk"));
List<String> compressedImages = new ArrayList<>(allImages);
for (String template : templates) {
String[] parts = template.split(":");
String bundleName = String.format("Disk.%s", parts[0]);
List<String> extensions = new ArrayList<>();
for (String extension : parts[1].split(",")) {
String ext1 = String.format("*.%s", extension);
String ext2 = String.format("*.%s.gz", extension);
extensions.add(ext1);
extensions.add(ext2);
compressedImages.add(ext2);
}
allImages.addAll(extensions);
String text = textBundle.get(bundleName);
filters.add(new FilenameFilter(text, extensions.toArray(new String[0])));
}
filters.addFirst(new FilenameFilter(textBundle.get("Disk.AllImages"), allImages.toArray(new String[0])));
filters.add(new FilenameFilter(textBundle.get("Disk.CompressedImages"), compressedImages.toArray(new String[0])));
filters.add(new FilenameFilter(textBundle.get("Disk.AllFiles"), "*.*"));
filenameFilters = filters.toArray(new FilenameFilter[0]);
// allFileExtensions is of the format ".dsk", ".dsk.gz", so we just strip the first character off...
allFileExtensions = allImages.stream().map(s -> s.substring(1)).toList();
}
private static final TextBundle textBundle = StorageBundle.getInstance();
private String filename;
private boolean newImage = false;
@@ -121,24 +61,7 @@ public class Disk {
private ImageOrder imageOrder = null;
private FormattedDisk[] formattedDisks;
/**
* Get the supported file filters supported by the Disk interface.
* This is due to the fact that FilenameFilter is an inner class of Disk -
* without an instance of the class, the filters cannot be created.
*/
public static FilenameFilter[] getFilenameFilters() {
return filenameFilters;
}
/**
* Get the supported file extensions supported by the Disk interface.
* This is used by the Swing UI to populate the open file dialog box.
*/
public static List<String> getAllExtensions() {
return allFileExtensions;
}
/**
/**
* Construct a Disk with the given byte array.
*/
protected Disk(String filename, ImageOrder imageOrder) {
@@ -0,0 +1,107 @@
/*
* AppleCommander - An Apple ][ image utility.
* Copyright (C) 2002-2025 by Robert Greene
* robgreene at users.sourceforge.net
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.webcodepro.applecommander.storage;
import com.webcodepro.applecommander.util.TextBundle;
import java.util.ArrayList;
import java.util.List;
/**
* Specifies a filter to be used in determining filetypes which are supported.
* This works from a file extension, so it may or may not apply to the Macintosh.
*/
public class FilenameFilter {
private String names;
private String[] extensions;
public FilenameFilter(String names, String... extensions) {
this.names = names;
this.extensions = extensions;
}
public String getExtensions() {
return String.join(";", extensions);
}
public String[] getExtensionList() {
return extensions;
}
public String getNames() {
return names;
}
private static final TextBundle textBundle = StorageBundle.getInstance();
private static final FilenameFilter[] filenameFilters;
private static final List<String> allFileExtensions;
static {
// Build everything dynamically
List<String> templates = List.of(
"140kDosImages:do,dsk",
"140kProdosImages:po",
"140kNibbleImages:nib",
"800kProdosImages:2mg,2img",
"ApplePcImages:hdv",
"WozImages:woz",
"DiskCopyImages:dc");
List<FilenameFilter> filters = new ArrayList<>();
List<String> allImages = new ArrayList<>(List.of("*.shk", "*.sdk"));
List<String> compressedImages = new ArrayList<>(allImages);
for (String template : templates) {
String[] parts = template.split(":");
String bundleName = String.format("Disk.%s", parts[0]);
List<String> extensions = new ArrayList<>();
for (String extension : parts[1].split(",")) {
String ext1 = String.format("*.%s", extension);
String ext2 = String.format("*.%s.gz", extension);
extensions.add(ext1);
extensions.add(ext2);
compressedImages.add(ext2);
}
allImages.addAll(extensions);
String text = textBundle.get(bundleName);
filters.add(new FilenameFilter(text, extensions.toArray(new String[0])));
}
filters.addFirst(new FilenameFilter(textBundle.get("Disk.AllImages"), allImages.toArray(new String[0])));
filters.add(new FilenameFilter(textBundle.get("Disk.CompressedImages"), compressedImages.toArray(new String[0])));
filters.add(new FilenameFilter(textBundle.get("Disk.AllFiles"), "*.*"));
filenameFilters = filters.toArray(new FilenameFilter[0]);
// allFileExtensions is of the format ".dsk", ".dsk.gz", so we just strip the first character off...
allFileExtensions = allImages.stream().map(s -> s.substring(1)).toList();
}
/**
* Get the supported file filters supported by the Disk interface.
* This is due to the fact that FilenameFilter is an inner class of Disk -
* without an instance of the class, the filters cannot be created.
*/
public static FilenameFilter[] getFilenameFilters() {
return filenameFilters;
}
/**
* Get the supported file extensions supported by the Disk interface.
* This is used by the Swing UI to populate the open file dialog box.
*/
public static List<String> getAllExtensions() {
return allFileExtensions;
}
}
@@ -20,7 +20,7 @@
package com.webcodepro.applecommander.ui.swt;
import com.webcodepro.applecommander.storage.Disk;
import com.webcodepro.applecommander.storage.Disk.FilenameFilter;
import com.webcodepro.applecommander.storage.FilenameFilter;
import com.webcodepro.applecommander.storage.DiskUnrecognizedException;
import com.webcodepro.applecommander.storage.FormattedDisk;
import com.webcodepro.applecommander.ui.AppleCommander;
@@ -185,7 +185,7 @@ public class SwtAppleCommander implements Listener {
*/
protected void openFile() {
FileDialog fileDialog = new FileDialog(shell, SWT.OPEN);
FilenameFilter[] fileFilters = Disk.getFilenameFilters();
FilenameFilter[] fileFilters = FilenameFilter.getFilenameFilters();
String[] names = new String[fileFilters.length];
String[] extensions = new String[fileFilters.length];
for (int i=0; i<fileFilters.length; i++) {