Icon work

This commit is contained in:
crschnick 2024-09-13 01:21:53 +00:00
parent 82d5adc7b1
commit a27205de38
5 changed files with 107 additions and 36 deletions

View file

@ -1,5 +1,7 @@
package io.xpipe.app.comp.store;
import atlantafx.base.layout.InputGroup;
import atlantafx.base.theme.Styles;
import io.xpipe.app.comp.base.LoadingOverlayComp;
import io.xpipe.app.core.*;
import io.xpipe.app.ext.ActionProvider;
@ -10,7 +12,6 @@ import io.xpipe.app.fxcomps.augment.ContextMenuAugment;
import io.xpipe.app.fxcomps.augment.GrowAugment;
import io.xpipe.app.fxcomps.impl.IconButtonComp;
import io.xpipe.app.fxcomps.impl.LabelComp;
import io.xpipe.app.fxcomps.impl.PrettyImageHelper;
import io.xpipe.app.fxcomps.impl.TooltipAugment;
import io.xpipe.app.fxcomps.util.BindingsHelper;
import io.xpipe.app.fxcomps.util.DerivedObservableList;
@ -21,7 +22,6 @@ import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStoreEntry;
import io.xpipe.app.update.XPipeDistributionType;
import io.xpipe.app.util.*;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableDoubleValue;
@ -33,10 +33,6 @@ import javafx.scene.control.*;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import atlantafx.base.layout.InputGroup;
import atlantafx.base.theme.Styles;
import org.kordamp.ikonli.javafx.FontIcon;
import java.nio.file.Files;
@ -192,26 +188,7 @@ public abstract class StoreEntryComp extends SimpleComp {
}
protected Node createIcon(int w, int h) {
var img = getWrapper().disabledProperty().get()
? "disabled_icon.png"
: getWrapper()
.getEntry()
.getProvider()
.getDisplayIconFileName(getWrapper().getEntry().getStore());
var imageComp = PrettyImageHelper.ofFixedSize(img, w, h);
var storeIcon = imageComp.createRegion();
if (getWrapper().getValidity().getValue().isUsable()) {
new TooltipAugment<>(getWrapper().getEntry().getProvider().displayName(), null).augment(storeIcon);
}
var stack = new StackPane(storeIcon);
stack.setMinHeight(w + 7);
stack.setMinWidth(w + 7);
stack.setMaxHeight(w + 7);
stack.setMaxWidth(w + 7);
stack.getStyleClass().add("icon");
stack.setAlignment(Pos.CENTER);
return stack;
return new StoreIconComp(getWrapper(), w, h).createRegion();
}
protected Region createButtonBar() {

View file

@ -40,6 +40,7 @@ public class StoreEntryWrapper {
private final Property<StoreCategoryWrapper> category = new SimpleObjectProperty<>();
private final Property<String> summary = new SimpleObjectProperty<>();
private final Property<StoreNotes> notes;
private final Property<String> icon = new SimpleObjectProperty<>();
public StoreEntryWrapper(DataStoreEntry entry) {
this.entry = entry;
@ -137,6 +138,7 @@ public class StoreEntryWrapper {
}
color.setValue(entry.getColor());
notes.setValue(new StoreNotes(entry.getNotes(), entry.getNotes()));
icon.setValue(entry.getIcon());
busy.setValue(entry.getBusyCounter().get() != 0);
deletable.setValue(entry.getConfiguration().isDeletable()

View file

@ -0,0 +1,76 @@
package io.xpipe.app.comp.store;
import io.xpipe.app.core.AppImages;
import io.xpipe.app.core.AppResources;
import io.xpipe.app.fxcomps.SimpleComp;
import io.xpipe.app.fxcomps.impl.PrettyImageHelper;
import io.xpipe.app.fxcomps.impl.TooltipAugment;
import javafx.beans.binding.Bindings;
import javafx.geometry.Pos;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import lombok.AllArgsConstructor;
import org.kordamp.ikonli.javafx.FontIcon;
import java.util.concurrent.atomic.AtomicBoolean;
@AllArgsConstructor
public class StoreIconComp extends SimpleComp {
private final StoreEntryWrapper wrapper;
private final int w;
private final int h;
private static final AtomicBoolean loaded = new AtomicBoolean();
@Override
protected Region createSimple() {
var icon = Bindings.createStringBinding(() -> {
return getImage();
}, wrapper.getIcon());
var imageComp = PrettyImageHelper.ofFixedSize(icon, w, h);
var storeIcon = imageComp.createRegion();
if (wrapper.getValidity().getValue().isUsable()) {
new TooltipAugment<>(wrapper.getEntry().getProvider().displayName(), null).augment(storeIcon);
}
var dots = new FontIcon("mdi2d-dots-horizontal");
dots.setIconSize((int) (h * 1.3));
var stack = new StackPane(storeIcon, dots);
stack.setMinHeight(w + 7);
stack.setMinWidth(w + 7);
stack.setMaxHeight(w + 7);
stack.setMaxWidth(w + 7);
stack.getStyleClass().add("icon");
stack.setAlignment(Pos.CENTER);
dots.visibleProperty().bind(stack.hoverProperty());
storeIcon.opacityProperty().bind(Bindings.createDoubleBinding(() -> {
return stack.isHover() ? 0.5 : 1.0;
}, stack.hoverProperty()));
return stack;
}
private String getImage() {
if (wrapper.disabledProperty().get()) {
return "disabled_icon.png";
}
if (wrapper.getIcon().getValue() == null) {
return wrapper
.getEntry()
.getProvider()
.getDisplayIconFileName(wrapper.getEntry().getStore());
}
synchronized (loaded) {
if (!loaded.get()) {
AppImages.loadDirectory(AppResources.XPIPE_MODULE, "img/apps", true, false);
}
loaded.set(true);
return "app:apps/" + wrapper.getIcon().getValue();
}
}
}

View file

@ -1,18 +1,17 @@
package io.xpipe.app.storage;
import io.xpipe.app.ext.DataStoreProvider;
import io.xpipe.app.ext.DataStoreProviders;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.util.FixedHierarchyStore;
import io.xpipe.core.store.*;
import io.xpipe.core.util.JacksonMapper;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.xpipe.app.ext.DataStoreProvider;
import io.xpipe.app.ext.DataStoreProviders;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.util.FixedHierarchyStore;
import io.xpipe.core.store.*;
import io.xpipe.core.util.JacksonMapper;
import lombok.*;
import lombok.experimental.NonFinal;
import org.apache.commons.io.FileUtils;
@ -69,6 +68,8 @@ public class DataStoreEntry extends StorageElement {
@NonFinal
Order explicitOrder;
String icon;
private DataStoreEntry(
Path directory,
UUID uuid,
@ -85,7 +86,8 @@ public class DataStoreEntry extends StorageElement {
boolean expanded,
DataColor color,
String notes,
Order explicitOrder) {
Order explicitOrder, String icon
) {
super(directory, uuid, name, lastUsed, lastModified, color, expanded, dirty);
this.categoryUuid = categoryUuid;
this.store = store;
@ -96,6 +98,7 @@ public class DataStoreEntry extends StorageElement {
this.provider = store != null ? DataStoreProviders.byStore(store) : null;
this.storePersistentStateNode = storePersistentState;
this.notes = notes;
this.icon = icon;
}
private DataStoreEntry(
@ -106,11 +109,14 @@ public class DataStoreEntry extends StorageElement {
Instant lastUsed,
Instant lastModified,
DataStore store,
Order explicitOrder) {
Order explicitOrder,
String icon
) {
super(directory, uuid, name, lastUsed, lastModified, null, false, false);
this.categoryUuid = categoryUuid;
this.store = store;
this.explicitOrder = explicitOrder;
this.icon = icon;
this.storeNode = null;
this.validity = Validity.INCOMPLETE;
this.configuration = Configuration.defaultConfiguration();
@ -128,6 +134,7 @@ public class DataStoreEntry extends StorageElement {
Instant.now(),
Instant.now(),
store,
null,
null);
}
@ -160,6 +167,7 @@ public class DataStoreEntry extends StorageElement {
false,
null,
null,
null,
null);
return entry;
}
@ -195,6 +203,8 @@ public class DataStoreEntry extends StorageElement {
}
})
.orElse(null);
var iconNode = json.get("icon");
String icon = iconNode != null ? iconNode.asText() : null;
var persistentState = stateJson.get("persistentState");
var lastUsed = Optional.ofNullable(stateJson.get("lastUsed"))
@ -266,7 +276,8 @@ public class DataStoreEntry extends StorageElement {
expanded,
color,
notes,
order));
order,
icon));
}
public void setExplicitOrder(Order uuid) {
@ -380,6 +391,7 @@ public class DataStoreEntry extends StorageElement {
obj.put("name", name);
obj.put("categoryUuid", categoryUuid.toString());
obj.set("color", mapper.valueToTree(color));
obj.set("icons", mapper.valueToTree(icon));
stateObj.put("lastUsed", lastUsed.toString());
stateObj.put("lastModified", lastModified.toString());
stateObj.set("persistentState", storePersistentStateNode);

View file

@ -34,6 +34,10 @@
-fx-background-radius: 5px;
}
.store-entry-grid .icon:hover {
-fx-background-color: -color-bg-inset;
}
.root.nord .store-entry-grid .icon {
-fx-background-radius: 3;
}