GithubHelp home page GithubHelp logo

dlsc-software-consulting-gmbh / preferencesfx Goto Github PK

View Code? Open in Web Editor NEW
583.0 23.0 66.0 4.61 MB

A framework for easily creating a UI for application settings / preferences.

License: Apache License 2.0

Java 97.43% CSS 2.57%
javafx ui preferences framework component

preferencesfx's Introduction

JFXCentral

PreferencesFX

Preference dialogs for business applications made easy. Creating preference dialogs in Java has never been this easy!

Maven Central Build Status FOSSA Status

screenshot of created preferences dialog

Table of Contents

Maven

To use this framework as part of your Maven build simply add the following dependency to your pom.xml file:

Java 8

<dependency>
  <groupId>com.dlsc.preferencesfx</groupId>
  <artifactId>preferencesfx-core</artifactId>
  <version>8.6.0</version>
</dependency>

Java 11

<dependency>
  <groupId>com.dlsc.preferencesfx</groupId>
  <artifactId>preferencesfx-core</artifactId>
  <version>11.8.0</version>
</dependency>

Gradle

To use this framework as part of your gradle build simply add the following to your build.gradle file and use the following dependency definition:

Java 8

dependencies {
    compile group: 'com.dlsc.preferencesfx', name: 'preferencesfx-core', version: '8.6.0'
}

Java 11

dependencies {
    compile group: 'com.dlsc.preferencesfx', name: 'preferencesfx-core', version: '11.8.0'
}

What is PreferencesFX?

Creating preference dialogs in JavaFX is a tedious and very error-prone task. PreferencesFX is a framework which solves this problem. It enables the developer to create preference dialogs with ease and creates well-designed and user-friendly preference dialogs by default.

Advantages

  • Less error-prone
  • Less code needed
  • Easy to learn
  • Easy to understand
  • Easy to use, for developers and users alike

Main Features

  • Simple and understandable API
  • The most important features are noted in the picture and the corresponding table below:

screenshot of created preferences dialog with features

Nr. Feature Description
1 Search / Filter Filters all categories for a given String. Enables searching for a Setting, Group or Category by name.
2 TreeView Shows all categories in a hierarchical structure
3 Breadcrumb Bar Shows the user the previous categories in the hierarchy to the currently displayed category and allows the user to navigate back.
4 Undo / Redo Buttons Allows the user a stepwise undo and redo possibility of his last changes.
5 Various pre-defined setting types e.g. Integer, Double, Boolean, String, Lists, Objects
6 close/cancel buttons The close button just closes the window and leaves the preferences as they are. The cancel button discards all changes which are made during the time the dialog was last opened.
  • | Instant persistance | Any changes to the application are saved instantly.

Documentation

This project uses the asciidoctor plugin to generate the necessary documentation. Run the following maven task:

process-resources

Afterwards, you will find the documentation in the target/generated-docs/ subdirectory.

Structure

A preferences dialog can contain multiple Categories.
Each Category contains one to multiple Groups
Each Group contains one to multiple Settings

For better illustration, the basic concept of writing a preferences dialog is shown below:

PreferencesFx preferencesFx = 
    PreferencesFx.of(SaveClass.class,
        Category.of("Category Title",
            Group.of("Group Title",
                Setting.of("Setting Title", new Property())
            )
        )
    );

Notes:

  • It is also possible to omit the Group and declare all settings in a Category directly. However, in this case all settings will simply be displayed one after another without grouping. If you want more control, use Group.
  • A Group can also be defined without a title. In this case, the individual groups are displayed with more space in between them, to ensure they can be differentiated.
  • A Category can also take a graphic node to be used as an icon as the second argument, e.g. Category.of("Category Title", new ImageView(new Image("file:icon.png")),

Demos

We created several demos to visualize the capabilities of PreferencesFX.
Simply launch preferencesfx-demo/src/com/dlsc/preferencesfx/AppStarter.java and look into the different Tabs.

The following demos are available:

Import Description
Standard The standard demo with a few settings and fully working bindings.
Internationalized Shows how to define preference dialogs in multiple languages, using internationalization.
OneCategory Shows the behavior of the API when only one category is used: The Breadcrumb Bar and TreeView will be omitted from the GUI.
Extended A demo, populated with lots of categories, groups and settings without any bindings. Designed to show usage in a big project.

Defining a preferences dialog

Creating a preferences dialog is as simple as calling PreferencesFx.of().

StringProperty stringProperty = new SimpleStringProperty("String");
BooleanProperty booleanProperty = new SimpleBooleanProperty(true);
IntegerProperty integerProperty = new SimpleIntegerProperty(12);
DoubleProperty doubleProperty = new SimpleDoubleProperty(6.5);

PreferencesFx preferencesFx = 
    PreferencesFx.of(AppStarter.class, // Save class (will be used to reference saved values of Settings to)
        Category.of("Category title 1",
            Setting.of("Setting title 1", stringProperty), // creates a group automatically
            Setting.of("Setting title 2", booleanProperty) // which contains both settings
        ),
        Category.of("Category title 2")
            .expand()                                       // Expand the parent category in the tree-view
            .subCategories( // adds a subcategory to "Category title 2"
                Category.of("Category title 3",
                    Group.of("Group title 1",
                        Setting.of("Setting title 3", integerProperty)
                    ),
                    Group.of( // group without title
                        Setting.of("Setting title 3", doubleProperty)
                    )
                )
            )
    );

This code snippet results in the following preferences window, containing three categories:

result

To create a Setting, you only need to define a title and a Property. PreferencesFX does the rest.
You can then integrate this Property in your application. Changes of values in the preferences dialog will be persisted instantly, however it's up to you to decide whether you want to persist them instantly in your application as well.

Required arguments

You have a lot of options to influence the behavior and layout of the preferences dialog.
The following parameters are the absolute minimum, needed for the proper functioning of PreferencesFX:

Parameter Description
AppStarter.class In the constructor of PreferencesFx a saveClass is required. This class is saved as a key for the saved setting values. Further information is available in the javadoc.
Category description Each Category must have a description. This is required to display its description in the TreeView.
Setting description Each Setting must have a description. It will be displayed on the left of the control, which is used to manipulate the respective Setting.

Note: The value of the each Setting is stored using the Java Preferences API by default.
For testing purposes, to clear the saved preferences of the demo, run the method in the class:

preferencesfx-demo/src/test/java/PreferencesStorageReset.java

Optional arguments

The following parameters are optionally available to further configure the dialog created by PreferencesFX:

Method Class Description
.subCategories Category Subcategories allow a Category to have additional subcategories as children. Those are also displayed in the tree.
.expand Category Allows to specify if the Category should be expanded in the Tree-View by default.
.description Group If you decide not to add the description of a group in the constructor, you can still add it after the creation of the group.
.validate Setting Allows to add a Validator to a setting, to set constraints to the values that can be entered.
.persistApplicationState PreferencesFx Defines if the Preferences API should save the application states. This includes the state persistence of the dialog window, as well as the values of each Setting.
.persistWindowState PreferencesFx Defines whether the state of the dialog window (position, size, last selected Category) should be persisted or not. Defaults to false.
.saveSettings PreferencesFx Defines whether the changed settings in the Preferences window should be saved or not. Defaults to true.
.debugHistoryMode PreferencesFx Makes it possible to enable or disable the keycombination to open a debug view of the list of all actions in the history (undo / redo). Pressing Ctrl + Shift + H (Windows) or CMD + Shift + H (Mac) opens a dialog with the undo / redo history, shown in a table. Defaults to false.
.buttonsVisibility PreferencesFx Sets the visibility of the cancel and close buttons in the PreferencesFxDialog. Defaults to true.
.instantPersistent PreferencesFx If set to true, it will instantly apply any changes that are being made in the PreferencesFxDialog. If set to false, it will only apply changes when the Save / Apply / OK button is pressed. Due to a limitation in FormsFX, undo / redo cannot be used with instant persistence switched off! Defaults to true.
.i18n PreferencesFx Sets the translation service of the preferences dialog for internationalization.
.dialogTitle PreferencesFx Allows to specify a custom dialog title.
.dialogIcon PreferencesFx Allows to specify a custom dialog icon.

Setting types

The following table shows how to create Settings using the predefined controls and how they look like:

Syntax Outcome
// Integer
IntegerProperty brightness = new SimpleIntegerProperty(50);
Setting.of("Brightness", brightness);
// Integer Range
IntegerProperty fontSize = new SimpleIntegerProperty(12);
Setting.of("Font Size", fontSize, 6, 36);
// Double
DoubleProperty scaling = new SimpleDoubleProperty(1);
Setting.of("Scaling", scaling);
// Double Range
DoubleProperty lineSpacing = new SimpleDoubleProperty(1.5);
Setting.of("Line Spacing", lineSpacing, 0, 3, 1);
// Boolean
BooleanProperty nightMode = new SimpleBooleanProperty(true);
Setting.of("Night Mode", nightMode);
// String
StringProperty welcomeText = new SimpleStringProperty("Hello World");
Setting.of("Welcome Text", welcomeText);
// Combobox, Single Selection, with ObservableList
ObservableList resolutionItems = FXCollections.observableArrayList(Arrays.asList(
  "1024x768", "1280x1024", "1440x900", "1920x1080")
);
ObjectProperty resolutionSelection = new SimpleObjectProperty<>("1024x768");
Setting.of("Resolution", resolutionItems, resolutionSelection);
// Combobox, Single Selection, with ListProperty
ListProperty orientationItems = new SimpleListProperty<>(
  FXCollections.observableArrayList(Arrays.asList("Vertical", "Horizontal"))
);
ObjectProperty orientationSelection = new SimpleObjectProperty<>("Vertical");
Setting.of("Orientation", orientationItems, orientationSelection);
// Combobox, Multi Selection
ListProperty favoritesItems = new SimpleListProperty<>(
  FXCollections.observableArrayList(Arrays.asList(
      "eMovie", "Eboda Phot-O-Shop", "Mikesoft Text",
      "Mikesoft Numbers", "Mikesoft Present", "IntelliG"
      )
  )
);
ListProperty favoritesSelection = new SimpleListProperty<>(
  FXCollections.observableArrayList(Arrays.asList(
      "Eboda Phot-O-Shop", "Mikesoft Text"))
);
Setting.of("Favorites", favoritesItems, favoritesSelection);
// Color
ObjectProperty colorProperty = new SimpleObjectProperty<>(Color.PAPAYAWHIP);
Setting.of("Font Color", colorProperty);
// FileChooser / DirectoryChooser
ObjectProperty fileProperty = new SimpleObjectProperty<>();
Setting.of("File", fileProperty, false);     // FileChooser
Setting.of("Directory", fileProperty, true); // DirectoryChooser
// Custom Control
IntegerProperty customControlProperty = new SimpleIntegerProperty(42);
IntegerField customControl = Field.ofIntegerType(customControlProperty).render(
  new IntegerSliderControl(0, 42));
Setting.of("Favorite Number", customControl, customControlProperty);
// Static node
Node staticNode = new Label("This can be your very own placeholder!");
Setting.of(staticNode);

Note: By default, PreferencesFX saves the settings under a key which consists of the breadcrumb to the setting, delimited by # signs. If you want to define your own key to be used for saving, use the method setting.customKey("key")

Localisation

All displayed strings can be internationalized. You can use resource bundles to define different locales and use the key instead of the descriptions. Adding i18n support is simply done by calling the method .i18n() at the end when creating the preferences:

private ResourceBundle rbDE = ResourceBundle.getBundle("demo.demo-locale", new Locale("de", "CH"));
private ResourceBundle rbEN = ResourceBundle.getBundle("demo.demo-locale", new Locale("en", "UK"));

private ResourceBundleService rbs = new ResourceBundleService(rbEN);

PreferencesFx.of(…)
             .i18n(rbs);

Validation

It is possible to optionally add a Validator to settings. PreferencesFX uses the implementation of FormsFX for the validation. FormsFX offers a wide range of pre-defined validators, but also includes support for custom validators using the CustomValidator.forPredicate() method. The following table lists the supported validators:

Validator Description
CustomValidator Defines a predicate that returns whether the field is valid or not.
DoubleRangeValidator Defines a number range which is considered valid. This range can be limited in either one direction or in both directions.
IntegerRangeValidator Defines a number range which is considered valid. This range can be limited in either one direction or in both directions.
RegexValidator Valiates text against a regular expression. This validator offers pre-defined expressions for common use cases, such as email addresses.
SelectionLengthValidator Defines a length interval which is considered valid. This range can be limited in either one direction or in both directions.
StringLengthValidator Defines a length interval which is considered valid. This range can be limited in either one direction or in both directions.

Visibility

PreferencesFX supports setting an optional visibility condition for Categories, Groups and Settings

  • condition could be defined as a lambda-expression
  • condition will be re-evaluated whenever any Setting changes
Category.of("General",
  Group.of("Display",
    Setting.of("Brightness", brightness),
    Setting.of("Night mode", nightMode, VisibilityProperty.of(brightness, (newValue) -> newValue.intValue() > 50)),
    Setting.of("Scale", scale, VisibilityProperty.of(nightMode),
    Setting.of("Is production category visible", productionVisibility)
  )
),
Category.of("Production", VisibilityProperty.of(productionVisibility),
  Group.of("Display",
      Setting.of("Port", salary, VisibilityProperty.of(nightMode)
  )
),
Category.of("View",
  Group.of("Display",
    Setting.of("Salary", salary, VisibilityProperty.of(nightMode)
  ),
  Group.of("Bonuses", VisibilityProperty.of(salary, (newValue) -> newValue.intValue() > 10),
    Setting.of("Bonus", bonus)
  )
)

Team

License

FOSSA Status

preferencesfx's People

Contributors

aalmiray avatar aldanchenko avatar anastasia-pavlovam avatar anneloreegger avatar arvidny avatar crschnick avatar dependabot-preview[bot] avatar dependabot[bot] avatar dieterholz avatar dlemmermann avatar finanzer avatar fossabot avatar genron avatar github-actions[bot] avatar jellevanabbema avatar kivimango avatar lgtm-migrator avatar marco-sanfratello avatar martinfrancois avatar naoghuman avatar nerd-king avatar psharma-gdal avatar reikjarloekl avatar rladstaetter avatar sclassen avatar shannah avatar unknowifguestindream avatar virtualtim avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

preferencesfx's Issues

Let Category support an additional description

As of 2.0.2 the Category class holds a simple description and a value. It would be great if an additional description could be added to a particular Category, see attached screenshot from IntelliJ

category-description

Allow the default category to be defined

Refactor the DEFAULT_CATEGORY into a property in the model (defaultCategoryPropety) and allow it to be set via a method in PreferencesFx like defaultCategory(...) that can be used for chaining, just as dialogTitle() for example. Then, in the PreferencesFxModel you just have to change: setDisplayedCategory(getCategories().get(DEFAULT_CATEGORY)); to check if the property is set, and if it's not, it will take the first category as the default category (as it is now) and if the property is set, it will set that as the displayed category.

Cancel Button doesn't restore original values

Hello,

I am currently trying to use PreferencesFX and I have encountered a problem or even a bug directly.

I created a simple demo application with PreferencesFX, with a StringProperty, an IntegerProperty and a BooleanProperty. I put a listener on the StringProperty, which always gives me the latest content when changes are made.

private final StringProperty welcomeText = new SimpleStringProperty("Hello World");
this.welcomeText.addListener((observable, oldValue, newValue) -> System.out.println(newValue));

This allows me to see that the changes are not undone when leaving the window via the Cancel button. Is this a bug or do I still have to adjust other parts to make the Cancel button work properly?

My entire demo application is available in the following Gist: https://gist.github.com/elyday/64a0975551fb7121b874491bc6eaef33

Invalid preferences format

For some reason, I get the above error each time I try to open previous settings. After some investigation, this seem to be because of characters that are stored that the preference file does not support. This is an example of a preference:

<entry key="/&#29;��Lϙ ��`��L?�H}=&lt;�&#9;�H�}&#23;��#=" value="0"/>

Note how it says e.g. &#29; instead of the character it is supposed to show. Removing those characters made the preference file open again. Changing this line to the line below resolves the issue for me.

return Base64.getEncoder().encodeToString(messageDigest.digest());

Has anyone else noticed this issue and would there be any other problems with changing the line to the above?

Wrong versions for dependencies?

I just tried to add this library to a Gradle project, but the synchronization fails.

Could not find org.controlsfx:controlsfx:9.0.1-SNAPSHOT.
Searched in the following locations:
  - https://jcenter.bintray.com/org/controlsfx/controlsfx/9.0.1-SNAPSHOT/maven-metadata.xml
  - https://jcenter.bintray.com/org/controlsfx/controlsfx/9.0.1-SNAPSHOT/controlsfx-9.0.1-SNAPSHOT.pom
  - https://jcenter.bintray.com/org/controlsfx/controlsfx/9.0.1-SNAPSHOT/controlsfx-9.0.1-SNAPSHOT.jar
  - https://jcenter.bintray.com/org/controlsfx/controlsfx/9.0.1-SNAPSHOT/maven-metadata.xml
  - https://jcenter.bintray.com/org/controlsfx/controlsfx/9.0.1-SNAPSHOT/controlsfx-9.0.1-SNAPSHOT.pom
  - https://jcenter.bintray.com/org/controlsfx/controlsfx/9.0.1-SNAPSHOT/controlsfx-9.0.1-SNAPSHOT.jar
Required by:
    project : > com.dlsc.preferencesfx:preferencesfx-core:11.1.0
Open File

When I was looking at the Maven Repository, it seems like the most recent version is 9.0.0. org.eclipse.fx.ui.controls also requires a higher version number (3.3.0) than the repository has (2.5.0). Or am I just missing something in the setup?

Allow preferences to be saved at any time

Currently preferences may be saved after the dialog is closed. It would be great to allow preferences to be saved at any point in time without having to pop open the dialog, think for example an application that stores x, y, width, height coordinates of the main window. These coordinates may be set using the preferences dialog, but can also be updated by tracking user actions (such as resizing or dragging the window). These values should be stored before the application is shutdown.

There are at least 2 possible options with the current API design:

  1. add a getter to expose PreferencesModel.
  2. add an explicit method to PreferencesFX such as savePreferences.

Personally I'd lean for option 1 as you may also load/sync preference values at any time value calling load on the model. This still keeps the load/save behavior in one place: the model.

Related to #8

How to access single preference values

Thanks for creating such a nice library. I like the idea and realization looks really promising.

There is one thing I couldn't figure out while browsing through the code. I hope it is ok if I use this issue tracker for my question: How do I load and save single (or multiple) settings without using the preference dialog?

The structure in the examples appears to be: you create a PreferencesFx instance which specifies in which categories and groups you want to display your settings. The preferences values are synced with JavaFX properties. I can then bind these properties to my controls or read their current values depending on my needs.
My questions with this process are the following:

  • Which method actually loads the preference values from the StorageHandler into these JavaFX properties.
  • Are the properties synced with the preference store, i.e. can I just change a value of the property and it is automatically stored in the registry?
  • What is the preferred way to access the current value of a given preference, especially if I want to respect separation between gui and backend code. Thus I probably don't want to use the PreferencesFX class because this is used to show the dialog, i.e. it GUI code.

So these questions can kind of be summarized in: How do you structure preferences loading and saving with your library while respecting separation of gui and backend logic?

Human readable key stored

Hi,

When a key is stored (except one of the predefined for positions and size), the key is a sha-256 converted to String.
When you look in the registry (in Windows), you have this uggly look:
image

I see that you want to use a hash of the key given, but

  1. you don't apply this rule to your keys, so why the other should do?
  2. why not store the breadcrumb directly?

And remember:
“Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.” – John F. Woods
which is also available for the results of the code.

External changes of preference values not possible

Now the preference values will be read from storage everytime the method show() is called. That makes it impossible to change a value somewhere else in the application, because a new value will b overriden by storageHandler. Is it really usefull to read the values everytime when the dialog is shown? I think the values are already in memory and could be used directly.

Switch implementation from `Field` to `Element`

As of FormsFX 1.3.0, introduced by dlsc-software-consulting-gmbh/FormsFX#28 a Field is now a subclass of Element. From PreferencesFX 2.1.0, the included dependency of FormsFX has been updated to 1.3.0, but still only Field is supported and not Element.
By using Field we are limited in terms of the features of FormsFX we and also the API user can use and thereby benefit from.

This change would involve replacing all occurences of Field with Element and to also expose Element instead of Field externally. Currently, a quick fix is in place (#39), which casts the Element objects to Fields. Going with Element internally instead of Field eliminates the need for a cast and opens up additional features which can then be used for custom controls and also to expose additional functionality with PreferencesFX.

Migrating to the new architecture of FormsFX makes sense, but since PreferencesFX makes heavy use of FormsFX, also using custom renderers and controls to change a lot of the behavior of FormsFX, this is not an easy task, while still preserving the original functionality as currently implemented by PreferencesFX.

Use as Node

Can I also have the preferences as Node, for example to make it a tab? Or does it only support popup dialogues?

Blank dialog content

When I use the maven release 2.0.3, it works fine. When I clone the repo's develop branch, and try to run the preferencesfx-demo, I get blank content in the preferences dialog as shown below. I get the same for all of the demos.

image

Running on JDK1.8u141

Buttons behavior: cancel should cancel?

Hi,

I have few remarks to share with you about the buttons:
Usually, for this kind of screen, there are 3 buttons (see example below form the settings screen of IntelliJ Idea):
image
OK: to save and close
Cancel: Do not save anything
Apply: save but keep open

  1. If you want to keep 2 buttons, which I think is easier to understand, I would suggest to rename "Close" into "Save and Close"

  2. My main concern is about the Cancel button. I do not expect to have anything saved when a user press the Cancel button. Currently, when persistWindowState(true) the position and size are saved.
    Also, when having a listener on the Preferences changes, we can see that the preferences are saved and then rollback. It's dangerous for many obvious reasons and also I do not see why you do it like that. I would suggest to have a Cancel (and top Cross button) to just close the dialog without any modification and thus to remove the mode where you do not have any buttons (which is never understandable for the users).

How to Wrap root with another parent?

Hi Just a question, is there a way to wrap the preferencefx window content into another Node?
I just want to wrap all the content in a stackpane... thank you.

Maven repository down?

I'm getting this when I try to build:

Steves-iMac:PreferencesFX shannah$ gradle jar
:compileJava

FAILURE: Build failed with an exception.

* What went wrong:
Could not resolve all dependencies for configuration ':compile'.
> Could not find at.bestsolution.efxclipse.rt:org.eclipse.fx.ui.controls:3.0.0.
  Searched in the following locations:
      https://jcenter.bintray.com/at/bestsolution/efxclipse/rt/org.eclipse.fx.ui.controls/3.0.0/org.eclipse.fx.ui.controls-3.0.0.pom
      https://jcenter.bintray.com/at/bestsolution/efxclipse/rt/org.eclipse.fx.ui.controls/3.0.0/org.eclipse.fx.ui.controls-3.0.0.jar
      https://repo1.maven.org/maven2/at/bestsolution/efxclipse/rt/org.eclipse.fx.ui.controls/3.0.0/org.eclipse.fx.ui.controls-3.0.0.pom
      https://repo1.maven.org/maven2/at/bestsolution/efxclipse/rt/org.eclipse.fx.ui.controls/3.0.0/org.eclipse.fx.ui.controls-3.0.0.jar
      https://jitpack.io/at/bestsolution/efxclipse/rt/org.eclipse.fx.ui.controls/3.0.0/org.eclipse.fx.ui.controls-3.0.0.pom
      https://jitpack.io/at/bestsolution/efxclipse/rt/org.eclipse.fx.ui.controls/3.0.0/org.eclipse.fx.ui.controls-3.0.0.jar
      http://maven.bestsolution.at/efxclipse-releases/at/bestsolution/efxclipse/rt/org.eclipse.fx.ui.controls/3.0.0/org.eclipse.fx.ui.controls-3.0.0.pom
      http://maven.bestsolution.at/efxclipse-releases/at/bestsolution/efxclipse/rt/org.eclipse.fx.ui.controls/3.0.0/org.eclipse.fx.ui.controls-3.0.0.jar
  Required by:
      com.dlsc:PreferencesFX:1.3.0-SNAPSHOT

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

Total time: 7.737 secs

Am I doing something wrong? Is there a jar only distribution I can download directly without having to build it?

Let Setting support additional description

As of 2.0.2 the Setting class holds a simple description and a value. It would be great if an additional description could be added to a particular Setting, see attached screenshot from IntelliJ

section-description

Retreive Saved prefrences with out binding

Hi,
I want to know, how to retreive saved prefrences , PrefrencesFX Object
Some thing like
if(prefs.get("settingName") == "some thing") {

// do task
}

Thank's in advenced,

Display overview per Category

Intellij has the ability to show an overview page for each Category that has subcategories. The overview shows a descriptive text and links to every subcategory. Clicking on a link opens the page for that category, as well as selecting the matching category on the tree. See attached screenshot

category-overview

Open PreferencesFX for extension

The current design of the PreferencesFX class does not provide extension points that could be used to tweak behavior (see #4 for example). It would be better perhaps to expose internal state via protected fields or methods, also use the template factory method in the constructor, delegating the actual creation on collaborators to protected methods, such as

  protected PreferencesFx(Class<?> saveClass, Category... categories) {
    // asciidoctor Documentation - tag::testMock[]
    preferencesFxModel = createPreferencesFxModel(
        createStorageHandler(saveClass), createSearchHandler(), createHistory(), categories
    );
    // asciidoctor Documentation - end::testMock[]

    // setting values are only loaded if they are present already
    preferencesFxModel.loadSettingValues();

    undoRedoBox = createUndoRedoBox(preferencesFxModel.getHistory());

    breadCrumbView = createBreadCrumbView(preferencesFxModel, undoRedoBox);
    breadCrumbPresenter = createBreadCrumbPresenter(preferencesFxModel, breadCrumbView);

    categoryController = createCategoryController();
    initializeCategoryViews();
    // display initial category
    categoryController.setView(preferencesFxModel.getDisplayedCategory());

    navigationView = createNavigationView(preferencesFxModel);
    navigationPresenter = createNavigationPresenter(preferencesFxModel, navigationView);

    preferencesFxView = createPreferencesFxView(
        preferencesFxModel, navigationView, breadCrumbView, categoryController
    );
    preferencesFxPresenter = createPreferencesFxPresenter(preferencesFxModel, preferencesFxView);
}

Reduce coupling

Currently, most objects store references the each other:
PreferencesFX stores everything
The view keeps references to storage and other stuff
Etc.

This is not good design and makes it harder to customise and improve the individual components.

Show() cannot be called twice?

I've just been trying out the new release and I'm really grateful for the additions that have been made for this release! However, as far as I can tell the PreferenceFXDialog cannot be closed and reopened with the current code, since modality is always set on show() but the modality cannot be reassigned if it's already been shown:

Exception in thread "JavaFX Application Thread" java.lang.IllegalStateException: Cannot set modality once stage has been set visible
	at javafx.stage.Stage.initModality(Stage.java:525)
	at javafx.scene.control.HeavyweightDialog.initModality(HeavyweightDialog.java:132)
	at javafx.scene.control.Dialog.initModality(Dialog.java:438)
	at com.dlsc.preferencesfx.view.PreferencesFxDialog.show(PreferencesFxDialog.java:71)
	at com.dlsc.preferencesfx.PreferencesFx.show(PreferencesFx.java:143)
	at com.dlsc.preferencesfx.PreferencesFx.show(PreferencesFx.java:134)

Please correct me if I'm missing something here.

Add icons

I was just wondering if you plan on supporting icons for the tree items? Something like this:

treeviewicons

I am investigating the possibility use your library instead of our own settings dialog with tabs, and being able to use the same icons would ease the transition for the users.

options

On a side note (you can make this a separate issue if you would consider this a feature suggestion), I'm also wondering if you plan on allowing users to add custom nodes (mainly images) to a category? As you can see in the example above, we use images to help users know what they are changing.

File/Directory setting type with chooser?

I'd love to use PreferenceFX but I'm held back by the lack of a setting that would allow the user to pick an existing or new file/directory from the file system. Seems to be a pretty general-purpose setting and I'm surprised it's not been asked about. Is there any plan to add that, or any easy workarounds that I've missed? I may eventually put some resources towards implementing it myself, but that's very unlikely for the time being.

Missing legend with quicklinks in the ReadMe.

Missing legend with quicklinks in the ReadMe.

In your amazing ReadMe I missing after the start section the legend with the quicklinks in the ReadMe which allowed the interested to jump quickly the section from interest.

Have a look in the ReadMe from https://github.com/openjfx/samples after the section 'Description'. When you want I can create a PR.

load

Why are preferences encrypted?

Too many Dependencies

PreferencesFX has many dependencies which themselves bring more transitive dependencies.
For a library which will be used in other projects this is sub optimal as it can easily lead to dependency hell.
For example: currently PreferencesFX has two versions of guava as its dependencies (27.0.1-jre and a shaded 21.0.0)

dependencies

I can provide a PR to decrease the number of dependencies if you see this as decirable

Null control character in the hash of breadcrumb

Hello!

I tried this little example:

 PreferencesFx preferencesFx = PreferencesFx.of(MainApp.class,
                Category.of("Test", Group.of("TestGroup",
                        Setting.of("Test Setting", new SimpleStringProperty("aa")))));
 preferencesFx.show();

At the show() method I got an exception:

Caused by: java.lang.IllegalArgumentException: Key contains code point U+0000
	at java.prefs/java.util.prefs.AbstractPreferences.get(AbstractPreferences.java:296)
	at com.dlsc.preferencesfx.util.StorageHandlerImpl.loadObject(StorageHandlerImpl.java:178)
	at com.dlsc.preferencesfx.model.Setting.loadSettingValue(Setting.java:359)
	at com.dlsc.preferencesfx.model.PreferencesFxModel.lambda$loadSettingValues$7(PreferencesFxModel.java:192)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1378)
	at com.dlsc.preferencesfx.model.PreferencesFxModel.loadSettingValues(PreferencesFxModel.java:189)
	at com.dlsc.preferencesfx.PreferencesFx.init(PreferencesFx.java:66)
	at com.dlsc.preferencesfx.PreferencesFx.<init>(PreferencesFx.java:61)
	at com.dlsc.preferencesfx.PreferencesFx.<init>(PreferencesFx.java:52)
	at com.dlsc.preferencesfx.PreferencesFx.of(PreferencesFx.java:97)
	at com.nokia.supervisor.controller.agent.MenuBarController.openSettings(MenuBarController.java:127)

The hashed breadcrumb contains a null control character which if prohibited in the key of a preference.
The breadcrumb: Test#TestGroup#Test Setting
The hashed breadcrumb: image
The null control character is at the index of 16.

This prohibition for the preference key was added in JDK9 9 b63, see:
https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8075156

Could you change the hashing algorithm so it avoids adding null control characters to the hashed value?

Cheers

Edit: Is this fixed in #55 ?

React to close/save actions found in PreferencesDialog

I have the need to find out if the Close or Save buttons found in PreferencesDialog were clicked, but it's not possible to reach the event source (the buttons) without resorting to reflection hacks.

Suggestion: return the ButtonType in show(boolean) (see #7). However this suggestion does not cover the use case where the dialog is non-modal (old behavior of preferencesfx.show()) thus perhaps adding close/save event handlers (or listeners) to PreferencesFX would be better.

Add custom preference key

In our current setup, we have chosen not to use the Java Preferences API for various reasons. For instance, we want our advance users to be able to manually edit/add settings and we want users to be able to send their settings file to us in case we have problems recreating an issue. I found out you have the option to add a custom StorageHandler which is great for us, since it allows us to store the settings wherever we want. However, we already have a key for each setting that we would prefer to keep using instead of the breadcrumb hash.

I know the breadcrumb approach has been discussed before and that it is a question of the maximum amount of characters, but I would like to propose an option to make the breadcrumb optional instead of replacing it. First I was thinking about adding it as another variable to the constructors, but I realized it would mean a lot of additional lines and it might risk confusing anyone. So my suggestion would be to add a method in the Settings class called setCustomPreferenceKey(String key) or something like that and in the method saveSettingsValue change the line to look like this: storageHandler.saveObject(key.isEmpty() ? getBreadcrumb() : key, value.getValue()); That should prevent users from accidentally setting it and it would use the breadcrumb approach unless something else is deliberately set.

For our project it would mean that we could reuse our existing preference file quite easily, but I'm sure more users would appreciate the option to set humanly readable keys. I just wanted to check with you if you would be willing to consider something like that if I created a PR for it and if you have anything else you think I need to take into account first in that case?

Add possibillity to make Dialog APPLICATION_MODAL

Now it's not possible to set a init owner and the Dialog is not application modal. And there is no possibility to change this. This results in a new window without an icon and parallel using of application and preferences dialog (see screenshot).

image

It would be better, if this could be configured.

Conditional settings enhancement

Settings should be allowed to have sub-settings that are shown/hidden conditionally on the value of the parent. Example: I have a checkbox that enables/disables an additional part of my application. I don't want the settings for that part to be available unless the parent function is enabled, so having the option to display a Group/Groups only if the value of the parent is 'True' would be a nice enhancement.

Cannot use custom stylesheets on dialog

Dialogs created with PreferencesFx.show() cannot have their stylesheets set. Applications with custom stylesheets are unable to use anything but the default Modena styles on preferences dialogs

Why is everything observable?

While inspecting the code I find many Properties whose value is actually immutable, and set only once on object creation. Why are these Properties instead of simple variables?

Integer editor allows non numeric characters

It's possible for users to type in non numeric characters (such as letters) in the default renderer of an IntegerProperty. This leads to exceptions being thrown when using the up/down arrows or storing properties.

Set default view/Show first subcategory

I'm trying to add subcategories to the first tab, but I haven't been able to show the first subcategory directly. Is this possible with the current code? Since the main category is empty, it doesn't make sense for us to show that - I think that would only confuse our users.

empty tab

Adding new categories to an existing object

Currently it appears that you can define the PreferencesFx object once and that's it. I would like to be able to later access that object to add additional categories (for example from a module loaded later in my program).

As a workaround I am using an interface to create my modules, and searching for them using Spring, and I have a method that returns Category[] which I then add to the PreferencesFx object at the time of creation, but if I load a new module later in the app, I have no way of updating.

Replace StorageHandler

What is the preferred way to replace the built-in StorageHandler by a custom implementation? This seems to be necessary if one wants to save the preferences not using the Java Preference API (e.g. store the preferences in a file instead).

Required Fields Enhancement

In FormsFX there is the ability to add required fields. We can currently use validators, but it would be nice to be able to mark a field as required. When exiting the window where a save would be called, validate the whole form and prevent closing if any required fields are not filled in.

As a side effect, having a non-required field that is invalid would have to be carefully scruitinized, because say you have a validator for e-mail address on a non-required field. It is considered invalid if the value is blank (as far as I can see currently) so those fields would be skipped unless they have a non-zero length value that is invalid (i.e. someone@somewhere. would be considered invalid)

How to read preferences from command line mode?

I'm switching an app to WorkbenchFX and in that process I'm also looking into PreferencesFX.
The app in question can after being run and configurated in gui mode be used from the command line.

Is it correct that reading preferences produced by PreferencesFX requires the fx toolkit to be initialized?

In order to read them I came up with

    public static void main(String[] args) {
        new JFXPanel();
        Platform.runLater(() -> {
            Preferences p = new Preferences();
            System.out.println(p.fontSize);
            System.out.println(p.brightness);
            System.out.println(p.isNightMode());
            Platform.exit();
        });
    }

The preferences class here is https://github.com/dlsc-software-consulting-gmbh/WorkbenchFX/blob/master/workbenchfx-demo/src/main/java/com/dlsc/workbenchfx/modules/preferences/Preferences.java

Is this the best way for me to do this?

NPE in SimpleRadioButtonControl

SimpleRadioButtonControl in not working because the order in initializeParts() is wrong the correct Code would be

`
public void initializeParts() {
super.initializeParts();

    node = new HBox();
    node.getStyleClass().add("simple-radio-control");

    toggleGroup = new ToggleGroup();

    createRadioButtons();
}

`
The assignment to fieldLabel is removed, because this field is useless.

Using of Enums as Field Values not possible

The using of enums as Values for Settings and Setting values and Setting selections is not possible, because the StorageHandler converts all stored values to Object and not to the type of the Setting value.

Example:

Create Setting:

    private ObjectProperty<MyEnum> myEnumSettingValue = new SimpleObjectProperty<>(MyEnum.FIRST);
    private SingleSelectionField<MyEnum> myEnumControl = Field.ofSingleSelectionType(Arrays.asList(MyEnum.values()), 0).render(new RadioButtonControl<>());

Create Preference:

        preferencesFx = PreferencesFx.of(MyApplication.class,
                Category.of("Category",
                        Group.of("Group",
                                Setting.of("My Enum", myEnumControl , myEnumSettingValue)
                        )
                )
        );

Reading of value of myEnumSettingValuewith

MyEnum myEnum = myEnumSettingValue.get()

after creation of PreferencesFx results in a ClassCastException because there is no MyEnum in myEnumValue,. but a String with value "FIRST".

The reason is that StorageHandler reads in loadObject (line 176) into Object and not into a MyEnum:

  public Object loadObject(String breadcrumb, Object defaultObject) {
    String serializedDefault = gson.toJson(defaultObject);
    String json = preferences.get(hash(breadcrumb), serializedDefault);
    return gson.fromJson(json, Object.class);
  }

The generic T at ObjectProperty will be infered to Object at runtime, so there is no Exception if the method setValue(T value) is called with a String.

My Workaround is to use an own implementation of SimpleObjectProperty that creates the correct enum value from the given string. I can't use here a more specific generic, because it would be result in ClassCastException too, when setValue() will be called.

public class SettingEnumObjectProperty<T> extends SimpleObjectProperty<T>
{
    private static final Object DEFAULT_BEAN = null;
    private static final String DEFAULT_NAME = "";

    private Class enumClass;

    /**
     * The constructor of {@code SettingEnumObjectProperty}
     *
     * @param initialValue
     *            the initial value of the wrapped value
     */
    public SettingEnumObjectProperty(T initialValue, Class<T> enumClass) {
        super(DEFAULT_BEAN, DEFAULT_NAME, initialValue);
        this.enumClass = enumClass;
    }

    /**
     * It's a little bit tricky because to runtime T will be infered to Object, so that passing a String is correct.
     * Here the false T will be converted to a correct enum value.
     */
    public void setValue(T value) {
        Object rawValue = value;
        if (rawValue instanceof String)
        {
            set((T)Enum.valueOf(enumClass, (String)rawValue));
        }
    }
}

Load settings easily

Hi,

I’m using PrefrerencesFX for the first time and I just wanted to load the setting on start up. Is it possible? How? I have pretty much the same questions than tobiasdiez.

Thanks

Pep

Missing license hint in ReadMe and files from project.

Missing license hint in ReadMe and files from project.

a) When I read the ReadMe I see some badges from 'img.shield.io'. The badge for the license is there missing :) .
b) No resource, either java file have an license hint. I see that the files in the package com.dlsc.preferencesfx.formsfx.view.renderer have a license hint for the apache 2.0.

I can prepare a PR if you are interested?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.