package org.eclipse.ui.internal; /* * (c) Copyright IBM Corp. 2000, 2001. * All Rights Reserved. */ import java.util.*; import org.eclipse.jface.action.*; import org.eclipse.jface.util.Assert; import org.eclipse.swt.SWT; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.*; /** * WORK IN PROGRESS FOR COOLBAR SUPPORT */ public class CoolBarManager extends ContributionManager implements IToolBarManager { /** * The cool bar style; SWT.NONE by default. */ private int style = SWT.NONE; /** * The cool bar control; null before creation * and after disposal. */ private CoolBar coolBar = null; /** * MenuManager for coolbar popup menu */ private MenuManager coolBarMenuManager = new MenuManager(); /** */ public CoolBarManager() { } /** */ public CoolBarManager(int style) { this.style = style; } /** * Adds an action as a contribution item to this manager. * Equivalent to add(new ActionContributionItem(action)). * * Not valid for CoolBarManager. Only CoolBarContributionItems may be added * to this manager. * * @param action the action */ public void add(IAction action) { Assert.isTrue(false); } /** * Adds a CoolBarContributionItem to this manager. * * @exception AssertionFailedException if the type of item is * not valid */ public void add(IContributionItem item) { Assert.isTrue(item instanceof CoolBarContributionItem); super.add(item); } /** * Adds a contribution item to the coolbar's menu. */ public void addToMenu(ActionContributionItem item) { coolBarMenuManager.add(item.getAction()); } /** * Adds a contribution item to the start or end of the group * with the given id. * * Not valid for CoolBarManager. Only CoolBarContributionItems are items * of this manager. */ private void addToGroup(String itemId, IContributionItem item, boolean append) { Assert.isTrue(false); } /** */ private boolean coolBarExist() { return coolBar != null && !coolBar.isDisposed(); } /** */ public CoolBar createControl(Composite parent) { if (!coolBarExist() && parent != null) { // Create the CoolBar and its popup menu. coolBar = new CoolBar(parent, style); coolBar.setLocked(false); coolBar.addListener(SWT.Resize, new Listener() { public void handleEvent(Event event) { coolBar.getParent().layout(); } }); coolBar.addMouseListener(new MouseAdapter() { public void mouseDown(MouseEvent e) { popupCoolBarMenu(e); } }); } return coolBar; } /** * Create the coolbar item for the given contribution item. */ private CoolItem createCoolItem(CoolBarContributionItem cbItem, ToolBar toolBar) { CoolItem coolItem; toolBar.setVisible(true); int index = -1; if (cbItem.isOrderBefore()) { index = getInsertBeforeIndex(cbItem); } else if (cbItem.isOrderAfter()) { index = getInsertAfterIndex(cbItem); } if (index == -1) { index = coolBar.getItemCount(); coolItem = new CoolItem(coolBar, SWT.DROP_DOWN); } else { coolItem = new CoolItem(coolBar, SWT.DROP_DOWN, index); } coolItem.setControl(toolBar); coolItem.setData(cbItem); setSizeFor(coolItem); return coolItem; } /** */ public void dispose(CoolBarContributionItem cbItem) { CoolItem coolItem = findCoolItem(cbItem); if (coolItem != null) { dispose(coolItem); } remove(cbItem); cbItem.getToolBarManager().dispose(); } /** */ protected void dispose(CoolItem coolItem) { if ((coolItem != null) && !coolItem.isDisposed()) { coolItem.setData(null); Control control = coolItem.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()) { coolItem.setControl(null); } coolItem.dispose(); } } /** */ public void dispose() { if (coolBarExist()) { IContributionItem[] cbItems = getItems(); for (int i=0; i 0) { while (i > 0) { afterItem = (CoolBarContributionItem)items[i-1]; if (afterItem.isVisible()) break; i--; } } else { // item is not after anything index = 0; } break; } } // get the coolbar location of the after item if (afterItem != null) { CoolItem afterCoolItem = findCoolItem(afterItem); if (afterCoolItem != null) { index = coolBar.indexOf(afterCoolItem); index++; } } return index; } private int getInsertBeforeIndex(CoolBarContributionItem coolBarItem) { IContributionItem[] items = getItems(); int index = -1; CoolBarContributionItem beforeItem = null; // find out which item should be before this item for (int i=0; i Save the preferred size as actual size for the last item on a row int[] lastIndices = getLastItemIndices(); for (int i = 0; i < lastIndices.length; i++) { int lastIndex = lastIndices[i]; if (lastIndex >= 0 && lastIndex < coolItems.length) { CoolItem lastItem = coolItems[lastIndex]; layout.itemSizes[lastIndex] = lastItem.getPreferredSize(); } } return layout; } /** * Get the row end for the given index. */ private int getRowEndIndex (int index) { int[] wrapIndices = getAdjustedWrapIndices(); int rowEndIndex = -1; // We will have at least one wrap index of 0. for (int i = 0; i < wrapIndices.length; i++) { int wrapIndex = wrapIndices[i]; if (index < wrapIndex) { rowEndIndex = wrapIndices[i] - 1; break; } else if (index == wrapIndex) { if (i < (wrapIndices.length - 1)) { rowEndIndex = wrapIndices[i+1] - 1; } break; } } if (rowEndIndex == -1) { rowEndIndex = coolBar.getItemCount() - 1; } return rowEndIndex; } /** * Get the space used by the items on the row that the item added * at index will be on. */ private int getSpaceUsed (int index) { // If no items exist, no space is used. if (coolBar.getItemCount() == 0) return 0; // Get row start and row end. int[] wrapIndices = getAdjustedWrapIndices(); int rowEndIndex = -1; int rowStartIndex = wrapIndices[0]; // We will have at least one wrap index of 0. for (int i = 0; i < wrapIndices.length; i++) { int wrapIndex = wrapIndices[i]; // want to use the equals here since the item at index // has not been added, for example wrapIndices[0,3] and // index = 3 - the item will be added to the end of the // first row, so we want our start/end to be 0/2 if (index <= wrapIndex) { rowEndIndex = wrapIndices[i] - 1; break; } else { rowStartIndex = wrapIndex; } } if (rowEndIndex == -1) { rowEndIndex = coolBar.getItemCount() - 1; } int width = 0; for (int i = rowStartIndex; i < rowEndIndex; i++) { width += coolBar.getItem(i).getSize().x; } // For row end item need to calculate size differently since // last item on a row is given a size to account for the // extra space on the row. width += coolBar.getItem(rowEndIndex).getPreferredSize().x; return width; } /** */ public int getStyle() { return style; } /** * Inserts a contribution item for the given action after the item * with the given id. * Equivalent to * insertAfter(id,new ActionContributionItem(action)). * * Not valid for CoolBarManager. Only CoolBarContributionItems may be added * to this manager. * * @param id the contribution item id * @param action the action to insert */ public void insertAfter(String id, IAction action) { Assert.isTrue(false); } /** * Inserts a contribution item after the item with the given id. * * @param id the CoolBarContributionItem * @param item the CoolBarContributionItem to insert * @exception IllegalArgumentException if there is no item with * the given id * @exception IllegalArgumentException if the type of item is * not valid */ public void insertAfter(String id, IContributionItem item) { Assert.isTrue(item instanceof CoolBarContributionItem); super.insertAfter(id, item); ((CoolBarContributionItem)item).setOrderAfter(true); } /** * Inserts a contribution item for the given action before the item * with the given id. * Equivalent to * insertBefore(id,new ActionContributionItem(action)). * * Not valid for CoolBarManager. Only CoolBarContributionItems may be added * to this manager. * * @param id the contribution item id * @param action the action to insert */ public void insertBefore(String id, IAction action) { Assert.isTrue(false); } /** * Inserts a contribution item before the item with the given id. * * @param id the CoolBarContributionItem * @param item the CoolBarContributionItem to insert * @exception IllegalArgumentException if there is no item with * the given id * @exception IllegalArgumentException if the type of item is * not valid */ public void insertBefore(String id, IContributionItem item) { Assert.isTrue(item instanceof CoolBarContributionItem); super.insertBefore(id, item); ((CoolBarContributionItem)item).setOrderBefore(true); } /** */ public boolean isLayoutLocked() { if (!coolBarExist()) return false; return coolBar.getLocked(); } /** */ public void lockLayout(boolean value) { coolBar.setLocked(value); } /** */ /* package */ void popupCoolBarMenu(MouseEvent e) { if (e.button != 3) return; Point pt = new Point(e.x, e.y); pt = ((Control) e.widget).toDisplay(pt); Menu coolBarMenu = coolBarMenuManager.createContextMenu(coolBar); coolBarMenu.setLocation(pt.x, pt.y); coolBarMenu.setVisible(true); } /** * Layout out the coolbar items in their current order, but in the most space efficient way.. */ protected void redoLayout() { // Reset the item sizes, necessary to do so before we set wrap indices so // that auto-wrapping occurs as it should. CoolItem[] coolItems = coolBar.getItems(); for (int i = 0; i < coolItems.length; i++) { CoolItem coolItem = coolItems[i]; setSizeFor(coolItem); } coolBar.setWrapIndices(new int[0]); relayout(); } /** */ protected void resetLayout() { coolBar.setRedraw(false); CoolItem[] coolItems = coolBar.getItems(); for (int i = 0; i < coolItems.length; i++) { CoolItem coolItem = coolItems[i]; dispose(coolItem); } coolBar.setWrapIndices(new int[] {}); update(true); coolBar.setRedraw(true); } /** * Removes the given contribution item from the contribution items * known to this manager. * * @param item the contribution item * @return the item parameter if the item was removed, * and null if it was not found * @exception IllegalArgumentException if the type of item is * not valid */ public IContributionItem remove(IContributionItem item) { Assert.isTrue(item instanceof CoolBarContributionItem); return super.remove(item); } /** */ protected void relayout() { coolBar.getParent().layout(); } /** */ public void setLayout(CoolBarLayout layout) { try { setLayoutTo(layout); } catch (Exception e) { // A lot can go wrong if the layout is out of sync with the coolbar state. // Try to recover by resetting the layout. WorkbenchPlugin.log("An error has occurred restoring the coolbar layout. " + e.toString()); //$NON-NLS-1$ resetLayout(); } } /** */ protected void setLayoutTo(CoolBarLayout layout) { // This method is called after update. All of the coolbar items have // been created, now apply the layout to the coolbar. if (layout == null) { coolBar.setRedraw(false); CoolItem[] coolItems = coolBar.getItems(); int[] newItemOrder = new int[coolItems.length]; // Reset the coolitem order to their original order. This order is // based on the order of the ContributionItems. Note that the only // way to reset item order is to setItemLayout (no setItemOrder API). IContributionItem[] items = getItems(); int j = 0; int[] oldItemOrder = coolBar.getItemOrder(); for (int i = 0; i < items.length; i++) { CoolBarContributionItem item = (CoolBarContributionItem)items[i]; CoolItem coolItem = findCoolItem(item); if (coolItem != null) { int visualIndex = coolBar.indexOf(coolItem); int creationIndex = oldItemOrder[visualIndex]; newItemOrder[j] = creationIndex; j++; } } coolBar.setItemLayout(newItemOrder, coolBar.getWrapIndices(), coolBar.getItemSizes()); redoLayout(); coolBar.setRedraw(true); return; } int maxItemCount = coolBar.getItemCount(); int[] itemOrder = new int[maxItemCount]; Point[] itemSizes = new Point[maxItemCount]; // Used to keep track of what cool items have been accounted for in // layout. New items that were added after the layout was saved, will // not be accounted for. int[] found = new int[maxItemCount]; for (int i = 0; i < found.length; i++) { found[i] = -1; } int[] currentItemOrder = coolBar.getItemOrder(); Vector foundItemOrder = new Vector(); Vector foundItemSizes = new Vector(); for (int i=0; i 2) { useRedraw = true; coolBar.setRedraw(false); } for (Iterator e = cbItemsToRemove.iterator(); e.hasNext();) { CoolBarContributionItem cbItem = (CoolBarContributionItem) e.next(); dispose(cbItem); } for (Iterator e = coolItemsToRemove.iterator(); e.hasNext();) { CoolItem coolItem = (CoolItem) e.next(); ToolBar tBar = (ToolBar) coolItem.getControl(); tBar.setVisible(false); dispose(coolItem); } // create a CoolItem for each group of items that does not have a CoolItem ArrayList coolItemIds = getCoolItemIds(); items = getItems(); boolean changed = false; boolean relock = false; for (int i = 0; i < items.length; i++) { CoolBarContributionItem cbItem = (CoolBarContributionItem) items[i]; if (!coolItemIds.contains(cbItem.getId())) { if (cbItem.isVisible()) { ToolBar toolBar = cbItem.getControl(); if ((toolBar != null) && (!toolBar.isDisposed()) && (toolBar.getItemCount() > 0) && cbItem.hasDisplayableItems()) { if (!changed) { // workaround for 14330 changed = true; if (coolBar.getLocked()) { coolBar.setLocked(false); relock = true; } } createCoolItem(cbItem, toolBar); } } } } setDirty(false); // workaround for 14330 if(relock) { coolBar.setLocked(true); } if (useRedraw) coolBar.setRedraw(true); } } } }