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);
}
}
}
}