mirror of
https://github.com/AppleCommander/AppleCommander.git
synced 2026-10-24 08:02:19 +00:00
Partially made GameDOS writable. Added a set capability to the DisplayColumn.
This commit is contained in:
1 parent
2c9e120547
commit
e91e6d75b7
3 files changed
+81
-30
No files matched your search
@@ -27,38 +27,34 @@ import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* A DisplayColumn supports formatted output from various FileStores in a
|
||||
* dynamic fashion. The intent is to provide a flexible display interface
|
||||
* that does not rely on hard-coded implementations.
|
||||
*/
|
||||
public record DisplayColumn(String headerText, Alignment alignment, Function<FileEntry,Object> valueFn, String fmt, Mode... modes) {
|
||||
/**
|
||||
* Indicates if this DisplayColumn supports the mode. In this manner, the columns
|
||||
* can be filtered out. Or it can be ignored to display everything.
|
||||
*/
|
||||
/// A DisplayColumn supports formatted output from various FileStores in a
|
||||
/// dynamic fashion. The intent is to provide a flexible display interface
|
||||
/// that does not rely on hard-coded implementations.
|
||||
public record DisplayColumn(String headerText, Alignment alignment,
|
||||
Function<FileEntry,Object> getValueFn, BiConsumer<FileEntry,Object> setValueFn,
|
||||
boolean editInline, String fmt, Mode... modes) {
|
||||
|
||||
/// Indicates if this DisplayColumn supports the mode. In this manner, the columns
|
||||
/// can be filtered out. Or it can be ignored to display everything.
|
||||
public boolean supports(Mode mode) {
|
||||
return Set.of(modes).contains(mode);
|
||||
}
|
||||
/**
|
||||
* Helper method to convert the column into a formatted string for display.
|
||||
*/
|
||||
|
||||
/// Helper method to convert the column into a formatted string for display.
|
||||
public String formatAsText(FileEntry fileEntry) {
|
||||
return String.format(fmt, valueFn.apply(fileEntry));
|
||||
return String.format(fmt, getValueFn.apply(fileEntry));
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates the display mode to help filter columns to users' preference.
|
||||
*/
|
||||
/// Indicates the display mode to help filter columns to users' preference.
|
||||
public enum Mode {
|
||||
NATIVE,
|
||||
DETAIL
|
||||
}
|
||||
/**
|
||||
* Indicates how this column should be aligned.
|
||||
*/
|
||||
|
||||
/// Indicates how this column should be aligned.
|
||||
public enum Alignment {
|
||||
LEFT,
|
||||
CENTER,
|
||||
@@ -81,16 +77,20 @@ public record DisplayColumn(String headerText, Alignment alignment, Function<Fil
|
||||
return columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper method that allows a short-cut of 0 modes meaning ALL modes.
|
||||
*/
|
||||
private Builder<T> add(String name, Alignment alignment, Function<FileEntry,Object> valueFn, String fmt, Mode ...modes) {
|
||||
/// A helper method that allows a short-cut of 0 modes meaning ALL modes.
|
||||
private Builder<T> add(String name, Alignment alignment,
|
||||
Function<FileEntry,Object> getValueFn, BiConsumer<FileEntry,Object> setValueFn,
|
||||
boolean editInline, String fmt, Mode... modes) {
|
||||
if (modes.length == 0) {
|
||||
modes = new Mode[] { Mode.NATIVE, Mode.DETAIL };
|
||||
}
|
||||
columns.add(new DisplayColumn(name, alignment, valueFn, fmt, modes));
|
||||
columns.add(new DisplayColumn(name, alignment, getValueFn, setValueFn, editInline, fmt, modes));
|
||||
return this;
|
||||
}
|
||||
private Builder<T> add(String name, Alignment alignment, Function<FileEntry,Object> getValueFn,
|
||||
String fmt, Mode... modes) {
|
||||
return add(name, alignment, getValueFn, null, false, fmt, modes);
|
||||
}
|
||||
|
||||
public Builder<T> addIntField(String name, Function<T,Integer> valueFn, Mode ...modes) {
|
||||
return addIntField(name, valueFn, "%d", modes);
|
||||
@@ -98,6 +98,12 @@ public record DisplayColumn(String headerText, Alignment alignment, Function<Fil
|
||||
public Builder<T> addIntField(String name, Function<T,Integer> valueFn, String fmt, Mode ...modes) {
|
||||
return add(name, Alignment.RIGHT, entry -> convert(entry, valueFn), fmt, modes);
|
||||
}
|
||||
public Builder<T> addStringField(String name, Function<T,String> getValueFn, BiConsumer<T,String> setValueFn,
|
||||
boolean editInline, Mode ...modes) {
|
||||
return add(name, Alignment.LEFT, entry -> convert(entry, getValueFn),
|
||||
(entry,value) -> convert(entry, setValueFn, String.class, value),
|
||||
editInline, "%s", modes);
|
||||
}
|
||||
public Builder<T> addStringField(String name, Function<T,String> valueFn, Mode ...modes) {
|
||||
return add(name, Alignment.LEFT, entry -> convert(entry, valueFn), "%s", modes);
|
||||
}
|
||||
@@ -124,6 +130,11 @@ public record DisplayColumn(String headerText, Alignment alignment, Function<Fil
|
||||
T typedFileEntry = clazz.cast(fileEntry);
|
||||
return valueFn.apply(typedFileEntry);
|
||||
}
|
||||
private <S> void convert(FileEntry fileEntry, BiConsumer<T,S> setValueFn, Class<S> valueClass, Object value) {
|
||||
T typedFileEntry = clazz.cast(fileEntry);
|
||||
S typedValue = valueClass.cast(value);
|
||||
setValueFn.accept(typedFileEntry, typedValue);
|
||||
}
|
||||
private double percentage(FileEntry fileEntry, Function<T,Number> numeratorFn, Function<T,Number> denominatorFn) {
|
||||
T typedFileEntry = clazz.cast(fileEntry);
|
||||
Number numerator = numeratorFn.apply(typedFileEntry);
|
||||
|
||||
@@ -21,15 +21,16 @@ package org.applecommander.os.gamedos;
|
||||
|
||||
import org.applecommander.device.TrackSectorDevice;
|
||||
import org.applecommander.filestore.Directory;
|
||||
import org.applecommander.filestore.FileEntry;
|
||||
import org.applecommander.filestore.FileStore;
|
||||
import org.applecommander.filestore.ProdosAttributes;
|
||||
import org.applecommander.filestore.WritableFileEntry;
|
||||
import org.applecommander.util.Container;
|
||||
import org.applecommander.util.DataBuffer;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class GamedosFileEntry implements FileEntry, GamedosConstants {
|
||||
public class GamedosFileEntry implements WritableFileEntry, GamedosConstants {
|
||||
private final GamedosDirectory directory;
|
||||
private final TrackSectorDevice device;
|
||||
private final int sector;
|
||||
@@ -43,7 +44,12 @@ public class GamedosFileEntry implements FileEntry, GamedosConstants {
|
||||
}
|
||||
|
||||
public DataBuffer readEntry() {
|
||||
return device.readSector(GamedosDirectory.DIRECTORY_TRACK, sector).slice(offset, ENTRY_SIZE);
|
||||
return device.readSector(DIRECTORY_TRACK, sector).slice(offset, ENTRY_SIZE);
|
||||
}
|
||||
public void modifyEntry(Consumer<DataBuffer> consumer) {
|
||||
DataBuffer data = device.readSector(GamedosDirectory.DIRECTORY_TRACK, sector);
|
||||
consumer.accept(data);
|
||||
device.writeSector(DIRECTORY_TRACK, sector, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -65,6 +71,10 @@ public class GamedosFileEntry implements FileEntry, GamedosConstants {
|
||||
public String getName() {
|
||||
return readEntry().getFixedLengthString(ENTRY_NAME_OFFSET, ENTRY_NAME_LENGTH).trim();
|
||||
}
|
||||
@Override
|
||||
public void setName(String name) {
|
||||
modifyEntry(data -> data.putFixedLengthString(ENTRY_NAME_OFFSET, ENTRY_NAME_LENGTH, name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSize() {
|
||||
@@ -74,24 +84,54 @@ public class GamedosFileEntry implements FileEntry, GamedosConstants {
|
||||
public String getFiletype() {
|
||||
return readEntry().getFixedLengthString(ENTRY_TYPE_OFFSET,1);
|
||||
}
|
||||
public void setFiletype(String filetype) {
|
||||
modifyEntry(data -> data.putFixedLengthString(ENTRY_TYPE_OFFSET, 1, filetype));
|
||||
}
|
||||
|
||||
public int getFirstTrack() {
|
||||
return readEntry().getUnsignedByte(ENTRY_TRACK_OFFSET);
|
||||
}
|
||||
public void setFirstTrack(int track) {
|
||||
modifyEntry(data -> data.putByte(ENTRY_TRACK_OFFSET, track));
|
||||
}
|
||||
|
||||
public int getFirstSector() {
|
||||
return readEntry().getUnsignedByte(ENTRY_SECTOR_OFFSET);
|
||||
}
|
||||
public void setFirstSector(int sector) {
|
||||
modifyEntry(data -> data.putByte(ENTRY_SECTOR_OFFSET, sector));
|
||||
}
|
||||
|
||||
public int getMeta() {
|
||||
return readEntry().getUnsignedShort(ENTRY_META_OFFSET);
|
||||
}
|
||||
public void setMeta(int meta) {
|
||||
modifyEntry(data -> data.putShort(ENTRY_META_OFFSET, (short)meta));
|
||||
}
|
||||
|
||||
public int getSectorCount() {
|
||||
return readEntry().getUnsignedByte(ENTRY_SECTORS_OFFSET);
|
||||
}
|
||||
public void setSectorCount(int sectorCount) {
|
||||
modifyEntry(data -> data.putByte(ENTRY_SECTORS_OFFSET, sectorCount));
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataBuffer getDataFork() {
|
||||
return device.readRange(getFirstTrack(), getFirstSector(), getSectorCount());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDataFork(DataBuffer data) {
|
||||
int requiredSectors = device.calculateRequiredSectors(data.limit());
|
||||
if (getSectorCount() <= requiredSectors) {
|
||||
device.writeRange(getFirstTrack(), getFirstSector(), data);
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException("TODO! can only write same size or smaller files");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProdosAttributes getProdosAttributes() {
|
||||
ProdosAttributes.Builder builder = ProdosAttributes.builder()
|
||||
|
||||
@@ -108,8 +108,8 @@ public class GamedosFileStore implements FileStore, GamedosConstants {
|
||||
@Override
|
||||
public List<DisplayColumn> getDisplayColumns() {
|
||||
return DisplayColumn.builder(GamedosFileEntry.class)
|
||||
.addStringField("Type", GamedosFileEntry::getFiletype)
|
||||
.addStringField("Name", GamedosFileEntry::getName)
|
||||
.addStringField("Type", GamedosFileEntry::getFiletype, GamedosFileEntry::setFiletype, false)
|
||||
.addStringField("Name", GamedosFileEntry::getName, GamedosFileEntry::setName, true)
|
||||
.addIntField("Meta", GamedosFileEntry::getMeta, "$%04X")
|
||||
.addIntField("First Track", GamedosFileEntry::getFirstTrack, Mode.DETAIL)
|
||||
.addIntField("First Sector", GamedosFileEntry::getFirstSector, Mode.DETAIL)
|
||||
|
||||
Reference in new issue
Block a user