/*
* Copyright 2015 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.breadcrumb;
import org.cruxframework.crux.core.client.collection.Array;
import org.cruxframework.crux.core.client.collection.CollectionFactory;
import org.cruxframework.crux.core.client.css.animation.Animation;
import org.cruxframework.crux.core.client.event.TouchEventsHandler;
import org.cruxframework.crux.core.client.screen.views.ViewActivateEvent;
import org.cruxframework.crux.core.client.screen.views.ViewActivateHandler;
import org.cruxframework.crux.core.client.screen.views.ViewContainer;
import org.cruxframework.crux.core.client.utils.DOMUtils;
import org.cruxframework.crux.core.client.utils.StringUtils;
import org.cruxframework.crux.core.shared.Experimental;
import org.cruxframework.crux.smartfaces.client.image.Image;
import org.cruxframework.crux.smartfaces.client.panel.BasePanel;
import org.cruxframework.crux.smartfaces.client.panel.SelectablePanel;
import org.cruxframework.crux.smartfaces.client.util.animation.InOutAnimation;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Node;
import com.google.gwt.dom.client.NodeList;
import com.google.gwt.event.logical.shared.AttachEvent;
import com.google.gwt.event.logical.shared.AttachEvent.Handler;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.event.logical.shared.HasCloseHandlers;
import com.google.gwt.event.logical.shared.HasOpenHandlers;
import com.google.gwt.event.logical.shared.HasSelectionHandlers;
import com.google.gwt.event.logical.shared.OpenEvent;
import com.google.gwt.event.logical.shared.OpenHandler;
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.user.client.Timer;
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 Breadcrumb component. Help to guide the user navigation.
* @author Thiago da Rosa de Bustamante
* - EXPERIMENTAL -
* THIS CLASS IS NOT READY TO BE USED IN PRODUCTION. IT CAN CHANGE FOR NEXT RELEASES
*/
@Experimental
public class Breadcrumb extends Composite implements HasEnabled, HasAnimation, HasSelectionHandlers<BreadcrumbItem>,
HasOpenHandlers<BreadcrumbItem>, HasCloseHandlers<BreadcrumbItem>
{
public static final String DEFAULT_STYLE_NAME = "faces-Breadcrumb";
public static final String STYLE_BREADCRUMB_ITEM = "item";
public static final String STYLE_BREADCRUMB_SEPARATOR = "separator";
private static final String STYLE_BREADCRUMB_DISABLED_SUFFIX = "-disabled";
private static final String STYLE_BREADCRUMB_ITEM_ACTIVE_SUFFIX = "-active";
private static final String STYLE_BREADCRUMB_ITEM_CONTRACT_SUFFIX = "-contract";
private static final String STYLE_BREADCRUMB_ITEM_EXPAND_SUFFIX = "-expand";
private HandlerRegistration activateHandler;
private boolean activateItemsOnSelectionEnabled = true;
private int activeIndex = -1;
private double animationDuration = -1;
private boolean animationEnabled;
private Array<BreadcrumbItem> children = CollectionFactory.createArray();
private InOutAnimation collapseAnimation = null;
private boolean collapsed = false;
private boolean collapsible = false;
private Image dividerImage;
private String dividerText;
private boolean enabled = true;
private BreadcrumbPanel mainPanel;
private boolean removeInactiveItems;
private boolean singleActivationModeEnabled = false;
private boolean updateOnViewChangeEnabled = true;
private ViewContainer viewContainer;
/**
* Constructor
*/
public Breadcrumb()
{
mainPanel = new BreadcrumbPanel(this);
initWidget(mainPanel);
setStyleName(DEFAULT_STYLE_NAME);
addAttachHandler(new Handler()
{
//Hack to avoid select bug on items from a breadcrumb.
@Override
public void onAttachOrDetach(AttachEvent event)
{
if (event.isAttached())
{
boolean childOfSelectableWidget = false;
Widget parent = getParent();
while (parent != null)
{
if (parent instanceof TouchEventsHandler)
{
childOfSelectableWidget = true;
break;
}
parent = parent.getParent();
}
if (childOfSelectableWidget)
{
for (int i=0; i < children.size(); i++)
{
children.get(i).itemPanel.setPreventDefaultTouchEvents(true);
}
}
}
}
});
}
/**
* Add a new {@link BreadcrumbItem} to this component. It is appended as the last item on
* this Breadcrumb.
* @param item Item to add.
* @return the Breadcrumb item added.
*/
public BreadcrumbItem add(BreadcrumbItem item)
{
return add(item, -1);
}
/**
* Add a new {@link BreadcrumbItem} to this component. It is inserted on
* the position informed through beforeIndex parameter.
* @param item Item to add.
* @param beforeIndex the item position. A negative or an out of range value makes the
* Breadcrumb to append the item as its last child.
* @return the Breadcrumb item added.
*/
public BreadcrumbItem add(BreadcrumbItem item, int beforeIndex)
{
item.setBreadcrumb(this, beforeIndex);
mainPanel.add(item, beforeIndex);
if (activeIndex >= 0)
{
if (beforeIndex >= 0 && activeIndex >= beforeIndex)
{
activeIndex++;
}
else
{
setActiveIndex(beforeIndex, false);
}
if (collapsed)
{
item.collapse(false);
}
}
return item;
}
/**
* Create an add a new {@link BreadcrumbItem} to this component. It is appended as the last item on
* this Breadcrumb.
* @param name the item name
* @param label the item label
* @return the Breadcrumb item added.
*/
public BreadcrumbItem add(String name, String label)
{
return add(name, label, -1);
}
/**
* Create an add a new {@link BreadcrumbItem} to this component. It is inserted on
* the position informed through beforeIndex parameter.
* @param name the item name
* @param label the item label
* @param beforeIndex the item position. A negative or an out of range value makes the
* @return the Breadcrumb item added.
*/
public BreadcrumbItem add(String name, String label, int beforeIndex)
{
BreadcrumbItem item = new BreadcrumbItem(name, label);
return add(item, beforeIndex);
}
@Override
public HandlerRegistration addCloseHandler(CloseHandler<BreadcrumbItem> handler)
{
return addHandler(handler, CloseEvent.getType());
}
@Override
public HandlerRegistration addOpenHandler(OpenHandler<BreadcrumbItem> handler)
{
return addHandler(handler, OpenEvent.getType());
}
@Override
public HandlerRegistration addSelectionHandler(SelectionHandler<BreadcrumbItem> handler)
{
return addHandler(handler, SelectionEvent.getType());
}
/**
* Retrieve the index of the current active item on this Breadcrumb.
* @return active item.
*/
public int getActiveIndex()
{
return activeIndex;
}
/**
* Retrieve the index of the current active item on this Breadcrumb.
* @return active item.
*/
public BreadcrumbItem getActiveItem()
{
if (activeIndex != -1)
{
return getItem(activeIndex);
}
return null;
}
/**
* Retrieve the image used as divider between items on this Breadcrumb.
* @return divider image
*/
public Image getDividerImage()
{
return dividerImage;
}
/**
* Retrieve the text used as divider between items on this Breadcrumb. If a divider
* image is also provided, this text is used as image title.
* @return divider text.
*/
public String getDividerText()
{
return dividerText;
}
/**
* Retrieve the item on the given position.
* @param index item index
* @return the {@link BreadcrumbItem}
*/
public BreadcrumbItem getItem(int index)
{
return children.get(index);
}
/**
* Retrieve the item with the given name.
* @param name item name
* @return the {@link BreadcrumbItem}
*/
public BreadcrumbItem getItem(String name)
{
int index = indexOf(name);
if (index >= 0)
{
return children.get(index);
}
return null;
}
/**
* Retrieve the associated ViewContainer. If there is a ViewContainer associated,
* the {@link BreadcrumbItem}s can automatically navigate to views on this container
* when selected.
* @return Associated ViewContainer.
*/
public ViewContainer getViewContainer()
{
return viewContainer;
}
/**
* Inform if this Breadcrumb has any divider configured.
* @return true if it has a divider configured.
*/
public boolean hasDivider()
{
return dividerText != null || dividerImage != null;
}
/**
* Find the index of the given item on this Breadcrumb, or -1 if it is not present.
* @param item item to find.
* @return item index or -1;
*/
public int indexOf(BreadcrumbItem item)
{
return children.indexOf(item);
}
/**
* Find the index of the item with the given name on this Breadcrumb, or -1 if it is not present.
* @param name the name of the item to find.
* @return item index or -1;
*/
public int indexOf(String name)
{
for (int i=0; i < children.size(); i++)
{
if (StringUtils.unsafeEquals(name, children.get(i).getName()))
{
return i;
}
}
return -1;
}
/**
* Retrieve the activateItemsOnSelectionEnabled property value. If this is enabled, the Breadcrumb will
* set the active index for an item when it is selected by the user.
* @return true if enabled.
*/
public boolean isActivateItemsOnSelectionEnabled()
{
return activateItemsOnSelectionEnabled;
}
@Override
public boolean isAnimationEnabled()
{
return animationEnabled;
}
/**
* Return true if this breadcrumbs is collapsed
* @return true if collapsed
*/
public boolean isCollapsed()
{
return collapsed;
}
/**
* Return true if this breadcrumbs supports to be collapsed
* @return true if collapsible
*/
public boolean isCollapsible()
{
return collapsible;
}
@Override
public boolean isEnabled()
{
return enabled;
}
/**
* Retrieve the removeInactiveItems property value. When this property is true,
* the Breadcrumb automatically remove the items that are not active anymore
* @return true if enabled.
*/
public boolean isRemoveInactiveItemsEnabled()
{
return removeInactiveItems;
}
/**
* Retrieve the singleActivationModeEnabled property value. If this is enabled, the Breadcrumb will
* keep only one item activated at a time. If false, all previous items are also activated.
* @return true if enabled.
*/
public boolean isSingleActivationModeEnabled()
{
return singleActivationModeEnabled;
}
/**
* Retrieve the updateOnViewChangeEnabled property value. If this is enabled, the Breadcrumb will
* set the active index for an item when it is bound to a view that is activated on the Breadcrumb's
* viewContainer.
* @return true if enabled.
*/
public boolean isUpdateOnViewChangeEnabled()
{
return updateOnViewChangeEnabled;
}
/**
* Remove the given item from this Breadcrumb.
* @param item item to be removed.
* @return the Breadcrumb reference.
*/
public Breadcrumb remove(BreadcrumbItem item)
{
return remove(item, indexOf(item));
}
/**
* Remove the item positioned on the given index from this Breadcrumb.
* @param index item index.
* @return the Breadcrumb reference.
*/
public Breadcrumb remove(int index)
{
BreadcrumbItem item = getItem(index);
remove(item, index);
return this;
}
/**
* Remove all items from this Breadcrumb, starting from the given position
* @param index the start position to remove
* @return the Breadcrumb reference.
*/
public Breadcrumb removeFrom(int index)
{
while (size() > index)
{
remove(index);
}
return this;
}
/**
* Set the activateItemsOnSelectionEnabled property value. If this is enabled, the Breadcrumb will
* set the active index for an item when it is selected by the user.
* @param activateItemsOnSelection true to enable.
* @return the Breadcrumb reference.
*/
public Breadcrumb setActivateItemsOnSelectionEnabled(boolean activateItemsOnSelection)
{
this.activateItemsOnSelectionEnabled = activateItemsOnSelection;
return this;
}
/**
* Set the index of the current active item on this Breadcrumb.
* @param index item index.
* @return the Breadcrumb reference.
*/
public Breadcrumb setActiveIndex(final int index)
{
return setActiveIndex(index, true);
}
/**
* Set the index of the current active item on this Breadcrumb.
* @param index item index.
* @param allowAnimations if false no animation will be allowed
* @return the Breadcrumb reference.
*/
public Breadcrumb setActiveIndex(final int index, final boolean allowAnimations)
{
return setActiveIndex(index, allowAnimations, false);
}
/**
* Set the duration for the animations
* @param duration animations duration in seconds
*/
public void setAnimationDuration(double duration)
{
this.animationDuration = duration;
}
@Override
public void setAnimationEnabled(boolean enable)
{
this.animationEnabled = enable;
}
/**
* Defines the animation used to animate collapse operations
* @param animation
*/
public void setCollapseAnimation(InOutAnimation animation)
{
this.collapseAnimation = animation;
setAnimationEnabled(animation != null);
}
/**
* Collapse or expand the breadcrumb. It only will take any effect if the collapsible property is true.
* @param collapsed true to collapse, false to expand
*/
public void setCollapsed(boolean collapsed)
{
if (this.collapsible && this.collapsed != collapsed)
{
collapseInactiveItems(collapsed);
uptadeActiveItemCollapsibleStyles(collapsed);
this.collapsed = collapsed;
if (collapsed)
{
CloseEvent.fire(this, getActiveItem());
}
else
{
OpenEvent.fire(this, getActiveItem());
}
}
}
/**
* Set the collapsible property. If this is true breadcrumb will support to be collapsed.
* @param collapsible true if collapsible
*/
public void setCollapsible(boolean collapsible)
{
this.collapsible = collapsible;
}
/**
* Set the image to be used as divider between items on this Breadcrumb.
* @param divider divider image
* @return the Breadcrumb reference.
*/
public Breadcrumb setDividerImage(Image divider)
{
dividerImage = divider;
mainPanel.updateDividers();
return this;
}
/**
* Set a text to be used as divider between items on this Breadcrumb. If a divider
* image is also provided, use this text as image title.
* @param divider divider text.
* @return the Breadcrumb reference.
*/
public Breadcrumb setDividerText(String divider)
{
dividerText = divider;
mainPanel.updateDividers();
return this;
}
@Override
public void setEnabled(boolean enabled)
{
this.enabled = enabled;
if (enabled)
{
removeStyleDependentName(STYLE_BREADCRUMB_DISABLED_SUFFIX);
}
else
{
addStyleDependentName(STYLE_BREADCRUMB_DISABLED_SUFFIX);
}
}
/**
* Set the removeInactiveItems property value. When this property is true,
* the Breadcrumb automatically remove the items that are not active anymore
* @param removeInactiveItems true to remove inactive items
* @return the Breadcrumb reference.
*/
public Breadcrumb setRemoveInactiveItemsEnabled(boolean removeInactiveItems)
{
this.removeInactiveItems = removeInactiveItems;
return this;
}
/**
* Set the singleActivationModeEnabled property value. If this is enabled, the Breadcrumb will
* keep only one item activated at a time. If false, all previous items are also activated.
* @param singleActivationModeEnabled true to enable.
* @return the Breadcrumb reference.
*/
public Breadcrumb setSingleActivationModeEnabled(boolean singleActivationModeEnabled)
{
this.singleActivationModeEnabled = singleActivationModeEnabled;
return this;
}
/**
* Set the updateOnViewChangeEnabled property value. If this is enabled, the Breadcrumb will
* set the active index for an item when it is bound to a view that is activated on the Breadcrumb's
* viewContainer.
* @param updateOnViewChangeEnabled true to enable.
* @return the Breadcrumb reference.
*/
public void setUpdateOnViewChangeEnabled(boolean updateOnViewChangeEnabled)
{
this.updateOnViewChangeEnabled = updateOnViewChangeEnabled;
}
/**
* Inform the associated ViewContainer. If there is a ViewContainer associated,
* the {@link BreadcrumbItem}s can automatically navigate to views on this container
* when selected.
* @param viewContainer the container.
* @return the Breadcrumb reference.
*/
public Breadcrumb setViewContainer(ViewContainer viewContainer)
{
if (this.viewContainer != viewContainer)
{
if (this.activateHandler != null)
{
activateHandler.removeHandler();
activateHandler = null;
}
if (viewContainer != null)
{
activateHandler = viewContainer.addViewActivateHandler(new ViewActivateHandler()
{
@Override
public void onActivate(ViewActivateEvent event)
{
if (updateOnViewChangeEnabled)
{
String viewId = event.getView().getId();
int viewIndex = indexOfItemByView(viewId);
if (viewIndex >= 0 && viewIndex != activeIndex)
{
setActiveIndex(viewIndex, false);
}
}
}
});
}
this.viewContainer = viewContainer;
}
return this;
}
/**
* Retrieve the number of items inside this Breadcrumb.
* @return number of children.
*/
public int size()
{
return children.size();
}
/**
* Called by {@link BreadcrumbItem} when it is associated to a Breadcrumb. It adopt the item as
* a new child.
* @param item the item to be adopted.
* @param onPosition the position where the item are being inserted.
*/
protected void adopt(BreadcrumbItem item, int onPosition)
{
children.add(item);
mainPanel.adopt(item);
}
protected void collapseInactiveItems(boolean collapse)
{
if (hasDivider())
{
mainPanel.showDividers(!collapse);
}
for (int i=0; i < children.size(); i++)
{
if (i != activeIndex)
{
BreadcrumbItem item = children.get(i);
if (collapse)
{
item.collapse();
}
else
{
item.uncollapse();
}
}
}
}
/**
* Create a new divider element.
* @return the element created
*/
protected Element createDivider()
{
Element el = null;
if (dividerImage != null)
{
el = dividerImage.getElement().cloneNode(true).cast();
if (!StringUtils.isEmpty(dividerText))
{
el.setTitle(dividerText);
}
}
else if (!StringUtils.isEmpty(dividerText))
{
el = Document.get().createSpanElement();
el.setInnerText(dividerText);
}
return el;
}
protected double getAnimationDuration()
{
return animationDuration;
}
protected InOutAnimation getCollapseAnimation()
{
if (collapseAnimation == null)
{
collapseAnimation = InOutAnimation.bounce;
}
return collapseAnimation;
}
/**
* Find the index of the item with the given viewId on this Breadcrumb, or -1 if it is not present.
* @param viewID the viewID of the item to find.
* @return item index or -1;
*/
protected int indexOfItemByView(String viewId)
{
for (int i=0; i < children.size(); i++)
{
if (StringUtils.unsafeEquals(viewId, children.get(i).getViewId()))
{
return i;
}
}
return -1;
}
/**
* Called by {@link BreadcrumbItem} when it is removed from the Breadcrumb. It removes the item
* from the internal children list.
* @param item the item to be removed.
*/
protected void orphan(BreadcrumbItem item)
{
children.remove(item);
mainPanel.orphan(item);
}
protected Breadcrumb remove(BreadcrumbItem item, int index)
{
item.setBreadcrumb(null, -1);
mainPanel.remove(item);
if ((activeIndex >= index))
{
activeIndex--;
}
return this;
}
protected Breadcrumb setActiveIndex(final int index, final boolean allowAnimations, final boolean collpase)
{
if (mainPanel.isAnimating())
{
new Timer()
{
@Override
public void run()
{
doSetActivateIndex(index, allowAnimations);
if (collpase && isCollapsible())
{
setCollapsed(true);
}
}
}.schedule((int)(animationDuration*1000));
return this;
}
return doSetActivateIndex(index, allowAnimations);
}
protected void uptadeActiveItemCollapsibleStyles(boolean collapsed)
{
BreadcrumbItem activeItem = getActiveItem();
if (activeItem != null)
{
setActiveStyleWhenCollapsible(activeItem, collapsed);
clearActiveOldStyleWhenCollapsible(activeItem, collapsed);
}
}
private void setActiveStyleWhenCollapsible(BreadcrumbItem item, boolean collapsed)
{
if (size() > 1 && item.breadcrumb == this)
{
item.addStyleDependentName(collapsed?STYLE_BREADCRUMB_ITEM_EXPAND_SUFFIX:STYLE_BREADCRUMB_ITEM_CONTRACT_SUFFIX);
}
}
private void clearActiveOldStyleWhenCollapsible(BreadcrumbItem item, boolean collapsed)
{
item.removeStyleDependentName(collapsed?STYLE_BREADCRUMB_ITEM_CONTRACT_SUFFIX:STYLE_BREADCRUMB_ITEM_EXPAND_SUFFIX);
}
private void clearActiveStylesWhenCollapsible(BreadcrumbItem item)
{
item.removeStyleDependentName(STYLE_BREADCRUMB_ITEM_CONTRACT_SUFFIX);
item.removeStyleDependentName(STYLE_BREADCRUMB_ITEM_EXPAND_SUFFIX);
}
private Breadcrumb doSetActivateIndex(int index, boolean allowAnimations)
{
int s = size();
if (index < 0 || index >= s || activeIndex == index)
{
return this;
}
if (singleActivationModeEnabled)
{
children.get(index).addStyleDependentName(STYLE_BREADCRUMB_ITEM_ACTIVE_SUFFIX);
}
else
{
for (int i = 0; i <= index; i++)
{
children.get(i).addStyleDependentName(STYLE_BREADCRUMB_ITEM_ACTIVE_SUFFIX);
}
}
if (collapsible)
{
setActiveStyleWhenCollapsible(children.get(index), collapsed);
if (activeIndex >= 0)
{
BreadcrumbItem activeItem = children.get(this.activeIndex);
clearActiveStylesWhenCollapsible(activeItem);
}
if (collapsed)
{
children.get(index).uncollapse(allowAnimations);
if (activeIndex >= 0 && (!removeInactiveItems || activeIndex < index))
{
children.get(this.activeIndex).collapse(allowAnimations);
}
}
}
if (removeInactiveItems && (index < size() -1))
{
removeFrom(index+1);
}
else if (singleActivationModeEnabled && activeIndex >= 0)
{
children.get(activeIndex).removeStyleDependentName(STYLE_BREADCRUMB_ITEM_ACTIVE_SUFFIX);
}
else
{
for (int i = index+1; i < s; i++)
{
children.get(i).removeStyleDependentName(STYLE_BREADCRUMB_ITEM_ACTIVE_SUFFIX);
}
}
this.activeIndex = index;
return this;
}
/**
* Internal class representing the outer panel of a Breadcrumb component.
* It generates a structure like:
*
* {@code <nav><ol></ol></nav>}. Each breadcrumb item is a rendered on a
* {@code <li></li>} tag.
* @author Thiago da Rosa de Bustamante
*/
protected static class BreadcrumbPanel extends BasePanel
{
private Breadcrumb breadcrumb;
private Element listElement;
protected BreadcrumbPanel(Breadcrumb breadcrumb)
{
super("nav");
this.breadcrumb = breadcrumb;
listElement = Document.get().createElement("ol");
getElement().appendChild(listElement);
}
protected void add(BreadcrumbItem item, int beforeIndex)
{
int listSize = listElement.getChildCount();
boolean hasDivider = breadcrumb.hasDivider();
if (beforeIndex < 0 || beforeIndex >= listSize)
{
if (hasDivider && listSize > 0)
{
listElement.appendChild(createNewDivider());
}
listElement.appendChild(item.getElement());
}
else
{
Node referenceNode;
if (hasDivider)
{
int referenceNodePosition = Math.min(0, beforeIndex*2 -1);
referenceNode = listElement.getChild(referenceNodePosition);
Node dividerNode = listElement.insertBefore(referenceNode, createNewDivider());
if (referenceNodePosition == 0)
{
referenceNode = dividerNode;
}
}
else
{
int referenceNodePosition = beforeIndex;
referenceNode = listElement.getChild(referenceNodePosition);
}
listElement.insertBefore(referenceNode, item.getElement());
}
}
protected void adopt(BreadcrumbItem item)
{
SelectablePanel itemPanel = item.getItemPanel();
if (itemPanel != null)
{
getChildren().add(itemPanel);
adopt(itemPanel);
}
}
protected Node createNewDivider()
{
Element dividerElement = Document.get().createElement("li");
dividerElement.setClassName(STYLE_BREADCRUMB_SEPARATOR);
dividerElement.appendChild(breadcrumb.createDivider());
return dividerElement;
}
protected boolean isAnimating()
{
NodeList<Element> separators = DOMUtils.getElementsByClassName(listElement, "animated");
return separators != null && separators.getLength() > 0;
}
protected void orphan(BreadcrumbItem item)
{
SelectablePanel itemPanel = item.getItemPanel();
if (itemPanel != null)
{
getChildren().remove(itemPanel);
orphan(itemPanel);
}
}
protected void remove(BreadcrumbItem item)
{
if (breadcrumb.hasDivider())
{
Element divider = item.getElement().getPreviousSiblingElement();
if (divider != null)
{
divider.removeFromParent();
}
}
item.getElement().removeFromParent();
}
protected void showDividers(boolean show)
{
NodeList<Element> separators = DOMUtils.getElementsByClassName(listElement, STYLE_BREADCRUMB_SEPARATOR);
for (int i = 0; i < separators.getLength(); i++)
{
final Element separator = separators.getItem(i);
if (breadcrumb.isAnimationEnabled())
{
if (show)
{
separator.getStyle().setProperty("display", "");
breadcrumb.getCollapseAnimation().animateEntrance(separator, null, breadcrumb.getAnimationDuration());
}
else
{
breadcrumb.getCollapseAnimation().animateExit(separator, new Animation.Callback()
{
@Override
public void onAnimationCompleted()
{
separator.getStyle().setProperty("display","none");
}
}, breadcrumb.getAnimationDuration());
}
}
else
{
separator.getStyle().setProperty("display", show?"":"none");
}
}
}
protected void updateDividers()
{
NodeList<Element> separators = DOMUtils.getElementsByClassName(listElement, STYLE_BREADCRUMB_SEPARATOR);
for (int i = 0; i < separators.getLength(); i++)
{
Element separator = separators.getItem(i);
separator.removeAllChildren();
separator.appendChild(breadcrumb.createDivider());
}
}
}
}