Implement basic ordering

This commit is contained in:
crschnick 2024-05-28 12:05:22 +00:00
parent f3557bb715
commit 6f6b4a76d4
8 changed files with 170 additions and 43 deletions

View file

@ -108,6 +108,7 @@ run {
}
workingDir = rootDir
jvmArgs += ['-XX:+EnableDynamicAgentLoading']
}
task runAttachedDebugger(type: JavaExec) {
@ -121,7 +122,7 @@ task runAttachedDebugger(type: JavaExec) {
"-javaagent:${System.getProperty("user.home")}/.attachme/attachme-agent-1.2.4.jar=port:7857,host:localhost".toString(),
"-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=127.0.0.1:0"
)
jvmArgs += '-XX:+EnableDynamicAgentLoading'
jvmArgs += ['-XX:+EnableDynamicAgentLoading']
systemProperties run.systemProperties
}

View file

@ -372,6 +372,14 @@ public abstract class StoreEntryComp extends SimpleComp {
contextMenu.getItems().add(new SeparatorMenuItem());
}
var notes = new MenuItem(AppI18n.get("addNotes"), new FontIcon("mdi2n-note-text"));
notes.setOnAction(event -> {
wrapper.getNotes().setValue(new StoreNotes(null, getDefaultNotes()));
event.consume();
});
notes.visibleProperty().bind(BindingsHelper.map(wrapper.getNotes(), s -> s.getCommited() == null));
contextMenu.getItems().add(notes);
if (AppPrefs.get().developerMode().getValue()) {
var browse = new MenuItem(AppI18n.get("browseInternalStorage"), new FontIcon("mdi2f-folder-open-outline"));
browse.setOnAction(
@ -379,6 +387,25 @@ public abstract class StoreEntryComp extends SimpleComp {
contextMenu.getItems().add(browse);
}
if (DataStorage.get().isRootEntry(wrapper.getEntry())) {
var color = new Menu(AppI18n.get("color"), new FontIcon("mdi2f-format-color-fill"));
var none = new MenuItem("None");
none.setOnAction(event -> {
wrapper.getEntry().setColor(null);
event.consume();
});
color.getItems().add(none);
Arrays.stream(DataStoreColor.values()).forEach(dataStoreColor -> {
MenuItem m = new MenuItem(DataStoreFormatter.capitalize(dataStoreColor.getId()));
m.setOnAction(event -> {
wrapper.getEntry().setColor(dataStoreColor);
event.consume();
});
color.getItems().add(m);
});
contextMenu.getItems().add(color);
}
if (wrapper.getEntry().getProvider() != null) {
var move = new Menu(AppI18n.get("moveTo"), new FontIcon("mdi2f-folder-move-outline"));
StoreViewState.get()
@ -399,32 +426,45 @@ public abstract class StoreEntryComp extends SimpleComp {
contextMenu.getItems().add(move);
}
if (DataStorage.get().isRootEntry(wrapper.getEntry())) {
var color = new Menu(AppI18n.get("color"), new FontIcon("mdi2f-format-color-fill"));
var none = new MenuItem("None");
none.setOnAction(event -> {
wrapper.getEntry().setColor(null);
event.consume();
});
color.getItems().add(none);
Arrays.stream(DataStoreColor.values()).forEach(dataStoreColor -> {
MenuItem m = new MenuItem(DataStoreFormatter.capitalize(dataStoreColor.getId()));
m.setOnAction(event -> {
wrapper.getEntry().setColor(dataStoreColor);
event.consume();
});
color.getItems().add(m);
});
contextMenu.getItems().add(color);
}
var notes = new MenuItem(AppI18n.get("addNotes"), new FontIcon("mdi2n-note-text"));
notes.setOnAction(event -> {
wrapper.getNotes().setValue(new StoreNotes(null, getDefaultNotes()));
var order = new Menu(AppI18n.get("order"), new FontIcon("mdal-bookmarks"));
var noOrder = new MenuItem("None");
noOrder.setOnAction(event -> {
DataStorage.get().orderBefore(wrapper.getEntry(), null);
event.consume();
});
notes.visibleProperty().bind(BindingsHelper.map(wrapper.getNotes(), s -> s.getCommited() == null));
contextMenu.getItems().add(notes);
if (wrapper.getEntry().getOrderBefore() == null) {
noOrder.setDisable(true);
}
order.getItems().add(noOrder);
var stick = new MenuItem(AppI18n.get("stickToTop"));
stick.setOnAction(event -> {
DataStorage.get().orderBefore(wrapper.getEntry(), wrapper.getEntry());
event.consume();
});
if (wrapper.getEntry().getUuid().equals(wrapper.getEntry().getOrderBefore())) {
stick.setDisable(true);
}
order.getItems().add(stick);
order.getItems().add(new SeparatorMenuItem());
var section = StoreViewState.get().getParentSectionForWrapper(wrapper);
section.get().getAllChildren().forEach(other -> {
var ow = other.getWrapper();
var op = ow.getEntry().getProvider();
MenuItem m = new MenuItem(ow.getName().getValue(),
op != null ? PrettyImageHelper.ofFixedSizeSquare(op.getDisplayIconFileName(ow.getEntry().getStore()),
16).createRegion() : null);
if (ow.getEntry().getUuid().equals(wrapper.getEntry().getOrderBefore())) {
m.setDisable(true);
}
m.setOnAction(event -> {
wrapper.orderBefore(ow);
event.consume();
});
order.getItems().add(m);
});
contextMenu.getItems().add(order);
contextMenu.getItems().add(new SeparatorMenuItem());
var del = new MenuItem(AppI18n.get("remove"), new FontIcon("mdal-delete_outline"));
del.disableProperty()

View file

@ -71,6 +71,12 @@ public class StoreEntryWrapper {
});
}
public void orderBefore(StoreEntryWrapper other) {
ThreadHelper.runAsync(() -> {
DataStorage.get().orderBefore(getEntry(),other.getEntry());
});
}
public boolean isInStorage() {
return DataStorage.get().getStoreEntries().contains(entry);
}

View file

@ -65,8 +65,32 @@ public class StoreSection {
return list;
}
var c = Comparator.<StoreSection>comparingInt(
var explicitOrderComp = new Comparator<StoreSection>() {
@Override
public int compare(StoreSection o1, StoreSection o2) {
var explicit1 = o1.getWrapper().getEntry().getOrderBefore();
var explicit2 = o2.getWrapper().getEntry().getOrderBefore();
if (explicit1 == null && explicit2 == null) {
return 0;
}
if (explicit1 != null && explicit2 == null) {
return -1;
}
if (explicit2 != null && explicit1 == null) {
return 1;
}
if (explicit1.equals(o2.getWrapper().getEntry().getUuid())) {
return -1;
}
if (explicit2.equals(o1.getWrapper().getEntry().getUuid())) {
return -1;
}
return 0;
}
};
var usableComp = Comparator.<StoreSection>comparingInt(
value -> value.getWrapper().getEntry().getValidity().isUsable() ? -1 : 1);
var comp = explicitOrderComp.thenComparing(usableComp);
var mappedSortMode = BindingsHelper.flatMap(
category,
storeCategoryWrapper -> storeCategoryWrapper != null ? storeCategoryWrapper.getSortMode() : null);
@ -75,10 +99,10 @@ public class StoreSection {
(o1, o2) -> {
var current = mappedSortMode.getValue();
if (current != null) {
return c.thenComparing(current.comparator())
return comp.thenComparing(current.comparator())
.compare(current.representative(o1), current.representative(o2));
} else {
return c.compare(o1, o2);
return comp.compare(o1, o2);
}
},
mappedSortMode);

View file

@ -240,6 +240,23 @@ public class StoreViewState {
});
}
public Optional<StoreSection> getParentSectionForWrapper(StoreEntryWrapper wrapper) {
StoreSection current = getCurrentTopLevelSection();
while (true) {
var child = current.getAllChildren().stream().filter(section -> section.getWrapper().equals(wrapper)).findFirst();
if (child.isPresent()) {
return Optional.of(current);
}
var traverse = current.getAllChildren().stream().filter(section -> section.anyMatches(w -> w.equals(wrapper))).findFirst();
if (traverse.isPresent()) {
current = traverse.get();
} else {
return Optional.empty();
}
}
}
public ObservableList<StoreCategoryWrapper> getSortedCategories(StoreCategoryWrapper root) {
Comparator<StoreCategoryWrapper> comparator = new Comparator<>() {
@Override

View file

@ -329,17 +329,26 @@ public abstract class DataStorage {
}
var children = getDeepStoreChildren(entry);
var toRemove = Stream.concat(Stream.of(entry), children.stream()).toArray(DataStoreEntry[]::new);
listeners.forEach(storageListener -> storageListener.onStoreRemove(toRemove));
var arr = Stream.concat(Stream.of(entry), children.stream()).toArray(DataStoreEntry[]::new);
listeners.forEach(storageListener -> storageListener.onStoreRemove(arr));
entry.setCategoryUuid(newCategory.getUuid());
children.forEach(child -> child.setCategoryUuid(newCategory.getUuid()));
var toAdd = Stream.concat(Stream.of(entry), children.stream()).toArray(DataStoreEntry[]::new);
listeners.forEach(storageListener -> storageListener.onStoreAdd(toAdd));
listeners.forEach(storageListener -> storageListener.onStoreAdd(arr));
saveAsync();
}
public void orderBefore(DataStoreEntry entry, DataStoreEntry reference) {
var children = getDeepStoreChildren(entry);
var arr = Stream.concat(Stream.of(entry), children.stream()).toArray(DataStoreEntry[]::new);
listeners.forEach(storageListener -> storageListener.onStoreRemove(arr));
entry.setOrderBefore(reference != null ? reference.getUuid() : null);
listeners.forEach(storageListener -> storageListener.onStoreAdd(arr));
}
public boolean refreshChildren(DataStoreEntry e) {
if (!(e.getStore() instanceof FixedHierarchyStore)) {
return false;
@ -439,7 +448,7 @@ public abstract class DataStorage {
pair.getKey().setStoreInternal(merged, false);
}
var mergedState = pair.getKey().getStorePersistentState().deepCopy();
var mergedState = pair.getKey().getStorePersistentState().copy();
mergedState.merge(pair.getValue().get().getStorePersistentState());
pair.getKey().setStorePersistentState(mergedState);
}
@ -788,9 +797,7 @@ public abstract class DataStorage {
public Optional<DataStoreEntry> getStoreEntryIfPresent(@NonNull DataStore store, boolean identityOnly) {
return storeEntriesSet.stream()
.filter(n -> n.getStore() == store
|| (!identityOnly
&& (n.getStore() != null
.filter(n -> n.getStore() == store || (!identityOnly && (n.getStore() != null
&& Objects.equals(
store.getClass(), n.getStore().getClass())
&& store.equals(n.getStore()))))

View file

@ -72,6 +72,9 @@ public class DataStoreEntry extends StorageElement {
@NonFinal
String notes;
@NonFinal
UUID orderBefore;
private DataStoreEntry(
Path directory,
UUID uuid,
@ -86,7 +89,8 @@ public class DataStoreEntry extends StorageElement {
JsonNode storePersistentState,
boolean expanded,
DataStoreColor color,
String notes) {
String notes, UUID orderBefore
) {
super(directory, uuid, name, lastUsed, lastModified, dirty);
this.categoryUuid = categoryUuid;
this.store = DataStorageParser.storeFromNode(storeNode);
@ -95,6 +99,7 @@ public class DataStoreEntry extends StorageElement {
this.configuration = configuration;
this.expanded = expanded;
this.color = color;
this.orderBefore = orderBefore;
this.provider = store != null
? DataStoreProviders.byStoreClass(store.getClass()).orElse(null)
: null;
@ -109,10 +114,12 @@ public class DataStoreEntry extends StorageElement {
String name,
Instant lastUsed,
Instant lastModified,
DataStore store) {
DataStore store, UUID orderBefore
) {
super(directory, uuid, name, lastUsed, lastModified, false);
this.categoryUuid = categoryUuid;
this.store = store;
this.orderBefore = orderBefore;
this.storeNode = null;
this.validity = Validity.INCOMPLETE;
this.configuration = Configuration.defaultConfiguration();
@ -130,7 +137,8 @@ public class DataStoreEntry extends StorageElement {
UUID.randomUUID().toString(),
Instant.now(),
Instant.now(),
store);
store,
null);
}
public static DataStoreEntry createNew(@NonNull String name, @NonNull DataStore store) {
@ -159,6 +167,7 @@ public class DataStoreEntry extends StorageElement {
null,
false,
null,
null,
null);
return entry;
}
@ -176,7 +185,8 @@ public class DataStoreEntry extends StorageElement {
JsonNode storePersistentState,
boolean expanded,
DataStoreColor color,
String notes) {
String notes,
UUID orderBeforeEntry) {
return new DataStoreEntry(
directory,
uuid,
@ -191,7 +201,8 @@ public class DataStoreEntry extends StorageElement {
storePersistentState,
expanded,
color,
notes);
notes,
orderBeforeEntry);
}
public static Optional<DataStoreEntry> fromDirectory(Path dir) throws Exception {
@ -226,6 +237,15 @@ public class DataStoreEntry extends StorageElement {
.map(jsonNode -> jsonNode.textValue())
.map(Instant::parse)
.orElse(Instant.EPOCH);
var order = Optional.ofNullable(stateJson.get("orderBefore"))
.map(node -> {
try {
return mapper.treeToValue(node, UUID.class);
} catch (JsonProcessingException e) {
return null;
}
})
.orElse(null);
var configuration = Optional.ofNullable(json.get("configuration"))
.map(node -> {
try {
@ -275,10 +295,19 @@ public class DataStoreEntry extends StorageElement {
persistentState,
expanded,
color,
notes
notes,
order
));
}
public void setOrderBefore(UUID uuid) {
var changed = !Objects.equals(orderBefore, uuid);
this.orderBefore = uuid;
if (changed) {
notifyUpdate(false, true);
}
}
@Override
public int hashCode() {
return getUuid().hashCode();
@ -330,7 +359,7 @@ public class DataStoreEntry extends StorageElement {
storePersistentStateNode = JacksonMapper.getDefault().valueToTree(storePersistentState);
}
}
return (T) sds.getStateClass().cast(storePersistentState);
return (T) storePersistentState;
}
public void setStorePersistentState(DataStoreState value) {
@ -379,6 +408,7 @@ public class DataStoreEntry extends StorageElement {
stateObj.set("persistentState", storePersistentStateNode);
obj.set("configuration", mapper.valueToTree(configuration));
stateObj.put("expanded", expanded);
stateObj.put("orderBefore", orderBefore.toString());
var entryString = mapper.writeValueAsString(obj);
var stateString = mapper.writeValueAsString(stateObj);

View file

@ -454,3 +454,5 @@ history=Browsing history
skipAll=Skip all
notes=Notes
addNotes=Add notes
#context: verb
order=Order ...