From 63fdb633aa22de465e934a7e890e2b8be97bed43 Mon Sep 17 00:00:00 2001 From: LeeWyatt Date: Sat, 14 Oct 2023 03:29:09 +0900 Subject: [PATCH] Add ShadowDesignerView --- .../overviewbox/UtilityOverviewBox.java | 9 + .../paintpicker/impl/FXColorInfoPane.java | 10 +- .../paintpicker/impl/PaintPicker.java | 17 +- .../impl/colorpicker/ColorPicker.java | 2 + .../utilities/shadowdesigner/EffectEnum.java | 97 ++++++ .../shadowdesigner/EffectFlowPane.java | 158 +++++++++ .../shadowdesigner/ShadowDesignerView.java | 142 +++++++++ .../editor/BlendBottomInputEditor.java | 22 ++ .../editor/BlendTopInputEditor.java | 21 ++ .../shadowdesigner/editor/BloomEditor.java | 19 ++ .../shadowdesigner/editor/BoxBlurEditor.java | 21 ++ .../editor/ColorAdjustEditor.java | 22 ++ .../editor/ColorInputEditor.java | 24 ++ .../editor/DisplacementMapEditor.java | 24 ++ .../editor/DropShadowEditor.java | 27 ++ .../shadowdesigner/editor/EffectEditor.java | 122 +++++++ .../editor/EffectPropertyFactory.java | 110 +++++++ .../editor/EffectPropperty.java | 45 +++ .../editor/GaussianBlurEditor.java | 20 ++ .../shadowdesigner/editor/GlowEditor.java | 20 ++ .../editor/ImageInputEditor.java | 22 ++ .../editor/InnerShadowEditor.java | 27 ++ .../editor/LightingBumpInputEditor.java | 23 ++ .../editor/MotionBlurEditor.java | 21 ++ .../editor/PerspectiveTransformEditor.java | 27 ++ .../editor/ReflectionEditor.java | 23 ++ .../editor/SepiaToneEditor.java | 20 ++ .../shadowdesigner/editor/ShadowEditor.java | 25 ++ .../effect/BlendBottomInput.java | 13 + .../shadowdesigner/effect/BlendTopInput.java | 13 + .../effect/LightingBumpInput.java | 14 + .../effect/LightingContentInput.java | 14 + .../com/dlsc/jfxcentral2/utils/IkonUtil.java | 54 +++- .../dlsc/jfxcentral2/utils/NumberUtil.java | 12 +- components/src/main/java/module-info.java | 4 + .../resources/com/dlsc/jfxcentral2/theme.css | 300 +++++++++++++++++- .../utilities/paintpicker/paint-picker.css | 10 +- .../devtools/HelloShadowDesignerView.java | 17 + 38 files changed, 1556 insertions(+), 15 deletions(-) create mode 100644 components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/EffectEnum.java create mode 100644 components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/EffectFlowPane.java create mode 100644 components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/ShadowDesignerView.java create mode 100644 components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/BlendBottomInputEditor.java create mode 100644 components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/BlendTopInputEditor.java create mode 100644 components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/BloomEditor.java create mode 100644 components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/BoxBlurEditor.java create mode 100644 components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/ColorAdjustEditor.java create mode 100644 components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/ColorInputEditor.java create mode 100644 components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/DisplacementMapEditor.java create mode 100644 components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/DropShadowEditor.java create mode 100644 components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/EffectEditor.java create mode 100644 components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/EffectPropertyFactory.java create mode 100644 components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/EffectPropperty.java create mode 100644 components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/GaussianBlurEditor.java create mode 100644 components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/GlowEditor.java create mode 100644 components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/ImageInputEditor.java create mode 100644 components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/InnerShadowEditor.java create mode 100644 components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/LightingBumpInputEditor.java create mode 100644 components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/MotionBlurEditor.java create mode 100644 components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/PerspectiveTransformEditor.java create mode 100644 components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/ReflectionEditor.java create mode 100644 components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/SepiaToneEditor.java create mode 100644 components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/ShadowEditor.java create mode 100644 components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/effect/BlendBottomInput.java create mode 100644 components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/effect/BlendTopInput.java create mode 100644 components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/effect/LightingBumpInput.java create mode 100644 components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/effect/LightingContentInput.java create mode 100644 sampler/src/main/java/com/dlsc/jfxcentral2/demo/devtools/HelloShadowDesignerView.java diff --git a/components/src/main/java/com/dlsc/jfxcentral2/components/overviewbox/UtilityOverviewBox.java b/components/src/main/java/com/dlsc/jfxcentral2/components/overviewbox/UtilityOverviewBox.java index 1fdc6705..b16f5904 100644 --- a/components/src/main/java/com/dlsc/jfxcentral2/components/overviewbox/UtilityOverviewBox.java +++ b/components/src/main/java/com/dlsc/jfxcentral2/components/overviewbox/UtilityOverviewBox.java @@ -6,6 +6,7 @@ import com.dlsc.jfxcentral2.utilities.cssplayground.CssPlaygroundView; import com.dlsc.jfxcentral2.utilities.paintpicker.GradientDesignerView; import com.dlsc.jfxcentral2.utilities.pathextractor.SVGPathExtractorView; +import com.dlsc.jfxcentral2.utilities.shadowdesigner.ShadowDesignerView; import com.dlsc.jfxcentral2.utils.ModelObjectTool; import javafx.scene.Node; import javafx.scene.control.Label; @@ -16,6 +17,7 @@ import org.kordamp.ikonli.javafx.FontIcon; import org.kordamp.ikonli.material2.Material2OutlinedAL; import org.kordamp.ikonli.materialdesign2.MaterialDesignS; +import org.kordamp.ikonli.simplelineicons.SimpleLineIcons; public class UtilityOverviewBox extends OverviewBox { @@ -63,6 +65,13 @@ private Node createToolPane(Utility model) { setIcon(Material2OutlinedAL.COLOR_LENS); getStyleClass().add("gradient-designer-overview-box"); return new GradientDesignerView(sizeProperty()); + } else if (StringUtils.equalsIgnoreCase(model.getId(), "shadowdesigner")){ + setTitle("Shadow Designer"); + setIcon(SimpleLineIcons.MAGIC_WAND); + getStyleClass().add("shadow-designer-overview-box"); + ShadowDesignerView shadowDesignerView = new ShadowDesignerView(); + shadowDesignerView.sizeProperty().bind(sizeProperty()); + return shadowDesignerView; } return createComingSoonPane(); diff --git a/components/src/main/java/com/dlsc/jfxcentral2/utilities/paintpicker/impl/FXColorInfoPane.java b/components/src/main/java/com/dlsc/jfxcentral2/utilities/paintpicker/impl/FXColorInfoPane.java index 2c17e378..69c4e69f 100644 --- a/components/src/main/java/com/dlsc/jfxcentral2/utilities/paintpicker/impl/FXColorInfoPane.java +++ b/components/src/main/java/com/dlsc/jfxcentral2/utilities/paintpicker/impl/FXColorInfoPane.java @@ -2,6 +2,7 @@ import com.dlsc.jfxcentral2.utilities.paintpicker.impl.datamodel.ColorFormat; import com.dlsc.jfxcentral2.utils.IkonUtil; +import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.geometry.Insets; import javafx.geometry.Pos; @@ -60,6 +61,7 @@ public FXColorInfoPane() { fieldHsl.setText("0,0,0,1.0"); fieldRgb.setText("0,0,0,1.0"); fieldHex.setText("#000000FF"); + managedProperty().bind(visibleProperty()); buildUI(); } @@ -126,10 +128,10 @@ private void copyFXCodeOnClick() { Paint fxPaint = paintPickerController.paintProperty().get(); if (type == CodeType.JAVAFX_CODE) { String javaCode = PaintConvertUtil.convertPaintToJavaCode(fxPaint); - CopyUtil.setCopyOnClick(copyCodeBtn, javaCode); + Platform.runLater(() -> CopyUtil.setCopyOnClick(copyCodeBtn, javaCode)); } else if (type == CodeType.JAVAFX_CSS) { String cssCode = PaintConvertUtil.convertPaintToCss(fxPaint); - CopyUtil.setCopyOnClick(copyCodeBtn, cssCode); + Platform.runLater(() -> CopyUtil.setCopyOnClick(copyCodeBtn, cssCode)); } } } @@ -144,8 +146,8 @@ private BorderPane createColorPane(String text, TextField field) { Button copyBtn = new Button("", new FontIcon(IkonUtil.copy)); copyBtn.getStyleClass().addAll("fill-button", "copy-button"); pane.setRight(copyBtn); - CopyUtil.setCopyOnClick(copyBtn, text); - field.textProperty().addListener((ob, ov, nv) -> CopyUtil.setCopyOnClick(copyBtn, field.getText())); + Platform.runLater(() -> CopyUtil.setCopyOnClick(copyBtn, field.getText())); + field.textProperty().addListener((ob, ov, nv) -> Platform.runLater(() -> CopyUtil.setCopyOnClick(copyBtn, field.getText()))); return pane; } diff --git a/components/src/main/java/com/dlsc/jfxcentral2/utilities/paintpicker/impl/PaintPicker.java b/components/src/main/java/com/dlsc/jfxcentral2/utilities/paintpicker/impl/PaintPicker.java index 5bf75e7c..287dcc33 100644 --- a/components/src/main/java/com/dlsc/jfxcentral2/utilities/paintpicker/impl/PaintPicker.java +++ b/components/src/main/java/com/dlsc/jfxcentral2/utilities/paintpicker/impl/PaintPicker.java @@ -85,10 +85,12 @@ public PaintPicker(Delegate delegate) { modeSwitch.getToggles().addAll(colorToggleButton, linearToggleButton, radialToggleButton); - HBox hBox = new HBox( colorToggleButton, linearToggleButton, radialToggleButton); - hBox.setAlignment(Pos.CENTER_LEFT); + HBox modeButtonsBox = new HBox( colorToggleButton, linearToggleButton, radialToggleButton); + modeButtonsBox.setAlignment(Pos.CENTER_LEFT); + modeButtonsBox.getStyleClass().add("mode-buttons-box"); + modeButtonsBox.managedProperty().bind(modeButtonsBox.visibleProperty()); - root_vbox = new VBox(hBox); + root_vbox = new VBox(modeButtonsBox); root_vbox.setAlignment(Pos.CENTER); root_vbox.setMinHeight(-1.0); root_vbox.setPrefHeight(-1.0); @@ -111,7 +113,14 @@ public PaintPicker(Delegate delegate, PaintMode paintMode) { controller.setSingleMode(paintMode); } - + /** + * Creates a color picker. + */ + public static PaintPicker createColorPicker() { + PaintPicker paintPicker = new PaintPicker((warningKey, arguments) -> {}); + paintPicker.getStyleClass().add("only-color-mode"); + return paintPicker; + } public final ObjectProperty paintProperty() { return controller.paintProperty(); diff --git a/components/src/main/java/com/dlsc/jfxcentral2/utilities/paintpicker/impl/colorpicker/ColorPicker.java b/components/src/main/java/com/dlsc/jfxcentral2/utilities/paintpicker/impl/colorpicker/ColorPicker.java index 894b2651..e8540283 100644 --- a/components/src/main/java/com/dlsc/jfxcentral2/utilities/paintpicker/impl/colorpicker/ColorPicker.java +++ b/components/src/main/java/com/dlsc/jfxcentral2/utilities/paintpicker/impl/colorpicker/ColorPicker.java @@ -149,6 +149,7 @@ public ColorPicker(PaintPickerController pe) { chip_region = new Region(); hexaTextfield = new TextField(); hue_slider = new Slider(); + hue_slider.setFocusTraversable(false); gridPane = new GridPane(); stackPane0 = new StackPane(); region2 = new Region(); @@ -303,6 +304,7 @@ public ColorPicker(PaintPickerController pe) { alpha_region.setStyle(""); alpha_slider.setBlockIncrement(0.01); + alpha_slider.setFocusTraversable(false); alpha_slider.setMax(1.0); alpha_slider.getStyleClass().add("opacity-slider"); GridPane.setMargin(stackPane0, new Insets(0.0, 0.0, 2.0, 0.0)); diff --git a/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/EffectEnum.java b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/EffectEnum.java new file mode 100644 index 00000000..96622df1 --- /dev/null +++ b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/EffectEnum.java @@ -0,0 +1,97 @@ +package com.dlsc.jfxcentral2.utilities.shadowdesigner; + +import com.dlsc.jfxcentral2.utilities.shadowdesigner.effect.BlendBottomInput; +import com.dlsc.jfxcentral2.utilities.shadowdesigner.effect.BlendTopInput; +import javafx.scene.effect.Bloom; +import javafx.scene.effect.BoxBlur; +import javafx.scene.effect.ColorAdjust; +import javafx.scene.effect.ColorInput; +import javafx.scene.effect.DisplacementMap; +import javafx.scene.effect.DropShadow; +import javafx.scene.effect.Effect; +import javafx.scene.effect.GaussianBlur; +import javafx.scene.effect.Glow; +import javafx.scene.effect.ImageInput; +import javafx.scene.effect.InnerShadow; +import javafx.scene.effect.MotionBlur; +import javafx.scene.effect.PerspectiveTransform; +import javafx.scene.effect.Reflection; +import javafx.scene.effect.SepiaTone; +import javafx.scene.effect.Shadow; +import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public enum EffectEnum { + //BLEND("Blend", Blend.class), + BLEND_TOP_INPUT("Blend (TopInPut)", BlendTopInput.class), + BLEND_BOTTOM_INPUT("Blend (BottomInput)", BlendBottomInput.class), + BLOOM("Bloom", Bloom.class), + BOX_BLUR("BoxBlur", BoxBlur.class), + COLOR_ADJUST("ColorAdjust", ColorAdjust.class), + COLOR_INPUT("ColorInput", ColorInput.class), + DISPLACEMENT_MAP("DisplacementMap", DisplacementMap.class), + DROP_SHADOW("DropShadow", DropShadow.class), + GAUSSIAN_BLUR("GaussianBlur", GaussianBlur.class), + GLOW("Glow", Glow.class), + IMAGE_INPUT("ImageInput", ImageInput.class), + INNER_SHADOW("InnerShadow", InnerShadow.class), + //LIGHTING("Lighting", Lighting.class), + //LIGHTING_BUMP_INPUT("Lighting (BumpInput)", LightingBumpInput.class), + //LIGHTING_CONTENT_INPUT("Lighting (ContentInput)", LightingContentInput.class), + MOTION_BLUR("MotionBlur", MotionBlur.class), + PERSPECTIVE_TRANSFORM("PerspectiveTransform", PerspectiveTransform.class), + REFLECTION("Reflection", Reflection.class), + SEPIA_TONE("SepiaTone", SepiaTone.class), + SHADOW("Shadow", Shadow.class); + + private static final Logger LOGGER = LogManager.getLogger(EffectEnum.class); + private final String name; + private final Class effectClass; + + EffectEnum(String name, Class effectClass) { + this.name = name; + this.effectClass = effectClass; + } + + public String getName() { + return name; + } + + public Class getEffectClass() { + return effectClass; + } + + public static Class[] getAllEffectClass() { + EffectEnum[] values = EffectEnum.values(); + Class[] classes = new Class[values.length]; + for (int i = 0; i < values.length; i++) { + classes[i] = values[i].getEffectClass(); + } + return classes; + } + + public static String[] getAllNames() { + EffectEnum[] values = EffectEnum.values(); + String[] names = new String[values.length]; + for (int i = 0; i < values.length; i++) { + names[i] = values[i].getName(); + } + return names; + } + + public static EffectEnum findByName(String name) { + EffectEnum[] values = EffectEnum.values(); + for (EffectEnum value : values) { + if (StringUtils.equalsIgnoreCase(value.getName(), name)) { + return value; + } + } + return null; + } + + @Override + public String toString() { + return name; + } +} diff --git a/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/EffectFlowPane.java b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/EffectFlowPane.java new file mode 100644 index 00000000..24ae6fc4 --- /dev/null +++ b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/EffectFlowPane.java @@ -0,0 +1,158 @@ +package com.dlsc.jfxcentral2.utilities.shadowdesigner; + +import com.dlsc.jfxcentral2.components.CustomToggleButton; +import javafx.beans.InvalidationListener; +import javafx.beans.binding.Bindings; +import javafx.beans.property.ReadOnlyObjectProperty; +import javafx.beans.property.ReadOnlyObjectWrapper; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.scene.control.MenuButton; +import javafx.scene.control.MenuItem; +import javafx.scene.control.Toggle; +import javafx.scene.control.ToggleGroup; +import javafx.scene.effect.Blend; +import javafx.scene.effect.Effect; +import javafx.scene.layout.FlowPane; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.kordamp.ikonli.javafx.FontIcon; +import org.kordamp.ikonli.material2.Material2AL; +import org.kordamp.ikonli.material2.Material2OutlinedMZ; + +import java.lang.reflect.InvocationTargetException; +import java.util.Arrays; +import java.util.List; + +public class EffectFlowPane extends FlowPane { + private static final Logger LOGGER = LogManager.getLogger(EffectFlowPane.class); + private static final ToggleGroup TOGGLE_GROUP = new ToggleGroup(); + + public EffectFlowPane() { + getStyleClass().add("effect-flow-pane"); + + value.bind(Bindings.createObjectBinding(() -> effects.stream().reduce((effect1, effect2) -> { + if (effect2 instanceof Blend blend2) { + blend2.setTopInput(effect1); + return blend2; + } + + if (supportsInputMethod(effect2)) { + try { + effect2.getClass().getMethod("setInput", Effect.class).invoke(effect2, effect1); + } catch (Exception e) { + LOGGER.error("Error while setting input for effect", e); + } + } + return effect2; + }).orElse(null), effects)); + + effects.addListener((InvalidationListener) it -> { + Toggle selectedToggle = TOGGLE_GROUP.getSelectedToggle(); + int index = TOGGLE_GROUP.getToggles().indexOf(selectedToggle); + Effect selectedEffect; + if (selectedToggle != null && index >= 0 && index < effects.size()) { + selectedEffect = effects.get(index); + } else { + selectedEffect = null; + } + TOGGLE_GROUP.getToggles().clear(); + int lastIndex = getChildren().size() - 1; + getChildren().remove(0, lastIndex); + effects.forEach(effect -> { + int i = getChildren().size() - 1; + CustomToggleButton effectButton = new CustomToggleButton((i + 1) + " " + effect.getClass().getSimpleName()); + effectButton.getStyleClass().add("effect-button"); + effectButton.setFocusTraversable(false); + if (i != effects.size() - 1) { + effectButton.setGraphic(new FontIcon(Material2OutlinedMZ.NAVIGATE_NEXT)); + } + getChildren().add(i, effectButton); + effectButton.setToggleGroup(TOGGLE_GROUP); + }); + //effects.forEach(effect -> { + // CustomToggleButton effectView = (CustomToggleButton) getChildren().get(effects.indexOf(effect)); + // effectView.setSelected(effect == selectedEffect); + //}); + }); + + MenuButton addEffectButton = new MenuButton("Add Effect"); + addEffectButton.setFocusTraversable(false); + addEffectButton.setGraphic(new FontIcon(Material2AL.ADD_CIRCLE)); + addEffectButton.getStyleClass().add("fill-button"); + getChildren().add(addEffectButton); + + List menuItems = Arrays.stream(EffectEnum.getAllNames()) + .map(name -> { + MenuItem menuItem = new MenuItem(name); + menuItem.setOnAction(event -> { + try { + EffectEnum effectEnum = EffectEnum.findByName(name); + if (effectEnum == null) { + return; + } + Effect effect = effectEnum.getEffectClass().getDeclaredConstructor().newInstance(); + effects.add(effect); + } catch (InstantiationException | IllegalAccessException | InvocationTargetException | + NoSuchMethodException e) { + LOGGER.error("Error while creating effect", e); + } + }); + return menuItem; + }) + .toList(); + addEffectButton.getItems().addAll(menuItems); + + TOGGLE_GROUP.selectedToggleProperty().addListener((ob, ov, nv) -> { + if (nv == null) { + setSelectedEffect(null); + return; + } + setSelectedEffect(effects.get(TOGGLE_GROUP.getToggles().indexOf(nv))); + }); + + } + + private final ObservableList effects = FXCollections.observableArrayList(); + + public ObservableList getEffects() { + return effects; + } + + private final ReadOnlyObjectWrapper value = new ReadOnlyObjectWrapper<>(this, "value", null); + + public Effect getValue() { + return value.get(); + } + + public ReadOnlyObjectProperty valueProperty() { + return value.getReadOnlyProperty(); + } + + private void setValue(Effect value) { + this.value.set(value); + } + + private boolean supportsInputMethod(Effect effect) { + try { + effect.getClass().getMethod("setInput", Effect.class); + return true; + } catch (NoSuchMethodException e) { + return false; + } + } + + private final ReadOnlyObjectWrapper selectedEffect = new ReadOnlyObjectWrapper<>(this, "selectedEffect"); + + public Effect getSelectedEffect() { + return selectedEffect.get(); + } + + public ReadOnlyObjectProperty selectedEffectProperty() { + return selectedEffect.getReadOnlyProperty(); + } + + private void setSelectedEffect(Effect selectedEffect) { + this.selectedEffect.set(selectedEffect); + } +} diff --git a/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/ShadowDesignerView.java b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/ShadowDesignerView.java new file mode 100644 index 00000000..6038520d --- /dev/null +++ b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/ShadowDesignerView.java @@ -0,0 +1,142 @@ +package com.dlsc.jfxcentral2.utilities.shadowdesigner; + +import com.dlsc.jfxcentral2.components.PaneBase; +import com.dlsc.jfxcentral2.utilities.shadowdesigner.editor.BlendBottomInputEditor; +import com.dlsc.jfxcentral2.utilities.shadowdesigner.editor.BlendTopInputEditor; +import com.dlsc.jfxcentral2.utilities.shadowdesigner.editor.BloomEditor; +import com.dlsc.jfxcentral2.utilities.shadowdesigner.editor.BoxBlurEditor; +import com.dlsc.jfxcentral2.utilities.shadowdesigner.editor.ColorAdjustEditor; +import com.dlsc.jfxcentral2.utilities.shadowdesigner.editor.ColorInputEditor; +import com.dlsc.jfxcentral2.utilities.shadowdesigner.editor.DisplacementMapEditor; +import com.dlsc.jfxcentral2.utilities.shadowdesigner.editor.DropShadowEditor; +import com.dlsc.jfxcentral2.utilities.shadowdesigner.editor.GaussianBlurEditor; +import com.dlsc.jfxcentral2.utilities.shadowdesigner.editor.GlowEditor; +import com.dlsc.jfxcentral2.utilities.shadowdesigner.editor.ImageInputEditor; +import com.dlsc.jfxcentral2.utilities.shadowdesigner.editor.InnerShadowEditor; +import com.dlsc.jfxcentral2.utilities.shadowdesigner.editor.MotionBlurEditor; +import com.dlsc.jfxcentral2.utilities.shadowdesigner.editor.PerspectiveTransformEditor; +import com.dlsc.jfxcentral2.utilities.shadowdesigner.editor.ReflectionEditor; +import com.dlsc.jfxcentral2.utilities.shadowdesigner.editor.SepiaToneEditor; +import com.dlsc.jfxcentral2.utilities.shadowdesigner.editor.ShadowEditor; +import com.dlsc.jfxcentral2.utilities.shadowdesigner.effect.BlendBottomInput; +import com.dlsc.jfxcentral2.utilities.shadowdesigner.effect.BlendTopInput; +import javafx.beans.InvalidationListener; +import javafx.beans.binding.Bindings; +import javafx.geometry.Pos; +import javafx.scene.Node; +import javafx.scene.control.Label; +import javafx.scene.effect.Bloom; +import javafx.scene.effect.BoxBlur; +import javafx.scene.effect.ColorAdjust; +import javafx.scene.effect.ColorInput; +import javafx.scene.effect.DisplacementMap; +import javafx.scene.effect.DropShadow; +import javafx.scene.effect.Effect; +import javafx.scene.effect.GaussianBlur; +import javafx.scene.effect.Glow; +import javafx.scene.effect.ImageInput; +import javafx.scene.effect.InnerShadow; +import javafx.scene.effect.MotionBlur; +import javafx.scene.effect.PerspectiveTransform; +import javafx.scene.effect.Reflection; +import javafx.scene.effect.SepiaTone; +import javafx.scene.effect.Shadow; +import javafx.scene.layout.FlowPane; +import javafx.scene.layout.StackPane; +import javafx.scene.layout.VBox; + +public class ShadowDesignerView extends PaneBase { + + public ShadowDesignerView() { + getStyleClass().add("shadow-designer-view"); + setAlignment(Pos.TOP_LEFT); + + StackPane previewPane = new StackPane(); + previewPane.getStyleClass().add("effect-preview-pane"); + previewPane.getChildren().add(new Label("Preview Pane")); + + EffectFlowPane effectFlowPane = new EffectFlowPane(); + previewPane.effectProperty().bind(effectFlowPane.valueProperty()); + + StackPane effectPaneWrapper = new StackPane(); + effectPaneWrapper.getStyleClass().add("effect-pane-wrapper"); + effectPaneWrapper.managedProperty().bind(effectPaneWrapper.visibleProperty()); + effectPaneWrapper.visibleProperty().bind(effectFlowPane.selectedEffectProperty().isNotNull()); + + effectFlowPane.selectedEffectProperty().addListener((ob, ov, newEffect) -> { + if (newEffect == null) { + effectPaneWrapper.getChildren().clear(); + } + Node node = createOptionPane(newEffect, () -> effectFlowPane.getEffects().remove(newEffect)); + if (node == null) { + effectPaneWrapper.getChildren().clear(); + } else { + effectPaneWrapper.getChildren().setAll(node); + } + }); + + VBox leftBox = new VBox(previewPane); + leftBox.getStyleClass().add("left-box"); + + VBox rightBox = new VBox(effectFlowPane, effectPaneWrapper); + rightBox.getStyleClass().addAll("right-box", "with-non-effect"); + rightBox.alignmentProperty().bind(Bindings.createObjectBinding(() -> + effectPaneWrapper.isVisible() && !effectFlowPane.getEffects().isEmpty() ? Pos.TOP_LEFT : Pos.CENTER, effectPaneWrapper.visibleProperty())); + + effectFlowPane.getEffects().addListener((InvalidationListener) observable -> { + if (effectFlowPane.getEffects().isEmpty()) { + if (!rightBox.getStyleClass().contains("with-non-effect")) { + rightBox.getStyleClass().add("with-non-effect"); + } + } else { + rightBox.getStyleClass().remove("with-non-effect"); + } + }); + + FlowPane flowPane = new FlowPane(leftBox, rightBox); + flowPane.getStyleClass().add("flow-pane"); + + getChildren().addAll(flowPane); + } + + private Node createOptionPane(Effect newEffect, Runnable deleteAction) { + Node node = null; + if (newEffect instanceof BlendTopInput effect) { + node = new BlendTopInputEditor(effect, deleteAction); + } else if (newEffect instanceof BlendBottomInput effect) { + node = new BlendBottomInputEditor(effect, deleteAction); + } else if (newEffect instanceof Bloom effect) { + node = new BloomEditor(effect, deleteAction); + } else if (newEffect instanceof BoxBlur effect) { + node = new BoxBlurEditor(effect, deleteAction); + } else if (newEffect instanceof ColorAdjust effect) { + node = new ColorAdjustEditor(effect, deleteAction); + } else if (newEffect instanceof ColorInput effect) { + node = new ColorInputEditor(effect, deleteAction); + } else if (newEffect instanceof DisplacementMap effect) { + node = new DisplacementMapEditor(effect, deleteAction); + } else if (newEffect instanceof DropShadow effect) { + node = new DropShadowEditor(effect, deleteAction); + } else if (newEffect instanceof GaussianBlur effect) { + node = new GaussianBlurEditor(effect, deleteAction); + } else if (newEffect instanceof Glow effect) { + node = new GlowEditor(effect, deleteAction); + } else if (newEffect instanceof ImageInput effect) { + node = new ImageInputEditor(effect, deleteAction); + } else if (newEffect instanceof InnerShadow effect) { + node = new InnerShadowEditor(effect, deleteAction); + } else if (newEffect instanceof MotionBlur effect) { + node = new MotionBlurEditor(effect, deleteAction); + } else if (newEffect instanceof PerspectiveTransform effect) { + node = new PerspectiveTransformEditor(effect, deleteAction); + } else if (newEffect instanceof Reflection effect) { + node = new ReflectionEditor(effect, deleteAction); + } else if (newEffect instanceof SepiaTone effect) { + node = new SepiaToneEditor(effect, deleteAction); + } else if (newEffect instanceof Shadow effect) { + node = new ShadowEditor(effect, deleteAction); + } + return node; + } + +} diff --git a/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/BlendBottomInputEditor.java b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/BlendBottomInputEditor.java new file mode 100644 index 00000000..edf36135 --- /dev/null +++ b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/BlendBottomInputEditor.java @@ -0,0 +1,22 @@ +package com.dlsc.jfxcentral2.utilities.shadowdesigner.editor; + +import com.dlsc.jfxcentral2.utilities.shadowdesigner.effect.BlendBottomInput; +import com.dlsc.jfxcentral2.utils.IkonUtil; +import javafx.scene.effect.BlendMode; + +import java.util.List; + +public class BlendBottomInputEditor extends EffectEditor { + + public BlendBottomInputEditor(BlendBottomInput effect, Runnable deleteAction) { + super(effect, deleteAction); + } + + @Override + protected List createOptions(BlendBottomInput effect) { + return List.of( + EffectPropertyFactory.create("Mode", IkonUtil.blendMode, BlendMode.class, null, effect.modeProperty()), + EffectPropertyFactory.create("Opacity", IkonUtil.opacity, 0, 1, 1, effect.opacityProperty()) + ); + } +} diff --git a/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/BlendTopInputEditor.java b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/BlendTopInputEditor.java new file mode 100644 index 00000000..a19caa88 --- /dev/null +++ b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/BlendTopInputEditor.java @@ -0,0 +1,21 @@ +package com.dlsc.jfxcentral2.utilities.shadowdesigner.editor; + +import com.dlsc.jfxcentral2.utilities.shadowdesigner.effect.BlendTopInput; +import com.dlsc.jfxcentral2.utils.IkonUtil; +import javafx.scene.effect.BlendMode; + +import java.util.List; + +public class BlendTopInputEditor extends EffectEditor { + public BlendTopInputEditor(BlendTopInput effect, Runnable deleteAction) { + super(effect, deleteAction); + } + + @Override + protected List createOptions(BlendTopInput effect) { + return List.of( + EffectPropertyFactory.create("Mode", IkonUtil.blendMode, BlendMode.class, null, effect.modeProperty()), + EffectPropertyFactory.create("Opacity", IkonUtil.opacity, 0, 1, 1, effect.opacityProperty()) + ); + } +} diff --git a/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/BloomEditor.java b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/BloomEditor.java new file mode 100644 index 00000000..2f252c12 --- /dev/null +++ b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/BloomEditor.java @@ -0,0 +1,19 @@ +package com.dlsc.jfxcentral2.utilities.shadowdesigner.editor; + +import com.dlsc.jfxcentral2.utils.IkonUtil; +import javafx.scene.effect.Bloom; + +import java.util.List; + +public class BloomEditor extends EffectEditor { + + public BloomEditor(Bloom effect, Runnable deleteAction) { + super(effect, deleteAction); + } + + @Override + protected List createOptions(Bloom effect) { + return List.of( + EffectPropertyFactory.create("Threshold", IkonUtil.threshold, 0, 1, 0.3, effect.thresholdProperty())); + } +} diff --git a/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/BoxBlurEditor.java b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/BoxBlurEditor.java new file mode 100644 index 00000000..555cb655 --- /dev/null +++ b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/BoxBlurEditor.java @@ -0,0 +1,21 @@ +package com.dlsc.jfxcentral2.utilities.shadowdesigner.editor; + +import com.dlsc.jfxcentral2.utils.IkonUtil; +import javafx.scene.effect.BoxBlur; + +import java.util.List; + +public class BoxBlurEditor extends EffectEditor { + public BoxBlurEditor(BoxBlur effect, Runnable deleteAction) { + super(effect, deleteAction); + } + + @Override + protected List createOptions(BoxBlur effect) { + return List.of( + EffectPropertyFactory.create("Width", IkonUtil.width, 0, 255, 5, effect.widthProperty()), + EffectPropertyFactory.create("Height", IkonUtil.height, 0, 255, 5, effect.heightProperty()), + EffectPropertyFactory.create("Iterations", IkonUtil.iterations, 0, 3, 1, effect.iterationsProperty())); + } + +} diff --git a/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/ColorAdjustEditor.java b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/ColorAdjustEditor.java new file mode 100644 index 00000000..bbbf7a46 --- /dev/null +++ b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/ColorAdjustEditor.java @@ -0,0 +1,22 @@ +package com.dlsc.jfxcentral2.utilities.shadowdesigner.editor; + +import com.dlsc.jfxcentral2.utils.IkonUtil; +import javafx.scene.effect.ColorAdjust; + +import java.util.List; + +public class ColorAdjustEditor extends EffectEditor { + + public ColorAdjustEditor(ColorAdjust effect, Runnable deleteAction) { + super(effect, deleteAction); + } + + @Override + protected List createOptions(ColorAdjust effect) { + return List.of( + EffectPropertyFactory.create("Hue", IkonUtil.hue, -1, 1, 0, effect.hueProperty()), + EffectPropertyFactory.create("Saturation", IkonUtil.saturation, -1, 1, 0, effect.saturationProperty()), + EffectPropertyFactory.create("Brightness", IkonUtil.brightness, -1, 1, 0, effect.brightnessProperty()), + EffectPropertyFactory.create("Contrast", IkonUtil.contrast, -1, 1, 0, effect.contrastProperty())); + } +} diff --git a/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/ColorInputEditor.java b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/ColorInputEditor.java new file mode 100644 index 00000000..0514ba15 --- /dev/null +++ b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/ColorInputEditor.java @@ -0,0 +1,24 @@ +package com.dlsc.jfxcentral2.utilities.shadowdesigner.editor; + +import com.dlsc.jfxcentral2.utils.IkonUtil; +import javafx.scene.effect.ColorInput; + +import java.util.List; + +public class ColorInputEditor extends EffectEditor { + + public ColorInputEditor(ColorInput effect, Runnable deleteAction) { + super(effect, deleteAction); + } + + @Override + protected List createOptions(ColorInput effect) { + return List.of( + EffectPropertyFactory.create("X", IkonUtil.x, -10, 10, 0, effect.xProperty()), + EffectPropertyFactory.create("Y", IkonUtil.y, -10, 10, 0, effect.yProperty()), + EffectPropertyFactory.create("Width", IkonUtil.width, 0, 255, 0, effect.widthProperty()), + EffectPropertyFactory.create("Height", IkonUtil.height, 0, 255, 0, effect.heightProperty()), + EffectPropertyFactory.createWithPaintPicker("Paint", IkonUtil.color, effect.paintProperty()) + ); + } +} diff --git a/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/DisplacementMapEditor.java b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/DisplacementMapEditor.java new file mode 100644 index 00000000..0bc8dff6 --- /dev/null +++ b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/DisplacementMapEditor.java @@ -0,0 +1,24 @@ +package com.dlsc.jfxcentral2.utilities.shadowdesigner.editor; + +import com.dlsc.jfxcentral2.utils.IkonUtil; +import javafx.scene.effect.DisplacementMap; + +import java.util.List; + +public class DisplacementMapEditor extends EffectEditor { + + public DisplacementMapEditor(DisplacementMap effect, Runnable deleteAction) { + super(effect, deleteAction); + } + + @Override + protected List createOptions(DisplacementMap effect) { + return List.of( + EffectPropertyFactory.create("OffsetX", IkonUtil.offsetX, -10, 10, 0, effect.offsetXProperty()), + EffectPropertyFactory.create("OffsetY", IkonUtil.offsetY, -10, 10, 0, effect.offsetYProperty()), + EffectPropertyFactory.create("ScaleX", IkonUtil.scaleX, -10, 10, 1.0, effect.scaleXProperty()), + EffectPropertyFactory.create("ScaleY", IkonUtil.scaleY, -10, 10, 1.0, effect.scaleYProperty()), + EffectPropertyFactory.create("Wrap", IkonUtil.wrap, effect.wrapProperty()) + ); + } +} diff --git a/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/DropShadowEditor.java b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/DropShadowEditor.java new file mode 100644 index 00000000..38c22d51 --- /dev/null +++ b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/DropShadowEditor.java @@ -0,0 +1,27 @@ +package com.dlsc.jfxcentral2.utilities.shadowdesigner.editor; + +import com.dlsc.jfxcentral2.utils.IkonUtil; +import javafx.scene.effect.BlurType; +import javafx.scene.effect.DropShadow; + +import java.util.List; + +public class DropShadowEditor extends EffectEditor { + public DropShadowEditor(DropShadow dropShadow, Runnable deleteAction) { + super(dropShadow, deleteAction); + } + + @Override + protected List createOptions(DropShadow effect) { + return List.of( + EffectPropertyFactory.create("BlurType", IkonUtil.blur, BlurType.class, null, effect.blurTypeProperty()), + EffectPropertyFactory.create("Width", IkonUtil.width, 0, 255, 21, effect.widthProperty()), + EffectPropertyFactory.create("Height", IkonUtil.height, 0, 255, 21, effect.heightProperty()), + EffectPropertyFactory.create("Radius", IkonUtil.radius, 0, 127, 10, effect.radiusProperty()), + EffectPropertyFactory.create("OffsetX", IkonUtil.offsetX, -10, 10, 0, effect.offsetXProperty()), + EffectPropertyFactory.create("OffsetY", IkonUtil.offsetY, -10, 10, 0, effect.offsetYProperty()), + EffectPropertyFactory.create("Spread", IkonUtil.spread, 0, 1, 0, effect.spreadProperty()), + EffectPropertyFactory.createWithColorPicker("Color", IkonUtil.color, effect.colorProperty()) + ); + } +} diff --git a/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/EffectEditor.java b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/EffectEditor.java new file mode 100644 index 00000000..4020b7a6 --- /dev/null +++ b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/EffectEditor.java @@ -0,0 +1,122 @@ +package com.dlsc.jfxcentral2.utilities.shadowdesigner.editor; + +import com.dlsc.gemsfx.Spacer; +import com.dlsc.jfxcentral2.utils.IkonUtil; +import com.dlsc.jfxcentral2.utils.StringUtil; +import javafx.concurrent.Service; +import javafx.concurrent.Task; +import javafx.geometry.VPos; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.effect.Effect; +import javafx.scene.layout.ColumnConstraints; +import javafx.scene.layout.GridPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.RowConstraints; +import javafx.scene.layout.VBox; +import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.kordamp.ikonli.antdesignicons.AntDesignIconsOutlined; +import org.kordamp.ikonli.fontawesome.FontAwesome; +import org.kordamp.ikonli.javafx.FontIcon; + +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.IntStream; + +public abstract class EffectEditor extends VBox { + private static final Logger LOGGER = LogManager.getLogger(EffectEditor.class); + private final T effect; + + public EffectEditor(T effect, Runnable deleteAction) { + this.effect = effect; + getStyleClass().add("effect-editor"); + + Label titleLabel = new Label(effect.getClass().getSimpleName()); + titleLabel.getStyleClass().add("title-label"); + titleLabel.setGraphic(new FontIcon(FontAwesome.SLIDERS)); + getChildren().add(titleLabel); + + Button deleteButton = new Button(); + deleteButton.getStyleClass().addAll("fill-button", "delete-button"); + deleteButton.setGraphic(new FontIcon(IkonUtil.delete)); + deleteButton.setFocusTraversable(false); + deleteButton.setOnAction(event -> { + if (deleteAction != null) { + deleteAction.run(); + } + }); + + HBox topBox = new HBox(titleLabel, new Spacer(), deleteButton); + topBox.getStyleClass().add("top-box"); + getChildren().add(topBox); + + Label tipsLabel = new Label(StringUtil.LOADING_TIPS); + tipsLabel.getStyleClass().add("tips-label"); + tipsLabel.setGraphic(new FontIcon(AntDesignIconsOutlined.CLOUD_DOWNLOAD)); + getChildren().add(tipsLabel); + + Service propertiesEditorService = createPropertiesEditorService(); + propertiesEditorService.setOnSucceeded(event -> { + GridPane contentPane = propertiesEditorService.getValue(); + getChildren().remove(tipsLabel); + getChildren().add(contentPane); + }); + + propertiesEditorService.setOnFailed(event -> { + Throwable ex = event.getSource().getException(); + LOGGER.error("Properties editor service failed", ex); + }); + + propertiesEditorService.start(); + } + + public T getData() { + return effect; + } + + private Service createPropertiesEditorService() { + return new Service<>() { + @Override + protected Task createTask() { + return new Task<>() { + @Override + protected GridPane call() throws Exception { + GridPane contentPane = new GridPane(); + contentPane.getStyleClass().add("content-pane"); + AtomicBoolean containBlurType = new AtomicBoolean(false); + List options = createOptions(effect); + IntStream.range(0, options.size()) + .forEachOrdered(i -> { + EffectPropperty option = options.get(i); + String title = option.getTitle(); + if (StringUtils.equalsAnyIgnoreCase(title, "BlurType", "Blur Type")) { + containBlurType.set(true); + } + Label propertyNameLabel = new Label(title); + propertyNameLabel.getStyleClass().add("property-name-label"); + if (option.getIkon() != null) { + propertyNameLabel.setGraphic(new FontIcon(option.getIkon())); + } + contentPane.add(propertyNameLabel, 0, i); + contentPane.add(option.getNode(), 1, i); + RowConstraints rowConstraints = new RowConstraints(); + rowConstraints.setValignment(VPos.TOP); + contentPane.getRowConstraints().add(rowConstraints); + }); + if (containBlurType.get()) { + ColumnConstraints col = new ColumnConstraints(); + col.setPrefWidth(95); + contentPane.getColumnConstraints().add(col); + } + return contentPane; + } + }; + } + }; + } + + protected abstract List createOptions(T effect); + +} diff --git a/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/EffectPropertyFactory.java b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/EffectPropertyFactory.java new file mode 100644 index 00000000..1ef35bb4 --- /dev/null +++ b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/EffectPropertyFactory.java @@ -0,0 +1,110 @@ +package com.dlsc.jfxcentral2.utilities.shadowdesigner.editor; + +import com.dlsc.jfxcentral2.components.FileHandlerView; +import com.dlsc.jfxcentral2.utilities.paintpicker.impl.PaintPicker; +import com.dlsc.jfxcentral2.utils.NumberUtil; +import javafx.beans.binding.Bindings; +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.DoubleProperty; +import javafx.beans.property.IntegerProperty; +import javafx.beans.property.ObjectProperty; +import javafx.scene.control.CheckBox; +import javafx.scene.control.ComboBox; +import javafx.scene.control.Label; +import javafx.scene.control.Slider; +import javafx.scene.control.Spinner; +import javafx.scene.control.TextField; +import javafx.scene.image.Image; +import javafx.scene.layout.HBox; +import javafx.scene.layout.VBox; +import javafx.scene.paint.Color; +import javafx.scene.paint.Paint; +import javafx.util.StringConverter; +import org.kordamp.ikonli.Ikon; + +public class EffectPropertyFactory { + + public static > EffectPropperty create(String title, Ikon ikon, Class enumClass, StringConverter stringConverter, ObjectProperty valueProperty) { + ComboBox comboBox = new ComboBox<>(); + comboBox.getStyleClass().add("md-combo-box"); + comboBox.setFocusTraversable(false); + comboBox.setConverter(stringConverter); + comboBox.getItems().addAll(enumClass.getEnumConstants()); + comboBox.getSelectionModel().select(valueProperty.get()); + comboBox.valueProperty().addListener((ob, ov, nv) -> valueProperty.set(nv)); + + return new EffectPropperty(title, ikon, comboBox); + } + + public static EffectPropperty create(String title, Ikon ikon, double min, double max, double current, DoubleProperty valueProperty) { + Slider slider = new Slider(min, max, current); + slider.setFocusTraversable(false); + slider.setMajorTickUnit(max); + slider.setMinorTickCount(0); + slider.setShowTickLabels(true); + slider.valueProperty().addListener((ob, ov, nv) -> valueProperty.set(nv.doubleValue())); + Label valueLabel = new Label(); + valueLabel.getStyleClass().add("value-label"); + valueLabel.textProperty().bind(Bindings.createObjectBinding(() -> { + double value = valueProperty.get(); + slider.setValue(value); + return NumberUtil.trimTrailingZeros(value); + }, valueProperty)); + HBox sliderBox = new HBox(10, slider, valueLabel); + sliderBox.getStyleClass().add("slider-box"); + return new EffectPropperty(title, ikon, sliderBox); + } + + public static EffectPropperty create(String title, Ikon ikon, int min, int max, int current, IntegerProperty valueProperty) { + Spinner spinner = new Spinner<>(min, max, current); + spinner.valueProperty().addListener((ob, ov, nv) -> valueProperty.set(nv)); + spinner.setFocusTraversable(false); + return new EffectPropperty(title, ikon, spinner); + } + + public static EffectPropperty create(String title, Ikon ikon, BooleanProperty valueProperty) { + CheckBox checkBox = new CheckBox(); + checkBox.setFocusTraversable(false); + checkBox.selectedProperty().bindBidirectional(valueProperty); + return new EffectPropperty(title, ikon, checkBox); + } + + public static EffectPropperty createWithColorPicker(String title, Ikon ikon, ObjectProperty valueProperty) { + PaintPicker colorPicker = PaintPicker.createColorPicker(); + colorPicker.setFocusTraversable(false); + colorPicker.setPaintProperty(valueProperty.get()); + colorPicker.paintProperty().addListener((ob, ov, nv) -> + valueProperty.set(nv instanceof Color color ? color : Color.TRANSPARENT)); + return new EffectPropperty(title, ikon, colorPicker); + } + + public static EffectPropperty createWithPaintPicker(String title, Ikon ikon, ObjectProperty valueProperty) { + PaintPicker paintPicker = new PaintPicker(); + paintPicker.setFocusTraversable(false); + paintPicker.setPaintProperty(valueProperty.get()); + paintPicker.paintProperty().addListener((ob, ov, nv) -> valueProperty.set(nv)); + return new EffectPropperty(title, ikon, paintPicker); + } + + public static EffectPropperty create(String title, Ikon ikon, ObjectProperty valueProperty) { + TextField fileNameField = new TextField(); + fileNameField.getStyleClass().add("file-name-label"); + fileNameField.setEditable(false); + fileNameField.setFocusTraversable(false); + fileNameField.managedProperty().bind(fileNameField.visibleProperty()); + fileNameField.visibleProperty().bind(valueProperty.isNotNull()); + + FileHandlerView fileHandlerView = new FileHandlerView(false, false, true); + fileHandlerView.getSupportedExtensions().addAll(".png", ".jpg", ".jpeg", ".gif"); + fileHandlerView.setText("Click or drop Image file here"); + fileHandlerView.setOnUploadedFile(file -> { + valueProperty.set(new Image(file.toURI().toString())); + fileNameField.setText(file.getName()); + }); + + VBox fileBox = new VBox(fileNameField, fileHandlerView); + fileBox.getStyleClass().add("file-box"); + return new EffectPropperty(title, ikon, fileBox); + } + +} diff --git a/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/EffectPropperty.java b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/EffectPropperty.java new file mode 100644 index 00000000..773f114d --- /dev/null +++ b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/EffectPropperty.java @@ -0,0 +1,45 @@ +package com.dlsc.jfxcentral2.utilities.shadowdesigner.editor; + +import javafx.scene.Node; +import org.kordamp.ikonli.Ikon; + +public class EffectPropperty { + private String title; + private Ikon ikon; + private Node node; + + public EffectPropperty() { + } + + public EffectPropperty(String title, Ikon ikon, Node node) { + this.title = title; + this.ikon = ikon; + this.node = node; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Ikon getIkon() { + return ikon; + } + + public void setIkon(Ikon ikon) { + this.ikon = ikon; + } + + public Node getNode() { + return node; + } + + public void setNode(Node node) { + this.node = node; + } + +} + diff --git a/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/GaussianBlurEditor.java b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/GaussianBlurEditor.java new file mode 100644 index 00000000..7b27aff0 --- /dev/null +++ b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/GaussianBlurEditor.java @@ -0,0 +1,20 @@ +package com.dlsc.jfxcentral2.utilities.shadowdesigner.editor; + +import com.dlsc.jfxcentral2.utils.IkonUtil; +import javafx.scene.effect.GaussianBlur; + +import java.util.List; + +public class GaussianBlurEditor extends EffectEditor { + + public GaussianBlurEditor(GaussianBlur effect, Runnable deleteAction) { + super(effect, deleteAction); + } + + @Override + protected List createOptions(GaussianBlur effect) { + return List.of( + EffectPropertyFactory.create("Radius", IkonUtil.radius, 0, 63, 10, effect.radiusProperty()) + ); + } +} diff --git a/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/GlowEditor.java b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/GlowEditor.java new file mode 100644 index 00000000..368ae8c4 --- /dev/null +++ b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/GlowEditor.java @@ -0,0 +1,20 @@ +package com.dlsc.jfxcentral2.utilities.shadowdesigner.editor; + +import com.dlsc.jfxcentral2.utils.IkonUtil; +import javafx.scene.effect.Glow; + +import java.util.List; + +public class GlowEditor extends EffectEditor { + + public GlowEditor(Glow effect, Runnable deleteAction) { + super(effect, deleteAction); + } + + @Override + protected List createOptions(Glow effect) { + return List.of( + EffectPropertyFactory.create("Level", IkonUtil.level, 0, 1, 0.3, effect.levelProperty()) + ); + } +} diff --git a/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/ImageInputEditor.java b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/ImageInputEditor.java new file mode 100644 index 00000000..3be3b2ef --- /dev/null +++ b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/ImageInputEditor.java @@ -0,0 +1,22 @@ +package com.dlsc.jfxcentral2.utilities.shadowdesigner.editor; + +import com.dlsc.jfxcentral2.utils.IkonUtil; +import javafx.scene.effect.ImageInput; + +import java.util.List; + +public class ImageInputEditor extends EffectEditor { + + public ImageInputEditor(ImageInput effect, Runnable deleteAction) { + super(effect, deleteAction); + } + + @Override + protected List createOptions(ImageInput effect) { + return List.of( + EffectPropertyFactory.create("X", IkonUtil.x, -10, 10, 0, effect.xProperty()), + EffectPropertyFactory.create("Y", IkonUtil.y, -10, 10, 0, effect.yProperty()), + EffectPropertyFactory.create("Image", IkonUtil.image, effect.sourceProperty()) + ); + } +} diff --git a/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/InnerShadowEditor.java b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/InnerShadowEditor.java new file mode 100644 index 00000000..b2849202 --- /dev/null +++ b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/InnerShadowEditor.java @@ -0,0 +1,27 @@ +package com.dlsc.jfxcentral2.utilities.shadowdesigner.editor; + +import com.dlsc.jfxcentral2.utils.IkonUtil; +import javafx.scene.effect.BlurType; +import javafx.scene.effect.InnerShadow; + +import java.util.List; + +public class InnerShadowEditor extends EffectEditor { + public InnerShadowEditor(InnerShadow innerShadow, Runnable deleteAction) { + super(innerShadow, deleteAction); + } + + @Override + protected List createOptions(InnerShadow effect) { + return List.of( + EffectPropertyFactory.create("BlurType", IkonUtil.blur, BlurType.class, null, effect.blurTypeProperty()), + EffectPropertyFactory.create("Width", IkonUtil.width, 0, 255, 21, effect.widthProperty()), + EffectPropertyFactory.create("Height", IkonUtil.height, 0, 255, 21, effect.heightProperty()), + EffectPropertyFactory.create("Radius", IkonUtil.radius, 0, 127, 10, effect.radiusProperty()), + EffectPropertyFactory.create("OffsetX", IkonUtil.offsetX, -10, 10, 0, effect.offsetXProperty()), + EffectPropertyFactory.create("OffsetY", IkonUtil.offsetY, -10, 10, 0, effect.offsetYProperty()), + EffectPropertyFactory.create("Choke", IkonUtil.spread, 0, 1, 0, effect.chokeProperty()), + EffectPropertyFactory.createWithColorPicker("Color", IkonUtil.color, effect.colorProperty()) + ); + } +} diff --git a/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/LightingBumpInputEditor.java b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/LightingBumpInputEditor.java new file mode 100644 index 00000000..eb05b1c6 --- /dev/null +++ b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/LightingBumpInputEditor.java @@ -0,0 +1,23 @@ +package com.dlsc.jfxcentral2.utilities.shadowdesigner.editor; + +import javafx.scene.effect.Lighting; + +import java.util.List; + +public class LightingBumpInputEditor extends EffectEditor { + + public LightingBumpInputEditor(Lighting effect, Runnable deleteAction) { + super(effect, deleteAction); + } + + @Override + protected List createOptions(Lighting effect) { + return List.of( + EffectPropertyFactory.create("Diffuse Constant", null, 0, 2, 1, effect.diffuseConstantProperty()), + EffectPropertyFactory.create("Specular Constant", null, 0, 2, 1, effect.specularConstantProperty()), + EffectPropertyFactory.create("Specular Exponent", null, 0, 40, 20, effect.specularExponentProperty()), + EffectPropertyFactory.create("Surface Scale", null, 0, 10, 1, effect.surfaceScaleProperty()) + + ); + } +} diff --git a/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/MotionBlurEditor.java b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/MotionBlurEditor.java new file mode 100644 index 00000000..c543d4b1 --- /dev/null +++ b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/MotionBlurEditor.java @@ -0,0 +1,21 @@ +package com.dlsc.jfxcentral2.utilities.shadowdesigner.editor; + +import com.dlsc.jfxcentral2.utils.IkonUtil; +import javafx.scene.effect.MotionBlur; + +import java.util.List; + +public class MotionBlurEditor extends EffectEditor { + + public MotionBlurEditor(MotionBlur effect, Runnable deleteAction) { + super(effect, deleteAction); + } + + @Override + protected List createOptions(MotionBlur effect) { + return List.of( + EffectPropertyFactory.create("Angle", IkonUtil.angle, 0, 360, 0, effect.angleProperty()), + EffectPropertyFactory.create("Radius", IkonUtil.radius, 0, 63, 10, effect.radiusProperty()) + ); + } +} diff --git a/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/PerspectiveTransformEditor.java b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/PerspectiveTransformEditor.java new file mode 100644 index 00000000..6988ca98 --- /dev/null +++ b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/PerspectiveTransformEditor.java @@ -0,0 +1,27 @@ +package com.dlsc.jfxcentral2.utilities.shadowdesigner.editor; + +import com.dlsc.jfxcentral2.utils.IkonUtil; +import javafx.scene.effect.PerspectiveTransform; + +import java.util.List; + +public class PerspectiveTransformEditor extends EffectEditor { + + public PerspectiveTransformEditor(PerspectiveTransform effect, Runnable deleteAction) { + super(effect, deleteAction); + } + + @Override + protected List createOptions(PerspectiveTransform effect) { + return List.of( + EffectPropertyFactory.create("Llx", IkonUtil.llx, -10, 10, 0, effect.llxProperty()), + EffectPropertyFactory.create("Lly", IkonUtil.lly, -10, 10, 0, effect.llyProperty()), + EffectPropertyFactory.create("Lrx", IkonUtil.lrx, -10, 10, 0, effect.lrxProperty()), + EffectPropertyFactory.create("Lry", IkonUtil.lry, -10, 10, 0, effect.lryProperty()), + EffectPropertyFactory.create("Ulx", IkonUtil.ulx, -10, 10, 0, effect.ulxProperty()), + EffectPropertyFactory.create("Uly", IkonUtil.uly, -10, 10, 0, effect.ulyProperty()), + EffectPropertyFactory.create("Urx", IkonUtil.urx, -10, 10, 0, effect.urxProperty()), + EffectPropertyFactory.create("Ury", IkonUtil.ury, -10, 10, 0, effect.uryProperty())); + } + +} diff --git a/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/ReflectionEditor.java b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/ReflectionEditor.java new file mode 100644 index 00000000..60f8ebe1 --- /dev/null +++ b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/ReflectionEditor.java @@ -0,0 +1,23 @@ +package com.dlsc.jfxcentral2.utilities.shadowdesigner.editor; + +import com.dlsc.jfxcentral2.utils.IkonUtil; +import javafx.scene.effect.Reflection; + +import java.util.List; + +public class ReflectionEditor extends EffectEditor { + + public ReflectionEditor(Reflection effect, Runnable deleteAction) { + super(effect, deleteAction); + } + + @Override + protected List createOptions(Reflection effect) { + return List.of( + EffectPropertyFactory.create("Fraction", IkonUtil.fraction, 0, 1, 0.75, effect.fractionProperty()), + EffectPropertyFactory.create("Top Offset", IkonUtil.topOffset, -10, 10, 0, effect.topOffsetProperty()), + EffectPropertyFactory.create("Top Opacity", IkonUtil.opacity, 0, 1, 0.5, effect.topOpacityProperty()), + EffectPropertyFactory.create("Bottom Opacity", IkonUtil.opacity, 0, 1, 0, effect.bottomOpacityProperty()) + ); + } +} diff --git a/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/SepiaToneEditor.java b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/SepiaToneEditor.java new file mode 100644 index 00000000..7f521320 --- /dev/null +++ b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/SepiaToneEditor.java @@ -0,0 +1,20 @@ +package com.dlsc.jfxcentral2.utilities.shadowdesigner.editor; + +import com.dlsc.jfxcentral2.utils.IkonUtil; +import javafx.scene.effect.SepiaTone; + +import java.util.List; + +public class SepiaToneEditor extends EffectEditor { + + public SepiaToneEditor(SepiaTone effect, Runnable deleteAction) { + super(effect, deleteAction); + } + + @Override + protected List createOptions(SepiaTone effect) { + return List.of( + EffectPropertyFactory.create("Level", IkonUtil.level, 0, 1, 1, effect.levelProperty()) + ); + } +} diff --git a/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/ShadowEditor.java b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/ShadowEditor.java new file mode 100644 index 00000000..21ee7528 --- /dev/null +++ b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/editor/ShadowEditor.java @@ -0,0 +1,25 @@ +package com.dlsc.jfxcentral2.utilities.shadowdesigner.editor; + +import com.dlsc.jfxcentral2.utils.IkonUtil; +import javafx.scene.effect.BlurType; +import javafx.scene.effect.Shadow; + +import java.util.List; + +public class ShadowEditor extends EffectEditor { + + public ShadowEditor(Shadow effect, Runnable deleteAction) { + super(effect, deleteAction); + } + + @Override + protected List createOptions(Shadow effect) { + return List.of( + EffectPropertyFactory.create("BlurType", IkonUtil.blur, BlurType.class, null, effect.blurTypeProperty()), + EffectPropertyFactory.create("Width", IkonUtil.width, 0, 255, 21, effect.widthProperty()), + EffectPropertyFactory.create("Height", IkonUtil.height, 0, 255, 21, effect.heightProperty()), + EffectPropertyFactory.create("Radius", IkonUtil.radius, 0, 127, 10, effect.radiusProperty()), + EffectPropertyFactory.createWithColorPicker("Color", IkonUtil.color, effect.colorProperty()) + ); + } +} diff --git a/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/effect/BlendBottomInput.java b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/effect/BlendBottomInput.java new file mode 100644 index 00000000..3250faf8 --- /dev/null +++ b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/effect/BlendBottomInput.java @@ -0,0 +1,13 @@ +package com.dlsc.jfxcentral2.utilities.shadowdesigner.effect; + +import javafx.scene.effect.Blend; + +public class BlendBottomInput extends Blend { + public BlendBottomInput() { + + } + + public void setInput(BlendBottomInput bottomInput) { + setBottomInput(bottomInput); + } +} diff --git a/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/effect/BlendTopInput.java b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/effect/BlendTopInput.java new file mode 100644 index 00000000..e5c9d060 --- /dev/null +++ b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/effect/BlendTopInput.java @@ -0,0 +1,13 @@ +package com.dlsc.jfxcentral2.utilities.shadowdesigner.effect; + +import javafx.scene.effect.Blend; + +public class BlendTopInput extends Blend { + public BlendTopInput() { + } + + public void setInput(BlendTopInput topInput) { + setTopInput(topInput); + } + +} diff --git a/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/effect/LightingBumpInput.java b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/effect/LightingBumpInput.java new file mode 100644 index 00000000..b3cc3571 --- /dev/null +++ b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/effect/LightingBumpInput.java @@ -0,0 +1,14 @@ +package com.dlsc.jfxcentral2.utilities.shadowdesigner.effect; + +import javafx.scene.effect.Lighting; + +public class LightingBumpInput extends Lighting { + + public LightingBumpInput() { + } + + public void setInput(LightingBumpInput bumpInput) { + setBumpInput(bumpInput); + } + +} diff --git a/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/effect/LightingContentInput.java b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/effect/LightingContentInput.java new file mode 100644 index 00000000..9fac83d0 --- /dev/null +++ b/components/src/main/java/com/dlsc/jfxcentral2/utilities/shadowdesigner/effect/LightingContentInput.java @@ -0,0 +1,14 @@ +package com.dlsc.jfxcentral2.utilities.shadowdesigner.effect; + +import javafx.scene.effect.Lighting; + +public class LightingContentInput extends Lighting { + + public LightingContentInput() { + + } + + public void setInput(LightingContentInput contentInput) { + setContentInput(contentInput); + } +} diff --git a/components/src/main/java/com/dlsc/jfxcentral2/utils/IkonUtil.java b/components/src/main/java/com/dlsc/jfxcentral2/utils/IkonUtil.java index 77203831..d91bbcbf 100644 --- a/components/src/main/java/com/dlsc/jfxcentral2/utils/IkonUtil.java +++ b/components/src/main/java/com/dlsc/jfxcentral2/utils/IkonUtil.java @@ -10,22 +10,38 @@ import com.dlsc.jfxcentral.data.model.LinksOfTheWeek; import com.dlsc.jfxcentral.data.model.ModelObject; import com.dlsc.jfxcentral.data.model.News; -import com.dlsc.jfxcentral.data.model.Utility; import com.dlsc.jfxcentral.data.model.Person; import com.dlsc.jfxcentral.data.model.RealWorldApp; import com.dlsc.jfxcentral.data.model.Tip; import com.dlsc.jfxcentral.data.model.Tool; import com.dlsc.jfxcentral.data.model.Tutorial; +import com.dlsc.jfxcentral.data.model.Utility; import com.dlsc.jfxcentral.data.model.Video; import com.dlsc.jfxcentral2.iconfont.JFXCentralIcon; import org.kordamp.ikonli.Ikon; +import org.kordamp.ikonli.antdesignicons.AntDesignIconsOutlined; +import org.kordamp.ikonli.bootstrapicons.BootstrapIcons; +import org.kordamp.ikonli.boxicons.BoxiconsRegular; +import org.kordamp.ikonli.carbonicons.CarbonIcons; import org.kordamp.ikonli.codicons.Codicons; import org.kordamp.ikonli.coreui.CoreUiBrands; +import org.kordamp.ikonli.coreui.CoreUiFree; +import org.kordamp.ikonli.dashicons.Dashicons; +import org.kordamp.ikonli.evaicons.Evaicons; +import org.kordamp.ikonli.fluentui.FluentUiFilledAL; import org.kordamp.ikonli.fluentui.FluentUiRegularAL; import org.kordamp.ikonli.hawcons.HawconsStroke; +import org.kordamp.ikonli.ionicons4.Ionicons4IOS; import org.kordamp.ikonli.lineawesome.LineAwesomeSolid; +import org.kordamp.ikonli.material2.Material2MZ; import org.kordamp.ikonli.materialdesign.MaterialDesign; +import org.kordamp.ikonli.materialdesign2.MaterialDesignA; import org.kordamp.ikonli.materialdesign2.MaterialDesignN; +import org.kordamp.ikonli.remixicon.RemixiconAL; +import org.kordamp.ikonli.subway.Subway; +import org.kordamp.ikonli.themify.Themify; +import org.kordamp.ikonli.unicons.UniconsLine; +import org.kordamp.ikonli.win10.Win10; public interface IkonUtil { @@ -65,10 +81,44 @@ public interface IkonUtil { Ikon icons = MaterialDesign.MDI_EMOTICON; Ikon documentation = Codicons.BOOK; Ikon utility = FluentUiRegularAL.DOCUMENT_TOOLBOX_20; - Ikon news = MaterialDesignN.NEWSPAPER_VARIANT_OUTLINE; Ikon linkOfTheWeek = JFXCentralIcon.LINKS_OF_THE_WEEK; + Ikon width = AntDesignIconsOutlined.COLUMN_WIDTH; + Ikon height = AntDesignIconsOutlined.COLUMN_HEIGHT; + Ikon radius = AntDesignIconsOutlined.RADIUS_UPRIGHT; + Ikon color = Evaicons.COLOR_PALETTE_OUTLINE; + Ikon offsetX = RemixiconAL.ARROW_LEFT_RIGHT_FILL; + Ikon offsetY = RemixiconAL.ARROW_UP_DOWN_FILL; + Ikon spread = Dashicons.EDITOR_DISTRACTIONFREE; + Ikon blur = FluentUiFilledAL.BLUR_16; + Ikon threshold = CarbonIcons.THRESHOLD; + Ikon brightness = BootstrapIcons.BRIGHTNESS_HIGH; + Ikon contrast = Ionicons4IOS.CONTRAST; + Ikon saturation = BootstrapIcons.DROPLET_HALF; + Ikon hue = UniconsLine.RAINBOW; + Ikon opacity = CoreUiFree.OPACITY; + Ikon blendMode = BoxiconsRegular.INTERSECT; + Ikon scaleX = Win10.RESIZE_HORIZONTAL; + Ikon scaleY = Win10.RESIZE_VERTICAL; + Ikon wrap = Themify.LOOP; + Ikon iterations = Material2MZ.WAVES; + Ikon level = CarbonIcons.BRIGHTNESS_CONTRAST; + Ikon x = CarbonIcons.X_AXIS; + Ikon y = CarbonIcons.Y_AXIS; + Ikon image = CarbonIcons.IMAGE; + Ikon angle = MaterialDesignA.ANGLE_ACUTE; + Ikon llx = Subway.RECTANGLE_3; + Ikon lly = Subway.RECTANGLE_3; + Ikon lrx = Subway.RECTANGLE_4; + Ikon lry = Subway.RECTANGLE_4; + Ikon ulx = Subway.RECTANGLE_1; + Ikon uly = Subway.RECTANGLE_1; + Ikon urx = Subway.RECTANGLE_2; + Ikon ury = Subway.RECTANGLE_2; + Ikon fraction = CarbonIcons.REFLECT_VERTICAL; + Ikon topOffset = AntDesignIconsOutlined.VERTICAL_ALIGN_TOP; + static Ikon getModelIkon(ModelObject mo) { return getModelIkon(mo.getClass()); } diff --git a/components/src/main/java/com/dlsc/jfxcentral2/utils/NumberUtil.java b/components/src/main/java/com/dlsc/jfxcentral2/utils/NumberUtil.java index 4f17f205..83dbe939 100644 --- a/components/src/main/java/com/dlsc/jfxcentral2/utils/NumberUtil.java +++ b/components/src/main/java/com/dlsc/jfxcentral2/utils/NumberUtil.java @@ -38,7 +38,17 @@ public static String trimTrailingZeros(double value, boolean keepDecimal, int de } } - + /** + * Clamps a value between a minimum and maximum value. + * + * @param value The value to be clamped. + * @param min The minimum allowable value. + * @param max The maximum allowable value. + * @return The clamped value, which will be between min and max (inclusive). + */ + public static double clamp(double value, double min, double max) { + return Math.max(min, Math.min(max, value)); + } } diff --git a/components/src/main/java/module-info.java b/components/src/main/java/module-info.java index 22ce6e5d..13386266 100644 --- a/components/src/main/java/module-info.java +++ b/components/src/main/java/module-info.java @@ -106,6 +106,10 @@ exports com.dlsc.jfxcentral2.components.hamburger; exports com.dlsc.jfxcentral2.components.topcontent; exports com.dlsc.jfxcentral2.utilities.pathextractor; + exports com.dlsc.jfxcentral2.utilities.shadowdesigner; + exports com.dlsc.jfxcentral2.utilities.shadowdesigner.editor; + exports com.dlsc.jfxcentral2.utilities.paintpicker.impl; + exports com.dlsc.jfxcentral2.utilities.shadowdesigner.effect; uses IkonProvider; } \ No newline at end of file diff --git a/components/src/main/resources/com/dlsc/jfxcentral2/theme.css b/components/src/main/resources/com/dlsc/jfxcentral2/theme.css index 26321423..826130bf 100644 --- a/components/src/main/resources/com/dlsc/jfxcentral2/theme.css +++ b/components/src/main/resources/com/dlsc/jfxcentral2/theme.css @@ -252,14 +252,81 @@ -fx-background-color: derive(-grey-10, 50%); } -.normal-page .combo-box .combo-box-popup .list-view .check-box { +.normal-page .check-box { -fx-border-color: -grey-20; } -.normal-page .combo-box .combo-box-popup .list-view .check-box .box { +.normal-page .check-box:hover { + -fx-border-color: -grey-60; +} + +.normal-page .check-box .box { -fx-background-color: transparent; } +.normal-page .text-field { + -fx-focus-color: -grey-30; + -fx-faint-focus-color: transparent; + -fx-background-radius: 0px; + -fx-border-radius: 0px; +} + +.normal-page .spinner { + -fx-focus-color: -grey-30; + -fx-faint-focus-color: transparent; + -fx-background-radius: 0px; + -fx-border-radius: 0px; +} + +.normal-page .spinner .text-field { + -fx-background-radius: 0px; +} + +.normal-page .spinner .increment-arrow-button, +.normal-page .spinner .decrement-arrow-button { + -fx-background-color: -grey-10; + -fx-background-radius: 0px; + -fx-cursor: hand; +} + +.normal-page .spinner .increment-arrow-button:hover, +.normal-page .spinner .decrement-arrow-button:hover { + -fx-background-color: -light-blue; +} + +.normal-page .spinner .increment-arrow-button:pressed, +.normal-page .spinner .decrement-arrow-button:pressed { + -fx-background-color: -bright-blue; +} + +.normal-page .spinner .increment-arrow-button:pressed .increment-arrow, +.normal-page .spinner .decrement-arrow-button:pressed .decrement-arrow { + -fx-background-color: -white; +} + +.md-combo-box.combo-box-base { + -fx-font-size: 12px; + -fx-background-radius: 2px; + -fx-padding: 5px 2px; +} + +.md-combo-box.combo-box .combo-box-popup .list-view, +.md-combo-box.combo-box .combo-box-popup .list-cell { + -fx-background-color: -white; + -fx-text-fill: -grey-100; +} + +.md-combo-box.combo-box .combo-box-popup .list-view { + -fx-background-radius: 2px; + -fx-padding: 5px; +} + +.md-combo-box.combo-box .combo-box-popup .list-view .list-cell { + -fx-font-size: 12px; + -fx-padding: 3px 10px 3px 12px; + -fx-cell-size: 30px; +} + /** ------------------------------------ * ScrollBar **/ @@ -9376,4 +9443,231 @@ .gradient-designer-overview-box:lg .gradient-designer-view { -fx-hgap: 50px; -} \ No newline at end of file +} + +/** ---------------------------------------------------------------------------- + * ShadowDesignerView + */ +.shadow-designer-view { + -fx-min-height: 560px; +} + +.shadow-designer-view .left-box .effect-preview-pane { + -fx-pref-width: 200px; + -fx-pref-height: 200px; + -fx-background-color: -white; + -fx-border-color: -grey-10; +} + +.shadow-designer-view > .flow-pane { + -fx-hgap: 60px; + -fx-vgap: 30px; +} + +.shadow-designer-view:md > .flow-pane { + -fx-hgap: 120px; +} + +.shadow-designer-view:sm-md > .flow-pane { + -fx-alignment: center; +} + +.shadow-designer-view .left-box .effect-preview-pane .label { + -fx-font-size: 20px; +} + +.shadow-designer-view > .flow-pane { + /*-fx-border-color: #08e093;*/ +} + +.shadow-designer-view > .flow-pane > .left-box { + -fx-padding: 50px; +} + +.shadow-designer-view > .flow-pane > .right-box { +} + +.shadow-designer-view > .flow-pane > .right-box.with-non-effect .menu-button { + -fx-pref-width: 200px; + -fx-background-radius: 200px; + -fx-font-size: 20px; +} + +.shadow-designer-view > .flow-pane > .right-box.with-non-effect .menu-button .ikonli-font-icon { + -fx-icon-size: 30px; +} + + +/** ---------------------------------------------------------------------------- + * EffectEditor + */ +.effect-editor { + -fx-background-color: -white; + -fx-padding: 10px; + -fx-font-size: 14px; + -fx-spacing: 10px; +} + +.shadow-designer-view:lg .effect-editor { + -fx-pref-width: 420px; + -fx-max-width: 420px; +} + +.shadow-designer-view:sm .effect-editor .property-name-label { + -fx-font-size: 12px; +} + +.shadow-designer-view:sm .effect-editor .property-name-label .ikonli-font-icon { + -fx-icon-size: 14px; +} + +.effect-editor .top-box { + -fx-alignment: center-left; + -fx-background-color: -bright-blue; + -fx-padding: 5px; +} + +.effect-editor .top-box .title-label { + -fx-font-size: 16px; + -fx-text-fill: -white; + -fx-graphic-text-gap: 10px; +} + +.effect-editor .top-box .title-label .ikonli-font-icon{ + -fx-icon-size: 18px; + -fx-icon-color: -white; +} + +.effect-editor .top-box .delete-button { + -fx-background-radius: 20px; + -fx-padding: 5px 6px; + -fx-background-color: -white; +} + +.effect-editor .top-box .delete-button .ikonli-font-icon { + -fx-icon-size: 16px; + -fx-icon-color: #fc6363; + -fx-scale-x: 1.5; + -fx-scale-y: 1.5; +} + +.effect-editor .top-box .delete-button:hover { + -fx-background-color: -grey-10; +} + +.effect-editor .top-box .delete-button:hover .ikonli-font-icon { + -fx-icon-color: red; +} + +.effect-editor .content-pane { + -fx-hgap: 5px; + -fx-vgap: 5px; + -fx-row-valignment: top; + -fx-column-halignment: right; +} + +.effect-editor .content-pane .combo-box-base { + -fx-border-color: -grey-10; + -fx-padding: 2px; + -fx-pref-width: 226px; +} + +.effect-editor .spinner { + -fx-pref-width: 226px; +} + +.effect-editor .content-pane .combo-box-base .arrow-button .arrow { + -fx-background-color: -grey-100; + -fx-scale-x: 1.2; + -fx-scale-y: 1.2; +} + +.effect-editor .content-pane .slider-box { + -fx-spacing: 5px; + -fx-alignment: top-left; +} + +.effect-editor .content-pane .slider-box > .value-label { + -fx-pref-width: 50px; + -fx-border-color: -grey-10; + -fx-padding: 1px 2px; +} + +.effect-editor .content-pane .slider-box > .slider { + -fx-pref-width: 170px; +} + +.effect-editor .content-pane .slider-box > .slider .track { + -fx-background-color: -grey-10; + -fx-background-radius: 0px; +} + +.effect-editor .content-pane .slider-box > .slider .thumb { + -fx-background-color: #A4D7EC; + -fx-cursor: hand; +} + +.effect-editor .content-pane .slider-box > .slider .thumb:hover, +.effect-editor .content-pane .slider-box > .slider .thumb:pressed { + -fx-background-color: -bright-blue; +} + +.effect-editor .file-handler-view { + -fx-border-color: -grey-10; + -fx-background-image: url("images/transparent-bg.png"); +} + +.effect-editor .paint-picker { + -fx-border-color: transparent; +} + +.effect-editor .paint-picker .info-root-pane { + visibility: hidden; +} + +.effect-editor .property-name-label { + -fx-font-size: 15px; +} + +.effect-editor .property-name-label .ikonli-font-icon { + -fx-icon-size: 18px; + -fx-icon-color: -grey-60; +} + +/** ---------------------------------------------------------------------------- + * EffectFlowPane + */ +.effect-flow-pane { + -fx-hgap: 5px; + -fx-vgap: 5px; + -fx-alignment: center; +} + +.effect-flow-pane .toggle-button { + -fx-background-color: -white; + -fx-background-radius: 15px; + -fx-background-insets: 0; + -fx-border-color: -grey-20; + -fx-border-radius: 15px; + -fx-padding: 6px 10px; + -fx-graphic-text-gap: 5px; + -fx-font-weight: bold; + -fx-font-size: 14px; + -fx-cursor: hand; + -fx-content-display: right; +} + +.effect-flow-pane .toggle-button .ikonli-font-icon { + -fx-icon-size: 16px; + -fx-scale-x: 1.5; + -fx-scale-y: 1.5; +} + +.effect-flow-pane .toggle-button:selected { + -fx-background-color: -green; + -fx-border-color: transparent; +} + +.effect-flow-pane .menu-button .ikonli-font-icon { + -fx-icon-size: 20px; +} diff --git a/components/src/main/resources/com/dlsc/jfxcentral2/utilities/paintpicker/paint-picker.css b/components/src/main/resources/com/dlsc/jfxcentral2/utilities/paintpicker/paint-picker.css index 5fb6eba4..10464494 100644 --- a/components/src/main/resources/com/dlsc/jfxcentral2/utilities/paintpicker/paint-picker.css +++ b/components/src/main/resources/com/dlsc/jfxcentral2/utilities/paintpicker/paint-picker.css @@ -222,7 +222,7 @@ .paint-picker .text-field { -fx-background-radius: 0; - -fx-text-fill: -grey-90; + -fx-text-fill: -grey-100; -fx-font-size: 12px; -fx-focus-color: -grey-30; -fx-faint-focus-color: transparent; @@ -305,3 +305,11 @@ -fx-background-insets: 0, 1; -fx-background-radius: 2px, 1px; } + +.paint-picker.only-color-mode .mode-buttons-box { + visibility: hidden; +} + +.paint-picker.only-color-mode .info-root-pane { + visibility: hidden; +} \ No newline at end of file diff --git a/sampler/src/main/java/com/dlsc/jfxcentral2/demo/devtools/HelloShadowDesignerView.java b/sampler/src/main/java/com/dlsc/jfxcentral2/demo/devtools/HelloShadowDesignerView.java new file mode 100644 index 00000000..821df43b --- /dev/null +++ b/sampler/src/main/java/com/dlsc/jfxcentral2/demo/devtools/HelloShadowDesignerView.java @@ -0,0 +1,17 @@ +package com.dlsc.jfxcentral2.demo.devtools; + +import com.dlsc.jfxcentral2.demo.JFXCentralSampleBase; +import com.dlsc.jfxcentral2.utilities.shadowdesigner.ShadowDesignerView; +import javafx.scene.layout.Region; + +public class HelloShadowDesignerView extends JFXCentralSampleBase { + @Override + protected Region createControl() { + return new ShadowDesignerView(); + } + + @Override + public String getSampleName() { + return "Shadow Designer View"; + } +}