| /******************************************************************************* |
| * Copyright (c) 2011, 2012 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.e4.ui.workbench.renderers.swt; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import org.eclipse.e4.core.contexts.EclipseContextFactory; |
| import org.eclipse.e4.core.contexts.IContextFunction; |
| import org.eclipse.e4.core.contexts.IEclipseContext; |
| import org.eclipse.e4.ui.internal.workbench.ContributionsAnalyzer; |
| import org.eclipse.e4.ui.model.application.ui.MCoreExpression; |
| import org.eclipse.e4.ui.model.application.ui.MElementContainer; |
| import org.eclipse.e4.ui.model.application.ui.menu.MToolBar; |
| import org.eclipse.e4.ui.model.application.ui.menu.MToolBarContribution; |
| import org.eclipse.e4.ui.model.application.ui.menu.MToolBarElement; |
| import org.eclipse.e4.ui.model.application.ui.menu.MToolBarSeparator; |
| import org.eclipse.e4.ui.workbench.modeling.ExpressionContext; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.util.EcoreUtil; |
| import org.eclipse.jface.action.ToolBarManager; |
| |
| public class ToolBarContributionRecord { |
| public static final String FACTORY = "ToolBarContributionFactory"; //$NON-NLS-1$ |
| static final String STATIC_CONTEXT = "ToolBarContributionFactoryContext"; //$NON-NLS-1$ |
| |
| MToolBar toolbarModel; |
| MToolBarContribution toolbarContribution; |
| ArrayList<MToolBarElement> generatedElements = new ArrayList<MToolBarElement>(); |
| HashSet<MToolBarElement> sharedElements = new HashSet<MToolBarElement>(); |
| ToolBarManagerRenderer renderer; |
| boolean isVisible = true; |
| private IEclipseContext infoContext; |
| private Runnable factoryDispose; |
| |
| public ToolBarContributionRecord(MToolBar model, |
| MToolBarContribution contribution, ToolBarManagerRenderer renderer) { |
| this.toolbarModel = model; |
| this.toolbarContribution = contribution; |
| this.renderer = renderer; |
| } |
| |
| public ToolBarManager getManagerForModel() { |
| return renderer.getManager(toolbarModel); |
| } |
| |
| /** |
| * @param context |
| */ |
| public void updateVisibility(IEclipseContext context) { |
| ExpressionContext exprContext = new ExpressionContext(context); |
| updateIsVisible(exprContext); |
| HashSet<ToolBarContributionRecord> recentlyUpdated = new HashSet<ToolBarContributionRecord>(); |
| recentlyUpdated.add(this); |
| boolean changed = false; |
| for (MToolBarElement item : generatedElements) { |
| boolean currentVisibility = computeVisibility(recentlyUpdated, |
| item, exprContext); |
| if (item.isVisible() != currentVisibility) { |
| item.setVisible(currentVisibility); |
| changed = true; |
| } |
| } |
| for (MToolBarElement item : sharedElements) { |
| boolean currentVisibility = computeVisibility(recentlyUpdated, |
| item, exprContext); |
| if (item.isVisible() != currentVisibility) { |
| item.setVisible(currentVisibility); |
| changed = true; |
| } |
| } |
| |
| if (changed) { |
| getManagerForModel().markDirty(); |
| } |
| } |
| |
| public void updateIsVisible(ExpressionContext exprContext) { |
| isVisible = ContributionsAnalyzer.isVisible(toolbarContribution, |
| exprContext); |
| } |
| |
| public boolean computeVisibility( |
| HashSet<ToolBarContributionRecord> recentlyUpdated, |
| MToolBarElement item, ExpressionContext exprContext) { |
| boolean currentVisibility = isVisible; |
| if (item instanceof MToolBarSeparator) { |
| ArrayList<ToolBarContributionRecord> list = renderer.getList(item); |
| if (list != null) { |
| Iterator<ToolBarContributionRecord> cr = list.iterator(); |
| while (!currentVisibility && cr.hasNext()) { |
| ToolBarContributionRecord rec = cr.next(); |
| if (!recentlyUpdated.contains(rec)) { |
| rec.updateIsVisible(exprContext); |
| recentlyUpdated.add(rec); |
| } |
| currentVisibility |= rec.isVisible; |
| } |
| } |
| } |
| if (currentVisibility |
| && item.getVisibleWhen() instanceof MCoreExpression) { |
| boolean val = ContributionsAnalyzer.isVisible( |
| (MCoreExpression) item.getVisibleWhen(), exprContext); |
| currentVisibility = val; |
| } |
| return currentVisibility; |
| } |
| |
| public boolean anyVisibleWhen() { |
| if (toolbarContribution.getVisibleWhen() != null) { |
| return true; |
| } |
| for (MToolBarElement child : toolbarContribution.getChildren()) { |
| if (child.getVisibleWhen() != null) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| public boolean mergeIntoModel() { |
| int idx = getIndex(toolbarModel, |
| toolbarContribution.getPositionInParent()); |
| if (idx == -1) { |
| return false; |
| } |
| |
| final List<MToolBarElement> copyElements; |
| if (toolbarContribution.getTransientData().get(FACTORY) != null) { |
| copyElements = mergeFactoryIntoModel(); |
| } else { |
| copyElements = new ArrayList<MToolBarElement>(); |
| for (MToolBarElement item : toolbarContribution.getChildren()) { |
| MToolBarElement copy = (MToolBarElement) EcoreUtil |
| .copy((EObject) item); |
| copyElements.add(copy); |
| } |
| } |
| for (MToolBarElement copy : copyElements) { |
| // if a visibleWhen clause is defined, the item should not be |
| // visible until the clause has been evaluated and returned 'true' |
| copy.setVisible(!anyVisibleWhen()); |
| if (copy instanceof MToolBarSeparator) { |
| MToolBarSeparator shared = findExistingSeparator(copy |
| .getElementId()); |
| if (shared == null) { |
| shared = (MToolBarSeparator) copy; |
| renderer.linkElementToContributionRecord(copy, this); |
| toolbarModel.getChildren().add(idx++, copy); |
| } else { |
| copy = shared; |
| } |
| sharedElements.add(shared); |
| } else { |
| generatedElements.add(copy); |
| renderer.linkElementToContributionRecord(copy, this); |
| toolbarModel.getChildren().add(idx++, copy); |
| } |
| if (copy instanceof MToolBarSeparator) { |
| ArrayList<ToolBarContributionRecord> array = renderer |
| .getList(copy); |
| array.add(this); |
| } |
| } |
| return true; |
| } |
| |
| /** |
| * @return |
| */ |
| private List<MToolBarElement> mergeFactoryIntoModel() { |
| Object obj = toolbarContribution.getTransientData().get(FACTORY); |
| if (!(obj instanceof IContextFunction)) { |
| return Collections.EMPTY_LIST; |
| } |
| IEclipseContext staticContext = getStaticContext(); |
| staticContext.remove(List.class); |
| factoryDispose = (Runnable) ((IContextFunction) obj) |
| .compute(staticContext); |
| return staticContext.get(List.class); |
| } |
| |
| private IEclipseContext getStaticContext() { |
| if (infoContext == null) { |
| IEclipseContext parentContext = renderer.getContext(toolbarModel); |
| if (parentContext != null) { |
| infoContext = parentContext.createChild(STATIC_CONTEXT); |
| } else { |
| infoContext = EclipseContextFactory.create(STATIC_CONTEXT); |
| } |
| ContributionsAnalyzer.populateModelInterfaces(toolbarModel, |
| infoContext, toolbarModel.getClass().getInterfaces()); |
| infoContext.set(ToolBarManagerRenderer.class, renderer); |
| } |
| return infoContext; |
| } |
| |
| MToolBarSeparator findExistingSeparator(String id) { |
| if (id == null) { |
| return null; |
| } |
| for (MToolBarElement item : toolbarModel.getChildren()) { |
| if (item instanceof MToolBarSeparator |
| && id.equals(item.getElementId())) { |
| return (MToolBarSeparator) item; |
| } |
| } |
| return null; |
| } |
| |
| public void dispose() { |
| for (MToolBarElement copy : generatedElements) { |
| toolbarModel.getChildren().remove(copy); |
| } |
| for (MToolBarElement shared : sharedElements) { |
| ArrayList<ToolBarContributionRecord> array = renderer |
| .getList(shared); |
| array.remove(this); |
| if (array.isEmpty()) { |
| toolbarModel.getChildren().remove(shared); |
| } |
| } |
| if (factoryDispose != null) { |
| factoryDispose.run(); |
| factoryDispose = null; |
| } |
| } |
| |
| private static int getIndex(MElementContainer<?> model, |
| String positionInParent) { |
| String id = null; |
| String modifier = null; |
| if (positionInParent != null && positionInParent.length() > 0) { |
| String[] array = positionInParent.split("="); //$NON-NLS-1$ |
| modifier = array[0]; |
| id = array[1]; |
| } |
| if (id == null) { |
| return model.getChildren().size(); |
| } |
| |
| int idx = 0; |
| int size = model.getChildren().size(); |
| while (idx < size) { |
| if (id.equals(model.getChildren().get(idx).getElementId())) { |
| if ("after".equals(modifier)) { //$NON-NLS-1$ |
| idx++; |
| } |
| return idx; |
| } |
| idx++; |
| } |
| return id.equals("additions") ? model.getChildren().size() : -1; //$NON-NLS-1$ |
| } |
| } |