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

PhoneNumberField - Added factory for changing country flags #92

Merged
Show file tree
Hide file tree
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
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.Separator;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
Expand All @@ -29,7 +28,7 @@ public class PhoneNumberFieldApp extends Application {
return null;
}
PhoneNumberField.CountryCallingCode code = (PhoneNumberField.CountryCallingCode) c;
return "(+" + code.countryCode() + ") " + code.displayName("en");
return "(+" + code.countryCode() + ") " + code;
};

@Override
Expand All @@ -42,12 +41,12 @@ public void start(Stage stage) throws Exception {
addControl("Preferred Countries", preferredCountriesSelector(field), controls);
addControl("Force Local Phone", forceLocalPhoneNumberCheck(field), controls);
addControl("Fixed Country", fixedCountrySelector(field), controls);
addControl("Mask", maskInputField(field), controls);

VBox fields = new VBox(10);
addField(fields, "Country Code", field.countryCodeProperty(), COUNTRY_CODE_CONVERTER);
addField(fields, "Phone Number", field.phoneNumberProperty());
addField(fields, "Local Number", field.localPhoneNumberProperty());
addField(fields, "Mask", field.maskProperty());

VBox vBox = new VBox(20);
vBox.setPadding(new Insets(20));
Expand Down Expand Up @@ -106,12 +105,6 @@ private Node preferredCountriesSelector(PhoneNumberField view) {
return comboBox;
}

private Node maskInputField(PhoneNumberField field) {
TextField mask = new TextField();
mask.textProperty().bindBidirectional(field.maskProperty());
return mask;
}

private Node forceLocalPhoneNumberCheck(PhoneNumberField field) {
CheckBox localCheck = new CheckBox();
localCheck.selectedProperty().bindBidirectional(field.forceLocalPhoneNumberProperty());
Expand Down
82 changes: 65 additions & 17 deletions gemsfx/src/main/java/com/dlsc/gemsfx/PhoneNumberField.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,13 @@
import javafx.scene.control.Skin;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.util.Callback;
import javafx.util.Pair;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
Expand All @@ -36,6 +34,7 @@
public class PhoneNumberField extends Control {

public static final String DEFAULT_STYLE_CLASS = "phone-number-field";
public static final String DEFAULT_MASK = "(###) ###-##-##";

private final TextField textField = new TextField();

Expand Down Expand Up @@ -142,6 +141,8 @@ public void set(CountryCallingCode countryCallingCode) {
.map(CountryCallingCode::defaultPhonePrefix)
.orElse(null));

Optional.ofNullable(getMaskProvider()).ifPresent(m -> setMask(m.call(countryCallingCode)));

} finally {
selfUpdate = false;
}
Expand Down Expand Up @@ -252,18 +253,53 @@ public final void setForceLocalPhoneNumber(boolean forceLocalPhoneNumber) {
forceLocalPhoneNumberProperty().set(forceLocalPhoneNumber);
}

private final StringProperty mask = new SimpleStringProperty(this, "mask");
private final ObjectProperty<Callback<CountryCallingCode, String>> maskProvider = new SimpleObjectProperty<>(this, "maskProvider", code ->
Optional.ofNullable(code).map(CountryCallingCode::mask).orElse(null)) {
@Override
public void set(Callback<CountryCallingCode, String> newMaskProvider) {
super.set(newMaskProvider);
setMask(Optional.ofNullable(newMaskProvider).map(p -> p.call(getCountryCode())).orElse(null));
}
};

public final StringProperty maskProperty() {
return mask;
public final ObjectProperty<Callback<CountryCallingCode, String>> maskProviderProperty() {
return maskProvider;
}

public final Callback<CountryCallingCode, String> getMaskProvider() {
return maskProviderProperty().get();
}

public final void setMaskProvider(Callback<CountryCallingCode, String> mask) {
maskProviderProperty().set(mask);
}

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

public final ReadOnlyStringProperty maskProperty() {
return mask.getReadOnlyProperty();
}

public final String getMask() {
return maskProperty().get();
return mask.get();
}

public final void setMask(String mask) {
maskProperty().set(mask);
private void setMask(String mask) {
this.mask.set(mask);
}

private final ObjectProperty<Callback<CountryCallingCode, Node>> countryCodeViewFactory = new SimpleObjectProperty<>(this, "countryCodeViewFactory");

public final ObjectProperty<Callback<CountryCallingCode, Node>> countryCodeViewFactoryProperty() {
return countryCodeViewFactory;
}

public final Callback<CountryCallingCode, Node> getCountryCodeViewFactory() {
return countryCodeViewFactoryProperty().get();
}

public final void setCountryCodeViewFactory(Callback<CountryCallingCode, Node> countryCodeViewFactory) {
countryCodeViewFactoryProperty().set(countryCodeViewFactory);
}

public interface CountryCallingCode {
Expand All @@ -272,9 +308,9 @@ public interface CountryCallingCode {

int[] areaCodes();

String displayName(String language);
String iso2Code();

Node flagView();
String mask();

default Integer defaultAreaCode() {
return areaCodes().length > 0 ? areaCodes()[0] : null;
Expand Down Expand Up @@ -540,13 +576,17 @@ enum Defaults implements CountryCallingCode {
private final int code;
private final String iso2Code;
private final int[] areaCodes;
private final Image flagImage;
private final String mask;

Defaults(int code, String iso2Code, int... areaCodes) {
this(code, iso2Code, DEFAULT_MASK, areaCodes);
}

Defaults(int code, String iso2Code, String mask, int... areaCodes) {
this.code = code;
this.iso2Code = iso2Code;
this.mask = mask;
this.areaCodes = Optional.ofNullable(areaCodes).orElse(new int[0]);
this.flagImage = new Image(Objects.requireNonNull(PhoneNumberField.class.getResource("phonenumberfield/country-flags/20x13/" + iso2Code.toLowerCase() + ".png")).toExternalForm());
}

@Override
Expand All @@ -560,13 +600,13 @@ public int[] areaCodes() {
}

@Override
public String displayName(String language) {
return new Locale(language, iso2Code).getDisplayCountry();
public String iso2Code() {
return iso2Code;
}

@Override
public Node flagView() {
return new ImageView(flagImage);
public String mask() {
return mask;
}

}
Expand Down Expand Up @@ -642,6 +682,13 @@ private static Pair<Integer, String> scoreAndLocalNumber(CountryCallingCode code
}

private final class PhoneNumberFormatter implements UnaryOperator<TextFormatter.Change> {

private PhoneNumberFormatter() {
maskProperty().addListener((observable, oldMask, newMask) -> {

});
}

@Override
public TextFormatter.Change apply(TextFormatter.Change change) {
if (change.isAdded() || change.isReplaced()) {
Expand All @@ -660,6 +707,7 @@ public TextFormatter.Change apply(TextFormatter.Change change) {
}
}
}

return change;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;

import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
Expand All @@ -29,6 +32,14 @@ public class PhoneNumberFieldSkin extends SkinBase<PhoneNumberField> {

private static final Image WORLD_ICON = new Image(Objects.requireNonNull(PhoneNumberField.class.getResource("phonenumberfield/world.png")).toExternalForm());

private static final Map<PhoneNumberField.CountryCallingCode, Image> FLAG_IMAGES = new HashMap<>();

static {
for (PhoneNumberField.CountryCallingCode code : PhoneNumberField.CountryCallingCode.Defaults.values()) {
FLAG_IMAGES.put(code, new Image(Objects.requireNonNull(PhoneNumberField.class.getResource("phonenumberfield/country-flags/20x13/" + code.iso2Code().toLowerCase() + ".png")).toExternalForm()));
}
}

public PhoneNumberFieldSkin(PhoneNumberField field, ReadOnlyObjectWrapper<PhoneNumberField.CountryCallingCode> countryCode) {
super(field);

Expand All @@ -49,8 +60,10 @@ public PhoneNumberFieldSkin(PhoneNumberField field, ReadOnlyObjectWrapper<PhoneN
}
};

getSkinnable().getAvailableCountryCodes().addListener((InvalidationListener) obs -> callingCodesUpdater.run());
getSkinnable().getPreferredCountryCodes().addListener((InvalidationListener) obs -> callingCodesUpdater.run());
InvalidationListener listener = obs -> callingCodesUpdater.run();
getSkinnable().getAvailableCountryCodes().addListener(listener);
getSkinnable().getPreferredCountryCodes().addListener(listener);
getSkinnable().countryCodeViewFactoryProperty().addListener(listener);
callingCodesUpdater.run();

PhoneNumberEditor editor = new PhoneNumberEditor();
Expand Down Expand Up @@ -105,11 +118,9 @@ public PhoneNumberEditor() {
StackPane flagBox = new StackPane();
flagBox.getStyleClass().add("flag-box");

Runnable flagUpdater = () -> flagBox.getChildren().setAll(Optional.ofNullable(getSkinnable().getCountryCode())
.map(PhoneNumberField.CountryCallingCode::flagView)
.orElse(new ImageView(WORLD_ICON)));

Runnable flagUpdater = () -> flagBox.getChildren().setAll(getCountryCodeFlagView(getSkinnable().getCountryCode()));
getSkinnable().countryCodeProperty().addListener(obs -> flagUpdater.run());
getSkinnable().countryCodeViewFactoryProperty().addListener(obs -> flagUpdater.run());
flagUpdater.run();

Region arrow = new Region();
Expand Down Expand Up @@ -177,8 +188,8 @@ protected void updateItem(PhoneNumberField.CountryCallingCode item, boolean empt
int index = -1;

if (item != null && !empty) {
setText("(+" + item.countryCode() + ") " + item.displayName("en"));
setGraphic(item.flagView());
setText("(+" + item.countryCode() + ") " + new Locale("en", item.iso2Code()).getDisplayCountry());
setGraphic(getCountryCodeFlagView(item));
index = getSkinnable().getPreferredCountryCodes().indexOf(item);
} else {
setText(null);
Expand All @@ -200,4 +211,18 @@ protected void updateItem(PhoneNumberField.CountryCallingCode item, boolean empt

}

private Node getCountryCodeFlagView(PhoneNumberField.CountryCallingCode code) {
Node flagView;
if (code != null) {
if (getSkinnable().getCountryCodeViewFactory() != null) {
flagView = getSkinnable().getCountryCodeViewFactory().call(code);
} else {
flagView = new ImageView(Optional.ofNullable(FLAG_IMAGES.get(code)).orElse(WORLD_ICON));
}
} else {
flagView = new ImageView(WORLD_ICON);
}
return flagView;
}

}
Loading