Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Issues-2-4] Keyboard support and Javadocs #22

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 100 additions & 45 deletions phonenumberfx/src/main/java/com/dlsc/phonenumberfx/PhoneNumberField.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ public class PhoneNumberField extends CustomTextField {
}

private static final Comparator<Country> NAME_SORT_ASC = (c1, c2) -> {
String c1Name = new Locale("en", c1.iso2Code()).getDisplayCountry();
String c2Name = new Locale("en", c2.iso2Code()).getDisplayCountry();
String c1Name = c1.countryName();
String c2Name = c2.countryName();
return c1Name.compareTo(c2Name);
};

Expand Down Expand Up @@ -110,8 +110,8 @@ protected void layoutChildren(double x, double y, double w, double h) {

// use same bounds for globe that were computed for the button cell
this.globeButton.resizeRelocate(bounds.getMinX(), bounds.getMinY(), bounds.getWidth(), bounds.getHeight());
this.globeButton.setVisible(getValue() == null);
this.globeButton.setManaged(getValue() == null);
this.globeButton.setVisible(getSkinnable().getValue() == null);
this.globeButton.setManaged(getSkinnable().getValue() == null);
this.globeButton.toFront();
}
};
Expand All @@ -133,6 +133,30 @@ protected void layoutChildren(double x, double y, double w, double h) {

setLeft(comboBox);

addEventFilter(KeyEvent.KEY_PRESSED, evt -> {
if (evt.getCode().isLetterKey()) {
String letter = evt.getCode().getChar();

ComboBoxListViewSkin<Country> comboBoxSkin = (ComboBoxListViewSkin<Country>) comboBox.getSkin();
ListView<Country> listView = (ListView<Country>) comboBoxSkin.getPopupContent();

Country country = countries
.stream()
.filter(c -> c.countryName().startsWith(letter))
.findFirst()
.orElse(null);

if (country != null) {
if (!comboBox.isShowing()) {
comboBox.show();
}

listView.requestFocus();
listView.scrollTo(country);
}
}
});

phoneNumberUtil = PhoneNumberUtil.getInstance();
resolver = new CountryResolver();
formatter = new PhoneNumberFormatter();
Expand Down Expand Up @@ -298,41 +322,10 @@ public void set(String newRawPhoneNumber) {
}
};

private final BooleanProperty showCountryDropdown = new SimpleBooleanProperty(this, "showCountryDropdown", true);

public final boolean isShowCountryDropdown() {
return showCountryDropdown.get();
}

/**
* Returns the property indicating whether the country dropdown is visible or not.
*
* @return the showCountryDropdown property
*/
public final BooleanProperty showCountryDropdownProperty() {
return showCountryDropdown;
}

public final void setShowCountryDropdown(boolean showCountryDropdown) {
this.showCountryDropdown.set(showCountryDropdown);
}

private final BooleanProperty showExampleNumbers = new SimpleBooleanProperty(this, "showExampleNumbers", true);

public final boolean isShowExampleNumbers() {
return showExampleNumbers.get();
}

public final BooleanProperty showExampleNumbersProperty() {
return showExampleNumbers;
}

public final void setShowExampleNumbers(boolean showExampleNumbers) {
this.showExampleNumbers.set(showExampleNumbers);
}
// RAW PHONE NUMBER

/**
* The raw phone number corresponding exactly to what the user typed in, including the (+) sign appended at the
* @return The raw phone number corresponding exactly to what the user typed in, including the (+) sign appended at the
* beginning. This value can be a valid E164 formatted number.
*/
public final StringProperty rawPhoneNumberProperty() {
Expand All @@ -347,6 +340,8 @@ public final void setRawPhoneNumber(String rawPhoneNumber) {
rawPhoneNumberProperty().set(rawPhoneNumber);
}

// SELECTED COUNTRY

private final ObjectProperty<Country> selectedCountry = new SimpleObjectProperty<>(this, "selectedCountry") {
private boolean selfUpdate;

Expand All @@ -371,7 +366,7 @@ public void set(Country newCountry) {
};

/**
* The selected country. Use this property if you want to define a default (pre-selected) country.
* @return The selected country. Use this property if you want to define a default (pre-selected) country.
* It can also be used in conjunction with {@link #disableCountryDropdownProperty()} to avoid
* changing the country part.
*/
Expand All @@ -391,6 +386,9 @@ public final void setSelectedCountry(Country selectedCountry) {

private final ReadOnlyStringWrapper nationalPhoneNumber = new ReadOnlyStringWrapper(this, "nationalPhoneNumber");

/**
* @return The {@link #phoneNumberProperty() phone number} formatted as a national number without the country code.
*/
public final ReadOnlyStringProperty nationalPhoneNumberProperty() {
return nationalPhoneNumber.getReadOnlyProperty();
}
Expand All @@ -407,6 +405,9 @@ private void setNationalPhoneNumber(String nationalPhoneNumber) {

private final ReadOnlyStringWrapper e164PhoneNumber = new ReadOnlyStringWrapper(this, "e164PhoneNumber");

/**
* @return The {@link #phoneNumberProperty() phone number} formatted as E164 standard format including the country code and national number.
*/
public final ReadOnlyStringProperty e164PhoneNumberProperty() {
return e164PhoneNumber.getReadOnlyProperty();
}
Expand All @@ -423,6 +424,10 @@ private void setE164PhoneNumber(String e164PhoneNumber) {

private final ReadOnlyObjectWrapper<Phonenumber.PhoneNumber> phoneNumber = new ReadOnlyObjectWrapper<>(this, "phoneNumber");

/**
* @return The phone number parsed out from the {@link #rawPhoneNumberProperty() raw phone number}, this might be {@code null} if the
* phone number is not a valid one.
*/
public final ReadOnlyObjectProperty<Phonenumber.PhoneNumber> phoneNumberProperty() {
return phoneNumber.getReadOnlyProperty();
}
Expand All @@ -440,7 +445,7 @@ private void setPhoneNumber(Phonenumber.PhoneNumber phoneNumber) {
private final ListProperty<Country> availableCountries = new SimpleListProperty<>(FXCollections.observableArrayList());

/**
* The list of available countries from which the user can select one and put it into the
* @return The list of available countries from which the user can select one and put it into the
* {@link #selectedCountryProperty()}.
*/
public final ListProperty<Country> availableCountriesProperty() {
Expand All @@ -460,7 +465,7 @@ public final void setAvailableCountries(ObservableList<Country> availableCountri
private final ListProperty<Country> preferredCountries = new SimpleListProperty<>(FXCollections.observableArrayList());

/**
* The list of preferred countries that are shown first in the list of available countries. If a country
* @return The list of preferred countries that are shown first in the list of available countries. If a country
* is added to this list that is not present in the {@link #getAvailableCountries()} then it will be ignored
* and not shown.
*/
Expand All @@ -481,7 +486,7 @@ public final void setPreferredCountries(ObservableList<Country> preferredCountri
private final BooleanProperty disableCountryDropdown = new SimpleBooleanProperty(this, "disableCountryDropdown");

/**
* Flag to disable the country dropdown. This will allow to specify a default country and avoid changing it
* @return Flag to disable the country dropdown. This will allow to specify a default country and avoid changing it
* in case it is wanted to be fixed.
*/
public final BooleanProperty disableCountryDropdownProperty() {
Expand All @@ -501,7 +506,7 @@ public final void setDisableCountryDropdown(boolean disableCountryDropdown) {
private final ObjectProperty<Callback<ListView<Country>, ListCell<Country>>> countryCellFactory = new SimpleObjectProperty<>(this, "countryCellFactory", listView -> new CountryCell());

/**
* Factory that allows to replace the list cells used to graphically represent each country.
* @return Factory that allows to replace the list cells used to graphically represent each country.
*/
public final ObjectProperty<Callback<ListView<Country>, ListCell<Country>>> countryCellFactoryProperty() {
return countryCellFactory;
Expand All @@ -520,7 +525,7 @@ public final void setCountryCellFactory(Callback<ListView<Country>, ListCell<Cou
private final ReadOnlyBooleanWrapper valid = new ReadOnlyBooleanWrapper(this, "valid");

/**
* Read-only property that indicates whether the phone number is valid or not.
* @return Read-only property that indicates whether the phone number is valid or not.
*/
public final ReadOnlyBooleanProperty validProperty() {
return valid.getReadOnlyProperty();
Expand Down Expand Up @@ -565,7 +570,7 @@ private boolean isExpectedTypeMatch(Phonenumber.PhoneNumber number) {
private final BooleanProperty countryCodeVisible = new SimpleBooleanProperty(this, "countryCodeVisible");

/**
* Determines if the country code stays visible in the field or if it gets removed as soon as
* @return Determines if the country code stays visible in the field or if it gets removed as soon as
* the field has determined which country it is.
*/
public final BooleanProperty countryCodeVisibleProperty() {
Expand All @@ -580,6 +585,44 @@ public final void setCountryCodeVisible(boolean countryCodeVisible) {
countryCodeVisibleProperty().set(countryCodeVisible);
}

// SHOW COUNTRY DROPDOWN

private final BooleanProperty showCountryDropdown = new SimpleBooleanProperty(this, "showCountryDropdown", true);

/**
* @return The property indicating whether the country dropdown is visible or not.
*/
public final BooleanProperty showCountryDropdownProperty() {
return showCountryDropdown;
}

public final boolean isShowCountryDropdown() {
return showCountryDropdown.get();
}

public final void setShowCountryDropdown(boolean showCountryDropdown) {
this.showCountryDropdown.set(showCountryDropdown);
}

// SHOW EXAMPLE NUMBERS

private final BooleanProperty showExampleNumbers = new SimpleBooleanProperty(this, "showExampleNumbers", true);

/**
* @return The property that allows to show/hide prompt text with phone number examples after selecting the country.
*/
public final BooleanProperty showExampleNumbersProperty() {
return showExampleNumbers;
}

public final boolean isShowExampleNumbers() {
return showExampleNumbers.get();
}

public final void setShowExampleNumbers(boolean showExampleNumbers) {
this.showExampleNumbers.set(showExampleNumbers);
}

/**
* All countries supported by the control.
*/
Expand Down Expand Up @@ -859,6 +902,9 @@ public String iso2Code() {
return iso2Code;
}

/**
* @return The phone number prefix including only the country code with (+) sign.
*/
public String countryCodePrefix() {
return "+" + countryCode();
}
Expand All @@ -872,9 +918,18 @@ public Integer defaultAreaCode() {
return areaCodes().length > 0 ? areaCodes()[0] : null;
}

/**
* The phone number prefix including the country and default area code if any.
* @return The phone number prefix.
*/
public String phonePrefix() {
return countryCodePrefix() + Optional.ofNullable(defaultAreaCode()).map(Object::toString).orElse("");
}

private String countryName() {
return new Locale("en", iso2Code).getDisplayCountry();
}

}

/**
Expand Down Expand Up @@ -1102,7 +1157,7 @@ protected void updateItem(Country country, boolean empty) {
int index = -1;

if (country != null && !empty) {
setText(new Locale("en", country.iso2Code()).getDisplayCountry());
setText(country.countryName());
setGraphic(getCountryGraphic(country));
index = getPreferredCountries().indexOf(country);
} else {
Expand Down
Loading