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 = ButtonBuilder.create().text("Apply custom selection model").id(APPLY_CUSTOM_SELECTION_MODEL_BUTTON_ID).build(); 171 applyCustomSelectionModel.setOnAction(new EventHandler<ActionEvent>() { 172 public void handle(ActionEvent t) { 173 testedComboBox.selectionModelProperty().setValue(selectionModel); 174 } 175 }); 176 177 Button applyCustomStringConverter = ButtonBuilder.create().text("Apply custom string converter").id(APPLY_CUSTOM_STRING_CONVERTER_BUTTON_ID).build(); 178 applyCustomStringConverter.setOnAction(new EventHandler<ActionEvent>() { 179 public void handle(ActionEvent t) { 180 testedComboBox.setConverter(new CustomStringConverter()); 181 } 182 }); 183 184 Button applyCustomCellFactory = ButtonBuilder.create().text("Apply custom cell factory").id(APPLY_CUSTOM_CELL_FACTORY_BUTTON_ID).build(); 185 applyCustomCellFactory.setOnAction(new EventHandler<ActionEvent>() { 186 public void handle(ActionEvent t) { 187 testedComboBox.setCellFactory(new Callback<ListView<String>, ListCell<String>>() { 188 public ListCell<String> call(ListView<String> p) { 189 tb.incrementCounter(CALLBACK_CALLED_ID); 190 return new TextFieldListCell(); 191 } 192 }); 193 } 194 }); 195 196 Button hardResetButton = ButtonBuilder.create().id(HARD_RESET_BUTTON_ID).text("Hard reset").build(); 197 hardResetButton.setOnAction(new EventHandler<ActionEvent>() { 198 public void handle(ActionEvent t) { 199 HBox hb = (HBox) getRoot(); 200 hb.getChildren().clear(); 201 prepareMainSceneStructure(); 202 prepareScene(); 203 } 204 }); 205 206 Button softResetButton = ButtonBuilder.create().id(SOFT_RESET_BUTTON_ID).text("Soft reset").build(); 207 softResetButton.setOnAction(new EventHandler<ActionEvent>() { 208 public void handle(ActionEvent t) { 209 tb.refresh(); 210 ComboBox<String> newOne = new ComboBox<String>(); 211 //testedComboBox.setItems(FXCollections.observableArrayList());//RT-18945 212 while (testedComboBox.getItems().size() != 0) { 213 testedComboBox.getItems().remove(0); 214 } 215 testedComboBox.setPrefHeight(newOne.getPrefHeight()); 216 testedComboBox.setPrefWidth(newOne.getPrefWidth()); 217 testedComboBox.setVisibleRowCount(newOne.getVisibleRowCount()); 218 testedComboBox.setPromptText(newOne.getPromptText()); 219 testedComboBox.setValue(null); 220 testedComboBox.setEditable(newOne.isEditable()); 221 testedComboBox.setVisible(newOne.isVisible()); 222 //testedComboBox.showingProperty().setValue(newOne.isShowing());//Showing is readonly from 2.1.0b10. 223 testedComboBox.setConverter(newOne.getConverter()); 224 testedComboBox.setCellFactory(newOne.getCellFactory()); 225 } 226 }); 227 228 HBox resetButtonsHBox = new HBox(); 229 resetButtonsHBox.getChildren().addAll(hardResetButton, softResetButton); 230 231 Button setAddingElementsOnShowing = ButtonBuilder.create() 232 .id(SET_ADDING_ELEMENTS_ON_SHOWING) 233 .text("Set adding elements on showing") 234 .build(); 235 236 setAddingElementsOnShowing.setOnAction(new EventHandler<ActionEvent>() { 237 public void handle(ActionEvent t) { 238 testedComboBox.setOnShowing(new EventHandler<Event>() { 239 public void handle(Event t) { 240 int index = ((ComboBox) testedComboBox).getItems().size(); 241 ((ComboBox) testedComboBox).getItems().add(index, INITIAL_VALUE); 242 243 tb.incrementCounter(SET_ON_SHOWING_COUNTER); 244 } 245 }); 246 } 247 }); 248 249 Button restoreDefaultOnShowingHandler = ButtonBuilder.create() 250 .id(RESTORE_ON_SHOWING_EVENT_HANDLER) 251 .text("Restore default onShowing handler") 252 .build(); 253 254 restoreDefaultOnShowingHandler.setOnAction(new EventHandler<ActionEvent>() { 255 public void handle(ActionEvent t) { 256 testedComboBox.setOnShowing(new EventHandler<Event>() { 257 public void handle(Event t) { 258 tb.incrementCounter(SET_ON_SHOWING_COUNTER); 259 } 260 }); 261 } 262 }); 263 264 Button populateComboBoxWithFontSizes = ButtonBuilder.create() 265 .id(POPULATE_COMBOBOX_WITH_FONT_SIZES) 266 .text("Populate ComboBox with font sizes") 267 .build(); 268 269 populateComboBoxWithFontSizes.setOnAction(new EventHandler<ActionEvent>() { 270 public void handle(ActionEvent t) { 271 272 testedComboBox.setCellFactory(new Callback<ListView<String>, ListCell<String>>() { 273 @Override 274 public ListCell<String> call(ListView<String> p) { 275 return new ListCell<String>() { 276 { 277 setContentDisplay(ContentDisplay.TEXT_ONLY); 278 } 279 280 @Override 281 protected void updateItem(String item, boolean empty) { 282 super.updateItem(item, empty); 283 284 if (item == null || empty) { 285 setText(null); 286 } else { 287 setText(item); 288 setFont(new Font(Double.valueOf(item))); 289 } 290 } 291 }; 292 } 293 }); 294 295 for (int i = INITIAL_FONT_SIZE; i <= MAX_FONT_SIZE; i += 2) { 296 testedComboBox.getItems().add(String.valueOf(i)); 297 } 298 } 299 }); 300 301 setTestedControl(testedComboBox); 302 303 VBox vb = new VBox(); 304 vb.setSpacing(5); 305 vb.getChildren().addAll(resetButtonsHBox, getAddItemHBox(), getRemoveItemHBox(), 306 applyCustomSelectionModel, applyCustomStringConverter, 307 flushCalledMethodsInSelectionModel, applyCustomCellFactory, 308 setAddingElementsOnShowing, 309 restoreDefaultOnShowingHandler, 310 populateComboBoxWithFontSizes, 311 getSetItemsNullHBox()); 312 setControllersContent(vb); 313 314 setPropertiesContent(tb); 315 } 316 317 private HBox getAddItemHBox() { 318 HBox hb = new HBox(); 319 Label lb = new Label("Add item"); 320 final TextField tf = TextFieldBuilder.create().prefWidth(50).id(ADD_ITEM_TEXT_FIELD_ID).build(); 321 Label atLb = new Label("at pos"); 322 final TextField tfPos = TextFieldBuilder.create().prefWidth(50).id(ADD_ITEM_POSITION_TEXT_FIELD_ID).build(); 323 Button bt = ButtonBuilder.create().text("Add!").id(ADD_ITEM_BUTTON_ID).build(); 324 bt.setOnAction(new EventHandler() { 325 public void handle(Event t) { 326 int index = Integer.parseInt(tfPos.getText()); 327 ((ComboBox) testedComboBox).getItems().add(index, tf.getText()); 328 } 329 }); 330 hb.getChildren().addAll(lb, tf, atLb, tfPos, bt); 331 return hb; 332 } 333 334 private HBox getRemoveItemHBox() { 335 HBox hb = new HBox(); 336 Label lb = new Label("From position"); 337 final TextField tf = TextFieldBuilder.create().text("0").prefWidth(50).id(REMOVE_ITEM_POS_TEXT_FIELD_ID).build(); 338 Button bt = ButtonBuilder.create().text("Remove!").id(REMOVE_BUTTON_ID).build(); 339 bt.setOnAction(new EventHandler() { 340 public void handle(Event t) { 341 int index = Integer.parseInt(tf.getText()); 342 ((ComboBox) testedComboBox).getItems().remove(index); 343 } 344 }); 345 hb.getChildren().addAll(lb, tf, bt); 346 return hb; 347 } 348 349 private HBox getSetItemsNullHBox() { 350 HBox hb = new HBox(); 351 352 Button bt = ButtonBuilder.create().text("Set items null").id(SET_ITEMS_NULL_BUTTON_ID).build(); 353 bt.setOnAction(new EventHandler() { 354 public void handle(Event t) { 355 ((ComboBox) testedComboBox).setItems(null); 356 } 357 }); 358 hb.getChildren().addAll(bt); 359 return hb; 360 } 361 362 class TextFieldListCell extends ListCell<String> { 363 364 public TextFieldListCell() { 365 setEditable(true); 366 } 367 368 @Override 369 public void startEdit() { 370 tb.incrementCounter(CUSTOM_CELL_START_EDIT_COUNTER); 371 super.startEdit(); 372 373 setText(null); 374 setGraphic(null); 375 } 376 377 @Override 378 public void cancelEdit() { 379 tb.incrementCounter(CUSTOM_CELL_CANCEL_EDIT_COUNTER); 380 super.cancelEdit(); 381 382 setText(null); 383 setGraphic(null); 384 } 385 386 @Override 387 public void updateItem(String item, boolean empty) { 388 tb.incrementCounter(CUSTOM_CELL_UPDATE_EDIT_COUNTER); 389 super.updateItem(item, empty); 390 391 if (empty) { 392 setText(null); 393 setGraphic(null); 394 } else { 395 if (isEditing()) { 396 tb.incrementCounter(CUSTOM_CELL_UPDATE_EDIT_FOR_EDITABLE_CELL_COUNTER); 397 } else { 398 setText(CUSTOM_CELL_FACTORY_ITEM_SUFFIX + item); 399 setGraphic(null); 400 } 401 } 402 } 403 } 404 } 405 406 /** 407 * MyMessageFormat wraps java.text.MessageFormat to provide a possibility to 408 * format only one object, in order to be used by 409 * javafx.util.converter.FormatStringConverter, because 410 * java.text.MessageFormat works only with array of objects. 411 * 412 * @see java.text.MessageFormat 413 * @see javafx.util.converter.FormatStringConverter 414 */ 415 public static class MyMessageFormat extends Format { 416 417 private MessageFormat fmt; 418 419 public MyMessageFormat(MessageFormat fmt) { 420 this.fmt = fmt; 421 } 422 423 @Override 424 public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) { 425 if (!obj.getClass().isAssignableFrom(Object[].class)) { 426 return fmt.format(new Object[]{obj}, toAppendTo, pos); 427 } else { 428 return fmt.format(obj, toAppendTo, pos); 429 } 430 } 431 432 @Override 433 public Object parseObject(String source, ParsePosition pos) { 434 Object parseObject = fmt.parseObject(source, pos); 435 if (parseObject.getClass().isAssignableFrom(Object[].class)) { 436 int length = ((Object[]) parseObject).length; 437 if (length == 1) { 438 return ((Object[]) parseObject)[0]; 439 } 440 } 441 return parseObject; 442 } 443 } 444 }