blob: c18411ac9c68fc7acee09227119899e85a55dd04 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
******************************************************************************/
package org.eclipse.ui.internal.menus;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.core.expressions.Expression;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.menus.IWidget;
import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants;
import org.eclipse.ui.internal.util.Util;
import org.eclipse.ui.menus.IMenuService;
import org.eclipse.ui.menus.IWorkbenchWidget;
/**
* Handles the top level caching for 3.2 style trim
* contributions.
*
* @since 3.3
*
*/
public class TrimAdditionCacheEntry {
private IConfigurationElement additionElement;
private MenuLocationURI uri = null;
/**
* The map contains {@link IWorkbenchWidget} entries
* for widgets that have failed to load on a previous
* attempt. Used to prevent multiple retries at
* loading a widget (which spams the log).
*/
private Map failedWidgets = new HashMap();
/**
* Maps the widget back to it's configurtation element
*/
private Map widgetToConfigElementMap = new HashMap();
// Caches
/**
* Maps an IContributionItem to its corresponding IConfigurationElement
*/
Map iciToConfigElementMap = new HashMap();
public TrimAdditionCacheEntry(IConfigurationElement element,
MenuLocationURI uri, IMenuService service) {
this.additionElement = element;
this.uri = uri;
}
/**
* Populate the list
*
* @param additions
*/
public void getContributionItems(List additions) {
additions.clear();
}
/* (non-Javadoc)
* @see org.eclipse.ui.internal.menus.MenuCacheEntry#generateSubCaches()
*/
public void generateSubCaches() {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see org.eclipse.ui.internal.menus.MenuCacheEntry#getVisibleWhenForItem(org.eclipse.jface.action.IContributionItem)
*/
public Expression getVisibleWhenForItem(IContributionItem item) {
// TODO Auto-generated method stub
return null;
}
/**
* @return
*/
public String getId() {
return additionElement.getAttribute(IWorkbenchRegistryConstants.ATT_ID);
}
/**
* @return <code>true</code> iff the group is positioned at the start
* (or 'before') the entry that it is relative to. Default is true
*
*/
public boolean isAtStart() {
IConfigurationElement location = additionElement.getChildren(IWorkbenchRegistryConstants.TAG_LOCATION)[0];
if (location.getChildren(IWorkbenchRegistryConstants.TAG_ORDER).length > 0) {
IConfigurationElement order = location.getChildren(IWorkbenchRegistryConstants.TAG_ORDER)[0];
String pos = order.getAttribute(IWorkbenchRegistryConstants.ATT_POSITION);
if (pos != null)
return (pos.equals("start") | pos.equals("before")); //$NON-NLS-1$//$NON-NLS-2$
}
return true;
}
/**
* Returns whether or not the defining {@link IConfigurationElement}
* declares that the widget should use extra space in the 'major'
* dimension (ie. use extra horizontal space in the status area).
* The space is equally divided with other elementa in the same
* trim area that also want to use the extra space.
*
* @param widgetElement the {@link IConfigurationElement} declaring this
* widget.
*
* @return <code>true</code> iff the resulting widget should use
* extra major space
*/
public boolean fillMajor(IConfigurationElement widgetElement) {
if (widgetElement.getChildren(IWorkbenchRegistryConstants.TAG_LAYOUT).length==0) {
return false;
}
IConfigurationElement layout = widgetElement.getChildren(IWorkbenchRegistryConstants.TAG_LAYOUT)[0];
String fillMajorVal = layout.getAttribute(IWorkbenchRegistryConstants.ATT_FILL_MAJOR);
return (fillMajorVal != null && fillMajorVal.equals("true")); //$NON-NLS-1$
}
/**
* Returns whether or not the defining {@link IConfigurationElement}
* declares that the widget should use extra space in the 'minor'
* dimension (ie. use extra vertical space in the status area)
*
* @param widgetElement the {@link IConfigurationElement} declaring this
* widget.
*
* @return <code>true</code> iff the resulting widget should use
* extra minor space
*/
public boolean fillMinor(IConfigurationElement widgetElement) {
if (widgetElement.getChildren(IWorkbenchRegistryConstants.TAG_LAYOUT).length==0) {
return false;
}
IConfigurationElement layout = widgetElement.getChildren(IWorkbenchRegistryConstants.TAG_LAYOUT)[0];
String fillMinorVal = layout.getAttribute(IWorkbenchRegistryConstants.ATT_FILL_MINOR);
return (fillMinorVal != null && fillMinorVal.equals("true")); //$NON-NLS-1$
}
/**
* @return The list of IConfigurationElements representing
* widgets to be added into this 'group'
*/
private List getWidgetConfigs() {
List widgetConfigs = new ArrayList();
// Return to the 'root' of the config tree and gather all elements
// for this 'group'. Note that while this is sub-optimal
// performace-wise that there are expected to be -very-
// few contributions in total (i.e. 10's, not 100's)
final IExtensionRegistry registry = Platform.getExtensionRegistry();
final IConfigurationElement[] widgetElements = registry
.getConfigurationElementsFor(IWorkbenchRegistryConstants.EXTENSION_MENUS);
// Locate all 'widget' additions appropriate for -this- group
for (int i = 0; i < widgetElements.length; i++) {
// Only process 'widget' entries
if (!IWorkbenchRegistryConstants.TAG_WIDGET.equals(widgetElements[i].getName()))
continue;
// Define the initial URI spec
if (widgetElements[i].getChildren(IWorkbenchRegistryConstants.TAG_LOCATION).length > 0) {
IConfigurationElement location = widgetElements[i].getChildren(IWorkbenchRegistryConstants.TAG_LOCATION)[0];
if (location.getChildren(IWorkbenchRegistryConstants.TAG_BAR).length > 0) {
IConfigurationElement bar = location.getChildren(IWorkbenchRegistryConstants.TAG_BAR)[0];
// The bar's path represents the 'group' it should go into
String path = bar.getAttribute(IWorkbenchRegistryConstants.ATT_PATH);
if (path != null && path.equals(getId()))
widgetConfigs.add(widgetElements[i]);
}
}
}
return widgetConfigs;
}
/**
* Attempts to load -all- widgets for this entry and
* keeps track of the successful loads only. Only elements
* who can be successfully loaded will be seen by the
* builder.
*
* @return The list of <code>IWorkbenchWidget</code> entries
* that have been successfully loaded
*/
public List getWidgets() {
List loadedWidgets = new ArrayList();
// Get the widget config elements for this 'group'
List widgetConfigs = getWidgetConfigs();
for (Iterator iterator = widgetConfigs.iterator(); iterator
.hasNext();) {
IConfigurationElement widgetCE = (IConfigurationElement) iterator.next();
// skip elements that are known to fail
if (failedWidgets.containsKey(widgetCE))
continue;
IWorkbenchWidget loadedWidget = loadWidget(widgetCE);
// Either add it to the 'valid' list or mark it
// as failed
if (loadedWidget != null) {
loadedWidgets.add(loadedWidget);
widgetToConfigElementMap.put(loadedWidget, widgetCE);
}
else
failedWidgets.put(widgetCE, widgetCE);
}
return loadedWidgets;
}
/**
* Attempts to load the executable extension defined within the given
* configuration element. An error is logged for any widget that fails
* to load.
*
* @param widgetCE The {@link IConfigurationElement} containing the
* widget's 'class' specification.
*
* @return The loaded {@link IWorkbenchWidget} or <code>null</code>
* if the loading fails
*/
private IWorkbenchWidget loadWidget(IConfigurationElement widgetCE) {
return (IWorkbenchWidget) Util.safeLoadExecutableExtension(widgetCE,
IWorkbenchRegistryConstants.ATT_CLASS,
IWorkbenchWidget.class);
}
/**
* @param widget The {@link IWorkbenchWidget} to get the defining configuration
* element for.
*
* @return The defining {@link IConfigurationElement}
*/
public IConfigurationElement getElement(IWorkbenchWidget widget) {
return (IConfigurationElement) widgetToConfigElementMap.get(widget);
}
/**
* @param widget
*/
public void removeWidget(IWidget widget) {
widgetToConfigElementMap.remove(widget);
}
public MenuLocationURI getUri() {
return uri;
}
}