javafx.scene.control.ContextMenu Maven / Gradle / Ivy
/*
* Copyright (c) 2010, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javafx.scene.control;
import com.sun.javafx.beans.IDProperty;
import com.sun.javafx.collections.TrackableObservableList;
import com.sun.javafx.util.Utils;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ObjectPropertyBase;
import javafx.collections.ListChangeListener.Change;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.geometry.HPos;
import javafx.geometry.Point2D;
import javafx.geometry.Side;
import javafx.geometry.VPos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.skin.ContextMenuSkin;
import javafx.stage.Window;
/**
*
* A popup control containing an ObservableList of menu items. The {@link #getItems() items}
* ObservableList allows for any {@link MenuItem} type to be inserted,
* including its subclasses {@link Menu}, {@link MenuItem}, {@link RadioMenuItem}, {@link CheckMenuItem} and
* {@link CustomMenuItem}. If an arbitrary Node needs to be
* inserted into a menu, a CustomMenuItem can be used. One exception to this general rule is that
* {@link SeparatorMenuItem} could be used for inserting a separator.
*
* A common use case for this class is creating and showing context menus to
* users. To create a context menu using ContextMenu you can do the
* following:
*
final ContextMenu contextMenu = new ContextMenu();
contextMenu.setOnShowing(new EventHandler<WindowEvent>() {
public void handle(WindowEvent e) {
System.out.println("showing");
}
});
contextMenu.setOnShown(new EventHandler<WindowEvent>() {
public void handle(WindowEvent e) {
System.out.println("shown");
}
});
MenuItem item1 = new MenuItem("About");
item1.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
System.out.println("About");
}
});
MenuItem item2 = new MenuItem("Preferences");
item2.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
System.out.println("Preferences");
}
});
contextMenu.getItems().addAll(item1, item2);
final TextField textField = new TextField("Type Something");
textField.setContextMenu(contextMenu);
*
*
*
* {@link Control#setContextMenu(javafx.scene.control.ContextMenu) } convenience
* method can be used to set a context menu on on any control. The example above results in the
* context menu being displayed on the right {@link javafx.geometry.Side Side}
* of the TextField. Alternatively, an event handler can also be set on the control
* to invoke the context menu as shown below.
*
textField.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
contextMenu.show(textField, Side.BOTTOM, 0, 0);
}
});
Group root = (Group) scene.getRoot();
root.getChildren().add(textField);
*
* In this example, the context menu is shown when the user clicks on the
* {@link javafx.scene.control.Button Button} (of course, you should use the
* {@link MenuButton} control to do this rather than doing the above).
*
* Note that the show function used in the code sample
* above will result in the ContextMenu appearing directly beneath the
* TextField. You can vary the {@link javafx.geometry.Side Side} to get the results you expect.
*
* @see MenuItem
* @see Menu
* @since JavaFX 2.0
*/
@IDProperty("id")
public class ContextMenu extends PopupControl {
/* *************************************************************************
* *
* Fields *
* *
**************************************************************************/
private boolean showRelativeToWindow = false;
/* *************************************************************************
* *
* Constructors *
* *
**************************************************************************/
/**
* Create a new ContextMenu
*/
public ContextMenu() {
getStyleClass().setAll(DEFAULT_STYLE_CLASS);
setAutoHide(true);
setConsumeAutoHidingEvents(false);
}
/**
* Create a new ContextMenu initialized with the given items
* @param items the list of menu items
*/
public ContextMenu(MenuItem... items) {
this();
this.items.addAll(items);
}
/* *************************************************************************
* *
* Properties *
* *
**************************************************************************/
/**
* Callback function to be informed when an item contained within this
* {@code ContextMenu} has been activated. The current implementation informs
* all parent menus as well, so that it is not necessary to listen to all
* sub menus for events.
*/
private ObjectProperty> onAction = new ObjectPropertyBase>() {
@Override protected void invalidated() {
setEventHandler(ActionEvent.ACTION, get());
}
@Override
public Object getBean() {
return ContextMenu.this;
}
@Override
public String getName() {
return "onAction";
}
};
public final void setOnAction(EventHandler value) { onActionProperty().set(value); }
public final EventHandler getOnAction() { return onActionProperty().get(); }
public final ObjectProperty> onActionProperty() { return onAction; }
private final ObservableList