blob: bf97b04b0632b4c9f45f4f6441ec7108e63a3c59 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2003 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.internal;
import java.util.*;
import org.eclipse.jface.action.*;
import org.eclipse.jface.util.Assert;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.*;
import org.eclipse.ui.internal.registry.ActionSetRegistry;
/**
*/
public class CoolBarManager extends ContributionManager implements IToolBarManager {
/**
* The cool bar style; <code>SWT.NONE</code> by default.
*/
private int style = SWT.NONE;
/**
* The cool bar control; <code>null</code> before creation
* and after disposal.
*/
private CoolBar coolBar = null;
/**
* MenuManager for chevron menu when CoolItems not fully displayed.
*/
private MenuManager chevronMenuManager;
/**
* MenuManager for coolbar popup menu
*/
private MenuManager coolBarMenuManager = new MenuManager();
private Menu coolBarMenu = null;
/**
* Flag to track whether or not to remember coolbar item positions when an item
* is deleted.
*/
private boolean rememberPositions = false;
/**
* Stack for remembering positions of coolitems that have been removed.
*/
private ArrayList rememberedPositions = new ArrayList();
private class RestoreItemData {
CoolItemPosition savedPosition;
String beforeItemId; // found afterItemId, restore item after this item
String afterItemId; // found beforeItemId, restore item before this item
int beforeIndex = -1; // index in current layout of beforeItemId
int afterIndex = -1; // index in current layout of afterItemId
RestoreItemData() {
}
}
/**
*/
public CoolBarManager() {
}
/**
*/
public CoolBarManager(int style) {
this.style = style;
}
/**
* Adds an action as a contribution item to this manager.
* Equivalent to <code>add(new ActionContributionItem(action))</code>.
*
* 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());
}
/**
*/
private boolean coolBarExist() {
return coolBar != null && !coolBar.isDisposed();
}
/**
*/
/* package */ 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.setMenu(getCoolBarMenu());
}
return coolBar;
}
/**
* Create the coolbar item for the given contribution item.
*/
private CoolItem createCoolItem(CoolBarContributionItem cbItem, ToolBar toolBar) {
CoolItem coolItem;
toolBar.setVisible(true);
CoolItemPosition position = getRememberedPosition(cbItem.getId());
if (position != null) {
coolItem = createRememberedCoolItem(cbItem, toolBar, position);
} else {
coolItem = createNewCoolItem(cbItem, toolBar);
}
coolItem.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
if (event.detail == SWT.ARROW) {
handleChevron(event);
}
}
});
return coolItem;
}
/**
* Create a new coolbar item for the given contribution item. Put the item in its original
* creation position.
*/
private CoolItem createNewCoolItem(CoolBarContributionItem cbItem, ToolBar toolBar) {
CoolItem coolItem;
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;
}
/**
* Create a new coolbar item for the given contribution item. Put the item in its rememberedl
* position.
*/
private CoolItem createRememberedCoolItem(CoolBarContributionItem cbItem, ToolBar toolBar, CoolItemPosition position) {
RestoreItemData data = getRestoreData(cbItem, position);
int savedAfterRow = -1;
int currentAfterRow = -1;
int savedBeforeRow = -1;
int currentBeforeRow = -1;
int savedItemRow = -1;
CoolBarLayout currentLayout = getLayout();
if (data.savedPosition != null) {
savedItemRow = data.savedPosition.getRowOf(cbItem.getId());
if (data.afterItemId != null) {
savedAfterRow = data.savedPosition.getRowOf(data.afterItemId);
currentAfterRow = currentLayout.getRowOfIndex(data.afterIndex);
}
if (data.beforeItemId != null) {
savedBeforeRow = data.savedPosition.getRowOf(data.beforeItemId);
currentBeforeRow = currentLayout.getRowOfIndex(data.beforeIndex);
}
}
int createIndex = -1;
int row;
int[] newWraps = null;
// Figure out where to place the item and how to adjust the wrap indices.
// When adding the item at the afterIndex, wrap indices may need to be
// adjusted if the index represents the beginning of a row in the current
// coolbar layout.
if (data.afterIndex != -1 && data.beforeIndex != -1) {
// both a beforeItem and afterItem were found in the current coolbar layout
// for the item to be added
if ((savedItemRow == savedAfterRow) && (savedItemRow == savedBeforeRow)) {
// in the saved layout the item was on the same row as both the beforeItem
// and the afterItem, compare this to the current coolbar layout
if (currentAfterRow == currentBeforeRow) {
// in the current layout, both the before and after item are on the
// same row, so add the item to this row
createIndex = data.beforeIndex + 1;
row = currentBeforeRow;
} else {
// in the current layout, both the before and after item are not on
// the same row
if (currentBeforeRow == savedBeforeRow) {
// the beforeItem is on the same row as in the saved layout
createIndex = data.beforeIndex + 1;
row = currentBeforeRow;
} else if (currentAfterRow == savedAfterRow) {
// the afterItem is on the same row as in the saved layout
createIndex = data.afterIndex;
row = currentAfterRow;
newWraps = currentLayout.wrapsForNewItem(row, createIndex);
} else {
// current layout rows are different than when the item
// was deleted, just add the item to the currentBeforeRow
createIndex = data.beforeIndex + 1;
row = currentBeforeRow;
}
}
} else if (savedItemRow == savedBeforeRow) {
// in the saved layout, the item was on the same row as the beforeItem,
// add the item to the before row
createIndex = data.beforeIndex + 1;
row = currentBeforeRow;
} else if (savedItemRow == savedAfterRow) {
// in the saved layout, the item was on the same row as the afterItem
// add the item to the currentAfterRow
createIndex = data.afterIndex;
row = currentAfterRow;
newWraps = currentLayout.wrapsForNewItem(row, createIndex);
} else {
// in the saved layout, the item was on a row by itself
// put the item on a row by itself after currentBeforeRow
row = currentBeforeRow + 1;
createIndex = currentLayout.getStartIndexOfRow(row);
if (createIndex == -1) {
// row does not exist
createIndex = coolBar.getItemCount();
}
newWraps = currentLayout.wrapsForNewRow(row, createIndex);
}
} else if (data.afterIndex != -1) {
// only an afterItem was found in the current coolbar layout
// for the item to be added
createIndex = data.afterIndex;
if (savedItemRow == savedAfterRow) {
// in the saved layout, the item was on the same row as the afterItem,
// put the item on the currentAfterRow
row = currentAfterRow;
newWraps = currentLayout.wrapsForNewItem(row, createIndex);
} else {
// in the saved layout, the item was not on the same row as the
// afterItem, create a new row before currentAfterRow
row = currentAfterRow;
createIndex = currentLayout.getStartIndexOfRow(row);
newWraps = currentLayout.wrapsForNewRow(row, createIndex);
}
} else if (data.beforeIndex != -1) {
// only a beforeItem was found in the current coolbar layout
// for the item to be added
createIndex = data.beforeIndex + 1;
if (savedItemRow == savedBeforeRow) {
// in the saved layout, the item was on the same row as the beforeItem,
// put the item on currentBeforeRow
row = currentBeforeRow;
newWraps = currentLayout.wrapsForNewItem(row, createIndex);
} else {
// in the saved layout, the item was not on the same row as the
// beforeItem, create a new row with the item after currentBeforeRow
row = currentBeforeRow + 1;
createIndex = currentLayout.getStartIndexOfRow(row);
if (createIndex == -1) {
// row does not exist
createIndex = coolBar.getItemCount();
}
newWraps = currentLayout.wrapsForNewRow(row, createIndex);
}
} else {
// neither a before or after item was found in the current coolbar
// layout, just add the item to the end of the coolbar
createIndex = coolBar.getItemCount();
}
// create the item
if (newWraps != null) {
// item will be added and then the wraps will set, so use
// since the position of the item will change
coolBar.setRedraw(false);
}
CoolItem coolItem = new CoolItem(coolBar, SWT.DROP_DOWN, createIndex);
coolItem.setControl(toolBar);
coolItem.setData(cbItem);
// setSizeFor(coolItem, position.getSizeOf(cbItem.getId()).x);
setSizeFor(coolItem);
if (newWraps != null) {
coolBar.setWrapIndices(newWraps);
coolBar.setRedraw(true);
}
positionAdded(position);
return coolItem;
}
/**
*/
private void dispose(CoolBarContributionItem cbItem) {
CoolItem coolItem = findCoolItem(cbItem);
if (coolItem != null) {
dispose(coolItem);
}
remove(cbItem);
cbItem.getToolBarManager().dispose();
}
/**
*/
private void dispose(CoolItem coolItem) {
if ((coolItem != null) && !coolItem.isDisposed()) {
CoolBarContributionItem cbItem = (CoolBarContributionItem)coolItem.getData();
if (cbItem != null && rememberPositions) rememberPositionFor(cbItem.getId(), getLayout());
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();
}
}
/**
*/
/* package */ void dispose() {
if (coolBarExist()) {
IContributionItem[] cbItems = getItems();
for (int i=0; i<cbItems.length; i++) {
CoolBarContributionItem cbItem = (CoolBarContributionItem)cbItems[i];
dispose(cbItem);
cbItem.dispose();
}
coolBar.dispose();
coolBar = null;
}
if (chevronMenuManager != null) {
chevronMenuManager.dispose();
chevronMenuManager = null;
}
if (coolBarMenuManager != null) {
coolBarMenuManager.dispose();
coolBarMenuManager = null;
}
}
/**
*/
private CoolItem findCoolItem(CoolBarContributionItem item) {
if (coolBar == null) return null;
CoolItem[] items = coolBar.getItems();
for (int i = 0; i < items.length; i++) {
CoolItem coolItem = items[i];
CoolBarContributionItem data = (CoolBarContributionItem)coolItem.getData();
if (data != null && data.equals(item)) return coolItem;
}
return null;
}
/**
*/
/* package */ CoolBarContributionItem findSubId(String id) {
IContributionItem[] items = getItems();
for (int i = 0; i < items.length; i++) {
CoolBarContributionItem item = (CoolBarContributionItem)items[i];
IContributionItem subItem = item.getToolBarManager().find(id);
if (subItem != null) return item;
}
return null;
}
/**
*/
private ArrayList getCoolItemIds() {
CoolItem[] coolItems = coolBar.getItems();
ArrayList ids = new ArrayList(coolItems.length);
for (int i = 0; i < coolItems.length; i++) {
CoolBarContributionItem group = (CoolBarContributionItem) coolItems[i].getData();
if (group != null) ids.add(group.getId());
}
return ids;
}
/**
*/
/* package */ Menu getCoolBarMenu() {
if (coolBarMenu == null) {
coolBarMenu = coolBarMenuManager.createContextMenu(coolBar);
}
return coolBarMenu;
}
/**
* Return the SWT control for this manager.
*/
/* package */ CoolBar getControl() {
return coolBar;
}
/**
*/
private int getInsertAfterIndex(CoolBarContributionItem coolBarItem) {
IContributionItem[] items = getItems();
int index = -1;
CoolBarContributionItem afterItem = null;
// find out which item should be after this item
for (int i=0; i<items.length; i++) {
if (items[i].equals(coolBarItem)) {
if (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<items.length; i++) {
if (items[i].equals(coolBarItem)) {
if (i < items.length - 1) {
while (i < items.length - 1) {
beforeItem = (CoolBarContributionItem)items[i+1];
if (beforeItem.isVisible()) break;
i++;
}
} else {
// item is not before anything
index = coolBar.getItems().length;
}
break;
}
}
// get the coolbar location of the before item
if (beforeItem != null) {
CoolItem beforeCoolItem = findCoolItem(beforeItem);
if (beforeCoolItem != null) {
index = coolBar.indexOf(beforeCoolItem);
}
}
return index;
}
/**
*/
private CoolBarLayout getLayout() {
if (!coolBarExist())
return null;
CoolBarLayout layout = new CoolBarLayout(coolBar);
layout.rememberedPositions = new ArrayList();
layout.rememberedPositions.addAll(rememberedPositions);
return layout;
}
private RestoreItemData getRestoreData(CoolBarContributionItem cbItem, CoolItemPosition position) {
RestoreItemData bestMatch = new RestoreItemData();
ArrayList coolBarItems = getLayout().items;
// Look at the remembered layouts starting at the layout for the item and heading
// down the stack looking for the best saved layout to use for restoring the
// item position. Stop processing when an exact match is found or the position of
// the item has changed in the remembered layouts.
int startIndex = rememberedPositions.indexOf(position);
CoolBarLayout previousLayout = null;
for (int i=startIndex; i < rememberedPositions.size(); i++) {
CoolItemPosition savedPosition = (CoolItemPosition)rememberedPositions.get(i);
ArrayList savedItems = savedPosition.getItems();
// the item we are trying to restore is not in the saved layout, so stop
int savedItemIndex = savedItems.indexOf(cbItem.getId());
if (savedItemIndex == -1) break;
// if the previousLayout is not similar to the next layout, stop
if (previousLayout != null) {
if (!previousLayout.isDerivativeOf(savedPosition.layout)) break;
}
boolean afterBeforeItemFound = bestMatch.afterIndex != -1 && bestMatch.beforeIndex != -1;
String afterId = null;
String beforeId = null;
int beforeIndex = -1;
int afterIndex = -1;
// look at the saved items after savedItemIndex, see if any of these items
// is in the current coolbar layout
for (int j = savedItemIndex + 1; j < savedItems.size(); j++) {
//
afterId = (String)savedItems.get(j);
afterIndex = coolBarItems.indexOf(afterId);
if (afterIndex != -1) {
break;
}
}
// look at the saved items before savedItemIndex, see if any of these items
// is in the current coolbar layout
for (int j = savedItemIndex - 1; j >= 0; j--) {
//
beforeId = (String)savedItems.get(j);
beforeIndex = coolBarItems.indexOf(beforeId);
if (beforeIndex != -1) {
break;
}
}
if (beforeIndex != -1 && afterIndex != -1) {
// test whether or not we've found an exact position,
// if we have use this savedPosition
bestMatch.savedPosition = savedPosition;
bestMatch.afterItemId = afterId;
bestMatch.afterIndex = afterIndex;
bestMatch.beforeItemId = beforeId;
bestMatch.beforeIndex = beforeIndex;
if (beforeIndex + 1 == afterIndex) {
break;
}
} else if (beforeIndex != -1) {
// If we found both items previously, that is the best match.
// This condition can happen if items were added between this
// savedPosition and the previous savedPosition.
if (afterBeforeItemFound) break;
bestMatch.savedPosition = savedPosition;
bestMatch.beforeItemId = beforeId;
bestMatch.beforeIndex = beforeIndex;
bestMatch.afterItemId = null;
bestMatch.afterIndex = -1;
// there are no after before index on the coolbar
if (beforeIndex == coolBarItems.size() - 1) break;
} else if (afterIndex != -1) {
// If we found both items previously, that is the best match.
// This condition can happen if items were added between this
// savedPosition and the previous savedPosition.
if (afterBeforeItemFound) break;
bestMatch.savedPosition = savedPosition;
bestMatch.afterItemId = afterId;
bestMatch.afterIndex = afterIndex;
bestMatch.beforeItemId = null;
bestMatch.beforeIndex = -1;
// there are no items before afterIndex on the coolbar
if (afterIndex == 0) break;
} else {
// nothing found
break;
}
previousLayout = savedPosition.layout;
}
return bestMatch;
}
/**
* Return the remembered position for the given CoolBarContributionItem. If a position
* was not remembered, return null.
*/
private CoolItemPosition getRememberedPosition (String cbItemId) {
for (int i=0; i<rememberedPositions.size(); i++) {
CoolItemPosition position = (CoolItemPosition)rememberedPositions.get(i);
if (position.id.equals(cbItemId) && !position.added) return position;
}
return null;
}
/* package */ int getStyle() {
return style;
}
/**
* Create and display the chevron menu.
*/
private void handleChevron(SelectionEvent event) {
CoolItem item = (CoolItem) event.widget;
Control control = item.getControl();
if ((control instanceof ToolBar) == false) {
return;
}
Point chevronPosition = coolBar.toDisplay(new Point(event.x, event.y));
ToolBar toolBar = (ToolBar) control;
ToolItem[] tools = toolBar.getItems();
int toolCount = tools.length;
int visibleItemCount = 0;
while (visibleItemCount < toolCount) {
Rectangle toolBounds = tools[visibleItemCount].getBounds();
Point point = toolBar.toDisplay(new Point(toolBounds.x, toolBounds.y));
toolBounds.x = point.x;
toolBounds.y = point.y;
// stop if the tool is at least partially hidden by the drop down chevron
if (chevronPosition.x >= toolBounds.x && chevronPosition.x - toolBounds.x <= toolBounds.width) {
break;
}
visibleItemCount++;
}
// Create a pop-up menu with items for each of the hidden buttons.
if (chevronMenuManager != null) {
chevronMenuManager.dispose();
}
chevronMenuManager = new MenuManager();
for (int i = visibleItemCount; i < toolCount; i++) {
IContributionItem data = (IContributionItem) tools[i].getData();
if (data instanceof ActionContributionItem) {
ActionContributionItem contribution = new ActionContributionItem(((ActionContributionItem) data).getAction());
chevronMenuManager.add(contribution);
} else if (data instanceof SubContributionItem) {
IContributionItem innerData = ((SubContributionItem)data).getInnerItem();
if (innerData instanceof ActionContributionItem) {
ActionContributionItem contribution = new ActionContributionItem(((ActionContributionItem) innerData).getAction());
chevronMenuManager.add(contribution);
}
} else if (data.isSeparator()) {
chevronMenuManager.add(new Separator());
}
}
Menu popup = chevronMenuManager.createContextMenu(coolBar);
popup.setLocation(chevronPosition.x, chevronPosition.y);
popup.setVisible(true);
}
/**
* Inserts a contribution item for the given action after the item
* with the given id.
* Equivalent to
* <code>insertAfter(id,new ActionContributionItem(action))</code>.
*
* 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
* <code>insertBefore(id,new ActionContributionItem(action))</code>.
*
* 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);
}
/**
*/
/* package */ boolean isLayoutLocked() {
if (!coolBarExist()) return false;
return coolBar.getLocked();
}
/* package */ boolean isValidCoolItemId(String id, WorkbenchWindow window) {
ActionSetRegistry registry = WorkbenchPlugin.getDefault().getActionSetRegistry();
if (registry.findActionSet(id) != null) return true;
if (window != null) {
return window.isWorkbenchCoolItemId(id);
}
return false;
}
/**
*/
/* package */ void lockLayout(boolean value) {
coolBar.setLocked(value);
}
/**
*/
private void positionAdded(CoolItemPosition position) {
// mark the position as added back
position.added = true;
// remembered positions on the top of the stack that have been added can be removed
boolean done = rememberedPositions.size() == 0;
while (!done) {
CoolItemPosition topLayout = (CoolItemPosition)rememberedPositions.get(0);
if (topLayout.added) {
rememberedPositions.remove(0);
done = rememberedPositions.size() == 0;
} else {
done = true;
}
}
// all except the least recently added position in a set of contiguously added positions
// can be removed from the stack within each g
int testIndex = 1;
done = testIndex + 1 > rememberedPositions.size() - 1;
while (!done) {
CoolItemPosition pos = (CoolItemPosition)rememberedPositions.get(testIndex);
if (pos.added) {
CoolItemPosition nextPos = (CoolItemPosition)rememberedPositions.get(testIndex + 1);
CoolItemPosition prevPos = (CoolItemPosition)rememberedPositions.get(testIndex - 1);
boolean nextSameGroup = pos.layout.isDerivativeOf(nextPos.layout);
boolean prevSameGroup = prevPos.layout.isDerivativeOf(pos.layout);
if (!nextSameGroup && !prevSameGroup) {
// only item in this group
rememberedPositions.remove(testIndex);
} else if (nextPos.added && nextSameGroup && !prevSameGroup) {
rememberedPositions.remove(testIndex);
} else {
testIndex++;
}
} else {
testIndex++;
}
done = testIndex + 1 > rememberedPositions.size() - 1;
}
}
/**
* Layout out the coolbar items so that each one is sized to its preferred size.
*/
private void redoLayout() {
// Reset the wrap indices and the cool item sizes. The coolbar will automatically
// wrap the items to the next row that do not fit.
coolBar.setWrapIndices(new int[0]);
CoolItem[] coolItems = coolBar.getItems();
for (int i = 0; i < coolItems.length; i++) {
CoolItem coolItem = coolItems[i];
setSizeFor(coolItem);
}
// clear any remembered data
rememberedPositions = new ArrayList();
}
/**
*/
private 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 <code>item</code> parameter if the item was removed,
* and <code>null</code> 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);
}
/**
* Save the position of the given CoolItem for restoring the item later.
*/
private CoolItemPosition rememberPositionFor(String cbItemId, CoolBarLayout layout) {
// create a CoolItemPosition for the given cbItem, no need to save
// remembered positions as part of the layout
layout.rememberedPositions = new ArrayList();
CoolItemPosition position = new CoolItemPosition(cbItemId, layout);
// remove the previously remembered position for the item if
// it exists
int index = -1;
for (int i=0; i<rememberedPositions.size(); i++) {
CoolItemPosition item = (CoolItemPosition)rememberedPositions.get(i);
if (position.id.equals(item.id)) index = i;
}
if (index != -1) rememberedPositions.remove(index);
// add the position to the beginning of the stack of remembered
// positions
rememberedPositions.add(0, position);
return position;
}
void saveLayoutFor(Perspective perspective) {
perspective.setToolBarLayout(getLayout());
rememberPositions = false;
rememberedPositions = new ArrayList();
}
void setLayoutFor(Perspective perspective) {
rememberedPositions = new ArrayList();
setLayout(perspective.getToolBarLayout());
updateTabOrder();
rememberPositions = true;
}
/**
*/
private 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();
}
}
/**
*/
private 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<layout.items.size(); i++) {
CoolItem coolItem = findCoolItem((CoolBarContributionItem)find((String)layout.items.get(i)));
if (coolItem != null) {
int index = currentItemOrder[coolBar.indexOf(coolItem)];
foundItemOrder.add(new Integer(index));
foundItemSizes.add(layout.itemSizes[i]);
// the cool item at the given index has been accounted for,
// so set the found value for that index to 0
found[index]=0;
}
}
int count=0;
for (count=0; count<foundItemOrder.size(); count++) {
itemOrder[count]=((Integer)foundItemOrder.elementAt(count)).intValue();
itemSizes[count]=(Point)foundItemSizes.elementAt(count);
}
rememberedPositions = layout.rememberedPositions;
// Handle those items that are on the coolbar, but not in the layout.
// Just add these items at the end of the coolbar for now.
ArrayList rememberedAddedItems = new ArrayList();
for (int i=0; i<found.length; i++) {
if (found[i] == -1) {
itemOrder[count]=i;
CoolItem cItem = coolBar.getItem(i);
itemSizes[count]=cItem.getSize();
CoolBarContributionItem cbItem = (CoolBarContributionItem)cItem.getData();
CoolItemPosition position = getRememberedPosition(cbItem.getId());
if (position != null) {
rememberedAddedItems.add(cItem);
}
count++;
}
}
coolBar.setRedraw(false);
coolBar.setItemLayout(itemOrder, new int[0], itemSizes);
// restore the wrap indices after the new item order is restored, wrap on the same items that
// were specified in the layout
String[] wrapItems = new String[layout.itemWrapIndices.length];
for (int i = 0; i < layout.itemWrapIndices.length; i++) {
wrapItems[i] = (String) layout.items.get(layout.itemWrapIndices[i]);
}
int[] wrapIndices = new int[wrapItems.length];
ArrayList currentCoolItemIds = getCoolItemIds();
int j = 0;
int k = 0;
while (k < wrapItems.length) {
int index = currentCoolItemIds.indexOf(wrapItems[k]);
if (index != -1) {
wrapIndices[j] = index;
j++;
k++;
} else {
// wrap item no longer exists, try wrapping on the next item in the
// saved layout, if we hit a new row, stop
int visualIndex = layout.items.indexOf(wrapItems[k]);
int row = layout.getRowOfIndex(visualIndex);
int nextIndex = visualIndex + 1;
int nextRow = layout.getRowOfIndex(nextIndex);
if (nextIndex < layout.items.size() && nextRow == row) {
String nextItem = (String)layout.items.get(nextIndex);
wrapItems[k]=nextItem;
} else {
k++;
}
}
}
int[] itemWraps = new int[j];
System.arraycopy(wrapIndices, 0, itemWraps, 0, j);
coolBar.setWrapIndices(itemWraps);
// restore the position of items whose position was remembered
ArrayList cbItems = new ArrayList();
ArrayList toolbars = new ArrayList();
// dispose of the coolitems, then add back one at a time - necessary to restore the
// original layout
for (int i=0; i<rememberedAddedItems.size(); i++) {
CoolItem item = (CoolItem)rememberedAddedItems.get(i);
CoolBarContributionItem cbItem = (CoolBarContributionItem)item.getData();
cbItems.add(cbItem);
ToolBar tBar = (ToolBar) item.getControl();
toolbars.add(tBar);
dispose(item);
}
for (int i=0; i<cbItems.size(); i++) {
CoolBarContributionItem cbItem = (CoolBarContributionItem)cbItems.get(i);
CoolItemPosition position = getRememberedPosition(cbItem.getId());
// restore the item's saved position
ToolBar tBar = (ToolBar)toolbars.get(i);
createRememberedCoolItem(cbItem, tBar, position);
}
// need to remember position for any item that was in the layout but not
// currently on the coolbar
ArrayList currentIds = getCoolItemIds();
for (int i=0; i<layout.items.size(); i++) {
String id = (String)layout.items.get(i);
if (!currentIds.contains(id)) {
rememberPositionFor(id, layout);
}
}
coolBar.setRedraw(true);
}
private void setSizeFor(CoolItem coolItem) {
setSizeFor(coolItem, -1);
}
/**
*/
private void setSizeFor(CoolItem coolItem, int coolWidth) {
ToolBar toolBar = (ToolBar) coolItem.getControl();
Point size = toolBar.computeSize(SWT.DEFAULT, SWT.DEFAULT);
Point coolSize = coolItem.computeSize(size.x, size.y);
// note setMinimumSize must be called before setSize, see PR 15565
coolItem.setMinimumSize(size.x, size.y);
coolItem.setPreferredSize(coolSize);
if (coolWidth == -1) {
coolItem.setSize(coolSize);
} else {
coolItem.setSize(new Point(coolWidth, coolSize.y));
}
}
/**
*/
public void update(boolean force) {
if (isDirty() || force) {
if (coolBarExist()) {
boolean useRedraw = false;
CoolBarLayout layout = getLayout();
// remove CoolBarItemContributions that are empty
IContributionItem[] items = getItems();
ArrayList cbItemsToRemove = new ArrayList(items.length);
for (int i = 0; i < items.length; i++) {
CoolBarContributionItem cbItem = (CoolBarContributionItem) items[i];
if (cbItem.isEmpty()) {
CoolItem coolItem = findCoolItem(cbItem);
if (!useRedraw && coolItem != null) {
int visualIndex = coolBar.indexOf(coolItem);
if (layout.isOnRowAlone(visualIndex)) {
useRedraw = true;
}
}
cbItemsToRemove.add(cbItem);
}
}
// remove non-visible CoolBarContributionItems
CoolItem[] coolItems = coolBar.getItems();
ArrayList coolItemsToRemove = new ArrayList(coolItems.length);
for (int i = 0; i < coolItems.length; i++) {
CoolItem coolItem = coolItems[i];
CoolBarContributionItem cbItem = (CoolBarContributionItem) coolItem.getData();
if ((cbItem != null) && !cbItem.isVisible() && (!cbItemsToRemove.contains(cbItem))) {
if (!useRedraw) {
int visualIndex = coolBar.indexOf(coolItem);
if (layout.isOnRowAlone(visualIndex)) {
useRedraw = true;
}
}
coolItemsToRemove.add(coolItem);
}
}
// set redraw off if deleting a sole item from a row to reduce jumpiness in the
// case that an item gets added back on that row as part of the update
if (!useRedraw && (cbItemsToRemove.size() + coolItemsToRemove.size() > 2)) {
useRedraw = true;
}
if (useRedraw) 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);
}
}
}
}
updateTabOrder();
setDirty(false);
// workaround for 14330
if(relock) {
coolBar.setLocked(true);
}
if (useRedraw) coolBar.setRedraw(true);
}
}
}
/**
* Recalculate and set the size for the given CoolBarContributionItem's coolitem.
*/
/* package */ void updateSizeFor(CoolBarContributionItem cbItem) {
CoolItem coolItem = findCoolItem(cbItem);
if (coolItem != null) setSizeFor(coolItem);
}
/**
* Sets the tab order of the coolbar to the visual order of its items.
*/
/* package */ void updateTabOrder() {
CoolItem[] items = coolBar.getItems();
Control[] children = new Control[items.length];
for (int i = 0; i < children.length; i++) {
children[i] = items[i].getControl();
}
coolBar.setTabList(children);
}
}