/*
* Copyright 2014 cruxframework.org.
*
* 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.cruxframework.crux.smartfaces.client.menu;
import org.cruxframework.crux.core.client.collection.FastList;
import org.cruxframework.crux.smartfaces.client.backbone.common.FacesBackboneResourcesCommon;
import org.cruxframework.crux.smartfaces.client.button.Button;
import org.cruxframework.crux.smartfaces.client.menu.MenuRenderer.LargeMenuRenderer;
import org.cruxframework.crux.smartfaces.client.menu.Type.LargeType;
import org.cruxframework.crux.smartfaces.client.menu.Type.SmallType;
import org.cruxframework.crux.smartfaces.client.panel.BasePanel;
import org.cruxframework.crux.smartfaces.client.panel.SelectablePanel;
import com.google.gwt.core.shared.GWT;
import com.google.gwt.event.logical.shared.HasSelectionHandlers;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HasAnimation;
import com.google.gwt.user.client.ui.HasEnabled;
import com.google.gwt.user.client.ui.Widget;
/**
* A cross device menu
* @author Samuel Almeida Cardoso (samuel@cruxframework.org)
* @author Claudio Holanda (claudio.junior@cruxframework.org)
* @author Thiago da Rosa de Bustamante
*
*/
public class Menu extends Composite implements HasAnimation, HasEnabled, HasSelectionHandlers<MenuItem>
{
public static final String STYLE_FACES_MENU = "faces-Menu";
protected static final String SPACE = " ";
protected static final String CLEARFIX = "faces--clearfix";
protected static final String STYLE_FACES_SLIDE = "faces-Menu-slide";
protected static final String STYLE_FACES_DROPDOWN = "faces-Menu-dropdown";
protected static final String STYLE_FACES_TREE = "faces-Menu-tree";
protected static final String STYLE_FACES_ACCORDION = "faces-Menu-accordion";
protected static final String STYLE_FACES_HORIZONTAL = "faces-Menu-horizontal";
protected static final String STYLE_FACES_VERTICAL = "faces-Menu-vertical";
protected static final String STYLE_FACES_OPEN = "faces-Menu--open";
protected static final String STYLE_FACES_HAS_CHILDREN = "faces-Menu-hasChildren";
protected static final String STYLE_FACES_DISABLED = "faces-Menu--disabled";
protected static final String STYLE_FACES_EMPTY = "faces-Menu--empty";
protected static final String STYLE_FACES_LI = "faces-Menu-li";
protected static final String STYLE_FACES_UL = "faces-Menu-ul";
protected static final String STYLE_AUX_OPEN_CLOSE_TRIGGER_HELPER = "faces-Menu-openCloseTriggerHelper";
protected static final String STYLE_AUX_CLOSE_TRIGGER_SLIDER_HELPER = "faces-Menu-closeTriggerSliderHelper";
private boolean enabled = true;
private MenuItem root;
private MenuPanel menuPanel = new MenuPanel();
protected Type currentType = null;
protected MenuRenderer menuRenderer = GWT.create(MenuRenderer.class);
private boolean animationEnabled;
//TODO implement animation to open or close menu items
public Menu(LargeType largeType, SmallType smallType)
{
FacesBackboneResourcesCommon.INSTANCE.css().ensureInjected();
initWidget(menuPanel);
root = new MenuItem(null);
menuPanel.add(root);
root.setMenu(this);
setStyleName(getBaseStyleName());
setMenuType(largeType, smallType);
}
@Override
public void setStyleName(String style, boolean add)
{
super.setStyleName(style, add);
if (!add)
{
addStyleName(FacesBackboneResourcesCommon.INSTANCE.css().facesBackboneMenu());
}
}
@Override
public void setStyleName(String style)
{
super.setStyleName(style);
addStyleName(FacesBackboneResourcesCommon.INSTANCE.css().facesBackboneMenu());
}
public Menu()
{
this(LargeType.HORIZONTAL_ACCORDION, SmallType.VERTICAL_ACCORDION);
}
public Menu(LargeType largeType)
{
this(largeType, null);
}
public Menu(SmallType smallType)
{
this(null, smallType);
}
public String getBaseStyleName()
{
return STYLE_FACES_MENU;
}
@Override
public HandlerRegistration addSelectionHandler(SelectionHandler<MenuItem> handler)
{
return addHandler(handler, SelectionEvent.getType());
}
@Override
public boolean isAnimationEnabled()
{
return animationEnabled;
}
@Override
public void setAnimationEnabled(boolean animationEnabled)
{
this.animationEnabled = animationEnabled;
}
@Override
public boolean isEnabled()
{
return enabled;
}
@Override
public void setEnabled(boolean enabled)
{
this.enabled = enabled;
FastList<MenuItem> itemsWithEnabledProperty = MenuUtils.findHasEnabledInMenu(root);
if(itemsWithEnabledProperty != null)
{
for(int i=0; i<itemsWithEnabledProperty.size();i++)
{
((HasEnabled) itemsWithEnabledProperty.get(i).getItemWidget()).setEnabled(enabled);
}
}
}
/**
* Remove all menuItems contained into this menu
*/
public void clear()
{
if(this.root != null)
{
this.root.clear();
}
}
/**
* Adds a root item.
* @return the inserted item.
*/
public MenuItem addItem(Widget w)
{
return root.addItem(w);
}
/**
* Adds a label root item.
* @return the inserted item.
*/
public MenuItem addItem(String labelText)
{
return root.addItem(labelText);
}
/**
* Adds a html root item.
* @return the inserted item.
*/
public MenuItem addItem(SafeHtml html)
{
return root.addItem(html);
}
/**
* Adds a label item.
* @return the inserted item.
*/
public MenuItem addItem(MenuItem placeToInsert, String labelText)
{
if(placeToInsert == null)
{
placeToInsert = this.root;
}
return placeToInsert.addItem(labelText);
}
/**
* Adds a label item.
* @return the inserted item.
*/
public MenuItem addItem(MenuItem placeToInsert, SafeHtml html)
{
if(placeToInsert == null)
{
placeToInsert = this.root;
}
return placeToInsert.addItem(html);
}
public MenuItem addItem(MenuItem placeToInsert, Widget w)
{
if(placeToInsert == null)
{
placeToInsert = this.root;
}
return placeToInsert.addItem(w);
}
public MenuItem getItem(int index)
{
return root.getItem(index);
}
public MenuItem getItem(String path)
{
return root.getItem(path);
}
public int getItemCount()
{
return root.getItemCount();
}
public int indexOf(MenuItem item)
{
return root.indexOf(item);
}
public boolean removeItem(int index)
{
return root.removeItem(index);
}
public void openAll()
{
MenuUtils.addOrRemoveClass(STYLE_FACES_OPEN, true, MenuUtils.getAllMenuItems(this.root));
}
public void open(MenuItem menuItem)
{
if(menuItem == null)
{
return;
}
menuItem.open();
}
public void closeAll()
{
MenuUtils.addOrRemoveClass(STYLE_FACES_OPEN, false, MenuUtils.getAllMenuItems(this.root));
}
public void close(MenuItem menuItem)
{
if(menuItem == null)
{
return;
}
menuItem.close();
}
protected boolean isSlider()
{
return currentType.isSlider();
}
protected boolean isTree()
{
return currentType.isTree();
}
protected void adopt(MenuItem item, Button button)
{
menuPanel.adopt(item, button);
}
protected void adopt(MenuItem item)
{
menuPanel.adopt(item);
}
protected void orphan(MenuItem item)
{
menuPanel.orphan(item);
}
/**
* Internal Panel mapped to a nav element around the menu
* @author Thiago da Rosa de Bustamante
*
*/
protected static class MenuPanel extends BasePanel
{
protected MenuPanel()
{
super("nav");
}
protected void add(MenuItem item)
{
getElement().appendChild(item.getElement());
}
protected void adopt(MenuItem item, Button button)
{
SelectablePanel itemPanel = item.getItemPanel();
if (itemPanel != null)
{
getChildren().add(button);
adopt(button);
}
}
protected void adopt(MenuItem item)
{
SelectablePanel itemPanel = item.getItemPanel();
if (itemPanel != null)
{
getChildren().add(itemPanel);
adopt(itemPanel);
}
}
protected void orphan(MenuItem item)
{
SelectablePanel itemPanel = item.getItemPanel();
if (itemPanel != null)
{
getElement().removeChild(item.getElement());
getChildren().remove(itemPanel);
orphan(itemPanel);
}
}
}
public void setMenuType(LargeType largeType, SmallType smallType)
{
if(menuRenderer instanceof LargeMenuRenderer)
{
this.currentType = largeType;
}
else
{
this.currentType = smallType;
}
menuRenderer.render(this, largeType, smallType);
}
}