Skip to content

Commit

Permalink
✨ Some new features in core module
Browse files Browse the repository at this point in the history
[Project]
:arrow_up: Update JavaFX to v21.0.2
:heavy_minus_sign: Remove JavaFX dependencies from ScenicView

[Core Module]
- Controls Package
:bug: SkinBase: whoops, fix double add in listeners' list

- Observables Package
:sparkles: Allow constructs to use a specific listener

- Utils Package
:recycle: Make resizers use fluent API for setters
:sparkles: Add consume(MouseEvent) method to resizers
:sparkles: Add new simple utility to move nodes around

Signed-off-by: palexdev <alessandro.parisi406@gmail.com>
  • Loading branch information
palexdev committed May 22, 2024
1 parent fa161ac commit 664c862
Show file tree
Hide file tree
Showing 12 changed files with 244 additions and 17 deletions.
4 changes: 3 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ subprojects {
testImplementation 'org.junit.jupiter:junit-jupiter'

testImplementation "org.testfx:testfx-junit5:$testfx"
testImplementation "io.github.palexdev:scenicview:$scenicView"
testImplementation("io.github.palexdev:scenicview:$scenicView") {
exclude group: "org.openjfx"
}
}

javafx {
Expand Down
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ testJdk=17

# Modules
mfx=11.24.2
mfxcore=11.8.1
mfxcore=11.9.0
mfxeffects=11.3.1
mfxlocalization=11.1.0
mfxresources=11.9.1
Expand All @@ -34,7 +34,7 @@ gradleSass=1.5.0
shadowJarPlugin=8.1.1

# Dependencies
jfx=21
jfx=21.0.2
vfx=11.9.6
sass=1.68.0

Expand Down
16 changes: 16 additions & 0 deletions modules/core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,22 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

[//]: ##[Unreleased]

## [11.9.0] - 21-05-2024

### Added

- Allow When constructs to use a specific listener
- Add consume(MouseEvent) method to resizers
- Add new simple utility to move nodes around

### Changed

- Make resizers use fluent API for setters

### Fixed

- SkinBase: whoops, fix double add in listeners' list

## [11.8.0] - 04-10-2023

### Added
Expand Down
2 changes: 1 addition & 1 deletion modules/core/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Maven #
#--------------------------------------#
POM_ARTIFACT_ID=mfxcore
VERSION_NAME=11.8.1
VERSION_NAME=11.9.0

POM_NAME=mfxcore
POM_DESCRIPTION=Core components for MaterialFX
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import io.github.palexdev.mfxcore.observables.When;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

Expand Down Expand Up @@ -120,7 +119,6 @@ public void listeners(When<?>... listeners) {
if (!w.isActive()) w.listen();
this.listeners.add(w);
}
Collections.addAll(this.listeners, listeners);
}

//================================================================================
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public class OnChanged<T> extends When<T> {
//================================================================================
// Properties
//================================================================================
private ChangeListener<T> listener;
protected ChangeListener<T> listener;
private BiConsumer<T, T> action;
private BiFunction<T, T, Boolean> condition = (o, n) -> true;
private TriConsumer<WeakReference<When<T>>, T, T> otherwise = (w, o, n) -> {};
Expand All @@ -42,6 +42,27 @@ public OnChanged(ObservableValue<T> observable) {
super(observable);
}

/**
* Build a "wrapping" {@code OnChanged} construct for the given observable and {@link ChangeListener}.
* <p>
* This should be used specifically when several listeners will execute the same action. To improve performance and
* memory usage, you can build the listener yourself and create the construct with this.
* <p>
* Automatically active upon creation!
* <p></p>
* <b>Note</b> however that this special construct will not have any of its features working (no action, no condition,
* no otherwise, etc.) because the listener is not built but the construct, of course.
*/
public static <T> OnChanged<T> withListener(ObservableValue<T> observable, ChangeListener<T> cl) {
return new OnChanged<>(observable) {
{
listener = cl;
register();
observable.addListener(cl);
}
};
}

//================================================================================
// Methods
//================================================================================
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public class OnInvalidated<T> extends When<T> {
//================================================================================
// Properties
//================================================================================
private InvalidationListener listener;
protected InvalidationListener listener;
private Consumer<T> action;
private BiConsumer<WeakReference<When<T>>, T> otherwise = (w, t) -> {};
private Function<T, Boolean> condition = t -> true;
Expand All @@ -42,6 +42,27 @@ public OnInvalidated(ObservableValue<T> observable) {
super(observable);
}

/**
* Build a "wrapping" {@code OnInvalidated} construct for the given observable and {@link InvalidationListener}.
* <p>
* This should be used specifically when several listeners will execute the same action. To improve performance and
* memory usage, you can build the listener yourself and create the construct with this.
* <p>
* Automatically active upon creation!
* <p></p>
* <b>Note</b> however that this special construct will not have any of its features working (no action, no condition,
* no otherwise, etc.) because the listener is not built but the construct, of course.
*/
public static <T> OnInvalidated<T> withListener(ObservableValue<T> observable, InvalidationListener il) {
return new OnInvalidated<>(observable) {
{
listener = il;
register();
observable.addListener(listener);
}
};
}

//================================================================================
// Methods
//================================================================================
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
/*
* Copyright (C) 2024 Parisi Alessandro - alessandro.parisi406@gmail.com
* This file is part of MaterialFX (https://github.com/palexdev/MaterialFX)
*
* MaterialFX is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 3 of the License,
* or (at your option) any later version.
*
* MaterialFX is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with MaterialFX. If not, see <http://www.gnu.org/licenses/>.
*/

package io.github.palexdev.mfxcore.utils;

import io.github.palexdev.mfxcore.base.TriConsumer;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;

// TODO documentation
public class NodeMover<N extends Node> {
//================================================================================
// Properties
//================================================================================
protected N node;

private EventHandler<MouseEvent> draggedHandler = this::handleDragged;
private EventHandler<MouseEvent> pressedHandler = this::handlePressed;
private EventHandler<MouseEvent> movedHandler = this::handleMoved;
private EventHandler<MouseEvent> releasedHandler = this::handleReleased;
private EventHandler<KeyEvent> keyHandler = this::handleKeyPressed;
private TriConsumer<N, Double, Double> moveHandler;

protected double clickedX;
protected double clickedY;
protected double translateX;
protected double translateY;

//================================================================================
// Constructors
//================================================================================
public NodeMover(N node) {
this(
node,
(n, x, y) -> {
n.setTranslateX(x);
n.setTranslateY(y);
}
);
}

public NodeMover(N node, TriConsumer<N, Double, Double> moveHandler) {
this.node = node;
this.moveHandler = moveHandler;
}

public static <T extends Node> NodeMover<T> install(T node) {
return new NodeMover<>(node).install();
}

//================================================================================
// Methods
//================================================================================
public NodeMover<N> install() {
node.addEventFilter(MouseEvent.MOUSE_PRESSED, pressedHandler);
node.addEventFilter(MouseEvent.MOUSE_DRAGGED, draggedHandler);
node.addEventFilter(MouseEvent.MOUSE_MOVED, movedHandler);
node.addEventFilter(MouseEvent.MOUSE_RELEASED, releasedHandler);
node.addEventFilter(KeyEvent.KEY_PRESSED, keyHandler);
return this;
}

public void uninstall() {
node.removeEventFilter(MouseEvent.MOUSE_PRESSED, pressedHandler);
node.removeEventFilter(MouseEvent.MOUSE_DRAGGED, draggedHandler);
node.removeEventFilter(MouseEvent.MOUSE_MOVED, movedHandler);
node.removeEventFilter(MouseEvent.MOUSE_RELEASED, releasedHandler);
node.removeEventFilter(KeyEvent.KEY_PRESSED, keyHandler);
}

public void dispose() {
uninstall();
handleReleased(null);
pressedHandler = null;
draggedHandler = null;
movedHandler = null;
releasedHandler = null;
keyHandler = null;
moveHandler = null;
node = null;
}

protected void handleDragged(MouseEvent event) {
double deltaX = event.getSceneX() - clickedX;
double deltaY = event.getSceneY() - clickedY;
moveHandler.accept(node, translateX + deltaX, translateY + deltaY);
}

protected void handlePressed(MouseEvent event) {
node.requestFocus();
clickedX = event.getSceneX();
clickedY = event.getSceneY();
translateX = node.getTranslateX();
translateY = node.getTranslateY();
node.setCursor(Cursor.CLOSED_HAND);
consume(event);
}

protected void handleMoved(MouseEvent event) {
node.setCursor(Cursor.OPEN_HAND);
}

protected void handleReleased(MouseEvent event) {
node.setCursor(Cursor.OPEN_HAND);
}

protected void handleKeyPressed(KeyEvent event) {
if (event.getCode() == KeyCode.ESCAPE) {
moveHandler.accept(node, translateX, translateY);
triggerMouseRelease();
}
}

protected void triggerMouseRelease() {
Event.fireEvent(node, new MouseEvent(MouseEvent.MOUSE_RELEASED,
0, 0, 0, 0, MouseButton.PRIMARY, 1,
false, false, false, false, true, false, false, false, false, false, null));
}

protected void consume(MouseEvent event) {
event.consume();
}

//================================================================================
// Getters/Setters
//================================================================================
public TriConsumer<N, Double, Double> getMoveHandler() {
return moveHandler;
}

public NodeMover<N> setMoveHandler(TriConsumer<N, Double, Double> moveHandler) {
this.moveHandler = moveHandler;
return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,15 +99,17 @@ public Function<Region, Double> getMinWidthFunction() {
return minWidthFunction;
}

public void setMinWidthFunction(Function<Region, Double> minWidthFunction) {
public RegionDragResizer setMinWidthFunction(Function<Region, Double> minWidthFunction) {
this.minWidthFunction = minWidthFunction;
return this;
}

public Function<Region, Double> getMinHeightFunction() {
return minHeightFunction;
}

public void setMinHeightFunction(Function<Region, Double> minHeightFunction) {
public RegionDragResizer setMinHeightFunction(Function<Region, Double> minHeightFunction) {
this.minHeightFunction = minHeightFunction;
return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import java.util.Arrays;
import java.util.EnumSet;

// TODO documentation
public abstract class AbstractDragResizer<T extends Node> {
protected T node;
private double margin = 6.0;
Expand Down Expand Up @@ -116,7 +117,7 @@ protected void handlePressed(MouseEvent event) {
nodeW = nodeW();
nodeH = nodeH();
draggedZone = getZoneByEvent(event);
event.consume();
consume(event);
}

protected void handleMoved(MouseEvent event) {
Expand All @@ -137,6 +138,10 @@ protected void handleKeyPressed(KeyEvent event) {
}
}

protected void consume(MouseEvent event) {
event.consume();
}

protected void triggerMouseRelease() {
Event.fireEvent(node, new MouseEvent(MouseEvent.MOUSE_RELEASED,
0, 0, 0, 0, MouseButton.PRIMARY, 1,
Expand Down Expand Up @@ -228,24 +233,27 @@ public double getMargin() {
return margin;
}

public void setMargin(double margin) {
public AbstractDragResizer<T> setMargin(double margin) {
this.margin = margin;
return this;
}

public DragResizeHandler<T> getResizeHandler() {
return resizeHandler;
}

public void setResizeHandler(DragResizeHandler<T> resizeHandler) {
public AbstractDragResizer<T> setResizeHandler(DragResizeHandler<T> resizeHandler) {
this.resizeHandler = resizeHandler;
return this;
}

public EnumSet<Zone> getAllowedZones() {
return allowedZones;
}

public void setAllowedZones(Zone... allowedZones) {
public AbstractDragResizer<T> setAllowedZones(Zone... allowedZones) {
this.allowedZones.clear();
this.allowedZones.addAll(Arrays.asList(allowedZones));
return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,8 @@ public Function<Circle, Double> getMinRadiusFunction() {
return minRadiusFunction;
}

public void setMinRadiusFunction(Function<Circle, Double> minRadiusFunction) {
public CircleDragResizer setMinRadiusFunction(Function<Circle, Double> minRadiusFunction) {
this.minRadiusFunction = minRadiusFunction;
return this;
}
}
Loading

0 comments on commit 664c862

Please sign in to comment.