/*******************************************************************************
 * Copyright (c) 2003, 2004 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
 *******************************************************************************/
package org.eclipse.jface.action;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

import org.eclipse.jface.util.Assert;
import org.eclipse.jface.util.Policy;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.CoolBar;
import org.eclipse.swt.widgets.CoolItem;
import org.eclipse.swt.widgets.Menu;

/**
 * A cool bar manager is a contribution manager which realizes itself and its
 * items in a cool bar control.
 * <p>
 * This class may be instantiated; it may also be subclassed.
 * </p>
 * 
 * @since 3.0
 */
public class CoolBarManager extends ContributionManager implements
        ICoolBarManager {

    /**
     * A separator created by the end user.
     */
    public final static String USER_SEPARATOR = "UserSeparator"; //$NON-NLS-1$

    /**
     * The original creation order of the contribution items.
     */
    private ArrayList cbItemsCreationOrder = new ArrayList();

    /**
     * MenuManager for cool bar pop-up menu, or null if none.
     */
    private MenuManager contextMenuManager = null;

    /**
     * The cool bar control; <code>null</code> before creation and after
     * disposal.
     */
    private CoolBar coolBar = null;

    /**
     * The cool bar items style; <code>SWT.NONE</code> by default.
     */
    private int itemStyle = SWT.NONE;

    /**
     * Creates a new cool bar manager with the default style. Equivalent to
     * <code>CoolBarManager(SWT.NONE)</code>.
     */
    public CoolBarManager() {
        // do nothing
    }

    /**
     * Creates a cool bar manager for an existing cool bar control. This
     * manager becomes responsible for the control, and will dispose of it when
     * the manager is disposed.
     * 
     * @param coolBar
     *            the cool bar control
     */
    public CoolBarManager(CoolBar coolBar) {
        this();
        Assert.isNotNull(coolBar);
        this.coolBar = coolBar;
        itemStyle = coolBar.getStyle();
    }

    /**
     * Creates a cool bar manager with the given SWT style. Calling <code>createControl</code>
     * will create the cool bar control.
     * 
     * @param style
     *            the cool bar item style; see
     *            {@link org.eclipse.swt.widgets.CoolBar CoolBar}for for valid
     *            style bits
     */
    public CoolBarManager(int style) {
        itemStyle = style;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.action.ICoolBarManager#add(org.eclipse.jface.action.IToolBarManager)
     */
    public void add(IToolBarManager toolBarManager) {
        Assert.isNotNull(toolBarManager);
        super.add(new ToolBarContributionItem(toolBarManager));
    }

    /**
     * Collapses consecutive separators and removes a separator from the
     * beginning and end of the list.
     * 
     * @param contributionList
     *            the list of contributions; must not be <code>null</code>.
     * @return The contribution list provided with extraneous separators
     *         removed; this value is never <code>null</code>, but may be
     *         empty.
     */
    private ArrayList adjustContributionList(ArrayList contributionList) {
        IContributionItem item;
        // Fist remove a separator if it is the first element of the list
        if (contributionList.size() != 0) {
            item = (IContributionItem) contributionList.get(0);
            if (item.isSeparator()) {
                contributionList.remove(0);
            }

            ListIterator iterator = contributionList.listIterator();
            // collapse consecutive separators
            while (iterator.hasNext()) {
                item = (IContributionItem) iterator.next();
                if (item.isSeparator()) {
                    while (iterator.hasNext()) {
                        item = (IContributionItem) iterator.next();
                        if (item.isSeparator()) {
                            iterator.remove();
                        } else {
                            break;
                        }
                    }

                }
            }
            // Now check last element to see if there is a separator
            item = (IContributionItem) contributionList.get(contributionList
                    .size() - 1);
            if (item.isSeparator()) {
                contributionList.remove(contributionList.size() - 1);
            }
        }
        return contributionList;

    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.action.ContributionManager#checkDuplication(org.eclipse.jface.action.IContributionItem)
     */
    protected boolean allowItem(IContributionItem itemToAdd) {
        /* We will allow as many null entries as they like, though there should
         * be none.
         */
        if (itemToAdd == null) {
            return true;
        }

        /* Null identifiers can be expected in generic contribution items.
         */
        String firstId = itemToAdd.getId();
        if (firstId == null) {
            return true;
        }

        // Cycle through the current list looking for duplicates.
        IContributionItem[] currentItems = getItems();
        for (int i = 0; i < currentItems.length; i++) {
            IContributionItem currentItem = currentItems[i];

            // We ignore null entries.
            if (currentItem == null) {
                continue;
            }

            String secondId = currentItem.getId();
            if (firstId.equals(secondId)) {
                if (Policy.TRACE_TOOLBAR) { 
                    System.out.println("Trying to add a duplicate item."); //$NON-NLS-1$
                    new Exception().printStackTrace(System.out);
                    System.out.println("DONE --------------------------"); //$NON-NLS-1$
                }
                return false;
            }
        }

        return true;
    }

    /**
     * Positions the list iterator to the end of all the separators. Calling
     * <code>next()</code> the iterator should return the immediate object
     * following the last separator.
     * 
     * @param iterator
     *            the list iterator.
     */
    private void collapseSeparators(ListIterator iterator) {

        while (iterator.hasNext()) {
            IContributionItem item = (IContributionItem) iterator.next();
            if (!item.isSeparator()) {
                iterator.previous();
                return;
            }
        }
    }

    /**
     * Returns whether the cool bar control has been created and not yet
     * disposed.
     * 
     * @return <code>true</code> if the control has been created and not yet
     *         disposed, <code>false</code> otherwise
     */
    private boolean coolBarExist() {
        return coolBar != null && !coolBar.isDisposed();
    }

    /**
     * Creates and returns this manager's cool bar control. Does not create a
     * new control if one already exists.
     * 
     * @param parent
     *            the parent control
     * @return the cool bar control
     */
    public CoolBar createControl(Composite parent) {
        Assert.isNotNull(parent);
        if (!coolBarExist()) {
            coolBar = new CoolBar(parent, itemStyle);
            coolBar.setMenu(getContextMenuControl());
            coolBar.setLocked(false);
            update(false);
        }
        return coolBar;
    }

    /**
     * Disposes of this cool bar manager and frees all allocated SWT resources.
     * Notifies all contribution items of the dispose. Note that this method
     * does not clean up references between this cool bar manager and its
     * associated contribution items. Use <code>removeAll</code> for that
     * purpose.
     */
    public void dispose() {
        if (coolBarExist()) {
            IContributionItem[] items = getItems();
            for (int i = 0; i < items.length; i++) {
                // Disposes of the contribution item.
                // If Contribution Item is a toolbar then it will dispose of
                // all the nested
                // contribution items.
                items[i].dispose();
            }
            coolBar.dispose();
            coolBar = null;
        }
        // If a context menu existed then dispose of it.
        if (contextMenuManager != null) {
            contextMenuManager.dispose();
            contextMenuManager = null;
        }

    }

    /**
     * Disposes the given cool item.
     * 
     * @param item
     *            the cool item to dispose
     */
    private void dispose(CoolItem item) {
        if ((item != null) && !item.isDisposed()) {

            item.setData(null);
            Control control = item.getControl();
            // if the control is already disposed, setting the coolitem
            // control to null will cause an SWT exception, workaround
            // for 19630
            if ((control != null) && !control.isDisposed()) {
                item.setControl(null);
            }
            item.dispose();
        }
    }

    /**
     * Finds the cool item associated with the given contribution item.
     * 
     * @param item
     *            the contribution item
     * @return the associated cool item, or <code>null</code> if not found
     */
    private CoolItem findCoolItem(IContributionItem item) {
        CoolItem[] coolItems = (coolBar == null) ? null : coolBar.getItems(); 
        return findCoolItem(coolItems, item);
    }
    
    private CoolItem findCoolItem(CoolItem[] items, IContributionItem item) {
        if (items == null)
            return null;

        for (int i = 0; i < items.length; i++) {
            CoolItem coolItem = items[i];
            IContributionItem data = (IContributionItem) coolItem.getData();
            if (data != null && data.equals(item))
                return coolItem;
        }
        return null;
    }

    /**
     * Return a consistent set of wrap indices. The return value will always
     * include at least one entry and the first entry will always be zero.
     * CoolBar.getWrapIndices() is inconsistent in whether or not it returns an
     * index for the first row.
     * 
     * @param wraps
     *            the wrap indicies from the cool bar widget
     * @return the adjusted wrap indicies.
     */
    private int[] getAdjustedWrapIndices(int[] wraps) {
        int[] adjustedWrapIndices;
        if (wraps.length == 0) {
            adjustedWrapIndices = new int[] { 0 };
        } else {
            if (wraps[0] != 0) {
                adjustedWrapIndices = new int[wraps.length + 1];
                adjustedWrapIndices[0] = 0;
                for (int i = 0; i < wraps.length; i++) {
                    adjustedWrapIndices[i + 1] = wraps[i];
                }
            } else {
                adjustedWrapIndices = wraps;
            }
        }
        return adjustedWrapIndices;
    }

    /**
     * Returns the control of the Menu Manager. If the menu manager does not
     * have a control then one is created.
     * 
     * @return menu control associated with manager, or null if none
     */
    private Menu getContextMenuControl() {
        if ((contextMenuManager != null) && (coolBar != null)) {
            Menu menuWidget = contextMenuManager.getMenu();
            if ((menuWidget == null) || (menuWidget.isDisposed())) {
                menuWidget = contextMenuManager.createContextMenu(coolBar);
            }
            return menuWidget;
        }
        return null;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.action.ICoolBarManager#isLayoutLocked()
     */
    public IMenuManager getContextMenuManager() {
        return contextMenuManager;
    }

    /**
     * Returns the cool bar control for this manager.
     * 
     * @return the cool bar control, or <code>null</code> if none
     */
    public CoolBar getControl() {
        return coolBar;
    }

    /**
     * Returns an array list of all the contribution items in the manager.
     * 
     * @return an array list of contribution items.
     */
    private ArrayList getItemList() {
        IContributionItem[] cbItems = getItems();
        ArrayList list = new ArrayList(cbItems.length);
        for (int i = 0; i < cbItems.length; i++) {
            list.add(cbItems[i]);
        }
        return list;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.action.ICoolBarManager#isLayoutLocked()
     */
    public boolean getLockLayout() {
        if (!coolBarExist()) {
            return false;
        }
        return coolBar.getLocked();
    }

    /**
     * Returns the number of rows that should be displayed visually.
     * 
     * @param items
     *            the array of contributin items
     * @return the number of rows
     */
    private int getNumRows(IContributionItem[] items) {
        int numRows = 1;
        boolean separatorFound = false;
        for (int i = 0; i < items.length; i++) {
            if (items[i].isSeparator()) {
                separatorFound = true;
            }
            if ((separatorFound) && (items[i].isVisible())
                    && (!items[i].isGroupMarker()) && (!items[i].isSeparator())) {
                numRows++;
                separatorFound = false;
            }
        }
        return numRows;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.action.ICoolBarManager#getStyle()
     */
    public int getStyle() {
        return itemStyle;
    }

    /**
     * Subclasses may extend this <code>ContributionManager</code> method,
     * but must call <code>super.itemAdded</code>.
     * 
     * @see org.eclipse.jface.action.ContributionManager#itemAdded(org.eclipse.jface.action.IContributionItem)
     */
    protected void itemAdded(IContributionItem item) {
        Assert.isNotNull(item);
        super.itemAdded(item);
        int insertedAt = indexOf(item);
        boolean replaced = false;
        final int size = cbItemsCreationOrder.size();
        for (int i = 0; i < size; i++) {
            IContributionItem created = (IContributionItem) cbItemsCreationOrder
                    .get(i);
            if (created.getId() != null && created.getId().equals(item.getId())) {
                cbItemsCreationOrder.set(i, item);
                replaced = true;
                break;
            }
        }

        if (!replaced) {
            cbItemsCreationOrder.add(Math.min(Math.max(insertedAt, 0),
                    cbItemsCreationOrder.size()), item);
        }
    }

    /**
     * Subclasses may extend this <code>ContributionManager</code> method,
     * but must call <code>super.itemRemoved</code>.
     * 
     * @see org.eclipse.jface.action.ContributionManager#itemRemoved(org.eclipse.jface.action.IContributionItem)
     */
    protected void itemRemoved(IContributionItem item) {
        Assert.isNotNull(item);
        super.itemRemoved(item);
        CoolItem coolItem = findCoolItem(item);
        if (coolItem != null) {
            coolItem.setData(null);
        }
    }

    /**
     * Positions the list iterator to the starting of the next row. By calling
     * next on the returned iterator, it will return the first element of the
     * next row.
     * 
     * @param iterator
     *            the list iterator of contribution items
     * @param ignoreCurrentItem
     *            Whether the current item in the iterator should be considered
     *            (as well as subsequent items).
     */
    private void nextRow(ListIterator iterator, boolean ignoreCurrentItem) {

        IContributionItem currentElement = null;
        if (!ignoreCurrentItem && iterator.hasPrevious()) {
            currentElement = (IContributionItem) iterator.previous();
            iterator.next();
        }

        if ((currentElement != null) && (currentElement.isSeparator())) {
            collapseSeparators(iterator);
            return;
        } 

        //Find next separator
        while (iterator.hasNext()) {
            IContributionItem item = (IContributionItem) iterator.next();
            if (item.isSeparator()) {
                // we we find a separator, collapse any consecutive
                // separators
                // and return
                collapseSeparators(iterator);
                return;
            }
        }
    }

    /*
     * Used for debuging. Prints all the items in the internal structures.
     */
    //    private void printContributions(ArrayList contributionList) {
    //        int index = 0;
    //        System.out.println("----------------------------------\n"); //$NON-NLS-1$
    //        for (Iterator i = contributionList.iterator(); i.hasNext(); index++) {
    //            IContributionItem item = (IContributionItem) i.next();
    //            if (item.isSeparator()) {
    //                System.out.println("Separator"); //$NON-NLS-1$
    //            } else {
    //                System.out.println(index + ". Item id: " + item.getId() //$NON-NLS-1$
    //                        + " - is Visible: " //$NON-NLS-1$
    //                        + item.isVisible());
    //            }
    //        }
    //    }
    /**
     * Synchronizes the visual order of the cool items in the control with this
     * manager's internal data structures. This method should be called before
     * requesting the order of the contribution items to ensure that the order
     * is accurate.
     * <p>
     * Note that <code>update()</code> and <code>refresh()</code> are
     * converses: <code>update()</code> changes the visual order to match the
     * internal structures, and <code>refresh</code> changes the internal
     * structures to match the visual order.
     * </p>
     */
    public void refresh() {
        if (!coolBarExist()) {
            return;
        }

        // Retreives the list of contribution items as an array list
        ArrayList contributionList = getItemList();

        // Check the size of the list
        if (contributionList.size() == 0)
            return;

        // The list of all the cool items in their visual order
        CoolItem[] coolItems = coolBar.getItems();
        // The wrap indicies of the coolbar
        int[] wrapIndicies = getAdjustedWrapIndices(coolBar.getWrapIndices());

        int row = 0;
        int coolItemIndex = 0;

        // Traverse through all cool items in the coolbar add them to a new
        // data structure
        // in the correct order
        ArrayList displayedItems = new ArrayList(coolBar.getItemCount());
        for (int i = 0; i < coolItems.length; i++) {
            CoolItem coolItem = coolItems[i];
            if (coolItem.getData() instanceof IContributionItem) {
                IContributionItem cbItem = (IContributionItem) coolItem
                        .getData();
                displayedItems.add(Math.min(i, displayedItems.size()), cbItem);
            }
        }

        // Add separators to the displayed Items data structure
        int offset = 0;
        for (int i = 1; i < wrapIndicies.length; i++) {
            int insertAt = wrapIndicies[i] + offset;
            displayedItems.add(insertAt, new Separator(USER_SEPARATOR));
            offset++;
        }

        // Determine which rows are invisible
        ArrayList existingVisibleRows = new ArrayList(4);
        ListIterator rowIterator = contributionList.listIterator();
        collapseSeparators(rowIterator);
        int numRow = 0;
        while (rowIterator.hasNext()) {
            // Scan row
            while (rowIterator.hasNext()) {
                IContributionItem cbItem = (IContributionItem) rowIterator
                        .next();
                if (displayedItems.contains(cbItem)) {
                    existingVisibleRows.add(new Integer(numRow));
                    break;
                }
                if (cbItem.isSeparator()) {
                    break;
                }
            }
            nextRow(rowIterator, false);
            numRow++;
        }

        Iterator existingRows = existingVisibleRows.iterator();
        // Adjust row number to the first visible
        if (existingRows.hasNext()) {
            row = ((Integer) existingRows.next()).intValue();
        }

        HashMap itemLocation = new HashMap();
        for (ListIterator locationIterator = displayedItems.listIterator(); locationIterator
                .hasNext();) {
            IContributionItem item = (IContributionItem) locationIterator
                    .next();
            if (item.isSeparator()) {
                if (existingRows.hasNext()) {
                    Integer value = (Integer) existingRows.next();
                    row = value.intValue();
                } else {
                    row++;
                }
            } else {
                itemLocation.put(item, new Integer(row));
            }

        }

        // Insert the contribution items in their correct location
        for (ListIterator iterator = displayedItems.listIterator(); iterator
                .hasNext();) {
            IContributionItem cbItem = (IContributionItem) iterator.next();
            if (cbItem.isSeparator()) {
                coolItemIndex = 0;
            } else {
                relocate(cbItem, coolItemIndex, contributionList, itemLocation);
                cbItem.saveWidgetState();
                coolItemIndex++;
            }
        }

        if (contributionList.size() != 0) {
            contributionList = adjustContributionList(contributionList);
            IContributionItem[] array = new IContributionItem[contributionList
                    .size() - 1];
            array = (IContributionItem[]) contributionList.toArray(array);
            internalSetItems(array);
        }

    }

    /**
     * Relocates the given contribution item to the specified index.
     * 
     * @param cbItem
     *            the conribution item to relocate
     * @param index
     *            the index to locate this item
     * @param contributionList
     *            the current list of conrtributions
     * @param itemLocation
     */
    private void relocate(IContributionItem cbItem, int index,
            ArrayList contributionList, HashMap itemLocation) {

        if (!(itemLocation.get(cbItem) instanceof Integer))
            return;
        int targetRow = ((Integer) itemLocation.get(cbItem)).intValue();

        int cbInternalIndex = contributionList.indexOf(cbItem);

        //	by default add to end of list
        int insertAt = contributionList.size();
        // Find the row to place this item in.
        ListIterator iterator = contributionList.listIterator();
        // bypass any separators at the begining
        collapseSeparators(iterator);
        int currentRow = -1;
        while (iterator.hasNext()) {

            currentRow++;
            if (currentRow == targetRow) {
                // We found the row to insert the item
                int virtualIndex = 0;
                insertAt = iterator.nextIndex();
                // first check the position of the current element (item)
                // then get the next element
                while (iterator.hasNext()) {
                    IContributionItem item = (IContributionItem) iterator
                            .next();
                    Integer itemRow = (Integer) itemLocation.get(item);
                    if (item.isSeparator())
                        break;
                    // if the item has an associate widget
                    if ((itemRow != null) && (itemRow.intValue() == targetRow)) {
                        // if the next element is the index we are looking for
                        // then break
                        if (virtualIndex >= index)
                            break;
                        virtualIndex++;

                    }
                    insertAt++;
                }
                // If we don't need to move it then we return
                if (cbInternalIndex == insertAt)
                    return;
                break;
            }
            nextRow(iterator, true);
        }
        contributionList.remove(cbItem);

        // Adjust insertAt index
        if (cbInternalIndex < insertAt) {
            insertAt--;
        }

        // if we didn't find the row then add a new row
        if (currentRow != targetRow) {
            contributionList.add(new Separator(USER_SEPARATOR));
            insertAt = contributionList.size();
        }
        insertAt = Math.min(insertAt, contributionList.size());
        contributionList.add(insertAt, cbItem);

    }

    /**
     * Restores the canonical order of this cool bar manager. The canonical
     * order is the order in which the contribution items where added.
     */
    public void resetItemOrder() {
        for (ListIterator iterator = cbItemsCreationOrder.listIterator(); iterator
                .hasNext();) {
            IContributionItem item = (IContributionItem) iterator.next();
            // if its a user separator then do not include in original order.
            if ((item.getId() != null) && (item.getId().equals(USER_SEPARATOR))) {
                iterator.remove();
            }
        }
        IContributionItem[] itemsToSet = new IContributionItem[cbItemsCreationOrder
                .size()];
        cbItemsCreationOrder.toArray(itemsToSet);
        setItems(itemsToSet);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.action.ICoolBarManager#setContextMenuManager(org.eclipse.jface.action.IMenuManager)
     */
    public void setContextMenuManager(IMenuManager contextMenuManager) {
        this.contextMenuManager = (MenuManager) contextMenuManager;
        if (coolBar != null) {
            coolBar.setMenu(getContextMenuControl());
        }
    }

    /**
     * Replaces the current items with the given items.
     * Forces an update.
     * 
     * @param newItems the items with which to replace the current items
     */
    public void setItems(IContributionItem[] newItems) {
        // dispose of all the cool items on the cool bar manager
        if (coolBar != null) {
            CoolItem[] coolItems = coolBar.getItems();
            for (int i = 0; i < coolItems.length; i++) {
                dispose(coolItems[i]);
            }
        }
        // Set the internal structure to this order
        internalSetItems(newItems);
        // Force and update
        update(true);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.action.ICoolBarManager#lockLayout(boolean)
     */
    public void setLockLayout(boolean value) {
        if (!coolBarExist()) {
            return;
        }
        coolBar.setLocked(value);
    }

    /**
     * Subclasses may extend this <code>IContributionManager</code> method,
     * but must call <code>super.update</code>.
     * 
     * @see org.eclipse.jface.action.IContributionManager#update(boolean)
     */
    public void update(boolean force) {
        if ((!isDirty() && !force) || (!coolBarExist())) {
            return;
        }

        boolean relock = false;
        boolean changed = false;

        try {
            coolBar.setRedraw(false);

            // Refresh the widget data with the internal data structure.
            refresh();

            if (coolBar.getLocked()) {
                coolBar.setLocked(false);
                relock = true;
            }

            /*
             * Make a list of items including only those items that are
             * visible. Separators should stay because they mark line breaks in
             * a cool bar.
             */
            final IContributionItem[] items = getItems();
            final List visibleItems = new ArrayList(items.length);
            for (int i = 0; i < items.length; i++) {
                final IContributionItem item = items[i];
                if (item.isVisible()) {
                    visibleItems.add(item);
                }
            }

            /*
             * Make a list of CoolItem widgets in the cool bar for which there
             * is no current visible contribution item. These are the widgets
             * to be disposed. Dynamic items are also removed.
             */
            CoolItem[] coolItems = coolBar.getItems();
            final ArrayList coolItemsToRemove = new ArrayList(coolItems.length);
            for (int i = 0; i < coolItems.length; i++) {
                final Object data = coolItems[i].getData();
                if ((data == null)
                        || (!visibleItems.contains(data))
                        || ((data instanceof IContributionItem) && ((IContributionItem) data)
                                .isDynamic())) {
                    coolItemsToRemove.add(coolItems[i]);
                }
            }

            // Dispose of any items in the list to be removed.
            for (int i = coolItemsToRemove.size() - 1; i >= 0; i--) {
                CoolItem coolItem = (CoolItem) coolItemsToRemove.get(i);
                if (!coolItem.isDisposed()) {
                    Control control = coolItem.getControl();
                    if (control != null) {
                        coolItem.setControl(null);
                        control.dispose();
                    }
                    coolItem.dispose();
                }
            }

            // Add any new items by telling them to fill.
            coolItems = coolBar.getItems();
            IContributionItem sourceItem;
            IContributionItem destinationItem;
            int sourceIndex = 0;
            int destinationIndex = 0;
            final Iterator visibleItemItr = visibleItems.iterator();
            while (visibleItemItr.hasNext()) {
                sourceItem = (IContributionItem) visibleItemItr.next();

                // Retrieve the corresponding contribution item from SWT's
                // data.
                if (sourceIndex < coolItems.length) {
                    destinationItem = (IContributionItem) coolItems[sourceIndex]
                            .getData();
                } else {
                    destinationItem = null;
                }

                // The items match is they are equal or both separators.
                if (destinationItem != null) {
                    if (sourceItem.equals(destinationItem)) {
                        sourceIndex++;
                        destinationIndex++;
                        sourceItem.update();
                        continue;

                    } else if ((destinationItem.isSeparator())
                            && (sourceItem.isSeparator())) {
                        coolItems[sourceIndex].setData(sourceItem);
                        sourceIndex++;
                        destinationIndex++;
                        sourceItem.update();
                        continue;

                    }
                }

                // Otherwise, a new item has to be added.
                final int start = coolBar.getItemCount();
                sourceItem.fill(coolBar, destinationIndex);
                final int newItems = coolBar.getItemCount() - start;
                for (int i = 0; i < newItems; i++) {
                    coolBar.getItem(destinationIndex++).setData(sourceItem);
                }
                changed = true;
            }

            // Remove any old widgets not accounted for.
            for (int i = coolItems.length - 1; i >= sourceIndex; i--) {
                final CoolItem item = coolItems[i];
                if (!item.isDisposed()) {
                    Control control = item.getControl();
                    if (control != null) {
                        item.setControl(null);
                        control.dispose();
                    }
                    item.dispose();
                    changed = true;
                }
            }

            // Update wrap indices.
            updateWrapIndices();

            // Update the sizes.
            for (int i = 0; i < items.length; i++) {
                IContributionItem item = items[i];
                item.update(SIZE);
            }

            // if the coolBar was previously locked then lock it
            if (relock) {
                coolBar.setLocked(true);
            }

            if (changed) {
                updateTabOrder();
            }

            // We are no longer dirty.
            setDirty(false);
        } finally {
            coolBar.setRedraw(true);
        }
    }

    /**
     * Sets the tab order of the coolbar to the visual order of its items.
     */
    /* package */void updateTabOrder() {
        if (coolBar != null) {
            CoolItem[] items = coolBar.getItems();
            if (items != null) {
                ArrayList children = new ArrayList(items.length);
                for (int i = 0; i < items.length; i++) {
                    if ((items[i].getControl() != null)
                            && (!items[i].getControl().isDisposed())) {
                        children.add(items[i].getControl());
                    }
                }
                // Convert array
                Control[] childrenArray = new Control[0];
                childrenArray = (Control[]) children.toArray(childrenArray);

                if (childrenArray != null) {
                    coolBar.setTabList(childrenArray);
                }

            }
        }
    }

    /**
     * Updates the indices at which the cool bar should wrap.
     */
    private void updateWrapIndices() {
        final IContributionItem[] items = getItems();
        final int numRows = getNumRows(items) - 1;

        // Generate the list of wrap indices.
        final int[] wrapIndices = new int[numRows];
        boolean foundSeparator = false;
        int j = 0;
        CoolItem[] coolItems = (coolBar == null) ? null : coolBar.getItems();

        for (int i = 0; i < items.length; i++) {
            IContributionItem item = items[i];
            CoolItem coolItem = findCoolItem(coolItems, item);
            if (item.isSeparator()) {
                foundSeparator = true;
            }
            if ((!item.isSeparator()) && (!item.isGroupMarker())
                    && (item.isVisible()) && (coolItem != null)
                    && (foundSeparator)) {
                wrapIndices[j] = coolBar.indexOf(coolItem);
                j++;
                foundSeparator = false;
            }
        }

        /*
         * Check to see if these new wrap indices are different than the old
         * ones.
         */
        final int[] oldIndices = coolBar.getWrapIndices();
        boolean shouldUpdate = false;
        if (oldIndices.length == wrapIndices.length) {
            for (int i = 0; i < oldIndices.length; i++) {
                if (oldIndices[i] != wrapIndices[i]) {
                    shouldUpdate = true;
                    break;
                }
            }
        } else {
            shouldUpdate = true;
        }

        if (shouldUpdate) {
            coolBar.setWrapIndices(wrapIndices);
        }
    }
}
