diff org.eclipse.jface/src/org/eclipse/jface/action/CoolBarManager.d @ 12:bc29606a740c

Added dwt-addons in original directory structure of eclipse.org
author Frank Benoit <benoit@tionex.de>
date Sat, 14 Mar 2009 18:23:29 +0100
parents
children 735224fcc45f
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.jface/src/org/eclipse/jface/action/CoolBarManager.d	Sat Mar 14 18:23:29 2009 +0100
@@ -0,0 +1,1054 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.jface.action.CoolBarManager;
+
+import org.eclipse.jface.action.ToolBarContributionItem;
+import org.eclipse.jface.action.Separator;
+
+import org.eclipse.jface.action.ContributionManager;
+import org.eclipse.jface.action.IContributionManager;
+import org.eclipse.jface.action.IContributionItem;
+import org.eclipse.jface.action.ICoolBarManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+
+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;
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.jface.util.Policy;
+
+import java.lang.all;
+import java.util.ListIterator;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.HashMap;
+import java.util.Set;
+import tango.io.Stdout;
+
+/**
+ * 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 : ContributionManager,
+        ICoolBarManager {
+    alias ContributionManager.add add;
+
+    /**
+     * 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;
+
+    /**
+     * 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 this() {
+        cbItemsCreationOrder = new ArrayList();
+        // 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 this(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 this(int style) {
+        cbItemsCreationOrder = new ArrayList();
+        itemStyle = style;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.eclipse.jface.action.ICoolBarManager#add(org.eclipse.jface.action.IToolBarManager)
+     */
+    public void add(IToolBarManager toolBarManager) {
+        Assert.isNotNull(cast(Object)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() !is 0) {
+            item = cast(IContributionItem) contributionList.get(0);
+            if (item.isSeparator()) {
+                contributionList.remove(0);
+            }
+
+            auto iterator = contributionList.listIterator();
+            // collapse consecutive separators
+            while (iterator.hasNext()) {
+                item = cast(IContributionItem) iterator.next();
+                if (item.isSeparator()) {
+                    while (iterator.hasNext()) {
+                        item = cast(IContributionItem) iterator.next();
+                        if (item.isSeparator()) {
+                            iterator.remove();
+                        } else {
+                            break;
+                        }
+                    }
+
+                }
+            }
+            // Now check last element to see if there is a separator
+            item = cast(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 override bool allowItem(IContributionItem itemToAdd) {
+        /* We will allow as many null entries as they like, though there should
+         * be none.
+         */
+        if (itemToAdd is null) {
+            return true;
+        }
+
+        /* Null identifiers can be expected in generic contribution items.
+         */
+        String firstId = itemToAdd.getId();
+        if (firstId is 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 is null) {
+                continue;
+            }
+
+            String secondId = currentItem.getId();
+            if (firstId.equals(secondId)) {
+                if (Policy.TRACE_TOOLBAR) {
+                    Stdout.formatln("Trying to add a duplicate item."); //$NON-NLS-1$
+                    ExceptionPrintStackTrace(new Exception(null), Stdout );
+                    Stdout.formatln("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 = cast(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 bool coolBarExist() {
+        return coolBar !is 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()) {
+            coolBar.dispose();
+            coolBar = null;
+        }
+        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();
+        }
+        // If a context menu existed then dispose of it.
+        if (contextMenuManager !is null) {
+            contextMenuManager.dispose();
+            contextMenuManager = null;
+        }
+
+    }
+
+    /**
+     * Disposes the given cool item.
+     *
+     * @param item
+     *            the cool item to dispose
+     */
+    private void dispose(CoolItem item) {
+        if ((item !is 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 !is 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 is null) ? null : coolBar.getItems();
+        return findCoolItem(coolItems, item);
+    }
+
+    private CoolItem findCoolItem(CoolItem[] items, IContributionItem item) {
+        if (items is null) {
+            return null;
+        }
+
+        for (int i = 0; i < items.length; i++) {
+            CoolItem coolItem = items[i];
+            IContributionItem data = cast(IContributionItem) coolItem.getData();
+            if (data !is null && (cast(Object)data).opEquals(cast(Object)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 is 0) {
+            adjustedWrapIndices = [ 0 ];
+        } else {
+            if (wraps[0] !is 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 !is null) && (coolBar !is null)) {
+            Menu menuWidget = contextMenuManager.getMenu();
+            if ((menuWidget is 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( cast(Object) cbItems[i]);
+        }
+        return list;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.eclipse.jface.action.ICoolBarManager#isLayoutLocked()
+     */
+    public bool 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;
+        bool 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 override void itemAdded(IContributionItem item) {
+        Assert.isNotNull(cast(Object)item);
+        super.itemAdded(item);
+        int insertedAt = indexOf(item);
+        bool replaced = false;
+        final int size = cbItemsCreationOrder.size();
+        for (int i = 0; i < size; i++) {
+            IContributionItem created = cast(IContributionItem) cbItemsCreationOrder
+                    .get(i);
+            if (created.getId() !is null && created.getId().equals(item.getId())) {
+                cbItemsCreationOrder.set(i, cast(Object) item);
+                replaced = true;
+                break;
+            }
+        }
+
+        if (!replaced) {
+            cbItemsCreationOrder.add(Math.min(Math.max(insertedAt, 0),
+                    cbItemsCreationOrder.size()), cast(Object) 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 override void itemRemoved(IContributionItem item) {
+        Assert.isNotNull(cast(Object)item);
+        super.itemRemoved(item);
+        CoolItem coolItem = findCoolItem(item);
+        if (coolItem !is 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, bool ignoreCurrentItem) {
+
+        IContributionItem currentElement = null;
+        if (!ignoreCurrentItem && iterator.hasPrevious()) {
+            currentElement = cast(IContributionItem) iterator.previous();
+            iterator.next();
+        }
+
+        if ((currentElement !is null) && (currentElement.isSeparator())) {
+            collapseSeparators(iterator);
+            return;
+        }
+
+        //Find next separator
+        while (iterator.hasNext()) {
+            IContributionItem item = cast(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
+        auto contributionList = getItemList();
+
+        // Check the size of the list
+        if (contributionList.size() is 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
+        auto displayedItems = new ArrayList(coolBar.getItemCount());
+        for (int i = 0; i < coolItems.length; i++) {
+            CoolItem coolItem = coolItems[i];
+            if ( auto cbItem = cast(IContributionItem) coolItem.getData() ) {
+                displayedItems.add(Math.min(i, displayedItems.size()), cast(Object) 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
+        auto existingVisibleRows = new ArrayList(4);
+        ListIterator rowIterator = contributionList.listIterator();
+        collapseSeparators(rowIterator);
+        int numRow = 0;
+        while (rowIterator.hasNext()) {
+            // Scan row
+            while (rowIterator.hasNext()) {
+                IContributionItem cbItem = cast(IContributionItem) rowIterator
+                        .next();
+                if (displayedItems.contains(cast(Object) cbItem)) {
+                    existingVisibleRows.add(new Integer(numRow));
+                    break;
+                }
+                if (cbItem.isSeparator()) {
+                    break;
+                }
+            }
+            nextRow(rowIterator, false);
+            numRow++;
+        }
+
+        auto existingRows = existingVisibleRows.iterator();
+        // Adjust row number to the first visible
+        if (existingRows.hasNext()) {
+            row = (cast(Integer) existingRows.next()).intValue();
+        }
+
+        auto itemLocation = new HashMap();
+        for (ListIterator locationIterator = displayedItems.listIterator(); locationIterator
+                .hasNext();) {
+            IContributionItem item = cast(IContributionItem) locationIterator
+                    .next();
+            if (item.isSeparator()) {
+                if (existingRows.hasNext()) {
+                    Integer value = cast(Integer) existingRows.next();
+                    row = value.intValue();
+                } else {
+                    row++;
+                }
+            } else {
+                itemLocation.put(cast(Object)item, new Integer(row));
+            }
+
+        }
+
+        // Insert the contribution items in their correct location
+        for (ListIterator iterator = displayedItems.listIterator(); iterator
+                .hasNext();) {
+            IContributionItem cbItem = cast(IContributionItem) iterator.next();
+            if (cbItem.isSeparator()) {
+                coolItemIndex = 0;
+            } else {
+                relocate(cbItem, coolItemIndex, contributionList, itemLocation);
+                cbItem.saveWidgetState();
+                coolItemIndex++;
+            }
+        }
+
+        if (contributionList.size() !is 0) {
+            contributionList = adjustContributionList(contributionList);
+            IContributionItem[] array = arraycast!(IContributionItem)( contributionList.toArray());
+            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 (!(cast(Integer)itemLocation.get(cast(Object)cbItem) )) {
+            return;
+        }
+        int targetRow = (cast(Integer) itemLocation.get(cast(Object)cbItem)).intValue();
+
+        int cbInternalIndex = contributionList.indexOf(cast(Object)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 is 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 = cast(IContributionItem) iterator
+                            .next();
+                    Integer itemRow = cast(Integer) itemLocation.get( cast(Object) item);
+                    if (item.isSeparator()) {
+                        break;
+                    }
+                    // if the item has an associate widget
+                    if ((itemRow !is null) && (itemRow.intValue() is 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 is insertAt) {
+                    return;
+                }
+                break;
+            }
+            nextRow(iterator, true);
+        }
+        contributionList.remove(cast(Object) cbItem);
+
+        // Adjust insertAt index
+        if (cbInternalIndex < insertAt) {
+            insertAt--;
+        }
+
+        // if we didn't find the row then add a new row
+        if (currentRow !is targetRow) {
+            contributionList.add(new Separator(USER_SEPARATOR));
+            insertAt = contributionList.size();
+        }
+        insertAt = Math.min(insertAt, contributionList.size());
+        contributionList.add(insertAt, cast(Object) 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 = cast(IContributionItem) iterator.next();
+            // if its a user separator then do not include in original order.
+            if ((item.getId() !is null) && (item.getId().equals(USER_SEPARATOR))) {
+                iterator.remove();
+            }
+        }
+        IContributionItem[] itemsToSet = arraycast!(IContributionItem)(cbItemsCreationOrder.toArray());
+        setItems(itemsToSet);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.eclipse.jface.action.ICoolBarManager#setContextMenuManager(org.eclipse.jface.action.IMenuManager)
+     */
+    public void setContextMenuManager(IMenuManager contextMenuManager) {
+        this.contextMenuManager = cast(MenuManager) contextMenuManager;
+        if (coolBar !is 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 !is 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(bool)
+     */
+    public void setLockLayout(bool 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(bool)
+     */
+    public void update(bool force) {
+        if ((!isDirty() && !force) || (!coolBarExist())) {
+            return;
+        }
+
+        bool relock = false;
+        bool 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.
+             */
+            IContributionItem[] items = getItems();
+            List visibleItems = new ArrayList(items.length);
+            for (int i = 0; i < items.length; i++) {
+                IContributionItem item = items[i];
+                if (item.isVisible()) {
+                    visibleItems.add(cast(Object)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();
+            ArrayList coolItemsToRemove = new ArrayList(coolItems.length);
+            for (int i = 0; i < coolItems.length; i++) {
+                Object data = coolItems[i].getData();
+                if ((data is null)
+                        || (!visibleItems.contains(data))
+                        || ((cast(IContributionItem)data ) && (cast(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 = cast(CoolItem) coolItemsToRemove.get(i);
+                if (!coolItem.isDisposed()) {
+                    Control control = coolItem.getControl();
+                    if (control !is 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;
+            Iterator visibleItemItr = visibleItems.iterator();
+            while (visibleItemItr.hasNext()) {
+                sourceItem = cast(IContributionItem) visibleItemItr.next();
+
+                // Retrieve the corresponding contribution item from SWT's
+                // data.
+                if (sourceIndex < coolItems.length) {
+                    destinationItem = cast(IContributionItem) coolItems[sourceIndex]
+                            .getData();
+                } else {
+                    destinationItem = null;
+                }
+
+                // The items match is they are equal or both separators.
+                if (destinationItem !is null) {
+                    if ((cast(Object)sourceItem).opEquals(cast(Object)destinationItem)) {
+                        sourceIndex++;
+                        destinationIndex++;
+                        sourceItem.update();
+                        continue;
+
+                    } else if ((destinationItem.isSeparator())
+                            && (sourceItem.isSeparator())) {
+                        coolItems[sourceIndex].setData(cast(Object)sourceItem);
+                        sourceIndex++;
+                        destinationIndex++;
+                        sourceItem.update();
+                        continue;
+
+                    }
+                }
+
+                // Otherwise, a new item has to be added.
+                int start = coolBar.getItemCount();
+                sourceItem.fill(coolBar, destinationIndex);
+                int newItems = coolBar.getItemCount() - start;
+                for (int i = 0; i < newItems; i++) {
+                    coolBar.getItem(destinationIndex++).setData(cast(Object)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 !is 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 !is null) {
+            CoolItem[] items = coolBar.getItems();
+            if (items !is null) {
+                ArrayList children = new ArrayList(items.length);
+                for (int i = 0; i < items.length; i++) {
+                    if ((items[i].getControl() !is null)
+                            && (!items[i].getControl().isDisposed())) {
+                        children.add(items[i].getControl());
+                    }
+                }
+                // Convert array
+                Control[] childrenArray;
+                childrenArray =  arraycast!(Control)(children.toArray());
+
+                if (childrenArray !is 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];
+        bool foundSeparator = false;
+        int j = 0;
+        CoolItem[] coolItems = (coolBar is 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 !is 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();
+        bool shouldUpdate = false;
+        if (oldIndices.length is wrapIndices.length) {
+            for (int i = 0; i < oldIndices.length; i++) {
+                if (oldIndices[i] !is wrapIndices[i]) {
+                    shouldUpdate = true;
+                    break;
+                }
+            }
+        } else {
+            shouldUpdate = true;
+        }
+
+        if (shouldUpdate) {
+            coolBar.setWrapIndices(wrapIndices);
+        }
+    }
+}