Allow runtime modification of JavaFX CSS

Overview

cssfx

Build Status Maven Central Open Hub project report for CSSFX

WARNING

In version 11.3.0 we have relocated & refactored the project.

  • maven groupId has been changed to fr.brouillard.oss
  • java module name has been changed from cssfx to fr.brouillard.oss.cssfx
  • classes package has been changed from org.fxmisc.cssfx to fr.brouillard.oss.cssfx

WARNING

CSSFX enhances developer productivity by providing CSS reloading functionality in your running application.

While developing you can run your JavaFX application, modify some CSS sources in your preferred editor, hit save button (or CTLR+S or CMD-S) and your JavaFX application is modified in real time.

CSSFX YouTube demo

Project coordinates

Java >= 11

Versions compatible with JavaFX 11 start with 11.X.
Find latest version on central or old ones before relocation.

Maven

<dependency>
  <groupId>fr.brouillard.oss</groupId>
  <artifactId>cssfx</artifactId>
  <version>11.4.0</version>
</dependency>

Gradle

dependencies {
    compile "fr.brouillard.oss:cssfx:11.4.0"
}

Modular Java

CSSFX does not currently provide a module descriptor, but it defines its module name fr.brouillard.oss.cssfx.
If you wish to use CSSFX from a modular javafx application you will need to require it for the moment as an automatic module.

// module-info.java 
module your.module.name {
  requires fr.brouillard.oss.cssfx;
}

Java 8

Versions compatible with JavaFX 8 are all 1.X versions (see latest on central)

Maven

<dependency>
  <groupId>org.fxmisc.cssfx</groupId>
  <artifactId>cssfx</artifactId>
  <version>1.1.1</version>
</dependency>

Gradle

dependencies {
    compile "org.fxmisc.cssfx:cssfx:1.1.1"
}

Usages

Embedded

Starting monitoring CSS changes in development is as simple as adding one line in your application code.

CSSFX.start()

Doing so CSSFX will start to track every CSS resource that will be declared on any Scene or Parent in your application. This monitoring will be active for all the Stage that your application will use.

Mapping URIs to files on disk

CSSFX uses a functional interface URIToPathConverter (a function<String, Path> in fact) in order to be able to map CSS uris to file on the disk.

By providing several default implementations CSSFX is expected to run for you out of the box, without changes.

CSSFX comes with converters for:

  • Maven
  • Gradle
  • execution from jar file

By registering new converters, you can influence the way CSSFX resolves the files to monitor, see next paragraph for an example

If you think that CSSFX is missing some default converters, please post a new issue or create a pull request.

Converter example

Let's consider the following situation (sorry for the windows like path, you'll transform by yourself for other envs):

  • my app is packaged in c:/jars/myapp.jar
  • my sources are located in c:/projects/myapp/src/...

In order to support this setup, you could create your converter and use it in CSSFX

URIToPathConverter myConverter = new URIToPathConverter() {
    @Override
    public Path convert(String uri) {
        Matcher m = Pattern.compile("jar:file:/.*\\.jar!/(.*\\.css)").matcher(uri);
        if (m.matches()) {
            final String sourceFile = m.replaceFirst("c:/projects/myapp/src/$1").replace('/', '\\');
            return Paths.get(sourceFile);
        }
        return null;
    }
};

CSSFX.addConverter(myConverter).start();

Embedded with homemade configuration

If you need more control on how CSSFX will monitor your application & CSS changes, then you can use some extended functionalities of the CSSFX builder class.

There you will be able to:

  • add/reset converters
  • restrict monitoring on
    • one Stage
    • one Scene
    • one Node

As an external application

TODO

As a java agent

TODO

Logging in CSSFX

CSSFX comes with a mini logging framework.

CSSFX supports different properties to change default logging behavior

System Property Description
cssfx.log activates CSSFX logging
cssfx.log.level set the logging level to use, possible values NONE ERROR WARN INFO DEBUG, default is INFO
cssfx.log.type set the type of "appender" to use, possible values none console jul, default is console

You can also register your own LoggerFactory.

CSSFXLogger.setLoggerFactory((loggerName) -> (level, message, args) -> {
    System.out.println("I log by myself, original message: " + String.format(message, args));
});

Build & release

Normal build

  • mvnw clean install : UI tests are run headless
  • mvnw -P-ci clean install : UI tests are run visible on screen

Release

  • mvnw -Prelease,ci clean install: this will simulate a full build for oss delivery (javadoc, source attachement, GPG signature, ...)
  • git tag -a -s -m "release X.Y.Z, additionnal reason" X.Y.Z: tag the current HEAD with the given tag name. The tag is signed by the author of the release. Adapt with gpg key of maintainer.
    • Matthieu Brouillard command: git tag -a -s -u 2AB5F258 -m "release X.Y.Z, additional reason" X.Y.Z
    • Matthieu Brouillard public key
  • mvnw -Prelease,ci -DskipTests deploy
  • git push --follow-tags origin master

Credits

Many thanks to the JPro company which actively supports cssfx and promotes its usage.

Also, a big thank you to all contributors and people who reported issues or enhancement requests ; an OSS project is nothing without its users and community.

Special thanks to Tomas Mikula and his FXMisc project umbrella that have simplified the route of CSSFX to maven central prior to version 11.3.0.

Comments
  • CSSFX shouldn't change the memory behaviour of JavaFX

    CSSFX shouldn't change the memory behaviour of JavaFX

    This PR adds many unit-tests to memory-semantics. The new test TestMemoryLeaks was initially not working but is fixed with this pull request. It only checks whether a Stage can be collected by the GC when CSSFX is used.

    This important so people can work on CSS and check for memory leaks in their application without changing their development setup. Otherwise, the development setup gets too complicated.

    This PR is quite big because it adds a lot of testability and required some rewrites. Fortunately, now I know the project so well that I might fix all other known missing features.

    opened by FlorianKirmaier 11
  • NPE when adding stylesheets

    NPE when adding stylesheets

    For my new ShowcaseFX view / app I constantly need to add and remove stylesheets. When doing to I keep getting this NPE:

    Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
    	at java.base/java.util.regex.Matcher.getTextLength(Matcher.java:1770)
    	at java.base/java.util.regex.Matcher.reset(Matcher.java:416)
    	at java.base/java.util.regex.Matcher.<init>(Matcher.java:253)
    	at java.base/java.util.regex.Pattern.matcher(Pattern.java:1133)
    	at [email protected]/fr.brouillard.oss.cssfx.impl.CSSFXMonitor$URIRegistrar.classpathToURI(CSSFXMonitor.java:319)
    	at [email protected]/fr.brouillard.oss.cssfx.impl.CSSFXMonitor$URIRegistrar.register(CSSFXMonitor.java:342)
    	at [email protected]/fr.brouillard.oss.cssfx.impl.CSSFXMonitor$StyleSheetChangeListener.onChanged(CSSFXMonitor.java:399)
    	at javafx.base/com.sun.javafx.collections.ListListenerHelper$Generic.fireValueChangedEvent(ListListenerHelper.java:329)
    	at javafx.base/com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:73)
    	at javafx.base/javafx.collections.ObservableListBase.fireChange(ObservableListBase.java:239)
    	at javafx.base/javafx.collections.ListChangeBuilder.commit(ListChangeBuilder.java:482)
    	at javafx.base/javafx.collections.ListChangeBuilder.endChange(ListChangeBuilder.java:541)
    	at javafx.base/javafx.collections.ObservableListBase.endChange(ObservableListBase.java:211)
    	at javafx.base/javafx.collections.ModifiableObservableListBase.addAll(ModifiableObservableListBase.java:109)
    	at [email protected]/com.dlsc.showcase.impl.CssShowcaseViewSkin.updateStylesheets(CssShowcaseViewSkin.java:103)
    	at [email protected]/com.dlsc.showcase.impl.CssShowcaseViewSkin.lambda$new$0(CssShowcaseViewSkin.java:90)
    
    waiting feedback 
    opened by dlemmermann 8
  • Many important improvements

    Many important improvements

    Guess it's time for some improvements for CSSFX.

    The improvements are:

    • CleanupDetector uses now WeakReferences instead of PhantomReferences - which helps analyze heap dumps, and also should improve the performance.
    • Updated JMemoryBuddy
    • Started CSSFX multiple times is now prevented. This actually caused problems in production.
    • It's now possible to globally disable CSSFX with the system property -Dcssfx.disable=true
    opened by FlorianKirmaier 7
  • Same URL can now be added to the same list and classpaths are now supported.

    Same URL can now be added to the same list and classpaths are now supported.

    I've noticed a race condition which only happened in the newest version. It was caused by removing runLater when using the FX-Thread - which was not wrong - but it changed the timings slightly. The underlying issue was, that adding the same URL can lead to an exception. I've simplified the logic in the URIStyleUpdater which now supports the same URL twice.

    I've also added support for specifying the stylesheet as a classpath.

    Slightly offtopic, can you do me a favor and mention somewhere https://www.jpro.one/ for providing/sponsoring the bugfixes I've provided? We will also promote the library because in our opinion this library is mandatory for JavaFX to stay competitive with all the other UI-Frameworks. For that reason, every JavaFX Developer should start using it.

    opened by FlorianKirmaier 7
  • #24 and #22 - Fixing exponential growth

    #24 and #22 - Fixing exponential growth

    #24 I Rewrote the "monitoring code" in CSSFXMonitor. previously listeners were created exponentially - leading to slowdowns and potential crashes. The new Code makes sure, that each Scene/Window/Node is monitored only once. I've removed the unregister methods and events because they weren't doing anything useful.

    I'm using WeakHashMaps as WeakHashSet, because I don't want to add a new dependency to the project.

    I've also fixed #22.

    opened by FlorianKirmaier 6
  • Replace cssfx's own logging functionality with slf4j

    Replace cssfx's own logging functionality with slf4j

    Please consider to replace cssfx's own logging functionality with slf4j. It's in order to support the major logging frameworks like log4j2, logback, etc. much easier.

    slf4j removes the boilercode inside the user's JavaFX application to translate from cssfx's logger implementation to the major logging frameworks by implementing fr.brouillard.oss.cssfx.impl.log.CSSFXLogger.Logger and fr.brouillard.oss.cssfx.impl.log.CSSFXLogger.LoggerFactory.

    enhancement wontfix 
    opened by fireandfuel 5
  • provide module info

    provide module info

    as stated in #30 cssfx is not modular.

    we should remedy to that by:

    • either fixing the automatic module name
    • provide real module-info

    Also the module name to expose must be defined:

    1. cssfx it is the current automatic module name:
      • good for compatibility reasons
      • bad for potential collisions in global namespace
    2. org.fxmisc.cssfx
      • avoid collisions by using the current groupId namespace
      • bad because out control, domain is owned by Thomas Mikula
    3. fr.brouillard.cssfx
      • avoid collisions by using an owned groupId namespace
      • its a controlled namespace (including for deployment in central)
    opened by McFoggy 5
  • Linear or Exponential Growth due to unregister logic

    Linear or Exponential Growth due to unregister logic

    CSSFXMonitor When the following methods are called: registerNode unregisterNode registerNode then the listener of the first registerNode are not cleanedUp. If this process is repeated, more and more listeners get collected ultimately slowing down the application. The same happens for the other register and unregister methods.

    Ironically this escalates when I'm opening ScenicView in the same JVM (Without the cssfx inside of ScenicView). Then it slowly slows down until it crashes.

    My recommendation is to remove the unregister events entirely like it was done in my original PR. It's really hard to get the unregister logic correct.

    I've tested that removing the whole unregister logic fixes the problem.

    opened by FlorianKirmaier 3
  • Make CSSFX work with Java 9+

    Make CSSFX work with Java 9+

    In Java 9+, the method in com.sun.javafx.stage.StageHelper.getStages() got removed, which breaks CSSFX. However, in Java 9+ there is a method in javafx.stage.Window.getWindows() which returns all Windows, which can then be cast into a Stage (since Stage extends Window, this is not problematic). I changed the call so it works with Java 9+. Maybe you could consider making a separate branch for Java 9+, I will then change the target to that branch, then you can release a separate version for Java 9, since Window.getWindows() is not available in Java 8.

    opened by martinfrancois 3
  • When a CSS-File is changed and used afterwards, the unchanged version is used.

    When a CSS-File is changed and used afterwards, the unchanged version is used.

    When a CSS-File is changed and used afterward, the unchanged version is used.

    Typical pattern to reproduce:

    • Open Your application
    • Make a change to your css file.
    • Open a stage which uses the changed css file
    • The old unchanged cssfile is used.
    enhancement 
    opened by FlorianKirmaier 2
  • Fixed Gradle Support

    Fixed Gradle Support

    This pull request fixes the support for Gradle. Probably, the old version never worked properly. With this change, cssfx should work fine with the latest version of Gradle.

    It also works with javafx11 for me.

    I've published it in my repository, so it can be used by everyone. Here is a snipped, on how to use it:

    repositories {
      jcenter()
    
      maven {
        url "http://sandec.bintray.com/repo"
      }
    }
    dependencies {
      compile 'de.sandec.cssfx:cssfx:1.0.4'
    }
    
    opened by FlorianKirmaier 2
  • Removing stylesheets from scene not possible while using CSSFX

    Removing stylesheets from scene not possible while using CSSFX

    While working on dark mode support I noticed that I could not disable the dark mode anymore. I enable dark mode by adding additional stylesheets to my application. Then when I disable the dark mode I do so by removing those added stylesheets. This has no effect when using CSSFX.

    enhancement 
    opened by dlemmermann 2
  • Stylesheets in FXML files used via AfterburnerFX are not monitored

    Stylesheets in FXML files used via AfterburnerFX are not monitored

    Our application uses AfterburnerFX and tons of FXML files. The CSS files are discovered either by "Convention" (css file has same name as fxml file) or via "Configuration" (declared explicitly in fxml file). I tried both and changing the CSS file does not trigger a reload.

    Example:

    <VBox styleClass="overview" xmlns="http://javafx.com/javafx/8.0.121"
          xmlns:fx="http://javafx.com/fxml/1" minWidth="400" maxWidth="400"
          stylesheets="@ElectricityRatePlanOverview.css, @../RatePlanOverview.css"
          fx:controller="uk.co.senapt.desktop.ui.module.product.rateplan.electricity.ElectricityRatePlanOverviewController">
    </VBox>
    
    enhancement 
    opened by dlemmermann 1
  • CSSFX doesn't monitor changes in Application stylesheet

    CSSFX doesn't monitor changes in Application stylesheet

    When I define global CSS file for all stages of javafx application (see below), then changes aren't reloaded.

            final URL globalCssFile = getClass().getResource("styles/Global.css");
            Application.setUserAgentStylesheet(globalCssFile.toExternalForm());
    
    enhancement help wanted 
    opened by Liso-cz 7
  • handle css resources declared as classpath resource

    handle css resources declared as classpath resource

    People reported me they were using CSS like

    scene.getStylesheets().add("/styles/main.css")
    

    instead of using a URL.

    The JavaFX CSS reference guide says that CSS should be referenced by URL.

    Not clear yet if we have to support it or not.

    enhancement help wanted 
    opened by McFoggy 1
Owner
Matthieu Brouillard
Passionate developer, I strongly believe in Java & JEE and do my best to participate in the OSS effort : http://oss.brouillard.fr. Feel free to contact me.
Matthieu Brouillard
CSS-style shadows for Android

Fifty Shades: CSS-style shadows for Android What? In CSS, shadows are specified by (dx, dy, blurRadius, colour) (I call it ShadowSpec). This library i

Mike 73 Dec 19, 2022
Tray Icon implementation for JavaFX applications. Say goodbye to using AWT's SystemTray icon, instead use a JavaFX Tray Icon.

FXTrayIcon Library intended for use in JavaFX applications that makes adding a System Tray icon easier. The FXTrayIcon class handles all the messy AWT

Dustin Redmond 248 Dec 30, 2022
Lib-Tile is a multi Maven project written in JavaFX and NetBeans IDE 8 and provides the functionalities to use and handle easily Tiles in your JavaFX application.

Lib-Tile Intention Lib-Tile is a multi Maven project written in JavaFX and NetBeans IDE and provides the functionalities to use and handle easily Tile

Peter Rogge 13 Apr 13, 2022
DataFX - is a JavaFX frameworks that provides additional features to create MVC based applications in JavaFX by providing routing and a context for CDI.

What you’ve stumbled upon here is a project that intends to make retrieving, massaging, populating, viewing, and editing data in JavaFX UI controls ea

Guigarage 110 Dec 29, 2022
Collection of Binding helpers for JavaFX(8)

Advanced-Bindings for JavaFX (8) advanced-bindings is a collection of useful helpers and custom binding implementations to simplify the development of

Manuel Mauky 63 Nov 19, 2022
Docking framework for JavaFX platform

Docking framework for JavaFX platform AnchorFX is a gratis and open source library for JavaFX to create graphical interfaces with docking features Anc

Alessio Vinerbi 197 Oct 15, 2022
A library of +70 ready-to-use animations for JavaFX

AnimateFX A library of ready-to-use animations for JavaFX Features: Custom animations Custom interpolators Play/Stop animation Play an animation after

Loïc Sculier 366 Jan 5, 2023
BootstrapFX: Bootstrap for JavaFX

BootstrapFX BootstrapFX is a partial port of Twitter Bootstrap for JavaFX. It mainly provides a CSS stylesheet that closely resembles the original whi

Kordamp 810 Dec 28, 2022
A Java framework for creating sophisticated calendar views (JavaFX 8, 9, 10, and 11)

CalendarFX A Java framework for creating sophisticated calendar views based on JavaFX. A detailed developer manual can be found online: CalendarFX 8 D

DLSC Software & Consulting GmbH 660 Jan 6, 2023
A JavaFX UI framework to create fully customized undecorated windows

CustomStage A JavaFX undecorated stage which can fully be customized Donations If this project is helpful to you and love my work and feel like showin

Oshan Mendis 186 Jan 6, 2023
MDI components for JavaFX

DesktopPaneFX DesktopPaneFX is a JavaFX version of Swing’s JDesktopPane which can be used as a container for individual "child" similar to JInternalFr

Kordamp 58 Sep 23, 2022
Efficient VirtualFlow for JavaFX

Flowless Efficient VirtualFlow for JavaFX. VirtualFlow is a layout container that lays out cells in a vertical or horizontal flow. The main feature of

null 163 Nov 24, 2022
A framework for easily creating forms for a JavaFX UI.

FormsFX Forms for business application made easy. Creating forms in Java has never been this easy! Maven To use this framework as part of your Maven b

DLSC Software & Consulting GmbH 534 Dec 30, 2022
:icecream: iOS frosty/translucent effect to JavaFX

FroXty is JavaFX library which replicates the famous iOS translucent effect with ease. Set-up FroXty can be imported into your project either by downl

Giorgio Garofalo 33 Dec 11, 2022
💠 Undecorated JavaFX Scene with implemented move, resize, minimise, maximise, close and Windows Aero Snap controls.

Support me joining PI Network app with invitation code AlexKent FX-BorderlessScene ( Library ) ?? Undecorated JavaFX Scene with implemented move, resi

Alexander Kentros 125 Jan 4, 2023
Dynamic JavaFX form generation

FXForm 2 Stop coding forms: FXForm 2 can do it for you! About FXForm2 is a library providing automatic JavaFX form generation. How does it work? Write

dooApp 209 Jan 9, 2023
A JavaFX library that allows Java2D code (Graphics2D) to be used to draw to a Canvas node.

FXGraphics2D Version 2.1, 3 October 2020. Overview FXGraphics2D is a free implementation of Java's Graphics2D API that targets the JavaFX Canvas. It m

David Gilbert 184 Dec 31, 2022
Auto updating launcher for JavaFX Applications

FXLauncher Auto updating launcher for JavaFX Applications. Combined with JavaFX native packaging, you get a native installer with automatic app update

Edvin Syse 694 Dec 27, 2022