/*
* Copyright 2010 Google Inc.
*
* 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 org.waveprotocol.wave.client.widget.menu;
/**
* Representation of a menu item.
* This representation is totally independent from its rendering.
* A collection of <code>MenuNode</code>s is contained inside a <code>MenuBranch</code>.
* A <code>MenuNode</code> can:
* <ul>
* <li>represent a separator symbol inside a menu.
* <li>be of kind HTML hyperlink, where it is meant to point to a URL.
* <li>have a sub-menu associated to itself.
* <li>launch an action when it is being clicked.
* <li>have a tooltip associated to itself.
* </ul>
* <p>
*
* @see MenuBranch
*/
public class MenuNode {
/**
* This type is different to GWT's command to help the compiler figure out
* that its execute method is only ever called from one place.
*/
public interface MenuCommand {
/**
* Causes the Command to perform its encapsulated behavior. This function
* must only be called by TopPanel.RunAsyncCommand to ensure that all menu
* items end up behind a single runAsync split point.
*/
void execute();
}
/**
* @see MenuNode#getPopupDebugClassName()
*/
private final String popupDebugClassName;
/**
* @see MenuNode#getCommand()
*/
private final MenuCommand command;
/**
* @see MenuNode#getSubMenu()
*/
private final MenuBranch subMenu;
/**
* @see MenuNode#getText()
*/
private final String text;
/**
* @see MenuNode#isHTML()
*/
private final boolean isHTML;
private final String url;
/**
* @see MenuNode#url
*/
private final String anchor;
/**
* @see MenuNode#url
*/
private final String target;
/**
* @see MenuNode#isSeparator()
*/
private final boolean isSeparator;
/**
* @see MenuNode#isNew()
* NOTE(user): This would be final, except we've got enough constructors...
* Builder pattern anyone?
*/
private boolean isNew = false;
/**
* @see MenuNode#getId()
*/
private final String id;
/**
* Constructs a menu item which is the head of a sub-menu.
* @param text is the name to be rendered.
* @param subMenu is the sub-menu attached to this menu item.
*/
public MenuNode(String text, MenuBranch subMenu) {
this(text, "", "", "", false, false, null, null, subMenu, null);
}
/**
* Constructs a menu item which is the head of a sub-menu.
* @param text is the name to be rendered.
* @param subMenu is the sub-menu attached to this menu item.
* @param id {@link MenuNode#getId()}
*/
public MenuNode(String text, MenuBranch subMenu, String id, String popupDebugClassName) {
this(text, "", "", "", false, false, id, null, subMenu, popupDebugClassName);
}
/**
* Constructs a simple menu item from its name and associated action.
* @param text is the name to be rendered.
* @param command is the action to be launched when this item is clicked.
*/
public MenuNode(String text, MenuCommand command) {
this(text, "", "", "", false, false, null, command, null, null);
}
/**
* Constructs a menu item of kind hyperlink along with associated action.
* @param anchor is the name to be rendered as hyperlink.
* @param url is the URL that the hyperlink is pointing to.
* @param command is the action to be launched when this item is clicked.
*/
public MenuNode(String anchor, String url, MenuCommand command) {
this("", anchor, url, "", true, false, null, command, null, null);
}
/**
* Constructs a menu item that opens the referenced url at the specified target.
* @param anchor
* @param url
*/
public static MenuNode openUrlInNewWindow(String anchor, String url) {
return new MenuNode("", anchor, url, "_blank", false, false, null, null, null, null);
}
/**
* Constructs a menu item with all its member variables initially supplied.
*/
private MenuNode(String text, String anchor, String url, String target, boolean asHTML,
boolean isSeparator, String id, MenuCommand command, MenuBranch subMenu,
String popupDebugClassName) {
this.text = text;
this.anchor = anchor;
this.url = url;
this.target = target;
this.isHTML = asHTML;
this.isSeparator = isSeparator;
this.id = id;
this.command = command;
this.subMenu = subMenu;
this.popupDebugClassName = popupDebugClassName;
}
/**
* Creates a menu item of kind separator symbol.
*/
public static MenuNode createDivider() {
return new MenuNode("", "", "", "", false, true, null, null, null, null);
}
/**
* @return {@link MenuCommand} to be launched when this menu item is being clicked.
* If <code>isSeparator</code> is <code>true</code>, this variable is ignored.
* If there is a sub-menu, this <code>command</code> variable is automatically created,
* so that it can trigger the appropriate popup sub-menu.
*/
public MenuCommand getCommand() {
return command;
}
/**
* A globally unique identifier for this menu item.
* With respect to the DOM, this should be added as an id attribute on the anchor.
*
* @return The id of the node, or null if no id given.
*/
public String getId() {
return id;
}
/**
* debugClassName to be associated to a popup Window if this item ever creates
* one.
*
* @return The debugClassName of the node.
*/
public String getPopupDebugClassName() {
return popupDebugClassName;
}
/**
* @return {@link MenuBranch} the optional sub-menu attached to this menu item.
*/
public MenuBranch getSubMenu() {
return subMenu;
}
/**
* @return String of the text to be rendered.
*/
public String getText() {
return text;
}
/**
* @return boolean equals <code>true</code> when the text member variable has to
* be rendered as HTML.
*/
public boolean isHTML() {
return isHTML;
}
/**
* @return the URL to which the MenuNode links.
* When <code>url</code> is set (which is when it contains at least 1 character):
* <ul>
* <li><code>isHTML</code> is automatically set to <code>true</code>.
* <li><code>text</code> is automatically filled so that it does represent a
* hyperlink when rendered as HTML.
* </ul>
* <p>
* <code>url</code>, <code>anchor</code> and <code>target</code> go together.
* <li><code>url</code> combined <code>target</code> is the address pointed by the hyperlink.
* <li><code>anchor</code> is the name to be rendered for the hyperlink.
*/
public String getUrl() {
return url;
}
/**
* @return the name to be rendered for the hyperlink.
* @see MenuNode#getUrl()
*/
public String getAnchor() {
return anchor;
}
/**
* @return the target frame for the address pointed by the hyperlink
* @see MenuNode#getUrl()
*/
public String getTarget() {
return target;
}
/**
* @return boolean equals <code>true</code> when this menu item is just a divider.
* and in that case the other variables are therefore being ignored.
*/
public boolean isSeparator() {
return isSeparator;
}
/**
* Sets that the menu node is for a new feature.
* @return this, for convenience.
*/
public MenuNode setNew() {
this.isNew = true;
return this;
}
/**
* @return boolean <code>true</code> if the menu item is new. This is to
* announce new features to the user.
*/
public boolean isNew() {
return isNew;
}
}