Search code examples
javajavafxdrombler-fx

How to pass information from one view (dockable) to another?


I am facing a design problem. If I have (for example) on the left dockable view a list view that contains some pojo's, how do I notify the center dockable which one is selected? I am trying to implement some kind of Master-Detail-View where the user selects one item and then can configure it in the center area and the right area. Thanks in advance :)


Solution

  • It depends on how you want to design your application.

    If you want to create a separate Editor for each pojo then you can have a look at the LeftTestPane provided by the drombler fx archetype for a sample.

    @FXML
    private void onNewSampleAction(ActionEvent event) {
        sampleCounter++;
        Sample sample = new Sample("Sample " + sampleCounter);
        SampleEditorPane sampleEditorPane = new SampleEditorPane(sample);
        Dockables.inject(sampleEditorPane);
        Dockables.open(sampleEditorPane);
    }
    

    There is currently no API for selecting an already opened editor, but please note that editors are currently being improved with the work done for issue #111.

    If you want a single detail view then you can use the Context Framework, which allows components such as Dockables and Actions to communicate in a loosly coupled way.

    The ListView should implement LocalContextProvider and keep the selected pojo in its local Context.

    @ViewDocking(...)
    public class ListView extends SomeNode implements LocalContextProvider {
    
        private final SimpleContextContent contextContent = new SimpleContextContent();
        private final SimpleContext context = new SimpleContext(contextContent);
        private MyPojo currentSelection;
    
        ...
    
        @Override
        public Context getLocalContext() {
            return context;
        }
    
        ...
    
        if (currentSelection != null){
            contextContent.remove(currentSelection);
        }
        currentSelection = <current selection>
        if (currentSelection != null){
            contextContent.add(currentSelection);
        }
        ...
    }
    

    In this case, the DetailsView should be registered as a view (singleton), too, and implement LocalContextProvider as well as ActiveContextSensitive:

    @ViewDocking(...)
    public class DetailsPane extends SomeNode implements ActiveContextSensitive, LocalContextProvider {
    
        private final SimpleContextContent contextContent = new SimpleContextContent();
        private final SimpleContext context = new SimpleContext(contextContent);
        private Context activeContext;
        private MyPojo myPojo;
    
        ...
    
        @Override
        public Context getLocalContext() {
            return context;
        }
    
        @Override
        public void setActiveContext(Context activeContext) {
            this.activeContext = activeContext;
            this.activeContext.addContextListener(MyPojo.class, (ContextEvent event) -> contextChanged());
            contextChanged();
        }
    
        private void contextChanged() {
            MyPojo newMyPojo = activeContext.find(MyPojo.class);
            if ((myPojo == null && newMyPojo != null) || (myPojo null && !sample.equals(newMyPojo))) {
                if (myPojo != null) {
                    unregister();
                }
                myPojo = newMyPojo;
                if (myPojo != null) {
                    register();
                }
            }
        }
    
        private void unregister() {
            contextContent.remove(myPojo);
    
            //reset DetailsView
        }
    
        private void register() {
            // configure DetailsView
    
            contextContent.add(myPojo);
        }
    ...
    }
    

    Have a look at the RightTestPane provided by the drombler fx archetype for a sample.