netopyr / reduxfx Goto Github PK
View Code? Open in Web Editor NEWFunctional Reactive Programming (FRP) for JavaFX
License: Apache License 2.0
Functional Reactive Programming (FRP) for JavaFX
License: Apache License 2.0
Write small introduction that explains the idea behind ReduxFX in one minute
I believe VChangeListener and VInvalidationListener can be replaced with BiFunction and Supplier.
Gradle/Ivy seems to want a redux-all
artifact that doesn't exist:
FAILURE: Build failed with an exception.
* What went wrong:
Could not resolve all dependencies for configuration ':compileClasspath'.
> Could not resolve com.netopyr.reduxfx:reduxfx:0.3.0.
Required by:
project :
> Could not resolve com.netopyr.reduxfx:reduxfx:0.3.0.
> Could not parse POM https://jcenter.bintray.com/com/netopyr/reduxfx/reduxfx/0.3.0/reduxfx-0.3.0.pom
> Could not find com.netopyr.reduxfx:reduxfx-all:0.3.0.
Searched in the following locations:
https://jcenter.bintray.com/com/netopyr/reduxfx/reduxfx-all/0.3.0/reduxfx-all-0.3.0.pom
https://jcenter.bintray.com/com/netopyr/reduxfx/reduxfx-all/0.3.0/reduxfx-all-0.3.0.jar
Currently only Nodes defined in the children property of the parent Node are diff-ed and patched. But there are other properties, that should be treated similar (e.g. top, center etc. in BorderPane).
To make sure the split between store- and view-library really works, there needs to be an example with another store, e.g. an implementation of jvm-redux-api.
Currently the items in a ListViewBuilder can only be Objects. Would be nice if one can specify the class and use that information for the properties "items" and "cellFactory"
Hi,
I'm having problems understanding the API of the middleware in reduxfx.
In the original redux API a middleware "is a higher-order function that composes a dispatch function to return a new dispatch function." redux docs.
Additionally the constructor of a middleware has also access to the getState
function.
Also see the detailed API description of applyMiddleware.
In reduxfx on the other hand the middleware operates with the Reducer/Updater function. It takes a reducer as argument and returns an enhanced reducer.
If I like to implement, for example, a thunk-middleware, I need access to the getState method because Thunk-Actions have to be able to decide which async actions to dispatch based on the current state. As far as I can see this isn't possible with the current reduxfx middleware API?
In my opinion it would be a good idea to stay as close to the original redux API as possible. But maybe I've overlooked something? Can you describe your ideas and your reasoning behind the current API?
At the moment I'm playing around with the reduxfx code to get this working but it takes some time because I'm not familiar with the reactivex API (yet).
Implement an example with ReduxFX based on @lestard's https://github.com/lestard/redux-javafx-example
Menus in JavaFX work very different than other UI elements. First and foremost menu-elements are not derived from Node. Nevertheless they have to be supported by ReduxFX.
Some properties have to be set in a specific order (e.g. properties defining an FXDialog have to be set before it is made visible). Currently properties are set in the order they appear in the view-definition. But it should not matter in which order the properties appear.
A solution could be to define different phases and each property has to specify in which phase it needs to be set.
To be able to submit the example to todomvcfx, the framework has to be publicly available.
Being able to partition your application in independent components is key to UI development. Need to figure out how this could be achieved with ReduxFX.
Currently the diff- and patch-algorithms can only work with a parent Node. This forces us to create a Parent-Node which would otherwise not be necessary. Would be nice, if we could get rid of it.
Hello @netopyr ,
thanks for creating reduxfx, it looks really nice. @lestard told me yesterday about it...
I just looked into the documentation. Isn't the ActionType redundant to the action class? Since an action could carry some data, an updater implementation would anyway need to cast the action to the specific action class to access the "action data". Therefor an updater implementation could implement "the switch" using instanceof (with if/else if/else... or of course some fancy javaslang pattern matching) without using the ActionType.
Would do you think?
Best regards,
Peti
Hi Michael,
at javaland we have already discussed about how we could add FXML support to ReduxFX. I've worked on a prototype that is inspired by the angular implementation of Redux.
I've tried to get this working with your existing ReduxFX codebase but I had a hard time to get it working so instead I created the prototype in a separate repository: https://github.com/lestard/redux-javafx-example.
I hope that we can integrate this into your ReduxFX project at some point.
In my prototype I've created a simple Redux implementation that is completely separated from any JavaFX specific code: https://github.com/lestard/redux-javafx-example/blob/master/src/main/java/redux/ReduxStore.java
It takes the initial state and a reducer. Like with the original redux you have a dispatch method that is used to dispatch actions and you can add subscribers that are invoked when the store is updated.
In the example I was creating the Views with standard JavaFX classes and FXML. My "Controller"-classes that are backing the FXML files implement an interface View which provides 2 features:
dispatch
method that can be used to dispatch new actionsselect
methods. This is what I've taken from Angular-Redux.The select
method takes a "Selector" (a Function that takes the State as argument and returns a specific slice or value from this state) and returns an ObservableValue
or an ObservableList
.
Everytime the store gets updated these observables will get the new values provided by the selector.
This way you can bind your JavaFX Controls to the state of the Redux store.
This can look like this:
public class ControlsView implements View {
@FXML
public Label itemsLeftLabel;
public void initialize(){
itemsLeftLabel.textProperty().bind(
Bindings.concat(select(Selectors.numberOfItemsLeft), " items left"));
}
public void all() {
dispatch(Actions.setFilter(Filter.ALL));
}
public void active() {
dispatch(Actions.setFilter(Filter.ACTIVE));
}
public void completed() {
dispatch(Actions.setFilter(Filter.COMPLETED));
}
}
It means that all UI components are stateful. I know that this is not as clean and elegant as your VNode approach but this way we can use FXML.
As you've already mentioned at javaland the handling of ListViews is problematic. I've had this problem already for FluxFX and I've copied the solution from there. It's solved with a special CellFactory that updates items when the underlying data has changed. This is also not a really clean solution but at least it works ;-) Maybe we can find a better approach. As I've said, it's all just a prototype.
I hope you find the time to take a look at the prototype.
Maybe we could change the API of ReduxFX so that it's not coupled to your VNode approach only.
At the moment we have this code to startup ReduxFX:
ReduxFX.start(initialState, Todos::update, MainView::view, primaryStage);
In my example I've come up with this API:
ReduxStore<AppModel> store = ReduxStore.create(initialState, Updater::update);
ReduxJavaFX.connect(store);
This separates the Redux Store and the UI part. This is similar to redux and react-redux.
Maybe we could do the same for the Java(FX) library: A Core Redux library and a separate module with your VSceneGraph and another module with the FXML approach?
While developing I've got the need for debugging and implemented a Logging-Middleware, inspired by the middleware concept of the original Redux implementation. Maybe this sort of extension mechanism could be added to ReduxFX too.
kind regards,
Manuel
Hello,
I'm trying to implement an example with ReduxFX but I have a problem that is keeping me from using this project.
Here's an example:
@Override
public void start(Stage mainStage) throws Exception {
final AppState initialState = AppState.create();
ReduxFX.start(
initialState,
IncrementReducer::update,
HomeView::view,
mainStage);
}
public class HomeView {
public static VNode view(AppState state) {
Objects.requireNonNull(state, "The parameter 'state' must not be null");
return Stage().....;
}
}
public class IncrementReducer {
public static AppState update(AppState state, Object action) {
Objects.requireNonNull(state, "The parameter 'state' must not be null");
Objects.requireNonNull(action, "The parameter 'action' must not be null");
// This is part of Javaslang's pattern-matching API. It works similar to the regular switch-case
// in Java, except that it is much more flexible and returns a value.
// We check which of the cases is true and in that branch we specify the newState.
return Match(action).of(
// If the action is a IncCounterAction, we return a new AppState with an increased counter
Case(instanceOf(IncrementReducer.class),
incCounterAction -> state.withCounter(state.getCounter() + 1)
),
// This is the default branch of this switch-case. If an unknown Action was passed to the
// updater, we simply return the old state. This is a convention, that is not needed right
// now, but will help once you start to decompose your updater.
Case($(), state)
);
}
}
The Intellij hint gives me this alert Cannot resolve method 'start(com.renanliberato.app.state.AppState, <method reference>, <method reference>, javafx.stage.Stage)'
and if I try to run it, it gives me this error:
Error:(28, 16) java: no suitable method found for start(com.renanliberato.app.state.AppState,IncrementR[...]pdate,HomeView::view,javafx.stage.Stage)
method com.netopyr.reduxfx.ReduxFX.<STATE>start(STATE,java.util.function.BiFunction<STATE,java.lang.Object,com.netopyr.reduxfx.updater.Update<STATE>>,java.util.function.Function<STATE,com.netopyr.reduxfx.vscenegraph.VNode>,javafx.stage.Stage) is not applicable
(cannot infer type-variable(s) STATE
(argument mismatch; bad return type in method reference
com.renanliberato.app.state.AppState cannot be converted to com.netopyr.reduxfx.updater.Update<STATE>))
method com.netopyr.reduxfx.ReduxFX.<STATE>start(STATE,java.util.function.BiFunction<STATE,java.lang.Object,com.netopyr.reduxfx.updater.Update<STATE>>,java.util.function.Function<STATE,com.netopyr.reduxfx.vscenegraph.VNode>,javafx.scene.Group) is not applicable
(cannot infer type-variable(s) STATE
(argument mismatch; bad return type in method reference
com.renanliberato.app.state.AppState cannot be converted to com.netopyr.reduxfx.updater.Update<STATE>))
method com.netopyr.reduxfx.ReduxFX.<STATE>start(STATE,java.util.function.BiFunction<STATE,java.lang.Object,com.netopyr.reduxfx.updater.Update<STATE>>,java.util.function.Function<STATE,com.netopyr.reduxfx.vscenegraph.VNode>,javafx.scene.layout.Pane) is not applicable
(cannot infer type-variable(s) STATE
(argument mismatch; bad return type in method reference
com.renanliberato.app.state.AppState cannot be converted to com.netopyr.reduxfx.updater.Update<STATE>))
In my pom.xml
file I've imported this dependency, as included in the README.md:
<dependency>
<groupId>com.netopyr.reduxfx</groupId>
<artifactId>reduxfx</artifactId>
<version>0.3.1</version>
</dependency>
I'd appreciate to know if this is some misunderstanding that I've made with Bifunction or anything else, because this may be an example of problems someone who didn't know this project may run when trying to implement it.
Will it help if I submit a gist with a more complete code example?
Add support to load properties from a local file
Have you ever tried it out?
If you pull a slider it goes wild on RAM and CPU usage.
At the moment the VNode ListView doesn't support selection of items (at least I haven't seen the possibility to do so).
This includes 2 aspects: I like to be able to define which items are selected based on the state and I like to dispatch an action when the user selects an item.
I've tried to add this functionality and to provide a PullRequest but I haven't understood how to add this with the existing builders. I think the reason is that the selection is not just a property on the ListView but instead in normal JavaFX you have to use the SelectionModel
from the ListView.
If you can give me some hints on how this should be implemented I'm happy to provide a PullRequest.
The example application has to pass all tests that are part of the todomvcFX project (https://github.com/lestard/todomvcFX) to ensure it is fully compatible.
The README.md
could have a reference to the Maven artifacts. The shields badge automatically refers to the current version. I've also added snippets of other common ways to refer to the artifacts, which require to manually update the version string on every release.
As shields badge:
[![Maven](https://img.shields.io/maven-central/v/com.netopyr.reduxfx/reduxfx.svg?label=com.netopyr.reduxfx)](https://search.maven.org/#search|ga|1|com.netopyr.reduxfx)
As maven coordinates table:
| Group ID | Artifact ID | Version |
| :-----------------: | :---------: | :-----: |
| com.netopyr.reduxfx | reduxfx | 0.1.0 |
Group ID | Artifact ID | Version |
---|---|---|
com.netopyr.reduxfx | reduxfx | 0.1.0 |
For maven pom xml:
<dependencies>
<dependency>
<groupId>com.netopyr.reduxfx</groupId>
<artifactId>reduxfx</artifactId>
<version>0.1.0</version>
</dependency>
</dependencies>
For gradle build file:
dependencies {
compile "com.netopyr.reduxfx:reduxfx:0.1.0"
}
As maven repository index url:
Write a few paragraphs that explain the basic concepts in about 5 minutes.
So far ReduxFX supports only single nodes with a name (e.g. BorderPane.center, Labeled.graphic). If there was a list of child-nodes, it was always assumed to be stored in the children-property. But as is turns out, some classes store the list of their children with a different name (e.g. Accordion.panes). ReduxFX has to support these properties, too.
Try to implement an API, where only properties that are available for a specific class are allowed.
To be able to write builders for custom nodes, too, one has to be able to define custom properties for single nodes and node-lists (e.g. BorderPane.center, Accordion.panes). Therefore there has to be a public API to define such properties.
One should be able to register drivers in ReduxFX. ComponentDriver has to be adapted.
Setup build system to deploy reduxfx, reduxfx-jfoenix, reduxfx-fontawesomefx in one go
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.