Lexaden Breadcrumb
breadcrumb.png

Breadcrumbs typically appear horizontally across the top of a web page, often below title bars or headers. They provide links back to each previous page the user navigated through to get to the current page or—in hierarchical site structures—the parent pages of the current one. Breadcrumbs provide a trail for the user to follow back to the starting or entry point.

Breadcrumb starts tracking locations when any of flows starts and stop tracking when flow reaches final state. Users can navigate back and forth just by one click. 

 A greater-than sign (>) often serves as hierarchy separator, although designers may use other glyphs (such as » or ›), as well as various graphical treatments.

Typical breadcrumbs look like this:

Home page > Section page > Subsection page    or   Home page : Section page : Subsection page

(Breadcrumb on Wikipedia)

Downloads 


<dependency>                                       <dependency>
    <groupId>com.lexaden.components</groupId>          <groupId>com.lexaden.components</groupId>
    <artifactId>breadcrumb</artifactId>                <artifactId>breadcrumb</artifactId>
    <version>1.6.0</version>                           <version>1.7.2</version>
</dependency>                                      </dependency>

<repository>                                       <repository>
    <id>lexaden</id>                                   <id>lexaden</id>
    <name>Lexaden Repository</name>                    <name>Lexaden Repository</name>
    <url>http://www.lexaden.com/maven2/repo</url>      <url>http://www.lexaden.com/maven2/repo</url>
</repository>                                      </repository>

          

Lexaden Breadcrumb Demo

Showcase Demo - advanced administrative system developed base on Lexaden Web Flow (Username/password: demo/demo)

Showcase Video - navigation through business model of Lexaden Administration


package com.lexaden.platform.web.container.application;


/**
 * This class is responsible for breadcrumb interactions on UI.
 */
public class BreadcrumbController extends AbstractController<BreadcrumbController.BreadCrumbExt> {

    public class BreadCrumbExt extends Breadcrumb {
        public int getComponentCount() {
            if (getCompositionRoot() != null) {
                final BreadcrumbLayout compositionRoot = (BreadcrumbLayout) getCompositionRoot();
                return compositionRoot.getComponentCount();
            }
            return super.getComponentCount();
        }
    }

    /**
     * Initializes view when system enters 'initView' action state.
     *
     * @param event -  state event.
     */
    @Override
    public void initView(StateEvent event) {
        final BreadCrumbExt breadCrumb = new BreadCrumbExt();
        breadCrumb.setShowAnimationSpeed(Breadcrumb.AnimSpeed.SLOW);
        breadCrumb.setHideAnimationSpeed(Breadcrumb.AnimSpeed.SLOW);
        breadCrumb.setUseDefaultClickBehaviour(false);
        breadCrumb.addLink(new Button());
        breadCrumb.setLinkEnabled(false, 0);
        breadCrumb.setHeight(18, Sizeable.Unit.PIXELS);
        setView(breadCrumb);
    }

    /**
     * This method is called every time system enters any controller state
     *
     * @param stateEvent -  state event.
     */
    @OnEnterState(StateConstants.CONTROLLER)
    public void buildBreadcrumbs(StateEvent stateEvent) {
        final Breadcrumb breadCrumb = getView();

        final State currentFlowState = (State) eventProcessor.getRootContext().get("currentFlowState");
        final List<State> breadcrumbList = new ArrayList<State>();

        if (currentFlowState != null) {
            final List<State> stateList = (List<State>) eventProcessor.getRootContext().get(currentFlowState.getAbsoluteId());
            for (State state : stateList) {
                breadcrumbList.add((State) state.getParent());
            }
        }

        breadCrumb.select(0);
        final int size = breadcrumbList.size();
        for (int i = 0, breadcrumbListSize = breadcrumbList.size(); i < breadcrumbListSize; i++) {
            State state = breadcrumbList.get(i);
            breadCrumb.addLink(new Button(getName(state), new BreadcrumbClickListener("cancel", eventProcessor, size - (i + 1))));
        }
    }

    private String getName(State state) {
        return TranslationUtils.getMessage("platform.state." + state.getParent().getId() + "." + state.getId());
    }

    private static class BreadcrumbClickListener implements Button.ClickListener {

        private String eventName;
        private EventProcessor eventProcessor;
        private int times;

        BreadcrumbClickListener(String event, EventProcessor eventProcessor, int times) {
            this.eventName = event;
            this.eventProcessor = eventProcessor;
            this.times = times;
        }

        @Override
        public void buttonClick(Button.ClickEvent event) {
            for (int i = 0; i < times; i++) {
                eventProcessor.fireEvent(eventName, null);
            }
        }

    }

    @Override
    public void clearView(StateEvent stateEvent) {
    }
}


   

package com.lexaden.breadcrumb;

/**
 * Breadcrumb server side component implementation. Breadcrumbs typically appear horizontally across the top of a web page,
 * often below title bars or headers. They provide links back to each previous page the user navigated through to get to the current
 * page or—in hierarchical site structures—the parent pages of the current one.
 * Breadcrumbs provide a trail for the user to follow back to the starting or entry point.
 */
public class Breadcrumb extends CustomComponent implements Button.ClickListener {
    public static interface AnimSpeed {
        String FAST = "fast";
        String SLOW = "slow";
        String NORMAL = "normal";
    }

    private static String LINK_STYLE_HOME = "home";
    private static final String CURRENT_STYLE_NAME = "current";
    private static String BREADCRUMB_LINK_STYLE = "xbreadcrumblink";
    private static String BREADCRUMB_BUTTON_STYLE = "xbreadcrumbbutton";

    private BreadcrumbLayout breadcrumbLayout;
    private Map<Component, BreadcrumbItem> componentToLi = new HashMap<Component, BreadcrumbItem>();
    private boolean collapsible = true;
    private int collapsedWidth = 20;
    private String showAnimationSpeed = AnimSpeed.FAST;
    private String hideAnimationSpeed = AnimSpeed.FAST;
    private boolean useDefaultClickBehaviour = true;

    public Breadcrumb() {
        breadcrumbLayout = new BreadcrumbLayout();
        breadcrumbLayout.setStyleName("xbreadcrumbs");
        setCompositionRoot(breadcrumbLayout);
    }


    /**
     * Add new link(com.vaadin.ui.Button) to the end of the breadcrumb Button
     * style will be set to BUTTON_LINK If default click behaviour is true, adds
     * click listener to the link
     *
     * @param link - vaadin button with link style
     */
    public void addLink(Button link) {
        link.setStyleName(BaseTheme.BUTTON_LINK);

        link.addStyleName(BREADCRUMB_BUTTON_STYLE);
        if (useDefaultClickBehaviour) {
            link.addClickListener(this);
        }
        BreadcrumbItem breadcrumbItem = createBreadcrumbItem(link);
        if (breadcrumbLayout.getComponentCount() > 0) {
            int index = breadcrumbLayout.getComponentCount();
            while (index-- > 0) {
                Component newLast = breadcrumbLayout.getComponent(index);
                if (newLast.getStyleName().contains((CURRENT_STYLE_NAME))) {
                    newLast.removeStyleName(CURRENT_STYLE_NAME);
                    break;
                }
            }
        } else {
            link.addStyleName(BREADCRUMB_BUTTON_STYLE + "-" + LINK_STYLE_HOME);
        }
        breadcrumbItem.addStyleName(CURRENT_STYLE_NAME);
        breadcrumbLayout.addComponent(breadcrumbItem);
        componentToLi.put(link, breadcrumbItem);
        updateParameters();
    }

    /**
     * Add new link(com.vaadin.ui.Link) to the end of the breadcrumb
     *
     * @param link - vaadin button with link style
     */
    public void addLink(Link link) {
        BreadcrumbItem breadcrumbItem = createBreadcrumbItem(link);
        link.addStyleName(BREADCRUMB_LINK_STYLE);
        if (breadcrumbLayout.getComponentCount() > 0) {
            int index = breadcrumbLayout.getComponentCount();
            while (index-- > 0) {
                Component newLast = breadcrumbLayout.getComponent(index);
                if (newLast.getStyleName().contains((CURRENT_STYLE_NAME))) {
                    newLast.removeStyleName(CURRENT_STYLE_NAME);
                    break;
                }
            }
        } else {
            link.addStyleName(BREADCRUMB_LINK_STYLE + "-" + LINK_STYLE_HOME);
        }
        breadcrumbItem.addStyleName(CURRENT_STYLE_NAME);
        breadcrumbLayout.addComponent(breadcrumbItem);
        componentToLi.put(link, breadcrumbItem);
        updateParameters();
    }

    private BreadcrumbItem createBreadcrumbItem(Component link) {
        final BreadcrumbItem breadcrumbItem = new BreadcrumbItem();
        breadcrumbItem.addComponent(link);
        return breadcrumbItem;
    }


    /**
     * selects the given input link
     *
     * @param link - vaadin button with link style
     */
    public void select(Component link) {
        BreadcrumbItem breadcrumbItem = componentToLi.get(link);
        int index = breadcrumbLayout.getComponentIndex(breadcrumbItem);
        while (breadcrumbLayout.getComponentCount() - 1 > index) {
            breadcrumbLayout.removeComponent(breadcrumbLayout.getLastComponent());
        }
        breadcrumbItem.addStyleName(CURRENT_STYLE_NAME);

    }

    /**
     * selects the crumb at given input index
     *
     * @param index - index of component
     */
    public void select(int index) {
        Component breadcrumbItem = breadcrumbLayout.getComponent(index);
        while (breadcrumbLayout.getComponentCount() - 1 > index) {
            breadcrumbLayout.removeComponent(breadcrumbLayout.getLastComponent());
        }
        breadcrumbItem.addStyleName(CURRENT_STYLE_NAME);
        updateParameters();
    }

    public void updateParameters() {
        getState().setCollapsedWidth(collapsedWidth);
        getState().setCollapsible(collapsible);
        getState().setHideAnimationSpeed(hideAnimationSpeed);
        getState().setShowAnimationSpeed(showAnimationSpeed);
        markAsDirty();
    }

    /**
     * Checks for collapsible option.
     *
     * @return collapsible option
     */
    public boolean isCollapsible() {
        return collapsible;
    }

    /**
     * If set true, crumb will be collapsible and animated
     *
     * @param collapsible - boolean flag to set breadcrumb as collapsible
     */
    public void setCollapsible(boolean collapsible) {
        this.collapsible = collapsible;
    }

    /**
     * Gets collapsed with.
     *
     * @return collapsed width
     */
    public int getCollapsedWidth() {
        return collapsedWidth;
    }

    /**
     * Determines the width of the link when it is collapsed.
     *
     * @param collapsedWidth - collapsed width
     */
    public void setCollapsedWidth(int collapsedWidth) {
        this.collapsedWidth = collapsedWidth;
    }

    /**
     * Gets show animation speed.
     *
     * @return show animation speed
     */
    public String getShowAnimationSpeed() {
        return showAnimationSpeed;
    }

    /**
     * Determines the speed when the link is shown, use Interface AnimSpeed for
     * input values
     *
     * @param showAnimationSpeed - show animate speed.
     */
    public void setShowAnimationSpeed(String showAnimationSpeed) {
        this.showAnimationSpeed = showAnimationSpeed;
    }

    /**
     * Gets hide animation speed.
     *
     * @return hide animation speed
     */
    public String getHideAnimationSpeed() {
        return hideAnimationSpeed;
    }

    /**
     * Determines the speed when the link is hide, use interface animation speed for
     * input values
     *
     * @param hideAnimationSpeed - hide animation speed.
     */
    public void setHideAnimationSpeed(String hideAnimationSpeed) {
        this.hideAnimationSpeed = hideAnimationSpeed;
    }

    /**
     * Button click action implementation, selects appropriate button link within breadcrumb.
     *
     * @param event - button click event
     */
    public void buttonClick(ClickEvent event) {
        select(event.getButton());
    }

    /**
     * Checks whether default click behaviour is enabled.
     *
     * @return true if enabled and false if it doesn't
     */
    public boolean isUseDefaultClickBehaviour() {
        return useDefaultClickBehaviour;
    }

    /**
     * If set, default click behaviour added to the links of type
     * com.vaadin.ui.Button.
     *
     * @param useDefaultClickBehaviour - indicates default click behaviour
     */
    public void setUseDefaultClickBehaviour(boolean useDefaultClickBehaviour) {
        this.useDefaultClickBehaviour = useDefaultClickBehaviour;
        Set<Component> buttons = componentToLi.keySet();
        for (Component component : buttons) {
            if (component instanceof Button) {
                ((Button) component).removeListener(this);
                if (useDefaultClickBehaviour) {
                    ((Button) component).addListener(this);
                }
            }
        }
        updateParameters();
    }

    /**
     * In order to make the link at location index to visible / invisible, this
     * method must be used
     *
     * @param visible - sets links visible
     * @param index   -  index of link within breadcrumb layout
     */
    public void setLinkVisible(boolean visible, int index) {
        Component component = breadcrumbLayout.getComponent(index);
        if (component != null) {
            component.setVisible(visible);
            if (index == breadcrumbLayout.getComponentCount() - 1) {
                if (!visible) {
                    component.removeStyleName(CURRENT_STYLE_NAME);
                    while (index-- > 0) {
                        Component newLast = breadcrumbLayout.getComponent(index);
                        if (newLast.isVisible()) {
                            newLast.addStyleName(CURRENT_STYLE_NAME);
                            break;
                        }
                    }
                } else {
                    component.addStyleName(CURRENT_STYLE_NAME);
                    while (index-- > 0) {
                        Component newLast = breadcrumbLayout.getComponent(index);
                        if (newLast.getStyleName().contains((CURRENT_STYLE_NAME))) {
                            newLast.removeStyleName(CURRENT_STYLE_NAME);
                            break;
                        }
                    }
                }
            }
            updateParameters();
        }
    }

    /**
     * In order to enable/disable the link at location index, this method must
     * be used
     *
     * @param enabled - sets link enabled
     * @param index   - component index within breadcrumb
     */
    public void setLinkEnabled(boolean enabled, int index) {
        Component component = breadcrumbLayout.getComponent(index);
        if (component != null) {
            component.setEnabled(enabled);
            updateParameters();
        }
    }

    /**
     * Gets index of link
     *
     * @param link - vaadin button with link style
     * @return index of link within breadcrumb layout
     */
    public int getIndexOfLink(Component link) {
        Component li = componentToLi.get(link);
        return breadcrumbLayout.getComponentIndex(li);
    }

    @Override
    protected BreadcrumbState getState() {
        return (BreadcrumbState) super.getState();
    }

}
 

Lexaden
Easy to keep focus on business needs