Skip to content

Commit

Permalink
🔖 Update and release components, core, and resources modules
Browse files Browse the repository at this point in the history
🔖 Bump components and release modules to version 11.21.0
🔖 Bump core module to version 11.6.3
🔖 Bump resources module to version 11.8.0

👷 Updated update_jfx_res.sh script. Now all stylesheets and assets are donwloaded to integrate with the new deployment system of the Theme API. The assets are automatically packed in a zip file. Also, all CSS files are now optimized by csso and beautified by cssbeautify, two are npm modules

Components Module
Controls Package
♻️ MFXCheckBox: SceneBuilder integration set text to "CheckBox"
♻️ MFXFabBase; SceneBuilder integration set text to "Floating Action Button"

Theming Package
✨ Added deployment API to Theme interface. Now themes can specify a zip file of assets needed for them to work properly. This zip file can be extracted on the filesystem so that when merging the theme with UserAgentBuilder the resources will still work
♻️ UserAgentBuilder: Implemented code to resolve @import statements and 'local' URL resources. These features will work only if the Theme deploys the needed assets on the disk first

Window Package
:ambulance: MFXTooltip and MFXPopup: Partially revert commit d209dd2. If we don't call close() when the owner's window is not showing anymore terrible things happen, like the entire app crashing with problematic frame reports :\

Core Module
:recycle: Resettable properties now notify about change when reset by default
:bug: Resettable properties now use Objects.equals(...) to check for equality as it is null safe

Resources Module
:sparkles: Add resources for themes, allowing them deployment capabilities
:bug: Fonts.css: fix Comfortaa font name

Signed-off-by: palexdev <alessandro.parisi406@gmail.com>
  • Loading branch information
palexdev committed Jun 1, 2023
1 parent 4843b6c commit 82dd321
Show file tree
Hide file tree
Showing 46 changed files with 3,483 additions and 3,815 deletions.
8 changes: 4 additions & 4 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ jdk=11
testJdk=17

# Modules
mfx=11.20.0
mfxcore=11.6.2
mfx=11.21.0
mfxcore=11.6.3
mfxeffects=11.2.1
mfxlocalization=11.1.0
mfxresources=11.7.0
mfxresources=11.8.0

# Plugins
jfxPlugin=0.0.14
Expand All @@ -35,7 +35,7 @@ shadowJarPlugin=7.1.2

# Dependencies
jfx=20.0.1
vfx=11.9.4
vfx=11.9.5
sass=1.57.1

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

[//]: ##[Unreleased]

## [11.21.0] - 01-06-2023

### Added

- Added deployment API to Theme interface. Now themes can specify a zip file of assets needed for them to work properly.
This zip file can be extracted on the filesystem so that when merging the theme with UserAgentBuilder the resources
will still work

### Changed

- MFXCheckBox: SceneBuilder integration set text to "CheckBox"
- MFXFabBase; SceneBuilder integration set text to "Floating Action Button"
- UserAgentBuilder: Implemented code to resolve @import statements and 'local' URL resources. These features will work
only if the Theme deploys the needed assets on the disk first

### Fixed

- MFXTooltip and MFXPopup: Partially revert commit d209dd275b9c1c87b8ee578f2362da2abaebfbda. If we don't call close()
when the owner's window is not showing anymore terrible things happen, like the entire app crashing with problematic
frame reports :\

## [11.20.0] - 29-05-2023

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

POM_NAME=mfxcomponents
POM_DESCRIPTION=Material Design/Modern components for JavaFX
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import io.github.palexdev.mfxcomponents.skins.MFXCheckBoxSkin;
import io.github.palexdev.mfxcomponents.theming.enums.PseudoClasses;
import io.github.palexdev.mfxcore.base.properties.styleable.StyleableBooleanProperty;
import io.github.palexdev.mfxcore.utils.fx.SceneBuilderIntegration;
import io.github.palexdev.mfxeffects.utils.StyleUtils;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
Expand Down Expand Up @@ -86,6 +87,12 @@ public Supplier<MFXCheckBoxBehavior> defaultBehaviorProvider() {
return () -> new MFXCheckBoxBehavior(this);
}

@Override
protected void sceneBuilderIntegration() {
super.sceneBuilderIntegration();
SceneBuilderIntegration.ifInSceneBuilder(() -> setText("CheckBox"));
}

//================================================================================
// Styleable Properties
//================================================================================
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import io.github.palexdev.mfxcomponents.theming.enums.PseudoClasses;
import io.github.palexdev.mfxcore.base.properties.styleable.StyleableBooleanProperty;
import io.github.palexdev.mfxcore.observables.When;
import io.github.palexdev.mfxcore.utils.fx.SceneBuilderIntegration;
import io.github.palexdev.mfxcore.utils.fx.StyleUtils;
import io.github.palexdev.mfxresources.base.properties.IconProperty;
import io.github.palexdev.mfxresources.fonts.IconProvider;
Expand Down Expand Up @@ -177,6 +178,12 @@ public List<String> defaultStyleClasses() {
return new MFXFabSkin(this);
}

@Override
protected void sceneBuilderIntegration() {
super.sceneBuilderIntegration();
SceneBuilderIntegration.ifInSceneBuilder(() -> setText("Floating Action Button"));
}

//================================================================================
// Styleable Properties
//================================================================================
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
/*
* Copyright (C) 2023 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.mfxcomponents.theming;

import io.github.palexdev.mfxcomponents.theming.base.Theme;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import static java.nio.file.FileVisitResult.CONTINUE;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;

/**
* Utility class to deploy {@link Theme}'s resources from the Jar/App to the filesystem.
* <p>
* The base path for all deployments is at the OS' temp directory {@code System.getProperty("java.io.tmpdir")} in a
* subdirectory named "themes-assets".
* <p></p>
* The deployment will always occur replacing any existing asset, this way we ensure that all assets are present,
* unmodified/uncorrupted, while also avoiding costly checks on the filesystem.
* <p></p>
* Deployments are stored in a nested map of type: [String, Map[String, Path]].
* <p>
* The first key is given by {@link Theme#deployName()}, and allows to check which themes have already been deployed.
* Keep in mind, that checks on which themes are deployed occur only on this cache in memory, for the same reason above,
* we void checks on the filesystem.
* <p>
* The internal map allows to associate each file in the zip to their path on the filesystem. The only note here is about
* the key of these maps. The key is the path of the file in the zip, for example:
* <pre>
* {@code
* // Consider this zip file
* assets.zip
* - assets
* - images
* - image.png
* - res
* - res.tmp
* - root.res
*
* // As already said the base path is TMP_DIR/themes-assets
* // The structure on the disk will be as follows
* TMP_DIR/assets
* TMP_DIR/assets/images
* TMP_DIR/assets/images/image.png
* TMP_DIR/assets/res
* TMP_DIR/assets/res/res.tmp
* TMP_DIR/root.res
*
* // The structure in the cache map will be as follows
* TMP_DIR/assets
* TMP_DIR/assets/images
* "assets/images/image.png" -> TMP_DIR/assets/images/image.png
* TMP_DIR/assets/res
* "assets/res/res.tmp" -> TMP_DIR/assets/res/res.tmp
* "root.res" -> TMP_DIR/root.res
* // Note that only files are stored in cache!
* }
* </pre>
* <p></p>
* Last but not least, there are method to also delete any deployed resource: {@link #clean(Theme)} and {@link #cleanAll()}.
*/
public class Deployer {
//================================================================================
// Singleton
//================================================================================
private static final Deployer instance = new Deployer();

public static Deployer instance() {
return instance;
}

//================================================================================
// Properties
//================================================================================
private final Map<String, Map<String, Path>> cache = new HashMap<>();
private final Path tmpDir = Path.of(System.getProperty("java.io.tmpdir"), "themes-assets");

//================================================================================
// Constructors
//================================================================================
private Deployer() {}

//================================================================================
// Methods
//================================================================================

/**
* Retrieves the given {@link Theme}'s assets using {@link Theme#assets()}, if the returned stream is not null
* and is a valid zip file, extracts its contents at: {@code System.getProperty("java.io.tmpdir")/themes-assets}.
* <p>
* The paths in the zip are preserved.
* <p></p>
* At the end the zip file is deleted.
*/
public void deploy(Theme theme) throws Exception {
if (!Files.isDirectory(tmpDir)) Files.createDirectories(tmpDir);

Path zipPath = null;
try (InputStream in = theme.assets()) {
if (in == null) return;
Path destDir = tmpDir.resolve(theme.deployName());
if (!Files.isDirectory(destDir)) Files.createDirectories(destDir);

// Copy zip to file system
zipPath = destDir.resolve("assets.zip");
OutputStream out = Files.newOutputStream(zipPath);
in.transferTo(out);

// Unzip
try (ZipFile zf = new ZipFile(zipPath.toFile())) {
List<? extends ZipEntry> entries = zf.stream().collect(Collectors.toList());
for (ZipEntry entry : entries) {
unzip(theme, zf, entry, destDir);
}
}
} catch (IOException ex) {
throw new RuntimeException(ex);
} finally {
if (zipPath != null) Files.delete(zipPath);
}
}

/**
* If the given {@link Theme} has already been deployed before, removes its entry from the cache map,
* and for each stored {@link Path} attempts their removal.
*
* @return true if the operation was successful or the cache didn't contain the entry, false otherwise
*/
public boolean clean(Theme theme) {
Map<String, Path> assets = cache.remove(theme.deployName());
if (assets == null) return true;
try {
for (Path path : assets.values()) {
delete(path);
}
return true;
} catch (Exception ignored) {
return false;
}
}

/**
* Removes all the deployed resources on the filesystem by deleting the temp directory, then clears the cache.
*
* @return true if the operation was successful, false otherwise
*/
public boolean cleanAll() {
try {
if (Files.isDirectory(tmpDir)) delete(tmpDir);
cache.clear();
return true;
} catch (IOException ignored) {
return false;
}
}

/**
* @return the Map containing the deployed Paths on the filesystem by their path into the zip
*/
public Map<String, Path> getDeployed(Theme theme) {
return cache.get(theme.deployName());
}

/**
* Responsible for copying resources from the zip file to the filesystem as well as building the cache.
*/
private void unzip(Theme theme, ZipFile zf, ZipEntry entry, Path destDir) throws IOException {
String name = entry.getName();
Path target = destDir.resolve(name);
if (entry.isDirectory()) {
Files.createDirectories(target);
} else {
try (InputStream in = zf.getInputStream(entry)) {
Files.copy(in, target, REPLACE_EXISTING);
Map<String, Path> themeCache = cache.computeIfAbsent(theme.deployName(), t -> new HashMap<>());
themeCache.put(name, target);
}
}
}

/**
* Utility method to delete a path whether it is a file or directory, in other words what Java should have already had
* in their java.io/java.nio mess.
*/
private void delete(Path path) throws IOException {
Files.walkFileTree(path, new SimpleFileVisitor<>() {
@Override
public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException {
Files.delete(file);
return CONTINUE;
}

@Override
public FileVisitResult postVisitDirectory(final Path dir, final IOException e) throws IOException {
Files.delete(dir);
return CONTINUE;
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
package io.github.palexdev.mfxcomponents.theming;

import io.github.palexdev.mfxcomponents.theming.base.Theme;
import io.github.palexdev.mfxresources.MFXResources;

import java.io.InputStream;

/**
* Enumeration of the standard JavaFX themes. This is useful when used with {@link UserAgentBuilder}.
Expand All @@ -44,4 +47,10 @@ public enum JavaFXThemes implements Theme {
public String path() {
return path;
}

@Override
public InputStream assets() {
String path = path().substring(0, path().lastIndexOf("/") + 1) + "assets.zip";
return MFXResources.loadStream(path);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
package io.github.palexdev.mfxcomponents.theming;

import io.github.palexdev.mfxcomponents.theming.base.Theme;
import io.github.palexdev.mfxresources.MFXResources;

import java.io.InputStream;

/**
* Enumeration of all the Material Design 3 themes currently offered by MaterialFX. Implements {@link Theme}.
Expand All @@ -40,4 +43,14 @@ public enum MaterialThemes implements Theme {
public String path() {
return path;
}

@Override
public InputStream assets() {
return MFXResources.loadStream("mfx-assets.zip");
}

@Override
public String deployName() {
return "mfx-assets";
}
}
Loading

0 comments on commit 82dd321

Please sign in to comment.