1 /* 2 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package javafx.scene.control.test.combobox; 26 27 import java.text.FieldPosition; 28 import java.text.Format; 29 import java.text.MessageFormat; 30 import java.text.ParsePosition; 31 import javafx.event.ActionEvent; 32 import javafx.event.Event; 33 import javafx.event.EventHandler; 34 import javafx.scene.Scene; 35 import javafx.scene.control.*; 36 import javafx.scene.control.test.utils.CommonPropertiesScene; 37 import javafx.scene.control.test.utils.CustomStringConverter; 38 import javafx.scene.control.test.utils.SingleSelectionModelImpl; 39 import javafx.scene.control.test.utils.ptables.PropertiesTable; 40 import javafx.scene.control.test.utils.ptables.PropertyTablesFactory; 41 import javafx.scene.layout.HBox; 42 import javafx.scene.layout.VBox; 43 import javafx.scene.text.Font; 44 import javafx.util.Callback; 45 import test.javaclient.shared.InteroperabilityApp; 46 import test.javaclient.shared.Utils; 47 48 /** 49 * @author Alexander Kirov 50 */ 51 public class ComboBoxApp extends InteroperabilityApp { 52 53 public final static String TESTED_COMBOBOX_ID = "TESTED_COMBOBOX_ID"; 54 public final static String HARD_RESET_BUTTON_ID = "HARD_RESET_COMBOBOX_BUTTON_ID"; 55 public final static String SOFT_RESET_BUTTON_ID = "SOFT_RESET_COMBOBOX_BUTTON_ID"; 56 public final static String ADD_ITEM_BUTTON_ID = "ADD_ITEM_BUTTON_ID"; 57 public final static String ADD_ITEM_POSITION_TEXT_FIELD_ID = "ADD_ITEM_POSITION_TEXT_FIELD_ID"; 58 public final static String ADD_ITEM_TEXT_FIELD_ID = "ADD_ITEM_TEXT_FIELD_ID"; 59 public final static String REMOVE_BUTTON_ID = "REMOVE_BUTTON_ID"; 60 public final static String REMOVE_ITEM_POS_TEXT_FIELD_ID = "REMOVE_ITEM_POS_TEXT_FIELD_ID"; 61 public final static String ON_ACTION_EVENT_COUNTER_ID = "ON_ACTION_EVENT_COUNTER"; 62 public final static String APPLY_CUSTOM_SELECTION_MODEL_BUTTON_ID = "APPLY_CUSTOM_SELECTION_MODEL_BUTTON_ID"; 63 public final static String APPLY_CUSTOM_STRING_CONVERTER_BUTTON_ID = "APPLY_CUSTOM_STRING_CONVERTER_BUTTON_ID"; 64 public final static String CUSTOM_CELL_START_EDIT_COUNTER = "CELL START EDIT"; 65 public final static String CUSTOM_CELL_CANCEL_EDIT_COUNTER = "CELL CANCEL EDIT"; 66 public final static String CUSTOM_CELL_UPDATE_EDIT_COUNTER = "CELL UPDATE EDIT"; 67 public final static String APPLY_CUSTOM_CELL_FACTORY_BUTTON_ID = "APPLIED CUSTOM CELL FACTORY"; 68 public final static String CALLBACK_CALLED_ID = "CALLBACK CALLED"; 69 public final static String CUSTOM_CELL_UPDATE_EDIT_FOR_EDITABLE_CELL_COUNTER = "UPDATE EDIT FOR EDITABLE CELL"; 70 public final static String CUSTOM_CELL_FACTORY_ITEM_SUFFIX = "Custom"; 71 public final static String INITIAL_VALUE = "Initial value"; 72 public final static String SET_ON_SHOWING_COUNTER = "SET_ON_SHOWING_COUNTER"; 73 public final static String SET_ON_SHOWN_COUNTER = "SET_ON_SHOWN_COUNTER"; 74 public final static String SET_ON_HIDING_COUNTER = "SET_ON_HIDING_COUNTER"; 75 public final static String SET_ON_HIDEN_COUNTER = "SET_ON_HIDEN_COUNTER"; 76 public final static String SET_ADDING_ELEMENTS_ON_SHOWING = "SET_ADDING_ELEMENTS_ON_SHOWING"; 77 public final static String RESTORE_ON_SHOWING_EVENT_HANDLER = "RESTORE_ON_SHOWING_EVENT_HANDLER"; 78 public final static String POPULATE_COMBOBOX_WITH_FONT_SIZES = "POPULATE_COMBOBOX_WITH_FONT_SIZES"; 79 public final static String SET_ITEMS_NULL_BUTTON_ID = "SET_ITEMS_NULL_BUTTON_ID"; 80 public final static int INITIAL_FONT_SIZE = 8; 81 public final static int MAX_FONT_SIZE = 36; 82 83 public static void main(String[] args) { 84 Utils.launch(ComboBoxApp.class, args); 85 } 86 87 @Override 88 protected Scene getScene() { 89 Utils.setTitleToStage(stage, "ComboBoxTestApp"); 90 return new ComboBoxScene(); 91 } 92 93 class ComboBoxScene extends CommonPropertiesScene { 94 95 PropertiesTable tb; 96 //ComboBox to be tested. 97 ComboBox<String> testedComboBox; 98 99 public ComboBoxScene() { 100 super("ComboBox", 800, 600); 101 102 prepareScene(); 103 } 104 105 @Override 106 final protected void prepareScene() { 107 Utils.addBrowser(this); 108 testedComboBox = new ComboBox<String>(); 109 testedComboBox.setId(TESTED_COMBOBOX_ID); 110 111 tb = new PropertiesTable(testedComboBox); 112 tb.addSimpleListener(testedComboBox.getSelectionModel().selectedIndexProperty(), testedComboBox.getSelectionModel()); 113 tb.addSimpleListener(testedComboBox.getSelectionModel().selectedItemProperty(), testedComboBox.getSelectionModel()); 114 tb.addSimpleListener(testedComboBox.getEditor().parentProperty(), testedComboBox.getEditor()); 115 tb.addStringLine(testedComboBox.getEditor().textProperty(), "", testedComboBox.getEditor()); 116 tb.addStringLine(testedComboBox.valueProperty(), INITIAL_VALUE); 117 PropertyTablesFactory.explorePropertiesList(testedComboBox, tb); 118 119 tb.addCounter(SET_ON_SHOWING_COUNTER); 120 testedComboBox.setOnShowing(new EventHandler<Event>() { 121 public void handle(Event t) { 122 tb.incrementCounter(SET_ON_SHOWING_COUNTER); 123 } 124 }); 125 126 tb.addCounter(SET_ON_SHOWN_COUNTER); 127 testedComboBox.setOnShown(new EventHandler<Event>() { 128 public void handle(Event t) { 129 tb.incrementCounter(SET_ON_SHOWN_COUNTER); 130 } 131 }); 132 133 tb.addCounter(SET_ON_HIDING_COUNTER); 134 testedComboBox.setOnHiding(new EventHandler<Event>() { 135 public void handle(Event t) { 136 tb.incrementCounter(SET_ON_HIDING_COUNTER); 137 } 138 }); 139 140 tb.addCounter(SET_ON_HIDEN_COUNTER); 141 testedComboBox.setOnHidden(new EventHandler<Event>() { 142 public void handle(Event t) { 143 tb.incrementCounter(SET_ON_HIDEN_COUNTER); 144 } 145 }); 146 147 tb.addCounter(ON_ACTION_EVENT_COUNTER_ID); 148 testedComboBox.setOnAction(new EventHandler() { 149 public void handle(Event t) { 150 tb.incrementCounter(ON_ACTION_EVENT_COUNTER_ID); 151 } 152 }); 153 154 tb.addCounter(CUSTOM_CELL_CANCEL_EDIT_COUNTER); 155 tb.addCounter(CUSTOM_CELL_START_EDIT_COUNTER); 156 tb.addCounter(CUSTOM_CELL_UPDATE_EDIT_COUNTER); 157 tb.addCounter(CALLBACK_CALLED_ID); 158 159 final SingleSelectionModel<String> selectionModel = new SingleSelectionModelImpl<String>(testedComboBox.getItems()); 160 Button flushCalledMethodsInSelectionModel = new Button("Flush called methods"); 161 // flushCalledMethodsInSelectionModel.setOnAction(new EventHandler<ActionEvent>() { 162 // 163 // public void handle(ActionEvent t) { 164 // CMSM.setLogBuf(PropertyValueController.getLogger().textProperty()); 165 // CMSM.flushCalledMethods(); 166 // testedComboBox.setSelectionModel(selectionModel); 167 // } 168 // }); 169 170 Button applyCustomSelectionModel = new Button("Apply custom selection model"); 171 applyCustomSelectionModel.setId(APPLY_CUSTOM_SELECTION_MODEL_BUTTON_ID); 172 applyCustomSelectionModel.setOnAction(new EventHandler<ActionEvent>() { 173 public void handle(ActionEvent t) { 174 testedComboBox.selectionModelProperty().setValue(selectionModel); 175 } 176 }); 177 178 Button applyCustomStringConverter = new Button("Apply custom string converter"); 179 applyCustomStringConverter.setId(APPLY_CUSTOM_STRING_CONVERTER_BUTTON_ID); 180 applyCustomStringConverter.setOnAction(new EventHandler<ActionEvent>() { 181 public void handle(ActionEvent t) { 182 testedComboBox.setConverter(new CustomStringConverter()); 183 } 184 }); 185 186 Button applyCustomCellFactory = new Button("Apply custom cell factory"); 187 applyCustomCellFactory.setId(APPLY_CUSTOM_CELL_FACTORY_BUTTON_ID); 188 applyCustomCellFactory.setOnAction(new EventHandler<ActionEvent>() { 189 public void handle(ActionEvent t) { 190 testedComboBox.setCellFactory(new Callback<ListView<String>, ListCell<String>>() { 191 public ListCell<String> call(ListView<String> p) { 192 tb.incrementCounter(CALLBACK_CALLED_ID); 193 return new TextFieldListCell(); 194 } 195 }); 196 } 197 }); 198 199 Button hardResetButton = new Button("Hard reset"); 200 hardResetButton.setId(HARD_RESET_BUTTON_ID); 201 hardResetButton.setOnAction(new EventHandler<ActionEvent>() { 202 public void handle(ActionEvent t) { 203 HBox hb = (HBox) getRoot(); 204 hb.getChildren().clear(); 205 prepareMainSceneStructure(); 206 prepareScene(); 207 } 208 }); 209 210 Button softResetButton = new Button("Soft reset"); 211 softResetButton.setId(SOFT_RESET_BUTTON_ID); 212 softResetButton.setOnAction(new EventHandler<ActionEvent>() { 213 public void handle(ActionEvent t) { 214 tb.refresh(); 215 ComboBox<String> newOne = new ComboBox<String>(); 216 //testedComboBox.setItems(FXCollections.observableArrayList());//RT-18945 217 while (testedComboBox.getItems().size() != 0) { 218 testedComboBox.getItems().remove(0); 219 } 220 testedComboBox.setPrefHeight(newOne.getPrefHeight()); 221 testedComboBox.setPrefWidth(newOne.getPrefWidth()); 222 testedComboBox.setVisibleRowCount(newOne.getVisibleRowCount()); 223 testedComboBox.setPromptText(newOne.getPromptText()); 224 testedComboBox.setValue(null); 225 testedComboBox.setEditable(newOne.isEditable()); 226 testedComboBox.setVisible(newOne.isVisible()); 227 //testedComboBox.showingProperty().setValue(newOne.isShowing());//Showing is readonly from 2.1.0b10. 228 testedComboBox.setConverter(newOne.getConverter()); 229 testedComboBox.setCellFactory(newOne.getCellFactory()); 230 } 231 }); 232 233 HBox resetButtonsHBox = new HBox(); 234 resetButtonsHBox.getChildren().addAll(hardResetButton, softResetButton); 235 236 Button setAddingElementsOnShowing = new Button("Set adding elements on showing"); 237 setAddingElementsOnShowing.setId(SET_ADDING_ELEMENTS_ON_SHOWING); 238 setAddingElementsOnShowing.setOnAction(new EventHandler<ActionEvent>() { 239 public void handle(ActionEvent t) { 240 testedComboBox.setOnShowing(new EventHandler<Event>() { 241 public void handle(Event t) { 242 int index = ((ComboBox) testedComboBox).getItems().size(); 243 ((ComboBox) testedComboBox).getItems().add(index, INITIAL_VALUE); 244 245 tb.incrementCounter(SET_ON_SHOWING_COUNTER); 246 } 247 }); 248 } 249 }); 250 251 Button restoreDefaultOnShowingHandler = new Button("Restore default onShowing handler"); 252 restoreDefaultOnShowingHandler.setId(RESTORE_ON_SHOWING_EVENT_HANDLER); 253 restoreDefaultOnShowingHandler.setOnAction(new EventHandler<ActionEvent>() { 254 public void handle(ActionEvent t) { 255 testedComboBox.setOnShowing(new EventHandler<Event>() { 256 public void handle(Event t) { 257 tb.incrementCounter(SET_ON_SHOWING_COUNTER); 258 } 259 }); 260 } 261 }); 262 263 Button populateComboBoxWithFontSizes = new Button("Populate ComboBox with font sizes"); 264 populateComboBoxWithFontSizes.setId(POPULATE_COMBOBOX_WITH_FONT_SIZES); 265 populateComboBoxWithFontSizes.setOnAction(new EventHandler<ActionEvent>() { 266 public void handle(ActionEvent t) { 267 268 testedComboBox.setCellFactory(new Callback<ListView<String>, ListCell<String>>() { 269 @Override 270 public ListCell<String> call(ListView<String> p) { 271 return new ListCell<String>() { 272 { 273 setContentDisplay(ContentDisplay.TEXT_ONLY); 274 } 275 276 @Override 277 protected void updateItem(String item, boolean empty) { 278 super.updateItem(item, empty); 279 280 if (item == null || empty) { 281 setText(null); 282 } else { 283 setText(item); 284 setFont(new Font(Double.valueOf(item))); 285 } 286 } 287 }; 288 } 289 }); 290 291 for (int i = INITIAL_FONT_SIZE; i <= MAX_FONT_SIZE; i += 2) { 292 testedComboBox.getItems().add(String.valueOf(i)); 293 } 294 } 295 }); 296 297 setTestedControl(testedComboBox); 298 299 VBox vb = new VBox(); 300 vb.setSpacing(5); 301 vb.getChildren().addAll(resetButtonsHBox, getAddItemHBox(), getRemoveItemHBox(), 302 applyCustomSelectionModel, applyCustomStringConverter, 303 flushCalledMethodsInSelectionModel, applyCustomCellFactory, 304 setAddingElementsOnShowing, 305 restoreDefaultOnShowingHandler, 306 populateComboBoxWithFontSizes, 307 getSetItemsNullHBox()); 308 setControllersContent(vb); 309 310 setPropertiesContent(tb); 311 } 312 313 private HBox getAddItemHBox() { 314 HBox hb = new HBox(); 315 Label lb = new Label("Add item"); 316 final TextField tf = new TextField(); 317 tf.setPrefWidth(50); 318 tf.setId(ADD_ITEM_TEXT_FIELD_ID); 319 Label atLb = new Label("at pos"); 320 final TextField tfPos = new TextField(); 321 tfPos.setPrefWidth(50); 322 tfPos.setId(ADD_ITEM_POSITION_TEXT_FIELD_ID); 323 Button bt = new Button("Add!"); 324 bt.setId(ADD_ITEM_BUTTON_ID); 325 bt.setOnAction(new EventHandler() { 326 public void handle(Event t) { 327 int index = Integer.parseInt(tfPos.getText()); 328 ((ComboBox) testedComboBox).getItems().add(index, tf.getText()); 329 } 330 }); 331 hb.getChildren().addAll(lb, tf, atLb, tfPos, bt); 332 return hb; 333 } 334 335 private HBox getRemoveItemHBox() { 336 HBox hb = new HBox(); 337 Label lb = new Label("From position"); 338 final TextField tf = new TextField("0"); 339 tf.setPrefWidth(50); 340 tf.setId(REMOVE_ITEM_POS_TEXT_FIELD_ID); 341 Button bt = new Button("Remove!"); 342 bt.setId(REMOVE_BUTTON_ID); 343 bt.setOnAction(new EventHandler() { 344 public void handle(Event t) { 345 int index = Integer.parseInt(tf.getText()); 346 ((ComboBox) testedComboBox).getItems().remove(index); 347 } 348 }); 349 hb.getChildren().addAll(lb, tf, bt); 350 return hb; 351 } 352 353 private HBox getSetItemsNullHBox() { 354 HBox hb = new HBox(); 355 356 Button bt = new Button("Set items null"); 357 bt.setId(SET_ITEMS_NULL_BUTTON_ID); 358 bt.setOnAction(new EventHandler() { 359 public void handle(Event t) { 360 ((ComboBox) testedComboBox).setItems(null); 361 } 362 }); 363 hb.getChildren().addAll(bt); 364 return hb; 365 } 366 367 class TextFieldListCell extends ListCell<String> { 368 369 public TextFieldListCell() { 370 setEditable(true); 371 } 372 373 @Override 374 public void startEdit() { 375 tb.incrementCounter(CUSTOM_CELL_START_EDIT_COUNTER); 376 super.startEdit(); 377 378 setText(null); 379 setGraphic(null); 380 } 381 382 @Override 383 public void cancelEdit() { 384 tb.incrementCounter(CUSTOM_CELL_CANCEL_EDIT_COUNTER); 385 super.cancelEdit(); 386 387 setText(null); 388 setGraphic(null); 389 } 390 391 @Override 392 public void updateItem(String item, boolean empty) { 393 tb.incrementCounter(CUSTOM_CELL_UPDATE_EDIT_COUNTER); 394 super.updateItem(item, empty); 395 396 if (empty) { 397 setText(null); 398 setGraphic(null); 399 } else { 400 if (isEditing()) { 401 tb.incrementCounter(CUSTOM_CELL_UPDATE_EDIT_FOR_EDITABLE_CELL_COUNTER); 402 } else { 403 setText(CUSTOM_CELL_FACTORY_ITEM_SUFFIX + item); 404 setGraphic(null); 405 } 406 } 407 } 408 } 409 } 410 411 /** 412 * MyMessageFormat wraps java.text.MessageFormat to provide a possibility to 413 * format only one object, in order to be used by 414 * javafx.util.converter.FormatStringConverter, because 415 * java.text.MessageFormat works only with array of objects. 416 * 417 * @see java.text.MessageFormat 418 * @see javafx.util.converter.FormatStringConverter 419 */ 420 public static class MyMessageFormat extends Format { 421 422 private MessageFormat fmt; 423 424 public MyMessageFormat(MessageFormat fmt) { 425 this.fmt = fmt; 426 } 427 428 @Override 429 public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) { 430 if (!obj.getClass().isAssignableFrom(Object[].class)) { 431 return fmt.format(new Object[]{obj}, toAppendTo, pos); 432 } else { 433 return fmt.format(obj, toAppendTo, pos); 434 } 435 } 436 437 @Override 438 public Object parseObject(String source, ParsePosition pos) { 439 Object parseObject = fmt.parseObject(source, pos); 440 if (parseObject.getClass().isAssignableFrom(Object[].class)) { 441 int length = ((Object[]) parseObject).length; 442 if (length == 1) { 443 return ((Object[]) parseObject)[0]; 444 } 445 } 446 return parseObject; 447 } 448 } 449 }