PreferencesFX
PreferencesFX copied to clipboard
Locale setting type
Inspired by the Color setting I started working on a java.util.Locale setting. It kind of works but I have two problems.
-
The setting stored is the setting displayed (in the SimpleComboBoxControl) In order for this setting to survive a language change and be human readable I must store the locale.toLanguageTag() and display locale.getDisplayLanguage().
-
Having about 160 locales, SimpleComboBoxControl.comboBox.setVisibleRowCount(4) is somewhat limited.
Any pointers on how to improve this?
If it matters, I use the locale setting on String.format and SimpleDateFormat, not the UI itself.
First off, cool, I'm pretty sure that would make a great addition to PreferencesFX!
-
If I understood your issue correctly, you could use the
Locale
objects as items directly for theCombobox
and then by calling something likesetCellValueFactory( locale -> locale.getDisplayLanguage() )
on the combo box control directly you can customize it to show the locale in the way you want it to be. You can then store theLocale
object itself, from which you can gettoLanguageTag()
if you need to. If there was a misunderstanding please tell me! -
You could just override this with a different row count in your control.
I assume you already did it in this way, but in your case I would create a new class, extending the SimpleComboboxControl and then you can apply the changes you need on top of that for your Locale control.
I avoided extending SimpleComboboxControl, but I'll do just that.
@trixon did it work?
@martinfrancois I have not got around to it yet, it's on the list though.
@martinfrancois Ok, this is what I have so far, and it looks likes it's working.
/**
* Creates a custom locale control.
*
* @param description the title of this setting
* @param localeProperty the current selected locale value
* @param locales the selectable locales, all if null or empty
* @return the constructed setting
*/
public static Setting of(String description, ObjectProperty<Locale> localeProperty, ObservableList<Locale> locales) {
StringProperty stringProperty = new SimpleStringProperty();
stringProperty.bindBidirectional(localeProperty, new StringConverter<Locale>() {
@Override
public String toString(Locale locale) {
return Objects.isNull(locale) ? Locale.getDefault().toLanguageTag() : locale.toLanguageTag();
}
@Override
public Locale fromString(String value) {
return Objects.isNull(value) ? Locale.getDefault() : Locale.forLanguageTag(value);
}
});
if (Objects.isNull(locales) || locales.isEmpty()) {
locales = Arrays.stream(Locale.getAvailableLocales())
.sorted((Locale o1, Locale o2) -> o1.getDisplayName().compareTo(o2.getDisplayName()))
.collect(Collectors.collectingAndThen(Collectors.toList(), l -> FXCollections.observableArrayList(l)));
locales.remove(0);
}
SimpleListProperty<Locale> localesProperty = new SimpleListProperty<>(locales);
return new Setting<>(
description,
Field.ofSingleSelectionType(localesProperty, localeProperty)
.label(description)
.render(new SimpleLocaleComboBoxControl()),
stringProperty);
}
public class SimpleLocaleComboBoxControl extends SimpleComboBoxControl {
public SimpleLocaleComboBoxControl() {
}
@Override
public void layoutParts() {
super.layoutParts();
try {
java.lang.reflect.Field comboBoxField = getClass().getSuperclass().getDeclaredField("comboBox");
comboBoxField.setAccessible(true);
ComboBox<Locale> comboBox = (ComboBox) comboBoxField.get(this);
comboBox.setVisibleRowCount(16);
comboBox.setConverter(new StringConverter<Locale>() {
@Override
public Locale fromString(String string) {
return null;
}
@Override
public String toString(Locale locale) {
return locale.getDisplayName();
}
});
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) {
Logger.getLogger(SimpleLocaleComboBoxControl.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
A couple of things...
- I'm not that happy about the reflection part, it was just a way forward. Could we add a getter for the combobox or make it default/protected?
- I had to came up with a unique method signature since the color setting already "claims" of(String description, ObjectProperty<> property), which after all wasn't that bad, limiting the locales can be useful. But for the future there might be good to have convention supporting multiple ObjectProperty settings.
- I have no idea how to get my code, if accepted, into the repository. For one thing, I have already messed up the code formatting...
- I have not used this feature much yet.