Spec-Zone .ru
спецификации, руководства, описания, API
|
001/* 002 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. Oracle designates this 008 * particular file as subject to the "Classpath" exception as provided 009 * by Oracle in the LICENSE file that accompanied this code. 010 * 011 * This code is distributed in the hope that it will be useful, but WITHOUT 012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 014 * version 2 for more details (a copy is included in the LICENSE file that 015 * accompanied this code). 016 * 017 * You should have received a copy of the GNU General Public License version 018 * 2 along with this work; if not, write to the Free Software Foundation, 019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 020 * 021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 022 * or visit www.oracle.com if you need additional information or have any 023 * questions. 024 */ 025 026package javafx.scene.control; 027 028import javafx.css.PseudoClass; 029import javafx.beans.property.*; 030import javafx.event.ActionEvent; 031import javafx.event.Event; 032import javafx.event.EventHandler; 033import javafx.event.EventType; 034 035/** 036 * Abstract base class for ComboBox-like controls. A ComboBox typically has 037 * a button that, when clicked, will pop up some means of allowing a user 038 * to select one or more values (depending on the implementation). This base 039 * class makes no assumptions about what happens when the {@link #show()} and 040 * {@link #hide()} methods are called, however commonly this results in either 041 * a popup or dialog appearing that allows for the user to provide the 042 * required information. 043 * 044 * <p>A ComboBox has a {@link #valueProperty() value} property that represents 045 * the current user input. This may be based on a selection from a drop-down list, 046 * or it may be from user input when the ComboBox is 047 * {@link #editableProperty() editable}. 048 * 049 * <p>An {@link #editableProperty() editable} ComboBox is one which provides some 050 * means for an end-user to provide input for values that are not otherwise 051 * options available to them. For example, in the {@link ComboBox} implementation, 052 * an editable ComboBox provides a {@link TextField} that may be typed into. 053 * As mentioned above, when the user commits textual input into the textfield 054 * (commonly by pressing the Enter keyboard key), the 055 * {@link #valueProperty() value} property will be updated. 056 * 057 * <p>The purpose of the separation between this class and, say, {@link ComboBox} 058 * is to allow for ComboBox-like controls that do not necessarily pop up a list 059 * of items. Examples of other implementations include color pickers, calendar 060 * pickers, etc. The {@link ComboBox} class provides the default, and most commonly 061 * expected implementation. Refer to that classes javadoc for more information. 062 * 063 * @see ComboBox 064 * @param <T> The type of the value that has been selected or otherwise 065 * entered in to this ComboBox. 066 */ 067public abstract class ComboBoxBase<T> extends Control { 068 069 070 /*************************************************************************** 071 * * 072 * Static properties and methods * 073 * * 074 **************************************************************************/ 075 076 /** 077 * <p>Called prior to the ComboBox showing its popup/display after the user 078 * has clicked or otherwise interacted with the ComboBox. 079 */ 080 public static final EventType<Event> ON_SHOWING = 081 new EventType<Event>(Event.ANY, "COMBO_BOX_BASE_ON_SHOWING"); 082 083 /** 084 * <p>Called after the ComboBox has shown its popup/display. 085 */ 086 public static final EventType<Event> ON_SHOWN = 087 new EventType<Event>(Event.ANY, "COMBO_BOX_BASE_ON_SHOWN"); 088 089 /** 090 * <p>Called when the ComboBox popup/display <b>will</b> be hidden. 091 */ 092 public static final EventType<Event> ON_HIDING = 093 new EventType<Event>(Event.ANY, "COMBO_BOX_BASE_ON_HIDING"); 094 095 /** 096 * <p>Called when the ComboBox popup/display has been hidden. 097 */ 098 public static final EventType<Event> ON_HIDDEN = 099 new EventType<Event>(Event.ANY, "COMBO_BOX_BASE_ON_HIDDEN"); 100 101 102 103 /*************************************************************************** 104 * * 105 * Constructors * 106 * * 107 **************************************************************************/ 108 109 /** 110 * Creates a default ComboBoxBase instance. 111 */ 112 public ComboBoxBase() { 113 getStyleClass().add(DEFAULT_STYLE_CLASS); 114 } 115 116 void valueInvalidated() { 117 fireEvent(new ActionEvent()); 118 } 119 120 /*************************************************************************** 121 * * 122 * Properties * 123 * * 124 **************************************************************************/ 125 126 // --- value 127 /** 128 * The value of this ComboBox is defined as the selected item if the input 129 * is not editable, or if it is editable, the most recent user action: 130 * either the value input by the user, or the last selected item. 131 */ 132 public ObjectProperty<T> valueProperty() { return value; } 133 private ObjectProperty<T> value = new SimpleObjectProperty<T>(this, "value") { 134 T oldValue; 135 136 @Override protected void invalidated() { 137 super.invalidated(); 138 T newValue = get(); 139 140 if ((oldValue == null && newValue != null) || 141 oldValue != null && ! oldValue.equals(newValue)) { 142 valueInvalidated(); 143 } 144 145 oldValue = newValue; 146 } 147 }; 148 public final void setValue(T value) { valueProperty().set(value); } 149 public final T getValue() { return valueProperty().get(); } 150 151 152 // --- editable 153 /** 154 * Specifies whether the ComboBox allows for user input. When editable is 155 * true, the ComboBox has a text input area that a user may type in to. This 156 * input is then available via the {@link #valueProperty() value} property. 157 * 158 * <p>Note that when the editable property changes, the value property is 159 * reset, along with any other relevant state. 160 */ 161 public BooleanProperty editableProperty() { return editable; } 162 public final void setEditable(boolean value) { editableProperty().set(value); } 163 public final boolean isEditable() { return editableProperty().get(); } 164 private BooleanProperty editable = new SimpleBooleanProperty(this, "editable", false) { 165 @Override protected void invalidated() { 166 pseudoClassStateChanged(PSEUDO_CLASS_EDITABLE, get()); 167 } 168 }; 169 170 171 // --- showing 172 /** 173 * Represents the current state of the ComboBox popup, and whether it is 174 * currently visible on screen (although it may be hidden behind other windows). 175 */ 176 private ReadOnlyBooleanWrapper showing; 177 public ReadOnlyBooleanProperty showingProperty() { return showingPropertyImpl().getReadOnlyProperty(); } 178 public final boolean isShowing() { return showingPropertyImpl().get(); } 179 private void setShowing(boolean value) { 180 // these events will not fire if the showing property is bound 181 Event.fireEvent(this, value ? new Event(ComboBoxBase.ON_SHOWING) : 182 new Event(ComboBoxBase.ON_HIDING)); 183 showingPropertyImpl().set(value); 184 Event.fireEvent(this, value ? new Event(ComboBoxBase.ON_SHOWN) : 185 new Event(ComboBoxBase.ON_HIDDEN)); 186 } 187 private ReadOnlyBooleanWrapper showingPropertyImpl() { 188 if (showing == null) { 189 showing = new ReadOnlyBooleanWrapper(false) { 190 @Override protected void invalidated() { 191 pseudoClassStateChanged(PSEUDO_CLASS_SHOWING, get()); 192 } 193 194 @Override 195 public Object getBean() { 196 return ComboBoxBase.this; 197 } 198 199 @Override 200 public String getName() { 201 return "showing"; 202 } 203 }; 204 } 205 return showing; 206 } 207 208 209 // --- prompt text 210 /** 211 * The {@code ComboBox} prompt text to display, or <tt>null</tt> if no 212 * prompt text is displayed. Prompt text is not displayed in all circumstances, 213 * it is dependent upon the subclasses of ComboBoxBase to clarify when 214 * promptText will be shown. 215 */ 216 private StringProperty promptText = new SimpleStringProperty(this, "promptText", "") { 217 @Override protected void invalidated() { 218 // Strip out newlines 219 String txt = get(); 220 if (txt != null && txt.contains("\n")) { 221 txt = txt.replace("\n", ""); 222 set(txt); 223 } 224 } 225 }; 226 public final StringProperty promptTextProperty() { return promptText; } 227 public final String getPromptText() { return promptText.get(); } 228 public final void setPromptText(String value) { promptText.set(value); } 229 230 231 // --- armed 232 /** 233 * Indicates that the ComboBox has been "armed" such that a mouse release 234 * will cause the ComboBox {@link #show()} method to be invoked. This is 235 * subtly different from pressed. Pressed indicates that the mouse has been 236 * pressed on a Node and has not yet been released. {@code arm} however 237 * also takes into account whether the mouse is actually over the 238 * ComboBox and pressed. 239 */ 240 public BooleanProperty armedProperty() { return armed; } 241 private final void setArmed(boolean value) { armedProperty().set(value); } 242 public final boolean isArmed() { return armedProperty().get(); } 243 private BooleanProperty armed = new SimpleBooleanProperty(this, "armed", false) { 244 @Override protected void invalidated() { 245 pseudoClassStateChanged(PSEUDO_CLASS_ARMED, get()); 246 } 247 }; 248 249 250 // --- On Action 251 /** 252 * The ComboBox action, which is invoked whenever the ComboBox 253 * {@link #valueProperty() value} property is changed. This 254 * may be due to the value property being programmatically changed, when the 255 * user selects an item in a popup list or dialog, or, in the case of 256 * {@link #editableProperty() editable} ComboBoxes, it may be when the user 257 * provides their own input (be that via a {@link TextField} or some other 258 * input mechanism. 259 */ 260 public final ObjectProperty<EventHandler<ActionEvent>> onActionProperty() { return onAction; } 261 public final void setOnAction(EventHandler<ActionEvent> value) { onActionProperty().set(value); } 262 public final EventHandler<ActionEvent> getOnAction() { return onActionProperty().get(); } 263 private ObjectProperty<EventHandler<ActionEvent>> onAction = new ObjectPropertyBase<EventHandler<ActionEvent>>() { 264 @Override protected void invalidated() { 265 setEventHandler(ActionEvent.ACTION, get()); 266 } 267 268 @Override 269 public Object getBean() { 270 return ComboBoxBase.this; 271 } 272 273 @Override 274 public String getName() { 275 return "onAction"; 276 } 277 }; 278 279 280 // --- On Showing 281 public final ObjectProperty<EventHandler<Event>> onShowingProperty() { return onShowing; } 282 /** 283 * Called just prior to the {@code ComboBoxBase} popup/display being shown, 284 * @since 2.2 285 */ 286 public final void setOnShowing(EventHandler<Event> value) { onShowingProperty().set(value); } 287 public final EventHandler<Event> getOnShowing() { return onShowingProperty().get(); } 288 private ObjectProperty<EventHandler<Event>> onShowing = new ObjectPropertyBase<EventHandler<Event>>() { 289 @Override protected void invalidated() { 290 setEventHandler(ON_SHOWING, get()); 291 } 292 293 @Override public Object getBean() { 294 return ComboBoxBase.this; 295 } 296 297 @Override public String getName() { 298 return "onShowing"; 299 } 300 }; 301 302 303 // -- On Shown 304 public final ObjectProperty<EventHandler<Event>> onShownProperty() { return onShown; } 305 /** 306 * Called just after the {@link ComboBoxBase} popup/display is shown. 307 * @since 2.2 308 */ 309 public final void setOnShown(EventHandler<Event> value) { onShownProperty().set(value); } 310 public final EventHandler<Event> getOnShown() { return onShownProperty().get(); } 311 private ObjectProperty<EventHandler<Event>> onShown = new ObjectPropertyBase<EventHandler<Event>>() { 312 @Override protected void invalidated() { 313 setEventHandler(ON_SHOWN, get()); 314 } 315 316 @Override public Object getBean() { 317 return ComboBoxBase.this; 318 } 319 320 @Override public String getName() { 321 return "onShown"; 322 } 323 }; 324 325 326 // --- On Hiding 327 public final ObjectProperty<EventHandler<Event>> onHidingProperty() { return onHiding; } 328 /** 329 * Called just prior to the {@link ComboBox} popup/display being hidden. 330 * @since 2.2 331 */ 332 public final void setOnHiding(EventHandler<Event> value) { onHidingProperty().set(value); } 333 public final EventHandler<Event> getOnHiding() { return onHidingProperty().get(); } 334 private ObjectProperty<EventHandler<Event>> onHiding = new ObjectPropertyBase<EventHandler<Event>>() { 335 @Override protected void invalidated() { 336 setEventHandler(ON_HIDING, get()); 337 } 338 339 @Override public Object getBean() { 340 return ComboBoxBase.this; 341 } 342 343 @Override public String getName() { 344 return "onHiding"; 345 } 346 }; 347 348 349 // --- On Hidden 350 public final ObjectProperty<EventHandler<Event>> onHiddenProperty() { return onHidden; } 351 /** 352 * Called just after the {@link ComboBoxBase} popup/display has been hidden. 353 * @since 2.2 354 */ 355 public final void setOnHidden(EventHandler<Event> value) { onHiddenProperty().set(value); } 356 public final EventHandler<Event> getOnHidden() { return onHiddenProperty().get(); } 357 private ObjectProperty<EventHandler<Event>> onHidden = new ObjectPropertyBase<EventHandler<Event>>() { 358 @Override protected void invalidated() { 359 setEventHandler(ON_HIDDEN, get()); 360 } 361 362 @Override public Object getBean() { 363 return ComboBoxBase.this; 364 } 365 366 @Override public String getName() { 367 return "onHidden"; 368 } 369 }; 370 371 372 /*************************************************************************** 373 * * 374 * Methods * 375 * * 376 **************************************************************************/ 377 378 /** 379 * Requests that the ComboBox display the popup aspect of the user interface. 380 * As mentioned in the {@link ComboBoxBase} class javadoc, what is actually 381 * shown when this method is called is undefined, but commonly it is some 382 * form of popup or dialog window. 383 */ 384 public void show() { 385 if (!isDisabled()) { 386 setShowing(true); 387 } 388 } 389 390 /** 391 * Closes the popup / dialog that was shown when {@link #show()} was called. 392 */ 393 public void hide() { 394 if (isShowing()) { 395 setShowing(false); 396 } 397 } 398 399 /** 400 * Arms the ComboBox. An armed ComboBox will show a popup list on the next 401 * expected UI gesture. 402 * 403 * @expert This function is intended to be used by experts, primarily 404 * by those implementing new Skins or Behaviors. It is not common 405 * for developers or designers to access this function directly. 406 */ 407 public void arm() { 408 if (! armedProperty().isBound()) { 409 setArmed(true); 410 } 411 } 412 413 /** 414 * Disarms the ComboBox. See {@link #arm()}. 415 * 416 * @expert This function is intended to be used by experts, primarily 417 * by those implementing new Skins or Behaviors. It is not common 418 * for developers or designers to access this function directly. 419 */ 420 public void disarm() { 421 if (! armedProperty().isBound()) { 422 setArmed(false); 423 } 424 } 425 426 /*************************************************************************** 427 * * 428 * Stylesheet Handling * 429 * * 430 **************************************************************************/ 431 432 private static final String DEFAULT_STYLE_CLASS = "combo-box-base"; 433 434 private static final PseudoClass PSEUDO_CLASS_EDITABLE = 435 PseudoClass.getPseudoClass("editable"); 436 private static final PseudoClass PSEUDO_CLASS_SHOWING = 437 PseudoClass.getPseudoClass("showing"); 438 private static final PseudoClass PSEUDO_CLASS_ARMED = 439 PseudoClass.getPseudoClass("armed"); 440 441}