diff --git a/javafx-ui-controls/src/javafx/scene/control/ComboBoxBase.java b/javafx-ui-controls/src/javafx/scene/control/ComboBoxBase.java --- a/javafx-ui-controls/src/javafx/scene/control/ComboBoxBase.java +++ b/javafx-ui-controls/src/javafx/scene/control/ComboBoxBase.java @@ -30,6 +30,7 @@ import javafx.event.ActionEvent; import javafx.event.Event; import javafx.event.EventHandler; +import javafx.event.EventType; /** * Abstract base class for ComboBox-like controls. A ComboBox typically has @@ -65,6 +66,46 @@ */ public abstract class ComboBoxBase extends Control { + + /*************************************************************************** + * * + * Static properties and methods * + * * + **************************************************************************/ + + /** + *

Called prior to the ComboBox showing its popup/display after the user + * has clicked or otherwise interacted with the ComboBox. + */ + public static final EventType ON_SHOWING = + new EventType(Event.ANY, "ON_SHOWING"); + + /** + *

Called after the ComboBox has shown its popup/display. + */ + public static final EventType ON_SHOWN = + new EventType(Event.ANY, "ON_SHOWN"); + + /** + *

Called when the ComboBox popup/display will be hidden. + */ + public static final EventType ON_HIDING = + new EventType(Event.ANY, "ON_HIDING"); + + /** + *

Called when the ComboBox popup/display has been hidden. + */ + public static final EventType ON_HIDDEN = + new EventType(Event.ANY, "ON_HIDDEN"); + + + + /*************************************************************************** + * * + * Constructors * + * * + **************************************************************************/ + /** * Creates a default ComboBoxBase instance. */ @@ -72,7 +113,14 @@ getStyleClass().add(DEFAULT_STYLE_CLASS); } - + + + /*************************************************************************** + * * + * Properties * + * * + **************************************************************************/ + // --- value /** * The value of this ComboBox is defined as the selected item if the input @@ -127,7 +175,12 @@ public ReadOnlyBooleanProperty showingProperty() { return showingPropertyImpl().getReadOnlyProperty(); } public final boolean isShowing() { return showingPropertyImpl().get(); } private void setShowing(boolean value) { + // these events will not fire if the showing property is bound + Event.fireEvent(this, value ? new Event(ComboBoxBase.ON_SHOWING) : + new Event(ComboBoxBase.ON_HIDING)); showingPropertyImpl().set(value); + Event.fireEvent(this, value ? new Event(ComboBoxBase.ON_SHOWN) : + new Event(ComboBoxBase.ON_HIDDEN)); } private ReadOnlyBooleanWrapper showingPropertyImpl() { if (showing == null) { @@ -220,6 +273,94 @@ }; + // --- On Showing + public final ObjectProperty> onShowingProperty() { return onShowing; } + /** + * Called just prior to the {@code ComboBoxBase} popup/display being shown, + */ + public final void setOnShowing(EventHandler value) { onShowingProperty().set(value); } + public final EventHandler getOnShowing() { return onShowingProperty().get(); } + private ObjectProperty> onShowing = new ObjectPropertyBase>() { + @Override protected void invalidated() { + setEventHandler(ON_SHOWING, get()); + } + + @Override public Object getBean() { + return ComboBoxBase.this; + } + + @Override public String getName() { + return "onShowing"; + } + }; + + + // -- On Shown + public final ObjectProperty> onShownProperty() { return onShown; } + /** + * Called just after the {@link ComboBoxBase} popup/display is shown. + */ + public final void setOnShown(EventHandler value) { onShownProperty().set(value); } + public final EventHandler getOnShown() { return onShownProperty().get(); } + private ObjectProperty> onShown = new ObjectPropertyBase>() { + @Override protected void invalidated() { + setEventHandler(ON_SHOWN, get()); + } + + @Override public Object getBean() { + return ComboBoxBase.this; + } + + @Override public String getName() { + return "onShown"; + } + }; + + + // --- On Hiding + public final ObjectProperty> onHidingProperty() { return onHiding; } + /** + * Called just prior to the {@link ComboBox} popup/display being hidden. + */ + public final void setOnHiding(EventHandler value) { onHidingProperty().set(value); } + public final EventHandler getOnHiding() { return onHidingProperty().get(); } + private ObjectProperty> onHiding = new ObjectPropertyBase>() { + @Override protected void invalidated() { + setEventHandler(ON_HIDING, get()); + } + + @Override public Object getBean() { + return ComboBoxBase.this; + } + + @Override public String getName() { + return "onHiding"; + } + }; + + + // --- On Hidden + public final ObjectProperty> onHiddenProperty() { return onHidden; } + /** + * Called just after the {@link ComboBoxBase} popup/display has been hidden. + */ + public final void setOnHidden(EventHandler value) { onHiddenProperty().set(value); } + public final EventHandler getOnHidden() { return onHiddenProperty().get(); } + private ObjectProperty> onHidden = new ObjectPropertyBase>() { + @Override protected void invalidated() { + setEventHandler(ON_HIDDEN, get()); + } + + @Override public Object getBean() { + return ComboBoxBase.this; + } + + @Override public String getName() { + return "onHidden"; + } + }; + + /*************************************************************************** * * * Methods * @@ -242,7 +383,9 @@ * Closes the popup / dialog that was shown when {@link #show()} was called. */ public void hide() { - setShowing(false); + if (isShowing()) { + setShowing(false); + } } /** diff --git a/javafx-ui-controls/src/javafx/scene/control/Menu.java b/javafx-ui-controls/src/javafx/scene/control/Menu.java --- a/javafx-ui-controls/src/javafx/scene/control/Menu.java +++ b/javafx-ui-controls/src/javafx/scene/control/Menu.java @@ -162,6 +162,8 @@ private void setShowing(boolean value) { if (getItems().size() == 0) return; + + // these events will not fire if the showing property is bound Event.fireEvent(this, (value) ? new Event(Menu.ON_SHOWING) : new Event(Menu.ON_HIDING)); showingPropertyImpl().set(value);