/* * @(#)TextFieldsDemo.java 5/19/2013 * * Copyright 2002 - 2013 JIDE Software Inc. All rights reserved. */ package jidefx.examples.fields; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.geometry.Insets; import javafx.geometry.Orientation; import javafx.geometry.Point2D; import javafx.geometry.Pos; import javafx.scene.Node; import javafx.scene.Parent; import javafx.scene.control.CheckBox; import javafx.scene.control.Label; import javafx.scene.control.Separator; import javafx.scene.control.Tooltip; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.HBox; import javafx.scene.layout.Priority; import javafx.scene.layout.Region; import jidefx.examples.decoration.DateFormatValidator; import jidefx.examples.decoration.SimpleValidator; import jidefx.examples.demo.AbstractFxDemo; import jidefx.scene.control.decoration.DecorationPane; import jidefx.scene.control.decoration.DecorationUtils; import jidefx.scene.control.decoration.Decorator; import jidefx.scene.control.field.*; import jidefx.scene.control.field.verifier.IntegerRangePatternVerifier; import jidefx.scene.control.validation.ValidationMode; import jidefx.scene.control.validation.ValidationUtils; import jidefx.utils.FXUtils; import net.miginfocom.layout.AC; import net.miginfocom.layout.CC; import net.miginfocom.layout.LC; import org.apache.commons.validator.routines.RegexValidator; import org.tbee.javafx.scene.layout.MigPane; import java.text.DateFormat; import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.Calendar; import java.util.Date; public class TextFieldsDemo extends AbstractFxDemo { public TextFieldsDemo() { } public String getName() { return "MaskTextField/FormattedTextField Demo"; } public static void main(String[] args) { launch(args); } public static final String PATTERN_IP4 = "\\b(([01]?\\d?\\d|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d?\\d|2[0-4]\\d|25[0-5])\\b"; public static final String PATTERN_IP6 = "^([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4}$"; public static final String PATTERN_MAC_ADDRESS = "^([0-9a-fA-F][0-9a-fA-F]:){5}([0-9a-fA-F][0-9a-fA-F])$"; public static final String PATTERN_SSN = "^\\d{3}-\\d{2}-\\d{4}$"; public static final String PREFIX_MASK_FIELD_FORM = "FieldForm"; public Region getDemoPanel() { Parent pane1 = createMaskTextFields(); Parent pane2 = createFormattedTextFields(); HBox.setHgrow(pane1, Priority.ALWAYS); HBox.setHgrow(pane2, Priority.ALWAYS); HBox pane = new HBox(6, pane1, new Separator(Orientation.VERTICAL), pane2); ValidationUtils.install(pane.lookup("#" + PREFIX_MASK_FIELD_FORM + "IP4Field"), new SimpleValidator(new RegexValidator(PATTERN_IP4)), ValidationMode.ON_FLY); ValidationUtils.install(pane.lookup("#" + PREFIX_MASK_FIELD_FORM + "IP6Field"), new SimpleValidator(new RegexValidator(PATTERN_IP6)), ValidationMode.ON_FLY); ValidationUtils.install(pane.lookup("#" + PREFIX_MASK_FIELD_FORM + "MacAddressField"), new SimpleValidator(new RegexValidator(PATTERN_MAC_ADDRESS)), ValidationMode.ON_FLY); ValidationUtils.install(pane.lookup("#" + PREFIX_MASK_FIELD_FORM + "SSNField"), new SimpleValidator(new RegexValidator(PATTERN_SSN)), ValidationMode.ON_FLY); Node dateField = pane.lookup("#" + PREFIX_MASK_FIELD_FORM + "dateField"); ValidationUtils.install(dateField, new DateFormatValidator(((FormattedTextField) dateField).getPattern()), ValidationMode.ON_FLY); Node timeField = pane.lookup("#" + PREFIX_MASK_FIELD_FORM + "timeField"); ValidationUtils.install(timeField, new DateFormatValidator(((FormattedTextField) timeField).getPattern()), ValidationMode.ON_FLY); Node dateShortField = pane.lookup("#" + PREFIX_MASK_FIELD_FORM + "dateShortField"); ValidationUtils.install(dateShortField, new DateFormatValidator(((FormattedTextField) dateShortField).getPattern()), ValidationMode.ON_FLY); Node dateTimeField = pane.lookup("#" + PREFIX_MASK_FIELD_FORM + "dateTimeField"); ValidationUtils.install(dateTimeField, new DateFormatValidator(((FormattedTextField) dateTimeField).getPattern()), ValidationMode.ON_FLY); Node localTimeField = pane.lookup("#" + PREFIX_MASK_FIELD_FORM + "localTimeField"); ValidationUtils.install(localTimeField, new DateFormatValidator(((FormattedTextField) localTimeField).getPattern()), ValidationMode.ON_FLY); Node dateTimeCustomField = pane.lookup("#" + PREFIX_MASK_FIELD_FORM + "dateTimeCustomField"); ValidationUtils.install(dateTimeCustomField, new DateFormatValidator(((FormattedTextField) dateTimeCustomField).getPattern()), ValidationMode.ON_FLY); return new DecorationPane(pane); } public static Parent createMaskTextFields() { MigPane pane = new MigPane(new LC().minWidth("450px").minHeight("450px").insets("20 10 10 10"), new AC().index(0).align("right").gap("20px").index(1).fill().grow().gap("6px").fill(), new AC().gap("6px")); Label title = new Label("Mask TextFields"); title.setStyle("-fx-font-size: 1.4em;"); pane.add(title, new CC().span(2).alignX("left").wrap()); final CheckBox showClearButtonCheckBox = new CheckBox("Show Clear Button"); showClearButtonCheckBox.setSelected(true); showClearButtonCheckBox.selectedProperty().addListener(new ChangeListener<Boolean>() { @Override public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) { FXUtils.setRecursively(pane, new FXUtils.Handler() { @Override public boolean condition(Object c) { return c instanceof MaskTextField; } @Override public void action(Object c) { ((MaskTextField) c).setClearButtonVisible(newValue); } }); } }); final CheckBox editableCheckBox = new CheckBox("Editable"); editableCheckBox.setSelected(true); editableCheckBox.selectedProperty().addListener(new ChangeListener<Boolean>() { @Override public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) { FXUtils.setRecursively(pane, new FXUtils.Handler() { @Override public boolean condition(Object c) { return c instanceof MaskTextField; } @Override public void action(Object c) { ((MaskTextField) c).setEditable(newValue); } }); } }); final CheckBox disableCheckBox = new CheckBox("Disable"); disableCheckBox.setSelected(false); disableCheckBox.selectedProperty().addListener(new ChangeListener<Boolean>() { @Override public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) { FXUtils.setRecursively(pane, new FXUtils.Handler() { @Override public boolean condition(Object c) { return c instanceof MaskTextField; } @Override public void action(Object c) { ((MaskTextField) c).setDisable(newValue); } }); } }); HBox hBox = new HBox(10, showClearButtonCheckBox, editableCheckBox, disableCheckBox); pane.add(hBox, new CC().spanX(2).alignX("right").gapBottom("10px").wrap()); Label digitsLabel = new Label("Number (5-digits):"); digitsLabel.setId(PREFIX_MASK_FIELD_FORM + "DigitsLabel"); MaskTextField digitsField = new MaskTextField(); digitsField.setInputMask("99999"); digitsField.setInputMask(null); digitsField.setPlaceholderCharacter('0'); digitsField.setId(PREFIX_MASK_FIELD_FORM + "DigitsField"); pane.add(digitsLabel); pane.add(digitsField, new CC().wrap()); addDecoratorForMaskTextField(digitsLabel, digitsField); Label lettersLabel = new Label("Letters (All required):"); lettersLabel.setId(PREFIX_MASK_FIELD_FORM + "LettersLabel"); MaskTextField lettersField = new MaskTextField(); lettersField.setInputMask("AAAAAA"); lettersField.setConversionMask("UUUUUU"); lettersField.setPlaceholderCharacter('_'); lettersField.setId(PREFIX_MASK_FIELD_FORM + "LettersField"); pane.add(lettersLabel); pane.add(lettersField, new CC().wrap()); addDecoratorForMaskTextField(lettersLabel, lettersField); Label optionalLettersLabel = new Label("Letters (Optional except 1st letter):"); optionalLettersLabel.setId(PREFIX_MASK_FIELD_FORM + "OptionalLettersLabel"); MaskTextField optionalLettersField = new MaskTextField(); optionalLettersField.setInputMask("AAAAAA"); optionalLettersField.setConversionMask("UUUUUU"); optionalLettersField.setRequiredMask("R_____"); optionalLettersField.setPlaceholderCharacter('_'); optionalLettersField.setId(PREFIX_MASK_FIELD_FORM + "OptionalLettersField"); pane.add(optionalLettersLabel); pane.add(optionalLettersField, new CC().wrap()); addDecoratorForMaskTextField(optionalLettersLabel, optionalLettersField); Label serialLabel = new Label("Serial:"); serialLabel.setId(PREFIX_MASK_FIELD_FORM + "SerialLabel"); MaskTextField serialField = MaskTextField.createSerialNumberField(); serialField.setPlaceholderCharacter('_'); serialField.setId(PREFIX_MASK_FIELD_FORM + "SerialField"); pane.add(serialLabel); pane.add(serialField, new CC().wrap()); addDecoratorForMaskTextField(serialLabel, serialField); Label IP6Label = new Label("IPv6:"); IP6Label.setId(PREFIX_MASK_FIELD_FORM + "IP6Label"); MaskTextField IP6Field = MaskTextField.createIPv6Field(); IP6Field.setId(PREFIX_MASK_FIELD_FORM + "IP6Field"); pane.add(IP6Label); pane.add(IP6Field, new CC().wrap()); addDecoratorForMaskTextField(IP6Label, IP6Field); Label macLabel = new Label("MAC Address:"); macLabel.setId(PREFIX_MASK_FIELD_FORM + "MacAddressLabel"); MaskTextField macField = MaskTextField.createMacAddressField(); macField.setId(PREFIX_MASK_FIELD_FORM + "MacAddressField"); pane.add(macLabel); pane.add(macField, new CC().wrap()); addDecoratorForMaskTextField(macLabel, macField); Label SSNLabel = new Label("SSN:"); SSNLabel.setId(PREFIX_MASK_FIELD_FORM + "SSNLabel"); MaskTextField SSNField = MaskTextField.createSSNField(); // 5/10/2013 decided to remove this example as MaskFormatter is a Swing class. Don't want to introduce any unnecessary dependency on Swing // // This is just a demo to configure MaskTextField from a MaskFormatter // try { // MaskFormatter maskFormatter = new MaskFormatter("###-##-####"); // maskFormatter.setPlaceholderCharacter('#'); // SSNField.fromMaskFormatter(maskFormatter); // } // catch (ParseException e) { // // ignore // } SSNField.setId(PREFIX_MASK_FIELD_FORM + "SSNField"); pane.add(SSNLabel); pane.add(SSNField, new CC().wrap()); addDecoratorForMaskTextField(SSNLabel, SSNField); Label phoneNumberLabel = new Label("Phone Number:"); phoneNumberLabel.setId(PREFIX_MASK_FIELD_FORM + "PhoneNumberLabel"); MaskTextField phoneNumberField = MaskTextField.createPhoneNumberField(); phoneNumberField.setPlaceholderCharacter('_'); phoneNumberField.setId(PREFIX_MASK_FIELD_FORM + "PhoneNumberField"); pane.add(phoneNumberLabel); pane.add(phoneNumberField, new CC().wrap()); addDecoratorForMaskTextField(phoneNumberLabel, phoneNumberField); Label zipCodeLabel = new Label("Zip Code + 4 (US):"); zipCodeLabel.setId(PREFIX_MASK_FIELD_FORM + "ZipCodeLabel"); MaskTextField zipCodeField = MaskTextField.createZipCodePlus4Field(); zipCodeField.setPlaceholderCharacter('_'); zipCodeField.setId(PREFIX_MASK_FIELD_FORM + "ZipCodeField"); pane.add(zipCodeLabel); pane.add(zipCodeField, new CC().wrap()); addDecoratorForMaskTextField(zipCodeLabel, zipCodeField); return pane; } public static Parent createFormattedTextFields() { MigPane pane = new MigPane(new LC().minWidth("450px").minHeight("450px").insets("20 10 10 10"), new AC().index(0).align("right").gap("20px").index(1).fill().grow().gap("6px").fill(), new AC().gap("6px")); Label title = new Label("Formatted TextFields"); title.setStyle("-fx-font-size: 1.4em;"); pane.add(title, new CC().span(2).alignX("left").wrap()); final CheckBox showSpinnersCheckBox = new CheckBox("Show Spinners"); showSpinnersCheckBox.setSelected(true); showSpinnersCheckBox.selectedProperty().addListener(new ChangeListener<Boolean>() { @Override public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) { FXUtils.setRecursively(pane, new FXUtils.Handler() { @Override public boolean condition(Object c) { return c instanceof FormattedTextField; } @Override public void action(Object c) { if (c instanceof PopupField) { ((FormattedTextField) c).setSpinnersVisible(newValue); ((PopupField) c).setPopupButtonVisible(!newValue); } else { ((FormattedTextField) c).setSpinnersVisible(newValue); } } }); } }); final CheckBox editableCheckBox = new CheckBox("Editable"); editableCheckBox.setSelected(true); editableCheckBox.selectedProperty().addListener(new ChangeListener<Boolean>() { @Override public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) { FXUtils.setRecursively(pane, new FXUtils.Handler() { @Override public boolean condition(Object c) { return c instanceof FormattedTextField; } @Override public void action(Object c) { ((FormattedTextField) c).setEditable(newValue); } }); } }); final CheckBox disableCheckBox = new CheckBox("Disable"); disableCheckBox.setSelected(false); disableCheckBox.selectedProperty().addListener(new ChangeListener<Boolean>() { @Override public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) { FXUtils.setRecursively(pane, new FXUtils.Handler() { @Override public boolean condition(Object c) { return c instanceof FormattedTextField; } @Override public void action(Object c) { ((FormattedTextField) c).setDisable(newValue); } }); } }); HBox hBox = new HBox(10, showSpinnersCheckBox, editableCheckBox, disableCheckBox); pane.add(hBox, new CC().spanX(2).alignX("right").gapBottom("10px").wrap()); Label digitsLabel = new Label("Positive Integer (with Grouping):"); digitsLabel.setId(PREFIX_MASK_FIELD_FORM + "DigitsLabel"); NumberField digitsField = new NumberField(); DecimalFormat integerFormat = (DecimalFormat) DecimalFormat.getIntegerInstance(); integerFormat.setGroupingUsed(true); digitsField.setDecimalFormat(integerFormat); digitsField.setAutoReformat(true); digitsField.setValue(12345); digitsField.setPositiveOnly(true); digitsField.setId(PREFIX_MASK_FIELD_FORM + "DigitsField"); pane.add(digitsLabel); pane.add(digitsField, new CC().wrap()); addDecoratorForGroupBasedField(digitsLabel, digitsField); Label amountLabel = new Label("Amount ($####.##):"); amountLabel.setId(PREFIX_MASK_FIELD_FORM + "AmountLabel"); NumberField amountField = new NumberField(); DecimalFormat currencyFormat = (DecimalFormat) NumberFormat.getCurrencyInstance(); currencyFormat.setMaximumIntegerDigits(4); currencyFormat.setMaximumFractionDigits(2); currencyFormat.setMinimumFractionDigits(2); amountField.setDecimalFormat(currencyFormat); amountField.setPositiveOnly(true); amountField.setValue(168.00); amountField.setId(PREFIX_MASK_FIELD_FORM + "AmountField"); pane.add(amountLabel); pane.add(amountField, new CC().wrap()); addDecoratorForGroupBasedField(amountLabel, amountField); Label percentLabel = new Label("Percentage (.##%):"); percentLabel.setId(PREFIX_MASK_FIELD_FORM + "PercentLabel"); NumberField percentField = new NumberField(); DecimalFormat percentFormat = (DecimalFormat) NumberFormat.getPercentInstance(); percentFormat.setGroupingUsed(false); percentFormat.setMaximumIntegerDigits(4); percentFormat.setMaximumFractionDigits(3); percentField.setDecimalFormat(percentFormat); percentField.setValue(0.5); percentField.setId(PREFIX_MASK_FIELD_FORM + "PercentField"); pane.add(percentLabel); pane.add(percentField, new CC().wrap()); addDecoratorForGroupBasedField(percentLabel, percentField); Label IP4Label = new Label("IPv4:"); IP4Label.setId(PREFIX_MASK_FIELD_FORM + "IP4Label"); FormattedTextField<String> IP4Field = FormattedTextField.createIPv4Field(); FormattedTextField<String> field = new FormattedTextField<>(); field.getPatternVerifiers().put("a", new IntegerRangePatternVerifier(0, 999, true)); field.getPatternVerifiers().put("b", new IntegerRangePatternVerifier(0, 999, true)); field.getPatternVerifiers().put("c", new IntegerRangePatternVerifier(0, 9999, true)); field.setPattern("a-b-c"); field.setId(PREFIX_MASK_FIELD_FORM + "IP4Field"); pane.add(IP4Label); pane.add(field, new CC().wrap()); addDecoratorForGroupBasedField(IP4Label, IP4Field); Label dateLabel = new Label("Date (Default Format):"); dateLabel.setId(PREFIX_MASK_FIELD_FORM + "dateLabel"); FormattedTextField<Date> dateField = DateField.createDateField(); dateField.setId(PREFIX_MASK_FIELD_FORM + "dateField"); pane.add(dateLabel); pane.add(dateField, new CC().wrap()); addDecoratorForGroupBasedField(dateLabel, dateField); Label dateShortLabel = new Label("Date (Short Format):"); dateShortLabel.setId(PREFIX_MASK_FIELD_FORM + "dateShortLabel"); FormattedTextField<Date> dateShortField = DateField.createDateField(DateFormat.SHORT); dateShortField.setId(PREFIX_MASK_FIELD_FORM + "dateShortField"); pane.add(dateShortLabel); pane.add(dateShortField, new CC().wrap()); addDecoratorForGroupBasedField(dateShortLabel, dateShortField); Label timeLabel = new Label("Time (Default Format):"); timeLabel.setId(PREFIX_MASK_FIELD_FORM + "timeLabel"); FormattedTextField<Date> timeField = DateField.createTimeField(); timeField.setId(PREFIX_MASK_FIELD_FORM + "timeField"); pane.add(timeLabel); pane.add(timeField, new CC().wrap()); addDecoratorForGroupBasedField(timeLabel, timeField); Label dateTimeLabel = new Label("Date/Time (Default):"); dateTimeLabel.setId(PREFIX_MASK_FIELD_FORM + "dateTimeLabel"); FormattedTextField<Date> dateTimeField = DateField.createDateTimeField(); dateTimeField.setId(PREFIX_MASK_FIELD_FORM + "dateTimeField"); pane.add(dateTimeLabel); pane.add(dateTimeField, new CC().wrap()); addDecoratorForGroupBasedField(dateTimeLabel, dateTimeField); Label dateTimeCustomLabel = new Label("Date/Time (Custom):"); dateTimeCustomLabel.setId(PREFIX_MASK_FIELD_FORM + "dateTimeCustomLabel"); FormattedTextField<Date> dateTimeCustomField = DateField.createDateField("EEEE yyyyy.MMMMM.dd G hh:mm aa", Calendar.getInstance().getTime()); dateTimeCustomField.setId(PREFIX_MASK_FIELD_FORM + "dateTimeCustomField"); pane.add(dateTimeCustomLabel); pane.add(dateTimeCustomField, new CC().wrap()); addDecoratorForGroupBasedField(dateTimeCustomLabel, dateTimeCustomField); Label localTimeLabel = new Label("Time (LocalTime):"); localTimeLabel.setId(PREFIX_MASK_FIELD_FORM + "localTimeLabel"); LocalTimeField localTimeField = LocalTimeField.createLocalTimeField(); localTimeField.setId(PREFIX_MASK_FIELD_FORM + "localTimeField"); pane.add(localTimeLabel); pane.add(localTimeField, new CC().wrap()); addDecoratorForGroupBasedField(localTimeLabel, localTimeField); return pane; } private static void addDecoratorForMaskTextField(Label label, MaskTextField field) { field.setClearButtonVisible(true); ImageView tip = new ImageView(new Image("/jidefx/examples/fields/mask.png")); Tooltip tooltip = new Tooltip("InputMask: " + field.getInputMask() + "\n" + "ConversionMask: " + field.getConversionMask() + "\n" + "RequiredMask: " + field.getRequiredMask() + "\n" + "PlaceholderCharacter: " + field.getPlaceholderCharacter() ); Tooltip.install(tip, tooltip); DecorationUtils.install(label, new Decorator<Node>(tip, Pos.CENTER_RIGHT, new Point2D(80, 0), new Insets(0))); } private static void addDecoratorForGroupBasedField(Label label, FormattedTextField<?> field) { field.setSpinnersVisible(true); ImageView tip = new ImageView(new Image("/jidefx/examples/fields/formatted.png")); Tooltip tooltip = new Tooltip("Pattern: " + field.getPattern()); Tooltip.install(tip, tooltip); DecorationUtils.install(label, new Decorator<Node>(tip, Pos.CENTER_RIGHT, new Point2D(80, 0), new Insets(0))); field.installAdjustmentMouseHandler(label, 1); } @Override public String getDemoFolder() { return "src/field"; } }