Skip to content

Commit

Permalink
Transferring mouse press event to the field editor
Browse files Browse the repository at this point in the history
  • Loading branch information
gldiazcardenas committed Sep 28, 2023
1 parent 849013f commit 66a65b1
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 41 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package com.dlsc.gemsfx.skins;

import com.dlsc.gemsfx.PhoneNumberField;
import javafx.geometry.Bounds;
import javafx.scene.Node;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.Skin;
import javafx.scene.control.SkinBase;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
Expand All @@ -18,45 +21,48 @@

public class PhoneNumberFieldSkin extends SkinBase<PhoneNumberField> {

private final ComboBox<String> comboBox = new ComboBox<>();

public PhoneNumberFieldSkin(PhoneNumberField control) {
super(control);

comboBox.setButtonCell(new Editor());
comboBox.getItems()
.setAll(Arrays.stream(Locale.getISOCountries())
PhoneNumberFieldEditor editor = new PhoneNumberFieldEditor();

ComboBox<String> comboBox = new ComboBox<>();
comboBox.setMouseTransparent(true);// Disable all mouse events on the combo box
comboBox.setButtonCell(editor);
comboBox.getItems().setAll(Arrays.stream(Locale.getISOCountries())
.map(c -> new Locale("", c).getDisplayCountry())
.collect(Collectors.toList()));

getChildren().addAll(comboBox);
}

private class Editor extends ListCell<String> {

public Editor() {
getStyleClass().add("editor");
}
// Manually handle mouse pressed over either the text field or the country selector
control.addEventFilter(MouseEvent.MOUSE_PRESSED, evt -> {
Bounds textFieldBounds = editor.textField.getBoundsInParent();
if (textFieldBounds.contains(evt.getX(), evt.getY())) {
editor.textField.requestFocus();
comboBox.hide();
}
else {
Bounds selectorBounds = editor.countrySelector.getBoundsInParent();
if (selectorBounds.contains(evt.getX(), evt.getY())) {
editor.countrySelector.requestFocus();
comboBox.show();
}
else {
comboBox.hide();
}
}
evt.consume();
});

@Override
protected Skin<?> createDefaultSkin() {
return new EditorSkin(this);
}

@Override
public void requestFocus() {
super.requestFocus();
}
getChildren().addAll(comboBox);
}

private class EditorSkin extends SkinBase<Editor> {
private class PhoneNumberFieldEditor extends ListCell<String> {

private final TextField textField = new TextField();
private final HBox countrySelector = new HBox();
private final TextField phoneNumberTextField = new TextField();
private final Label maskLabel = new Label("### ### ####");

protected EditorSkin(Editor control) {
super(control);
public PhoneNumberFieldEditor() {
getStyleClass().add("editor");

Label countryCode = new Label("(+##)");
countryCode.getStyleClass().add("country-code");
Expand All @@ -68,24 +74,47 @@ protected EditorSkin(Editor control) {
arrowButton.getStyleClass().add("arrow-button");
arrowButton.getChildren().add(arrow);

countrySelector.getChildren().addAll(countryCode, arrowButton);
countrySelector.getStyleClass().add("country-selector");
countrySelector.setOnMouseClicked(evt -> comboBox.show());
countrySelector.getChildren().addAll(countryCode, arrowButton);

textField.textProperty().bindBidirectional(PhoneNumberFieldSkin.this.getSkinnable().phoneNumberProperty());
textField.setTextFormatter(new TextFormatter<>(change -> {
if (change.isAdded()) {
String text = change.getText();
if (!text.matches("[0-9]")) {
return null;
}
}
return change;
}));
}

@Override
protected Skin<?> createDefaultSkin() {
return new PhoneNumberFieldEditorSkin(this);
}

maskLabel.getStyleClass().add("mask");
}

getChildren().addAll(countrySelector, phoneNumberTextField, maskLabel);
private class PhoneNumberFieldEditorSkin extends SkinBase<PhoneNumberFieldEditor> {

private final Label maskLabel = new Label("(###) ###-####");

protected PhoneNumberFieldEditorSkin(PhoneNumberFieldEditor control) {
super(control);
maskLabel.getStyleClass().add("text-field-mask");
getChildren().addAll(control.countrySelector, control.textField, maskLabel);
}

@Override
protected void layoutChildren(double x, double y, double w, double h) {
final double arrowWidth = snapSizeX(countrySelector.prefWidth(-1));
countrySelector.resizeRelocate(x, y, arrowWidth, h);
final double arrowWidth = snapSizeX(getSkinnable().countrySelector.prefWidth(-1));
getSkinnable().countrySelector.resizeRelocate(x, y, arrowWidth, h);

final double textFieldX = snapPositionX(x + arrowWidth);
phoneNumberTextField.resizeRelocate(textFieldX, y, w - arrowWidth, h);
getSkinnable().textField.resizeRelocate(textFieldX, y, w - arrowWidth, h);

final Node textNode = phoneNumberTextField.lookup(".text");
final Node textNode = getSkinnable().textField.lookup(".text");
final double maskX = snapPositionX(textFieldX + textNode.getLayoutBounds().getWidth());
final double maskWidth = snapSizeX(Math.max(0, Math.min(maskLabel.prefWidth(-1), w - maskX)));
maskLabel.resizeRelocate(maskX, y, maskWidth, h);
Expand Down
14 changes: 8 additions & 6 deletions gemsfx/src/main/resources/com/dlsc/gemsfx/phone-number-field.css
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,24 @@
-fx-max-width: 0px;
-fx-pref-width: 0px;
-fx-min-width: 0px;
-fx-padding: 0;
-fx-padding: 0px;
}

.phone-number-field > .combo-box > .arrow-button > .arrow {
-fx-padding: 0;
-fx-padding: 0px;
}

.phone-number-field > .combo-box > .editor {
-fx-padding: 0;
-fx-padding: 0px;
}

.phone-number-field > .combo-box > .editor > .text-field {
-fx-background-color: transparent;
-fx-padding: 0px;
}

.phone-number-field > .combo-box > .editor > .text-field-mask {
-fx-text-fill: rgb(0, 0, 0, .4);
}

.phone-number-field > .combo-box > .editor > .country-selector {
Expand All @@ -51,7 +56,4 @@
-fx-text-fill: rgb(0, 0, 0, .4);
}

.phone-number-field > .combo-box > .editor > .mask {
-fx-text-fill: rgb(0, 0, 0, .4);
}

0 comments on commit 66a65b1

Please sign in to comment.