PreferencesFX icon indicating copy to clipboard operation
PreferencesFX copied to clipboard

Adding new categories to an existing object

Open p1r9t3 opened this issue 5 years ago • 3 comments

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.

p1r9t3 avatar Jun 06 '19 00:06 p1r9t3

This is possible by creating a new PreferencesFx object every time you show the Preferences, making sure you use the same class as the storage key, you can always pass in less or more settings / categories.

Although I admit this is not as elegant as having the possibility to add them at runtime by calling for example preferences.getCategories() along the lines of how it works with getChildren() in JavaFX.

I would welcome someone adding a PR for this functionality, however I think it involves quite a lot of work, since we currently assume everything is set before initializing. So a lot of change listeners need to be added to support every behavior of PreferencesFX.

martinfrancois avatar Jul 19 '19 08:07 martinfrancois

As a workaround for this, instead of having my modules add to the preferences object, I'm using Spring to search for all of my modules and then using a common interface, each module is required to return Category[] which is then added to the preferences object the first time it's built.

p1r9t3 avatar Jul 20 '19 06:07 p1r9t3

This is possible by creating a new PreferencesFx object every time you show the Preferences, making sure you use the same class as the storage key, you can always pass in less or more settings / categories.

Hi @martinfrancois I was happy to see this workaround but I can't get it to work. On the second call I get 'IllegalStateException: Cannot change a control's field once set.' I can reproduce this in the WorkbenchFX demo too by duplicating the line

  public Preferences() {
    preferencesFx = createPreferences();
    preferencesFx = createPreferences();
  }

https://github.com/dlsc-software-consulting-gmbh/WorkbenchFX/blob/60a7e5fef4c2c3c8fcfda9561bfac2abcc49a9b4/workbenchfx-demo/src/main/java/com/dlsc/workbenchfx/modules/preferences/Preferences.java#L75

Am I doing something wrong?

The output I get is:

Exception in thread "JavaFX Application Thread" java.lang.IllegalStateException: Cannot change a control's field once set.
	at com.dlsc.preferencesfx.formsfx.view.controls.SimpleControl.setField(SimpleControl.java:70)
	at com.dlsc.preferencesfx.formsfx.view.renderer.PreferencesFxGroupRenderer.layoutParts(PreferencesFxGroupRenderer.java:88)
	at com.dlsc.preferencesfx.formsfx.view.renderer.PreferencesFxGroupRenderer.init(PreferencesFxGroupRenderer.java:51)
	at com.dlsc.preferencesfx.formsfx.view.renderer.PreferencesFxGroupRenderer.<init>(PreferencesFxGroupRenderer.java:43)
	at com.dlsc.preferencesfx.formsfx.view.renderer.PreferencesFxFormRenderer.lambda$initializeParts$0(PreferencesFxFormRenderer.java:50)
	at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
	at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1382)
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
	at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:566)
	at com.dlsc.preferencesfx.formsfx.view.renderer.PreferencesFxFormRenderer.initializeParts(PreferencesFxFormRenderer.java:51)
	at com.dlsc.formsfx.view.util.ViewMixin.init(ViewMixin.java:45)
	at com.dlsc.preferencesfx.formsfx.view.renderer.PreferencesFxFormRenderer.<init>(PreferencesFxFormRenderer.java:36)
	at com.dlsc.preferencesfx.view.CategoryView.initializeFormRenderer(CategoryView.java:48)
	at com.dlsc.preferencesfx.view.CategoryPresenter.initializeViewParts(CategoryPresenter.java:60)
	at com.dlsc.preferencesfx.view.Presenter.init(Presenter.java:15)
	at com.dlsc.preferencesfx.view.CategoryPresenter.<init>(CategoryPresenter.java:51)
	at com.dlsc.preferencesfx.PreferencesFx.lambda$initializeCategoryViews$0(PreferencesFx.java:123)
	at java.util.ArrayList.forEach(ArrayList.java:1257)
	at com.dlsc.preferencesfx.PreferencesFx.initializeCategoryViews(PreferencesFx.java:121)
	at com.dlsc.preferencesfx.PreferencesFx.init(PreferencesFx.java:77)
	at com.dlsc.preferencesfx.PreferencesFx.<init>(PreferencesFx.java:64)
	at com.dlsc.preferencesfx.PreferencesFx.<init>(PreferencesFx.java:55)
	at com.dlsc.preferencesfx.PreferencesFx.of(PreferencesFx.java:102)
	at com.dlsc.workbenchfx.modules.preferences.Preferences.createPreferences(Preferences.java:89)
	at com.dlsc.workbenchfx.modules.preferences.Preferences.initPrefs(Preferences.java:79)
	at com.dlsc.workbenchfx.modules.preferences.PreferencesModule.activate(PreferencesModule.java:36)
	at com.dlsc.workbenchfx.Workbench.lambda$initListeners$0(Workbench.java:419)
	at com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:361)
	at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
	at javafx.beans.property.ObjectPropertyBase.fireValueChangedEvent(ObjectPropertyBase.java:105)
	at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:112)
	at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:146)
	at javafx.beans.property.ObjectProperty.setValue(ObjectProperty.java:69)
	at com.dlsc.workbenchfx.Workbench.openModule(Workbench.java:499)
	at com.dlsc.workbenchfx.view.controls.module.Tile.open(Tile.java:73)
	at com.dlsc.workbenchfx.view.controls.module.Tile.lambda$setupEventHandlers$1(Tile.java:66)
	at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
	at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
	at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
	at javafx.event.Event.fireEvent(Event.java:198)
	at javafx.scene.Scene$ClickGenerator.postProcess(Scene.java:3470)
	at javafx.scene.Scene$ClickGenerator.access$8100(Scene.java:3398)
	at javafx.scene.Scene$MouseHandler.process(Scene.java:3766)
	at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
	at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
	at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:394)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
	at java.security.AccessController.doPrivileged(Native Method)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:432)
	at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:431)
	at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
	at com.sun.glass.ui.View.notifyMouse(View.java:937)
	at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
	at com.sun.glass.ui.gtk.GtkApplication.lambda$null$10(GtkApplication.java:245)
	at java.lang.Thread.run(Thread.java:748)
30.08.2019 17:06:00.319 [JavaFX Application Thread] TRACE com.dlsc.workbenchfx.Workbench - openModule - set active module to Preferences

trixon avatar Aug 30 '19 15:08 trixon