In the part I would like to do the following:
I want to initialize a member variable with the preference value from the ConfigurationScope, if available, otherwise from the DefaultScope (the value is defined in the plugin_customization.ini) I do not use the InstanceScope because all my preference values have to survive each restart of the application. As soon as the value in the ConfigurationScope changes, I'd like a method in the part to be called, so that I can react on the change.
It seems that this scenario cannot be implemented as easy as it maybe should. If I use this method within my part:
@Inject
@Optional
public void updatePrefValue(@Preference(nodePath = PREFERENCES_NODE, value = PREFERENCE_NAME) int intPrefValue) {
this.intPrefValue = intPrefValue;
if (lblPrefValue != null && !lblPrefValue.isDisposed()) {
lblPrefValue.setText(String.valueOf(intPrefValue));
}
}
then the member variable intPrefValue gets correctly initialized (either with the value from ConfigurationScope or with the value from the DefaultScope). That is really nice, but this method gets not called again, if I change the preference value within the ConfigurationScope like this:
Button btnUpdateInConfigurationScope = new Button(parent, SWT.PUSH);
btnUpdateInConfigurationScope.setText("Update in ConfigurationScope");
btnUpdateInConfigurationScope.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
IEclipsePreferences node = ConfigurationScope.INSTANCE.getNode(PREFERENCES_NODE);
node.putInt(PREFERENCE_NAME, Integer.valueOf(txtNewPrefValue.getText()));
try {
node.flush();
} catch (BackingStoreException e1) {
e1.printStackTrace();
}
}
});
I only can get the method called again by changing the value in the InstanceScope instead:
Button btnUpdateInInstanceScope = new Button(parent, SWT.PUSH);
btnUpdateInInstanceScope.setText("Update in InstanceScope");
btnUpdateInInstanceScope.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
InstanceScope.INSTANCE.getNode(PREFERENCES_NODE).putInt(PREFERENCE_NAME, Integer.valueOf(txtNewPrefValue.getText()));
}
});
(So I could change the value always in the InstanceScope and in the ConfigurationScope, but that seems not to be the correct way to do it!?)
Following method gets always called when the preference value changes in the ConfigurationScope, because I explicitly ask for the ConfigurationScope in the nodePath.
@Inject
@Optional
public void updatePrefValue(@Preference(nodePath = "/configuration/" + PREFERENCES_NODE, value = PREFERENCE_NAME) int intPrefValue) {
this.intPrefValue = intPrefValue;
if (lblPrefValue != null && !lblPrefValue.isDisposed()) {
lblPrefValue.setText(String.valueOf(intPrefValue));
}
}
But using this method I obviously cannot initialize my member variable intPrefValue correctly, because the method gets always called with 0, even if there is a non-zero value defined in the DefaultScope. It is consistent that the value in the DefaultScope is not taken into consideration, but, as side note, do we want our methods to be called, if there is no value defined?
I have two ideas to deal with this dilemma. On the one hand, I could use two methods. One for the initialization and one for the update:
@Inject
@Optional
public void updatePrefValue(@Preference(nodePath = "/configuration/" + PREFERENCES_NODE, value = PREFERENCE_NAME) int intPrefValue) {
this.intPrefValue = intPrefValue;
if (lblPrefValue != null && !lblPrefValue.isDisposed()) {
lblPrefValue.setText(String.valueOf(intPrefValue));
}
}
@Inject
@Optional
public void initPrefValue(@Preference(nodePath = PREFERENCES_NODE, value = PREFERENCE_NAME) int intPrefValue) {
this.intPrefValue = intPrefValue;
}
But this is terrible. Not only because it is a lot of code, but also the order of the methods is relevant now. Changing the order would result in a wrong initialized intPrefValue because the initPrefValue method would not override the value set by the updatePrefValue method.
On the other hand, I could initialize the intPrefValue using the IPreferencesService
@Inject
public SamplePart(IPreferenceService prefService) {
this.intPrefValue = prefService.getInt(PREFERENCES_NODE, PREFERENCE_NAME, 0, null);
}
This might be reasonable but adds another dependency and also strikes me as a workaround.
Any ideas?
(The source code can be seen here github.com/tobbaumann/e4Sandbox/blob/master/org.tobbaumann.e4.preferencesTest/src/org/tobbaumann/e4/preferencestest/parts/SamplePart.java)
Kind regards.]]>