// Copyright 2012 Google Inc. All Rights Reserved.
//
// 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.google.collide.client.ui.menu;
import com.google.collide.client.util.Elements;
import elemental.events.EventListener;
import elemental.html.Element;
/**
* Simple tuple of a label and an action.
*
*/
public class MenuItem<T> {
/**
* Behavior invoked for a MenuItem.
*/
public interface MenuAction<T> {
/**
* @param context the context, or null if the action is being performed on the root
*/
public void doAction(T context);
}
/**
* Allows for custom rendering of a MenuItem.
*/
public interface MenuItemRenderer<T> {
/**
* Called when the menu item is to be created. Any returned element will
* automatically have the menuItem css style added.
*
* @return The menu item element.
*/
public Element render(MenuItem<T> item);
/**
* Called as the menu item is being shown so that it can make conditional
* modifications to the rendered menu item.
*/
public void onShowing(MenuItem<T> item, T context);
}
protected final MenuAction<T> action;
private final String label;
private boolean enabled = true;
private Element element;
private MenuItemRenderer<T> renderer;
public MenuItem(String label, MenuAction<T> action) {
this.action = action;
this.label = label;
}
/**
* @return the label
*/
public String getLabel() {
return label;
}
public void setMenuItemRenderer(MenuItemRenderer<T> renderer) {
this.renderer = renderer;
}
/**
* Dispatches the menu action if the MenuItem is enabled and we have a valid
* MenuAction to dispatch.
*
* A <code>null</code> context implies that this action refers to the Tree's
* root.
*/
public void dispatchAction(T context) {
if (isEnabled() && action != null) {
action.doAction(context);
}
}
public void dispatchShowing(T context) {
if (isEnabled() && renderer != null) {
renderer.onShowing(this, context);
}
}
/**
* @param enabled the enabled to set
*/
public void setEnabled(boolean enabled) {
this.enabled = enabled;
setEnabledStyle();
}
/**
* @return the enabled
*/
public boolean isEnabled() {
return enabled;
}
/**
* Creates the DOM structure of a given element, using the given event handler
* as the "appropriate" callback.
*
* @return the element of the new menu item
*/
public Element createDom(
String menuItemCss, EventListener clickListener, EventListener mouseDownListener) {
if (getElement() == null) {
if (renderer != null) {
element = renderer.render(this);
element.addClassName(menuItemCss);
} else {
element = Elements.createDivElement(menuItemCss);
element.setTextContent(getLabel());
}
if (clickListener != null) {
element.setOnClick(clickListener);
}
if (mouseDownListener != null) {
element.setOnMouseDown(mouseDownListener);
}
setEnabledStyle();
}
return element;
}
/**
* Gets the DOM element, or null if not initialized
*/
public Element getElement() {
return element;
}
private void setEnabledStyle() {
if (getElement() != null) {
element.setAttribute("enabled", enabled ? "true" : "false");
}
}
}