1 /*
   2  * Copyright (c) 2013, 2014, Oracle and/or its affiliates.
   3  * All rights reserved. Use is subject to license terms.
   4  *
   5  * This file is available and licensed under the following license:
   6  *
   7  * Redistribution and use in source and binary forms, with or without
   8  * modification, are permitted provided that the following conditions
   9  * are met:
  10  *
  11  *  - Redistributions of source code must retain the above copyright
  12  *    notice, this list of conditions and the following disclaimer.
  13  *  - Redistributions in binary form must reproduce the above copyright
  14  *    notice, this list of conditions and the following disclaimer in
  15  *    the documentation and/or other materials provided with the distribution.
  16  *  - Neither the name of Oracle Corporation nor the names of its
  17  *    contributors may be used to endorse or promote products derived
  18  *    from this software without specific prior written permission.
  19  *
  20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31  */
  32 package ensemble.samples.controls.datepicker;
  33 
  34 import java.time.LocalDate;
  35 import java.util.Iterator;
  36 import java.util.Locale;
  37 import javafx.application.Application;
  38 import javafx.beans.value.ChangeListener;
  39 import javafx.beans.value.ObservableValue;
  40 import javafx.collections.FXCollections;
  41 import javafx.collections.ObservableList;
  42 import javafx.event.ActionEvent;
  43 import javafx.event.EventHandler;
  44 import javafx.geometry.Pos;
  45 import javafx.scene.Parent;
  46 import javafx.scene.Scene;
  47 import javafx.scene.control.CheckMenuItem;
  48 import javafx.scene.control.DateCell;
  49 import javafx.scene.control.DatePicker;
  50 import javafx.scene.control.Menu;
  51 import javafx.scene.control.MenuBar;
  52 import javafx.scene.control.MenuItem;
  53 import javafx.scene.control.RadioMenuItem;
  54 import javafx.scene.control.Toggle;
  55 import javafx.scene.control.ToggleGroup;
  56 import javafx.scene.control.Tooltip;
  57 import javafx.scene.layout.HBox;
  58 import javafx.scene.layout.VBox;
  59 import javafx.scene.text.Text;
  60 import javafx.stage.Stage;
  61 import javafx.util.Callback;
  62 
  63 
  64 /**
  65  * A sample that demonstrates the DatePicker. There is an option to switch
  66  * locales and see how DatePicker control picks it up.
  67  *
  68  * @sampleName DatePicker
  69  * @preview preview.png
  70  * @see javafx.scene.control.DateCell
  71  * @see javafx.scene.control.DatePicker
  72  */
  73 public class DatePickerApp extends Application {
  74 
  75     private final static ObservableList<String> locales = FXCollections.observableArrayList();
  76     private DatePicker datePicker;
  77     private MenuBar datePickerMenuBar;
  78     private final LocalDate today = LocalDate.now();
  79     private final LocalDate tomorrow = today.plusDays(1);
  80     private Locale originalLocale;
  81     private HBox hbox;
  82     static {
  83         locales.addAll(new String[]{
  84             "en-US",
  85             "ar-SA",
  86             "en-GB",
  87             "cs-CZ",
  88             "el-GR",
  89             "he-IL",
  90             "hi-IN",
  91             "ja-JP",
  92             "ja-JP-u-ca-japanese",
  93             "ru-RU",
  94             "sv-SE",
  95             "th-TH",
  96             "th-TH-u-ca-buddhist",
  97             "th-TH-u-ca-buddhist-nu-thai",
  98             "zh-CN",
  99             "en-US-u-ca-islamic-umalqura",
 100             "ar-SA-u-ca-islamic-umalqura",
 101             "en-u-ca-japanese-nu-thai"
 102         });
 103     }
 104 
 105     public Parent createContent() {
 106         Text datePickerText = new Text("Date:");
 107         
 108         hbox = new HBox(18);
 109         hbox.setAlignment(Pos.CENTER);
 110         hbox.getChildren().add(datePickerText);
 111         
 112         datePicker = createDatePicker();
 113         
 114         VBox vbox = new VBox(22);
 115         vbox.getChildren().addAll(datePickerMenuBar, hbox);
 116         vbox.setPrefSize(300, 200);
 117         vbox.setMinSize(VBox.USE_PREF_SIZE, VBox.USE_PREF_SIZE);
 118         return vbox;
 119     }
 120 
 121     private DatePicker createDatePicker() {
 122         hbox.getChildren().remove(datePicker);
 123         LocalDate value = null;
 124         if (datePicker != null) {
 125             value = datePicker.getValue();
 126         }
 127         DatePicker picker = new DatePicker();
 128         // day cell factory
 129         final Callback<DatePicker, DateCell> dayCellFactory = new Callback<DatePicker, DateCell>() {
 130             @Override
 131             public DateCell call(final DatePicker datePicker) {
 132                 return new DateCell() {
 133                     @Override
 134                     public void updateItem(LocalDate item, boolean empty) {
 135                         super.updateItem(item, empty);
 136                         if (item.isBefore(today)) {
 137                             setStyle("-fx-background-color: #8099ff;");
 138                         } else {
 139                             if (item.equals(tomorrow)) {
 140                                 setTooltip(new Tooltip("Tomorrow is important"));
 141                             }
 142                         }
 143                     }
 144                 };
 145             }
 146         };
 147         //Create the menubar to experiment with the DatePicker
 148         datePickerMenuBar = createMenuBar(dayCellFactory);
 149         // Listen for DatePicker actions
 150         picker.setOnAction((ActionEvent t) -> {
 151             LocalDate isoDate = picker.getValue();
 152             if ((isoDate != null) && (!isoDate.equals(LocalDate.now()))) {
 153                 for (Menu menu : datePickerMenuBar.getMenus()) {
 154                     if (menu.getText().equals("Options for Locale")) {
 155                         for (MenuItem menuItem : menu.getItems()) {
 156                             if (menuItem.getText().equals("Set date to today")) {
 157                                 if ((menuItem instanceof CheckMenuItem) && ((CheckMenuItem) menuItem).isSelected()) {
 158                                     ((CheckMenuItem) menuItem).setSelected(false);
 159                                 }
 160                             }
 161                         }
 162                     }
 163                 }
 164             }
 165         });
 166         hbox.getChildren().add(picker);
 167         if (value != null) {
 168             picker.setValue(value);
 169         }
 170         return picker;
 171     }
 172 
 173     private MenuBar createMenuBar(final Callback<DatePicker, DateCell> dayCellFac) {
 174         final MenuBar menuBar = new MenuBar();
 175         final ToggleGroup localeToggleGroup = new ToggleGroup();
 176         // Locales
 177         Menu localeMenu = new Menu("Locales");
 178         Iterator<String> localeIterator = locales.iterator();
 179         while (localeIterator.hasNext()) {
 180             RadioMenuItem localeMenuItem = new RadioMenuItem(localeIterator.next());
 181             localeMenuItem.setToggleGroup(localeToggleGroup);
 182             localeMenu.getItems().add(localeMenuItem);
 183         }
 184 
 185         Menu optionsMenu = new Menu("Options for Locale");
 186         //Style DatePicker with cell factory
 187         // XXX - localize
 188         final String MSG = "Use cell factory to color past days and add tooltip to tomorrow";
 189         final CheckMenuItem cellFactoryMenuItem = new CheckMenuItem(MSG);
 190         optionsMenu.getItems().add(cellFactoryMenuItem);
 191         cellFactoryMenuItem.setOnAction((ActionEvent t) -> {
 192             if (cellFactoryMenuItem.isSelected()) {
 193                 datePicker.setDayCellFactory(dayCellFac);
 194             } else {
 195                 datePicker.setDayCellFactory(null);
 196             }
 197         });
 198                        
 199         //Set date to today
 200         final CheckMenuItem todayMenuItem = new CheckMenuItem("Set date to today");
 201         optionsMenu.getItems().add(todayMenuItem);
 202         todayMenuItem.setOnAction((ActionEvent t) -> {
 203             if (todayMenuItem.isSelected()) {
 204                 datePicker.setValue(today);
 205             }
 206         });
 207 
 208         //Set date to today
 209         final CheckMenuItem showWeekNumMenuItem = new CheckMenuItem("Show week numbers");
 210         optionsMenu.getItems().add(showWeekNumMenuItem);
 211         showWeekNumMenuItem.setOnAction((ActionEvent t) -> {
 212             datePicker.setShowWeekNumbers(showWeekNumMenuItem.isSelected());
 213         });        
 214         
 215         localeToggleGroup.selectedToggleProperty().addListener((ObservableValue<? extends Toggle> ov,
 216                                                                 Toggle oldToggle, Toggle newToggle) -> {
 217             if (localeToggleGroup.getSelectedToggle() != null) {
 218                 String selectedLocale = ((RadioMenuItem) localeToggleGroup.getSelectedToggle()).getText();
 219                 Locale locale = Locale.forLanguageTag(selectedLocale.replace('_', '-'));
 220                 Locale.setDefault(locale);
 221                 datePicker = createDatePicker();
 222                 datePicker.setShowWeekNumbers(showWeekNumMenuItem.isSelected());
 223             }
 224         });       
 225 
 226         menuBar.getMenus().addAll(localeMenu, optionsMenu);
 227         return menuBar;
 228     }    
 229  
 230     public void play() {
 231         originalLocale = Locale.getDefault();
 232     }
 233     
 234     @Override
 235     public void stop() {
 236         Locale.setDefault(originalLocale);
 237     }
 238     
 239     @Override
 240     public void start(Stage primaryStage) throws Exception { 
 241         primaryStage.setScene(new Scene(createContent()));      
 242         primaryStage.show();
 243         play();
 244     }
 245     
 246     /**
 247      * Java main for when running without JavaFX launcher
 248      * @param args command line arguments
 249      */
 250     public static void main(String[] args) {
 251         launch(args);
 252     }
 253 }