fn-fx / fn-fx

A Functional API around JavaFX / OpenJFX.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Trouble editing TabPane.selectionModel.selectedIndex / Nested Modify

DavidYKay opened this issue · comments

Overview

Hey Tim!

Great library. Thanks a million for providing it.

Here's a question for you and the community:

I'm having an issue adding a listener to TabPane.selectionModelProperty.selectedIndexProperty.

I've never had to go two layers deep in fn-fx before, so I may be missing something fairly obvious.

Details

Here's what I'm attempting to do in Java:

tabPane.getSelectionModel().selectedIndexProperty().addListener(new ChangeListener<Number>() {
    @Override
    public void changed(ObservableValue<? extends Number> ov, Number oldValue, Number newValue) {
        // do something...
    }
});

1 - Dream Client Code

Here's my dream client code in Clojure with fn-fx:

(ui/tab-pane
 :selection-model {:selected-index/listener {:event :tab-changed}}
 :tabs tabs))

Error Running Dream Client Code

The error I encountered when writing the above code:

Can't convert {:selected-index/listener {:event :tab-changed}} of type class clojure.lang.PersistentArrayMap to class javafx.scene.control.SingleSelectionModel

^ Seems that my attempt at a nested modification [:selection-model :selected-index/listener] failed.

2 - Failure to Instantiate SingleSelectionModel

I attempted to instantiate a SingleSelectionModel, but it looks like this violates JavaFX's instantiation policy:

(ui/tab-pane
 :selection-model (SingleSelectionModel.)
 :tabs tabs))

Recap

I suspect that there may be something simple for doing a nested modify.

Is there a good workaround or perhaps an insight that I am missing? Many thanks!

Ah! I see now that SingleSelectionModel is an abstract class, not a class. I'll override it and make my own implementation.

Will update once I've tried this.

OK, it seems that TabPane is dependent on TabPaneSelectionModel internally. My approach of passing in a new SingleSelectionModel is flawed and will not work.

Now looking at other avenues.

Hi @DavidYKay , did you get this to work?

I have the same problem with TreeView, and badly need at least a workaround. This is how it works in Java:

 treeView.getSelectionModel().selectedItemProperty().addListener( new ChangeListener() {

        @Override
        public void changed(ObservableValue observable, Object oldValue,
                Object newValue) {

            TreeItem<String> selectedItem = (TreeItem<String>) newValue;
            System.out.println("Selected Text : " + selectedItem.getValue());
            // do what ever you want 
        }

      });

I implemented a change which will allow to access nested properties via the dot notation. It looks like this:

(ui/tab-pane
    :id :my-tabpane
    :listen/selection-model.selected-item 
        {:event         :tab-selected
         :fn-fx/include {:my-tabpane [:selection-model.selected-item.text]}}
)

An example here: https://github.com/fn-fx/fn-fx/blob/nested_properties/examples/other_examples/tabpane.clj

@DavidYKay the "Dream Code" you mention actually looks better, I'm just not sure if it's compatible with the current API. I also intend to have a look at Om's query syntax (https://github.com/omcljs/om/wiki#om-next), maybe the ideas there can be applied here. As such, the changes are not yet merged into master.