com.google.gwt.eclipse.oophm.breadcrumbs.BreadcrumbViewer.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gwt.eclipse.oophm.breadcrumbs.BreadcrumbViewer.java

Source

/*******************************************************************************
 * Copyright 2011 Google Inc. All Rights Reserved.
 *
 * 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
 *
 * 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 com.google.gwt.eclipse.oophm.breadcrumbs;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.jface.viewers.CellLabelProvider;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.OpenEvent;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.MenuDetectEvent;
import org.eclipse.swt.events.MenuDetectListener;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Widget;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

/**
 * A breadcrumb viewer shows a the parent chain of its input element in a list.
 * Each breadcrumb item of that list can be expanded and a sibling of the
 * element presented by the breadcrumb item can be selected.
 * <p>
 * Content providers for breadcrumb viewers must implement the
 * <code>ITreeContentProvider</code> interface.
 * </p>
 * <p>
 * Label providers for breadcrumb viewers must implement the
 * <code>ILabelProvider</code> interface.
 * </p>
 * 
 * NOTE: This code was derived from
 * org.eclipse.jdt.internal.ui.javaeditor.breadcrumb.BreadcrumbViewer.
 * 
 * @since 3.4
 */
@SuppressWarnings("unchecked")
public abstract class BreadcrumbViewer extends StructuredViewer {

    private static final boolean IS_GTK = "gtk".equals(SWT.getPlatform()); //$NON-NLS-1$

    private final Composite fContainer;
    private final ArrayList fBreadcrumbItems;
    private final ListenerList fMenuListeners;

    private Image fGradientBackground;
    private BreadcrumbItem fSelectedItem;
    private ILabelProvider fToolTipLabelProvider;

    /**
     * Create a new <code>BreadcrumbViewer</code>.
     * <p>
     * Style is one of:
     * <ul>
     * <li>SWT.NONE</li>
     * <li>SWT.VERTICAL</li>
     * <li>SWT.HORIZONTAL</li>
     * </ul>
     * 
     * @param parent the container for the viewer
     * @param style the style flag used for this viewer
     */
    public BreadcrumbViewer(Composite parent, int style) {
        fBreadcrumbItems = new ArrayList();
        fMenuListeners = new ListenerList();

        fContainer = new Composite(parent, SWT.NONE);
        GridData layoutData = new GridData(SWT.FILL, SWT.TOP, true, false);
        fContainer.setLayoutData(layoutData);
        fContainer.addTraverseListener(new TraverseListener() {
            public void keyTraversed(TraverseEvent e) {
                e.doit = true;
            }
        });
        fContainer.setBackgroundMode(SWT.INHERIT_DEFAULT);

        fContainer.addListener(SWT.Resize, new Listener() {
            public void handleEvent(Event event) {
                int height = fContainer.getClientArea().height;

                if (fGradientBackground == null || fGradientBackground.getBounds().height != height) {
                    Image image = createGradientImage(height, event.display);
                    fContainer.setBackgroundImage(image);

                    if (fGradientBackground != null)
                        fGradientBackground.dispose();
                    fGradientBackground = image;
                }
            }
        });
        fContainer.addDisposeListener(new DisposeListener() {
            public void widgetDisposed(DisposeEvent e) {
                if (fGradientBackground != null) {
                    fGradientBackground.dispose();
                }
            }
        });

        hookControl(fContainer);

        int columns = 1000;
        if ((SWT.VERTICAL & style) != 0) {
            columns = 1;
        }

        GridLayout gridLayout = new GridLayout(columns, false);
        gridLayout.marginWidth = 0;
        gridLayout.marginHeight = 0;
        gridLayout.verticalSpacing = 0;
        gridLayout.horizontalSpacing = 0;
        fContainer.setLayout(gridLayout);

        fContainer.addListener(SWT.Resize, new Listener() {
            public void handleEvent(Event event) {
                refresh();
            }
        });
    }

    /**
     * Add the given listener to the set of listeners which will be informed when
     * a context menu is requested for a breadcrumb item.
     * 
     * @param listener the listener to add
     */
    public void addMenuDetectListener(MenuDetectListener listener) {
        fMenuListeners.add(listener);
    }

    /*
     * @see org.eclipse.jface.viewers.Viewer#getControl()
     */
    public Control getControl() {
        return fContainer;
    }

    /**
     * Returns the selection provider which provides the selection of the drop
     * down currently opened or <code>null</code> if no drop down is open at the
     * moment.
     * 
     * @return the selection provider of the open drop down or <code>null</code>
     */
    public ISelectionProvider getDropDownSelectionProvider() {
        for (int i = 0, size = fBreadcrumbItems.size(); i < size; i++) {
            BreadcrumbItem item = (BreadcrumbItem) fBreadcrumbItems.get(i);
            if (item.isMenuShown()) {
                return item.getDropDownSelectionProvider();
            }
        }

        return null;
    }

    /**
     * The shell used for the shown drop down or <code>null</code> if no drop down
     * is shown at the moment.
     * 
     * @return the drop downs shell or <code>null</code>
     */
    public Shell getDropDownShell() {
        for (int i = 0, size = fBreadcrumbItems.size(); i < size; i++) {
            BreadcrumbItem item = (BreadcrumbItem) fBreadcrumbItems.get(i);
            if (item.isMenuShown())
                return item.getDropDownShell();
        }

        return null;
    }

    /**
     * @return true if any of the items in the viewer is expanded
     */
    public boolean isDropDownOpen() {
        for (int i = 0, size = fBreadcrumbItems.size(); i < size; i++) {
            BreadcrumbItem item = (BreadcrumbItem) fBreadcrumbItems.get(i);
            if (item.isMenuShown())
                return true;
        }

        return false;
    }

    /**
     * Remove the given listener from the set of menu detect listeners. Does
     * nothing if the listener is not element of the set.
     * 
     * @param listener the listener to remove
     */
    public void removeMenuDetectListener(MenuDetectListener listener) {
        fMenuListeners.remove(listener);
    }

    /*
     * @see org.eclipse.jface.viewers.StructuredViewer#reveal(java.lang.Object)
     */
    public void reveal(Object element) {
        // all elements are always visible
    }

    /**
     * Transfers the keyboard focus into the viewer.
     */
    public void setFocus() {
        fContainer.setFocus();

        if (fSelectedItem != null) {
            fSelectedItem.setFocus(true);
        } else {
            if (fBreadcrumbItems.size() == 0)
                return;

            BreadcrumbItem item = (BreadcrumbItem) fBreadcrumbItems.get(fBreadcrumbItems.size() - 1);
            if (item.getData() == null) {
                if (fBreadcrumbItems.size() < 2)
                    return;

                item = (BreadcrumbItem) fBreadcrumbItems.get(fBreadcrumbItems.size() - 2);
            }
            item.setFocus(true);
        }
    }

    /**
     * The tool tip to use for the tool tip labels. <code>null</code> if the
     * viewers label provider should be used.
     * 
     * @param toolTipLabelProvider the label provider for the tool tips or
     *          <code>null</code>
     */
    public void setToolTipLabelProvider(ILabelProvider toolTipLabelProvider) {
        fToolTipLabelProvider = toolTipLabelProvider;
    }

    /*
     * @see
     * org.eclipse.jface.viewers.StructuredViewer#assertContentProviderType(org
     * .eclipse.jface.viewers.IContentProvider)
     */
    protected void assertContentProviderType(IContentProvider provider) {
        super.assertContentProviderType(provider);
        Assert.isTrue(provider instanceof ITreeContentProvider);
    }

    /**
     * Configure the given drop down viewer. The given input is used for the
     * viewers input. Clients must at least set the label and the content provider
     * for the viewer.
     * 
     * @param viewer the viewer to configure
     * @param input the input for the viewer
     */
    protected abstract void configureDropDownViewer(TreeViewer viewer, Object input);

    /*
     * @see
     * org.eclipse.jface.viewers.StructuredViewer#doFindInputItem(java.lang.Object
     * )
     */
    protected Widget doFindInputItem(Object element) {
        if (element == null)
            return null;

        if (element == getInput() || element.equals(getInput()))
            return doFindItem(element);

        return null;
    }

    /*
     * @see
     * org.eclipse.jface.viewers.StructuredViewer#doFindItem(java.lang.Object)
     */
    protected Widget doFindItem(Object element) {
        if (element == null)
            return null;

        for (int i = 0, size = fBreadcrumbItems.size(); i < size; i++) {
            BreadcrumbItem item = (BreadcrumbItem) fBreadcrumbItems.get(i);
            if (item.getData() == element || element.equals(item.getData()))
                return item;
        }

        return null;
    }

    /*
     * @see
     * org.eclipse.jface.viewers.StructuredViewer#doUpdateItem(org.eclipse.swt
     * .widgets.Widget, java.lang.Object, boolean)
     */
    protected void doUpdateItem(Widget widget, Object element, boolean fullMap) {
        if (widget instanceof BreadcrumbItem) {
            final BreadcrumbItem item = (BreadcrumbItem) widget;

            // remember element we are showing
            if (fullMap) {
                associate(element, item);
            } else {
                Object data = item.getData();
                if (data != null) {
                    unmapElement(data, item);
                }
                item.setData(element);
                mapElement(element, item);
            }

            BreadcrumbViewerRow row = new BreadcrumbViewerRow(this, item);
            ViewerCell cell = row.getCell(0);

            ((CellLabelProvider) getLabelProvider()).update(cell);

            item.refreshArrow();

            if (fToolTipLabelProvider != null) {
                item.setToolTip(fToolTipLabelProvider.getText(item.getData()));
            } else {
                item.setToolTip(cell.getText());
            }
        }
    }

    @Override
    public void refresh() {
        /*
         * By default only the root element is refreshed. However the root element
         * has no links to the children so any children of the root are not
         * refreshed by default. Here we will enumerate the current set of
         * breadcrumb items and refresh them individually.
         */
        List<BreadcrumbItem> breadcrumbItems = fBreadcrumbItems;
        for (BreadcrumbItem breadcrumbItem : breadcrumbItems) {
            refresh(breadcrumbItem.getData());
        }
    }

    /*
     * @see org.eclipse.jface.viewers.StructuredViewer#getRoot()
     */
    protected Object getRoot() {
        if (fBreadcrumbItems.isEmpty())
            return null;

        return ((BreadcrumbItem) fBreadcrumbItems.get(0)).getData();
    }

    /*
     * @see org.eclipse.jface.viewers.StructuredViewer#getSelectionFromWidget()
     */
    protected List getSelectionFromWidget() {
        if (fSelectedItem == null)
            return Collections.EMPTY_LIST;

        if (fSelectedItem.getData() == null)
            return Collections.EMPTY_LIST;

        ArrayList result = new ArrayList();
        result.add(fSelectedItem.getData());
        return result;
    }

    /*
     * @see org.eclipse.jface.viewers.Viewer#inputChanged(java.lang.Object,
     * java.lang.Object)
     */
    protected void inputChanged(Object fInput, Object oldInput) {
        if (fContainer.isDisposed())
            return;

        disableRedraw();
        try {
            if (fBreadcrumbItems.size() > 0) {
                BreadcrumbItem last = (BreadcrumbItem) fBreadcrumbItems.get(fBreadcrumbItems.size() - 1);
                last.setIsLastItem(false);
            }

            int lastIndex = buildItemChain(fInput);

            if (lastIndex > 0) {
                BreadcrumbItem last = (BreadcrumbItem) fBreadcrumbItems.get(lastIndex - 1);
                last.setIsLastItem(true);
            }

            while (lastIndex < fBreadcrumbItems.size()) {
                BreadcrumbItem item = (BreadcrumbItem) fBreadcrumbItems.remove(fBreadcrumbItems.size() - 1);
                if (item == fSelectedItem) {
                    selectItem(null);
                }
                if (item.getData() != null)
                    unmapElement(item.getData());
                item.dispose();
            }

            updateSize();
            fContainer.layout(true, true);
        } finally {
            enableRedraw();
        }
    }

    /*
     * @see
     * org.eclipse.jface.viewers.StructuredViewer#internalRefresh(java.lang.Object
     * )
     */
    protected void internalRefresh(Object element) {

        disableRedraw();
        try {
            BreadcrumbItem item = (BreadcrumbItem) doFindItem(element);
            if (item == null) {
                for (int i = 0, size = fBreadcrumbItems.size(); i < size; i++) {
                    BreadcrumbItem item1 = (BreadcrumbItem) fBreadcrumbItems.get(i);
                    item1.refresh();
                }
            } else {
                item.refresh();
            }
            if (updateSize())
                fContainer.layout(true, true);
        } finally {
            enableRedraw();
        }
    }

    /*
     * @see
     * org.eclipse.jface.viewers.StructuredViewer#setSelectionToWidget(java.util
     * .List, boolean)
     */
    protected void setSelectionToWidget(List l, boolean reveal) {
        BreadcrumbItem focusItem = null;

        for (int i = 0, size = fBreadcrumbItems.size(); i < size; i++) {
            BreadcrumbItem item = (BreadcrumbItem) fBreadcrumbItems.get(i);
            if (item.hasFocus())
                focusItem = item;

            item.setSelected(false);
        }

        if (l == null)
            return;

        for (Iterator iterator = l.iterator(); iterator.hasNext();) {
            Object element = iterator.next();
            BreadcrumbItem item = (BreadcrumbItem) doFindItem(element);
            if (item != null) {
                item.setSelected(true);
                fSelectedItem = item;
                if (item == focusItem) {
                    item.setFocus(true);
                }
            }
        }
    }

    /**
     * Set selection to the next or previous element if possible.
     * 
     * @param next <code>true</code> if the next element should be selected,
     *          otherwise the previous one will be selected
     */
    void doTraverse(boolean next) {
        if (fSelectedItem == null)
            return;

        int index = fBreadcrumbItems.indexOf(fSelectedItem);
        if (next) {
            if (index == fBreadcrumbItems.size() - 1) {
                BreadcrumbItem current = (BreadcrumbItem) fBreadcrumbItems.get(index);

                ITreeContentProvider contentProvider = (ITreeContentProvider) getContentProvider();
                if (!contentProvider.hasChildren(current.getData()))
                    return;

                current.openDropDownMenu();
                current.getDropDownShell().setFocus();
            } else {
                BreadcrumbItem nextItem = (BreadcrumbItem) fBreadcrumbItems.get(index + 1);
                selectItem(nextItem);
            }
        } else {
            if (index == 1) {
                BreadcrumbItem root = (BreadcrumbItem) fBreadcrumbItems.get(0);
                root.openDropDownMenu();
                root.getDropDownShell().setFocus();
            } else {
                selectItem((BreadcrumbItem) fBreadcrumbItems.get(index - 1));
            }
        }
    }

    /**
     * Notifies all double click listeners.
     */
    void fireDoubleClick() {
        fireDoubleClick(new DoubleClickEvent(this, getSelection()));
    }

    /**
     * A context menu has been requested for the selected breadcrumb item.
     * 
     * @param event the event issued the menu detection
     */
    void fireMenuDetect(MenuDetectEvent event) {
        Object[] listeners = fMenuListeners.getListeners();
        for (int i = 0; i < listeners.length; i++) {
            ((MenuDetectListener) listeners[i]).menuDetected(event);
        }
    }

    /**
     * The given element was selected from a drop down menu.
     * 
     * @param element the selected element
     */
    void fireMenuSelection(Object element) {
        fireOpen(new OpenEvent(this, new StructuredSelection(element)));
    }

    /**
     * Notifies all open listeners.
     */
    void fireOpen() {
        fireOpen(new OpenEvent(this, getSelection()));
    }

    /**
     * Returns the index of the given item.
     * 
     * @param item the item to search
     * @return the index of the item or -1 if not found
     */
    int getIndexOfItem(BreadcrumbItem item) {
        for (int i = 0, size = fBreadcrumbItems.size(); i < size; i++) {
            BreadcrumbItem pItem = (BreadcrumbItem) fBreadcrumbItems.get(i);
            if (pItem == item)
                return i;
        }

        return -1;
    }

    /**
     * Returns the item for the given item index.
     * 
     * @param index the index of the item
     * @return the item ad the given <code>index</code>
     */
    BreadcrumbItem getItem(int index) {
        return (BreadcrumbItem) fBreadcrumbItems.get(index);
    }

    /**
     * Returns the item count.
     * 
     * @return number of items shown in the viewer
     */
    int getItemCount() {
        return fBreadcrumbItems.size();
    }

    /**
     * Set a single selection to the given item. <code>null</code> to deselect
     * all.
     * 
     * @param item the item to select or <code>null</code>
     */
    void selectItem(BreadcrumbItem item) {
        if (fSelectedItem != null)
            fSelectedItem.setSelected(false);

        fSelectedItem = item;
        setSelectionToWidget(getSelection(), false);

        if (item != null) {
            setFocus();
        } else {
            for (int i = 0, size = fBreadcrumbItems.size(); i < size; i++) {
                BreadcrumbItem listItem = (BreadcrumbItem) fBreadcrumbItems.get(i);
                listItem.setFocus(false);
            }
        }

        fireSelectionChanged(new SelectionChangedEvent(this, getSelection()));
    }

    /**
     * Generates the parent chain of the given element.
     * 
     * @param element element to build the parent chain for
     * @return the first index of an item in fBreadcrumbItems which is not part of
     *         the chain
     */
    private int buildItemChain(Object element) {
        if (element == null)
            return 0;

        ITreeContentProvider contentProvider = (ITreeContentProvider) getContentProvider();
        Object parent = contentProvider.getParent(element);

        int index = buildItemChain(parent);

        BreadcrumbItem item;
        if (index < fBreadcrumbItems.size()) {
            item = (BreadcrumbItem) fBreadcrumbItems.get(index);
            if (item.getData() != null)
                unmapElement(item.getData());
        } else {
            item = createItem();
            fBreadcrumbItems.add(item);
        }

        if (equals(element, item.getData())) {
            update(element, null);
        } else {
            item.setData(element);
            item.refresh();
        }
        if (parent == null) {
            // don't show the models root
            item.setDetailsVisible(false);
        }

        mapElement(element, item);

        return index + 1;
    }

    private Color createColor(int color1, int color2, int ratio, Display display) {
        RGB rgb1 = display.getSystemColor(color1).getRGB();
        RGB rgb2 = display.getSystemColor(color2).getRGB();

        RGB blend = ColorBlender.blend(rgb2, rgb1, ratio);

        return new Color(display, blend);
    }

    /**
     * The image to use for the breadcrumb background as specified in
     * https://bugs.eclipse.org/bugs/show_bug.cgi?id=221477
     * 
     * @param height the height of the image to create
     * @param display the current display
     * @return the image for the breadcrumb background
     */
    private Image createGradientImage(int height, Display display) {
        int width = 50;

        Image result = new Image(display, width, height);

        GC gc = new GC(result);

        Color colorC = createColor(SWT.COLOR_WIDGET_BACKGROUND, SWT.COLOR_LIST_BACKGROUND, 35, display);
        Color colorD = createColor(SWT.COLOR_WIDGET_BACKGROUND, SWT.COLOR_LIST_BACKGROUND, 45, display);
        Color colorE = createColor(SWT.COLOR_WIDGET_BACKGROUND, SWT.COLOR_LIST_BACKGROUND, 80, display);
        Color colorF = createColor(SWT.COLOR_WIDGET_BACKGROUND, SWT.COLOR_LIST_BACKGROUND, 70, display);
        Color colorG = createColor(SWT.COLOR_WIDGET_BACKGROUND, SWT.COLOR_WHITE, 45, display);
        Color colorH = createColor(SWT.COLOR_WIDGET_NORMAL_SHADOW, SWT.COLOR_LIST_BACKGROUND, 35, display);

        try {
            drawLine(width, 0, colorC, gc);
            drawLine(width, 1, colorC, gc);

            gc.setForeground(colorD);
            gc.setBackground(colorE);
            gc.fillGradientRectangle(0, 2, width, 2 + 8, true);

            gc.setBackground(colorE);
            gc.fillRectangle(0, 2 + 9, width, height - 4);

            drawLine(width, height - 3, colorF, gc);
            drawLine(width, height - 2, colorG, gc);
            drawLine(width, height - 1, colorH, gc);

        } finally {
            gc.dispose();

            colorC.dispose();
            colorD.dispose();
            colorE.dispose();
            colorF.dispose();
            colorG.dispose();
            colorH.dispose();
        }

        return result;
    }

    /**
     * Creates and returns a new instance of a breadcrumb item.
     * 
     * @return new instance of a breadcrumb item
     */
    private BreadcrumbItem createItem() {
        BreadcrumbItem result = new BreadcrumbItem(this, fContainer);

        result.setLabelProvider((ILabelProvider) getLabelProvider());
        if (fToolTipLabelProvider != null) {
            result.setToolTipLabelProvider(fToolTipLabelProvider);
        } else {
            result.setToolTipLabelProvider((ILabelProvider) getLabelProvider());
        }
        result.setContentProvider((ITreeContentProvider) getContentProvider());

        return result;
    }

    /**
     * Disables redrawing of the breadcrumb.
     * 
     * <p>
     * <strong>A call to this method must be followed by a call to
     * {@link #enableRedraw()}</strong>
     * </p>
     */
    private void disableRedraw() {
        if (IS_GTK) // flickers on GTK
            return;

        fContainer.setRedraw(false);
    }

    private void drawLine(int width, int position, Color color, GC gc) {
        gc.setForeground(color);
        gc.drawLine(0, position, width, position);
    }

    /**
     * Enables redrawing of the breadcrumb.
     */
    private void enableRedraw() {
        if (IS_GTK) // flickers on GTK
            return;

        fContainer.setRedraw(true);
    }

    /**
     * Returns the current width of all items in the list.
     * 
     * @return the width of all items in the list
     */
    private int getCurrentWidth() {
        int result = 0;
        for (int i = 0, size = fBreadcrumbItems.size(); i < size; i++) {
            BreadcrumbItem viewer = (BreadcrumbItem) fBreadcrumbItems.get(i);
            result += viewer.getWidth();
        }

        return result;
    }

    /**
     * Update the size of the items such that all items are visible, if possible.
     * 
     * @return <code>true</code> if any item has changed, <code>false</code>
     *         otherwise
     */
    private boolean updateSize() {
        int width = fContainer.getClientArea().width;

        int currentWidth = getCurrentWidth();

        boolean requiresLayout = false;

        if (currentWidth > width) {
            int index = 0;
            while (currentWidth > width && index < fBreadcrumbItems.size() - 1) {
                BreadcrumbItem viewer = (BreadcrumbItem) fBreadcrumbItems.get(index);
                if (viewer.isShowText()) {
                    viewer.setShowText(false);
                    currentWidth = getCurrentWidth();
                    requiresLayout = true;
                }

                index++;
            }

        } else if (currentWidth < width) {

            int index = fBreadcrumbItems.size() - 1;
            while (currentWidth < width && index >= 0) {

                BreadcrumbItem viewer = (BreadcrumbItem) fBreadcrumbItems.get(index);
                if (!viewer.isShowText()) {
                    viewer.setShowText(true);
                    currentWidth = getCurrentWidth();
                    if (currentWidth > width) {
                        viewer.setShowText(false);
                        index = 0;
                    } else {
                        requiresLayout = true;
                    }
                }

                index--;
            }
        }

        return requiresLayout;
    }

}