/*******************************************************************************
* Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Darrell Meyer <darrell@mygwt.net> - derived implementation
*******************************************************************************/
package net.mygwt.ui.client.widget.menu;
import net.mygwt.ui.client.Events;
import net.mygwt.ui.client.Style;
import net.mygwt.ui.client.event.BaseEvent;
import net.mygwt.ui.client.event.SelectionListener;
import net.mygwt.ui.client.event.TypedListener;
import net.mygwt.ui.client.widget.Item;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
/**
* A selectable item in a <code>MenuBar</code>.
*
* <dl>
* <dt><b>Styles:</b></dt>
* <dd>PUSH, CHECK, RADIO, MENU, SEPARATOR</dd>
*
* <dt><b>Events:</b></dt>
*
* <dd><b>Select</b> : (widget this)<br>
* <div>Fired when a item is selected.</div>
* <ul>
* <li>widget : this</li>
* </ul>
* </dd>
* </dl>
*
* <dd><b>CheckChange</b> : (widget)<br>
* <div>Fires after a check state change.</div>
* <ul>
* <li>widget : this</li>
* </ul>
* </dd>
*
* <p>
* Note: Only one of the styles PUSH, CHECK, RADIO, MENU, and SEPARATOR may be
* specified.
* </p>
*/
public class MenuItem extends Item {
boolean canActivate = true;
boolean enabled;
protected boolean hideOnClick = true;
protected Menu parentMenu;
protected Menu subMenu;
protected boolean showingMenu = false;
private String group = "";
private int style;
/**
* Creates a new menu item.
*/
public MenuItem(int style) {
super("my-menuitem");
this.style = style;
}
protected void onRender() {
super.onRender();
DOM.appendChild(midRightElem, DOM.createDiv());
switch (style) {
case Style.SEPARATOR:
setElement(DOM.createDiv());
setStyleName("my-menu-seperator");
DOM.appendChild(getElement(), DOM.createDiv());
hideOnClick = false;
overStyleEnabled = false;
break;
case Style.CHECK:
setIconStyle("icon-notchecked");
break;
}
if (style != Style.SEPARATOR && iconStyle == null) {
setIconStyle("blank");
}
}
public int getStyle() {
return style;
}
/**
* Adds a listener interface to receive selection events.
*
* @param listener the listener to add
*/
public void addSelectionListener(SelectionListener listener) {
TypedListener tl = new TypedListener(listener);
addListener(Events.Select, tl);
}
/**
* Returns the item's group value.
*
* @return the group
*/
public String getGroup() {
return group;
}
/**
* Returns the item's sub menu.
*
* @return the sub menu
*/
public Menu getSubMenu() {
return subMenu;
}
/**
* Returns <code>true</code> if the item is selected.
* <p>
* When the item is of type CHECK or RADIO, it is selected when it is checked.
* </p>
*
* @return the selected state
*/
public boolean isSelected() {
return super.isSelected();
}
/**
* Removes a previously added listener.
*
* @param listener the listener to be removed
*/
public void removeSelectionListener(SelectionListener listener) {
unhook(Events.EffectStart, listener);
}
/**
* Allows radio items to be grouped together.
*/
public void setGroup(String group) {
this.group = group;
}
/**
* Sets the item's selected state.
* <p>
* When the item is of type CHECK or RADIO, it is selected when it is checked.
* </p>
*
* @param selected the select state
*/
public void setSelected(boolean selected) {
setSelected(selected, true);
}
/**
* Sets the item's sub menu.
*
* @param menu the sub menu
*/
public void setSubMenu(Menu menu) {
this.subMenu = menu;
menu.parentItem = this;
addStyleName("my-menuitem-submenu");
}
void activate(boolean autoOpen) {
if (autoOpen) {
expandMenu();
}
}
void deactivate() {
hideMenu();
}
void expandMenu() {
if (subMenu != null) {
if (!subMenu.showing) {
subMenu.show(getElement(), "tl-tr-?");
}
}
}
void hideMenu() {
if (subMenu != null && subMenu.isVisible()) {
subMenu.hide();
}
}
boolean shouldDeactivate(Event event) {
if (subMenu != null && subMenu.isVisible()) {
return DOM.isOrHasChild(getElement(), DOM.eventGetTarget(event));
}
return false;
}
protected void onClick(BaseEvent be) {
switch (style) {
case Style.MENU:
if (subMenu != null && subMenu.isVisible()) {
return;
}
break;
case Style.CHECK:
case Style.RADIO:
case Style.PUSH:
setSelected(!isSelected());
break;
}
if (hideOnClick) {
onMouseOut(be);
parentMenu.closeAllMenus();
}
}
private void setSelected(boolean selected, boolean fireEvent) {
super.setSelected(selected);
switch (style) {
case Style.CHECK: {
String s = selected ? "icon-checked" : "icon-notchecked";
setIconStyle(s);
if (fireEvent) {
fireEvent(Events.CheckChange);
}
break;
}
case Style.RADIO: {
if (parentMenu == null) {
setIconStyle("icon-group-sel");
break;
}
int size = parentMenu.getItemCount();
for (int i = 0; i < size; i++) {
MenuItem item = parentMenu.getItem(i);
if (item.style == Style.RADIO) {
if (!item.group.equals(group)) {
continue;
}
String s = item == this ? "icon-group-sel" : "my-none";
item.setIconStyle(s);
}
}
if (fireEvent) {
fireEvent(Events.CheckChange);
}
break;
}
}
if (fireEvent) {
fireEvent(Events.Select);
}
}
}