All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.vaadin.flow.component.contextmenu.MenuItemBase Maven / Gradle / Ivy

There is a newer version: 24.6.2
Show newest version
/*
 * Copyright 2000-2024 Vaadin Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.vaadin.flow.component.contextmenu;

import java.io.Serializable;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.stream.Collectors;

import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.HasAriaLabel;
import com.vaadin.flow.component.HasComponents;
import com.vaadin.flow.component.HasEnabled;
import com.vaadin.flow.component.HasText;
import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.dependency.JsModule;
import com.vaadin.flow.component.dependency.NpmPackage;

/**
 * Base class for item component used inside {@link ContextMenu}s.
 *
 * @param 
 *            the context menu type
 * @param 
 *            the menu item type
 * @param 
 *            the sub menu type
 * @author Vaadin Ltd.
 * @see MenuItem
 */
@SuppressWarnings("serial")
@Tag("vaadin-context-menu-item")
@NpmPackage(value = "@vaadin/polymer-legacy-adapter", version = "24.4.9")
@JsModule("@vaadin/polymer-legacy-adapter/style-modules.js")
public abstract class MenuItemBase, I extends MenuItemBase, S extends SubMenuBase>
        extends Component
        implements HasAriaLabel, HasComponents, HasEnabled, HasText {

    private static final String PRIVATE_THEME_ATTRIBUTE = "__theme";

    private final C contextMenu;
    private S subMenu;

    private boolean checkable = false;

    private Set themeNames = new LinkedHashSet<>();

    /**
     * Default constructor
     *
     * @param contextMenu
     *            the context menu to which this item belongs to
     */
    public MenuItemBase(C contextMenu) {
        this.contextMenu = contextMenu;
        getElement().addEventListener("click", e -> {
            if (checkable) {
                setChecked(!isChecked());
            }
        });

    }

    /**
     * Gets the context menu component that this item belongs to.
     *
     * @return the context-menu component
     */
    public C getContextMenu() {
        return contextMenu;
    }

    /**
     * Gets the sub menu API for this menu item. Adding content to the returned
     * sub menu makes this component a parent item which opens the sub menu
     * overlay. When the sub menu has no content, it won't be rendered.
     *
     * @return the sub menu that can be opened via this item
     */
    public S getSubMenu() {
        if (subMenu == null) {
            subMenu = createSubMenu();
        }
        return subMenu;
    }

    /**
     * Gets whether this item has a sub menu attached to it or not.
     *
     * @return {@code true} if this component has a sub menu with content inside
     *         it, {@code false} otherwise
     * @see #getSubMenu()
     */
    public boolean isParentItem() {
        return getSubMenu().getChildren().findAny().isPresent();
    }

    /**
     * Sets the checkable state of this menu item. A checkable item toggles a
     * checkmark icon when clicked. Changes in the checked state can be handled
     * in the item's click handler with {@link #isChecked()}.
     * 

* Setting a checked item un-checkable also makes it un-checked. * * @param checkable * {@code true} to enable toggling the checked-state of this menu * item by clicking, {@code false} to disable it. * @throws IllegalStateException * if setting a parent item checkable */ public void setCheckable(boolean checkable) { if (checkable && isParentItem()) { throw new IllegalStateException( "A checkable item cannot have a sub menu"); } this.checkable = checkable; if (!checkable) { setChecked(false); } } /** * Gets whether this item toggles a checkmark icon when clicked. * * @return the checkable state of the item * @see #setCheckable(boolean) */ public boolean isCheckable() { return checkable; } /** * Sets the checked state of this item. A checked item displays a checkmark * icon next to it. The checked state is also toggled by clicking the item. *

* Note that the item needs to be explicitly set as checkable via * {@link #setCheckable(boolean)} in order to check it. * * @param checked * {@code true} to check this item, {@code false} to un-check it * @throws IllegalStateException * if trying to check the item when it's checkable */ public void setChecked(boolean checked) { if (isChecked() == checked) { return; } if (!checkable && checked) { throw new IllegalStateException( "Trying to set a non-checkable menu item checked. " + "Use setCheckable() to make the item checkable first."); } getElement().setProperty("_checked", checked); executeJsWhenAttached( "window.Vaadin.Flow.contextMenuConnector.setChecked($0, $1)", getElement(), checked); } /** * Gets the checked state of this item. The item can be checked and * un-checked with {@link #setChecked(boolean)} or by clicking it when it is * checkable. A checked item displays a checkmark icon inside it. * * @return {@code true} if the item is checked, {@code false} otherwise * @see #setCheckable(boolean) * @see #setChecked(boolean) */ public boolean isChecked() { return getElement().getProperty("_checked", false); } /** * Sets the keep open state of this menu item. An item that marked as keep * open prevents menu from closing when clicked. * * @param keepOpen * {@code true} to enable keeping the menu open when toggle this * item selection, {@code false} to disable it. */ public void setKeepOpen(boolean keepOpen) { if (keepOpen && isParentItem()) { throw new IllegalStateException( "A keepOpen item cannot have a sub menu"); } getElement().setProperty("_keepOpen", keepOpen); executeJsWhenAttached( "window.Vaadin.Flow.contextMenuConnector.setKeepOpen($0, $1)", getElement(), keepOpen); } /** * Gets whether clicking this item keeps the menu open. * * @return the keep open state of the item * @see #setKeepOpen(boolean) */ public boolean isKeepOpen() { return getElement().getProperty("_keepOpen", false); } /** * Adds one or more theme names to this item. Multiple theme names can be * specified by using multiple parameters. * * @param themeNames * the theme name or theme names to be added to the item */ public void addThemeNames(String... themeNames) { this.themeNames.addAll(Arrays.asList(themeNames)); setThemeName(); } /** * Removes one or more theme names from this item. Multiple theme names can * be specified by using multiple parameters. * * @param themeNames * the theme name or theme names to be removed from the item */ public void removeThemeNames(String... themeNames) { this.themeNames.removeAll(Arrays.asList(themeNames)); setThemeName(); } /** * Checks if the item has the given theme name. * * @param themeName * the theme name to check for * @return true if the item has the given theme name, * false otherwise */ public boolean hasThemeName(String themeName) { return themeNames.contains(themeName); } private void setThemeName() { String themeName = themeNames.stream().collect(Collectors.joining(" ")); if (themeName != null) { getElement().setProperty(PRIVATE_THEME_ATTRIBUTE, themeName); } else { getElement().removeProperty(PRIVATE_THEME_ATTRIBUTE); } executeJsWhenAttached( "window.Vaadin.Flow.contextMenuConnector.setTheme($0, $1)", getElement(), themeName); } protected abstract S createSubMenu(); protected void executeJsWhenAttached(String expression, Serializable... parameters) { getElement().getNode().runWhenAttached(ui -> ui.beforeClientResponse( this, context -> ui.getPage().executeJs(expression, parameters))); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy